mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 10:54:24 -04:00
494 lines
21 KiB
Python
494 lines
21 KiB
Python
#################################################################
|
|
# 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
|