################################################################# # seLights.py # Written by Yi-Hong Lin, yihhongl@andrew.cmu.edu, 2004 ################################################################# from direct.showbase.DirectObject import * from string import lower from direct.directtools import DirectUtil from pandac.PandaModules import * import string class seLight(NodePath): ################################################################# # seLight(NodePath) # This is an object for keeping light data and let we can manipulate # lights as otherNopaths. # This idea basically is from directLight. # But the way directLight object worked is not we want in our # sceneEditor. So, we wrote one by ourself. ################################################################# def __init__(self, light, parent, type, lightcolor=VBase4(0.3,0.3,0.3,1), specularColor = VBase4(1), position = Point3(0,0,0), orientation = Vec3(1,0,0), constant = 1.0, linear = 0.0, quadratic = 0.0, exponent = 0.0, tag="", lence = None): ################################################################# # __init__(self, light, parent, type, # lightcolor=VBase4(0.3,0.3,0.3,1), # specularColor = VBase4(1), # position = Point3(0,0,0), # orientation = Vec3(1,0,0), # constant = 1.0, # linear = 0.0, # quadratic = 0.0, # exponent = 0.0, # tag="", # lence = None): # This constructor will create a light node inside it and upcast # this light node to itself as a nodePath. # Also, it will load a model as a reference to itself on the secene so that # user can easily recognize where is the light and can easily manipulate # by mouse picking and widget control. ################################################################# # Initialize the super class NodePath.__init__(self) # Initialize and save values self.light = light self.type = type self.lightcolor=lightcolor self.specularColor = specularColor self.position = position self.orientation = orientation self.constant = constant self.linear = linear self.quadratic = quadratic self.exponent = exponent self.lence = lence self.active = True if isinstance(light, Spotlight): node = light.upcastToLensNode() else: node = light.upcastToPandaNode() # Attach node to self self.LightNode=parent.attachNewNode(node) self.LightNode.setTag("Metadata",tag) if(self.type=='spot'): self.LightNode.setHpr(self.orientation) self.LightNode.setPos(self.position) else: self.LightNode.setHpr(self.orientation) self.LightNode.setPos(self.position) self.assign(self.LightNode) if(self.type=='spot'): self.helpModel = loader.loadModelCopy( "models/misc/Spotlight" ) elif(self.type=='point'): self.helpModel = loader.loadModelCopy( "models/misc/Pointlight" ) elif(self.type=='directional'): self.helpModel = loader.loadModelCopy( "models/misc/Dirlight" ) else: self.helpModel = loader.loadModelCopy( "models/misc/sphere" ) self.helpModel.setColor(self.lightcolor) self.helpModel.reparentTo(self) DirectUtil.useDirectRenderStyle(self.helpModel) if not ((self.type == 'directional')or(self.type == 'point')or(self.type == 'spot')): self.helpModel.hide() def getLight(self): ################################################################# # getLight(self) # This function will return the light object it contains. ################################################################# return self.light def getLightColor(self): ################################################################# # getLightColor(self) # This function will return the color of the light color of this light node. ################################################################# return self.lightcolor def getName(self): ################################################################# # getName(self) # This function will return the name of this light. ################################################################# return self.light.getName() def rename(self,name): ################################################################# # rename(self, name) # User should specify a string object, name, as the new name of this # light node. This function will rename itself and light object # to this new name. ################################################################# self.light.setName(name) self.setName(name) def getType(self): ################################################################# # getType(self) # This function will return a string which is the type of this # light node. (We only have four types of light) ################################################################# return self.type def setColor(self,color): ################################################################# # setColor(self, color) # This function takes one input parameter, color, which is a # VBase4 object. This function will simply set this object into # light node it has to change the property of light. # Also, if the light type is either "directional" or "point", which # means it has a reference model with it, this function will also # change the reference model's color to input value. ################################################################# self.light.setColor(color) self.lightcolor = color if (self.type == 'directional')or(self.type == 'point'): self.helpModel.setColor(self.lightcolor) return def getSpecColor(self): ################################################################# # getSpecColor(self) # This function will return the specular color of the light. # Although you can call this function for all kinds of light, # it will only meanful if this light is not a ambient light. ################################################################# return self.specularColor def setSpecColor(self,color): ################################################################# # setSpecColor(self, color) # This function can be used to set the specular color of the light. # Although you can call this function for all kinds of light, # it will only meanful if the light type is not "ambient" ################################################################# self.light.setSpecularColor(color) self.specularcolor = color return def getPosition(self): ################################################################# # getPosition(self) # getPosition(self) # This functioln will return a Point3 object which contains # the x, y, z position data of this light node. # It only has meaning for "point Light" and "Directional light" ################################################################# self.position = self.LightNode.getPos() return self.position def setPosition(self, pos): ################################################################# # setPosition(self, pos) # This function will take a Point3 object as a input. # Then, this function will set the itself andd light node to the # target point. ################################################################# self.LightNode.setPos(pos) self.position = pos return def getOrientation(self): ################################################################# # getOrientation(self) # This function will return a Vec3-type object which contains the # orientation data of this light node # # This function will only have meaning for point light and directional light. # ################################################################# self.orientation = self.LightNode.getHpr() return self.orientation def setOrientation(self,orient): ################################################################# # setOrientation(self, orient) # This funtction will take a Vec3-type object as an input. # Then this function will set itself nad light node to face # the target orientation. # # This function only has meaning for point light and directional light # type of lights. # ################################################################# self.LightNode.setHpr(orient) self.orientation = orient return def getAttenuation(self): ################################################################# # getAttenuation(self) # This function will return a Vec3 type of object which contains # the constant, linear and quadratic attenuation for this light node. # # This function will only have meaning for point light and spot light # tyoe of lights. # ################################################################# return Vec3(self.constant,self.linear,self.quadratic) def setConstantAttenuation(self, value): ################################################################# # setConstantAttenuation(self, value) # This function will take a float number as an input. # Then, this function will set the Constant Atenuation value # to this number. ################################################################# self.light.setAttenuation(Vec3(value, self.linear, self.quadratic)) self.constant = value return def setLinearAttenuation(self, value): ################################################################# # setLinearAttenuation(self, value) # This function will take a float number as an input. # Then, this function will set the Linear Atenuation value # to this number. ################################################################# self.light.setAttenuation(Vec3(self.constant, value, self.quadratic)) self.linear = value return def setQuadraticAttenuation(self, value): ################################################################# # setQuadraticAttenuation(self, value) # This function will take a float number as an input. # Then, this function will set the Quadratic Atenuation value # to this number. ################################################################# self.light.setAttenuation(Vec3(self.constant, self.linear, value)) self.quadratic = value return def getExponent(self): ################################################################# # getExponent(self) # This function will return the value of the Exponent Attenuation # of this light node. (float) ################################################################# return self.exponent def setExponent(self, value): ################################################################# # setExponent(self, value) # This function will take a float number as an input. # Then, this function will set the Exponent Atenuation value # to this number. ################################################################# self.light.setExponent(value) self.exponent = value return class seLightManager(NodePath): ################################################################# # seLightManager(NodePath) # This is the class we used to control al lightings in our sceneEditor. ################################################################# def __init__(self): # Initialize the superclass NodePath.__init__(self) # Create a node for the lights self.lnode=render.attachNewNode('Lights') self.assign(self.lnode) # Create a light attrib self.lightAttrib = LightAttrib.makeAllOff() self.lightDict = {} self.ambientCount = 0 self.directionalCount = 0 self.pointCount = 0 self.spotCount = 0 # Originally, we don't do this load model thing. # But the problem is, if we don't, then it will cause some # Bounding calculation error... self.helpModel = loader.loadModelCopy( "models/misc/sphere" ) self.helpModel.reparentTo(self) self.helpModel.hide() def create(self, type = 'ambient', lightcolor=VBase4(0.3,0.3,0.3,1), specularColor = VBase4(1), position = Point3(0,0,0), orientation = Vec3(1,0,0), constant = 1.0, linear = 0.0, quadratic = 0.0, exponent = 0.0, tag= "", name='DEFAULT_NAME'): ################################################################# # create(self, type = 'ambient', # lightcolor=VBase4(0.3,0.3,0.3,1), # specularColor = VBase4(1), # position = Point3(0,0,0), # orientation = Vec3(1,0,0), # constant = 1.0, # linear = 0.0, # quadratic = 0.0, # exponent = 0.0, # tag= "", # name='DEFAULT_NAME') # As you can see, once user call this function and specify those # variables, this function will create a seLight node. # In the default, the light which just has been created will be # set to off. ################################################################# ### create the light lence = None if type == 'ambient': self.ambientCount += 1 if(name=='DEFAULT_NAME'): light = AmbientLight('ambient_' + `self.ambientCount`) else: light = AmbientLight(name) light.setColor(lightcolor) elif type == 'directional': self.directionalCount += 1 if(name=='DEFAULT_NAME'): light = DirectionalLight('directional_' + `self.directionalCount`) else: light = DirectionalLight(name) light.setColor(lightcolor) light.setSpecularColor(specularColor) elif type == 'point': self.pointCount += 1 if(name=='DEFAULT_NAME'): light = PointLight('point_' + `self.pointCount`) else: light = PointLight(name) light.setColor(lightcolor) light.setSpecularColor(specularColor) light.setAttenuation(Vec3(constant, linear, quadratic)) elif type == 'spot': self.spotCount += 1 if(name=='DEFAULT_NAME'): light = Spotlight('spot_' + `self.spotCount`) else: light = Spotlight(name) light.setColor(lightcolor) lence = PerspectiveLens() light.setLens(lence) light.setSpecularColor(specularColor) light.setAttenuation(Vec3(constant, linear, quadratic)) light.setExponent(exponent) else: print 'Invalid light type' return None # Create the seLight objects and put the light object we just created into it. lightNode = seLight(light,self,type, lightcolor=lightcolor, specularColor = specularColor, position = position, orientation = orientation, constant = constant, linear = linear, quadratic = quadratic, exponent = exponent, tag=tag, lence = lence ) self.lightDict[light.getName()] = lightNode self.setOn(lightNode) return self.lightDict.keys(),lightNode def addLight(self, light): ################################################################# # addLight(self, light) # This function will put light in and save its properties in to a seLight Node # Attention!! # only Spotlight obj nneds to be specified a lens node first. i.e. setLens() first! ################################################################# type = lower(light.getType().getName()) light.upcastToNamable() specularColor = VBase4(1) position = Point3(0,0,0) orientation = Vec3(1,0,0) constant = 1.0 linear = 0.0 quadratic = 0.0 exponent = 0.0 lence = None lightcolor = light.getColor() if type == 'ambientlight': type = 'ambient' self.ambientCount += 1 elif type == 'directionallight': type = 'directional' self.directionalCount += 1 orientation = light.getDirection() position = light.getPoint() specularColor = light.getSpecularColor() elif type == 'pointlight': type = 'point' self.pointCount += 1 position = light.getPoint() specularColor = light.getSpecularColor() Attenuation = light.getAttenuation() constant = Attenuation.getX() linear = Attenuation.getY() quadratic = Attenuation.getZ() elif type == 'spotlight': type = 'spot' self.spotCount += 1 specularColor = light.getSpecularColor() Attenuation = light.getAttenuation() constant = Attenuation.getX() linear = Attenuation.getY() quadratic = Attenuation.getZ() exponent = light.getExponent() else: print 'Invalid light type' return None lightNode = seLight(light,self,type, lightcolor=lightcolor, specularColor = specularColor, position = position, orientation = orientation, constant = constant, linear = linear, quadratic = quadratic, exponent = exponent, lence = lence) self.lightDict[light.getName()] = lightNode self.setOn(lightNode) return self.lightDict.keys(),lightNode def delete(self, name, removeEntry = True): ################################################################# # delete(self, name, removeEntry = True) # This function will remove light node had the same name with user input. # Also, you can specify the removeEntry to decide to remove the entry from the lightDict or not. # Normaly, you alway want to remove the entry from the dictionary. Thsi is only used for "deleteAll" function. ################################################################# type = self.lightDict[name].getType() if type == 'ambient': self.ambientCount -= 1 elif type == 'directional': self.directionalCount -= 1 elif type == 'point': self.pointCount -= 1 elif type == 'spot': self.spotCount -= 1 self.setOff(self.lightDict[name]) self.lightDict[name].removeChildren() self.lightDict[name].removeNode() if removeEntry: del self.lightDict[name] return self.lightDict.keys() def deleteAll(self): ################################################################# # deleteAll(self) # This function will keep calling delete and put exist lights in # until all lights have been eliminated. ################################################################# for name in self.lightDict: self.delete(name, removeEntry = False) self.lightDict.clear() def isLight(self,name): ################################################################# # isLight(self.name) # Use a string as a index to check if there existing a light named "name" ################################################################# return self.lightDict.has_key(name) def rename(self,oName,nName): ################################################################# # rename(self, oName, nName) # This function will reanem the light named "oName(String)" to # nName(String) ################################################################# if self.isLight(oName): lightNode = self.lightDict[oName] self.lightDict[nName] = lightNode lightNode.rename(nName) del self.lightDict[oName] return self.lightDict.keys(),lightNode else: print '----Light Mnager: No such Light!' def getLightNodeList(self): ################################################################# # getLightNodeList(self) # Return a list which contains all seLight nodes ################################################################# list = [] for name in self.lightDict: list.append(self.lightDict[name]) return list def getLightNodeDict(self): ################################################################# # getLightNodeDict(self) # Return the light dictionary itself. # # Attention! # Because it doesn't make a copy when you return a dictionary, it # means when you can change the value from outside and that change # will directly reflect back to here. # ################################################################# return self.lightDict def getLightList(self): ################################################################# # getLightList(self) # Return a list which contains names of all lights. ################################################################# list = [] for name in self.lightDict: list.append(name) return list def getLightNode(self,lightName): ################################################################# # getLightNode(self, lightName) # This function will return a seLight Node using a string, lightName. as a index. ################################################################# if lightName in self.lightDict: return self.lightDict[lightName] def allOn(self): ################################################################# # allOb(self) # Enable the lighting system. ################################################################# # Turn on all lighting render.node().setAttrib(self.lightAttrib) # Make sure there is a default material render.setMaterial(Material()) def allOff(self): ################################################################# # allOff(self) # Disable whole lighting system ################################################################# # Turn off all lighting render.node().clearAttrib(LightAttrib.getClassType()) def toggle(self): ################################################################# # toggle(self) # Toggles light attribute, but doesn't toggle individual lights ################################################################# if render.node().hasAttrib(LightAttrib.getClassType()): self.allOff() else: self.allOn() def setOn(self, lightNode): ################################################################# # setOn(lightNode) # This function will enable the input seLight node. # If the light system itself is down, activate it. ################################################################# self.lightAttrib = self.lightAttrib.addLight(lightNode.getLight()) lightNode.active = True if render.node().hasAttrib(LightAttrib.getClassType()): render.node().setAttrib(self.lightAttrib) def setOff(self, lightNode): ################################################################# # setOff(self, lightNode) # This function will disable the input seLight node # If the light system itself is down, activate it. ################################################################# lightNode.active = False self.lightAttrib = self.lightAttrib.removeLight(lightNode.getLight()) if render.node().hasAttrib(LightAttrib.getClassType()): render.node().setAttrib(self.lightAttrib) def getList(self): ################################################################# # getList(self) # This function actually has the same functionality with getLightList(), # but this one should be more efficient. ################################################################# return self.lightDict.keys()