lightingPanel.py 21 KB

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