lightingPanel.py 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. #################################################################
  2. # lightingPanel.py
  3. # Written by Yi-Hong Lin, [email protected], 2004
  4. #################################################################
  5. # Import Tkinter, Pmw, and the floater code from this directory tree.
  6. from direct.tkwidgets.AppShell import AppShell
  7. from seColorEntry import *
  8. from direct.tkwidgets.VectorWidgets import Vector3Entry
  9. from direct.tkwidgets.Slider import Slider
  10. from Tkinter import Frame, Button, Menubutton, Menu
  11. import string, math, types, Pmw, Tkinter
  12. class lightingPanel(AppShell):
  13. #################################################################
  14. # lightingPanel(AppShell)
  15. # This will create a window to let user
  16. # create any kinds of lighting into the scene
  17. #################################################################
  18. # Override class variables
  19. appname = 'Lighting Panel'
  20. frameWidth = 400
  21. frameHeight = 400
  22. currentLight = None
  23. def __init__(self, lightList, parent = None, **kw):
  24. self.lightList = lightList
  25. self.lightColor = [0.3*255,0.3*255,0.3*255]
  26. self.type = ''
  27. INITOPT = Pmw.INITOPT
  28. optiondefs = (
  29. ('title', self.appname, None),
  30. )
  31. self.defineoptions(kw, optiondefs)
  32. # Initialize the superclass
  33. AppShell.__init__(self)
  34. # Execute option callbacks
  35. self.initialiseoptions(lightingPanel)
  36. self.parent.resizable(False,False) ## Disable the ability to resize for this Window.
  37. def createInterface(self):
  38. # Handle to the toplevels interior
  39. interior = self.interior()
  40. menuBar = self.menuBar
  41. self.menuBar.destroy()
  42. # Create a frame to hold all stuff
  43. mainFrame = Frame(interior)
  44. self.listZone = Pmw.Group(mainFrame,tag_pyclass = None)
  45. self.listZone.pack(expand=0, fill=Tkinter.X,padx=3,pady=3)
  46. listFrame = self.listZone.interior()
  47. self.lightEntry = self.createcomponent(
  48. 'Lights List', (), None,
  49. Pmw.ComboBox, (listFrame,),label_text='Light :',
  50. labelpos = Tkinter.W, entry_width = 25, selectioncommand = self.selectLight,
  51. scrolledlist_items = self.lightList)
  52. self.lightEntry.pack(side=Tkinter.LEFT)
  53. self.renameButton = self.createcomponent(
  54. 'Rename Light', (), None,
  55. Button, (listFrame,),
  56. text = ' Rename ',
  57. command = self.renameLight)
  58. self.renameButton.pack(side=Tkinter.LEFT)
  59. self.addLighZone = Pmw.Group(listFrame,tag_pyclass = None)
  60. self.addLighZone.pack(side=Tkinter.LEFT)
  61. insideFrame = self.addLighZone.interior()
  62. self.lightsButton = Menubutton(insideFrame, text = 'Add light',borderwidth = 3,
  63. activebackground = '#909090')
  64. lightsMenu = Menu(self.lightsButton)
  65. lightsMenu.add_command(label = 'Add Ambient Light',
  66. command = self.addAmbient)
  67. lightsMenu.add_command(label = 'Add Directional Light',
  68. command = self.addDirectional)
  69. lightsMenu.add_command(label = 'Add Point Light',
  70. command = self.addPoint)
  71. lightsMenu.add_command(label = 'Add Spotlight',
  72. command = self.addSpot)
  73. self.lightsButton.pack(expand=0)
  74. self.lightsButton['menu'] = lightsMenu
  75. self.deleteButton = self.createcomponent(
  76. 'delete Light', (), None,
  77. Button, (listFrame,),
  78. text = ' Delete ',
  79. command = self.deleteLight)
  80. self.deleteButton.pack(side=Tkinter.LEFT)
  81. self.lightColor = seColorEntry(
  82. mainFrame, text = 'Light Color', value=self.lightColor)
  83. self.lightColor['command'] = self.setLightingColorVec
  84. self.lightColor['resetValue'] = [0.3*255,0.3*255,0.3*255,0]
  85. self.lightColor.pack(fill=Tkinter.X,expand=0)
  86. self.bind(self.lightColor, 'Set light color')
  87. # Notebook pages for light specific controls
  88. self.lightNotebook = Pmw.NoteBook(mainFrame, tabpos = None,
  89. borderwidth = 0)
  90. ambientPage = self.lightNotebook.add('Ambient')
  91. directionalPage = self.lightNotebook.add('Directional')
  92. pointPage = self.lightNotebook.add('Point')
  93. spotPage = self.lightNotebook.add('Spot')
  94. # Put this here so it isn't called right away
  95. self.lightNotebook['raisecommand'] = self.updateLightInfo
  96. # Directional light controls
  97. self.dSpecularColor = seColorEntry(
  98. directionalPage, text = 'Specular Color')
  99. self.dSpecularColor['command'] = self.setSpecularColor
  100. self.dSpecularColor.pack(fill = Tkinter.X, expand = 0)
  101. self.bind(self.dSpecularColor,
  102. 'Set directional light specular color')
  103. self.dPosition = Vector3Entry(
  104. directionalPage, text = 'Position')
  105. self.dPosition['command'] = self.setPosition
  106. self.dPosition['resetValue'] = [0,0,0,0]
  107. self.dPosition.pack(fill = Tkinter.X, expand = 0)
  108. self.bind(self.dPosition, 'Set directional light position')
  109. self.dOrientation = Vector3Entry(
  110. directionalPage, text = 'Orientation')
  111. self.dOrientation['command'] = self.setOrientation
  112. self.dOrientation['resetValue'] = [0,0,0,0]
  113. self.dOrientation.pack(fill = Tkinter.X, expand = 0)
  114. self.bind(self.dOrientation, 'Set directional light orientation')
  115. # Point light controls
  116. self.pSpecularColor = seColorEntry(
  117. pointPage, text = 'Specular Color')
  118. self.pSpecularColor['command'] = self.setSpecularColor
  119. self.pSpecularColor.pack(fill = Tkinter.X, expand = 0)
  120. self.bind(self.pSpecularColor,
  121. 'Set point light specular color')
  122. self.pPosition = Vector3Entry(
  123. pointPage, text = 'Position')
  124. self.pPosition['command'] = self.setPosition
  125. self.pPosition['resetValue'] = [0,0,0,0]
  126. self.pPosition.pack(fill = Tkinter.X, expand = 0)
  127. self.bind(self.pPosition, 'Set point light position')
  128. self.pConstantAttenuation = Slider(
  129. pointPage,
  130. text = 'Constant Attenuation',
  131. max = 1.0,
  132. resolution = 0.01,
  133. value = 1.0)
  134. self.pConstantAttenuation['command'] = self.setConstantAttenuation
  135. self.pConstantAttenuation.pack(fill = Tkinter.X, expand = 0)
  136. self.bind(self.pConstantAttenuation,
  137. 'Set point light constant attenuation')
  138. self.pLinearAttenuation = Slider(
  139. pointPage,
  140. text = 'Linear Attenuation',
  141. max = 1.0,
  142. resolution = 0.01,
  143. value = 0.0)
  144. self.pLinearAttenuation['command'] = self.setLinearAttenuation
  145. self.pLinearAttenuation.pack(fill = Tkinter.X, expand = 0)
  146. self.bind(self.pLinearAttenuation,
  147. 'Set point light linear attenuation')
  148. self.pQuadraticAttenuation = Slider(
  149. pointPage,
  150. text = 'Quadratic Attenuation',
  151. max = 1.0,
  152. resolution = 0.01,
  153. value = 0.0)
  154. self.pQuadraticAttenuation['command'] = self.setQuadraticAttenuation
  155. self.pQuadraticAttenuation.pack(fill = Tkinter.X, expand = 0)
  156. self.bind(self.pQuadraticAttenuation,
  157. 'Set point light quadratic attenuation')
  158. # Spot light controls
  159. self.sSpecularColor = seColorEntry(
  160. spotPage, text = 'Specular Color')
  161. self.sSpecularColor['command'] = self.setSpecularColor
  162. self.sSpecularColor.pack(fill = Tkinter.X, expand = 0)
  163. self.bind(self.sSpecularColor,
  164. 'Set spot light specular color')
  165. self.sConstantAttenuation = Slider(
  166. spotPage,
  167. text = 'Constant Attenuation',
  168. max = 1.0,
  169. resolution = 0.01,
  170. value = 1.0)
  171. self.sConstantAttenuation['command'] = self.setConstantAttenuation
  172. self.sConstantAttenuation.pack(fill = Tkinter.X, expand = 0)
  173. self.bind(self.sConstantAttenuation,
  174. 'Set spot light constant attenuation')
  175. self.sLinearAttenuation = Slider(
  176. spotPage,
  177. text = 'Linear Attenuation',
  178. max = 1.0,
  179. resolution = 0.01,
  180. value = 0.0)
  181. self.sLinearAttenuation['command'] = self.setLinearAttenuation
  182. self.sLinearAttenuation.pack(fill = Tkinter.X, expand = 0)
  183. self.bind(self.sLinearAttenuation,
  184. 'Set spot light linear attenuation')
  185. self.sQuadraticAttenuation = Slider(
  186. spotPage,
  187. text = 'Quadratic Attenuation',
  188. max = 1.0,
  189. resolution = 0.01,
  190. value = 0.0)
  191. self.sQuadraticAttenuation['command'] = self.setQuadraticAttenuation
  192. self.sQuadraticAttenuation.pack(fill = Tkinter.X, expand = 0)
  193. self.bind(self.sQuadraticAttenuation,
  194. 'Set spot light quadratic attenuation')
  195. self.sExponent = Slider(
  196. spotPage,
  197. text = 'Exponent',
  198. max = 1.0,
  199. resolution = 0.01,
  200. value = 0.0)
  201. self.sExponent['command'] = self.setExponent
  202. self.sExponent.pack(fill = Tkinter.X, expand = 0)
  203. self.bind(self.sExponent,
  204. 'Set spot light exponent')
  205. # MRM: Add frustum controls
  206. self.lightNotebook.setnaturalsize()
  207. self.lightNotebook.pack(expand = 1, fill = Tkinter.BOTH)
  208. mainFrame.pack(expand=1, fill = Tkinter.BOTH)
  209. def onDestroy(self, event):
  210. messenger.send('LP_close')
  211. '''
  212. If you have open any thing, please rewrite here!
  213. '''
  214. pass
  215. def renameLight(self):
  216. #################################################################
  217. # renameLight(self)
  218. # Call Back function
  219. # This function will be called when user push
  220. # the "Rename" button on the panel.
  221. #
  222. # Then, this function will collect data and send out them with a message
  223. # "LP_rename"
  224. # Which will be caught by sceneEditor and pass to dataHolder to
  225. # complete the renaming.
  226. #
  227. #################################################################
  228. oName = self.currentLight
  229. nName = self.lightEntry.get()
  230. messenger.send('LP_rename',[oName,nName])
  231. return
  232. def deleteLight(self):
  233. #################################################################
  234. # deleteLight(self)
  235. # Call Back Function.
  236. # This function will be called when user click on
  237. # the "Delete" button on the panel.
  238. #
  239. # Then, this function will send out a message with current seleted light
  240. # "LP_removeLight"
  241. # Which will be caught by sceneEditor and pass to dataHolder to
  242. # complete the delete process.
  243. #
  244. #################################################################
  245. messenger.send('LP_removeLight',[self.currentLight])
  246. return
  247. def updateList(self, list, node=None):
  248. #################################################################
  249. # updataList(self, list, node = None)
  250. # This function will take a list object which contains names of lights in the scene.
  251. # Also, if user has put node as a parameter,
  252. # this function will automatically select that node as the current working target.
  253. #################################################################
  254. self.lightList = list
  255. self.lightEntry.setlist(list)
  256. if node!=None:
  257. self.lightEntry.selectitem(index=node.getName(), setentry=True )
  258. self.updateDisplay(node)
  259. elif len(list)>0:
  260. self.lightEntry.selectitem(index=0, setentry=True )
  261. self.selectLight(list[0])
  262. else:
  263. self.lightEntry.clear()
  264. return
  265. def selectLight(self, lightName):
  266. #################################################################
  267. # selectLight(self, lightName)
  268. # This function will be called each time when
  269. # user select a light from the list on the panel.
  270. # Then, this function will send out the message,
  271. # 'LP_selectLight' to sceneEditorand get the current light information from dataHolder.
  272. #################################################################
  273. if lightName in self.lightList:
  274. messenger.send('LP_selectLight',[lightName])
  275. return
  276. def updateDisplay(self, lightNode):
  277. #################################################################
  278. # updateDisplay(self, lightNode)
  279. # This function will update the information showing on the panel.
  280. # For example, give a lightNode which is a Point Light.
  281. # This function will switch the page to specify the type.
  282. # Also, new node is the same type with the previous one,
  283. # then this is function won't do the page switching,
  284. # but will call other function to refresh the data to target node.
  285. #################################################################
  286. self.currentLight = lightNode
  287. if self.currentLight != None:
  288. color = lightNode.getLightColor()
  289. self.lightColor.set([255*color.getX(),255*color.getY(),255*color.getZ()])
  290. oldType = self.type
  291. self.type = lightNode.getType()
  292. else:
  293. self.lightColor.set([255*0.3,255*0.3,255*0.3])
  294. oldType = self.type
  295. self.type = 'ambient'
  296. if self.type=='ambient':
  297. self.lightNotebook.selectpage('Ambient')
  298. elif self.type =='directional':
  299. self.lightNotebook.selectpage('Directional')
  300. elif self.type =='point':
  301. self.lightNotebook.selectpage('Point')
  302. elif self.type =='spot':
  303. self.lightNotebook.selectpage('Spot')
  304. if oldType == self.type:
  305. # The same type with previous one, call updateLightInfo to refresh the values.
  306. self.updateLightInfo()
  307. return
  308. def updateLightInfo(self, page=None):
  309. #################################################################
  310. # updateLightInfo(self, page=None)
  311. # This function will refresh the data we user have done any selection.
  312. #################################################################
  313. if self.currentLight != None:
  314. light = self.currentLight.getLight()
  315. if self.type != 'ambient':
  316. specColor = light.getSpecularColor()
  317. if self.type =='directional':
  318. point = self.currentLight.getPosition()
  319. dir = self.currentLight.getOrientation()
  320. self.dSpecularColor.set([specColor.getX()*255,specColor.getY()*255,specColor.getZ()*255])
  321. self.dPosition.set([point.getX(),point.getY(),point.getZ()])
  322. self.dOrientation.set([dir.getX(),dir.getY(),dir.getZ()])
  323. elif self.type =='point':
  324. point = self.currentLight.getPosition()
  325. attenuation = light.getAttenuation()
  326. self.pSpecularColor.set([specColor.getX()*255,specColor.getY()*255,specColor.getZ()*255])
  327. self.pPosition.set([point.getX(),point.getY(),point.getZ()])
  328. self.pConstantAttenuation.set(attenuation.getX())
  329. self.pLinearAttenuation.set(attenuation.getY())
  330. self.pQuadraticAttenuation.set(attenuation.getZ())
  331. elif self.type =='spot':
  332. attenuation = light.getAttenuation()
  333. expo = light.getExponent()
  334. self.sSpecularColor.set([specColor.getX()*255,specColor.getY()*255,specColor.getZ()*255])
  335. self.sConstantAttenuation.set(attenuation.getX())
  336. self.sLinearAttenuation.set(attenuation.getY())
  337. self.sQuadraticAttenuation.set(attenuation.getZ())
  338. self.sExponent.set(expo)
  339. return
  340. def addAmbient(self):
  341. #################################################################
  342. # addAmbient(self)
  343. # This function will send out a message to
  344. # ask dataHolder to create a default ambient light
  345. #################################################################
  346. messenger.send('LP_addLight',['ambient'])
  347. return
  348. def addDirectional(self):
  349. #################################################################
  350. # addDirectional(self)
  351. # This function will send out a message to
  352. # sk dataHolder to create a default Directional light
  353. #################################################################
  354. messenger.send('LP_addLight',['directional'])
  355. return
  356. def addPoint(self):
  357. #################################################################
  358. # addPoint(self)
  359. # This function will send out a message to
  360. # ask dataHolder to create a default Point light
  361. #################################################################
  362. messenger.send('LP_addLight',['point'])
  363. return
  364. def addSpot(self):
  365. #################################################################
  366. # addSpot(self)
  367. # This function will send out a message to
  368. # ask dataHolder to create a default Spot light
  369. #################################################################
  370. messenger.send('LP_addLight',['spot'])
  371. return
  372. def setLightingColorVec(self,color):
  373. #################################################################
  374. # setLightingColorVec(self,color)
  375. # Call Back function. This will be called
  376. # when user try to change the color of light.
  377. #################################################################
  378. if self.currentLight==None:
  379. return
  380. self.currentLight.setColor(VBase4((color[0]/255),(color[1]/255),(color[2]/255),1))
  381. return
  382. def setSpecularColor(self,color):
  383. #################################################################
  384. # setSpecularColor(self,color)
  385. # Call Back function. This will be called
  386. # when user try to change the Specular color of light.
  387. #################################################################
  388. if self.currentLight==None:
  389. return
  390. self.currentLight.setSpecColor(VBase4((color[0]/255),(color[1]/255),(color[2]/255),1))
  391. return
  392. def setPosition(self,position):
  393. #################################################################
  394. # setPosition(self,position)
  395. # Call Back function. This will be called
  396. # when user try to change the position of light.
  397. #################################################################
  398. if self.currentLight==None:
  399. return
  400. self.currentLight.setPosition(Point3(position[0],position[1],position[2]))
  401. return
  402. def setOrientation(self, orient):
  403. #################################################################
  404. # setOrientation(self, orient)
  405. # Call Back function. This will be called
  406. # when user try to change the orientation of light.
  407. #################################################################
  408. if self.currentLight==None:
  409. return
  410. self.currentLight.setOrientation(Vec3(orient[0],orient[1],orient[2]))
  411. return
  412. def setConstantAttenuation(self, value):
  413. #################################################################
  414. # setConstantAttenuation(self, value)
  415. # Call Back function. This will be called
  416. # when user try to change the Constant Attenuation of light.
  417. #################################################################
  418. self.currentLight.setConstantAttenuation(value)
  419. return
  420. def setLinearAttenuation(self, value):
  421. #################################################################
  422. # setLinearAttenuation(self, value)
  423. # Call Back function. This will be called
  424. # when user try to change the Linear Attenuation of light.
  425. #################################################################
  426. self.currentLight.setLinearAttenuation(value)
  427. return
  428. def setQuadraticAttenuation(self, value):
  429. #################################################################
  430. # setQuadraticAttenuation(self, value)
  431. # Call Back function. This will be called
  432. # when user try to change the Quadratic Attenuation of light.
  433. #################################################################
  434. self.currentLight.setQuadraticAttenuation(value)
  435. return
  436. def setExponent(self, value):
  437. #################################################################
  438. # setExponent(self, value)
  439. # Call Back function. This will be called
  440. # when user try to change Exponent value of light.
  441. #################################################################
  442. self.currentLight.setExponent(value)
  443. return