*** empty log message ***
This commit is contained in:
parent
862e472a19
commit
f361e4d922
|
|
@ -175,6 +175,9 @@ class DirectJoybox(PandaObject):
|
|||
self.enable()
|
||||
|
||||
def joyboxFly(self):
|
||||
# Do nothing if no nodePath selected
|
||||
if self.nodePath == None:
|
||||
return
|
||||
hprScale = (self.analogs.normalizeChannel(L_SLIDE, 0.1, 100) *
|
||||
DirectJoybox.hprMultiplier)
|
||||
posScale = (self.analogs.normalizeChannel(R_SLIDE, 0.1, 100) *
|
||||
|
|
@ -215,6 +218,12 @@ class DirectJoybox(PandaObject):
|
|||
self.modifier = [1,1,1,-1,1,0]
|
||||
self.setMode(self.joyboxFly, 'Look At Mode')
|
||||
|
||||
def lookAroundMode(self):
|
||||
self.mapping = [NULL_AXIS, NULL_AXIS, NULL_AXIS,
|
||||
R_LEFT_RIGHT, R_FWD_BACK, NULL_AXIS]
|
||||
self.modifier = [0,0,0,-1,-1,0]
|
||||
self.setMode(self.joyboxFly, 'Lookaround Mode')
|
||||
|
||||
def demoMode(self):
|
||||
self.mapping = [R_LEFT_RIGHT, R_FWD_BACK, L_FWD_BACK,
|
||||
R_TWIST, NULL_AXIS, NULL_AXIS]
|
||||
|
|
@ -227,12 +236,6 @@ class DirectJoybox(PandaObject):
|
|||
self.modifier = [1,1,-1,-1,-1,1]
|
||||
self.setMode(self.joyboxFly, 'HprXyz Mode')
|
||||
|
||||
def lookaroundMode(self):
|
||||
self.mapping = [NULL_AXIS, NULL_AXIS, NULL_AXIS,
|
||||
R_LEFT_RIGHT, R_FWD_BACK, NULL_AXIS]
|
||||
self.modifier = [0,0,0,-1,-1,0]
|
||||
self.setMode(self.joyboxFly, 'Lookaround Mode')
|
||||
|
||||
def walkthruMode(self):
|
||||
self.mapping = [R_LEFT_RIGHT, R_FWD_BACK, L_TWIST,
|
||||
R_TWIST, L_FWD_BACK, L_LEFT_RIGHT]
|
||||
|
|
@ -243,6 +246,9 @@ class DirectJoybox(PandaObject):
|
|||
self.setMode(self.orbitFly, 'Orbit Mode')
|
||||
|
||||
def orbitFly(self):
|
||||
# Do nothing if no nodePath selected
|
||||
if self.nodePath == None:
|
||||
return
|
||||
hprScale = (self.analogs.normalizeChannel(L_SLIDE, 0.1, 100) *
|
||||
DirectJoybox.hprMultiplier)
|
||||
posScale = (self.analogs.normalizeChannel(R_SLIDE, 0.1, 100) *
|
||||
|
|
|
|||
|
|
@ -380,9 +380,9 @@ class DirectBoundingBox:
|
|||
|
||||
|
||||
class SelectionRay:
|
||||
def __init__(self, camera):
|
||||
# Create a collision node path attached to the given camera
|
||||
self.rayCollisionNodePath = camera.attachNewNode( CollisionNode() )
|
||||
def __init__(self, parent):
|
||||
# Create a collision node path attached to the given parent
|
||||
self.rayCollisionNodePath = parent.attachNewNode( CollisionNode() )
|
||||
# Don't pay the penalty of drawing this collision ray
|
||||
self.rayCollisionNodePath.hide()
|
||||
self.rayCollisionNode = self.rayCollisionNodePath.node()
|
||||
|
|
@ -419,7 +419,7 @@ class SelectionRay:
|
|||
index = -1
|
||||
# Pick out the closest object that isn't a widget
|
||||
for i in range(0,numEntries):
|
||||
entry = direct.iRay.cq.getEntry(i)
|
||||
entry = self.cq.getEntry(i)
|
||||
node = entry.getIntoNode()
|
||||
# Don't pick hidden nodes
|
||||
if node.isHidden():
|
||||
|
|
@ -443,8 +443,8 @@ class SelectionRay:
|
|||
# Did we hit an object?
|
||||
if(index >= 0):
|
||||
# Yes!
|
||||
# Find hit point in camera's space
|
||||
hitPt = direct.iRay.camToHitPt(index)
|
||||
# Find hit point in parent's space
|
||||
hitPt = self.parentToHitPt(index)
|
||||
hitPtDist = Vec3(hitPt - ZERO_POINT).length()
|
||||
return (node, hitPt, hitPtDist)
|
||||
else:
|
||||
|
|
@ -460,11 +460,11 @@ class SelectionRay:
|
|||
# Yes!
|
||||
# Entry 0 is the closest hit point if multiple hits
|
||||
minPt = 0
|
||||
# Find hit point in camera's space
|
||||
hitPt = direct.iRay.camToHitPt(minPt)
|
||||
# Find hit point in parent's space
|
||||
hitPt = self.parentToHitPt(minPt)
|
||||
hitPtDist = Vec3(hitPt).length()
|
||||
# Get the associated collision queue object
|
||||
entry = direct.iRay.cq.getEntry(minPt)
|
||||
entry = self.cq.getEntry(minPt)
|
||||
# Extract the node
|
||||
node = entry.getIntoNode()
|
||||
# Return info
|
||||
|
|
@ -481,6 +481,55 @@ class SelectionRay:
|
|||
self.cq.sortEntries()
|
||||
return self.numEntries
|
||||
|
||||
def pickGeom3D(self, targetNodePath = render, origin = Point3(0),
|
||||
dir = Vec3(0,0,-1), fIntersectUnpickable = 0):
|
||||
self.collideWithGeom()
|
||||
numEntries = self.pick3D(targetNodePath, origin, dir)
|
||||
# Init index
|
||||
index = -1
|
||||
# Pick out the closest object that isn't a widget
|
||||
for i in range(0,numEntries):
|
||||
entry = self.cq.getEntry(i)
|
||||
node = entry.getIntoNode()
|
||||
# Don't pick hidden nodes
|
||||
if node.isHidden():
|
||||
pass
|
||||
# Can pick unpickable, use the first visible node
|
||||
elif fIntersectUnpickable:
|
||||
index = i
|
||||
break
|
||||
# Is it a named node?, If so, see if it has a name
|
||||
elif issubclass(node.__class__, NamedNode):
|
||||
name = node.getName()
|
||||
if name in self.unpickable:
|
||||
pass
|
||||
else:
|
||||
index = i
|
||||
break
|
||||
# Not hidden and not one of the widgets, use it
|
||||
else:
|
||||
index = i
|
||||
break
|
||||
# Did we hit an object?
|
||||
if(index >= 0):
|
||||
# Yes!
|
||||
# Find hit point in parent's space
|
||||
hitPt = self.parentToHitPt(index)
|
||||
hitPtDist = Vec3(hitPt - ZERO_POINT).length()
|
||||
return (node, hitPt, hitPtDist)
|
||||
else:
|
||||
return (None, ZERO_POINT, 0)
|
||||
|
||||
def pick3D(self, targetNodePath, origin, dir):
|
||||
# Determine ray direction based upon the mouse coordinates
|
||||
# Note! This has to be a cam object (of type ProjectionNode)
|
||||
self.ray.setOrigin( origin )
|
||||
self.ray.setDirection( dir )
|
||||
self.ct.traverse( targetNodePath.node() )
|
||||
self.numEntries = self.cq.getNumEntries()
|
||||
self.cq.sortEntries()
|
||||
return self.numEntries
|
||||
|
||||
def collideWithGeom(self):
|
||||
self.rayCollisionNode.setIntoCollideMask(BitMask32().allOff())
|
||||
self.rayCollisionNode.setFromCollideMask(BitMask32().allOff())
|
||||
|
|
@ -496,10 +545,10 @@ class SelectionRay:
|
|||
def objectToHitPt(self, index):
|
||||
return self.cq.getEntry(index).getIntoIntersectionPoint()
|
||||
|
||||
def camToHitPt(self, index):
|
||||
def parentToHitPt(self, index):
|
||||
# Get the specified entry
|
||||
entry = self.cq.getEntry(index)
|
||||
hitPt = entry.getIntoIntersectionPoint()
|
||||
# Convert point from object local space to camera space
|
||||
# Convert point from object local space to parent's space
|
||||
return entry.getInvWrtSpace().xformPoint(hitPt)
|
||||
|
||||
|
|
|
|||
|
|
@ -59,6 +59,8 @@ class DirectSession(PandaObject):
|
|||
if joybox:
|
||||
from DirectJoybox import *
|
||||
self.joybox = DirectJoybox(joybox)
|
||||
else:
|
||||
self.joybox = None
|
||||
else:
|
||||
self.deviceManager = None
|
||||
|
||||
|
|
|
|||
|
|
@ -59,6 +59,13 @@ class DirectSessionPanel(AppShell):
|
|||
self.nodePathDict['widget'] = 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'] = direct.widget
|
||||
self.jbNodePathDict['camera'] = direct.camera
|
||||
self.jbNodePathNames = ['camera', 'selected', 'none']
|
||||
|
||||
# Set up event hooks
|
||||
self.actionEvents = [('undo', self.undoHook),
|
||||
('pushUndo', self.pushUndoHook),
|
||||
|
|
@ -108,7 +115,7 @@ class DirectSessionPanel(AppShell):
|
|||
self.nodePathMenu.component('entryfield_entry'))
|
||||
self.nodePathMenuBG = (
|
||||
self.nodePathMenuEntry.configure('background')[3])
|
||||
self.nodePathMenu.pack(side = 'left', fill = 'x', expand = 1)
|
||||
self.nodePathMenu.pack(side = LEFT, fill = X, expand = 1)
|
||||
self.bind(self.nodePathMenu, 'Select node path to manipulate')
|
||||
|
||||
self.undoButton = Button(menuFrame, text = 'Undo',
|
||||
|
|
@ -117,7 +124,7 @@ class DirectSessionPanel(AppShell):
|
|||
self.undoButton['state'] = 'normal'
|
||||
else:
|
||||
self.undoButton['state'] = 'disabled'
|
||||
self.undoButton.pack(side = 'left', expand = 0)
|
||||
self.undoButton.pack(side = LEFT, expand = 0)
|
||||
self.bind(self.undoButton, 'Undo last operation')
|
||||
|
||||
self.redoButton = Button(menuFrame, text = 'Redo',
|
||||
|
|
@ -126,7 +133,7 @@ class DirectSessionPanel(AppShell):
|
|||
self.redoButton['state'] = 'normal'
|
||||
else:
|
||||
self.redoButton['state'] = 'disabled'
|
||||
self.redoButton.pack(side = 'left', expand = 0)
|
||||
self.redoButton.pack(side = LEFT, expand = 0)
|
||||
self.bind(self.redoButton, 'Redo last operation')
|
||||
|
||||
# The master frame for the dials
|
||||
|
|
@ -135,7 +142,7 @@ class DirectSessionPanel(AppShell):
|
|||
# Scene Graph Explorer
|
||||
sgeFrame = Frame(mainFrame)
|
||||
self.sgeUpdate = Button(sgeFrame, text = 'Update Explorer')
|
||||
self.sgeUpdate.pack(fill = 'x', expand = 0)
|
||||
self.sgeUpdate.pack(fill = X, expand = 0)
|
||||
self.SGE = SceneGraphExplorer.SceneGraphExplorer(
|
||||
sgeFrame, nodePath = render,
|
||||
scrolledCanvas_hull_width = 200,
|
||||
|
|
@ -149,8 +156,8 @@ class DirectSessionPanel(AppShell):
|
|||
notebook.pack(fill = BOTH, expand = 1)
|
||||
envPage = notebook.add('Environment')
|
||||
lightsPage = notebook.add('Lights')
|
||||
renderPage = notebook.add('Render Style')
|
||||
gridPage = notebook.add('Grid')
|
||||
devicePage = notebook.add('Devices')
|
||||
scenePage = notebook.add('Scene')
|
||||
# Put this here so it isn't called right away
|
||||
notebook['raisecommand'] = self.updateInfo
|
||||
|
|
@ -165,7 +172,7 @@ class DirectSessionPanel(AppShell):
|
|||
self.backgroundColor = VectorWidgets.ColorEntry(
|
||||
bkgrdFrame, text = 'Background Color')
|
||||
self.backgroundColor['command'] = self.setBackgroundColor
|
||||
self.backgroundColor.pack(fill = 'x', expand = 0)
|
||||
self.backgroundColor.pack(fill = X, expand = 0)
|
||||
self.bind(self.backgroundColor, 'Set background color')
|
||||
bkgrdFrame.pack(fill = BOTH, expand = 0)
|
||||
|
||||
|
|
@ -180,7 +187,7 @@ class DirectSessionPanel(AppShell):
|
|||
entry_width = 20,
|
||||
selectioncommand = self.selectDisplayRegionNamed,
|
||||
scrolledlist_items = nameList)
|
||||
self.drMenu.pack(fill = 'x', expand = 0)
|
||||
self.drMenu.pack(fill = X, expand = 0)
|
||||
self.bind(self.drMenu, 'Select display region to configure')
|
||||
|
||||
self.nearPlane = Floater.Floater(
|
||||
|
|
@ -188,7 +195,7 @@ class DirectSessionPanel(AppShell):
|
|||
text = 'Near Plane',
|
||||
min = 0.01)
|
||||
self.nearPlane['command'] = self.setNear
|
||||
self.nearPlane.pack(fill = 'x', expand = 0)
|
||||
self.nearPlane.pack(fill = X, expand = 0)
|
||||
self.bind(self.nearPlane, 'Set near plane distance')
|
||||
|
||||
self.farPlane = Floater.Floater(
|
||||
|
|
@ -196,36 +203,78 @@ class DirectSessionPanel(AppShell):
|
|||
text = 'Far Plane',
|
||||
min = 0.01)
|
||||
self.farPlane['command'] = self.setFar
|
||||
self.farPlane.pack(fill = 'x', expand = 0)
|
||||
self.farPlane.pack(fill = X, expand = 0)
|
||||
self.bind(self.farPlane, 'Set far plane distance')
|
||||
|
||||
self.hFov = Floater.Floater(
|
||||
drFrame,
|
||||
|
||||
fovFrame = Frame(drFrame)
|
||||
fovFloaterFrame = Frame(fovFrame)
|
||||
self.hFov = EntryScale.EntryScale(
|
||||
fovFloaterFrame,
|
||||
text = 'Horizontal FOV',
|
||||
min = 0.01, max = 179.9)
|
||||
min = 0.01, max = 170.0)
|
||||
self.hFov['command'] = self.setHFov
|
||||
self.hFov.pack(fill = 'x', expand = 0)
|
||||
self.hFov.pack(fill = X, expand = 0)
|
||||
self.bind(self.hFov, 'Set horizontal field of view')
|
||||
|
||||
self.vFov = Floater.Floater(
|
||||
drFrame,
|
||||
self.vFov = EntryScale.EntryScale(
|
||||
fovFloaterFrame,
|
||||
text = 'Vertical FOV',
|
||||
min = 0.01, max = 179.9)
|
||||
min = 0.01, max = 170.0)
|
||||
self.vFov['command'] = self.setVFov
|
||||
self.vFov.pack(fill = 'x', expand = 0)
|
||||
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(
|
||||
drFrame,
|
||||
text = 'FOV Locked',
|
||||
anchor = 'w', justify = 'left',
|
||||
frame,
|
||||
text = 'Locked',
|
||||
anchor = 'w', justify = LEFT,
|
||||
variable = self.lockedFov)
|
||||
self.lockedFovButton.pack(fill = 'x', expand = 0)
|
||||
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 = 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)
|
||||
|
||||
## Lights page ##
|
||||
# Lights #
|
||||
lightFrame = Frame(lightsPage, borderwidth = 2, relief = 'sunken')
|
||||
|
|
@ -258,15 +307,15 @@ class DirectSessionPanel(AppShell):
|
|||
# Main light switch
|
||||
mainSwitchFrame = Frame(lightFrame)
|
||||
Label(mainSwitchFrame,
|
||||
text = 'Lighting:').pack(side = 'left', expand = 0)
|
||||
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)
|
||||
self.enableLightsButton.pack(side = LEFT, fill = X, expand = 0)
|
||||
mainSwitchFrame.pack(fill = X, expand = 0)
|
||||
|
||||
# Widget to select a light to configure
|
||||
nameList = direct.lights.nameList
|
||||
|
|
@ -277,7 +326,7 @@ class DirectSessionPanel(AppShell):
|
|||
entry_width = 20,
|
||||
selectioncommand = self.selectLightNamed,
|
||||
scrolledlist_items = nameList)
|
||||
self.lightMenu.pack(side = 'left', fill = 'x', expand = 0)
|
||||
self.lightMenu.pack(side = LEFT, fill = X, expand = 0)
|
||||
self.bind(self.lightMenu, 'Select light to configure')
|
||||
|
||||
self.lightActive = BooleanVar()
|
||||
|
|
@ -286,22 +335,22 @@ class DirectSessionPanel(AppShell):
|
|||
text = 'On/Off',
|
||||
variable = self.lightActive,
|
||||
command = self.toggleActiveLight)
|
||||
self.lightActiveButton.pack(side = 'left', fill = 'x', expand = 0)
|
||||
self.lightActiveButton.pack(side = LEFT, fill = X, expand = 0)
|
||||
|
||||
# Pack light menu
|
||||
lightMenuFrame.pack(fill = 'x', expand = 0, padx = 2)
|
||||
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.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.dSpecularColor.pack(fill = X, expand = 0)
|
||||
self.bind(self.dSpecularColor,
|
||||
'Set directional light specular color')
|
||||
|
||||
|
|
@ -309,7 +358,7 @@ class DirectSessionPanel(AppShell):
|
|||
self.pSpecularColor = VectorWidgets.ColorEntry(
|
||||
pointPage, text = 'Specular Color')
|
||||
self.pSpecularColor['command'] = self.setSpecularColor
|
||||
self.pSpecularColor.pack(fill = 'x', expand = 0)
|
||||
self.pSpecularColor.pack(fill = X, expand = 0)
|
||||
self.bind(self.pSpecularColor,
|
||||
'Set point light specular color')
|
||||
|
||||
|
|
@ -318,7 +367,7 @@ class DirectSessionPanel(AppShell):
|
|||
text = 'Constant Attenuation',
|
||||
min = 0.0, max = 1.0, initialValue = 1.0)
|
||||
self.pConstantAttenuation['command'] = self.setConstantAttenuation
|
||||
self.pConstantAttenuation.pack(fill = 'x', expand = 0)
|
||||
self.pConstantAttenuation.pack(fill = X, expand = 0)
|
||||
self.bind(self.pConstantAttenuation,
|
||||
'Set point light constant attenuation')
|
||||
|
||||
|
|
@ -327,7 +376,7 @@ class DirectSessionPanel(AppShell):
|
|||
text = 'Linear Attenuation',
|
||||
min = 0.0, max = 1.0, initialValue = 0.0)
|
||||
self.pLinearAttenuation['command'] = self.setLinearAttenuation
|
||||
self.pLinearAttenuation.pack(fill = 'x', expand = 0)
|
||||
self.pLinearAttenuation.pack(fill = X, expand = 0)
|
||||
self.bind(self.pLinearAttenuation,
|
||||
'Set point light linear attenuation')
|
||||
|
||||
|
|
@ -336,7 +385,7 @@ class DirectSessionPanel(AppShell):
|
|||
text = 'Quadratic Attenuation',
|
||||
min = 0.0, max = 1.0, initialValue = 0.0)
|
||||
self.pQuadraticAttenuation['command'] = self.setQuadraticAttenuation
|
||||
self.pQuadraticAttenuation.pack(fill = 'x', expand = 0)
|
||||
self.pQuadraticAttenuation.pack(fill = X, expand = 0)
|
||||
self.bind(self.pQuadraticAttenuation,
|
||||
'Set point light quadratic attenuation')
|
||||
|
||||
|
|
@ -344,7 +393,7 @@ class DirectSessionPanel(AppShell):
|
|||
self.sSpecularColor = VectorWidgets.ColorEntry(
|
||||
spotPage, text = 'Specular Color')
|
||||
self.sSpecularColor['command'] = self.setSpecularColor
|
||||
self.sSpecularColor.pack(fill = 'x', expand = 0)
|
||||
self.sSpecularColor.pack(fill = X, expand = 0)
|
||||
self.bind(self.sSpecularColor,
|
||||
'Set spot light specular color')
|
||||
|
||||
|
|
@ -353,7 +402,7 @@ class DirectSessionPanel(AppShell):
|
|||
text = 'Constant Attenuation',
|
||||
min = 0.0, max = 1.0, initialValue = 1.0)
|
||||
self.sConstantAttenuation['command'] = self.setConstantAttenuation
|
||||
self.sConstantAttenuation.pack(fill = 'x', expand = 0)
|
||||
self.sConstantAttenuation.pack(fill = X, expand = 0)
|
||||
self.bind(self.sConstantAttenuation,
|
||||
'Set spot light constant attenuation')
|
||||
|
||||
|
|
@ -362,7 +411,7 @@ class DirectSessionPanel(AppShell):
|
|||
text = 'Linear Attenuation',
|
||||
min = 0.0, max = 1.0, initialValue = 0.0)
|
||||
self.sLinearAttenuation['command'] = self.setLinearAttenuation
|
||||
self.sLinearAttenuation.pack(fill = 'x', expand = 0)
|
||||
self.sLinearAttenuation.pack(fill = X, expand = 0)
|
||||
self.bind(self.sLinearAttenuation,
|
||||
'Set spot light linear attenuation')
|
||||
|
||||
|
|
@ -371,7 +420,7 @@ class DirectSessionPanel(AppShell):
|
|||
text = 'Quadratic Attenuation',
|
||||
min = 0.0, max = 1.0, initialValue = 0.0)
|
||||
self.sQuadraticAttenuation['command'] = self.setQuadraticAttenuation
|
||||
self.sQuadraticAttenuation.pack(fill = 'x', expand = 0)
|
||||
self.sQuadraticAttenuation.pack(fill = X, expand = 0)
|
||||
self.bind(self.sQuadraticAttenuation,
|
||||
'Set spot light quadratic attenuation')
|
||||
|
||||
|
|
@ -380,7 +429,7 @@ class DirectSessionPanel(AppShell):
|
|||
text = 'Exponent',
|
||||
min = 0.0, max = 1.0, initialValue = 0.0)
|
||||
self.sExponent['command'] = self.setExponent
|
||||
self.sExponent.pack(fill = 'x', expand = 0)
|
||||
self.sExponent.pack(fill = X, expand = 0)
|
||||
self.bind(self.sExponent,
|
||||
'Set spot light exponent')
|
||||
|
||||
|
|
@ -391,33 +440,6 @@ class DirectSessionPanel(AppShell):
|
|||
|
||||
lightFrame.pack(expand = 1, fill = BOTH)
|
||||
|
||||
## Render Style ##
|
||||
toggleFrame = Frame(renderPage)
|
||||
self.toggleBackfaceButton = Button(
|
||||
toggleFrame,
|
||||
text = 'Toggle backface',
|
||||
command = base.toggleBackface)
|
||||
self.toggleBackfaceButton.pack(fill = 'x', expand = 0)
|
||||
|
||||
self.toggleLightsButton = Button(
|
||||
toggleFrame,
|
||||
text = 'Toggle lights',
|
||||
command = direct.lights.toggle)
|
||||
self.toggleLightsButton.pack(fill = 'x', expand = 0)
|
||||
|
||||
self.toggleTextureButton = Button(
|
||||
toggleFrame,
|
||||
text = 'Toggle texture',
|
||||
command = base.toggleTexture)
|
||||
self.toggleTextureButton.pack(fill = 'x', expand = 0)
|
||||
|
||||
self.toggleWireframeButton = Button(
|
||||
toggleFrame,
|
||||
text = 'Toggle wireframe',
|
||||
command = base.toggleWireframe)
|
||||
self.toggleWireframeButton.pack(fill = 'x', expand = 0)
|
||||
toggleFrame.pack(fill = BOTH, expand = 0)
|
||||
|
||||
## GRID PAGE ##
|
||||
Label(gridPage, text = 'Grid',
|
||||
font=('MSSansSerif', 14, 'bold')).pack(expand = 0)
|
||||
|
|
@ -425,28 +447,28 @@ class DirectSessionPanel(AppShell):
|
|||
self.enableGridButton = Checkbutton(
|
||||
gridPage,
|
||||
text = 'Enabled/Disabled',
|
||||
anchor = 'w', justify = 'left',
|
||||
anchor = 'w', justify = LEFT,
|
||||
variable = self.enableGrid,
|
||||
command = self.toggleGrid)
|
||||
self.enableGridButton.pack(fill = 'x', expand = 0)
|
||||
self.enableGridButton.pack(fill = X, expand = 0)
|
||||
|
||||
self.xyzSnap = BooleanVar()
|
||||
self.xyzSnapButton = Checkbutton(
|
||||
gridPage,
|
||||
text = 'XYZ Snap',
|
||||
anchor = 'w', justify = 'left',
|
||||
anchor = 'w', justify = LEFT,
|
||||
variable = self.xyzSnap,
|
||||
command = self.toggleXyzSnap)
|
||||
self.xyzSnapButton.pack(fill = 'x', expand = 0)
|
||||
self.xyzSnapButton.pack(fill = X, expand = 0)
|
||||
|
||||
self.hprSnap = BooleanVar()
|
||||
self.hprSnapButton = Checkbutton(
|
||||
gridPage,
|
||||
text = 'HPR Snap',
|
||||
anchor = 'w', justify = 'left',
|
||||
anchor = 'w', justify = LEFT,
|
||||
variable = self.hprSnap,
|
||||
command = self.toggleHprSnap)
|
||||
self.hprSnapButton.pack(fill = 'x', expand = 0)
|
||||
self.hprSnapButton.pack(fill = X, expand = 0)
|
||||
|
||||
self.gridSpacing = Floater.Floater(
|
||||
gridPage,
|
||||
|
|
@ -454,7 +476,7 @@ class DirectSessionPanel(AppShell):
|
|||
min = 0.1,
|
||||
initialValue = direct.grid.getGridSpacing())
|
||||
self.gridSpacing['command'] = direct.grid.setGridSpacing
|
||||
self.gridSpacing.pack(fill = 'x', expand = 0)
|
||||
self.gridSpacing.pack(fill = X, expand = 0)
|
||||
|
||||
self.gridSize = Floater.Floater(
|
||||
gridPage,
|
||||
|
|
@ -462,7 +484,7 @@ class DirectSessionPanel(AppShell):
|
|||
min = 1.0,
|
||||
initialValue = direct.grid.getGridSize())
|
||||
self.gridSize['command'] = direct.grid.setGridSize
|
||||
self.gridSize.pack(fill = 'x', expand = 0)
|
||||
self.gridSize.pack(fill = X, expand = 0)
|
||||
|
||||
self.gridSnapAngle = Dial.Dial(
|
||||
gridPage,
|
||||
|
|
@ -472,8 +494,75 @@ class DirectSessionPanel(AppShell):
|
|||
fRollover = 0,
|
||||
initialValue = direct.grid.getSnapAngle())
|
||||
self.gridSnapAngle['command'] = direct.grid.setSnapAngle
|
||||
self.gridSnapAngle.pack(fill = 'x', expand = 0)
|
||||
|
||||
self.gridSnapAngle.pack(fill = X, expand = 0)
|
||||
|
||||
## DEVICE PAGE ##
|
||||
Label(devicePage, text = 'DEVICES',
|
||||
font=('MSSansSerif', 14, 'bold')).pack(expand = 0)
|
||||
|
||||
if 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 = EntryScale.EntryScale(
|
||||
joyboxFrame,
|
||||
text = 'XYZ Scale Factor',
|
||||
initialValue = 1.0,
|
||||
hull_relief = RIDGE, hull_borderwidth = 2,
|
||||
min = 1.0, max = 100.0)
|
||||
self.jbXyzSF['command'] = (
|
||||
lambda v: direct.joybox.setXyzMultiplier(v))
|
||||
self.jbXyzSF.pack(fill = X, expand = 0)
|
||||
self.bind(self.jbXyzSF, 'Set joybox XYZ speed multiplier')
|
||||
|
||||
self.jbHprSF = EntryScale.EntryScale(
|
||||
joyboxFrame,
|
||||
text = 'HPR Scale Factor',
|
||||
initialValue = 1.0,
|
||||
hull_relief = RIDGE, hull_borderwidth = 2,
|
||||
min = 1.0, max = 100.0)
|
||||
self.jbHprSF['command'] = (
|
||||
lambda v: direct.joybox.setHprMultiplier(v))
|
||||
self.jbHprSF.pack(fill = X, expand = 0)
|
||||
self.bind(self.jbHprSF, 'Set joybox HPR speed multiplier')
|
||||
|
||||
|
||||
notebook.setnaturalsize()
|
||||
|
||||
mainFrame.pack(fill = 'both', expand = 1)
|
||||
|
|
@ -546,6 +635,59 @@ class DirectSessionPanel(AppShell):
|
|||
self.addNodePathToDict(nodePath, self.nodePathNames,
|
||||
self.nodePathMenu, self.nodePathDict)
|
||||
|
||||
def selectJBModeNamed(self, name):
|
||||
if name == 'Joe Mode':
|
||||
direct.joybox.joeMode()
|
||||
elif name == 'Drive Mode':
|
||||
direct.joybox.driveMode()
|
||||
elif name == 'Orbit Mode':
|
||||
direct.joybox.orbitMode()
|
||||
elif name == 'Look At Mode':
|
||||
direct.joybox.lookAtMode()
|
||||
elif name == 'Look Around Mode':
|
||||
direct.joybox.lookAroundMode()
|
||||
elif name == 'Walkthru Mode':
|
||||
direct.joybox.walkthruMode()
|
||||
elif name == 'Demo Mode':
|
||||
direct.joybox.demoMode()
|
||||
elif name == 'HPRXYZ Mode':
|
||||
direct.joybox.hprXyzMode()
|
||||
|
||||
def selectJBNodePathNamed(self, name):
|
||||
if name == 'selected':
|
||||
nodePath = 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'):
|
||||
direct.joybox.setNodePath(None)
|
||||
else:
|
||||
direct.joybox.setNodePath(nodePath)
|
||||
|
||||
def addJBNodePath(self, nodePath):
|
||||
self.addNodePathToDict(nodePath, self.jbNodePathNames,
|
||||
self.jbNodePathMenu, self.jbNodePathDict)
|
||||
|
||||
def addNodePathToDict(self, nodePath, names, menu, dict):
|
||||
if not nodePath:
|
||||
return
|
||||
|
|
@ -598,7 +740,7 @@ class DirectSessionPanel(AppShell):
|
|||
if dr:
|
||||
if self.lockedFov.get():
|
||||
sf = hFov/dr.camNode.getHfov()
|
||||
vFov = dr.camNode.getVfov() * sf
|
||||
vFov = min(dr.camNode.getVfov() * sf, 170.0)
|
||||
dr.camNode.setFov(hFov, vFov)
|
||||
# Update scale
|
||||
self.vFov.set(vFov, 0)
|
||||
|
|
@ -611,7 +753,7 @@ class DirectSessionPanel(AppShell):
|
|||
if dr:
|
||||
if self.lockedFov.get():
|
||||
sf = vFov/dr.camNode.getVfov()
|
||||
hFov = dr.camNode.getHfov() * sf
|
||||
hFov = min(dr.camNode.getHfov() * sf, 170.0)
|
||||
dr.camNode.setFov(hFov, vFov)
|
||||
# Update scale
|
||||
self.hFov.set(hFov, 0)
|
||||
|
|
@ -619,6 +761,13 @@ class DirectSessionPanel(AppShell):
|
|||
# Just set horizontal
|
||||
dr.camNode.setVfov(vFov)
|
||||
|
||||
def resetFov(self):
|
||||
dr = self.activeDisplayRegion
|
||||
if dr:
|
||||
dr.camNode.setFov(45.0, 33.75)
|
||||
self.hFov.set(45.0, 0)
|
||||
self.vFov.set(33.75, 0)
|
||||
|
||||
# Lights #
|
||||
def selectLightNamed(self, name):
|
||||
self.activeLight = None
|
||||
|
|
@ -723,6 +872,13 @@ class DirectSessionPanel(AppShell):
|
|||
def toggleHprSnap(self):
|
||||
direct.grid.setHprSnap(self.hprSnap.get())
|
||||
|
||||
## DEVICE CONTROLS
|
||||
def toggleJoybox(self):
|
||||
if self.enableJoybox.get():
|
||||
direct.joybox.enable()
|
||||
else:
|
||||
direct.joybox.disable()
|
||||
|
||||
## UPDATE INFO ##
|
||||
def updateInfo(self, page = 'Environment'):
|
||||
if page == 'Environment':
|
||||
|
|
|
|||
|
|
@ -5,36 +5,28 @@ from PandaObject import *
|
|||
from Tkinter import *
|
||||
from AppShell import *
|
||||
from DirectGeometry import *
|
||||
from DirectSelection import *
|
||||
from tkFileDialog import *
|
||||
import os
|
||||
import Pmw
|
||||
import Dial
|
||||
import Floater
|
||||
import EntryScale
|
||||
import VectorWidgets
|
||||
import __builtin__
|
||||
|
||||
"""
|
||||
To Add
|
||||
Num Segs lines between knots
|
||||
Num Ticks
|
||||
setCvColor <function setCvColor at 01BADDCC>
|
||||
setColor <function setColor at 01B7B09C>
|
||||
setHullColor <function setHullColor at 01BADA7C>
|
||||
setKnotColor <function setKnotColor at 01BADA1C>
|
||||
setShowCvs <function setShowCvs at 01BAD9BC>
|
||||
setShowHull <function setShowHull at 01BAD8FC>
|
||||
setShowKnots <function setShowKnots at 01BADB0C>
|
||||
setNumSegs <function setNumSegs at 01B7B42C>
|
||||
setNumTicks <function setNumTicks at 01B7B15C>
|
||||
setTickColor <function setTickColor at 01B7B03C>
|
||||
setTickScale <function setTickScale at 01B7CF6C>
|
||||
"""
|
||||
PRF_UTILITIES = [
|
||||
'lambda: direct.camera.lookAt(render)',
|
||||
'lambda: direct.camera.setZ(render, 0.0)',
|
||||
'lambda s = self: s.playbackMarker.lookAt(render)',
|
||||
'lambda s = self: s.playbackMarker.setZ(render, 0.0)',
|
||||
'lambda s = self: s.followTerrain(10.0)']
|
||||
|
||||
class MopathRecorder(AppShell, PandaObject):
|
||||
# Override class variables here
|
||||
appname = 'Mopath Recorder Panel'
|
||||
frameWidth = 450
|
||||
frameHeight = 510
|
||||
frameHeight = 535
|
||||
usecommandarea = 0
|
||||
usestatusarea = 0
|
||||
count = 0
|
||||
|
|
@ -67,8 +59,6 @@ class MopathRecorder(AppShell, PandaObject):
|
|||
self.recorderNodePath = direct.group.attachNewNode(self.name)
|
||||
self.tempCS = self.recorderNodePath.attachNewNode(
|
||||
'mopathRecorderTempCS')
|
||||
self.editCS = self.recorderNodePath.attachNewNode(
|
||||
'mopathRecorderEditCS')
|
||||
self.playbackMarker = loader.loadModel('models/directmodels/smiley')
|
||||
self.playbackMarker.reparentTo(self.recorderNodePath)
|
||||
self.playbackMarker.hide()
|
||||
|
|
@ -95,14 +85,12 @@ class MopathRecorder(AppShell, PandaObject):
|
|||
self.recNodePathDict['camera'] = direct.camera
|
||||
self.recNodePathDict['widget'] = direct.widget
|
||||
self.recNodePathDict['mopathRecorderTempCS'] = self.tempCS
|
||||
self.recNodePathDict['edit CS'] = self.editCS
|
||||
self.recNodePathNames = ['marker', 'camera', 'selected']
|
||||
self.pbNodePathDict = {}
|
||||
self.pbNodePathDict['marker'] = self.playbackMarker
|
||||
self.pbNodePathDict['camera'] = direct.camera
|
||||
self.pbNodePathDict['widget'] = direct.widget
|
||||
self.pbNodePathDict['mopathRecorderTempCS'] = self.tempCS
|
||||
self.pbNodePathDict['edit CS'] = self.editCS
|
||||
self.pbNodePathNames = ['marker', 'camera', 'selected']
|
||||
# Count of point sets recorded
|
||||
self.pointSet = []
|
||||
|
|
@ -112,6 +100,7 @@ class MopathRecorder(AppShell, PandaObject):
|
|||
self.pointSetCount = 0
|
||||
self.pointSetName = self.name + '-ps-' + `self.pointSetCount`
|
||||
# User callback to call before recording point
|
||||
self.samplingMode = 'Continuous'
|
||||
self.preRecordFunc = None
|
||||
# Hook to start/stop recording
|
||||
self.startStopHook = 'f6'
|
||||
|
|
@ -125,7 +114,7 @@ class MopathRecorder(AppShell, PandaObject):
|
|||
self.numTicks = 1
|
||||
# Number of segments to represent each parametric unit
|
||||
# This just affects the visual appearance of the curve
|
||||
self.numSegs = 20
|
||||
self.numSegs = 40
|
||||
# The nurbs curves
|
||||
self.xyzNurbsCurve = None
|
||||
self.hprNurbsCurve = None
|
||||
|
|
@ -152,6 +141,10 @@ class MopathRecorder(AppShell, PandaObject):
|
|||
self.cropFrom = 0.0
|
||||
self.cropTo = 0.0
|
||||
self.fAdjustingValues = 0
|
||||
# For terrain following
|
||||
self.iRayCS = self.recorderNodePath.attachNewNode(
|
||||
'mopathRecorderIRayCS')
|
||||
self.iRay = SelectionRay(self.iRayCS)
|
||||
# Set up event hooks
|
||||
self.actionEvents = [
|
||||
('undo', self.undoHook),
|
||||
|
|
@ -194,52 +187,6 @@ class MopathRecorder(AppShell, PandaObject):
|
|||
'Save current curve as a new point set',
|
||||
label = 'Save Point Set',
|
||||
command = self.savePointSet)
|
||||
self.menuBar.addcascademenu(
|
||||
'Recorder', 'Show/Hide',
|
||||
statusHelp = 'Show/Hide Mopath Recorder Objects',
|
||||
tearoff = 1)
|
||||
self.pathVis = BooleanVar()
|
||||
self.pathVis.set(1)
|
||||
self.menuBar.addmenuitem('Show/Hide', 'checkbutton',
|
||||
'Toggle Path Visability',
|
||||
label = 'Toggle Path Vis',
|
||||
variable = self.pathVis,
|
||||
command = self.setPathVis)
|
||||
self.hullVis = BooleanVar()
|
||||
self.hullVis.set(0)
|
||||
self.menuBar.addmenuitem('Show/Hide', 'checkbutton',
|
||||
'Toggle Hull Visability',
|
||||
label = 'Toggle Hull Vis',
|
||||
variable = self.hullVis,
|
||||
command = self.setHullVis)
|
||||
self.cvVis = BooleanVar()
|
||||
self.cvVis.set(0)
|
||||
self.menuBar.addmenuitem('Show/Hide', 'checkbutton',
|
||||
'Toggle CV Visability',
|
||||
label = 'Toggle CV Vis',
|
||||
variable = self.cvVis,
|
||||
command = self.setCvVis)
|
||||
self.knotVis = BooleanVar()
|
||||
self.knotVis.set(1)
|
||||
self.menuBar.addmenuitem('Show/Hide', 'checkbutton',
|
||||
'Toggle Knot Visability',
|
||||
label = 'Toggle Knot Vis',
|
||||
variable = self.knotVis,
|
||||
command = self.setKnotVis)
|
||||
self.tickVis = BooleanVar()
|
||||
self.tickVis.set(0)
|
||||
self.menuBar.addmenuitem('Show/Hide', 'checkbutton',
|
||||
'Toggle Tick Visability',
|
||||
label = 'Toggle Tick Vis',
|
||||
variable = self.tickVis,
|
||||
command = self.setTickVis)
|
||||
self.markerVis = BooleanVar()
|
||||
self.markerVis.set(1)
|
||||
self.menuBar.addmenuitem('Show/Hide', 'checkbutton',
|
||||
'Toggle Marker Visability',
|
||||
label = 'Toggle Marker Vis',
|
||||
variable = self.markerVis,
|
||||
command = self.setMarkerVis)
|
||||
self.menuBar.addmenuitem(
|
||||
'Recorder', 'command',
|
||||
'Toggle widget visability',
|
||||
|
|
@ -281,6 +228,10 @@ class MopathRecorder(AppShell, PandaObject):
|
|||
side = LEFT, fill = BOTH, expand = 1)
|
||||
widget.configure(foreground = 'Red', relief = RAISED, borderwidth = 2,
|
||||
anchor = CENTER, width = 16)
|
||||
widget = self.createButton(frame, 'Recording', 'Add Keyframe',
|
||||
'Add Keyframe To Current Path',
|
||||
self.addKeyframe,
|
||||
side = LEFT, expand = 1)
|
||||
self.recordingType = StringVar()
|
||||
self.recordingType.set('New Curve')
|
||||
widget = self.createRadiobutton(
|
||||
|
|
@ -381,6 +332,7 @@ class MopathRecorder(AppShell, PandaObject):
|
|||
self.refinePage = self.mainNotebook.add('Refine')
|
||||
self.extendPage = self.mainNotebook.add('Extend')
|
||||
self.cropPage = self.mainNotebook.add('Crop')
|
||||
self.stylePage = self.mainNotebook.add('Style')
|
||||
|
||||
## RECORD PAGE ##
|
||||
recordFrame = Frame(self.recordPage, relief = SUNKEN,
|
||||
|
|
@ -427,44 +379,18 @@ class MopathRecorder(AppShell, PandaObject):
|
|||
frame.pack(expand = 1, fill = X)
|
||||
# PreRecordFunc
|
||||
frame = Frame(recordFrame)
|
||||
widget = self.createLabeledEntry(
|
||||
widget = self.createComboBox(
|
||||
frame, 'Recording', 'Pre-Record Func',
|
||||
'Function called before recording each point',
|
||||
command = self.setPreRecordFunc)[0]
|
||||
label = self.getWidget('Recording', 'Pre-Record Func-Label')
|
||||
label.configure(width = 16, anchor = W)
|
||||
'Function called before sampling each point',
|
||||
PRF_UTILITIES, self.setPreRecordFunc,
|
||||
history = 1, expand = 1)
|
||||
widget.configure(label_width = 16, label_anchor = W)
|
||||
widget.configure(entryfield_entry_state = 'normal')
|
||||
self.createCheckbutton(frame, 'Recording', 'PRF Active',
|
||||
'On: Pre Record Func enabled',
|
||||
None, 0,
|
||||
side = LEFT, fill = BOTH, expand = 0)
|
||||
frame.pack(expand = 1, fill = X)
|
||||
|
||||
# Record type
|
||||
frame = Frame(recordFrame)
|
||||
self.samplingMode = StringVar()
|
||||
self.samplingMode.set('Continuous')
|
||||
widget = self.createRadiobutton(
|
||||
frame, 'left',
|
||||
'Recording', 'Continuous Sampling',
|
||||
('New point added to curve fitter every frame'),
|
||||
self.samplingMode, 'Continuous', self.setSamplingMode,
|
||||
expand = 1)
|
||||
widget['anchor'] = 'center'
|
||||
widget = self.createRadiobutton(
|
||||
frame, 'left',
|
||||
'Recording', 'Keyframe Sampling',
|
||||
('Add new point to curve fitter by pressing keyframe button'),
|
||||
self.samplingMode, 'Keyframe', self.setSamplingMode,
|
||||
expand = 1)
|
||||
widget['anchor'] = 'center'
|
||||
frame.pack(expand = 1, fill = X)
|
||||
|
||||
widget = self.createButton(recordFrame, 'Recording', 'Add Key Frame',
|
||||
'Add Keyframe To Current Path',
|
||||
self.addKeyframe,
|
||||
side = LEFT, expand = 1)
|
||||
widget.configure(state = 'disabled')
|
||||
|
||||
# Pack record frame
|
||||
recordFrame.pack(fill = X, pady = 2)
|
||||
|
||||
|
|
@ -497,7 +423,7 @@ class MopathRecorder(AppShell, PandaObject):
|
|||
font=('MSSansSerif', 12, 'bold')).pack()
|
||||
widget = self.createEntryScale(
|
||||
desampleFrame, 'Resample', 'Points Between Samples',
|
||||
'Recompute curve using every nth point',
|
||||
'Specify number of points to skip between samples',
|
||||
min = 1, max = 100, resolution = 1,
|
||||
command = self.setDesampleFrequency)
|
||||
widget.component('hull')['relief'] = RIDGE
|
||||
|
|
@ -516,6 +442,7 @@ class MopathRecorder(AppShell, PandaObject):
|
|||
'Begin time of refine pass',
|
||||
resolution = 0.01,
|
||||
command = self.setRecordStart)
|
||||
widget.onPress = self.setRefineMode
|
||||
widget.onRelease = widget.onReturnRelease = (
|
||||
lambda s = self: s.getPrePoints('Refine'))
|
||||
widget = self.createEntryScale(
|
||||
|
|
@ -524,18 +451,19 @@ class MopathRecorder(AppShell, PandaObject):
|
|||
'Time when full control of node path is given during refine pass',
|
||||
resolution = 0.01,
|
||||
command = self.setControlStart)
|
||||
widget.onRelease = widget.onReturnRelease = self.setRefineMode
|
||||
widget.onPress = widget.onReturn = self.setRefineMode
|
||||
widget = self.createEntryScale(
|
||||
refineFrame, 'Refine Page',
|
||||
'Control Stop',
|
||||
'Time when node path begins transition back to original curve',
|
||||
resolution = 0.01,
|
||||
command = self.setControlStop)
|
||||
widget.onRelease = widget.onReturnRelease = self.setRefineMode
|
||||
widget.onPress = widget.onReturn = self.setRefineMode
|
||||
widget = self.createEntryScale(refineFrame, 'Refine Page', 'Refine To',
|
||||
'Stop time of refine pass',
|
||||
resolution = 0.01,
|
||||
command = self.setRefineStop)
|
||||
widget.onPress = self.setRefineMode
|
||||
widget.onRelease = widget.onReturnRelease = self.getPostPoints
|
||||
refineFrame.pack(fill = X)
|
||||
|
||||
|
|
@ -551,6 +479,7 @@ class MopathRecorder(AppShell, PandaObject):
|
|||
'Begin time of extend pass',
|
||||
resolution = 0.01,
|
||||
command = self.setRecordStart)
|
||||
widget.onPress = self.setExtendMode
|
||||
widget.onRelease = widget.onReturnRelease = (
|
||||
lambda s = self: s.getPrePoints('Extend'))
|
||||
widget = self.createEntryScale(
|
||||
|
|
@ -559,7 +488,7 @@ class MopathRecorder(AppShell, PandaObject):
|
|||
'Time when full control of node path is given during extend pass',
|
||||
resolution = 0.01,
|
||||
command = self.setControlStart)
|
||||
widget.onRelease = widget.onReturnRelease = self.setExtendMode
|
||||
widget.onPress = widget.onReturn = self.setExtendMode
|
||||
extendFrame.pack(fill = X)
|
||||
|
||||
## CROP PAGE ##
|
||||
|
|
@ -588,6 +517,88 @@ class MopathRecorder(AppShell, PandaObject):
|
|||
self.cropCurve, fill = NONE)
|
||||
cropFrame.pack(fill = X)
|
||||
|
||||
## STYLE PAGE ##
|
||||
styleFrame = Frame(self.stylePage, relief = SUNKEN,
|
||||
borderwidth = 2)
|
||||
label = Label(styleFrame, text = 'CURVE RENDERINNG STYLE',
|
||||
font=('MSSansSerif', 12, 'bold'))
|
||||
label.pack(fill = X)
|
||||
|
||||
self.sf = Pmw.ScrolledFrame(styleFrame, horizflex = 'elastic')
|
||||
self.sf.pack(fill = 'both', expand = 1)
|
||||
sfFrame = self.sf.interior()
|
||||
frame = Frame(sfFrame)
|
||||
widget = self.createCheckbutton(
|
||||
frame, 'Style', 'Show Path',
|
||||
'On: path is visible', self.setPathVis, 1,
|
||||
side = LEFT, fill = X, expand = 1)
|
||||
widget = self.createCheckbutton(
|
||||
frame, 'Style', 'Show Knots',
|
||||
'On: path knots are visible', self.setKnotVis, 1,
|
||||
side = LEFT, fill = X, expand = 1)
|
||||
widget = self.createCheckbutton(
|
||||
frame, 'Style', 'Show CVs',
|
||||
'On: path CVs are visible', self.setCvVis, 0,
|
||||
side = LEFT, fill = X, expand = 1)
|
||||
widget = self.createCheckbutton(
|
||||
frame, 'Style', 'Show Hull',
|
||||
'On: path hull is visible', self.setHullVis, 0,
|
||||
side = LEFT, fill = X, expand = 1)
|
||||
widget = self.createCheckbutton(
|
||||
frame, 'Style', 'Show Marker',
|
||||
'On: playback marker is visible', self.setMarkerVis, 0,
|
||||
side = LEFT, fill = X, expand = 1)
|
||||
frame.pack(fill = X, expand = 1)
|
||||
# Sliders
|
||||
widget = self.createEntryScale(
|
||||
sfFrame, 'Style', 'Num Segs',
|
||||
'Set number of segments used to approximate each parametric unit',
|
||||
min = 1.0, max = 400, resolution = 1.0,
|
||||
initialValue = 40,
|
||||
command = self.setNumSegs, side = TOP)
|
||||
widget.component('hull')['relief'] = RIDGE
|
||||
widget = self.createEntryScale(
|
||||
sfFrame, 'Style', 'Num Ticks',
|
||||
'Set number of tick marks drawn for each unit of time',
|
||||
min = 0.0, max = 10.0, resolution = 1.0,
|
||||
initialValue = 0.0,
|
||||
command = self.setNumTicks, side = TOP)
|
||||
widget.component('hull')['relief'] = RIDGE
|
||||
widget = self.createEntryScale(
|
||||
sfFrame, 'Style', 'Tick Scale',
|
||||
'Set visible size of time tick marks',
|
||||
min = 0.01, max = 100.0, resolution = 0.01,
|
||||
initialValue = 1.0,
|
||||
command = self.setTickScale, side = TOP)
|
||||
widget.component('hull')['relief'] = RIDGE
|
||||
self.createColorEntry(
|
||||
sfFrame, 'Style', 'Path Color',
|
||||
'Color of curve',
|
||||
command = self.setPathColor,
|
||||
initialValue = [255.0,255.0,255.0,255.0])
|
||||
self.createColorEntry(
|
||||
sfFrame, 'Style', 'Knot Color',
|
||||
'Color of knots',
|
||||
command = self.setKnotColor,
|
||||
initialValue = [0,0,255.0,255.0])
|
||||
self.createColorEntry(
|
||||
sfFrame, 'Style', 'CV Color',
|
||||
'Color of CVs',
|
||||
command = self.setCvColor,
|
||||
initialValue = [255.0,0,0,255.0])
|
||||
self.createColorEntry(
|
||||
sfFrame, 'Style', 'Tick Color',
|
||||
'Color of Ticks',
|
||||
command = self.setTickColor,
|
||||
initialValue = [255.0,0,0,255.0])
|
||||
self.createColorEntry(
|
||||
sfFrame, 'Style', 'Hull Color',
|
||||
'Color of Hull',
|
||||
command = self.setHullColor,
|
||||
initialValue = [255.0,128.0,128.0,255.0])
|
||||
|
||||
styleFrame.pack(fill = X)
|
||||
|
||||
self.mainNotebook.setnaturalsize()
|
||||
|
||||
def pushUndo(self, fResetRedo = 1):
|
||||
|
|
@ -761,33 +772,61 @@ class MopathRecorder(AppShell, PandaObject):
|
|||
# Compute curve
|
||||
self.computeCurves()
|
||||
|
||||
def setHullVis(self):
|
||||
self.xyzNurbsCurveDrawer.setShowHull(self.hullVis.get())
|
||||
|
||||
def setPathVis(self):
|
||||
if self.pathVis.get():
|
||||
if self.getVariable('Style', 'Show Path').get():
|
||||
self.curveNodePath.show()
|
||||
else:
|
||||
self.curveNodePath.hide()
|
||||
|
||||
def setCvVis(self):
|
||||
self.xyzNurbsCurveDrawer.setShowCvs(self.cvVis.get())
|
||||
|
||||
def setKnotVis(self):
|
||||
self.xyzNurbsCurveDrawer.setShowKnots(self.knotVis.get())
|
||||
|
||||
def setTickVis(self):
|
||||
if self.tickVis.get():
|
||||
self.xyzNurbsCurveDrawer.setNumTicks(self.numTicks)
|
||||
else:
|
||||
self.xyzNurbsCurveDrawer.setNumTicks(0)
|
||||
self.xyzNurbsCurveDrawer.setShowKnots(
|
||||
self.getVariable('Style', 'Show Knots').get())
|
||||
|
||||
def setCvVis(self):
|
||||
self.xyzNurbsCurveDrawer.setShowCvs(
|
||||
self.getVariable('Style', 'Show CVs').get())
|
||||
|
||||
def setHullVis(self):
|
||||
self.xyzNurbsCurveDrawer.setShowHull(
|
||||
self.getVariable('Style', 'Show Hull').get())
|
||||
|
||||
def setMarkerVis(self):
|
||||
if self.markerVis.get():
|
||||
if self.getVariable('Style', 'Show Marker').get():
|
||||
self.playbackMarker.reparentTo(self.recorderNodePath)
|
||||
else:
|
||||
self.playbackMarker.reparentTo(hidden)
|
||||
|
||||
def setNumSegs(self, value):
|
||||
self.numSegs = int(value)
|
||||
self.xyzNurbsCurveDrawer.setNumSegs(self.numSegs)
|
||||
|
||||
def setNumTicks(self, value):
|
||||
self.xyzNurbsCurveDrawer.setNumTicks(float(value))
|
||||
|
||||
def setTickScale(self, value):
|
||||
self.xyzNurbsCurveDrawer.setTickScale(float(value))
|
||||
|
||||
def setPathColor(self, color):
|
||||
self.xyzNurbsCurveDrawer.setColor(
|
||||
color[0]/255.0,color[1]/255.0,color[2]/255.0)
|
||||
self.xyzNurbsCurveDrawer.draw()
|
||||
|
||||
def setKnotColor(self, color):
|
||||
self.xyzNurbsCurveDrawer.setKnotColor(
|
||||
color[0]/255.0,color[1]/255.0,color[2]/255.0)
|
||||
|
||||
def setCvColor(self, color):
|
||||
self.xyzNurbsCurveDrawer.setCvColor(
|
||||
color[0]/255.0,color[1]/255.0,color[2]/255.0)
|
||||
|
||||
def setTickColor(self, color):
|
||||
self.xyzNurbsCurveDrawer.setTickColor(
|
||||
color[0]/255.0,color[1]/255.0,color[2]/255.0)
|
||||
|
||||
def setHullColor(self, color):
|
||||
self.xyzNurbsCurveDrawer.setHullColor(
|
||||
color[0]/255.0,color[1]/255.0,color[2]/255.0)
|
||||
|
||||
def setStartStopHook(self, event = None):
|
||||
# Clear out old hook
|
||||
self.ignore(self.startStopHook)
|
||||
|
|
@ -821,11 +860,13 @@ class MopathRecorder(AppShell, PandaObject):
|
|||
self.hprCurveFitter.reset()
|
||||
self.xyzNurbsCurveDrawer.hide()
|
||||
|
||||
def setSamplingMode(self):
|
||||
if self.samplingMode.get() == 'Keyframe':
|
||||
self.getWidget('Recording', 'Add Key Frame')['state'] = 'normal'
|
||||
else:
|
||||
self.getWidget('Recording', 'Add Key Frame')['state'] = 'disabled'
|
||||
def setSamplingMode(self, mode):
|
||||
self.samplingMode = mode
|
||||
|
||||
def disableKeyframeButton(self):
|
||||
self.getWidget('Recording', 'Add Keyframe')['state'] = 'disabled'
|
||||
def enableKeyframeButton(self):
|
||||
self.getWidget('Recording', 'Add Keyframe')['state'] = 'normal'
|
||||
|
||||
def setRecordingType(self, type):
|
||||
self.recordingType.set(type)
|
||||
|
|
@ -856,12 +897,15 @@ class MopathRecorder(AppShell, PandaObject):
|
|||
# Reset curve fitters
|
||||
self.xyzCurveFitter.reset()
|
||||
self.hprCurveFitter.reset()
|
||||
# Update sampling mode button if necessary
|
||||
if self.samplingMode == 'Continuous':
|
||||
self.disableKeyframeButton()
|
||||
# Create a new point set to hold raw data
|
||||
self.createNewPointSet()
|
||||
# Record nopath's parent
|
||||
self.nodePathParent = self['nodePath'].getParent()
|
||||
# Keyframe mode?
|
||||
if (self.samplingMode.get() == 'Keyframe'):
|
||||
if (self.samplingMode == 'Keyframe'):
|
||||
# Add hook
|
||||
self.acceptKeyframeHook()
|
||||
# Record first point
|
||||
|
|
@ -891,14 +935,8 @@ class MopathRecorder(AppShell, PandaObject):
|
|||
t = taskMgr.spawnMethodNamed(
|
||||
self.recordTask, self.name + '-recordTask')
|
||||
t.startTime = globalClock.getTime()
|
||||
|
||||
# Don't want to change record modes
|
||||
self.getWidget('Recording', 'Continuous Sampling')['state'] = (
|
||||
'disabled')
|
||||
self.getWidget('Recording', 'Keyframe Sampling')['state'] = (
|
||||
'disabled')
|
||||
else:
|
||||
if self.samplingMode.get() == 'Continuous':
|
||||
if self.samplingMode == 'Continuous':
|
||||
# Kill old task
|
||||
taskMgr.removeTasksNamed(self.name + '-recordTask')
|
||||
if ((self.recordingType.get() == 'Refine') |
|
||||
|
|
@ -915,6 +953,9 @@ class MopathRecorder(AppShell, PandaObject):
|
|||
self.addKeyframe(0)
|
||||
# Ignore hook
|
||||
self.ignoreKeyframeHook()
|
||||
# Reset sampling mode
|
||||
self.setSamplingMode('Continuous')
|
||||
self.enableKeyframeButton()
|
||||
# Clean up after refine or extend
|
||||
if ((self.recordingType.get() == 'Refine') |
|
||||
(self.recordingType.get() == 'Extend')):
|
||||
|
|
@ -927,11 +968,6 @@ class MopathRecorder(AppShell, PandaObject):
|
|||
self.setNewCurveMode()
|
||||
# Compute curve
|
||||
self.computeCurves()
|
||||
# Now you can change record modes
|
||||
self.getWidget('Recording', 'Continuous Sampling')['state'] = (
|
||||
'normal')
|
||||
self.getWidget('Recording', 'Keyframe Sampling')['state'] = (
|
||||
'normal')
|
||||
|
||||
def recordTask(self, state):
|
||||
# Record raw data point
|
||||
|
|
@ -943,6 +979,8 @@ class MopathRecorder(AppShell, PandaObject):
|
|||
# Make sure we're in a recording mode!
|
||||
if (fToggleRecord &
|
||||
(not self.getVariable('Recording', 'Record').get())):
|
||||
# Set sampling mode
|
||||
self.setSamplingMode('Keyframe')
|
||||
# This will automatically add the first point
|
||||
self.toggleRecordVar()
|
||||
else:
|
||||
|
|
@ -955,11 +993,10 @@ class MopathRecorder(AppShell, PandaObject):
|
|||
x = t * t
|
||||
return (3 * x) - (2 * t * x)
|
||||
|
||||
def setPreRecordFunc(self, event):
|
||||
def setPreRecordFunc(self, func):
|
||||
# Note: If func is one defined at command prompt, need to set
|
||||
# __builtins__.func = func at command line
|
||||
self.preRecordFunc = eval(
|
||||
self.getVariable('Recording', 'Pre-Record Func').get())
|
||||
self.preRecordFunc = eval(func)
|
||||
# Update widget to reflect new value
|
||||
self.getVariable('Recording', 'PRF Active').set(1)
|
||||
|
||||
|
|
@ -1336,8 +1373,24 @@ class MopathRecorder(AppShell, PandaObject):
|
|||
for i in range(self.hprNurbsCurve.getNumKnots()):
|
||||
self.hprNurbsCurve.setKnot(i, sf * self.hprNurbsCurve.getKnot(i))
|
||||
self.hprNurbsCurve.recompute()
|
||||
# Update info
|
||||
self.updateWidgets()
|
||||
# Scale point set
|
||||
# Save handle to old point set
|
||||
oldPointSet = self.pointSet
|
||||
# Create new point set
|
||||
self.createNewPointSet()
|
||||
# Reset curve fitters
|
||||
self.xyzCurveFitter.reset()
|
||||
self.hprCurveFitter.reset()
|
||||
# Now scale values
|
||||
for time, pos, hpr in oldPointSet:
|
||||
newTime = time * sf
|
||||
# Update point set
|
||||
self.pointSet.append([newTime, Point3(pos), Point3(hpr)])
|
||||
# Add it to the curve fitters
|
||||
self.xyzCurveFitter.addPoint(newTime, pos )
|
||||
self.hprCurveFitter.addPoint(newTime, hpr)
|
||||
# Compute curve
|
||||
self.computeCurves()
|
||||
|
||||
def setRecordStart(self,value):
|
||||
self.recordStart = value
|
||||
|
|
@ -1620,6 +1673,14 @@ class MopathRecorder(AppShell, PandaObject):
|
|||
self.xyzNurbsCurve.writeEgg(mopathFilename)
|
||||
self.hprNurbsCurve.writeEgg(mopathFilename)
|
||||
|
||||
def followTerrain(self, height = 1.0):
|
||||
self.iRay.rayCollisionNodePath.reparentTo(self['nodePath'])
|
||||
node, hitPt, hitPtDist = self.iRay.pickGeom3D()
|
||||
if node:
|
||||
self['nodePath'].setZ(self['nodePath'], height - hitPtDist)
|
||||
self.iRay.rayCollisionNodePath.reparentTo(self.recorderNodePath)
|
||||
|
||||
|
||||
## WIDGET UTILITY FUNCTIONS ##
|
||||
def addWidget(self, widget, category, text):
|
||||
self.widgetDict[category + '-' + text] = widget
|
||||
|
|
@ -1639,10 +1700,12 @@ class MopathRecorder(AppShell, PandaObject):
|
|||
variable.set(initialValue)
|
||||
label = Label(frame, text = text)
|
||||
label.pack(side = LEFT, fill = X)
|
||||
self.bind(label, balloonHelp)
|
||||
self.widgetDict[category + '-' + text + '-Label'] = label
|
||||
entry = Entry(frame, width = width, relief = relief,
|
||||
textvariable = variable)
|
||||
entry.pack(side = LEFT, fill = X, expand = expand)
|
||||
self.bind(entry, balloonHelp)
|
||||
self.widgetDict[category + '-' + text] = entry
|
||||
self.variableDict[category + '-' + text] = variable
|
||||
if command:
|
||||
|
|
@ -1800,7 +1863,7 @@ class MopathRecorder(AppShell, PandaObject):
|
|||
widget.selectitem(items[0])
|
||||
# Bind selection command
|
||||
widget['selectioncommand'] = command
|
||||
widget.pack(side = side, expand = expand)
|
||||
widget.pack(side = side, fill = fill, expand = expand)
|
||||
# Bind help
|
||||
self.bind(widget, balloonHelp)
|
||||
# Record widget
|
||||
|
|
|
|||
Loading…
Reference in New Issue