panda3d/doc/SceneEditor/sceneEditor.py
2006-01-24 07:52:54 +00:00

1710 lines
74 KiB
Python

import sys
try: import _tkinter
except: sys.exit("Please install python module 'Tkinter'")
import direct
from direct.directbase.DirectStart import*
from direct.showbase.TkGlobal import*
from tkFileDialog import *
from direct.directtools.DirectGlobals import *
from direct.tkwidgets.AppShell import*
from SideWindow import*
from duplicateWindow import*
from lightingPanel import *
from seMopathRecorder import *
from seSession import *
from quad import *
from sePlacer import *
from seFileSaver import *
from propertyWindow import *
import seParticlePanel
from collisionWindow import *
from direct.gui.DirectGui import *
from MetadataPanel import *
from seBlendAnimPanel import *
from controllerWindow import *
from AlignTool import *
import os
import string
from direct.tkwidgets import Dial
from direct.tkwidgets import Floater
from direct.tkwidgets import Slider
from direct.actor import Actor
import seAnimPanel
from direct.task import Task
import math
from path import path
#################################################################
# All scene and windows object will be stored in here.
# So, any event which will or need to change contents
# should be wirtten in here or imported into here!
#################################################################
from dataHolder import* ## Use this thing to Save/load data.
AllScene = dataHolder()
class myLevelEditor(AppShell):
## overridden the basic app info ##
appname = 'Scene Editor - New Scene'
appversion = '1.0'
copyright = ('Copyright 2004 E.T.C. Carnegie Mellon U.' +
' All Rights Reserved')
contactname = 'Jesse Schell, Shalin Shodhan & YiHong Lin'
contactphone = '(412) 268-5791'
contactemail = 'etc-panda3d@lists.andrew.cmu.edu'
frameWidth = 1024
frameHeight = 80
frameIniPosX = 0
frameIniPosY = 0
usecommandarea = 0
usestatusarea = 0
padx = 5
pady = 5
sideWindowCount = 0
## Basic World default setting (For side window)
worldColor = [0,0,0,0]
lightEnable = 1
ParticleEnable = 1
basedriveEnable = 0
collision = 1
backface = 0
texture = 1
wireframe = 0
grid = 0
widgetVis = 0
enableAutoCamera = 1
enableControl = False
controlType = 'Keyboard'
keyboardMapDict = {}
keyboardSpeedDict = {}
Scene=None
isSelect = False
nodeSelected = None
undoDic = {}
redoDic = {}
animPanel = {}
animBlendPanel = {}
propertyWindow = {}
CurrentFileName=None #Holds the current scene file name
CurrentDirName=None # Holds the current file name without extension which is the path where file's data gets saved
Dirty=0 # Keeps track of whether there are any modifications that should be saved
def __init__(self, parent = None, **kw):
base.setBackgroundColor(0,0,0)
self.parent = parent
## Check TkTool is activated! ##
self.wantTK = config.GetBool('want-tk', 0)
if self.wantTK:
pass
else:
taskMgr.remove('tkloop')
spawnTkLoop()
## Set up window frame
INITOPT = Pmw.INITOPT
optiondefs = (
('title', self.appname, None),
)
self.defineoptions(kw, optiondefs)
AppShell.__init__(self, parent)
self.parent.geometry('%dx%d+%d+%d' % (self.frameWidth, self.frameHeight,self.frameIniPosX,self.frameIniPosY))
###### Put th directLabel on the screen to show the selected object Data
self.posLabel = DirectLabel(
relief = None,
pos = (-1.3, 0, 0.90),
text = "Position : X: 00.00 Y: 00.00 Z: 00.00",
color = Vec4(1, 1, 1, 1),
text_scale = 0.05,
text_align = TextNode.ALeft
)
self.hprLabel = DirectLabel(
relief = None,
pos = (-1.3 , 0, 0.80),
text = "Orientation: H: 00.00 P: 00.00 R: 00.00",
color = Vec4(1, 1, 1, 1),
text_scale = 0.05,
text_align = TextNode.ALeft
)
self.scaleLabel = DirectLabel(
relief = None,
pos = (-1.3, 0, 0.70),
text = "Scale : X: 00.00 Y: 00.00 Z: 00.00",
color = Vec4(1, 1, 1, 1),
text_scale = 0.05,
text_align = TextNode.ALeft
)
self.initialiseoptions(myLevelEditor)
self.parent.resizable(False,False) ## Disable the ability to resize for this Window.
######### Set the event handler ##########
self.dataFlowEvents = [
## Event from Side Window
['SW_lightToggle',self.lightToggle],
['SW_collisionToggle',AllScene.toggleCollisionVisable],
['SW_particleToggle',self.toggleParticleVisable],
['SW_close',self.sideWindowClose],
## From Duplication Window
['DW_duplicating',self.duplicationObj],
## From Animation Panel
['AW_AnimationLoad',self.animationLoader],
['AW_removeAnim',self.animationRemove],
['AW_close',self.animPanelClose],
## From Blending Animation Window
['BAW_saveBlendAnim',self.animBlendPanelSave],
['BAW_removeBlendAnim',self.animBlendPanelRemove],
['BAW_renameBlendAnim',self.animBlendPanelRename],
['BAW_close',self.animBlendPanelClose],
## From Lighting Panel
['LP_selectLight', self.lightSelect],
['LP_addLight',self.addLight],
['LP_rename',self.lightRename],
['LP_removeLight',self.removeLight],
['LP_close',self.lightingPanelClose],
## From MotionPath Panel
['mPath_bindPathToNode',AllScene.bindCurveToNode],
['mPath_requestCurveList', self.requestCurveList],
['mPath_close', self.mopathClosed],
## From Property Window
['PW_removeCurveFromNode', AllScene.removeCurveFromNode],
['PW_removeAnimFromNode', AllScene.removeAnimation],
['PW_toggleLight', AllScene.toggleLightNode],
['PW_close', self.closePropertyWindow],
## From collisionWindow
['CW_addCollisionObj', AllScene.addCollisionObject],
## From AlignWindow
['ALW_close', self.closeAlignPanel],
['ALW_align', self.alignObject],
## From controllerWindow
['ControlW_close', self.closeInputPanel],
['ControlW_require', self.requestObjFromControlW],
['ControlW_controlSetting', self.setControlSet],
['ControlW_controlEnable', self.startControl],
['ControlW_controlDisable', self.stopControl],
['ControlW_saveSetting', AllScene.saveControlSetting],
## From Placer
['Placer_close', self.closePlacerPanel],
## From Particle Panel
['ParticlePanle_close', self.closeParticlePanel],
## From SEditor object which is a altered DirectSession
['SEditor-ToggleWidgetVis',self.toggleWidgetVis],
['SEditor-ToggleBackface',self.toggleBackface],
['SEditor-ToggleTexture',self.toggleTexture],
['SEditor-ToggleWireframe',self.toggleWireframe],
['ParticlePanel_Added_Effect',self.addParticleEffect],
['f11',self.loadFromBam],
['f12',self.saveAsBam],
]
#################################
### Collision detection
#################################
self.cTrav = CollisionTraverser()
base.cTrav = self.cTrav
for event in self.dataFlowEvents:
self.accept(event[0], event[1], extraArgs = event[2:])
self.actionEvents = [
# Scene graph explorer functions
['SGE_changeName', self.changeName],
['SGE_Properties', self.openPropertyPanel],
['SGE_Duplicate', self.duplicate],
['SGE_Remove', self.remove],
['SGE_Add Dummy', self.addDummyNode],
['SGE_Add Collision Object', self.addCollisionObj],
['SGE_Metadata', self.openMetadataPanel],
['SGE_Set as Reparent Target', self.setAsReparentTarget],
['SGE_Reparent to Target', self.reparentToNode],
['SGE_Animation Panel', self.openAnimPanel],
['SGE_Blend Animation Panel', self.openBlendAnimPanel],
['SGE_MoPath Panel', self.openMoPathPanel],
['SGE_Align Tool', self.openAlignPanel],
['SGE_Flash', self.flash],
['SGE_madeSelection', self.selectNode],
['select',self.selectNode],
['deselect', self.deSelectNode],
['se_selectedNodePath',self.selectFromScene],
['se_deselectedAll',self.deselectFromScene],
]
''' All messages starting with "SGE_" are generated in seSceneGraphExplorer'''
for event in self.actionEvents:
self.accept(event[0], event[1], extraArgs = event[2:])
camera.toggleVis()
self.selectNode(base.camera) ## Initially, we select camera as the first node...
def appInit(self):
#################################################################
# appInit(self)
# Initialize the application.
# This function will be called when you call AppShell's constructor
#################################################################
### Create SceneEditor Ver. DirectSession
self.seSession = SeSession()
self.seSession.enable()
SEditor.camera.setPos(0,-50,10)
self.placer=None
self.MopathPanel = None
self.alignPanelDict = {}
#self.quadview=QuadView()
self.lightingPanel = None
self.controllerPanel = None
self.particlePanel = None
### Create Side Window
self.sideWindow = sideWindow(worldColor = self.worldColor,
lightEnable = self.lightEnable,
ParticleEnable = self.ParticleEnable,
basedriveEnable = self.basedriveEnable,
collision = self.collision,
backface = self.backface,
texture = self.texture,
wireframe = self.wireframe,
grid = self.grid,
widgetVis = self.widgetVis,
enableAutoCamera = self.enableAutoCamera)
self.sideWindowCount = 1
self.sideWindow.selectPage()
messenger.send('SGE_Update Explorer',[render]) ## Update the Scene Graph
pass
def getPhotoImage(self,name):
modpath = ConfigVariableSearchPath("model-path")
path = modpath.findFile(Filename(name))
return PhotoImage(file=path.toOsSpecific())
def createInterface(self):
# The interior of the toplevel panel
interior = self.interior()
#######################################################
### Creating the Buttons in the window frame
#######################################################
buttonFrame = Frame(interior)
self.image=[]
self.image.append(self.getPhotoImage('models/icons/new.gif'))#0
self.image.append(self.getPhotoImage('models/icons/open.gif'))#1
self.image.append(self.getPhotoImage('models/icons/save.gif'))#2
self.image.append(self.getPhotoImage('models/icons/model.gif'))#3
self.image.append(self.getPhotoImage('models/icons/actor.gif'))#4
self.image.append(self.getPhotoImage('models/icons/placer.gif'))#5
self.image.append(self.getPhotoImage('models/icons/mopath.gif'))#6
self.image.append(self.getPhotoImage('models/icons/lights.gif'))#7
self.image.append(self.getPhotoImage('models/icons/particles.gif'))#8
self.image.append(self.getPhotoImage('models/icons/control.gif'))
self.image.append(self.getPhotoImage('models/icons/help.gif'))#9
self.image.append(self.getPhotoImage('models/icons/blank.gif'))
self.image.append(self.getPhotoImage('models/icons/blank.gif'))
self.image.append(self.getPhotoImage('models/icons/blank.gif'))
self.image.append(self.getPhotoImage('models/icons/blank.gif'))
self.image.append(self.getPhotoImage('models/icons/blank.gif'))
self.image.append(self.getPhotoImage('models/icons/blank.gif'))
self.image.append(self.getPhotoImage('models/icons/blank.gif'))
self.image.append(self.getPhotoImage('models/icons/blank.gif'))
self.image.append(self.getPhotoImage('models/icons/blank.gif'))
self.image.append(self.getPhotoImage('models/icons/blank.gif'))
self.image.append(self.getPhotoImage('models/icons/blank.gif'))
self.image.append(self.getPhotoImage('models/icons/blank.gif'))
i = 0
for element in self.image:
i += 1
button = Button(buttonFrame, image = element, command=lambda n=i : self.buttonPushed(n))
button.pack(fill=X, side = LEFT)
buttonFrame.pack(fill=X, side=LEFT,expand=True)
def buttonPushed(self, buttonIndex):
#################################################################
# buttonPushed(self, buttonNum)
# This function will handle all button events from top level window
# Take the button index as a reference to sence which button has been pushed.
#################################################################
####
#### Change here to process the button event further.
####
if buttonIndex==1: # New Scene
self.newScene()
return
elif buttonIndex==2: # Open Scene
self.openScene()
return
elif buttonIndex==3: # Save Scene
self.saveScene()
return
elif buttonIndex==4: # Load Model
self.loadModel()
return
elif buttonIndex==5: # Load Actor
self.loadActor()
return
elif buttonIndex==6: # Open Placer
self.openPlacerPanel()
return
elif buttonIndex==7: # Open Mopath Panel
self.openMoPathPanel()
return
elif buttonIndex==8: # Open Lighting Panel
self.openLightingPanel()
return
elif buttonIndex==9: # Open Particle Panel
self.openParticlePanel()
return
elif buttonIndex==10:
self.openInputPanel()
return
elif buttonIndex==11: # Help
self.showAbout()
return
elif buttonIndex==12:
print "You haven't defined the function for this Button, Number %d."%buttonIndex
return
elif buttonIndex==13:
print "You haven't defined the function for this Button, Number %d."%buttonIndex
return
elif buttonIndex==14:
print "You haven't defined the function for this Button, Number %d."%buttonIndex
return
elif buttonIndex==15:
print "You haven't defined the function for this Button, Number %d."%buttonIndex
return
elif buttonIndex==16:
print "Your scene will be eliminated within five seconds, Save your world!!!, Number %d."%buttonIndex
return
elif buttonIndex==17:
print "You haven't defined the function for this Button, Number %d."%buttonIndex
return
elif buttonIndex==18:
print "You haven't defined the function for this Button, Number %d."%buttonIndex
return
elif buttonIndex==19:
print "You haven't defined the function for this Button, Number %d."%buttonIndex
return
elif buttonIndex==20:
print "You haven't defined the function for this Button, Number %d."%buttonIndex
return
return
def createMenuBar(self):
# Creates default menus. Can be overridden or simply augmented
# Using button Add below
self.menuBar.addmenuitem('Help', 'command',
'Get information on application',
label='About...', command=self.showAbout)
## Creat stuff inside the "File"
self.menuBar.addmenuitem('File', 'command', 'Creat New Scene',
label='New Scene',
command=self.newScene)
self.menuBar.addmenuitem('File', 'command', 'Open a Scene',
label='Open Scene',
command=self.openScene)
self.menuBar.addmenuitem('File', 'command', 'Save a Scene',
label='Save Scene',
command=self.saveScene)
self.menuBar.addmenuitem('File', 'command', 'Save Scene as...',
label='Save as...',
command=self.saveAsScene)
self.menuBar.addmenuitem('File', 'separator')
self.menuBar.addmenuitem('File', 'command', 'Load Model',
label='Load Model',
command=self.loadModel)
self.menuBar.addmenuitem('File', 'command', 'Load Actor',
label='Load Actor',
command=self.loadActor)
self.menuBar.addmenuitem('File', 'separator')
self.menuBar.addmenuitem('File', 'command', 'Import a Scene',
label='Import...',
command=self.importScene)
self.menuBar.addmenuitem('File', 'separator')
self.menuBar.addmenuitem('File', 'command', 'Quit this application',
label='Exit',
command=self.quit)
## Creat "Edit" on the menu and its stuff
self.menuBar.addmenu('Edit', 'Editting tools')
self.menuBar.addmenuitem('Edit', 'command', 'Un-do',
label='Undo...',
command=self.unDo)
self.menuBar.addmenuitem('Edit', 'command', 'Re-do',
label='Redo...',
command=self.reDo)
self.menuBar.addmenuitem('Edit', 'separator')
self.menuBar.addmenuitem('Edit', 'command', 'Deselect nodepath',
label='Deselect',
command=self.deSelectNode)
self.menuBar.addmenuitem('Edit', 'separator')
self.menuBar.addmenuitem('Edit', 'command', 'Add a Dummy',
label='Add Dummy',
command=self.addDummy)
self.menuBar.addmenuitem('Edit', 'command', 'Duplicate nodepath',
label='Duplicate',
command=self.duplicateNode)
self.menuBar.addmenuitem('Edit', 'command', 'Remove the nodepath',
label='Remove',
command=self.removeNode)
self.menuBar.addmenuitem('Edit', 'command', 'Show the object properties',
label='Object Properties',
command=self.showObjProp)
self.menuBar.addmenuitem('Edit', 'separator')
self.menuBar.addmenuitem('Edit', 'command', 'Show the Camera setting',
label='Camera Setting',
command=self.showCameraSetting)
self.menuBar.addmenuitem('Edit', 'command', 'Render setting',
label='Render Setting',
command=self.showRenderSetting)
## Creat "Panel" on the menu and its stuff
self.menuBar.addmenu('Panel', 'Panel tools')
self.menuBar.addmenuitem('Panel', 'command', 'Open Side Window',
label='Side Window',
command=self.openSideWindow)
self.menuBar.addmenuitem('Panel', 'command', 'Placer Panel',
label='Placer Panel',
command=self.openPlacerPanel)
self.menuBar.addmenuitem('Panel', 'command', 'Animation Panel',
label='Animation Panel',
command=self.openAnimationPanel)
self.menuBar.addmenuitem('Panel', 'command', 'Motion Path Panel',
label='Mopath Panel',
command=self.openMopathPanel)
self.menuBar.addmenuitem('Panel', 'command', 'Lighting Panel',
label='Lighting Panel',
command=self.openLightingPanel)
self.menuBar.addmenuitem('Panel', 'command', 'Particle Panel',
label='Particle Panel',
command=self.openParticlePanel)
self.menuBar.addmenuitem('Panel', 'separator')
self.menuBar.addmenuitem('Panel', 'command', 'Input control Panel',
label='Input device panel',
command=self.openInputPanel)
self.menuBar.pack(fill=X, side = LEFT)
## get "Menu" items in order to control the entry status
self.menuFile = self.menuBar.component('File-menu')
self.menuEdit = self.menuBar.component('Edit-menu')
self.menuPanel = self.menuBar.component('Panel-menu')
## Disable entries when user doesn't select anything
if not self.isSelect:
self.menuEdit.entryconfig('Deselect', state=DISABLED)
self.menuEdit.entryconfig('Add Dummy', state=DISABLED)
self.menuEdit.entryconfig('Duplicate', state=DISABLED)
self.menuEdit.entryconfig('Remove', state=DISABLED)
self.menuEdit.entryconfig('Object Properties', state=DISABLED)
self.menuPanel.entryconfig('Animation Panel', state=DISABLED)
self.menuPanel.entryconfig('Side Window', state=DISABLED)
def onDestroy(self, event):
#################################################################
# If you have open any thing, please rewrite here!
#################################################################
if taskMgr.hasTaskNamed('seMonitorSelectedNode'):
taskMgr.remove('seMonitorSelectedNode')
pass
def closeAllSubWindows(self):
#################################################################
# closeAllSubWindows(self)
# except side window. this function will close all sub window if there is any.
#################################################################
if self.lightingPanel != None:
self.lightingPanel.quit()
if self.placer != None:
self.placer.quit()
if self.MopathPanel != None:
self.MopathPanel.quit()
if self.particlePanel != None:
self.particlePanel.quit()
if self.controllerPanel != None:
self.controllerPanel.quit()
list = self.animPanel.keys()
for index in list:
self.animPanel[index].quit()
list = self.animBlendPanel.keys()
for index in list:
self.animBlendPanel[index].quit()
list = self.propertyWindow.keys()
for index in list:
self.propertyWindow[index].quit()
list = self.alignPanelDict.keys()
for index in list:
self.alignPanelDict[index].quit()
self.animPanel.clear()
self.animBlendPanel.clear()
self.propertyWindow.clear()
self.alignPanelDict.clear()
return
## Processing message events
def makeDirty(self):
self.Dirty=1
def removeLight(self, lightNode):
#################################################################
# removeLight(self, lightNode)
# This function will be called when user try to remove the light from lightingPanel
# (by sending out the message)
# So, in here we will call dataHolder(AllScene) to remove the light
# and return a list contains the newest data of lights in he scene.
# Then, this function will reset the lighting list in the lightingPanel
#################################################################
list = AllScene.removeObj(lightNode)
if self.lightingPanel != None:
self.lightingPanel.updateList(list)
return
def lightRename(self,oName, nName):
#################################################################
# lightRename(self,oName, nName)
# This function will be called when user try to rename the light from lightingPanel
# (by sending out the message)
# So, in here we will call dataHolder(AllScene) to rename the light
# and return a list contains the newest data of lights in he scene.
# Then, this function will reset the lighting list in the lightingPanel
#################################################################
list, lightNode = AllScene.rename(oName, nName)
if self.lightingPanel != None:
self.lightingPanel.updateList(list,lightNode)
return
def lightSelect(self,lightName):
#################################################################
# lightSelect(self,lightName)
# This function will be called when user try to select the light from lightingPanel
# (by sending out the message)
# So, in here we will call dataHolder(AllScene) to get the target light node
# Then, this function will put this light node back into lighting
# panel and update the data on the panel.
#################################################################
lightNode = AllScene.getLightNode(lightName)
if self.lightingPanel != None:
self.lightingPanel.updateDisplay(lightNode)
return
def addLight(self, type):
#################################################################
# addLight(self, type)
# This function will be called when user try to add a light from lightingPanel
# (by sending out the message)
# So, in here we will call dataHolder(AllScene) to create a default light node
# by the type that user assigned.
# Then, this function will put this light node back into lighting
# panel with the newest lighting list and update the data on the panel.
#################################################################
list, lightNode = AllScene.createLight(type = type)
if self.lightingPanel != None:
self.lightingPanel.updateList(list,lightNode)
self.makeDirty()
return
def lightingPanelClose(self):
#################################################################
# lightingPanelClose(self)
# This function will be called when user try to close the lighting panel
# This function will re-config the state of the lighting panel button on the top screen
# And it will set the self.lightingPanel to None
#################################################################
self.menuPanel.entryconfig('Lighting Panel', state=NORMAL)
self.lightingPanel = None
return
def openPropertyPanel(self, nodePath = None):
#################################################################
# openPropertyPanel(self, nodePath = None)
# This function will be called when user try to open a property window
# for one specific node in the scene.
# Here we will call dataHolder to get the basic properties
# we would like to let user to see and cange.
# And then we pass those information into propertyWindow
#################################################################
type, info = AllScene.getInfoOfThisNode(nodePath)
name = nodePath.getName()
if not self.propertyWindow.has_key(name):
self.propertyWindow[name] = propertyWindow(nodePath, type,info )
pass
def closePropertyWindow(self, name):
if self.propertyWindow.has_key(name):
del self.propertyWindow[name]
return
def openMetadataPanel(self,nodePath=None):
print nodePath
self.MetadataPanel=MetadataPanel(nodePath)
pass
def duplicate(self, nodePath = None):
#################################################################
# duplicate(self, nodePath = None)
# This function will be called when user try to open the duplication window
#################################################################
print '----Duplication!!'
if nodePath != None:
self.duplicateWindow = duplicateWindow(nodePath = nodePath)
pass
def remove(self, nodePath = None):
#################################################################
# remove(self, nodePath = None)
# This function will be called when user try to delete a node from scene
#
# For safty issue,
# we will do deselect first then remove the certain node.
#
#################################################################
if nodePath==None:
if self.nodeSelected == None:
return
nodePath = self.nodeSelected
self.deSelectNode()
if AllScene.isLight(nodePath.getName()):
self.removeLight(nodePath)
else:
AllScene.removeObj(nodePath)
pass
def addDummyNode(self, nodepath = None):
#################################################################
# addDummyNode(self, nodepath = None)
# This function will be called when user try to create a dummy node into scene
#
# Here we will call dataHolder to create a dummy node
# and reparent it to the nodePath that user has assigned.
#
#################################################################
AllScene.addDummyNode(nodepath)
self.makeDirty()
pass
def addCollisionObj(self, nodepath = None):
#################################################################
# addCollisionObj(self, nodepath = None)
# This function will be called when user try to create a collision object into the scene
#
# Here we will call collisionWindow to ask user what kind of collision objects they want to have.
# Then, send the information and generated collision object to dataHolder to finish the whole process
# and reparent it to the nodePath that user has assigned.
#
#################################################################
self.collisionWindow = collisionWindow(nodepath)
pass
def setAsReparentTarget(self, nodepath = None):
#################################################################
# setAsReparentTarget(self, nodepath = None)
# This function will be called when user select a nodePaht
# and want to reparent other node under it. (Drom side window pop-up nemu)
#################################################################
SEditor.setActiveParent(nodepath)
return
def reparentToNode(self, nodepath = None):
#################################################################
# reparentToNode(self, nodepath = None)
# This function will be call when user try to reparent a node to
# that node he selected as a reparent target before.
#
# The whole reparent process is handled by seSession,
# which is tunned from DirectSession
#
#################################################################
SEditor.reparent(nodepath, fWrt = 1)
return
def openPlacerPanel(self, nodePath = None):
#################################################################
# openPlacerPanel(self, nodePath = None)
# This function will be call when user try to open a placer panel.
# This call will only success if there is no other placer panel been activated
#################################################################
if(self.placer==None):
self.placer = Placer()
self.menuPanel.entryconfig('Placer Panel', state=DISABLED)
return
def closePlacerPanel(self):
#################################################################
# closePlacerPanel(self)
# This function will be called when user close the placer panel.
# Here we will reset the self.placer back to None.
# (You can think this is just like a reference count)
#################################################################
self.placer = None
self.menuPanel.entryconfig('Placer Panel', state=NORMAL)
return
def openAnimPanel(self, nodePath = None):
#################################################################
# openAnimPanel(self, nodePath = None)
# This function will be called when user tries to open an Animation Panel
# This will generated a panel and put it
# into a dictionary using the actor's name as an index.
# So, if there already has an animation panel for the target actor,
# it won't allow user to open another one.
#################################################################
name = nodePath.getName()
if AllScene.isActor(name):
if self.animPanel.has_key(name):
print '---- You already have an animation panel for this Actor!'
return
else:
Actor = AllScene.getActor(name)
self.animPanel[name] = seAnimPanel.AnimPanel(aNode=Actor)
pass
def openMoPathPanel(self, nodepath = None):
#################################################################
# openMoPathPanel(self, nodepath = None)
# This function will open a Motion Path Recorder for you.
#################################################################
if self.MopathPanel == None:
self.MopathPanel = MopathRecorder()
pass
def mopathClosed(self):
self.MopathPanel = None
return
def changeName(self, nodePath, nName):
#################################################################
# changeName(self, nodePath, nName)
# This function will be called when user tries to change the name of the node
#################################################################
oName = nodePath.getName() # I need this line in order to check the obj name in the control panel.
AllScene.rename(nodePath,nName)
# reset the list in the controller panel if it has been opened.
if (self.controllerPanel) != None:
list = AllScene.getAllObjNameAsList()
self.controllerPanel.resetNameList(list = list, name = oName, nodePath = nodePath)
return
# Take care things under File menu
def newScene(self):
#################################################################
# newScene(self)
# This function will clear whole stuff in the scene
# and will reset the application title to "New Scene"
#################################################################
self.closeAllSubWindows() ## Close all sub window
if(self.CurrentFileName):
currentF=Filename(self.CurrentFileName)
self.CurrentFileName=None
AllScene.resetAll()
currentModName=currentF.getBasenameWoExtension()
# Let us actually remove the scene from sys modules... this is done because every scene is loaded as a module
# And if we reload a scene python wont reload since its already in sys.modules... and hence we delete it
# If there is ever a garbage colleciton bug..this might be a point to look at
if sys.modules.has_key(currentModName):
del sys.modules[currentModName]
print sys.getrefcount(AllScene.theScene)
del AllScene.theScene
else:
AllScene.resetAll()
self.parent.title('Scene Editor - New Scene')
pass
def openScene(self):
#################################################################
# openScene(self)
#################################################################
# In the future try and provide merging of two scenes
if(self.CurrentFileName or self.Dirty):
saveScene = tkMessageBox._show("Load scene","Save the current scene?",icon = tkMessageBox.QUESTION,type = tkMessageBox.YESNOCANCEL)
if (saveScene == "yes"):
self.saveScene()
elif (saveScene == "cancel"):
return
self.closeAllSubWindows() ## Close all sub window
if(self.CurrentFileName):
currentF=Filename(self.CurrentFileName)
AllScene.resetAll()
currentModName=currentF.getBasenameWoExtension()
# Let us actually remove the scene from sys modules... this is done because every scene is loaded as a module
# And if we reload a scene python wont reload since its already in sys.modules... and hence we delete it
# If there is ever a garbage colleciton bug..this might be a point to look at
if sys.modules.has_key(currentModName):
del sys.modules[currentModName]
print sys.getrefcount(AllScene.theScene)
del AllScene.theScene
else:
AllScene.resetAll()
self.CurrentFileName = AllScene.loadScene()
if(self.CurrentFileName==None):
return
thefile=Filename(self.CurrentFileName)
thedir=thefile.getFullpathWoExtension()
print "SCENE EDITOR::" + thedir
self.CurrentDirName=thedir
if self.CurrentFileName != None:
self.parent.title('Scene Editor - '+ Filename.fromOsSpecific(self.CurrentFileName).getBasenameWoExtension())
if self.lightingPanel !=None:
lightList=AllScene.getList()
self.lightingPanel.updateList(lightList)
messenger.send('SGE_Update Explorer',[render])
# Close the side window in order to reset all world settings to fit the scene we have loaded.
self.sideWindow.quit()
# Try to re-open the side window again
while self.sideWindow == None:
wColor = base.getBackgroundColor()
self.worldColor[0] = wColor.getX()
self.worldColor[1] = wColor.getY()
self.worldColor[2] = wColor.getZ()
self.worldColor[3] = wColor.getW()
self.lightEnable = 1
self.ParticleEnable = 1
self.collision = 1
self.openSideWindow()
def saveScene(self):
#################################################################
# saveScene(self)
# If this is an open file call saveAsScene
# or else instantiate FileSaver from seFileSaver.py and pass it the filename
# If this filename exists in sys.modules you cannot use it
#################################################################
if(self.CurrentFileName):
f=FileSaver()
f.SaveFile(AllScene,self.CurrentFileName,self.CurrentDirName,1)
self.Dirty=0
else:
self.saveAsScene()
pass
def saveAsBam(self):
fileName = tkFileDialog.asksaveasfilename(filetypes = [("BAM",".bam")],title = "Save Scenegraph as Bam file")
theScene=render.find("**/Scene")
if not theScene is None:
theScene.writeBamFile(fileName)
else:
render.writeBamFile(fileName+".bad")
print " Scenegraph saved as :" +str(fileName)
def loadFromBam(self):
fileName = tkFileDialog.askopenfilename(filetypes = [("BAM",".bam")],title = "Load Scenegraph from Bam file")
if not fileName is None:
d=path(fileName)
scene=loader.loadModel(d.relpath())
scene.reparentTo(render)
def saveAsScene(self):
#################################################################
# saveAsScene(self)
# Ask for filename using a file save dialog
# If this filename exists in sys.modules you cannot use it
# Instantiate FileSaver from seFileSaver.py and pass it the filename
#################################################################
fileName = tkFileDialog.asksaveasfilename(filetypes = [("PY","py")],title = "Save Scene")
if(not fileName):
return
fCheck=Filename(fileName)
#print fCheck.getBasenameWoExtension()
###############################################################################
# !!!!! See if a module exists by this name... if it does you cannot use this filename !!!!!
###############################################################################
if(sys.modules.has_key(fCheck.getBasenameWoExtension())):
tkMessageBox.showwarning(
"Save file",
"Cannot save with this name because there is a system module with the same name. Please resave as something else."
)
return
self.CurrentDirName=fileName
fileName=fileName+".py"
f=FileSaver()
self.CurrentFileName=fileName
f.SaveFile(AllScene,fileName,self.CurrentDirName,0)
self.Dirty=0
self.parent.title('Scene Editor - '+ Filename.fromOsSpecific(self.CurrentFileName).getBasenameWoExtension())
pass
def loadModel(self):
#################################################################
# loadModel(self)
# This function will be called when user tries to load a model into the scene.
# Here we will pop-up a dialog to ask user which model file should be loaded in.
# Then, pass the path to dataHolder to load the model in.
#################################################################
modelFilename = askopenfilename(
defaultextension = '.egg',
filetypes = (('Egg Files', '*.egg'),
('Bam Files', '*.bam'),
('All files', '*')),
initialdir = '.',
title = 'Load New Model',
parent = self.parent)
if modelFilename:
self.makeDirty()
if not AllScene.loadModel(modelFilename, Filename.fromOsSpecific(modelFilename)):
print '----Error! No Such Model File!'
pass
def loadActor(self):
#################################################################
# loadActor(self)
# This function will be called when user tries to load an Actor into the scene.
# Here we will pop-up a dialog to ask user which Actor file should be loaded in.
# Then, pass the path to dataHolder to load the Actor in.
#################################################################
ActorFilename = askopenfilename(
defaultextension = '.egg',
filetypes = (('Egg Files', '*.egg'),
('Bam Files', '*.bam'),
('All files', '*')),
initialdir = '.',
title = 'Load New Actor',
parent = self.parent)
if ActorFilename:
self.makeDirty()
if not AllScene.loadActor(ActorFilename, Filename.fromOsSpecific(ActorFilename)):
print '----Error! No Such Model File!'
pass
def importScene(self):
self.makeDirty()
print '----God bless you Please Import!'
pass
## Take care those things under Edit nemu
def unDo(self):
pass
def reDo(self):
pass
def deSelectNode(self, nodePath=None):
#################################################################
# deSelectNode(self, nodePath=None)
# This function will deselect the node which we have selected currently.
# This will also remove the monitor task which monitor selected object's
# position, orientation and scale each frame.
#################################################################
if nodePath != None:
self.seSession.deselect(nodePath)
if self.isSelect:
self.isSelect = False
#if self.nodeSelected != None:
# self.nodeSelected.hideBounds()
self.nodeSelected =None
self.menuEdit.entryconfig('Deselect', state=DISABLED)
self.menuEdit.entryconfig('Add Dummy', state=DISABLED)
self.menuEdit.entryconfig('Duplicate', state=DISABLED)
self.menuEdit.entryconfig('Remove', state=DISABLED)
self.menuEdit.entryconfig('Object Properties', state=DISABLED)
if self.sideWindowCount==1:
self.sideWindow.SGE.deSelectTree()
if taskMgr.hasTaskNamed('seMonitorSelectedNode'):
taskMgr.remove('seMonitorSelectedNode')
return
pass
def addDummy(self):
#################################################################
# addDummy(self)
# This function will do nothing but call other function
# to add a dummy into the scene.
#
# Ok... this is really redundancy...
#
#################################################################
self.addDummyNode(self.nodeSelected)
pass
def duplicateNode(self):
#################################################################
# duplicateNode(self)
# This function will do nothing but call other function
# to open the duplication window.
#
# Ok... this is really redundancy...
#
#################################################################
if self.nodeSelected!=None:
self.duplicate(self.nodeSelected)
pass
def removeNode(self):
#################################################################
# removeNode(self)
# This function will do nothing but call other function
# to remove the current selected node..
#
# Ok... this is really redundancy...
#
################################################################
self.remove(self.nodeSelected)
pass
def showObjProp(self):
################################################################
# showObjProp(self)
# This function will do nothing but call other function
# to open the property window of current selected node..
#
# Ok... this is really redundancy...
#
################################################################
self.openPropertyPanel(self.nodeSelected)
pass
def showCameraSetting(self):
################################################################
# showCameraSetting(self)
# This function will do nothing but call other function
# to open the property window of camera..
#
# Ok... this is really redundancy...
#
################################################################
self.openPropertyPanel(camera)
pass
def showRenderSetting(self):
'''Currently, no idea what gonna pop-out here...'''
pass
## Take care those thins under Edit nemu
def openSideWindow(self):
################################################################
# openSideWindow(self)
# This function will open the side window and set the reference number
# so that we can make sure there won't have two or more side windows in the same time.
################################################################
if self.sideWindowCount==0:
self.sideWindow = sideWindow(worldColor = self.worldColor,
lightEnable = self.lightEnable,
ParticleEnable = self.ParticleEnable,
basedriveEnable = self.basedriveEnable,
collision = self.collision,
backface = self.backface,
texture = self.texture,
wireframe = self.wireframe,
grid = self.grid,
widgetVis = self.widgetVis,
enableAutoCamera = self.enableAutoCamera)
self.sideWindowCount = 1
self.menuPanel.entryconfig('Side Window', state=DISABLED)
return
def openAnimationPanel(self):
################################################################
# openAnimationPanel(self)
# This function will do nothing but call other function
# to open the animation window for selected node(if it is an Actor)..
#
# Ok... this is really redundancy...
#
################################################################
if AllScene.isActor(self.nodeSelected):
self.openAnimPanel(self.nodeSelected)
pass
def openMopathPanel(self):
################################################################
# openMopathPanel(self)
# This function will create a Motion Path Recorder
################################################################
MopathPanel = MopathRecorder()
pass
def toggleParticleVisable(self, visable):
################################################################
# toggleParticleVisable(self, visable)
# This function will be called each time user has toggled
# the check box of Particle visibility in the side window.
# The reason we keep track this is because
# we have to know we should show/hide the model on the new-created particle
################################################################
self.ParticleEnable = visable
AllScene.toggleParticleVisable(visable)
return
def openLightingPanel(self):
################################################################
# openLightingPanel(self)
# open the lighting panel here.
# If there is already exist a lighting panel, then do nothing
################################################################
if self.lightingPanel==None:
self.lightingPanel = lightingPanel(AllScene.getLightList())
self.menuPanel.entryconfig('Lighting Panel', state=DISABLED)
return
def addParticleEffect(self,effect_name,effect,node):
AllScene.particleDict[effect_name]=effect
AllScene.particleNodes[effect_name]=node
if not self.ParticleEnable:
AllScene.particleNodes[effect_name].setTransparency(True)
AllScene.particleNodes[effect_name].setAlphaScale(0)
AllScene.particleNodes[effect_name].setBin("fixed",1)
return
def openParticlePanel(self):
if self.particlePanel != None:
## There already has a Particle panel!
return
if(len(AllScene.particleDict)==0):
self.particlePanel=seParticlePanel.ParticlePanel()
else:
for effect in AllScene.particleDict:
theeffect=AllScene.particleDict[effect]
self.particlePanel=seParticlePanel.ParticlePanel(particleEffect=theeffect,effectsDict=AllScene.particleDict)
pass
def closeParticlePanel(self):
self.particlePanel = None
return
def openInputPanel(self):
if self.controllerPanel==None:
list = AllScene.getAllObjNameAsList()
type, dataList = AllScene.getControlSetting()
self.controllerPanel = controllerWindow(listOfObj = list, controlType = type, dataList = dataList)
pass
def closeInputPanel(self):
self.controllerPanel = None
return
def requestObjFromControlW(self, name):
################################################################
# requestObjFromControlW(self, name)
# Call back function
# Each time when user selects a node from Control Panel,
# this function will be called.
# This function will get the actual nodePath from dataHolder and then
# set it back into controller panel
################################################################
node = AllScene.getObjFromSceneByName(name)
if (self.controllerPanel) != None and (node!=None):
self.controllerPanel.setNodePathIn(node)
return
def setControlSet(self, controlType, dataList):
if controlType == 'Keyboard':
self.controlTarget = dataList[0]
self.keyboardMapDict.clear()
self.keyboardMapDict = dataList[1].copy()
self.keyboardSpeedDict.clear()
self.keyboardSpeedDict = dataList[2].copy()
return
def startControl(self, controlType, dataList):
if not self.enableControl:
self.enableControl = True
else:
# Stop the current control setting first
# Also this will make sure we won't catch wrong keyboard message
self.stopControl(controlType)
self.enableControl = True
self.setControlSet(controlType, dataList)
self.lastContorlTimer = globalClock.getFrameTime()
if controlType == 'Keyboard':
self.controlType = 'Keyboard'
self.keyControlEventDict = {}
self.transNodeKeyboard = self.controlTarget.attachNewNode('transformNode')
self.transNodeKeyboard.hide()
for index in self.keyboardMapDict:
self.keyControlEventDict[index] = 0
self.accept(self.keyboardMapDict[index], lambda a = index:self.keyboardPushed(a))
self.accept(self.keyboardMapDict[index]+'-up', lambda a = index:self.keyboardReleased(a))
return
def stopControl(self, controlType):
if not self.enableControl:
return
if controlType == 'Keyboard':
self.enableControl = False
for index in self.keyboardMapDict:
self.ignore(self.keyboardMapDict[index])
self.ignore(self.keyboardMapDict[index]+'-up')
taskMgr.remove("KeyboardControlTask")
self.transNodeKeyboard.removeNode()
return
def keyboardPushed(self, key):
self.keyControlEventDict[key] = 1
if not taskMgr.hasTaskNamed("KeyboardControlTask"):
self.keyboardLastTimer = globalClock.getFrameTime()
taskMgr.add(self.keyboardControlTask, "KeyboardControlTask")
return
def keyboardReleased(self, key):
self.keyControlEventDict[key] = 0
for index in self.keyControlEventDict:
if self.keyControlEventDict[index] == 1:
return
if taskMgr.hasTaskNamed("KeyboardControlTask"):
taskMgr.remove("KeyboardControlTask")
return
def keyboardControlTask(self, task):
newTimer = globalClock.getFrameTime()
delta = newTimer - self.keyboardLastTimer
self.keyboardLastTimer = newTimer
pos = self.controlTarget.getPos()
hpr = self.controlTarget.getHpr()
scale = self.controlTarget.getScale()
self.transNodeKeyboard.setPosHpr((self.keyControlEventDict['KeyRight']*self.keyboardSpeedDict['SpeedRight']-self.keyControlEventDict['KeyLeft']*self.keyboardSpeedDict['SpeedLeft'])*delta,
(self.keyControlEventDict['KeyForward']*self.keyboardSpeedDict['SpeedForward']-self.keyControlEventDict['KeyBackward']*self.keyboardSpeedDict['SpeedBackward'])*delta,
(self.keyControlEventDict['KeyUp']*self.keyboardSpeedDict['SpeedUp']-self.keyControlEventDict['KeyDown']*self.keyboardSpeedDict['SpeedDown'])*delta,
(self.keyControlEventDict['KeyTurnLeft']*self.keyboardSpeedDict['SpeedTurnLeft']-self.keyControlEventDict['KeyTurnRight']*self.keyboardSpeedDict['SpeedTurnRight'])*delta,
(self.keyControlEventDict['KeyTurnUp']*self.keyboardSpeedDict['SpeedTurnUp']-self.keyControlEventDict['KeyTurnDown']*self.keyboardSpeedDict['SpeedTurnDown'])*delta,
(self.keyControlEventDict['KeyRollLeft']*self.keyboardSpeedDict['SpeedRollLeft']-self.keyControlEventDict['KeyRollRight']*self.keyboardSpeedDict['SpeedRollRight'])*delta)
newPos = self.transNodeKeyboard.getPos(self.controlTarget.getParent())
newHpr = self.transNodeKeyboard.getHpr(self.controlTarget.getParent())
overAllScale = self.keyControlEventDict['KeyScaleUp']*self.keyboardSpeedDict['SpeedScaleUp']-self.keyControlEventDict['KeyScaleDown']*self.keyboardSpeedDict['SpeedScaleDown']
newScale = Point3(scale.getX() + (overAllScale + self.keyControlEventDict['KeyScaleXUp']*self.keyboardSpeedDict['SpeedScaleXUp'] - self.keyControlEventDict['KeyScaleXDown']*self.keyboardSpeedDict['SpeedScaleXDown'])*delta,
scale.getY() + (overAllScale + self.keyControlEventDict['KeyScaleYUp']*self.keyboardSpeedDict['SpeedScaleYUp'] - self.keyControlEventDict['KeyScaleYDown']*self.keyboardSpeedDict['SpeedScaleYDown'])*delta,
scale.getZ() + (overAllScale + self.keyControlEventDict['KeyScaleZUp']*self.keyboardSpeedDict['SpeedScaleZUp'] - self.keyControlEventDict['KeyScaleZDown']*self.keyboardSpeedDict['SpeedScaleZDown'])*delta
)
self.controlTarget.setPos(newPos.getX(), newPos.getY() , newPos.getZ())
self.controlTarget.setHpr(newHpr.getX(), newHpr.getY() , newHpr.getZ())
self.controlTarget.setScale(newScale.getX(),newScale.getY(),newScale.getZ())
self.transNodeKeyboard.setPosHpr(0,0,0,0,0,0)
return Task.cont
## Misc
##### This one get the event from SGE (Scene Graph Explorer) and Picking
def selectNode(self, nodePath=None, callBack = True):
################################################################
# selectNode(self, nodePath=None, callBack = True)
# This will be called when user try to select nodes from the
# side window.
# It will also call seSession to select this node in order to keep data's consistency
################################################################
if nodePath==None:
self.isSelect = False
self.nodeSelected =None
if taskMgr.hasTaskNamed('seMonitorSelectedNode'):
taskMgr.remove('seMonitorSelectedNode')
return
else:
self.isSelect = True
#if self.nodeSelected != None:
# self.nodeSelected.hideBounds()
self.nodeSelected = nodePath
#self.nodeSelected.showBounds()
self.menuEdit.entryconfig('Deselect', state=NORMAL)
self.menuEdit.entryconfig('Add Dummy', state=NORMAL)
self.menuEdit.entryconfig('Duplicate', state=NORMAL)
self.menuEdit.entryconfig('Remove', state=NORMAL)
self.menuEdit.entryconfig('Object Properties', state=NORMAL)
if callBack:
self.seSession.select(nodePath,fResetAncestry=1)
messenger.send('SGE_Update Explorer',[render])
if not taskMgr.hasTaskNamed('seMonitorSelectedNode'):
self.oPos = self.nodeSelected.getPos()
self.oHpr = self.nodeSelected.getHpr()
self.oScale = self.nodeSelected.getScale()
taskMgr.add(self.monitorSelectedNodeTask, 'seMonitorSelectedNode')
return
pass
def selectFromScene(self, nodePath=None, callBack=True):
################################################################
# selectFromScene(self, nodePath=None, callBack = True)
# This will be called when user try to select nodes from the
# scene. (By picking)
# Actually this will be called by seSession
# The reason we make two selections is we don't want they call each other and never stop...
################################################################
if nodePath==None:
self.isSelect = False
self.nodeSelected =None
if taskMgr.hasTaskNamed('seMonitorSelectedNode'):
taskMgr.remove('seMonitorSelectedNode')
return
else:
self.isSelect = True
#if self.nodeSelected != None:
# self.nodeSelected.hideBounds()
self.nodeSelected = nodePath
#self.nodeSelected.showBounds()
self.menuEdit.entryconfig('Deselect', state=NORMAL)
self.menuEdit.entryconfig('Add Dummy', state=NORMAL)
self.menuEdit.entryconfig('Duplicate', state=NORMAL)
self.menuEdit.entryconfig('Remove', state=NORMAL)
self.menuEdit.entryconfig('Object Properties', state=NORMAL)
self.sideWindow.SGE.selectNodePath(nodePath,callBack)
messenger.send('SGE_Update Explorer',[render])
if not taskMgr.hasTaskNamed('seMonitorSelectedNode'):
self.oPos = self.nodeSelected.getPos()
self.oHpr = self.nodeSelected.getHpr()
self.oScale = self.nodeSelected.getScale()
taskMgr.add(self.monitorSelectedNodeTask, 'seMonitorSelectedNode')
return
pass
def monitorSelectedNodeTask(self, task):
################################################################
# monitorSelectedNodeTask(self, task)
# This is a function which will keep tracking
# the position, orientation and scale data of selected node and update the display on the screen.
# Alos, it will send out message to sychronize the data in the placer and property window.
################################################################
if self.nodeSelected != None:
pos = self.nodeSelected.getPos()
hpr = self.nodeSelected.getHpr()
scale = self.nodeSelected.getScale()
if ((self.oPos != pos )or(self.oScale != scale)or(self.oHpr != hpr)):
messenger.send('forPorpertyWindow'+self.nodeSelected.getName(),[pos, hpr, scale])
messenger.send('placerUpdate')
self.oPos = pos
self.oScale = scale
self.oHpr = hpr
self.posLabel['text'] = "Position : X: %2.2f Y: %2.2f Z: %2.2f"%(pos.getX(), pos.getY(),pos.getZ())
self.hprLabel['text'] = "Orientation: H: %2.2f P: %2.2f R: %2.2f"%(hpr.getX(), hpr.getY(),hpr.getZ())
self.scaleLabel['text'] = "Scale : X: %2.2f Y: %2.2f Z: %2.2f"%(scale.getX(), scale.getY(),scale.getZ())
return Task.cont
def deselectFromScene(self):
################################################################
# deselectFromScene(self)
# This function will do nothing but call other function
# to delete selected node...
#
# Ok... this is really redundancy...
#
################################################################
self.deSelectNode(self.nodeSelected)
messenger.send('SGE_Update Explorer',[render])
##### Take care the even quest from Side Window
def lightToggle(self):
################################################################
# lightToggle(self)
# This function will do nothing but call other function
# to toggle the light...
################################################################
self.makeDirty()
AllScene.toggleLight()
return
def sideWindowClose(self,worldColor,lightEnable,ParticleEnable, basedriveEnable,collision,
backface, texture, wireframe, grid, widgetVis, enableAutoCamera):
################################################################
# sideWindowClose(self,worldColor,lightEnable,ParticleEnable, basedriveEnable,collision,
# backface, texture, wireframe, grid, widgetVis, enableAutoCamera):
# This function will be called when user close the side window.
# Here we will restore all parameters about world setting back in the sceneEditor.
# So, when next time people recall the side window, it will still keep the same world setting.
################################################################
if self.sideWindowCount==1:
self.worldColor = worldColor
self.lightEnable = lightEnable
self.ParticleEnable = ParticleEnable
self.basedriveEnable = basedriveEnable
self.collision = collision
self.backface = backface
self.texture = texture
self.wireframe = wireframe
self.grid = grid
self.enableAutoCamera = enableAutoCamera
self.widgetVis = widgetVis
self.sideWindowCount=0
self.sideWindow = None
self.menuPanel.entryconfig('Side Window', state=NORMAL)
return
## Process message from Duplication Window
def duplicationObj(self, nodePath, pos, hpr, scale, num):
################################################################
# duplicationObj(self, nodePath, pos, hpr, scale, num)
# This function will do nothing but call other function
# to duplicate selected node...
#
# Ok... this is really redundancy...
#
################################################################
AllScene.duplicateObj(nodePath, pos, hpr, scale, num)
return
## Process message from Animation Panel
def animationLoader(self, nodePath, Dic):
name = nodePath.getName()
AllScene.loadAnimation(name, Dic)
return
def animationRemove(self, nodePath, name):
AllScene.removeAnimation(nodePath.getName(),name)
return
def animPanelClose(self, name):
if self.animPanel.has_key(name):
del self.animPanel[name]
return
### Blend Animation Panel
def openBlendAnimPanel(self, nodePath=None):
################################################################
# openBlendAnimPanel(self, nodePath=None)
# This function will get the user defined blending animation data from dataHolder.
# And then open a blendAnimPanel by passing those data in.
################################################################
name = nodePath.getName()
if AllScene.isActor(name):
if self.animBlendPanel.has_key(name):
print '---- You already have an Blend Animation Panel for this Actor!'
return
else:
Actor = AllScene.getActor(name)
Dict = AllScene.getBlendAnimAsDict(name)
self.animBlendPanel[name] = BlendAnimPanel(aNode=Actor, blendDict=Dict)
pass
return
def animBlendPanelSave(self, actorName, blendName, animNameA, animNameB, effect):
################################################################
# animBlendPanelSave(self, actorName, blendName, animNameA, animNameB, effect)
# This function will call dataHolder to save the blended animation.
# Then, it will reset the newest blended animation list back to animBlendPanel
################################################################
dict = AllScene.saveBlendAnim(actorName, blendName, animNameA, animNameB, effect)
self.animBlendPanel[actorName].setBlendAnimList(dict)
return
def animBlendPanelRemove(self, actorName, blendName):
################################################################
# animBlendPanelRemove(self, actorName, blendName)
# This function will call dataHolder to remove the blended animation.
# Then, it will reset the newest blended animation list back to animBlendPanel
################################################################
dict = AllScene.removeBlendAnim(actorName, blendName)
self.animBlendPanel[actorName].setBlendAnimList(dict, True)
return
def animBlendPanelRename(self, actorName, nName, oName, animNameA, animNameB, effect):
################################################################
# animBlendPanelRename(self, actorName, nName, oName, animNameA, animNameB, effect)
# This function will call dataHolder to rename the blended animation.
# Then, it will reset the newest blended animation list back to animBlendPanel
################################################################
dict = AllScene.renameBlendAnim(actorName, nName, oName, animNameA, animNameB, effect)
self.animBlendPanel[actorName].setBlendAnimList(dict)
return
def animBlendPanelClose(self, name):
################################################################
# animBlendPanelClose(self, name)
# This function will be called when Blend panel has been closed.
# Here we will reset the reference dictionary so it can be open again.
################################################################
if self.animBlendPanel.has_key(name):
del self.animBlendPanel[name]
return
## Process message from SEditor object
def toggleWidgetVis(self):
################################################################
# toggleWidgetVis(self)
# This function will be called when user use the hot-key to change the
# world setting. (From seSession)
# In this function we will restore the change and let side window know
# the hot-key ahs been pushed.
################################################################
if self.sideWindow != None:
self.sideWindow.toggleWidgetVisFromMainW()
else:
self.widgetVis = (self.widgetVis+1)%2
def toggleBackface(self):
################################################################
# toggleBackface(self)
# This function will be called when user use the hot-key to change the
# world setting. (From seSession)
# In this function we will restore the change and let side window know
# the hot-key ahs been pushed.
################################################################
if self.sideWindow != None:
self.sideWindow.toggleBackfaceFromMainW()
else:
self.backface = (self.backface+1)%2
def toggleTexture(self):
################################################################
# toggleTexture(self)
# This function will be called when user use the hot-key to change the
# world setting. (From seSession)
# In this function we will restore the change and let side window know
# the hot-key ahs been pushed.
################################################################
if self.sideWindow != None:
self.sideWindow.toggleTextureFromMainW()
else:
self.texture = (self.texture+1)%2
def toggleWireframe(self):
################################################################
# toggleWireframe(self)
# This function will be called when user use the hot-key to change the
# world setting. (From seSession)
# In this function we will restore the change and let side window know
# the hot-key ahs been pushed.
################################################################
if self.sideWindow != None:
self.sideWindow.toggleWireframeFromMainW()
else:
self.wireframe = (self.wireframe+1)%2
def openAlignPanel(self, nodePath=None):
name = nodePath.getName()
if not self.alignPanelDict.has_key(name):
list = AllScene.getAllObjNameAsList()
if name in list:
list.remove(name)
else:
return
self.alignPanelDict[name] = AlignTool(nodePath = nodePath, list = list)
return
def closeAlignPanel(self, name=None):
if self.alignPanelDict.has_key(name):
del self.alignPanelDict[name]
def alignObject(self, nodePath, name, list):
target = AllScene.getObjFromSceneByName(name)
pos = target.getPos()
hpr = target.getHpr()
scale = target.getScale()
if list[0]: # Align X
nodePath.setX(pos.getX())
if list[1]: # Align Y
nodePath.setY(pos.getY())
if list[2]: # Align Z
nodePath.setZ(pos.getZ())
if list[3]: # Align H
nodePath.setH(hpr.getX())
if list[4]: # Align P
nodePath.setP(hpr.getY())
if list[5]: # Align R
nodePath.setR(hpr.getZ())
if list[6]: # Scale X
nodePath.setSx(scale.getX())
if list[7]: # Scale Y
nodePath.setSy(scale.getY())
if list[8]: # Scale Z
nodePath.setSz(scale.getZ())
return
### Event from Motion Path Panel
def requestCurveList(self, nodePath,name):
curveList = AllScene.getCurveList(nodePath)
messenger.send('curveListFor'+name, [curveList])
## Steal from DirectSession...
def flash(self, nodePath = 'None Given'):
""" Highlight an object by setting it red for a few seconds """
# Clean up any existing task
taskMgr.remove('flashNodePath')
# Spawn new task if appropriate
if nodePath == 'None Given':
# If nothing specified, try selected node path
nodePath = self.selected.last
if nodePath:
if nodePath.hasColor():
doneColor = nodePath.getColor()
flashColor = VBase4(1) - doneColor
flashColor.setW(1)
else:
doneColor = None
flashColor = VBase4(1,0,0,1)
# Temporarily set node path color
nodePath.setColor(flashColor)
# Clean up color in a few seconds
t = taskMgr.doMethodLater(1.5,
# This is just a dummy task
self.flashDummy,
'flashNodePath')
t.nodePath = nodePath
t.doneColor = doneColor
# This really does all the work
t.uponDeath = self.flashDone
def flashDummy(self, state):
# Real work is done in upon death function
return Task.done
def flashDone(self,state):
# Return node Path to original state
if state.nodePath.isEmpty():
# Node path doesn't exist anymore, bail
return
if state.doneColor:
state.nodePath.setColor(state.doneColor)
else:
state.nodePath.clearColor()
editor = myLevelEditor(parent = tkroot)
run()