################################################################# # lightingPanel.py # Written by Yi-Hong Lin, yihhongl@andrew.cmu.edu, 2004 ################################################################# # Import Tkinter, Pmw, and the floater code from this directory tree. from direct.tkwidgets.AppShell import AppShell from seColorEntry import * from direct.tkwidgets.VectorWidgets import Vector3Entry from direct.tkwidgets.Slider import Slider from Tkinter import Frame, Button, Menubutton, Menu import string, math, types, Pmw, Tkinter from pandac.PandaModules import * class lightingPanel(AppShell): ################################################################# # lightingPanel(AppShell) # This will create a window to let user # create any kinds of lighting into the scene ################################################################# # Override class variables appname = 'Lighting Panel' frameWidth = 400 frameHeight = 400 currentLight = None def __init__(self, lightList, parent = None, **kw): self.lightList = lightList self.lightColor = [0.3*255,0.3*255,0.3*255] self.type = '' INITOPT = Pmw.INITOPT optiondefs = ( ('title', self.appname, None), ) self.defineoptions(kw, optiondefs) # Initialize the superclass AppShell.__init__(self) # Execute option callbacks self.initialiseoptions(lightingPanel) self.parent.resizable(False,False) ## Disable the ability to resize for this Window. def createInterface(self): # Handle to the toplevels interior interior = self.interior() menuBar = self.menuBar self.menuBar.destroy() # Create a frame to hold all stuff mainFrame = Frame(interior) self.listZone = Pmw.Group(mainFrame,tag_pyclass = None) self.listZone.pack(expand=0, fill=Tkinter.X,padx=3,pady=3) listFrame = self.listZone.interior() self.lightEntry = self.createcomponent( 'Lights List', (), None, Pmw.ComboBox, (listFrame,),label_text='Light :', labelpos = Tkinter.W, entry_width = 25, selectioncommand = self.selectLight, scrolledlist_items = self.lightList) self.lightEntry.pack(side=Tkinter.LEFT) self.renameButton = self.createcomponent( 'Rename Light', (), None, Button, (listFrame,), text = ' Rename ', command = self.renameLight) self.renameButton.pack(side=Tkinter.LEFT) self.addLighZone = Pmw.Group(listFrame,tag_pyclass = None) self.addLighZone.pack(side=Tkinter.LEFT) insideFrame = self.addLighZone.interior() self.lightsButton = Menubutton(insideFrame, text = 'Add light',borderwidth = 3, activebackground = '#909090') lightsMenu = Menu(self.lightsButton) lightsMenu.add_command(label = 'Add Ambient Light', command = self.addAmbient) lightsMenu.add_command(label = 'Add Directional Light', command = self.addDirectional) lightsMenu.add_command(label = 'Add Point Light', command = self.addPoint) lightsMenu.add_command(label = 'Add Spotlight', command = self.addSpot) self.lightsButton.pack(expand=0) self.lightsButton['menu'] = lightsMenu self.deleteButton = self.createcomponent( 'delete Light', (), None, Button, (listFrame,), text = ' Delete ', command = self.deleteLight) self.deleteButton.pack(side=Tkinter.LEFT) self.lightColor = seColorEntry( mainFrame, text = 'Light Color', value=self.lightColor) self.lightColor['command'] = self.setLightingColorVec self.lightColor['resetValue'] = [0.3*255,0.3*255,0.3*255,0] self.lightColor.pack(fill=Tkinter.X,expand=0) self.bind(self.lightColor, 'Set light color') # Notebook pages for light specific controls self.lightNotebook = Pmw.NoteBook(mainFrame, tabpos = None, borderwidth = 0) ambientPage = self.lightNotebook.add('Ambient') directionalPage = self.lightNotebook.add('Directional') pointPage = self.lightNotebook.add('Point') spotPage = self.lightNotebook.add('Spot') # Put this here so it isn't called right away self.lightNotebook['raisecommand'] = self.updateLightInfo # Directional light controls self.dSpecularColor = seColorEntry( directionalPage, text = 'Specular Color') self.dSpecularColor['command'] = self.setSpecularColor self.dSpecularColor.pack(fill = Tkinter.X, expand = 0) self.bind(self.dSpecularColor, 'Set directional light specular color') self.dPosition = Vector3Entry( directionalPage, text = 'Position') self.dPosition['command'] = self.setPosition self.dPosition['resetValue'] = [0,0,0,0] self.dPosition.pack(fill = Tkinter.X, expand = 0) self.bind(self.dPosition, 'Set directional light position') self.dOrientation = Vector3Entry( directionalPage, text = 'Orientation') self.dOrientation['command'] = self.setOrientation self.dOrientation['resetValue'] = [0,0,0,0] self.dOrientation.pack(fill = Tkinter.X, expand = 0) self.bind(self.dOrientation, 'Set directional light orientation') # Point light controls self.pSpecularColor = seColorEntry( pointPage, text = 'Specular Color') self.pSpecularColor['command'] = self.setSpecularColor self.pSpecularColor.pack(fill = Tkinter.X, expand = 0) self.bind(self.pSpecularColor, 'Set point light specular color') self.pPosition = Vector3Entry( pointPage, text = 'Position') self.pPosition['command'] = self.setPosition self.pPosition['resetValue'] = [0,0,0,0] self.pPosition.pack(fill = Tkinter.X, expand = 0) self.bind(self.pPosition, 'Set point light position') self.pConstantAttenuation = Slider( pointPage, text = 'Constant Attenuation', max = 1.0, resolution = 0.01, value = 1.0) self.pConstantAttenuation['command'] = self.setConstantAttenuation self.pConstantAttenuation.pack(fill = Tkinter.X, expand = 0) self.bind(self.pConstantAttenuation, 'Set point light constant attenuation') self.pLinearAttenuation = Slider( pointPage, text = 'Linear Attenuation', max = 1.0, resolution = 0.01, value = 0.0) self.pLinearAttenuation['command'] = self.setLinearAttenuation self.pLinearAttenuation.pack(fill = Tkinter.X, expand = 0) self.bind(self.pLinearAttenuation, 'Set point light linear attenuation') self.pQuadraticAttenuation = Slider( pointPage, text = 'Quadratic Attenuation', max = 1.0, resolution = 0.01, value = 0.0) self.pQuadraticAttenuation['command'] = self.setQuadraticAttenuation self.pQuadraticAttenuation.pack(fill = Tkinter.X, expand = 0) self.bind(self.pQuadraticAttenuation, 'Set point light quadratic attenuation') # Spot light controls self.sSpecularColor = seColorEntry( spotPage, text = 'Specular Color') self.sSpecularColor['command'] = self.setSpecularColor self.sSpecularColor.pack(fill = Tkinter.X, expand = 0) self.bind(self.sSpecularColor, 'Set spot light specular color') self.sConstantAttenuation = Slider( spotPage, text = 'Constant Attenuation', max = 1.0, resolution = 0.01, value = 1.0) self.sConstantAttenuation['command'] = self.setConstantAttenuation self.sConstantAttenuation.pack(fill = Tkinter.X, expand = 0) self.bind(self.sConstantAttenuation, 'Set spot light constant attenuation') self.sLinearAttenuation = Slider( spotPage, text = 'Linear Attenuation', max = 1.0, resolution = 0.01, value = 0.0) self.sLinearAttenuation['command'] = self.setLinearAttenuation self.sLinearAttenuation.pack(fill = Tkinter.X, expand = 0) self.bind(self.sLinearAttenuation, 'Set spot light linear attenuation') self.sQuadraticAttenuation = Slider( spotPage, text = 'Quadratic Attenuation', max = 1.0, resolution = 0.01, value = 0.0) self.sQuadraticAttenuation['command'] = self.setQuadraticAttenuation self.sQuadraticAttenuation.pack(fill = Tkinter.X, expand = 0) self.bind(self.sQuadraticAttenuation, 'Set spot light quadratic attenuation') self.sExponent = Slider( spotPage, text = 'Exponent', max = 1.0, resolution = 0.01, value = 0.0) self.sExponent['command'] = self.setExponent self.sExponent.pack(fill = Tkinter.X, expand = 0) self.bind(self.sExponent, 'Set spot light exponent') # MRM: Add frustum controls self.lightNotebook.setnaturalsize() self.lightNotebook.pack(expand = 1, fill = Tkinter.BOTH) mainFrame.pack(expand=1, fill = Tkinter.BOTH) def onDestroy(self, event): messenger.send('LP_close') ''' If you have open any thing, please rewrite here! ''' pass def renameLight(self): ################################################################# # renameLight(self) # Call Back function # This function will be called when user push # the "Rename" button on the panel. # # Then, this function will collect data and send out them with a message # "LP_rename" # Which will be caught by sceneEditor and pass to dataHolder to # complete the renaming. # ################################################################# oName = self.currentLight nName = self.lightEntry.get() messenger.send('LP_rename',[oName,nName]) return def deleteLight(self): ################################################################# # deleteLight(self) # Call Back Function. # This function will be called when user click on # the "Delete" button on the panel. # # Then, this function will send out a message with current seleted light # "LP_removeLight" # Which will be caught by sceneEditor and pass to dataHolder to # complete the delete process. # ################################################################# messenger.send('LP_removeLight',[self.currentLight]) return def updateList(self, list, node=None): ################################################################# # updataList(self, list, node = None) # This function will take a list object which contains names of lights in the scene. # Also, if user has put node as a parameter, # this function will automatically select that node as the current working target. ################################################################# self.lightList = list self.lightEntry.setlist(list) if node!=None: self.lightEntry.selectitem(index=node.getName(), setentry=True ) self.updateDisplay(node) elif len(list)>0: self.lightEntry.selectitem(index=0, setentry=True ) self.selectLight(list[0]) else: self.lightEntry.clear() return def selectLight(self, lightName): ################################################################# # selectLight(self, lightName) # This function will be called each time when # user select a light from the list on the panel. # Then, this function will send out the message, # 'LP_selectLight' to sceneEditorand get the current light information from dataHolder. ################################################################# if lightName in self.lightList: messenger.send('LP_selectLight',[lightName]) return def updateDisplay(self, lightNode): ################################################################# # updateDisplay(self, lightNode) # This function will update the information showing on the panel. # For example, give a lightNode which is a Point Light. # This function will switch the page to specify the type. # Also, new node is the same type with the previous one, # then this is function won't do the page switching, # but will call other function to refresh the data to target node. ################################################################# self.currentLight = lightNode if self.currentLight != None: color = lightNode.getLightColor() self.lightColor.set([255*color.getX(),255*color.getY(),255*color.getZ()]) oldType = self.type self.type = lightNode.getType() else: self.lightColor.set([255*0.3,255*0.3,255*0.3]) oldType = self.type self.type = 'ambient' if self.type=='ambient': self.lightNotebook.selectpage('Ambient') elif self.type =='directional': self.lightNotebook.selectpage('Directional') elif self.type =='point': self.lightNotebook.selectpage('Point') elif self.type =='spot': self.lightNotebook.selectpage('Spot') if oldType == self.type: # The same type with previous one, call updateLightInfo to refresh the values. self.updateLightInfo() return def updateLightInfo(self, page=None): ################################################################# # updateLightInfo(self, page=None) # This function will refresh the data we user have done any selection. ################################################################# if self.currentLight != None: light = self.currentLight.getLight() if self.type != 'ambient': specColor = light.getSpecularColor() if self.type =='directional': point = self.currentLight.getPosition() dir = self.currentLight.getOrientation() self.dSpecularColor.set([specColor.getX()*255,specColor.getY()*255,specColor.getZ()*255]) self.dPosition.set([point.getX(),point.getY(),point.getZ()]) self.dOrientation.set([dir.getX(),dir.getY(),dir.getZ()]) elif self.type =='point': point = self.currentLight.getPosition() attenuation = light.getAttenuation() self.pSpecularColor.set([specColor.getX()*255,specColor.getY()*255,specColor.getZ()*255]) self.pPosition.set([point.getX(),point.getY(),point.getZ()]) self.pConstantAttenuation.set(attenuation.getX()) self.pLinearAttenuation.set(attenuation.getY()) self.pQuadraticAttenuation.set(attenuation.getZ()) elif self.type =='spot': attenuation = light.getAttenuation() expo = light.getExponent() self.sSpecularColor.set([specColor.getX()*255,specColor.getY()*255,specColor.getZ()*255]) self.sConstantAttenuation.set(attenuation.getX()) self.sLinearAttenuation.set(attenuation.getY()) self.sQuadraticAttenuation.set(attenuation.getZ()) self.sExponent.set(expo) return def addAmbient(self): ################################################################# # addAmbient(self) # This function will send out a message to # ask dataHolder to create a default ambient light ################################################################# messenger.send('LP_addLight',['ambient']) return def addDirectional(self): ################################################################# # addDirectional(self) # This function will send out a message to # sk dataHolder to create a default Directional light ################################################################# messenger.send('LP_addLight',['directional']) return def addPoint(self): ################################################################# # addPoint(self) # This function will send out a message to # ask dataHolder to create a default Point light ################################################################# messenger.send('LP_addLight',['point']) return def addSpot(self): ################################################################# # addSpot(self) # This function will send out a message to # ask dataHolder to create a default Spot light ################################################################# messenger.send('LP_addLight',['spot']) return def setLightingColorVec(self,color): ################################################################# # setLightingColorVec(self,color) # Call Back function. This will be called # when user try to change the color of light. ################################################################# if self.currentLight==None: return self.currentLight.setColor(VBase4((color[0]/255),(color[1]/255),(color[2]/255),1)) return def setSpecularColor(self,color): ################################################################# # setSpecularColor(self,color) # Call Back function. This will be called # when user try to change the Specular color of light. ################################################################# if self.currentLight==None: return self.currentLight.setSpecColor(VBase4((color[0]/255),(color[1]/255),(color[2]/255),1)) return def setPosition(self,position): ################################################################# # setPosition(self,position) # Call Back function. This will be called # when user try to change the position of light. ################################################################# if self.currentLight==None: return self.currentLight.setPosition(Point3(position[0],position[1],position[2])) return def setOrientation(self, orient): ################################################################# # setOrientation(self, orient) # Call Back function. This will be called # when user try to change the orientation of light. ################################################################# if self.currentLight==None: return self.currentLight.setOrientation(Vec3(orient[0],orient[1],orient[2])) return def setConstantAttenuation(self, value): ################################################################# # setConstantAttenuation(self, value) # Call Back function. This will be called # when user try to change the Constant Attenuation of light. ################################################################# self.currentLight.setConstantAttenuation(value) return def setLinearAttenuation(self, value): ################################################################# # setLinearAttenuation(self, value) # Call Back function. This will be called # when user try to change the Linear Attenuation of light. ################################################################# self.currentLight.setLinearAttenuation(value) return def setQuadraticAttenuation(self, value): ################################################################# # setQuadraticAttenuation(self, value) # Call Back function. This will be called # when user try to change the Quadratic Attenuation of light. ################################################################# self.currentLight.setQuadraticAttenuation(value) return def setExponent(self, value): ################################################################# # setExponent(self, value) # Call Back function. This will be called # when user try to change Exponent value of light. ################################################################# self.currentLight.setExponent(value) return