mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 01:07:51 -04:00
*** empty log message ***
This commit is contained in:
parent
cda6f2be96
commit
e5ab222f36
@ -15,7 +15,7 @@ class DirectCameraControl(PandaObject):
|
||||
self.coaMarker = loader.loadModel('models/misc/sphere')
|
||||
self.coaMarker.setName('DirectCameraCOAMarker')
|
||||
self.coaMarker.setColor(1,0,0)
|
||||
self.coaMarker.setPos(0,0,0)
|
||||
self.coaMarker.setPos(0,100,0)
|
||||
useDirectRenderStyle(self.coaMarker)
|
||||
self.coaMarkerPos = Point3(0)
|
||||
self.camManipRef = direct.group.attachNewNode('camManipRef')
|
||||
@ -56,27 +56,15 @@ class DirectCameraControl(PandaObject):
|
||||
self.coaMarker.hide()
|
||||
# Check for a hit point based on
|
||||
# current mouse position
|
||||
# Allow intersection with unpickable objects
|
||||
# And then spawn task to determine mouse mode
|
||||
numEntries = direct.iRay.pickGeom(
|
||||
render,direct.dr.mouseX,direct.dr.mouseY)
|
||||
# Then filter out hidden nodes from entry list
|
||||
indexList = []
|
||||
for i in range(0,numEntries):
|
||||
entry = direct.iRay.cq.getEntry(i)
|
||||
node = entry.getIntoNode()
|
||||
if node.isHidden():
|
||||
pass
|
||||
else:
|
||||
# Not one of the widgets, use it
|
||||
indexList.append(i)
|
||||
node, hitPt, hitPtDist = direct.iRay.pickGeom(
|
||||
fIntersectUnpickable = 1)
|
||||
coa = Point3(0)
|
||||
if(indexList):
|
||||
# Grab first point (it should be the closest)
|
||||
minPt = indexList[0]
|
||||
# Find hit point in camera's space
|
||||
hitPt = direct.iRay.camToHitPt(minPt)
|
||||
coa.set(hitPt[0],hitPt[1],hitPt[2])
|
||||
coaDist = Vec3(coa - ZERO_POINT).length()
|
||||
if node:
|
||||
# Set center of action
|
||||
coa.assign(hitPt)
|
||||
coaDist = hitPtDist
|
||||
# Handle case of bad coa point (too close or too far)
|
||||
if ((coaDist < (1.1 * direct.dr.near)) |
|
||||
(coaDist > direct.dr.far)):
|
||||
|
@ -2,8 +2,6 @@ from PandaObject import *
|
||||
from DirectGeometry import *
|
||||
|
||||
MANIPULATION_MOVE_DELAY = 0.65
|
||||
UNPICKABLE = ['x-disc-visible', 'y-disc-visible', 'z-disc-visible',
|
||||
'GridBack']
|
||||
|
||||
class DirectManipulationControl(PandaObject):
|
||||
def __init__(self):
|
||||
@ -24,7 +22,6 @@ class DirectManipulationControl(PandaObject):
|
||||
self.fWidgetTop = 0
|
||||
self.fFreeManip = 1
|
||||
self.fScaling = 0
|
||||
self.unpickable = UNPICKABLE
|
||||
self.mode = None
|
||||
self.actionEvents = [
|
||||
['handleMouse1', self.manipulationStart],
|
||||
@ -35,26 +32,19 @@ class DirectManipulationControl(PandaObject):
|
||||
[',', self.objectHandles.multiplyScalingFactorBy, 0.5],
|
||||
['<', self.objectHandles.multiplyScalingFactorBy, 0.5],
|
||||
['F', self.objectHandles.growToFit],
|
||||
['p', self.plantSelectedNodePath],
|
||||
]
|
||||
|
||||
def manipulationStart(self):
|
||||
# Start out in select mode
|
||||
self.mode = 'select'
|
||||
# Check for a widget hit point
|
||||
numEntries = direct.iRay.pickWidget(
|
||||
render,direct.dr.mouseX,direct.dr.mouseY)
|
||||
node, hitPt, hitPtDist = direct.iRay.pickWidget()
|
||||
# Did we hit a widget?
|
||||
if(numEntries):
|
||||
if node:
|
||||
# Yes!
|
||||
# Entry 0 is the closest hit point if multiple hits
|
||||
minPt = 0
|
||||
# Find hit point in camera's space
|
||||
self.hitPt = direct.iRay.camToHitPt(minPt)
|
||||
self.hitPtDist = Vec3(self.hitPt - ZERO_POINT).length()
|
||||
# Get the associated collision queue object
|
||||
entry = direct.iRay.cq.getEntry(minPt)
|
||||
# Extract the node
|
||||
node = entry.getIntoNode()
|
||||
self.hitPt.assign(hitPt)
|
||||
self.hitPtDist = hitPtDist
|
||||
# Constraint determined by nodes name
|
||||
self.constraint = node.getName()
|
||||
else:
|
||||
@ -97,32 +87,11 @@ class DirectManipulationControl(PandaObject):
|
||||
# depending on flag.....
|
||||
if self.mode == 'select':
|
||||
# Check for object under mouse
|
||||
numEntries = direct.iRay.pickGeom(
|
||||
render,direct.dr.mouseX,direct.dr.mouseY)
|
||||
# Pick out the closest object that isn't a widget
|
||||
index = -1
|
||||
for i in range(0,numEntries):
|
||||
entry = direct.iRay.cq.getEntry(i)
|
||||
node = entry.getIntoNode()
|
||||
if node.isHidden():
|
||||
pass
|
||||
# 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
|
||||
else:
|
||||
# Not hidden and not one of the widgets, use it
|
||||
index = i
|
||||
# Did we hit an object?
|
||||
if(index >= 0):
|
||||
# Yes!
|
||||
# Find hit point in camera's space
|
||||
self.hitPt = direct.iRay.camToHitPt(index)
|
||||
self.hitPtDist = Vec3(self.hitPt - ZERO_POINT).length()
|
||||
node, hitPt, hitPtDist = direct.iRay.pickGeom()
|
||||
if node:
|
||||
# Record hit point information
|
||||
self.hitPt.assign(hitPt)
|
||||
self.hitPtDist = hitPtDist
|
||||
# Find the node path from the node found above
|
||||
nodePath = render.findPathDownTo(node)
|
||||
# Select it
|
||||
@ -479,15 +448,32 @@ class DirectManipulationControl(PandaObject):
|
||||
self.initScaleMag)
|
||||
)
|
||||
direct.widget.setScale(currScale)
|
||||
|
||||
|
||||
## Utility functions ##
|
||||
def plantSelectedNodePath(self):
|
||||
""" Move selected object to intersection point of cursor on scene """
|
||||
# Check for intersection
|
||||
node, hitPt, hitPtDist = direct.iRay.pickGeom(
|
||||
fIntersectUnpickable = 1)
|
||||
# MRM: Need to handle moving COA
|
||||
if (node != None) & (direct.selected.last != None):
|
||||
# Record undo point
|
||||
direct.pushUndo(direct.selected)
|
||||
# Record wrt matrix
|
||||
direct.selected.getWrtAll()
|
||||
# Move selected
|
||||
direct.widget.setPos(direct.camera, hitPt)
|
||||
# Move all the selected objects with widget
|
||||
# Move the objects with the widget
|
||||
direct.selected.moveWrtWidgetAll()
|
||||
# Let everyone know that something was moved
|
||||
messenger.send('manipulateObjectCleanup')
|
||||
|
||||
class ObjectHandles(NodePath,PandaObject):
|
||||
def __init__(self):
|
||||
# Initialize the superclass
|
||||
NodePath.__init__(self)
|
||||
|
||||
# Starts off deactivated
|
||||
self.fActive = 0
|
||||
# Load up object handles model and assign it to self
|
||||
self.assign(loader.loadModel('models/misc/objectHandles'))
|
||||
self.node().setName('objectHandles')
|
||||
@ -540,6 +526,10 @@ class ObjectHandles(NodePath,PandaObject):
|
||||
self.createGuideLines()
|
||||
self.hideGuides()
|
||||
|
||||
# Start with widget handles hidden
|
||||
self.fActive = 1
|
||||
self.toggleWidget()
|
||||
|
||||
# Make sure object handles are never lit or drawn in wireframe
|
||||
useDirectRenderStyle(self)
|
||||
|
||||
@ -551,10 +541,10 @@ class ObjectHandles(NodePath,PandaObject):
|
||||
|
||||
def toggleWidget(self):
|
||||
if self.fActive:
|
||||
self.reparentTo(hidden)
|
||||
self.scalingNode.reparentTo(hidden)
|
||||
self.fActive = 0
|
||||
else:
|
||||
self.reparentTo(direct.group)
|
||||
self.scalingNode.reparentTo(self)
|
||||
self.fActive = 1
|
||||
|
||||
def showWidgetIfActive(self):
|
||||
|
@ -2,6 +2,9 @@ from PandaObject import *
|
||||
from DirectGeometry import *
|
||||
from DirectSelection import *
|
||||
|
||||
UNPICKABLE = ['x-disc-visible', 'y-disc-visible', 'z-disc-visible',
|
||||
'GridBack']
|
||||
|
||||
# MRM: To do: handle broken node paths in selected and deselected dicts
|
||||
class DirectNodePath(NodePath):
|
||||
# A node path augmented with info, bounding box, and utility methods
|
||||
@ -394,14 +397,70 @@ class SelectionRay:
|
||||
self.ct = CollisionTraverser( RenderRelation.getClassType() )
|
||||
# Let the traverser know about the queue and the collision node
|
||||
self.ct.addCollider(self.rayCollisionNode, self.cq )
|
||||
# List of objects that can't be selected
|
||||
self.unpickable = UNPICKABLE
|
||||
|
||||
def pickGeom(self, targetNodePath, mouseX, mouseY):
|
||||
def pickGeom(self, targetNodePath = render, fIntersectUnpickable = 0):
|
||||
self.collideWithGeom()
|
||||
return self.pick(targetNodePath, mouseX, mouseY)
|
||||
numEntries = self.pick(targetNodePath,
|
||||
direct.dr.mouseX,
|
||||
direct.dr.mouseY)
|
||||
# Init index
|
||||
index = -1
|
||||
# Pick out the closest object that isn't a widget
|
||||
for i in range(0,numEntries):
|
||||
entry = direct.iRay.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 camera's space
|
||||
hitPt = direct.iRay.camToHitPt(index)
|
||||
hitPtDist = Vec3(hitPt - ZERO_POINT).length()
|
||||
return (node, hitPt, hitPtDist)
|
||||
else:
|
||||
return (None, ZERO_POINT, 0)
|
||||
|
||||
def pickWidget(self, targetNodePath, mouseX, mouseY):
|
||||
def pickWidget(self, targetNodePath = render):
|
||||
self.collideWithWidget()
|
||||
return self.pick(targetNodePath, mouseX, mouseY)
|
||||
numEntries = self.pick(targetNodePath,
|
||||
direct.dr.mouseX,
|
||||
direct.dr.mouseY)
|
||||
# Did we hit a widget?
|
||||
if numEntries:
|
||||
# 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)
|
||||
hitPtDist = Vec3(hitPt).length()
|
||||
# Get the associated collision queue object
|
||||
entry = direct.iRay.cq.getEntry(minPt)
|
||||
# Extract the node
|
||||
node = entry.getIntoNode()
|
||||
# Return info
|
||||
return (node, hitPt, hitPtDist)
|
||||
else:
|
||||
return (None, ZERO_POINT, 0)
|
||||
|
||||
def pick(self, targetNodePath, mouseX, mouseY):
|
||||
# Determine ray direction based upon the mouse coordinates
|
||||
|
@ -79,9 +79,8 @@ class DirectSession(PandaObject):
|
||||
['SGENodePath_Delete', self.removeNodePath],
|
||||
]
|
||||
self.keyEvents = ['left', 'right', 'up', 'down',
|
||||
'escape', 'space', 'delete',
|
||||
'escape', 'delete', 'control', 'control-up',
|
||||
'shift', 'shift-up', 'alt', 'alt-up',
|
||||
'control', 'control-up',
|
||||
'page_up', 'page_down', 'tab',
|
||||
'[', '{', ']', '}',
|
||||
'b', 'c', 'f', 'l', 's', 't', 'v', 'w']
|
||||
@ -213,8 +212,8 @@ class DirectSession(PandaObject):
|
||||
elif (input == ']') | (input == '}'):
|
||||
self.redo()
|
||||
|
||||
def select(self, nodePath, fMultiselect = 0, fResetAncestry = 1):
|
||||
dnp = self.selected.select(nodePath, fMultiselect)
|
||||
def select(self, nodePath, fMultiSelect = 0, fResetAncestry = 1):
|
||||
dnp = self.selected.select(nodePath, fMultiSelect)
|
||||
if dnp:
|
||||
messenger.send('preSelectNodePath', [dnp])
|
||||
if fResetAncestry:
|
||||
@ -465,6 +464,7 @@ class DirectSession(PandaObject):
|
||||
# UTILITY FUNCTIONS
|
||||
def useObjectHandles(self):
|
||||
self.widget = self.manipulationControl.objectHandles
|
||||
self.widget.reparentTo(direct.group)
|
||||
|
||||
def hideReadout(self):
|
||||
self.readout.reparentTo(hidden)
|
||||
|
@ -60,6 +60,7 @@ classRenameDictionary = {
|
||||
'LVecBase2f' : 'VBase2',
|
||||
'LVector2f' : 'Vec2',
|
||||
'LPoint2f' : 'Point2',
|
||||
'LQuaternionf' : 'Quat',
|
||||
'LMatrix4d' : 'Mat4D',
|
||||
'LMatrix3d' : 'Mat3D',
|
||||
'LVecBase4d' : 'VBase4D',
|
||||
@ -71,6 +72,7 @@ classRenameDictionary = {
|
||||
'LVecBase2d' : 'VBase2D',
|
||||
'LVector2d' : 'Vec2D',
|
||||
'LPoint2d' : 'Point2D',
|
||||
'LQuaterniond' : 'QuatD',
|
||||
'Plane' : 'PlaneBase',
|
||||
'Planef' : 'Plane',
|
||||
'Planed' : 'PlaneD',
|
||||
|
@ -59,23 +59,23 @@ class ParticlePanel(AppShell):
|
||||
## SYSTEM PAGE ##
|
||||
# Create system floaters
|
||||
systemFloaterDefs = (
|
||||
('System Pool size',
|
||||
('System Pool Size',
|
||||
'Size of particle pool',
|
||||
self.setSystemPoolSize,
|
||||
1.0, 1.0),
|
||||
('System Birth rate',
|
||||
('System Birth Rate',
|
||||
'Seconds between particle births',
|
||||
self.setSystemBirthRate,
|
||||
0.0, None),
|
||||
('System Litter size',
|
||||
('System Litter Size',
|
||||
'Number of particle created at each birth',
|
||||
self.setSystemLitterSize,
|
||||
1.0, 1.0),
|
||||
('System Litter spread',
|
||||
('System Litter Spread',
|
||||
'Variation in litter size',
|
||||
self.setSystemLitterSpread,
|
||||
0.0, 1.0),
|
||||
('System lifespan',
|
||||
('System Lifespan',
|
||||
'Age in seconds at which system should die',
|
||||
self.setSystemLifespan,
|
||||
0.0, None)
|
||||
@ -83,17 +83,17 @@ class ParticlePanel(AppShell):
|
||||
self.createFloaters(systemPage, systemFloaterDefs)
|
||||
# Checkboxes
|
||||
self.systemLocalVelocity = self.createCheckbutton(
|
||||
systemPage, 'Local velocity',
|
||||
systemPage, 'System Local Velocity',
|
||||
self.toggleSystemLocalVelocity, 0)
|
||||
self.systemGrowsOlder = self.createCheckbutton(
|
||||
systemPage, 'System grows older',
|
||||
systemPage, 'System Grows Older',
|
||||
self.toggleSystemGrowsOlder, 0)
|
||||
# Vector widgets
|
||||
pos = self.createVector3Entry(systemPage, 'Pos',
|
||||
pos = self.createVector3Entry(systemPage, 'System Pos',
|
||||
'Particle system position',
|
||||
command = self.setSystemPos)
|
||||
pos.addMenuItem('Popup Placer Panel', Placer.Placer)
|
||||
hpr = self.createVector3Entry(systemPage, 'Hpr',
|
||||
hpr = self.createVector3Entry(systemPage, 'System Hpr',
|
||||
'Particle system orientation',
|
||||
fGroup_labels = ('H', 'P', 'R'),
|
||||
command = self.setSystemHpr)
|
||||
@ -107,27 +107,27 @@ class ParticlePanel(AppShell):
|
||||
('Point', 'Z Spin', 'Oriented'),
|
||||
self.selectFactoryType)
|
||||
factoryWidgets = (
|
||||
('Life span',
|
||||
('Factory Life Span',
|
||||
'Average lifespan in seconds',
|
||||
self.setFactoryLifeSpan,
|
||||
0.0, None),
|
||||
('Life span spread',
|
||||
('Factory Life Span Spread',
|
||||
'Variation in lifespan',
|
||||
self.setFactoryLifeSpanSpread,
|
||||
0.0, None),
|
||||
('Mass',
|
||||
('Factory Mass',
|
||||
'Average particle mass',
|
||||
self.setFactoryParticleMass,
|
||||
0.0, None),
|
||||
('Mass spread',
|
||||
('Factory Mass Spread',
|
||||
'Variation in particle mass',
|
||||
self.setFactoryParticleMassSpread,
|
||||
0.0, None),
|
||||
('Terminal velocity',
|
||||
('Factory Terminal Velocity',
|
||||
'Average particle terminal velocity',
|
||||
self.setFactoryTerminalVelocity,
|
||||
0.0, None),
|
||||
('Terminal vel. spread',
|
||||
('Factory Terminal Vel. Spread',
|
||||
'Variation in terminal velocity',
|
||||
self.setFactoryTerminalVelocitySpread,
|
||||
0.0, None))
|
||||
@ -138,13 +138,13 @@ class ParticlePanel(AppShell):
|
||||
factoryPointPage = self.factoryNotebook.add('Point')
|
||||
# Z spin page #
|
||||
zSpinPage = self.factoryNotebook.add('Z Spin')
|
||||
self.createAngleDial(zSpinPage, 'Initial angle',
|
||||
self.createAngleDial(zSpinPage, 'Z Spin Initial Angle',
|
||||
'Starting angle in degrees',
|
||||
command = self.setFactoryZSpinInitialAngle)
|
||||
self.createAngleDial(zSpinPage, 'Final angle',
|
||||
self.createAngleDial(zSpinPage, 'Z Spin Final Angle',
|
||||
'Final angle in degrees',
|
||||
command = self.setFactoryZSpinFinalAngle)
|
||||
self.createAngleDial(zSpinPage, 'Angle spread',
|
||||
self.createAngleDial(zSpinPage, 'Z Spin Angle Spread',
|
||||
'Spread of the final angle',
|
||||
command = self.setFactoryZSpinAngleSpread)
|
||||
# Oriented page #
|
||||
@ -164,18 +164,19 @@ class ParticlePanel(AppShell):
|
||||
self.emitterNotebook = Pmw.NoteBook(emitterPage, tabpos = None)
|
||||
# Box page #
|
||||
boxPage = self.emitterNotebook.add('Box')
|
||||
self.createVector3Entry(boxPage, 'Point 1',
|
||||
'Point defining emitter box',
|
||||
self.createVector3Entry(boxPage, 'Box Emitter Min',
|
||||
'Min point defining emitter box',
|
||||
command = self.setEmitterBoxPoint1)
|
||||
self.createVector3Entry(boxPage, 'Point 2',
|
||||
'Point defining emitter box',
|
||||
self.createVector3Entry(boxPage, 'Box Emitter Max',
|
||||
'Max point defining emitter box',
|
||||
command = self.setEmitterBoxPoint2,
|
||||
initialValue = (1.0, 1.0, 1.0))
|
||||
self.createVector3Entry(boxPage, 'Velocity vector',
|
||||
'Initial particle velocity vector',
|
||||
'Initial particle velocity vector',
|
||||
command = self.setEmitterBoxVelocityVector)
|
||||
# Disc page #
|
||||
discPage = self.emitterNotebook.add('Disc')
|
||||
self.emitter
|
||||
self.createFloater(discPage, 'Radius', 'Radius of disc',
|
||||
command = self.setEmitterDiscRadius)
|
||||
self.createAngleDial(discPage, 'Inner angle',
|
||||
@ -195,23 +196,24 @@ class ParticlePanel(AppShell):
|
||||
self.toggleEmitterDiscCubicLerping, 0)
|
||||
# Line page #
|
||||
linePage = self.emitterNotebook.add('Line')
|
||||
self.createVector3Entry(linePage, 'Point 1',
|
||||
'Point defining emitter line',
|
||||
self.createVector3Entry(linePage, 'Line Emitter Min',
|
||||
'Min point defining emitter line',
|
||||
command = self.setEmitterLinePoint1)
|
||||
self.createVector3Entry(linePage, 'Point 2',
|
||||
'Point defining emitter line',
|
||||
self.createVector3Entry(linePage, 'Line Emitter Max',
|
||||
'Max point defining emitter line',
|
||||
command = self.setEmitterLinePoint2,
|
||||
initialValue = (1.0, 0.0, 0.0))
|
||||
self.createVector3Entry(linePage, 'Velocity Vector',
|
||||
self.createVector3Entry(linePage, 'Line Emitter Velocity',
|
||||
'Initial particle velocity vector',
|
||||
command = self.setEmitterLineVelocityVector,
|
||||
initialValue = (0.0, 0.0, 1.0))
|
||||
# Point page #
|
||||
emitterPointPage = self.emitterNotebook.add('Point')
|
||||
self.createVector3Entry(emitterPointPage, 'Position',
|
||||
self.createVector3Entry(emitterPointPage, 'Point Emitter Position',
|
||||
'Position of emitter point',
|
||||
command = self.setEmitterPointPosition)
|
||||
self.createVector3Entry(emitterPointPage, 'Velocity vector',
|
||||
self.createVector3Entry(emitterPointPage,
|
||||
'Point Emitter Velocity',
|
||||
'Initial particle velocity vector',
|
||||
command = self.setEmitterPointVelocityVector,
|
||||
initialValue = (0.0, 0.0, 1.0))
|
||||
@ -374,11 +376,12 @@ class ParticlePanel(AppShell):
|
||||
def createCheckbutton(self, parent, text, command, initialState):
|
||||
bool = BooleanVar()
|
||||
bool.set(initialState)
|
||||
cb = Checkbutton(parent, text = text, anchor = W,
|
||||
widget = Checkbutton(parent, text = text, anchor = W,
|
||||
variable = bool)
|
||||
# Do this after the widget so command isn't called on creation
|
||||
cb.command = command
|
||||
cb.pack(fill = X)
|
||||
widget['command'] = command
|
||||
widget.pack(fill = X)
|
||||
self.widgetDict['text'] = widget
|
||||
return bool
|
||||
|
||||
def createFloaters(self, parent, widgetDefinitions):
|
||||
@ -412,6 +415,7 @@ class ParticlePanel(AppShell):
|
||||
widget['command'] = command
|
||||
widget.pack(fill = X)
|
||||
self.bind(widget, balloonHelp)
|
||||
self.widgetDict['text'] = widget
|
||||
return widget
|
||||
|
||||
def createVector3Entry(self, parent, text, balloonHelp,
|
||||
@ -423,6 +427,7 @@ class ParticlePanel(AppShell):
|
||||
widget['command'] = command
|
||||
widget.pack(fill = X)
|
||||
self.bind(widget, balloonHelp)
|
||||
self.widgetDict['text'] = widget
|
||||
return widget
|
||||
|
||||
def createColorEntry(self, parent, text, balloonHelp,
|
||||
@ -434,6 +439,7 @@ class ParticlePanel(AppShell):
|
||||
widget['command'] = command
|
||||
widget.pack(fill = X)
|
||||
self.bind(widget, balloonHelp)
|
||||
self.widgetDict['text'] = widget
|
||||
return widget
|
||||
|
||||
def createOptionMenu(self, parent, text, balloonHelp, items, command):
|
||||
@ -447,6 +453,7 @@ class ParticlePanel(AppShell):
|
||||
widget['command'] = command
|
||||
widget.pack(fill = X)
|
||||
self.bind(widget.component('menubutton'), balloonHelp)
|
||||
self.widgetDict['text'] = widget
|
||||
return optionVar
|
||||
|
||||
### PARTICLE SYSTEM COMMANDS ###
|
||||
@ -500,6 +507,39 @@ class ParticlePanel(AppShell):
|
||||
def selectEmitterType(self, type):
|
||||
self.emitterNotebook.selectpage(type)
|
||||
self.particles.setEmitter(type)
|
||||
self.updateEmitterWidgets()
|
||||
|
||||
def updateEmitterWidgets(self):
|
||||
emitter = self.particles.emitter
|
||||
if isinstance(emitter, BoxEmitter):
|
||||
min = emitter.getMinBound()
|
||||
self.emitterBoxPoint1VectorEntry.set(
|
||||
[min[0], min[1], min[2]])
|
||||
max = emitter.getMaxBound()
|
||||
self.emitterBoxPoint2VectorEntry.set(
|
||||
[max[0], max[1], max[2]])
|
||||
elif isinstance(emitter, DiscEmitter):
|
||||
radius = emitter.getRadius()
|
||||
cubicLerping = emitter.getCubicLerping()
|
||||
innerAngle = emitter.getInnerAngle()
|
||||
getInnerMagnitude
|
||||
getOuterAngle
|
||||
getOuterMagnitude
|
||||
elif isinstance(emitter, LineEmitter):
|
||||
pass
|
||||
elif isinstance(emitter, PointEmitter):
|
||||
pass
|
||||
elif isinstance(emitter, RectangleEmitter):
|
||||
pass
|
||||
elif isinstance(emitter, RingEmitter):
|
||||
pass
|
||||
elif isinstance(emitter, SphereVolumeEmitter):
|
||||
pass
|
||||
elif isinstance(emitter, SphereSurfaceEmitter):
|
||||
pass
|
||||
elif isinstance(emitter, TangentRingEmitter):
|
||||
pass
|
||||
|
||||
# Box #
|
||||
def setEmitterBoxPoint1(self, point):
|
||||
self.particles.emitter.setMinBound(Point3(point[0],
|
||||
|
@ -64,6 +64,7 @@ class Placer(AppShell):
|
||||
self.initPos = Vec3(0)
|
||||
self.initHpr = Vec3(0)
|
||||
self.initScale = Vec3(1)
|
||||
self.deltaHpr = Vec3(0)
|
||||
|
||||
# Offset for orbital mode
|
||||
self.posOffset = Vec3(0)
|
||||
@ -450,7 +451,7 @@ class Placer(AppShell):
|
||||
else:
|
||||
if name == 'widget':
|
||||
# Record relationship between selected nodes and widget
|
||||
direct.selected.getWrtAll()
|
||||
direct.selected.getWrtAll()
|
||||
# Update active node path
|
||||
self.setActiveNodePath(nodePath)
|
||||
|
||||
@ -459,10 +460,19 @@ class Placer(AppShell):
|
||||
if self['nodePath']:
|
||||
self.nodePathMenuEntry.configure(
|
||||
background = self.nodePathMenuBG)
|
||||
# Check to see if node path and ref node path are the same
|
||||
if ((self.refCS != None) &
|
||||
(self.refCS.id() == self['nodePath'].id())):
|
||||
# Yes they are, use temp CS as ref
|
||||
# This calls updatePlacer
|
||||
self.setReferenceNodePath(self.tempCS)
|
||||
# update listbox accordingly
|
||||
self.refNodePathMenu.selectitem('self')
|
||||
else:
|
||||
# Record initial value and initialize the widgets
|
||||
self.updatePlacer()
|
||||
# Record initial position
|
||||
self.updateResetValues(self['nodePath'])
|
||||
# Record initial value and initialize the widgets
|
||||
self.updatePlacer()
|
||||
else:
|
||||
# Flash entry
|
||||
self.nodePathMenuEntry.configure(background = 'Pink')
|
||||
@ -494,7 +504,12 @@ class Placer(AppShell):
|
||||
# Clear bogus entry from listbox
|
||||
listbox = self.refNodePathMenu.component('scrolledlist')
|
||||
listbox.setlist(self.refNodePathNames)
|
||||
# Update ref node path accordingly
|
||||
# Check to see if node path and ref node path are the same
|
||||
if (nodePath != None) & (nodePath.id() == self['nodePath'].id()):
|
||||
# Yes they are, use temp CS and update listbox accordingly
|
||||
nodePath = self.tempCS
|
||||
self.refNodePathMenu.selectitem('self')
|
||||
# Update ref node path
|
||||
self.setReferenceNodePath(nodePath)
|
||||
|
||||
def setReferenceNodePath(self, nodePath):
|
||||
@ -594,6 +609,8 @@ class Placer(AppShell):
|
||||
taskMgr.removeTasksNamed('followSelectedNodePath')
|
||||
# Record relationship between selected nodes and widget
|
||||
direct.selected.getWrtAll()
|
||||
# Record initial state
|
||||
self.deltaHpr = self['nodePath'].getHpr(self.refCS)
|
||||
# Update placer to reflect new state
|
||||
self.updatePlacer()
|
||||
|
||||
@ -609,7 +626,6 @@ class Placer(AppShell):
|
||||
|
||||
def xformRelative(self, value, axis):
|
||||
nodePath = self['nodePath']
|
||||
|
||||
if (nodePath != None) & (self.refCS != None):
|
||||
if axis == 'x':
|
||||
nodePath.setX(self.refCS, value)
|
||||
@ -617,12 +633,15 @@ class Placer(AppShell):
|
||||
nodePath.setY(self.refCS, value)
|
||||
elif axis == 'z':
|
||||
nodePath.setZ(self.refCS, value)
|
||||
elif axis == 'h':
|
||||
nodePath.setH(self.refCS, value)
|
||||
elif axis == 'p':
|
||||
nodePath.setP(self.refCS, value)
|
||||
elif axis == 'r':
|
||||
nodePath.setR(self.refCS, value)
|
||||
else:
|
||||
if axis == 'h':
|
||||
self.deltaHpr.setX(value)
|
||||
elif axis == 'p':
|
||||
self.deltaHpr.setY(value)
|
||||
elif axis == 'r':
|
||||
self.deltaHpr.setZ(value)
|
||||
# Put node path at new hpr
|
||||
nodePath.setHpr(self.refCS, self.deltaHpr)
|
||||
|
||||
def xformOrbit(self, value, axis):
|
||||
nodePath = self['nodePath']
|
||||
|
@ -163,11 +163,11 @@ class VectorEntry(Pmw.MegaWidget):
|
||||
def getAt(self,index):
|
||||
return self._value[index]
|
||||
|
||||
def set(self, value):
|
||||
def set(self, value, fCommand = 0):
|
||||
for i in range(self['dim']):
|
||||
self._value[i] = value[i]
|
||||
self.variableList[i].set(self.entryFormat % value[i])
|
||||
self.action()
|
||||
self.action(fCommand)
|
||||
|
||||
def setAt(self, index, value):
|
||||
self.variableList[index].set(self.entryFormat % value)
|
||||
@ -207,9 +207,9 @@ class VectorEntry(Pmw.MegaWidget):
|
||||
if self._floaters:
|
||||
self._floaters.set(self._value, 0)
|
||||
|
||||
def action(self):
|
||||
def action(self, fCommand = 0):
|
||||
self._refreshFloaters()
|
||||
if self['command']:
|
||||
if fCommand & (self['command'] != None):
|
||||
self['command'](self._value)
|
||||
|
||||
def reset(self):
|
||||
|
Loading…
x
Reference in New Issue
Block a user