sceneEditor.py 72 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679
  1. from ShowBaseGlobal import*
  2. from TkGlobal import*
  3. from tkFileDialog import *
  4. from DirectGlobals import *
  5. from AppShell import*
  6. from SideWindow import*
  7. from duplicateWindow import*
  8. from lightingPanel import *
  9. from seMopathRecorder import *
  10. from seSession import *
  11. from quad import *
  12. from sePlacer import *
  13. from seFileSaver import *
  14. from propertyWindow import *
  15. import seParticlePanel
  16. from collisionWindow import *
  17. from DirectGui import *
  18. from MetadataPanel import *
  19. from seBlendAnimPanel import *
  20. from controllerWindow import *
  21. from AlignTool import *
  22. import os
  23. import string
  24. import Dial
  25. import Floater
  26. import Slider
  27. import Actor
  28. import seAnimPanel
  29. import Task
  30. import math
  31. #################################################################
  32. # All scene and windows object will be stored in here.
  33. # So, any event which will or need to change contents
  34. # should be wirtten in here or imported into here!
  35. #################################################################
  36. from dataHolder import* ## Use this thing to Save/load data.
  37. AllScene = dataHolder()
  38. class myLevelEditor(AppShell):
  39. ## overridden the basic app info ##
  40. appname = 'Scene Editor - New Scene'
  41. appversion = '1.0'
  42. copyright = ('Copyright 2004 E.T.C. Carnegie Mellon U.' +
  43. ' All Rights Reserved')
  44. contactname = 'Jesse Schell, Shalin Shodhan & YiHong Lin'
  45. contactphone = '(412) 268-5791'
  46. contactemail = '[email protected]'
  47. frameWidth = 1024
  48. frameHeight = 80
  49. frameIniPosX = 0
  50. frameIniPosY = 0
  51. usecommandarea = 0
  52. usestatusarea = 0
  53. padx = 5
  54. pady = 5
  55. sideWindowCount = 0
  56. ## Basic World default setting (For side window)
  57. worldColor = [0,0,0,0]
  58. lightEnable = 1
  59. ParticleEnable = 1
  60. basedriveEnable = 0
  61. collision = 1
  62. backface = 0
  63. texture = 1
  64. wireframe = 0
  65. grid = 0
  66. widgetVis = 0
  67. enableAutoCamera = 1
  68. enableControl = False
  69. controlType = 'Keyboard'
  70. keyboardMapDict = {}
  71. keyboardSpeedDict = {}
  72. Scene=None
  73. isSelect = False
  74. nodeSelected = None
  75. undoDic = {}
  76. redoDic = {}
  77. animPanel = {}
  78. animBlendPanel = {}
  79. propertyWindow = {}
  80. CurrentFileName=None #Holds the current scene file name
  81. CurrentDirName=None # Holds the current file name without extension which is the path where file's data gets saved
  82. Dirty=0 # Keeps track of whether there are any modifications that should be saved
  83. def __init__(self, parent = None, **kw):
  84. base.setBackgroundColor(0,0,0)
  85. self.parent = parent
  86. ## Check TkTool is activated! ##
  87. self.wantTK = config.GetBool('want-tk', 0)
  88. if self.wantTK:
  89. pass
  90. else:
  91. taskMgr.remove('tkloop')
  92. spawnTkLoop()
  93. ## Set up window frame
  94. INITOPT = Pmw.INITOPT
  95. optiondefs = (
  96. ('title', self.appname, None),
  97. )
  98. self.defineoptions(kw, optiondefs)
  99. AppShell.__init__(self, parent)
  100. self.parent.geometry('%dx%d+%d+%d' % (self.frameWidth, self.frameHeight,self.frameIniPosX,self.frameIniPosY))
  101. ###### Put th directLabel on the screen to show the selected object Data
  102. self.posLabel = DirectLabel(
  103. relief = None,
  104. pos = (-1.3, 0, 0.90),
  105. text = "Position : X: 00.00 Y: 00.00 Z: 00.00",
  106. color = Vec4(1, 1, 1, 1),
  107. text_scale = 0.05,
  108. text_align = TextNode.ALeft
  109. )
  110. self.hprLabel = DirectLabel(
  111. relief = None,
  112. pos = (-1.3 , 0, 0.80),
  113. text = "Orientation: H: 00.00 P: 00.00 R: 00.00",
  114. color = Vec4(1, 1, 1, 1),
  115. text_scale = 0.05,
  116. text_align = TextNode.ALeft
  117. )
  118. self.scaleLabel = DirectLabel(
  119. relief = None,
  120. pos = (-1.3, 0, 0.70),
  121. text = "Scale : X: 00.00 Y: 00.00 Z: 00.00",
  122. color = Vec4(1, 1, 1, 1),
  123. text_scale = 0.05,
  124. text_align = TextNode.ALeft
  125. )
  126. self.initialiseoptions(myLevelEditor)
  127. self.parent.resizable(False,False) ## Disable the ability to resize for this Window.
  128. ######### Set the event handler ##########
  129. self.dataFlowEvents = [
  130. ## Event from Side Window
  131. ['SW_lightToggle',self.lightToggle],
  132. ['SW_collisionToggle',AllScene.toggleCollisionVisable],
  133. ['SW_particleToggle',self.toggleParticleVisable],
  134. ['SW_close',self.sideWindowClose],
  135. ## From Duplication Window
  136. ['DW_duplicating',self.duplicationObj],
  137. ## From Animation Panel
  138. ['AW_AnimationLoad',self.animationLoader],
  139. ['AW_removeAnim',self.animationRemove],
  140. ['AW_close',self.animPanelClose],
  141. ## From Blending Animation Window
  142. ['BAW_saveBlendAnim',self.animBlendPanelSave],
  143. ['BAW_removeBlendAnim',self.animBlendPanelRemove],
  144. ['BAW_renameBlendAnim',self.animBlendPanelRename],
  145. ['BAW_close',self.animBlendPanelClose],
  146. ## From Lighting Panel
  147. ['LP_selectLight', self.lightSelect],
  148. ['LP_addLight',self.addLight],
  149. ['LP_rename',self.lightRename],
  150. ['LP_removeLight',self.removeLight],
  151. ['LP_close',self.lightingPanelClose],
  152. ## From MotionPath Panel
  153. ['mPath_bindPathToNode',AllScene.bindCurveToNode],
  154. ['mPath_requestCurveList', self.requestCurveList],
  155. ['mPath_close', self.mopathClosed],
  156. ## From Property Window
  157. ['PW_removeCurveFromNode', AllScene.removeCurveFromNode],
  158. ['PW_removeAnimFromNode', AllScene.removeAnimation],
  159. ['PW_toggleLight', AllScene.toggleLightNode],
  160. ['PW_close', self.closePropertyWindow],
  161. ## From collisionWindow
  162. ['CW_addCollisionObj', AllScene.addCollisionObject],
  163. ## From AlignWindow
  164. ['ALW_close', self.closeAlignPanel],
  165. ['ALW_align', self.alignObject],
  166. ## From controllerWindow
  167. ['ControlW_close', self.closeInputPanel],
  168. ['ControlW_require', self.requestObjFromControlW],
  169. ['ControlW_controlSetting', self.setControlSet],
  170. ['ControlW_controlEnable', self.startControl],
  171. ['ControlW_controlDisable', self.stopControl],
  172. ['ControlW_saveSetting', AllScene.saveControlSetting],
  173. ## From Placer
  174. ['Placer_close', self.closePlacerPanel],
  175. ## From Particle Panel
  176. ['ParticlePanle_close', self.closeParticlePanel],
  177. ## From SEditor object which is a altered DirectSession
  178. ['SEditor-ToggleWidgetVis',self.toggleWidgetVis],
  179. ['SEditor-ToggleBackface',self.toggleBackface],
  180. ['SEditor-ToggleTexture',self.toggleTexture],
  181. ['SEditor-ToggleWireframe',self.toggleWireframe],
  182. ['ParticlePanel_Added_Effect',self.addParticleEffect],
  183. ]
  184. #################################
  185. ### Collision detection
  186. #################################
  187. self.cTrav = CollisionTraverser()
  188. base.cTrav = self.cTrav
  189. for event in self.dataFlowEvents:
  190. self.accept(event[0], event[1], extraArgs = event[2:])
  191. self.actionEvents = [
  192. # Scene graph explorer functions
  193. ['SGE_changeName', self.changeName],
  194. ['SGE_Properties', self.openPropertyPanel],
  195. ['SGE_Duplicate', self.duplicate],
  196. ['SGE_Remove', self.remove],
  197. ['SGE_Add Dummy', self.addDummyNode],
  198. ['SGE_Add Collision Object', self.addCollisionObj],
  199. ['SGE_Metadata', self.openMetadataPanel],
  200. ['SGE_Set as Reparent Target', self.setAsReparentTarget],
  201. ['SGE_Reparent to Target', self.reparentToNode],
  202. ['SGE_Animation Panel', self.openAnimPanel],
  203. ['SGE_Blend Animation Panel', self.openBlendAnimPanel],
  204. ['SGE_MoPath Panel', self.openMoPathPanel],
  205. ['SGE_Align Tool', self.openAlignPanel],
  206. ['SGE_Flash', self.flash],
  207. ['SGE_madeSelection', self.selectNode],
  208. ['select',self.selectNode],
  209. ['deselect', self.deSelectNode],
  210. ['se_selectedNodePath',self.selectFromScene],
  211. ['se_deselectedAll',self.deselectFromScene],
  212. ]
  213. ''' All messages starting with "SGE_" are generated in seSceneGraphExplorer'''
  214. for event in self.actionEvents:
  215. self.accept(event[0], event[1], extraArgs = event[2:])
  216. camera.toggleVis()
  217. self.selectNode(base.camera) ## Initially, we select camera as the first node...
  218. def appInit(self):
  219. #################################################################
  220. # appInit(self)
  221. # Initialize the application.
  222. # This function will be called when you call AppShell's constructor
  223. #################################################################
  224. ### Create SceneEditor Ver. DirectSession
  225. self.seSession = SeSession()
  226. self.seSession.enable()
  227. SEditor.camera.setPos(0,-50,10)
  228. self.placer=None
  229. self.MopathPanel = None
  230. self.alignPanelDict = {}
  231. #self.quadview=QuadView()
  232. self.lightingPanel = None
  233. self.controllerPanel = None
  234. self.particlePanel = None
  235. ### Create Side Window
  236. self.sideWindow = sideWindow(worldColor = self.worldColor,
  237. lightEnable = self.lightEnable,
  238. ParticleEnable = self.ParticleEnable,
  239. basedriveEnable = self.basedriveEnable,
  240. collision = self.collision,
  241. backface = self.backface,
  242. texture = self.texture,
  243. wireframe = self.wireframe,
  244. grid = self.grid,
  245. widgetVis = self.widgetVis,
  246. enableAutoCamera = self.enableAutoCamera)
  247. self.sideWindowCount = 1
  248. self.sideWindow.selectPage()
  249. messenger.send('SGE_Update Explorer',[render]) ## Update the Scene Graph
  250. pass
  251. def createInterface(self):
  252. # The interior of the toplevel panel
  253. interior = self.interior()
  254. #######################################################
  255. ### Creating the Buttons in the window frame
  256. #######################################################
  257. buttonFrame = Frame(interior)
  258. self.image=[]
  259. self.image.append(PhotoImage(file='new.gif'))#0
  260. self.image.append(PhotoImage(file='open.gif'))#1
  261. self.image.append(PhotoImage(file='save.gif'))#2
  262. self.image.append(PhotoImage(file='model.gif'))#3
  263. self.image.append(PhotoImage(file='actor.gif'))#4
  264. self.image.append(PhotoImage(file='placer.gif'))#5
  265. self.image.append(PhotoImage(file='mopath.gif'))#6
  266. self.image.append(PhotoImage(file='lights.gif'))#7
  267. self.image.append(PhotoImage(file='particles.gif'))#8
  268. self.image.append(PhotoImage(file='control.gif'))
  269. self.image.append(PhotoImage(file='help.gif'))#9
  270. self.image.append(PhotoImage(file='blank.gif'))
  271. self.image.append(PhotoImage(file='blank.gif'))
  272. self.image.append(PhotoImage(file='blank.gif'))
  273. self.image.append(PhotoImage(file='blank.gif'))
  274. self.image.append(PhotoImage(file='blank.gif'))
  275. self.image.append(PhotoImage(file='blank.gif'))
  276. self.image.append(PhotoImage(file='blank.gif'))
  277. self.image.append(PhotoImage(file='blank.gif'))
  278. self.image.append(PhotoImage(file='blank.gif'))
  279. self.image.append(PhotoImage(file='blank.gif'))
  280. self.image.append(PhotoImage(file='blank.gif'))
  281. self.image.append(PhotoImage(file='blank.gif'))
  282. i = 0
  283. for element in self.image:
  284. i += 1
  285. button = Button(buttonFrame, image = element, command=lambda n=i : self.buttonPushed(n))
  286. button.pack(fill=X, side = LEFT)
  287. buttonFrame.pack(fill=X, side=LEFT,expand=True)
  288. def buttonPushed(self, buttonIndex):
  289. #################################################################
  290. # buttonPushed(self, buttonNum)
  291. # This function will handle all button events from top level window
  292. # Take the button index as a reference to sence which button has been pushed.
  293. #################################################################
  294. ####
  295. #### Change here to process the button event further.
  296. ####
  297. if buttonIndex==1: # New Scene
  298. self.newScene()
  299. return
  300. elif buttonIndex==2: # Open Scene
  301. self.openScene()
  302. return
  303. elif buttonIndex==3: # Save Scene
  304. self.saveScene()
  305. return
  306. elif buttonIndex==4: # Load Model
  307. self.loadModel()
  308. return
  309. elif buttonIndex==5: # Load Actor
  310. self.loadActor()
  311. return
  312. elif buttonIndex==6: # Open Placer
  313. self.openPlacerPanel()
  314. return
  315. elif buttonIndex==7: # Open Mopath Panel
  316. self.openMoPathPanel()
  317. return
  318. elif buttonIndex==8: # Open Lighting Panel
  319. self.openLightingPanel()
  320. return
  321. elif buttonIndex==9: # Open Particle Panel
  322. self.openParticlePanel()
  323. return
  324. elif buttonIndex==10:
  325. self.openInputPanel()
  326. return
  327. elif buttonIndex==11: # Help
  328. self.showAbout()
  329. return
  330. elif buttonIndex==12:
  331. print "You haven't defined the function for this Button, Number %d."%buttonIndex
  332. return
  333. elif buttonIndex==13:
  334. print "You haven't defined the function for this Button, Number %d."%buttonIndex
  335. return
  336. elif buttonIndex==14:
  337. print "You haven't defined the function for this Button, Number %d."%buttonIndex
  338. return
  339. elif buttonIndex==15:
  340. print "You haven't defined the function for this Button, Number %d."%buttonIndex
  341. return
  342. elif buttonIndex==16:
  343. print "Your scene will be eliminated within five seconds, Save your world!!!, Number %d."%buttonIndex
  344. return
  345. elif buttonIndex==17:
  346. print "You haven't defined the function for this Button, Number %d."%buttonIndex
  347. return
  348. elif buttonIndex==18:
  349. print "You haven't defined the function for this Button, Number %d."%buttonIndex
  350. return
  351. elif buttonIndex==19:
  352. print "You haven't defined the function for this Button, Number %d."%buttonIndex
  353. return
  354. elif buttonIndex==20:
  355. print "You haven't defined the function for this Button, Number %d."%buttonIndex
  356. return
  357. return
  358. def createMenuBar(self):
  359. # Creates default menus. Can be overridden or simply augmented
  360. # Using button Add below
  361. self.menuBar.addmenuitem('Help', 'command',
  362. 'Get information on application',
  363. label='About...', command=self.showAbout)
  364. ## Creat stuff inside the "File"
  365. self.menuBar.addmenuitem('File', 'command', 'Creat New Scene',
  366. label='New Scene',
  367. command=self.newScene)
  368. self.menuBar.addmenuitem('File', 'command', 'Open a Scene',
  369. label='Open Scene',
  370. command=self.openScene)
  371. self.menuBar.addmenuitem('File', 'command', 'Save a Scene',
  372. label='Save Scene',
  373. command=self.saveScene)
  374. self.menuBar.addmenuitem('File', 'command', 'Save Scene as...',
  375. label='Save as...',
  376. command=self.saveAsScene)
  377. self.menuBar.addmenuitem('File', 'separator')
  378. self.menuBar.addmenuitem('File', 'command', 'Load Model',
  379. label='Load Model',
  380. command=self.loadModel)
  381. self.menuBar.addmenuitem('File', 'command', 'Load Actor',
  382. label='Load Actor',
  383. command=self.loadActor)
  384. self.menuBar.addmenuitem('File', 'separator')
  385. self.menuBar.addmenuitem('File', 'command', 'Import a Scene',
  386. label='Import...',
  387. command=self.importScene)
  388. self.menuBar.addmenuitem('File', 'separator')
  389. self.menuBar.addmenuitem('File', 'command', 'Quit this application',
  390. label='Exit',
  391. command=self.quit)
  392. ## Creat "Edit" on the menu and its stuff
  393. self.menuBar.addmenu('Edit', 'Editting tools')
  394. self.menuBar.addmenuitem('Edit', 'command', 'Un-do',
  395. label='Undo...',
  396. command=self.unDo)
  397. self.menuBar.addmenuitem('Edit', 'command', 'Re-do',
  398. label='Redo...',
  399. command=self.reDo)
  400. self.menuBar.addmenuitem('Edit', 'separator')
  401. self.menuBar.addmenuitem('Edit', 'command', 'Deselect nodepath',
  402. label='Deselect',
  403. command=self.deSelectNode)
  404. self.menuBar.addmenuitem('Edit', 'separator')
  405. self.menuBar.addmenuitem('Edit', 'command', 'Add a Dummy',
  406. label='Add Dummy',
  407. command=self.addDummy)
  408. self.menuBar.addmenuitem('Edit', 'command', 'Duplicate nodepath',
  409. label='Duplicate',
  410. command=self.duplicateNode)
  411. self.menuBar.addmenuitem('Edit', 'command', 'Remove the nodepath',
  412. label='Remove',
  413. command=self.removeNode)
  414. self.menuBar.addmenuitem('Edit', 'command', 'Show the object properties',
  415. label='Object Properties',
  416. command=self.showObjProp)
  417. self.menuBar.addmenuitem('Edit', 'separator')
  418. self.menuBar.addmenuitem('Edit', 'command', 'Show the Camera setting',
  419. label='Camera Setting',
  420. command=self.showCameraSetting)
  421. self.menuBar.addmenuitem('Edit', 'command', 'Render setting',
  422. label='Render Setting',
  423. command=self.showRenderSetting)
  424. ## Creat "Panel" on the menu and its stuff
  425. self.menuBar.addmenu('Panel', 'Panel tools')
  426. self.menuBar.addmenuitem('Panel', 'command', 'Open Side Window',
  427. label='Side Window',
  428. command=self.openSideWindow)
  429. self.menuBar.addmenuitem('Panel', 'command', 'Placer Panel',
  430. label='Placer Panel',
  431. command=self.openPlacerPanel)
  432. self.menuBar.addmenuitem('Panel', 'command', 'Animation Panel',
  433. label='Animation Panel',
  434. command=self.openAnimationPanel)
  435. self.menuBar.addmenuitem('Panel', 'command', 'Motion Path Panel',
  436. label='Mopath Panel',
  437. command=self.openMopathPanel)
  438. self.menuBar.addmenuitem('Panel', 'command', 'Lighting Panel',
  439. label='Lighting Panel',
  440. command=self.openLightingPanel)
  441. self.menuBar.addmenuitem('Panel', 'command', 'Particle Panel',
  442. label='Particle Panel',
  443. command=self.openParticlePanel)
  444. self.menuBar.addmenuitem('Panel', 'separator')
  445. self.menuBar.addmenuitem('Panel', 'command', 'Input control Panel',
  446. label='Input device panel',
  447. command=self.openInputPanel)
  448. self.menuBar.pack(fill=X, side = LEFT)
  449. ## get "Menu" items in order to control the entry status
  450. self.menuFile = self.menuBar.component('File-menu')
  451. self.menuEdit = self.menuBar.component('Edit-menu')
  452. self.menuPanel = self.menuBar.component('Panel-menu')
  453. ## Disable entries when user doesn't select anything
  454. if not self.isSelect:
  455. self.menuEdit.entryconfig('Deselect', state=DISABLED)
  456. self.menuEdit.entryconfig('Add Dummy', state=DISABLED)
  457. self.menuEdit.entryconfig('Duplicate', state=DISABLED)
  458. self.menuEdit.entryconfig('Remove', state=DISABLED)
  459. self.menuEdit.entryconfig('Object Properties', state=DISABLED)
  460. self.menuPanel.entryconfig('Animation Panel', state=DISABLED)
  461. self.menuPanel.entryconfig('Side Window', state=DISABLED)
  462. def onDestroy(self, event):
  463. #################################################################
  464. # If you have open any thing, please rewrite here!
  465. #################################################################
  466. if taskMgr.hasTaskNamed('seMonitorSelectedNode'):
  467. taskMgr.remove('seMonitorSelectedNode')
  468. pass
  469. def closeAllSubWindows(self):
  470. #################################################################
  471. # closeAllSubWindows(self)
  472. # except side window. this function will close all sub window if there is any.
  473. #################################################################
  474. if self.lightingPanel != None:
  475. self.lightingPanel.quit()
  476. if self.placer != None:
  477. self.placer.quit()
  478. if self.MopathPanel != None:
  479. self.MopathPanel.quit()
  480. if self.particlePanel != None:
  481. self.particlePanel.quit()
  482. if self.controllerPanel != None:
  483. self.controllerPanel.quit()
  484. list = self.animPanel.keys()
  485. for index in list:
  486. self.animPanel[index].quit()
  487. list = self.animBlendPanel.keys()
  488. for index in list:
  489. self.animBlendPanel[index].quit()
  490. list = self.propertyWindow.keys()
  491. for index in list:
  492. self.propertyWindow[index].quit()
  493. list = self.alignPanelDict.keys()
  494. for index in list:
  495. self.alignPanelDict[index].quit()
  496. self.animPanel.clear()
  497. self.animBlendPanel.clear()
  498. self.propertyWindow.clear()
  499. self.alignPanelDict.clear()
  500. return
  501. ## Processing message events
  502. def makeDirty(self):
  503. self.Dirty=1
  504. def removeLight(self, lightNode):
  505. #################################################################
  506. # removeLight(self, lightNode)
  507. # This function will be called when user try to remove the light from lightingPanel
  508. # (by sending out the message)
  509. # So, in here we will call dataHolder(AllScene) to remove the light
  510. # and return a list contains the newest data of lights in he scene.
  511. # Then, this function will reset the lighting list in the lightingPanel
  512. #################################################################
  513. list = AllScene.removeObj(lightNode)
  514. if self.lightingPanel != None:
  515. self.lightingPanel.updateList(list)
  516. return
  517. def lightRename(self,oName, nName):
  518. #################################################################
  519. # lightRename(self,oName, nName)
  520. # This function will be called when user try to rename the light from lightingPanel
  521. # (by sending out the message)
  522. # So, in here we will call dataHolder(AllScene) to rename the light
  523. # and return a list contains the newest data of lights in he scene.
  524. # Then, this function will reset the lighting list in the lightingPanel
  525. #################################################################
  526. list, lightNode = AllScene.rename(oName, nName)
  527. if self.lightingPanel != None:
  528. self.lightingPanel.updateList(list,lightNode)
  529. return
  530. def lightSelect(self,lightName):
  531. #################################################################
  532. # lightSelect(self,lightName)
  533. # This function will be called when user try to select the light from lightingPanel
  534. # (by sending out the message)
  535. # So, in here we will call dataHolder(AllScene) to get the target light node
  536. # Then, this function will put this light node back into lighting
  537. # panel and update the data on the panel.
  538. #################################################################
  539. lightNode = AllScene.getLightNode(lightName)
  540. if self.lightingPanel != None:
  541. self.lightingPanel.updateDisplay(lightNode)
  542. return
  543. def addLight(self, type):
  544. #################################################################
  545. # addLight(self, type)
  546. # This function will be called when user try to add a light from lightingPanel
  547. # (by sending out the message)
  548. # So, in here we will call dataHolder(AllScene) to create a default light node
  549. # by the type that user assigned.
  550. # Then, this function will put this light node back into lighting
  551. # panel with the newest lighting list and update the data on the panel.
  552. #################################################################
  553. list, lightNode = AllScene.createLight(type = type)
  554. if self.lightingPanel != None:
  555. self.lightingPanel.updateList(list,lightNode)
  556. self.makeDirty()
  557. return
  558. def lightingPanelClose(self):
  559. #################################################################
  560. # lightingPanelClose(self)
  561. # This function will be called when user try to close the lighting panel
  562. # This function will re-config the state of the lighting panel button on the top screen
  563. # And it will set the self.lightingPanel to None
  564. #################################################################
  565. self.menuPanel.entryconfig('Lighting Panel', state=NORMAL)
  566. self.lightingPanel = None
  567. return
  568. def openPropertyPanel(self, nodePath = None):
  569. #################################################################
  570. # openPropertyPanel(self, nodePath = None)
  571. # This function will be called when user try to open a property window
  572. # for one specific node in the scene.
  573. # Here we will call dataHolder to get the basic properties
  574. # we would like to let user to see and cange.
  575. # And then we pass those information into propertyWindow
  576. #################################################################
  577. type, info = AllScene.getInfoOfThisNode(nodePath)
  578. name = nodePath.getName()
  579. if not self.propertyWindow.has_key(name):
  580. self.propertyWindow[name] = propertyWindow(nodePath, type,info )
  581. pass
  582. def closePropertyWindow(self, name):
  583. if self.propertyWindow.has_key(name):
  584. del self.propertyWindow[name]
  585. return
  586. def openMetadataPanel(self,nodePath=None):
  587. print nodePath
  588. self.MetadataPanel=MetadataPanel(nodePath)
  589. pass
  590. def duplicate(self, nodePath = None):
  591. #################################################################
  592. # duplicate(self, nodePath = None)
  593. # This function will be called when user try to open the duplication window
  594. #################################################################
  595. print '----Duplication!!'
  596. if nodePath != None:
  597. self.duplicateWindow = duplicateWindow(nodePath = nodePath)
  598. pass
  599. def remove(self, nodePath = None):
  600. #################################################################
  601. # remove(self, nodePath = None)
  602. # This function will be called when user try to delete a node from scene
  603. #
  604. # For safty issue,
  605. # we will do deselect first then remove the certain node.
  606. #
  607. #################################################################
  608. if nodePath==None:
  609. if self.nodeSelected == None:
  610. return
  611. nodePath = self.nodeSelected
  612. self.deSelectNode()
  613. if AllScene.isLight(nodePath.getName()):
  614. self.removeLight(nodePath)
  615. else:
  616. AllScene.removeObj(nodePath)
  617. pass
  618. def addDummyNode(self, nodepath = None):
  619. #################################################################
  620. # addDummyNode(self, nodepath = None)
  621. # This function will be called when user try to create a dummy node into scene
  622. #
  623. # Here we will call dataHolder to create a dummy node
  624. # and reparent it to the nodePath that user has assigned.
  625. #
  626. #################################################################
  627. AllScene.addDummyNode(nodepath)
  628. self.makeDirty()
  629. pass
  630. def addCollisionObj(self, nodepath = None):
  631. #################################################################
  632. # addCollisionObj(self, nodepath = None)
  633. # This function will be called when user try to create a collision object into the scene
  634. #
  635. # Here we will call collisionWindow to ask user what kind of collision objects they want to have.
  636. # Then, send the information and generated collision object to dataHolder to finish the whole process
  637. # and reparent it to the nodePath that user has assigned.
  638. #
  639. #################################################################
  640. self.collisionWindow = collisionWindow(nodepath)
  641. pass
  642. def setAsReparentTarget(self, nodepath = None):
  643. #################################################################
  644. # setAsReparentTarget(self, nodepath = None)
  645. # This function will be called when user select a nodePaht
  646. # and want to reparent other node under it. (Drom side window pop-up nemu)
  647. #################################################################
  648. SEditor.setActiveParent(nodepath)
  649. return
  650. def reparentToNode(self, nodepath = None):
  651. #################################################################
  652. # reparentToNode(self, nodepath = None)
  653. # This function will be call when user try to reparent a node to
  654. # that node he selected as a reparent target before.
  655. #
  656. # The whole reparent process is handled by seSession,
  657. # which is tunned from DirectSession
  658. #
  659. #################################################################
  660. SEditor.reparent(nodepath, fWrt = 1)
  661. return
  662. def openPlacerPanel(self, nodePath = None):
  663. #################################################################
  664. # openPlacerPanel(self, nodePath = None)
  665. # This function will be call when user try to open a placer panel.
  666. # This call will only success if there is no other placer panel been activated
  667. #################################################################
  668. if(self.placer==None):
  669. self.placer = Placer()
  670. self.menuPanel.entryconfig('Placer Panel', state=DISABLED)
  671. return
  672. def closePlacerPanel(self):
  673. #################################################################
  674. # closePlacerPanel(self)
  675. # This function will be called when user close the placer panel.
  676. # Here we will reset the self.placer back to None.
  677. # (You can think this is just like a reference count)
  678. #################################################################
  679. self.placer = None
  680. self.menuPanel.entryconfig('Placer Panel', state=NORMAL)
  681. return
  682. def openAnimPanel(self, nodePath = None):
  683. #################################################################
  684. # openAnimPanel(self, nodePath = None)
  685. # This function will be called when user tries to open an Animation Panel
  686. # This will generated a panel and put it
  687. # into a dictionary using the actor's name as an index.
  688. # So, if there already has an animation panel for the target actor,
  689. # it won't allow user to open another one.
  690. #################################################################
  691. name = nodePath.getName()
  692. if AllScene.isActor(name):
  693. if self.animPanel.has_key(name):
  694. print '---- You already have an animation panel for this Actor!'
  695. return
  696. else:
  697. Actor = AllScene.getActor(name)
  698. self.animPanel[name] = seAnimPanel.AnimPanel(aNode=Actor)
  699. pass
  700. def openMoPathPanel(self, nodepath = None):
  701. #################################################################
  702. # openMoPathPanel(self, nodepath = None)
  703. # This function will open a Motion Path Recorder for you.
  704. #################################################################
  705. if self.MopathPanel == None:
  706. self.MopathPanel = MopathRecorder()
  707. pass
  708. def mopathClosed(self):
  709. self.MopathPanel = None
  710. return
  711. def changeName(self, nodePath, nName):
  712. #################################################################
  713. # changeName(self, nodePath, nName)
  714. # This function will be called when user tries to change the name of the node
  715. #################################################################
  716. oName = nodePath.getName() # I need this line in order to check the obj name in the control panel.
  717. AllScene.rename(nodePath,nName)
  718. # reset the list in the controller panel if it has been opened.
  719. if (self.controllerPanel) != None:
  720. list = AllScene.getAllObjNameAsList()
  721. self.controllerPanel.resetNameList(list = list, name = oName, nodePath = nodePath)
  722. return
  723. # Take care things under File menu
  724. def newScene(self):
  725. #################################################################
  726. # newScene(self)
  727. # This function will clear whole stuff in the scene
  728. # and will reset the application title to "New Scene"
  729. #################################################################
  730. self.closeAllSubWindows() ## Close all sub window
  731. if(self.CurrentFileName):
  732. currentF=Filename(self.CurrentFileName)
  733. self.CurrentFileName=None
  734. AllScene.resetAll()
  735. currentModName=currentF.getBasenameWoExtension()
  736. # Let us actually remove the scene from sys modules... this is done because every scene is loaded as a module
  737. # And if we reload a scene python wont reload since its already in sys.modules... and hence we delete it
  738. # If there is ever a garbage colleciton bug..this might be a point to look at
  739. if sys.modules.has_key(currentModName):
  740. del sys.modules[currentModName]
  741. print sys.getrefcount(AllScene.theScene)
  742. del AllScene.theScene
  743. else:
  744. AllScene.resetAll()
  745. self.parent.title('Scene Editor - New Scene')
  746. pass
  747. def openScene(self):
  748. #################################################################
  749. # openScene(self)
  750. #################################################################
  751. # In the future try and provide merging of two scenes
  752. if(self.CurrentFileName or self.Dirty):
  753. saveScene = tkMessageBox._show("Load scene","Save the current scene?",icon = tkMessageBox.QUESTION,type = tkMessageBox.YESNOCANCEL)
  754. if (saveScene == "yes"):
  755. self.saveScene()
  756. elif (saveScene == "cancel"):
  757. return
  758. self.closeAllSubWindows() ## Close all sub window
  759. if(self.CurrentFileName):
  760. currentF=Filename(self.CurrentFileName)
  761. AllScene.resetAll()
  762. currentModName=currentF.getBasenameWoExtension()
  763. # Let us actually remove the scene from sys modules... this is done because every scene is loaded as a module
  764. # And if we reload a scene python wont reload since its already in sys.modules... and hence we delete it
  765. # If there is ever a garbage colleciton bug..this might be a point to look at
  766. if sys.modules.has_key(currentModName):
  767. del sys.modules[currentModName]
  768. print sys.getrefcount(AllScene.theScene)
  769. del AllScene.theScene
  770. else:
  771. AllScene.resetAll()
  772. self.CurrentFileName = AllScene.loadScene()
  773. if(self.CurrentFileName==None):
  774. return
  775. thefile=Filename(self.CurrentFileName)
  776. thedir=thefile.getFullpathWoExtension()
  777. print "SCENE EDITOR::" + thedir
  778. self.CurrentDirName=thedir
  779. if self.CurrentFileName != None:
  780. self.parent.title('Scene Editor - '+ Filename.fromOsSpecific(self.CurrentFileName).getBasenameWoExtension())
  781. if self.lightingPanel !=None:
  782. lightList=AllScene.getList()
  783. self.lightingPanel.updateList(lightList)
  784. messenger.send('SGE_Update Explorer',[render])
  785. # Close the side window in order to reset all world settings to fit the scene we have loaded.
  786. self.sideWindow.quit()
  787. # Try to re-open the side window again
  788. while self.sideWindow == None:
  789. wColor = base.getBackgroundColor()
  790. self.worldColor[0] = wColor.getX()
  791. self.worldColor[1] = wColor.getY()
  792. self.worldColor[2] = wColor.getZ()
  793. self.worldColor[3] = wColor.getW()
  794. self.lightEnable = 1
  795. self.ParticleEnable = 1
  796. self.collision = 1
  797. self.openSideWindow()
  798. def saveScene(self):
  799. #################################################################
  800. # saveScene(self)
  801. # If this is an open file call saveAsScene
  802. # or else instantiate FileSaver from seFileSaver.py and pass it the filename
  803. # If this filename exists in sys.modules you cannot use it
  804. #################################################################
  805. if(self.CurrentFileName):
  806. f=FileSaver()
  807. f.SaveFile(AllScene,self.CurrentFileName,self.CurrentDirName,1)
  808. self.Dirty=0
  809. else:
  810. self.saveAsScene()
  811. pass
  812. def saveAsScene(self):
  813. #################################################################
  814. # saveAsScene(self)
  815. # Ask for filename using a file save dialog
  816. # If this filename exists in sys.modules you cannot use it
  817. # Instantiate FileSaver from seFileSaver.py and pass it the filename
  818. #################################################################
  819. fileName = tkFileDialog.asksaveasfilename(filetypes = [("PY","py")],title = "Save Scene")
  820. if(not fileName):
  821. return
  822. fCheck=Filename(fileName)
  823. #print fCheck.getBasenameWoExtension()
  824. ###############################################################################
  825. # !!!!! See if a module exists by this name... if it does you cannot use this filename !!!!!
  826. ###############################################################################
  827. if(sys.modules.has_key(fCheck.getBasenameWoExtension())):
  828. tkMessageBox.showwarning(
  829. "Save file",
  830. "Cannot save with this name because there is a system module with the same name. Please resave as something else."
  831. )
  832. return
  833. self.CurrentDirName=fileName
  834. fileName=fileName+".py"
  835. f=FileSaver()
  836. self.CurrentFileName=fileName
  837. f.SaveFile(AllScene,fileName,self.CurrentDirName,0)
  838. self.Dirty=0
  839. self.parent.title('Scene Editor - '+ Filename.fromOsSpecific(self.CurrentFileName).getBasenameWoExtension())
  840. pass
  841. def loadModel(self):
  842. #################################################################
  843. # loadModel(self)
  844. # This function will be called when user tries to load a model into the scene.
  845. # Here we will pop-up a dialog to ask user which model file should be loaded in.
  846. # Then, pass the path to dataHolder to load the model in.
  847. #################################################################
  848. modelFilename = askopenfilename(
  849. defaultextension = '.egg',
  850. filetypes = (('Egg Files', '*.egg'),
  851. ('Bam Files', '*.bam'),
  852. ('All files', '*')),
  853. initialdir = '.',
  854. title = 'Load New Model',
  855. parent = self.parent)
  856. if modelFilename:
  857. self.makeDirty()
  858. if not AllScene.loadModel(modelFilename, Filename.fromOsSpecific(modelFilename)):
  859. print '----Error! No Such Model File!'
  860. pass
  861. def loadActor(self):
  862. #################################################################
  863. # loadActor(self)
  864. # This function will be called when user tries to load an Actor into the scene.
  865. # Here we will pop-up a dialog to ask user which Actor file should be loaded in.
  866. # Then, pass the path to dataHolder to load the Actor in.
  867. #################################################################
  868. ActorFilename = askopenfilename(
  869. defaultextension = '.egg',
  870. filetypes = (('Egg Files', '*.egg'),
  871. ('Bam Files', '*.bam'),
  872. ('All files', '*')),
  873. initialdir = '.',
  874. title = 'Load New Actor',
  875. parent = self.parent)
  876. if ActorFilename:
  877. self.makeDirty()
  878. if not AllScene.loadActor(ActorFilename, Filename.fromOsSpecific(ActorFilename)):
  879. print '----Error! No Such Model File!'
  880. pass
  881. def importScene(self):
  882. self.makeDirty()
  883. print '----God bless you Please Import!'
  884. pass
  885. ## Take care those things under Edit nemu
  886. def unDo(self):
  887. pass
  888. def reDo(self):
  889. pass
  890. def deSelectNode(self, nodePath=None):
  891. #################################################################
  892. # deSelectNode(self, nodePath=None)
  893. # This function will deselect the node which we have selected currently.
  894. # This will also remove the monitor task which monitor selected object's
  895. # position, orientation and scale each frame.
  896. #################################################################
  897. if nodePath != None:
  898. self.seSession.deselect(nodePath)
  899. if self.isSelect:
  900. self.isSelect = False
  901. #if self.nodeSelected != None:
  902. # self.nodeSelected.hideBounds()
  903. self.nodeSelected =None
  904. self.menuEdit.entryconfig('Deselect', state=DISABLED)
  905. self.menuEdit.entryconfig('Add Dummy', state=DISABLED)
  906. self.menuEdit.entryconfig('Duplicate', state=DISABLED)
  907. self.menuEdit.entryconfig('Remove', state=DISABLED)
  908. self.menuEdit.entryconfig('Object Properties', state=DISABLED)
  909. if self.sideWindowCount==1:
  910. self.sideWindow.SGE.deSelectTree()
  911. if taskMgr.hasTaskNamed('seMonitorSelectedNode'):
  912. taskMgr.remove('seMonitorSelectedNode')
  913. return
  914. pass
  915. def addDummy(self):
  916. #################################################################
  917. # addDummy(self)
  918. # This function will do nothing but call other function
  919. # to add a dummy into the scene.
  920. #
  921. # Ok... this is really redundancy...
  922. #
  923. #################################################################
  924. self.addDummyNode(self.nodeSelected)
  925. pass
  926. def duplicateNode(self):
  927. #################################################################
  928. # duplicateNode(self)
  929. # This function will do nothing but call other function
  930. # to open the duplication window.
  931. #
  932. # Ok... this is really redundancy...
  933. #
  934. #################################################################
  935. if self.nodeSelected!=None:
  936. self.duplicate(self.nodeSelected)
  937. pass
  938. def removeNode(self):
  939. #################################################################
  940. # removeNode(self)
  941. # This function will do nothing but call other function
  942. # to remove the current selected node..
  943. #
  944. # Ok... this is really redundancy...
  945. #
  946. ################################################################
  947. self.remove(self.nodeSelected)
  948. pass
  949. def showObjProp(self):
  950. ################################################################
  951. # showObjProp(self)
  952. # This function will do nothing but call other function
  953. # to open the property window of current selected node..
  954. #
  955. # Ok... this is really redundancy...
  956. #
  957. ################################################################
  958. self.openPropertyPanel(self.nodeSelected)
  959. pass
  960. def showCameraSetting(self):
  961. ################################################################
  962. # showCameraSetting(self)
  963. # This function will do nothing but call other function
  964. # to open the property window of camera..
  965. #
  966. # Ok... this is really redundancy...
  967. #
  968. ################################################################
  969. self.openPropertyPanel(camera)
  970. pass
  971. def showRenderSetting(self):
  972. '''Currently, no idea what gonna pop-out here...'''
  973. pass
  974. ## Take care those thins under Edit nemu
  975. def openSideWindow(self):
  976. ################################################################
  977. # openSideWindow(self)
  978. # This function will open the side window and set the reference number
  979. # so that we can make sure there won't have two or more side windows in the same time.
  980. ################################################################
  981. if self.sideWindowCount==0:
  982. self.sideWindow = sideWindow(worldColor = self.worldColor,
  983. lightEnable = self.lightEnable,
  984. ParticleEnable = self.ParticleEnable,
  985. basedriveEnable = self.basedriveEnable,
  986. collision = self.collision,
  987. backface = self.backface,
  988. texture = self.texture,
  989. wireframe = self.wireframe,
  990. grid = self.grid,
  991. widgetVis = self.widgetVis,
  992. enableAutoCamera = self.enableAutoCamera)
  993. self.sideWindowCount = 1
  994. self.menuPanel.entryconfig('Side Window', state=DISABLED)
  995. return
  996. def openAnimationPanel(self):
  997. ################################################################
  998. # openAnimationPanel(self)
  999. # This function will do nothing but call other function
  1000. # to open the animation window for selected node(if it is an Actor)..
  1001. #
  1002. # Ok... this is really redundancy...
  1003. #
  1004. ################################################################
  1005. if AllScene.isActor(self.nodeSelected):
  1006. self.openAnimPanel(self.nodeSelected)
  1007. pass
  1008. def openMopathPanel(self):
  1009. ################################################################
  1010. # openMopathPanel(self)
  1011. # This function will create a Motion Path Recorder
  1012. ################################################################
  1013. MopathPanel = MopathRecorder()
  1014. pass
  1015. def toggleParticleVisable(self, visable):
  1016. ################################################################
  1017. # toggleParticleVisable(self, visable)
  1018. # This function will be called each time user has toggled
  1019. # the check box of Particle visibility in the side window.
  1020. # The reason we keep track this is because
  1021. # we have to know we should show/hide the model on the new-created particle
  1022. ################################################################
  1023. self.ParticleEnable = visable
  1024. AllScene.toggleParticleVisable(visable)
  1025. return
  1026. def openLightingPanel(self):
  1027. ################################################################
  1028. # openLightingPanel(self)
  1029. # open the lighting panel here.
  1030. # If there is already exist a lighting panel, then do nothing
  1031. ################################################################
  1032. if self.lightingPanel==None:
  1033. self.lightingPanel = lightingPanel(AllScene.getLightList())
  1034. self.menuPanel.entryconfig('Lighting Panel', state=DISABLED)
  1035. return
  1036. def addParticleEffect(self,effect_name,effect,node):
  1037. AllScene.particleDict[effect_name]=effect
  1038. AllScene.particleNodes[effect_name]=node
  1039. if not self.ParticleEnable:
  1040. AllScene.particleNodes[effect_name].setTransparency(True)
  1041. AllScene.particleNodes[effect_name].setAlphaScale(0)
  1042. AllScene.particleNodes[effect_name].setBin("fixed",1)
  1043. return
  1044. def openParticlePanel(self):
  1045. if self.particlePanel != None:
  1046. ## There already has a Particle panel!
  1047. return
  1048. if(len(AllScene.particleDict)==0):
  1049. self.particlePanel=seParticlePanel.ParticlePanel()
  1050. else:
  1051. for effect in AllScene.particleDict:
  1052. theeffect=AllScene.particleDict[effect]
  1053. self.particlePanel=seParticlePanel.ParticlePanel(particleEffect=theeffect,effectsDict=AllScene.particleDict)
  1054. pass
  1055. def closeParticlePanel(self):
  1056. self.particlePanel = None
  1057. return
  1058. def openInputPanel(self):
  1059. if self.controllerPanel==None:
  1060. list = AllScene.getAllObjNameAsList()
  1061. type, dataList = AllScene.getControlSetting()
  1062. self.controllerPanel = controllerWindow(listOfObj = list, controlType = type, dataList = dataList)
  1063. pass
  1064. def closeInputPanel(self):
  1065. self.controllerPanel = None
  1066. return
  1067. def requestObjFromControlW(self, name):
  1068. ################################################################
  1069. # requestObjFromControlW(self, name)
  1070. # Call back function
  1071. # Each time when user selects a node from Control Panel,
  1072. # this function will be called.
  1073. # This function will get the actual nodePath from dataHolder and then
  1074. # set it back into controller panel
  1075. ################################################################
  1076. node = AllScene.getObjFromSceneByName(name)
  1077. if (self.controllerPanel) != None and (node!=None):
  1078. self.controllerPanel.setNodePathIn(node)
  1079. return
  1080. def setControlSet(self, controlType, dataList):
  1081. if controlType == 'Keyboard':
  1082. self.controlTarget = dataList[0]
  1083. self.keyboardMapDict.clear()
  1084. self.keyboardMapDict = dataList[1].copy()
  1085. self.keyboardSpeedDict.clear()
  1086. self.keyboardSpeedDict = dataList[2].copy()
  1087. return
  1088. def startControl(self, controlType, dataList):
  1089. if not self.enableControl:
  1090. self.enableControl = True
  1091. else:
  1092. # Stop the current control setting first
  1093. # Also this will make sure we won't catch wrong keyboard message
  1094. self.stopControl(controlType)
  1095. self.enableControl = True
  1096. self.setControlSet(controlType, dataList)
  1097. self.lastContorlTimer = globalClock.getFrameTime()
  1098. if controlType == 'Keyboard':
  1099. self.controlType = 'Keyboard'
  1100. self.keyControlEventDict = {}
  1101. self.transNodeKeyboard = self.controlTarget.attachNewNode('transformNode')
  1102. self.transNodeKeyboard.hide()
  1103. for index in self.keyboardMapDict:
  1104. self.keyControlEventDict[index] = 0
  1105. self.accept(self.keyboardMapDict[index], lambda a = index:self.keyboardPushed(a))
  1106. self.accept(self.keyboardMapDict[index]+'-up', lambda a = index:self.keyboardReleased(a))
  1107. return
  1108. def stopControl(self, controlType):
  1109. if not self.enableControl:
  1110. return
  1111. if controlType == 'Keyboard':
  1112. self.enableControl = False
  1113. for index in self.keyboardMapDict:
  1114. self.ignore(self.keyboardMapDict[index])
  1115. self.ignore(self.keyboardMapDict[index]+'-up')
  1116. taskMgr.remove("KeyboardControlTask")
  1117. self.transNodeKeyboard.removeNode()
  1118. return
  1119. def keyboardPushed(self, key):
  1120. self.keyControlEventDict[key] = 1
  1121. if not taskMgr.hasTaskNamed("KeyboardControlTask"):
  1122. self.keyboardLastTimer = globalClock.getFrameTime()
  1123. taskMgr.add(self.keyboardControlTask, "KeyboardControlTask")
  1124. return
  1125. def keyboardReleased(self, key):
  1126. self.keyControlEventDict[key] = 0
  1127. for index in self.keyControlEventDict:
  1128. if self.keyControlEventDict[index] == 1:
  1129. return
  1130. if taskMgr.hasTaskNamed("KeyboardControlTask"):
  1131. taskMgr.remove("KeyboardControlTask")
  1132. return
  1133. def keyboardControlTask(self, task):
  1134. newTimer = globalClock.getFrameTime()
  1135. delta = newTimer - self.keyboardLastTimer
  1136. self.keyboardLastTimer = newTimer
  1137. pos = self.controlTarget.getPos()
  1138. hpr = self.controlTarget.getHpr()
  1139. scale = self.controlTarget.getScale()
  1140. self.transNodeKeyboard.setPosHpr((self.keyControlEventDict['KeyRight']*self.keyboardSpeedDict['SpeedRight']-self.keyControlEventDict['KeyLeft']*self.keyboardSpeedDict['SpeedLeft'])*delta,
  1141. (self.keyControlEventDict['KeyForward']*self.keyboardSpeedDict['SpeedForward']-self.keyControlEventDict['KeyBackward']*self.keyboardSpeedDict['SpeedBackward'])*delta,
  1142. (self.keyControlEventDict['KeyUp']*self.keyboardSpeedDict['SpeedUp']-self.keyControlEventDict['KeyDown']*self.keyboardSpeedDict['SpeedDown'])*delta,
  1143. (self.keyControlEventDict['KeyTurnLeft']*self.keyboardSpeedDict['SpeedTurnLeft']-self.keyControlEventDict['KeyTurnRight']*self.keyboardSpeedDict['SpeedTurnRight'])*delta,
  1144. (self.keyControlEventDict['KeyTurnUp']*self.keyboardSpeedDict['SpeedTurnUp']-self.keyControlEventDict['KeyTurnDown']*self.keyboardSpeedDict['SpeedTurnDown'])*delta,
  1145. (self.keyControlEventDict['KeyRollLeft']*self.keyboardSpeedDict['SpeedRollLeft']-self.keyControlEventDict['KeyRollRight']*self.keyboardSpeedDict['SpeedRollRight'])*delta)
  1146. newPos = self.transNodeKeyboard.getPos(self.controlTarget.getParent())
  1147. newHpr = self.transNodeKeyboard.getHpr(self.controlTarget.getParent())
  1148. overAllScale = self.keyControlEventDict['KeyScaleUp']*self.keyboardSpeedDict['SpeedScaleUp']-self.keyControlEventDict['KeyScaleDown']*self.keyboardSpeedDict['SpeedScaleDown']
  1149. newScale = Point3(scale.getX() + (overAllScale + self.keyControlEventDict['KeyScaleXUp']*self.keyboardSpeedDict['SpeedScaleXUp'] - self.keyControlEventDict['KeyScaleXDown']*self.keyboardSpeedDict['SpeedScaleXDown'])*delta,
  1150. scale.getY() + (overAllScale + self.keyControlEventDict['KeyScaleYUp']*self.keyboardSpeedDict['SpeedScaleYUp'] - self.keyControlEventDict['KeyScaleYDown']*self.keyboardSpeedDict['SpeedScaleYDown'])*delta,
  1151. scale.getZ() + (overAllScale + self.keyControlEventDict['KeyScaleZUp']*self.keyboardSpeedDict['SpeedScaleZUp'] - self.keyControlEventDict['KeyScaleZDown']*self.keyboardSpeedDict['SpeedScaleZDown'])*delta
  1152. )
  1153. self.controlTarget.setPos(newPos.getX(), newPos.getY() , newPos.getZ())
  1154. self.controlTarget.setHpr(newHpr.getX(), newHpr.getY() , newHpr.getZ())
  1155. self.controlTarget.setScale(newScale.getX(),newScale.getY(),newScale.getZ())
  1156. self.transNodeKeyboard.setPosHpr(0,0,0,0,0,0)
  1157. return Task.cont
  1158. ## Misc
  1159. ##### This one get the event from SGE (Scene Graph Explorer) and Picking
  1160. def selectNode(self, nodePath=None, callBack = True):
  1161. ################################################################
  1162. # selectNode(self, nodePath=None, callBack = True)
  1163. # This will be called when user try to select nodes from the
  1164. # side window.
  1165. # It will also call seSession to select this node in order to keep data's consistency
  1166. ################################################################
  1167. if nodePath==None:
  1168. self.isSelect = False
  1169. self.nodeSelected =None
  1170. if taskMgr.hasTaskNamed('seMonitorSelectedNode'):
  1171. taskMgr.remove('seMonitorSelectedNode')
  1172. return
  1173. else:
  1174. self.isSelect = True
  1175. #if self.nodeSelected != None:
  1176. # self.nodeSelected.hideBounds()
  1177. self.nodeSelected = nodePath
  1178. #self.nodeSelected.showBounds()
  1179. self.menuEdit.entryconfig('Deselect', state=NORMAL)
  1180. self.menuEdit.entryconfig('Add Dummy', state=NORMAL)
  1181. self.menuEdit.entryconfig('Duplicate', state=NORMAL)
  1182. self.menuEdit.entryconfig('Remove', state=NORMAL)
  1183. self.menuEdit.entryconfig('Object Properties', state=NORMAL)
  1184. if callBack:
  1185. self.seSession.select(nodePath,fResetAncestry=1)
  1186. messenger.send('SGE_Update Explorer',[render])
  1187. if not taskMgr.hasTaskNamed('seMonitorSelectedNode'):
  1188. self.oPos = self.nodeSelected.getPos()
  1189. self.oHpr = self.nodeSelected.getHpr()
  1190. self.oScale = self.nodeSelected.getScale()
  1191. taskMgr.add(self.monitorSelectedNodeTask, 'seMonitorSelectedNode')
  1192. return
  1193. pass
  1194. def selectFromScene(self, nodePath=None, callBack=True):
  1195. ################################################################
  1196. # selectFromScene(self, nodePath=None, callBack = True)
  1197. # This will be called when user try to select nodes from the
  1198. # scene. (By picking)
  1199. # Actually this will be called by seSession
  1200. # The reason we make two selections is we don't want they call each other and never stop...
  1201. ################################################################
  1202. if nodePath==None:
  1203. self.isSelect = False
  1204. self.nodeSelected =None
  1205. if taskMgr.hasTaskNamed('seMonitorSelectedNode'):
  1206. taskMgr.remove('seMonitorSelectedNode')
  1207. return
  1208. else:
  1209. self.isSelect = True
  1210. #if self.nodeSelected != None:
  1211. # self.nodeSelected.hideBounds()
  1212. self.nodeSelected = nodePath
  1213. #self.nodeSelected.showBounds()
  1214. self.menuEdit.entryconfig('Deselect', state=NORMAL)
  1215. self.menuEdit.entryconfig('Add Dummy', state=NORMAL)
  1216. self.menuEdit.entryconfig('Duplicate', state=NORMAL)
  1217. self.menuEdit.entryconfig('Remove', state=NORMAL)
  1218. self.menuEdit.entryconfig('Object Properties', state=NORMAL)
  1219. self.sideWindow.SGE.selectNodePath(nodePath,callBack)
  1220. messenger.send('SGE_Update Explorer',[render])
  1221. if not taskMgr.hasTaskNamed('seMonitorSelectedNode'):
  1222. self.oPos = self.nodeSelected.getPos()
  1223. self.oHpr = self.nodeSelected.getHpr()
  1224. self.oScale = self.nodeSelected.getScale()
  1225. taskMgr.add(self.monitorSelectedNodeTask, 'seMonitorSelectedNode')
  1226. return
  1227. pass
  1228. def monitorSelectedNodeTask(self, task):
  1229. ################################################################
  1230. # monitorSelectedNodeTask(self, task)
  1231. # This is a function which will keep tracking
  1232. # the position, orientation and scale data of selected node and update the display on the screen.
  1233. # Alos, it will send out message to sychronize the data in the placer and property window.
  1234. ################################################################
  1235. if self.nodeSelected != None:
  1236. pos = self.nodeSelected.getPos()
  1237. hpr = self.nodeSelected.getHpr()
  1238. scale = self.nodeSelected.getScale()
  1239. if ((self.oPos != pos )or(self.oScale != scale)or(self.oHpr != hpr)):
  1240. messenger.send('forPorpertyWindow'+self.nodeSelected.getName(),[pos, hpr, scale])
  1241. messenger.send('placerUpdate')
  1242. self.oPos = pos
  1243. self.oScale = scale
  1244. self.oHpr = hpr
  1245. self.posLabel['text'] = "Position : X: %2.2f Y: %2.2f Z: %2.2f"%(pos.getX(), pos.getY(),pos.getZ())
  1246. self.hprLabel['text'] = "Orientation: H: %2.2f P: %2.2f R: %2.2f"%(hpr.getX(), hpr.getY(),hpr.getZ())
  1247. self.scaleLabel['text'] = "Scale : X: %2.2f Y: %2.2f Z: %2.2f"%(scale.getX(), scale.getY(),scale.getZ())
  1248. return Task.cont
  1249. def deselectFromScene(self):
  1250. ################################################################
  1251. # deselectFromScene(self)
  1252. # This function will do nothing but call other function
  1253. # to delete selected node...
  1254. #
  1255. # Ok... this is really redundancy...
  1256. #
  1257. ################################################################
  1258. self.deSelectNode(self.nodeSelected)
  1259. messenger.send('SGE_Update Explorer',[render])
  1260. ##### Take care the even quest from Side Window
  1261. def lightToggle(self):
  1262. ################################################################
  1263. # lightToggle(self)
  1264. # This function will do nothing but call other function
  1265. # to toggle the light...
  1266. ################################################################
  1267. self.makeDirty()
  1268. AllScene.toggleLight()
  1269. return
  1270. def sideWindowClose(self,worldColor,lightEnable,ParticleEnable, basedriveEnable,collision,
  1271. backface, texture, wireframe, grid, widgetVis, enableAutoCamera):
  1272. ################################################################
  1273. # sideWindowClose(self,worldColor,lightEnable,ParticleEnable, basedriveEnable,collision,
  1274. # backface, texture, wireframe, grid, widgetVis, enableAutoCamera):
  1275. # This function will be called when user close the side window.
  1276. # Here we will restore all parameters about world setting back in the sceneEditor.
  1277. # So, when next time people recall the side window, it will still keep the same world setting.
  1278. ################################################################
  1279. if self.sideWindowCount==1:
  1280. self.worldColor = worldColor
  1281. self.lightEnable = lightEnable
  1282. self.ParticleEnable = ParticleEnable
  1283. self.basedriveEnable = basedriveEnable
  1284. self.collision = collision
  1285. self.backface = backface
  1286. self.texture = texture
  1287. self.wireframe = wireframe
  1288. self.grid = grid
  1289. self.enableAutoCamera = enableAutoCamera
  1290. self.widgetVis = widgetVis
  1291. self.sideWindowCount=0
  1292. self.sideWindow = None
  1293. self.menuPanel.entryconfig('Side Window', state=NORMAL)
  1294. return
  1295. ## Process message from Duplication Window
  1296. def duplicationObj(self, nodePath, pos, hpr, scale, num):
  1297. ################################################################
  1298. # duplicationObj(self, nodePath, pos, hpr, scale, num)
  1299. # This function will do nothing but call other function
  1300. # to duplicate selected node...
  1301. #
  1302. # Ok... this is really redundancy...
  1303. #
  1304. ################################################################
  1305. AllScene.duplicateObj(nodePath, pos, hpr, scale, num)
  1306. return
  1307. ## Process message from Animation Panel
  1308. def animationLoader(self, nodePath, Dic):
  1309. name = nodePath.getName()
  1310. AllScene.loadAnimation(name, Dic)
  1311. return
  1312. def animationRemove(self, nodePath, name):
  1313. AllScene.removeAnimation(nodePath.getName(),name)
  1314. return
  1315. def animPanelClose(self, name):
  1316. if self.animPanel.has_key(name):
  1317. del self.animPanel[name]
  1318. return
  1319. ### Blend Animation Panel
  1320. def openBlendAnimPanel(self, nodePath=None):
  1321. ################################################################
  1322. # openBlendAnimPanel(self, nodePath=None)
  1323. # This function will get the user defined blending animation data from dataHolder.
  1324. # And then open a blendAnimPanel by passing those data in.
  1325. ################################################################
  1326. name = nodePath.getName()
  1327. if AllScene.isActor(name):
  1328. if self.animBlendPanel.has_key(name):
  1329. print '---- You already have an Blend Animation Panel for this Actor!'
  1330. return
  1331. else:
  1332. Actor = AllScene.getActor(name)
  1333. Dict = AllScene.getBlendAnimAsDict(name)
  1334. self.animBlendPanel[name] = BlendAnimPanel(aNode=Actor, blendDict=Dict)
  1335. pass
  1336. return
  1337. def animBlendPanelSave(self, actorName, blendName, animNameA, animNameB, effect):
  1338. ################################################################
  1339. # animBlendPanelSave(self, actorName, blendName, animNameA, animNameB, effect)
  1340. # This function will call dataHolder to save the blended animation.
  1341. # Then, it will reset the newest blended animation list back to animBlendPanel
  1342. ################################################################
  1343. dict = AllScene.saveBlendAnim(actorName, blendName, animNameA, animNameB, effect)
  1344. self.animBlendPanel[actorName].setBlendAnimList(dict)
  1345. return
  1346. def animBlendPanelRemove(self, actorName, blendName):
  1347. ################################################################
  1348. # animBlendPanelRemove(self, actorName, blendName)
  1349. # This function will call dataHolder to remove the blended animation.
  1350. # Then, it will reset the newest blended animation list back to animBlendPanel
  1351. ################################################################
  1352. dict = AllScene.removeBlendAnim(actorName, blendName)
  1353. self.animBlendPanel[actorName].setBlendAnimList(dict, True)
  1354. return
  1355. def animBlendPanelRename(self, actorName, nName, oName, animNameA, animNameB, effect):
  1356. ################################################################
  1357. # animBlendPanelRename(self, actorName, nName, oName, animNameA, animNameB, effect)
  1358. # This function will call dataHolder to rename the blended animation.
  1359. # Then, it will reset the newest blended animation list back to animBlendPanel
  1360. ################################################################
  1361. dict = AllScene.renameBlendAnim(actorName, nName, oName, animNameA, animNameB, effect)
  1362. self.animBlendPanel[actorName].setBlendAnimList(dict)
  1363. return
  1364. def animBlendPanelClose(self, name):
  1365. ################################################################
  1366. # animBlendPanelClose(self, name)
  1367. # This function will be called when Blend panel has been closed.
  1368. # Here we will reset the reference dictionary so it can be open again.
  1369. ################################################################
  1370. if self.animBlendPanel.has_key(name):
  1371. del self.animBlendPanel[name]
  1372. return
  1373. ## Process message from SEditor object
  1374. def toggleWidgetVis(self):
  1375. ################################################################
  1376. # toggleWidgetVis(self)
  1377. # This function will be called when user use the hot-key to change the
  1378. # world setting. (From seSession)
  1379. # In this function we will restore the change and let side window know
  1380. # the hot-key ahs been pushed.
  1381. ################################################################
  1382. if self.sideWindow != None:
  1383. self.sideWindow.toggleWidgetVisFromMainW()
  1384. else:
  1385. self.widgetVis = (self.widgetVis+1)%2
  1386. def toggleBackface(self):
  1387. ################################################################
  1388. # toggleBackface(self)
  1389. # This function will be called when user use the hot-key to change the
  1390. # world setting. (From seSession)
  1391. # In this function we will restore the change and let side window know
  1392. # the hot-key ahs been pushed.
  1393. ################################################################
  1394. if self.sideWindow != None:
  1395. self.sideWindow.toggleBackfaceFromMainW()
  1396. else:
  1397. self.backface = (self.backface+1)%2
  1398. def toggleTexture(self):
  1399. ################################################################
  1400. # toggleTexture(self)
  1401. # This function will be called when user use the hot-key to change the
  1402. # world setting. (From seSession)
  1403. # In this function we will restore the change and let side window know
  1404. # the hot-key ahs been pushed.
  1405. ################################################################
  1406. if self.sideWindow != None:
  1407. self.sideWindow.toggleTextureFromMainW()
  1408. else:
  1409. self.texture = (self.texture+1)%2
  1410. def toggleWireframe(self):
  1411. ################################################################
  1412. # toggleWireframe(self)
  1413. # This function will be called when user use the hot-key to change the
  1414. # world setting. (From seSession)
  1415. # In this function we will restore the change and let side window know
  1416. # the hot-key ahs been pushed.
  1417. ################################################################
  1418. if self.sideWindow != None:
  1419. self.sideWindow.toggleWireframeFromMainW()
  1420. else:
  1421. self.wireframe = (self.wireframe+1)%2
  1422. def openAlignPanel(self, nodePath=None):
  1423. name = nodePath.getName()
  1424. if not self.alignPanelDict.has_key(name):
  1425. list = AllScene.getAllObjNameAsList()
  1426. if name in list:
  1427. list.remove(name)
  1428. else:
  1429. return
  1430. self.alignPanelDict[name] = AlignTool(nodePath = nodePath, list = list)
  1431. return
  1432. def closeAlignPanel(self, name=None):
  1433. if self.alignPanelDict.has_key(name):
  1434. del self.alignPanelDict[name]
  1435. def alignObject(self, nodePath, name, list):
  1436. target = AllScene.getObjFromSceneByName(name)
  1437. pos = target.getPos()
  1438. hpr = target.getHpr()
  1439. scale = target.getScale()
  1440. if list[0]: # Align X
  1441. nodePath.setX(pos.getX())
  1442. if list[1]: # Align Y
  1443. nodePath.setY(pos.getY())
  1444. if list[2]: # Align Z
  1445. nodePath.setZ(pos.getZ())
  1446. if list[3]: # Align H
  1447. nodePath.setH(hpr.getX())
  1448. if list[4]: # Align P
  1449. nodePath.setP(hpr.getY())
  1450. if list[5]: # Align R
  1451. nodePath.setR(hpr.getZ())
  1452. if list[6]: # Scale X
  1453. nodePath.setSx(scale.getX())
  1454. if list[7]: # Scale Y
  1455. nodePath.setSy(scale.getY())
  1456. if list[8]: # Scale Z
  1457. nodePath.setSz(scale.getZ())
  1458. return
  1459. ### Event from Motion Path Panel
  1460. def requestCurveList(self, nodePath,name):
  1461. curveList = AllScene.getCurveList(nodePath)
  1462. messenger.send('curveListFor'+name, [curveList])
  1463. ## Steal from DirectSession...
  1464. def flash(self, nodePath = 'None Given'):
  1465. """ Highlight an object by setting it red for a few seconds """
  1466. # Clean up any existing task
  1467. taskMgr.remove('flashNodePath')
  1468. # Spawn new task if appropriate
  1469. if nodePath == 'None Given':
  1470. # If nothing specified, try selected node path
  1471. nodePath = self.selected.last
  1472. if nodePath:
  1473. if nodePath.hasColor():
  1474. doneColor = nodePath.getColor()
  1475. flashColor = VBase4(1) - doneColor
  1476. flashColor.setW(1)
  1477. else:
  1478. doneColor = None
  1479. flashColor = VBase4(1,0,0,1)
  1480. # Temporarily set node path color
  1481. nodePath.setColor(flashColor)
  1482. # Clean up color in a few seconds
  1483. t = taskMgr.doMethodLater(1.5,
  1484. # This is just a dummy task
  1485. self.flashDummy,
  1486. 'flashNodePath')
  1487. t.nodePath = nodePath
  1488. t.doneColor = doneColor
  1489. # This really does all the work
  1490. t.uponDeath = self.flashDone
  1491. def flashDummy(self, state):
  1492. # Real work is done in upon death function
  1493. return Task.done
  1494. def flashDone(self,state):
  1495. # Return node Path to original state
  1496. if state.nodePath.isEmpty():
  1497. # Node path doesn't exist anymore, bail
  1498. return
  1499. if state.doneColor:
  1500. state.nodePath.setColor(state.doneColor)
  1501. else:
  1502. state.nodePath.clearColor()
  1503. editor = myLevelEditor(parent = tkroot)
  1504. run()