""" DIRECT Session Main panel """
__all__ = ['DirectSessionPanel']
# Import Tkinter, Pmw, and the dial code
from direct.showbase.TkGlobal import *
from direct.tkwidgets.AppShell import *
from panda3d.core import *
import Pmw
from direct.tkwidgets import Dial
from direct.tkwidgets import Floater
from direct.tkwidgets import Slider
from direct.tkwidgets import VectorWidgets
from direct.tkwidgets import SceneGraphExplorer
from .TaskManagerPanel import TaskManagerWidget
from direct.tkwidgets import MemoryExplorer
"""
Possible to add:
messenger.clear?
popup panels
taskMgr page
"""
[docs]class DirectSessionPanel(AppShell):
# Override class variables here
appname = 'Direct Session Panel'
frameWidth = 600
frameHeight = 365
usecommandarea = 0
usestatusarea = 0
[docs] def __init__(self, parent = None, **kw):
INITOPT = Pmw.INITOPT
optiondefs = (
('title', self.appname, None),
)
self.defineoptions(kw, optiondefs)
# Call superclass initialization function
AppShell.__init__(self, parent)
# Active light
if len(base.direct.lights) > 0:
name = base.direct.lights.getNameList()[0]
self.lightMenu.selectitem(name)
self.selectLightNamed(name)
else:
self.activeLight = None
# Active display region
self.drMenu.selectitem('Display Region 0')
self.selectDisplayRegionNamed('Display Region 0')
# Make sure we've got valid initial values
self.updateInfo()
self.initialiseoptions(DirectSessionPanel)
[docs] def appInit(self):
# Initialize state
# Dictionary keeping track of all node paths selected so far
self.nodePathDict = {}
self.nodePathDict['widget'] = base.direct.widget
self.nodePathNames = ['widget']
# Dictionary keeping track of all jb node paths selected so far
self.jbNodePathDict = {}
self.jbNodePathDict['none'] = 'No Node Path'
self.jbNodePathDict['widget'] = base.direct.widget
self.jbNodePathDict['camera'] = base.direct.camera
self.jbNodePathNames = ['camera', 'selected', 'none']
# Set up event hooks
self.actionEvents = [
('DIRECT_undo', self.undoHook),
('DIRECT_pushUndo', self.pushUndoHook),
('DIRECT_undoListEmpty', self.undoListEmptyHook),
('DIRECT_redo', self.redoHook),
('DIRECT_pushRedo', self.pushRedoHook),
('DIRECT_redoListEmpty', self.redoListEmptyHook),
('DIRECT_selectedNodePath', self.selectedNodePathHook),
('DIRECT_addLight', self.addLight),
]
for event, method in self.actionEvents:
self.accept(event, method)
[docs] def createInterface(self):
# The interior of the toplevel panel
interior = self.interior()
# Add placer commands to menubar
self.menuBar.addmenu('DIRECT', 'Direct Session Panel Operations')
self.directEnabled = BooleanVar()
self.directEnabled.set(1)
self.menuBar.addmenuitem('DIRECT', 'checkbutton',
'DIRECT Enabled',
label = 'Enable',
variable = self.directEnabled,
command = self.toggleDirect)
self.directGridEnabled = BooleanVar()
self.directGridEnabled.set(base.direct.grid.isEnabled())
self.menuBar.addmenuitem('DIRECT', 'checkbutton',
'DIRECT Grid Enabled',
label = 'Enable Grid',
variable = self.directGridEnabled,
command = self.toggleDirectGrid)
self.menuBar.addmenuitem('DIRECT', 'command',
'Toggle Object Handles Visability',
label = 'Toggle Widget Viz',
command = base.direct.toggleWidgetVis)
self.menuBar.addmenuitem(
'DIRECT', 'command',
'Toggle Widget Move/COA Mode',
label = 'Toggle Widget Mode',
command = base.direct.manipulationControl.toggleObjectHandlesMode)
self.directWidgetOnTop = BooleanVar()
self.directWidgetOnTop.set(0)
self.menuBar.addmenuitem('DIRECT', 'checkbutton',
'DIRECT Widget On Top',
label = 'Widget On Top',
variable = self.directWidgetOnTop,
command = self.toggleWidgetOnTop)
self.menuBar.addmenuitem('DIRECT', 'command',
'Deselect All',
label = 'Deselect All',
command = base.direct.deselectAll)
# Get a handle to the menu frame
menuFrame = self.menuFrame
# Widget to select node paths (and display list of selected node paths)
self.nodePathMenu = Pmw.ComboBox(
menuFrame, labelpos = W, label_text = 'DIRECT Select:',
entry_width = 20,
selectioncommand = self.selectNodePathNamed,
scrolledlist_items = self.nodePathNames)
self.nodePathMenu.selectitem('widget')
self.nodePathMenuEntry = (
self.nodePathMenu.component('entryfield_entry'))
self.nodePathMenuBG = (
self.nodePathMenuEntry.configure('background')[3])
self.nodePathMenu.pack(side = LEFT, fill = X, expand = 1)
self.bind(self.nodePathMenu, 'Select node path to manipulate')
self.undoButton = Button(menuFrame, text = 'Undo',
command = base.direct.undo)
if base.direct.undoList:
self.undoButton['state'] = 'normal'
else:
self.undoButton['state'] = 'disabled'
self.undoButton.pack(side = LEFT, expand = 0)
self.bind(self.undoButton, 'Undo last operation')
self.redoButton = Button(menuFrame, text = 'Redo',
command = base.direct.redo)
if base.direct.redoList:
self.redoButton['state'] = 'normal'
else:
self.redoButton['state'] = 'disabled'
self.redoButton.pack(side = LEFT, expand = 0)
self.bind(self.redoButton, 'Redo last operation')
# The master frame for the dials
mainFrame = Frame(interior)
# Paned widget for dividing two halves
framePane = Pmw.PanedWidget(mainFrame, orient = HORIZONTAL)
sgeFrame = framePane.add('left', min = 250)
notebookFrame = framePane.add('right', min = 300)
# Scene Graph Explorer
self.SGE = SceneGraphExplorer.SceneGraphExplorer(
sgeFrame, nodePath = render,
scrolledCanvas_hull_width = 250,
scrolledCanvas_hull_height = 300)
self.SGE.pack(fill = BOTH, expand = 1)
sgeFrame.pack(side = LEFT, fill = 'both', expand = 1)
# Create the notebook pages
notebook = Pmw.NoteBook(notebookFrame)
notebook.pack(fill = BOTH, expand = 1)
self.createEnvPage(notebook.add('Environment'))
self.createLightsPage(notebook.add('Lights'))
self.createGridPage(notebook.add('Grid'))
self.createDevicePage(notebook.add('Devices'))
self.createTasksPage(notebook.add('Tasks'))
self.createMemPage(notebook.add('Memory'))
notebook.setnaturalsize()
framePane.pack(expand = 1, fill = BOTH)
mainFrame.pack(fill = 'both', expand = 1)
# Put this here so it isn't called right away
notebook['raisecommand'] = self.updateInfo
[docs] def createEnvPage(self, envPage):
bkgrdFrame = Frame(envPage, borderwidth = 2, relief = 'sunken')
Label(bkgrdFrame, text = 'Background',
font=('MSSansSerif', 14, 'bold')).pack(expand = 0)
self.backgroundColor = VectorWidgets.ColorEntry(
bkgrdFrame, text = 'Background Color')
self.backgroundColor['command'] = self.setBackgroundColorVec
self.backgroundColor.pack(fill = X, expand = 0)
self.bind(self.backgroundColor, 'Set background color')
bkgrdFrame.pack(fill = BOTH, expand = 0)
drFrame = Frame(envPage, borderwidth = 2, relief = 'sunken')
Label(drFrame, text = 'Display Region',
font=('MSSansSerif', 14, 'bold')).pack(expand = 0)
nameList = ['Display Region ' + repr(x) for x in range(len(base.direct.drList))]
self.drMenu = Pmw.ComboBox(
drFrame, labelpos = W, label_text = 'Display Region:',
entry_width = 20,
selectioncommand = self.selectDisplayRegionNamed,
scrolledlist_items = nameList)
self.drMenu.pack(fill = X, expand = 0)
self.bind(self.drMenu, 'Select display region to configure')
self.nearPlane = Floater.Floater(
drFrame,
text = 'Near Plane',
min = 0.01)
self.nearPlane['command'] = self.setNear
self.nearPlane.pack(fill = X, expand = 0)
self.bind(self.nearPlane, 'Set near plane distance')
self.farPlane = Floater.Floater(
drFrame,
text = 'Far Plane',
min = 0.01)
self.farPlane['command'] = self.setFar
self.farPlane.pack(fill = X, expand = 0)
self.bind(self.farPlane, 'Set far plane distance')
fovFrame = Frame(drFrame)
fovFloaterFrame = Frame(fovFrame)
self.hFov = Slider.Slider(
fovFloaterFrame,
text = 'Horizontal FOV',
min = 0.01, max = 170.0)
self.hFov['command'] = self.setHFov
self.hFov.pack(fill = X, expand = 0)
self.bind(self.hFov, 'Set horizontal field of view')
self.vFov = Slider.Slider(
fovFloaterFrame,
text = 'Vertical FOV',
min = 0.01, max = 170.0)
self.vFov['command'] = self.setVFov
self.vFov.pack(fill = X, expand = 0)
self.bind(self.vFov, 'Set vertical field of view')
fovFloaterFrame.pack(side = LEFT, fill = X, expand = 1)
frame = Frame(fovFrame)
self.lockedFov = BooleanVar()
self.lockedFov.set(1)
self.lockedFovButton = Checkbutton(
frame,
text = 'Locked',
anchor = 'w', justify = LEFT,
variable = self.lockedFov)
self.lockedFovButton.pack(fill = X, expand = 0)
self.resetFovButton = Button(
frame,
text = 'Reset',
command = self.resetFov)
self.resetFovButton.pack(fill = X, expand = 0)
frame.pack(side = LEFT, fill = X, expand = 0)
fovFrame.pack(fill = X, expand = 1)
drFrame.pack(fill = BOTH, expand = 0)
## Render Style ##
toggleFrame = Frame(envPage, borderwidth = 2, relief = 'sunken')
Label(toggleFrame, text = 'Toggle Render Style',
font=('MSSansSerif', 14, 'bold')).pack(expand = 0)
self.toggleBackfaceButton = Button(
toggleFrame,
text = 'Backface',
command = base.toggleBackface)
self.toggleBackfaceButton.pack(side = LEFT, fill = X, expand = 1)
self.toggleLightsButton = Button(
toggleFrame,
text = 'Lights',
command = base.direct.lights.toggle)
self.toggleLightsButton.pack(side = LEFT, fill = X, expand = 1)
self.toggleTextureButton = Button(
toggleFrame,
text = 'Texture',
command = base.toggleTexture)
self.toggleTextureButton.pack(side = LEFT, fill = X, expand = 1)
self.toggleWireframeButton = Button(
toggleFrame,
text = 'Wireframe',
command = base.toggleWireframe)
self.toggleWireframeButton.pack(fill = X, expand = 1)
toggleFrame.pack(side = LEFT, fill = X, expand = 1)
[docs] def createLightsPage(self, lightsPage):
# Lights #
lightFrame = Frame(lightsPage, borderwidth = 2, relief = 'sunken')
self.lightsButton = Menubutton(lightFrame, text = 'Lights',
font=('MSSansSerif', 14, 'bold'),
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
# Notebook pages for light specific controls
self.lightNotebook = Pmw.NoteBook(lightFrame, 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
# Main light switch
mainSwitchFrame = Frame(lightFrame)
Label(mainSwitchFrame,
text = 'Lighting:').pack(side = LEFT, expand = 0)
self.enableLights = BooleanVar()
self.enableLightsButton = Checkbutton(
mainSwitchFrame,
text = 'Enabled/Disabled',
variable = self.enableLights,
command = self.toggleLights)
self.enableLightsButton.pack(side = LEFT, fill = X, expand = 0)
mainSwitchFrame.pack(fill = X, expand = 0)
# Widget to select a light to configure
nameList = base.direct.lights.getNameList()
lightMenuFrame = Frame(lightFrame)
self.lightMenu = Pmw.ComboBox(
lightMenuFrame, labelpos = W, label_text = 'Light:',
entry_width = 20,
selectioncommand = self.selectLightNamed,
scrolledlist_items = nameList)
self.lightMenu.pack(side = LEFT, fill = X, expand = 0)
self.bind(self.lightMenu, 'Select light to configure')
self.lightActive = BooleanVar()
self.lightActiveButton = Checkbutton(
lightMenuFrame,
text = 'On/Off',
variable = self.lightActive,
command = self.toggleActiveLight)
self.lightActiveButton.pack(side = LEFT, fill = X, expand = 0)
# Pack light menu
lightMenuFrame.pack(fill = X, expand = 0, padx = 2)
self.lightColor = VectorWidgets.ColorEntry(
lightFrame, text = 'Light Color')
self.lightColor['command'] = self.setLightColor
self.lightColor.pack(fill = X, expand = 0, padx = 4)
self.bind(self.lightColor, 'Set active light color')
# Directional light controls
self.dSpecularColor = VectorWidgets.ColorEntry(
directionalPage, text = 'Specular Color')
self.dSpecularColor['command'] = self.setSpecularColor
self.dSpecularColor.pack(fill = X, expand = 0)
self.bind(self.dSpecularColor,
'Set directional light specular color')
# Point light controls
self.pSpecularColor = VectorWidgets.ColorEntry(
pointPage, text = 'Specular Color')
self.pSpecularColor['command'] = self.setSpecularColor
self.pSpecularColor.pack(fill = X, expand = 0)
self.bind(self.pSpecularColor,
'Set point light specular color')
self.pConstantAttenuation = Slider.Slider(
pointPage,
text = 'Constant Attenuation',
min = 0.0, max = 1.0, value = 1.0)
self.pConstantAttenuation['command'] = self.setConstantAttenuation
self.pConstantAttenuation.pack(fill = X, expand = 0)
self.bind(self.pConstantAttenuation,
'Set point light constant attenuation')
self.pLinearAttenuation = Slider.Slider(
pointPage,
text = 'Linear Attenuation',
min = 0.0, max = 1.0, value = 0.0)
self.pLinearAttenuation['command'] = self.setLinearAttenuation
self.pLinearAttenuation.pack(fill = X, expand = 0)
self.bind(self.pLinearAttenuation,
'Set point light linear attenuation')
self.pQuadraticAttenuation = Slider.Slider(
pointPage,
text = 'Quadratic Attenuation',
min = 0.0, max = 1.0, value = 0.0)
self.pQuadraticAttenuation['command'] = self.setQuadraticAttenuation
self.pQuadraticAttenuation.pack(fill = X, expand = 0)
self.bind(self.pQuadraticAttenuation,
'Set point light quadratic attenuation')
# Spot light controls
self.sSpecularColor = VectorWidgets.ColorEntry(
spotPage, text = 'Specular Color')
self.sSpecularColor['command'] = self.setSpecularColor
self.sSpecularColor.pack(fill = X, expand = 0)
self.bind(self.sSpecularColor,
'Set spot light specular color')
self.sConstantAttenuation = Slider.Slider(
spotPage,
text = 'Constant Attenuation',
min = 0.0, max = 1.0, value = 1.0)
self.sConstantAttenuation['command'] = self.setConstantAttenuation
self.sConstantAttenuation.pack(fill = X, expand = 0)
self.bind(self.sConstantAttenuation,
'Set spot light constant attenuation')
self.sLinearAttenuation = Slider.Slider(
spotPage,
text = 'Linear Attenuation',
min = 0.0, max = 1.0, value = 0.0)
self.sLinearAttenuation['command'] = self.setLinearAttenuation
self.sLinearAttenuation.pack(fill = X, expand = 0)
self.bind(self.sLinearAttenuation,
'Set spot light linear attenuation')
self.sQuadraticAttenuation = Slider.Slider(
spotPage,
text = 'Quadratic Attenuation',
min = 0.0, max = 1.0, value = 0.0)
self.sQuadraticAttenuation['command'] = self.setQuadraticAttenuation
self.sQuadraticAttenuation.pack(fill = X, expand = 0)
self.bind(self.sQuadraticAttenuation,
'Set spot light quadratic attenuation')
self.sExponent = Slider.Slider(
spotPage,
text = 'Exponent',
min = 0.0, max = 1.0, value = 0.0)
self.sExponent['command'] = self.setExponent
self.sExponent.pack(fill = X, expand = 0)
self.bind(self.sExponent,
'Set spot light exponent')
# MRM: Add frustum controls
self.lightNotebook.setnaturalsize()
self.lightNotebook.pack(expand = 1, fill = BOTH)
lightFrame.pack(expand = 1, fill = BOTH)
[docs] def createGridPage(self, gridPage):
Label(gridPage, text = 'Grid',
font=('MSSansSerif', 14, 'bold')).pack(expand = 0)
self.enableGrid = BooleanVar()
self.enableGridButton = Checkbutton(
gridPage,
text = 'Enabled/Disabled',
anchor = 'w', justify = LEFT,
variable = self.enableGrid,
command = self.toggleGrid)
self.enableGridButton.pack(fill = X, expand = 0)
self.xyzSnap = BooleanVar()
self.xyzSnapButton = Checkbutton(
gridPage,
text = 'XYZ Snap',
anchor = 'w', justify = LEFT,
variable = self.xyzSnap,
command = self.toggleXyzSnap)
self.xyzSnapButton.pack(fill = X, expand = 0)
self.hprSnap = BooleanVar()
self.hprSnapButton = Checkbutton(
gridPage,
text = 'HPR Snap',
anchor = 'w', justify = LEFT,
variable = self.hprSnap,
command = self.toggleHprSnap)
self.hprSnapButton.pack(fill = X, expand = 0)
self.gridSpacing = Floater.Floater(
gridPage,
text = 'Grid Spacing',
min = 0.1,
value = base.direct.grid.getGridSpacing())
self.gridSpacing['command'] = base.direct.grid.setGridSpacing
self.gridSpacing.pack(fill = X, expand = 0)
self.gridSize = Floater.Floater(
gridPage,
text = 'Grid Size',
min = 1.0,
value = base.direct.grid.getGridSize())
self.gridSize['command'] = base.direct.grid.setGridSize
self.gridSize.pack(fill = X, expand = 0)
self.gridSnapAngle = Dial.AngleDial(
gridPage,
text = 'Snap Angle',
style = 'mini',
value = base.direct.grid.getSnapAngle())
self.gridSnapAngle['command'] = base.direct.grid.setSnapAngle
self.gridSnapAngle.pack(fill = X, expand = 0)
[docs] def createDevicePage(self, devicePage):
Label(devicePage, text = 'DEVICES',
font=('MSSansSerif', 14, 'bold')).pack(expand = 0)
if base.direct.joybox != None:
joyboxFrame = Frame(devicePage, borderwidth = 2, relief = 'sunken')
Label(joyboxFrame, text = 'Joybox',
font=('MSSansSerif', 14, 'bold')).pack(expand = 0)
self.enableJoybox = BooleanVar()
self.enableJoybox.set(1)
self.enableJoyboxButton = Checkbutton(
joyboxFrame,
text = 'Enabled/Disabled',
anchor = 'w', justify = LEFT,
variable = self.enableJoybox,
command = self.toggleJoybox)
self.enableJoyboxButton.pack(fill = X, expand = 0)
joyboxFrame.pack(fill = X, expand = 0)
self.jbModeMenu = Pmw.ComboBox(
joyboxFrame, labelpos = W, label_text = 'Joybox Mode:',
label_width = 16, entry_width = 20,
selectioncommand = self.selectJBModeNamed,
scrolledlist_items = ['Joe Mode', 'Drive Mode', 'Orbit Mode',
'Look At Mode', 'Look Around Mode',
'Walkthru Mode', 'Demo Mode',
'HPRXYZ Mode'])
self.jbModeMenu.selectitem('Joe Mode')
self.jbModeMenu.pack(fill = X, expand = 1)
self.jbNodePathMenu = Pmw.ComboBox(
joyboxFrame, labelpos = W, label_text = 'Joybox Node Path:',
label_width = 16, entry_width = 20,
selectioncommand = self.selectJBNodePathNamed,
scrolledlist_items = self.jbNodePathNames)
self.jbNodePathMenu.selectitem('camera')
self.jbNodePathMenuEntry = (
self.jbNodePathMenu.component('entryfield_entry'))
self.jbNodePathMenuBG = (
self.jbNodePathMenuEntry.configure('background')[3])
self.jbNodePathMenu.pack(fill = X, expand = 1)
self.bind(self.jbNodePathMenu,
'Select node path to manipulate using the joybox')
self.jbXyzSF = Slider.Slider(
joyboxFrame,
text = 'XYZ Scale Factor',
value = 1.0,
hull_relief = RIDGE, hull_borderwidth = 2,
min = 1.0, max = 100.0)
self.jbXyzSF['command'] = (
lambda v: base.direct.joybox.setXyzMultiplier(v))
self.jbXyzSF.pack(fill = X, expand = 0)
self.bind(self.jbXyzSF, 'Set joybox XYZ speed multiplier')
self.jbHprSF = Slider.Slider(
joyboxFrame,
text = 'HPR Scale Factor',
value = 1.0,
hull_relief = RIDGE, hull_borderwidth = 2,
min = 1.0, max = 100.0)
self.jbHprSF['command'] = (
lambda v: base.direct.joybox.setHprMultiplier(v))
self.jbHprSF.pack(fill = X, expand = 0)
self.bind(self.jbHprSF, 'Set joybox HPR speed multiplier')
[docs] def createTasksPage(self, tasksPage):
Label(tasksPage, text = 'TASKS',
font=('MSSansSerif', 14, 'bold')).pack(expand = 0)
self.taskMgrPanel = TaskManagerWidget(tasksPage, taskMgr)
self.taskMgrPanel.taskListBox['listbox_height'] = 10
[docs] def createMemPage(self, memPage):
self.MemExp = MemoryExplorer.MemoryExplorer(
memPage, nodePath = render,
scrolledCanvas_hull_width = 250,
scrolledCanvas_hull_height = 250)
self.MemExp.pack(fill = BOTH, expand = 1)
[docs] def toggleDirect(self):
if self.directEnabled.get():
base.direct.enable()
else:
base.direct.disable()
[docs] def toggleDirectGrid(self):
if self.directGridEnabled.get():
base.direct.grid.enable()
else:
base.direct.grid.disable()
[docs] def selectedNodePathHook(self, nodePath):
# Make sure node path is in nodePathDict
# MRM: Do we need to truncate list?
if isinstance(nodePath, NodePath):
self.addNodePath(nodePath)
[docs] def selectNodePathNamed(self, name):
# See if node path has already been selected
nodePath = self.nodePathDict.get(name, None)
# If not, see if listbox evals into a node path
if (nodePath == None):
# See if this evaluates into a node path
try:
nodePath = eval(name)
if isinstance(nodePath, NodePath):
self.addNodePath(nodePath)
else:
# Good eval but not a node path, give up
nodePath = None
except:
# Bogus eval
nodePath = None
# Clear bogus entry from listbox
listbox = self.nodePathMenu.component('scrolledlist')
listbox.setlist(self.nodePathNames)
# Did we finally get something?
if (nodePath != None):
# Yes, select it!
base.direct.select(nodePath)
[docs] def addNodePath(self, nodePath):
self.addNodePathToDict(nodePath, self.nodePathNames,
self.nodePathMenu, self.nodePathDict)
[docs] def selectJBModeNamed(self, name):
if name == 'Joe Mode':
base.direct.joybox.joeMode()
elif name == 'Drive Mode':
base.direct.joybox.driveMode()
elif name == 'Orbit Mode':
base.direct.joybox.orbitMode()
elif name == 'Look At Mode':
base.direct.joybox.lookAtMode()
elif name == 'Look Around Mode':
base.direct.joybox.lookAroundMode()
elif name == 'Walkthru Mode':
base.direct.joybox.walkthruMode()
elif name == 'Demo Mode':
base.direct.joybox.demoMode()
elif name == 'HPRXYZ Mode':
base.direct.joybox.hprXyzMode()
[docs] def selectJBNodePathNamed(self, name):
if name == 'selected':
nodePath = base.direct.selected.last
# Add Combo box entry for this selected object
self.addJBNodePath(nodePath)
else:
# See if node path has already been selected
nodePath = self.jbNodePathDict.get(name, None)
if (nodePath == None):
# If not, see if listbox evals into a node path
try:
nodePath = eval(name)
if isinstance(nodePath, NodePath):
self.addJBNodePath(nodePath)
else:
# Good eval but not a node path, give up
nodePath = None
except:
# Bogus eval
nodePath = None
# Clear bogus entry from listbox
listbox = self.jbNodePathMenu.component('scrolledlist')
listbox.setlist(self.jbNodePathNames)
# Did we finally get something?
if (nodePath != None):
# Yes, select it!
if (nodePath == 'No Node Path'):
base.direct.joybox.setNodePath(None)
else:
base.direct.joybox.setNodePath(nodePath)
[docs] def addJBNodePath(self, nodePath):
self.addNodePathToDict(nodePath, self.jbNodePathNames,
self.jbNodePathMenu, self.jbNodePathDict)
[docs] def addNodePathToDict(self, nodePath, names, menu, dict):
if not nodePath:
return
# Get node path's name
name = nodePath.getName()
if name in ['parent', 'render', 'camera']:
dictName = name
else:
# Generate a unique name for the dict
dictName = name + '-' + repr(hash(nodePath))
if dictName not in dict:
# Update combo box to include new item
names.append(dictName)
listbox = menu.component('scrolledlist')
listbox.setlist(names)
# Add new item to dictionary
dict[dictName] = nodePath
menu.selectitem(dictName)
## ENVIRONMENT CONTROLS ##
# Background #
[docs] def setBackgroundColor(self, r, g, b):
self.setBackgroundColorVec((r, g, b))
[docs] def setBackgroundColorVec(self, color):
base.setBackgroundColor(color[0]/255.0,
color[1]/255.0,
color[2]/255.0)
[docs] def selectDisplayRegionNamed(self, name):
if name.find('Display Region ') >= 0:
drIndex = int(name[-1:])
self.activeDisplayRegion = base.direct.drList[drIndex]
else:
self.activeDisplayRegion = None
# Make sure info is current
self.updateDisplayRegionInfo()
[docs] def setNear(self, near):
dr = self.activeDisplayRegion
if dr:
dr.camLens.setNear(near)
cluster('base.camLens.setNear(%f)' % near, 0)
[docs] def setFar(self, far):
dr = self.activeDisplayRegion
if dr:
dr.camLens.setFar(far)
cluster('base.camLens.setFar(%f)' % far, 0)
[docs] def setHFov(self, hFov):
dr = self.activeDisplayRegion
if dr:
if self.lockedFov.get():
sf = hFov/dr.getHfov()
vFov = min(dr.getVfov() * sf, 170.0)
dr.setFov(hFov, vFov)
# Update scale
self.vFov.set(vFov, 0)
else:
# Just set horizontal
dr.setHfov(hFov)
[docs] def setVFov(self, vFov):
dr = self.activeDisplayRegion
if dr:
if self.lockedFov.get():
sf = vFov/dr.getVfov()
hFov = min(dr.getHfov() * sf, 170.0)
dr.setFov(hFov, vFov)
# Update scale
self.hFov.set(hFov, 0)
else:
# Just set horizontal
dr.setVfov(vFov)
[docs] def resetFov(self):
dr = self.activeDisplayRegion
if dr:
dr.setFov(45.0, 33.75)
self.hFov.set(45.0, 0)
self.vFov.set(33.75, 0)
# Lights #
[docs] def selectLightNamed(self, name):
# See if light exists
self.activeLight = base.direct.lights[name]
# If not...create new one
if self.activeLight == None:
self.activeLight = base.direct.lights.create(name)
# Do we have a valid light at this point?
if self.activeLight:
light = self.activeLight.getLight()
if isinstance(light, AmbientLight):
self.lightNotebook.selectpage('Ambient')
elif isinstance(light, DirectionalLight):
self.lightNotebook.selectpage('Directional')
elif isinstance(light, PointLight):
self.lightNotebook.selectpage('Point')
elif isinstance(light, Spotlight):
self.lightNotebook.selectpage('Spot')
else:
# Restore valid data
listbox = self.lightMenu.component('scrolledlist')
listbox.setlist(base.direct.lights.getNameList())
if len(base.direct.lights) > 0:
self.lightMenu.selectitem(base.direct.lights.getNameList()[0])
# Make sure info is current
self.updateLightInfo()
[docs] def addAmbient(self):
return base.direct.lights.create('ambient')
[docs] def addDirectional(self):
return base.direct.lights.create('directional')
[docs] def addPoint(self):
return base.direct.lights.create('point')
[docs] def addSpot(self):
return base.direct.lights.create('spot')
[docs] def addLight(self, light):
# Make list reflect current list of lights
listbox = self.lightMenu.component('scrolledlist')
listbox.setlist(base.direct.lights.getNameList())
# Select the newly added light
self.lightMenu.selectitem(light.getName())
# And show corresponding page
self.selectLightNamed(light.getName())
[docs] def toggleLights(self):
if self.enableLights.get():
base.direct.lights.allOn()
else:
base.direct.lights.allOff()
[docs] def toggleActiveLight(self):
if self.activeLight:
if self.lightActive.get():
base.direct.lights.setOn(self.activeLight)
else:
base.direct.lights.setOff(self.activeLight)
[docs] def setLightColor(self, color):
if self.activeLight:
self.activeLight.getLight().setColor(Vec4(color[0]/255.0,
color[1]/255.0,
color[2]/255.0,
color[3]/255.0))
[docs] def setSpecularColor(self, color):
if self.activeLight:
self.activeLight.getLight().setSpecularColor(Vec4(color[0]/255.0,
color[1]/255.0,
color[2]/255.0,
color[3]/255.0))
[docs] def setConstantAttenuation(self, value):
if self.activeLight:
self.activeLight.getLight().setConstantAttenuation(value)
[docs] def setLinearAttenuation(self, value):
if self.activeLight:
self.activeLight.getLight().setLinearAttenuation(value)
[docs] def setQuadraticAttenuation(self, value):
if self.activeLight:
self.activeLight.getLight().setQuadraticAttenuation(value)
[docs] def setExponent(self, value):
if self.activeLight:
self.activeLight.getLight().setExponent(value)
## GRID CONTROLS ##
[docs] def toggleGrid(self):
if self.enableGrid.get():
base.direct.grid.enable()
else:
base.direct.grid.disable()
[docs] def toggleXyzSnap(self):
base.direct.grid.setXyzSnap(self.xyzSnap.get())
[docs] def toggleHprSnap(self):
base.direct.grid.setHprSnap(self.hprSnap.get())
## DEVICE CONTROLS
[docs] def toggleJoybox(self):
if self.enableJoybox.get():
base.direct.joybox.enable()
else:
base.direct.joybox.disable()
## UPDATE INFO ##
[docs] def updateInfo(self, page = 'Environment'):
if page == 'Environment':
self.updateEnvironmentInfo()
elif page == 'Lights':
self.updateLightInfo()
elif page == 'Grid':
self.updateGridInfo()
[docs] def updateEnvironmentInfo(self):
bkgrdColor = base.getBackgroundColor() * 255.0
self.backgroundColor.set([bkgrdColor[0],
bkgrdColor[1],
bkgrdColor[2],
bkgrdColor[3]], 0)
self.updateDisplayRegionInfo()
[docs] def updateDisplayRegionInfo(self):
if self.activeDisplayRegion:
self.nearPlane.set(self.activeDisplayRegion.near, 0)
self.farPlane.set(self.activeDisplayRegion.far, 0)
self.hFov.set(self.activeDisplayRegion.fovH, 0)
self.vFov.set(self.activeDisplayRegion.fovV, 0)
[docs] def updateLightInfo(self, page = None):
# Set main lighting button
self.enableLights.set(
render.node().hasAttrib(LightAttrib.getClassType()))
# Set light specific info
if self.activeLight:
l = self.activeLight.getLight()
self.lightActive.set(render.hasLight(self.activeLight))
lightColor = l.getColor() * 255.0
self.lightColor.set([lightColor[0], lightColor[1],
lightColor[2], lightColor[3]], 0)
if isinstance(l, DirectionalLight):
specularColor = l.getSpecularColor() * 255.0
self.dSpecularColor.set([specularColor[0],
specularColor[1],
specularColor[2],
specularColor[3]], 0)
elif isinstance(l, PointLight):
specularColor = l.getSpecularColor() * 255.0
self.pSpecularColor.set([specularColor[0],
specularColor[1],
specularColor[2],
specularColor[3]], 0)
att = l.getAttenuation()
self.pConstantAttenuation.set(att[0], 0)
self.pLinearAttenuation.set(att[1], 0)
self.pQuadraticAttenuation.set(att[2], 0)
elif isinstance(l, Spotlight):
specularColor = l.getSpecularColor() * 255.0
self.sSpecularColor.set([specularColor[0],
specularColor[1],
specularColor[2],
specularColor[3]], 0)
att = l.getAttenuation()
self.pConstantAttenuation.set(att[0], 0)
self.pLinearAttenuation.set(att[1], 0)
self.pQuadraticAttenuation.set(att[2], 0)
[docs] def updateGridInfo(self):
self.enableGrid.set(base.direct.grid.isEnabled())
self.xyzSnap.set(base.direct.grid.getXyzSnap())
self.hprSnap.set(base.direct.grid.getHprSnap())
self.gridSpacing.set(base.direct.grid.getGridSpacing(), 0)
self.gridSize.set(base.direct.grid.getGridSize(), 0)
self.gridSnapAngle.set(base.direct.grid.getSnapAngle(), 0)
# UNDO/REDO
[docs] def pushUndo(self, fResetRedo = 1):
base.direct.pushUndo([self['nodePath']])
[docs] def undoHook(self, nodePathList = []):
pass
[docs] def pushUndoHook(self):
# Make sure button is reactivated
self.undoButton.configure(state = 'normal')
[docs] def undoListEmptyHook(self):
# Make sure button is deactivated
self.undoButton.configure(state = 'disabled')
[docs] def pushRedo(self):
base.direct.pushRedo([self['nodePath']])
[docs] def redoHook(self, nodePathList = []):
pass
[docs] def pushRedoHook(self):
# Make sure button is reactivated
self.redoButton.configure(state = 'normal')
[docs] def redoListEmptyHook(self):
# Make sure button is deactivated
self.redoButton.configure(state = 'disabled')
[docs] def onDestroy(self, event):
# Remove hooks
for event, method in self.actionEvents:
self.ignore(event)
# Destroy SGE hierarchy
self.SGE._node.destroy()