panda3d/doc/SceneEditor/seLights.py
2005-01-19 23:27:15 +00:00

633 lines
26 KiB
Python

#################################################################
# seLights.py
# Written by Yi-Hong Lin, yihhongl@andrew.cmu.edu, 2004
#################################################################
from direct.showbase.PandaObject import *
from string import lower
from direct.directtools import DirectUtil
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( "Spotlight" )
elif(self.type=='point'):
self.helpModel = loader.loadModelCopy( "Pointlight" )
elif(self.type=='directional'):
self.helpModel = loader.loadModelCopy( "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()