mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-02 01:44:06 -04:00
*** empty log message ***
This commit is contained in:
parent
f3068ee1bc
commit
98eda01daa
@ -1,86 +1,88 @@
|
||||
from PandaModules import *
|
||||
from PandaObject import *
|
||||
|
||||
X_AXIS = Vec3(1,0,0)
|
||||
Y_AXIS = Vec3(0,1,0)
|
||||
Z_AXIS = Vec3(0,0,1)
|
||||
NEG_X_AXIS = Vec3(-1,0,0)
|
||||
NEG_Y_AXIS = Vec3(0,-1,0)
|
||||
NEG_Z_AXIS = Vec3(0,0,-1)
|
||||
ZERO_VEC = ORIGIN = Vec3(0)
|
||||
UNIT_VEC = Vec3(1)
|
||||
ZERO_POINT = Point3(0)
|
||||
|
||||
class LineNodePath(NodePath):
|
||||
def __init__(self, parent = None, **kw):
|
||||
|
||||
# Initialize the superclass
|
||||
NodePath.__init__(self)
|
||||
|
||||
if parent is None:
|
||||
parent = hidden
|
||||
|
||||
# Attach a geomNode to the parent and set self to be
|
||||
# the resulting node path
|
||||
self.lineNode = GeomNode()
|
||||
self.assign(parent.attachNewNode( self.lineNode ))
|
||||
|
||||
# Create a lineSegs object to hold the line
|
||||
ls = self.lineSegs = LineSegs()
|
||||
# Initialize the lineSegs parameters
|
||||
ls.setThickness( kw.get('thickness', 1.0) )
|
||||
ls.setColor( kw.get('colorVec', VBase4(1.0)) )
|
||||
|
||||
def moveTo( self, *_args ):
|
||||
apply( self.lineSegs.moveTo, _args )
|
||||
|
||||
def drawTo( self, *_args ):
|
||||
apply( self.lineSegs.drawTo, _args )
|
||||
|
||||
def create( self, frameAccurate = 0 ):
|
||||
self.lineSegs.create( self.lineNode, frameAccurate )
|
||||
|
||||
def reset( self ):
|
||||
self.lineSegs.reset()
|
||||
self.lineNode.clear()
|
||||
|
||||
def isEmpty( self ):
|
||||
return self.lineSegs.isEmpty()
|
||||
|
||||
def setThickness( self, thickness ):
|
||||
self.lineSegs.setThickness( thickness )
|
||||
|
||||
def setColor( self, *_args ):
|
||||
apply( self.lineSegs.setColor, _args )
|
||||
|
||||
def setVertex( self, *_args):
|
||||
apply( self.lineSegs.setVertex, _args )
|
||||
|
||||
def setVertexColor( self, vertex, *_args ):
|
||||
apply( self.lineSegs.setVertexColor, (vertex,) + _args )
|
||||
|
||||
def getCurrentPosition( self ):
|
||||
return self.lineSegs.getCurrentPosition()
|
||||
|
||||
def getNumVertices( self ):
|
||||
return self.lineSegs.getNumVertices()
|
||||
|
||||
def getVertex( self, index ):
|
||||
return self.lineSegs.getVertex(index)
|
||||
|
||||
def getVertexColor( self ):
|
||||
return self.lineSegs.getVertexColor()
|
||||
|
||||
|
||||
##
|
||||
## Given a point in space, and a direction, find the point of intersection
|
||||
## of that ray with a plane at the specified origin, with the specified normal
|
||||
def planeIntersect (lineOrigin, lineDir, planeOrigin, normal):
|
||||
t = 0
|
||||
offset = planeOrigin - lineOrigin
|
||||
t = offset.dot(normal) / lineDir.dot(normal)
|
||||
hitPt = lineDir * t
|
||||
return hitPt + lineOrigin
|
||||
|
||||
def roundTo(value, divisor):
|
||||
return round(value/float(divisor)) * divisor
|
||||
from PandaModules import *
|
||||
from PandaObject import *
|
||||
|
||||
X_AXIS = Vec3(1,0,0)
|
||||
Y_AXIS = Vec3(0,1,0)
|
||||
Z_AXIS = Vec3(0,0,1)
|
||||
NEG_X_AXIS = Vec3(-1,0,0)
|
||||
NEG_Y_AXIS = Vec3(0,-1,0)
|
||||
NEG_Z_AXIS = Vec3(0,0,-1)
|
||||
ZERO_VEC = ORIGIN = Vec3(0)
|
||||
UNIT_VEC = Vec3(1)
|
||||
ZERO_POINT = Point3(0)
|
||||
|
||||
class LineNodePath(NodePath):
|
||||
def __init__(self, parent = None, **kw):
|
||||
|
||||
# Initialize the superclass
|
||||
NodePath.__init__(self)
|
||||
|
||||
if parent is None:
|
||||
parent = hidden
|
||||
|
||||
# Attach a geomNode to the parent and set self to be
|
||||
# the resulting node path
|
||||
self.lineNode = GeomNode()
|
||||
self.assign(parent.attachNewNode( self.lineNode ))
|
||||
|
||||
# Create a lineSegs object to hold the line
|
||||
ls = self.lineSegs = LineSegs()
|
||||
# Initialize the lineSegs parameters
|
||||
ls.setThickness( kw.get('thickness', 1.0) )
|
||||
ls.setColor( kw.get('colorVec', VBase4(1.0)) )
|
||||
|
||||
def moveTo( self, *_args ):
|
||||
apply( self.lineSegs.moveTo, _args )
|
||||
|
||||
def drawTo( self, *_args ):
|
||||
apply( self.lineSegs.drawTo, _args )
|
||||
|
||||
def create( self, frameAccurate = 0 ):
|
||||
self.lineSegs.create( self.lineNode, frameAccurate )
|
||||
|
||||
def reset( self ):
|
||||
self.lineSegs.reset()
|
||||
self.lineNode.clear()
|
||||
|
||||
def isEmpty( self ):
|
||||
return self.lineSegs.isEmpty()
|
||||
|
||||
def setThickness( self, thickness ):
|
||||
self.lineSegs.setThickness( thickness )
|
||||
|
||||
def setColor( self, *_args ):
|
||||
apply( self.lineSegs.setColor, _args )
|
||||
|
||||
def setVertex( self, *_args):
|
||||
apply( self.lineSegs.setVertex, _args )
|
||||
|
||||
def setVertexColor( self, vertex, *_args ):
|
||||
apply( self.lineSegs.setVertexColor, (vertex,) + _args )
|
||||
|
||||
def getCurrentPosition( self ):
|
||||
return self.lineSegs.getCurrentPosition()
|
||||
|
||||
def getNumVertices( self ):
|
||||
return self.lineSegs.getNumVertices()
|
||||
|
||||
def getVertex( self, index ):
|
||||
return self.lineSegs.getVertex(index)
|
||||
|
||||
def getVertexColor( self ):
|
||||
return self.lineSegs.getVertexColor()
|
||||
|
||||
|
||||
##
|
||||
## Given a point in space, and a direction, find the point of intersection
|
||||
## of that ray with a plane at the specified origin, with the specified normal
|
||||
def planeIntersect (lineOrigin, lineDir, planeOrigin, normal):
|
||||
t = 0
|
||||
offset = planeOrigin - lineOrigin
|
||||
t = offset.dot(normal) / lineDir.dot(normal)
|
||||
hitPt = lineDir * t
|
||||
return hitPt + lineOrigin
|
||||
|
||||
def ROUND_TO(value, divisor):
|
||||
return round(value/float(divisor)) * divisor
|
||||
def ROUND_INT(val):
|
||||
return int(round(val))
|
||||
|
@ -114,9 +114,9 @@ class DirectGrid(NodePath,PandaObject):
|
||||
# Snap if necessary
|
||||
if self.fXyzSnap:
|
||||
self.snapPos.set(
|
||||
roundTo(self.snapPos[0], self.gridSpacing),
|
||||
roundTo(self.snapPos[1], self.gridSpacing),
|
||||
roundTo(self.snapPos[2], self.gridSpacing))
|
||||
ROUND_TO(self.snapPos[0], self.gridSpacing),
|
||||
ROUND_TO(self.snapPos[1], self.gridSpacing),
|
||||
ROUND_TO(self.snapPos[2], self.gridSpacing))
|
||||
|
||||
# Move snap marker to this point
|
||||
self.snapMarker.setPos(self.snapPos)
|
||||
@ -125,7 +125,7 @@ class DirectGrid(NodePath,PandaObject):
|
||||
return self.snapPos
|
||||
|
||||
def computeSnapAngle(self, angle):
|
||||
return roundTo(angle, self.snapAngle)
|
||||
return ROUND_TO(angle, self.snapAngle)
|
||||
|
||||
def setSnapAngle(self, angle):
|
||||
self.snapAngle = angle
|
||||
|
@ -2,7 +2,8 @@ from PandaObject import *
|
||||
from DirectGeometry import *
|
||||
|
||||
MANIPULATION_MOVE_DELAY = 0.65
|
||||
VISIBLE_DISCS = ['x-disc-visible', 'y-disc-visible', 'z-disc-visible']
|
||||
UNPICKABLE = ['x-disc-visible', 'y-disc-visible', 'z-disc-visible',
|
||||
'GridBack']
|
||||
|
||||
class DirectManipulationControl(PandaObject):
|
||||
def __init__(self):
|
||||
@ -24,6 +25,7 @@ class DirectManipulationControl(PandaObject):
|
||||
self.fWidgetTop = 0
|
||||
self.fFreeManip = 1
|
||||
self.fScaling = 1
|
||||
self.unpickable = UNPICKABLE
|
||||
self.mode = None
|
||||
|
||||
def manipulationStart(self, chan):
|
||||
@ -102,7 +104,7 @@ class DirectManipulationControl(PandaObject):
|
||||
# Is it a named node?, If so, see if it has a name
|
||||
elif issubclass(node.__class__, NamedNode):
|
||||
name = node.getName()
|
||||
if name in VISIBLE_DISCS:
|
||||
if name in self.unpickable:
|
||||
pass
|
||||
else:
|
||||
index = i
|
||||
@ -119,7 +121,7 @@ class DirectManipulationControl(PandaObject):
|
||||
# Find the node path from the node found above
|
||||
nodePath = render.findPathDownTo(node)
|
||||
# Select it
|
||||
direct.select(nodePath)
|
||||
direct.select(nodePath, direct.fShift)
|
||||
else:
|
||||
direct.deselectAll()
|
||||
else:
|
||||
@ -136,11 +138,15 @@ class DirectManipulationControl(PandaObject):
|
||||
self.objectHandles.showAllHandles()
|
||||
self.objectHandles.hideGuides()
|
||||
# Restart followSelectedNodePath task
|
||||
if direct.selected.last:
|
||||
self.spawnFollowSelectedNodePathTask()
|
||||
self.spawnFollowSelectedNodePathTask()
|
||||
messenger.send('manipulateObjectCleanup')
|
||||
|
||||
def spawnFollowSelectedNodePathTask(self):
|
||||
# If nothing selected, just return
|
||||
if not direct.selected.last:
|
||||
return
|
||||
# Clear out old task to make sure
|
||||
taskMgr.removeTasksNamed('followSelectedNodePath')
|
||||
# Where are the object handles relative to the selected object
|
||||
pos = VBase3(0)
|
||||
hpr = VBase3(0)
|
||||
@ -183,6 +189,14 @@ class DirectManipulationControl(PandaObject):
|
||||
self.ignore(',')
|
||||
self.ignore('F')
|
||||
|
||||
def addUnpickable(self, item):
|
||||
if item not in self.unpickable:
|
||||
self.unpickable.append(item)
|
||||
|
||||
def removeUnpickable(self, item):
|
||||
if item in self.unpickable:
|
||||
self.unpickable.remove(item)
|
||||
|
||||
def removeManipulateObjectTask(self):
|
||||
taskMgr.removeTasksNamed('manipulateObject')
|
||||
|
||||
@ -435,9 +449,8 @@ class DirectManipulationControl(PandaObject):
|
||||
# Compute widget2newWidget relative to base coordinate system
|
||||
mWidget2Base = direct.widget.getMat(base)
|
||||
mBase2NewBase = Mat4()
|
||||
mBase2NewBase.composeMatrix(
|
||||
UNIT_VEC, VBase3(h,p,r), ZERO_VEC,
|
||||
CSDefault)
|
||||
composeMatrix(mBase2NewBase, UNIT_VEC, VBase3(h,p,r), ZERO_VEC,
|
||||
CSDefault)
|
||||
mBase2Widget = base.getMat(direct.widget)
|
||||
mWidget2Parent = direct.widget.getMat()
|
||||
# Compose the result
|
||||
|
@ -2,7 +2,7 @@ from PandaObject import *
|
||||
from DirectGeometry import *
|
||||
from DirectSelection import *
|
||||
|
||||
|
||||
# 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
|
||||
def __init__(self, nodePath):
|
||||
@ -47,11 +47,15 @@ class DirectNodePath(NodePath):
|
||||
|
||||
class SelectedNodePaths(PandaObject):
|
||||
def __init__(self):
|
||||
self.reset()
|
||||
|
||||
def reset(self):
|
||||
self.selectedDict = {}
|
||||
self.deselectedDict = {}
|
||||
self.last = None
|
||||
|
||||
def select(self, nodePath, fMultiSelect = 0):
|
||||
""" Select the specified node path. Multiselect as required """
|
||||
# Do nothing if nothing selected
|
||||
if not nodePath:
|
||||
print 'Nothing selected!!'
|
||||
@ -60,21 +64,20 @@ class SelectedNodePaths(PandaObject):
|
||||
# Reset selected objects and highlight if multiSelect is false
|
||||
if not fMultiSelect:
|
||||
self.deselectAll()
|
||||
|
||||
|
||||
# Get this pointer
|
||||
id = nodePath.id()
|
||||
# First see if its already in the selected dictionary
|
||||
dnp = self.selectedDict.get(id, None)
|
||||
dnp = self.getSelectedDict(id)
|
||||
# If so, we're done
|
||||
if not dnp:
|
||||
# See if it is in the deselected dictionary
|
||||
dnp = self.deselectedDict.get(id, None)
|
||||
dnp = self.getDeselectedDict(id)
|
||||
if dnp:
|
||||
# It has been previously selected:
|
||||
# Show its bounding box
|
||||
dnp.highlight()
|
||||
# Remove it from the deselected dictionary
|
||||
del(self.deselectedDict[id])
|
||||
# Show its bounding box
|
||||
dnp.highlight()
|
||||
else:
|
||||
# Didn't find it, create a new selectedNodePath instance
|
||||
dnp = DirectNodePath(nodePath)
|
||||
@ -87,10 +90,11 @@ class SelectedNodePaths(PandaObject):
|
||||
return dnp
|
||||
|
||||
def deselect(self, nodePath):
|
||||
""" Deselect the specified node path """
|
||||
# Get this pointer
|
||||
id = nodePath.id()
|
||||
# See if it is in the selected dictionary
|
||||
dnp = self.selectedDict.get(id, None)
|
||||
dnp = self.getSelectedDict(id)
|
||||
if dnp:
|
||||
# It was selected:
|
||||
# Hide its bounding box
|
||||
@ -101,30 +105,80 @@ class SelectedNodePaths(PandaObject):
|
||||
self.deselectedDict[id] = dnp
|
||||
return dnp
|
||||
|
||||
def selectedAsList(self):
|
||||
list = []
|
||||
for key in self.selectedDict.keys():
|
||||
list.append(self.selectedDict[key])
|
||||
return list
|
||||
def getSelectedAsList(self):
|
||||
"""
|
||||
Return a list of all selected node paths. No verification of
|
||||
connectivity is performed on the members of the list
|
||||
"""
|
||||
return self.selectedDict.values()[:]
|
||||
|
||||
def __getitem__(self,index):
|
||||
return self.selectedAsList()[index]
|
||||
return self.getSelectedAsList()[index]
|
||||
|
||||
def deselectedAsList(self):
|
||||
list = []
|
||||
for key in self.deselectedDict.keys():
|
||||
list.append(self.deselectedDict[key])
|
||||
return list
|
||||
def getSelectedDict(self, id):
|
||||
"""
|
||||
Search selectedDict for node path, try to repair broken node paths.
|
||||
"""
|
||||
dnp = self.selectedDict.get(id, None)
|
||||
if dnp:
|
||||
# Found item in selected Dictionary, is it still valid?
|
||||
if dnp.verifyConnectivity():
|
||||
# Yes
|
||||
return dnp
|
||||
else:
|
||||
# Not valid anymore, try to repair
|
||||
if dnp.repairConnectivity(render):
|
||||
# Fixed, return node path
|
||||
return dnp
|
||||
else:
|
||||
del(self.selectedDict[id])
|
||||
return None
|
||||
else:
|
||||
# Not in selected dictionary
|
||||
return None
|
||||
|
||||
def getDeselectedAsList(self):
|
||||
return self.deselectedDict.values()[:]
|
||||
|
||||
def getDeselectedDict(self, id):
|
||||
"""
|
||||
Search deselectedDict for node path, try to repair broken node paths.
|
||||
"""
|
||||
dnp = self.deselectedDict.get(id, None)
|
||||
if dnp:
|
||||
# Found item in deselected Dictionary, is it still valid?
|
||||
if dnp.verifyConnectivity():
|
||||
# Yes
|
||||
return dnp
|
||||
else:
|
||||
# Not valid anymore, try to repair
|
||||
if dnp.repairConnectivity(render):
|
||||
# Fixed, return node path
|
||||
return dnp
|
||||
else:
|
||||
del(self.deselectedDict[id])
|
||||
return None
|
||||
else:
|
||||
# Not in deselected dictionary
|
||||
return None
|
||||
|
||||
def forEachSelectedNodePathDo(self, func):
|
||||
duplicateKeys = self.selectedDict.keys()[:]
|
||||
for key in duplicateKeys:
|
||||
func(self.selectedDict[key])
|
||||
"""
|
||||
Perform given func on selected node paths. No node path
|
||||
connectivity verification performed
|
||||
"""
|
||||
selectedNodePaths = self.getSelectedAsList()
|
||||
for nodePath in selectedNodePaths:
|
||||
func(nodePath)
|
||||
|
||||
def forEachDeselectedNodePathDo(self, func):
|
||||
duplicateKeys = self.deselectedDict.keys()[:]
|
||||
for key in duplicateKeys:
|
||||
func(self.deselectedDict[key])
|
||||
"""
|
||||
Perform given func on deselected node paths. No node path
|
||||
connectivity verification performed
|
||||
"""
|
||||
deselectedNodePaths = self.getDeselectedAsList()
|
||||
for nodePath in deselectedNodePaths:
|
||||
func(nodePath)
|
||||
|
||||
def getWrtAll(self):
|
||||
self.forEachSelectedNodePathDo(self.getWrt)
|
||||
@ -175,11 +229,11 @@ class SelectedNodePaths(PandaObject):
|
||||
# Get this pointer
|
||||
id = nodePath.id()
|
||||
# First check selected dict
|
||||
dnp = self.selectedDict.get(id, None)
|
||||
dnp = self.getSelectedDict(id)
|
||||
if dnp:
|
||||
return dnp
|
||||
# Otherwise return result of deselected search
|
||||
return self.selectedDict.get(id, None)
|
||||
return self.getDeselectedDict(id)
|
||||
|
||||
def getNumSelected(self):
|
||||
return len(self.selectedDict.keys())
|
||||
|
@ -63,8 +63,8 @@ class DirectSession(PandaObject):
|
||||
'mouse2', 'mouse2-up',
|
||||
'mouse3', 'mouse3-up']
|
||||
|
||||
def select(self, nodePath):
|
||||
dnp = self.selected.select(nodePath)
|
||||
def select(self, nodePath, fMultiselect = 0):
|
||||
dnp = self.selected.select(nodePath, fMultiselect)
|
||||
if dnp:
|
||||
messenger.send('preSelectNodePath', [dnp])
|
||||
# Update the readout
|
||||
@ -127,6 +127,8 @@ class DirectSession(PandaObject):
|
||||
self.cameraControl.enableMouseFly()
|
||||
# Turn on object manipulation
|
||||
self.manipulationControl.enableManipulation()
|
||||
# Make sure list of selected items is reset
|
||||
self.selected.reset()
|
||||
# Accept appropriate hooks
|
||||
self.enableKeyEvents()
|
||||
self.enableMouseEvents()
|
||||
@ -159,7 +161,7 @@ class DirectSession(PandaObject):
|
||||
def destroy(self):
|
||||
self.disable()
|
||||
|
||||
def restart(self):
|
||||
def reset(self):
|
||||
self.enable()
|
||||
|
||||
def enableActionEvents(self):
|
||||
|
@ -23,6 +23,15 @@
|
||||
name = namedNodeName
|
||||
return name
|
||||
|
||||
def setName(self, name = '<noname>'):
|
||||
"""Returns the name of the bottom node if it exists, or <noname>"""
|
||||
from PandaModules import *
|
||||
# Get the bottom node
|
||||
node = self.node()
|
||||
# Is it a named node?, If so, see if it has a name
|
||||
if issubclass(node.__class__, NamedNode):
|
||||
node.setName(name)
|
||||
|
||||
# For iterating over children
|
||||
def getChildrenAsList(self):
|
||||
"""Converts a node path's child NodePathCollection into a list"""
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2,28 +2,29 @@ from PandaObject import *
|
||||
from DirectGeometry import *
|
||||
|
||||
class PieMenu(NodePath, PandaObject):
|
||||
def __init__(self, direct, menu, action = None, fUpdateOnlyOnChange = 1):
|
||||
def __init__(self, visibleMenu, menuItems,
|
||||
action = None, fUpdateOnlyOnChange = 1):
|
||||
NodePath.__init__(self)
|
||||
# Create a toplevel node for aspect ratio scaling
|
||||
self.assign(hidden.attachNewNode(NamedNode('PieMenu')))
|
||||
# Attach the menu
|
||||
self.menu = menu
|
||||
# Try to flatten the menu (note, flattenStrong is too strong
|
||||
self.visibleMenu = visibleMenu
|
||||
# Try to flatten the visibleMenu (note, flattenStrong is too strong
|
||||
# for texture text
|
||||
menu.flattenMedium()
|
||||
self.menu.reparentTo(self)
|
||||
self.visibleMenu.flattenMedium()
|
||||
self.visibleMenu.reparentTo(self)
|
||||
# Initialize instance variables
|
||||
self.direct = direct
|
||||
self.numItems = self.menu.getNumChildren()
|
||||
self.menuItems = menuItems
|
||||
self.numItems = len(self.menuItems)
|
||||
self.degreesPerItem = 360.0/self.numItems
|
||||
self.itemOffset = self.degreesPerItem / 2.0
|
||||
self.sfx = self.menu.getSx()
|
||||
self.sfz = self.menu.getSz()
|
||||
self.sfx = self.visibleMenu.getSx()
|
||||
self.sfz = self.visibleMenu.getSz()
|
||||
# Record target and action
|
||||
self.action = action
|
||||
self.initialState = None
|
||||
# Marking lines
|
||||
self.lines = LineNodePath(self.menu)
|
||||
self.lines = LineNodePath(self.visibleMenu)
|
||||
self.lines.setColor(VBase4(1))
|
||||
self.lines.setThickness(1)
|
||||
# Set flags
|
||||
@ -43,15 +44,15 @@ class PieMenu(NodePath, PandaObject):
|
||||
taskMgr.removeTasksNamed('pieMenuTask')
|
||||
|
||||
# Where did the user press the button?
|
||||
self.originX = self.direct.chan.mouseX
|
||||
self.originY = self.direct.chan.mouseY
|
||||
self.originX = direct.chan.mouseX
|
||||
self.originY = direct.chan.mouseY
|
||||
|
||||
# Pop up menu
|
||||
self.reparentTo(render2d)
|
||||
self.setPos(self.originX,0.0,self.originY)
|
||||
# Compensate for window aspect ratio
|
||||
self.setScale(1.0, 1.0,1.0)
|
||||
#self.direct.chan.width/float(self.direct.chan.height))
|
||||
#direct.chan.width/float(direct.chan.height))
|
||||
# Start drawing the selection line
|
||||
self.lines.reset()
|
||||
self.lines.moveTo(0,0,0)
|
||||
@ -64,8 +65,8 @@ class PieMenu(NodePath, PandaObject):
|
||||
taskMgr.spawnTaskNamed(t, 'pieMenuTask')
|
||||
|
||||
def pieMenuTask(self,state):
|
||||
mouseX = self.direct.chan.mouseX
|
||||
mouseY = self.direct.chan.mouseY
|
||||
mouseX = direct.chan.mouseX
|
||||
mouseY = direct.chan.mouseY
|
||||
deltaX = mouseX - self.originX
|
||||
deltaY = mouseY - self.originY
|
||||
|
||||
@ -78,10 +79,10 @@ class PieMenu(NodePath, PandaObject):
|
||||
if self.fUpdateOnlyOnChange:
|
||||
# Only do this when things change
|
||||
if (self.currItem != -1):
|
||||
self.performAction(-1)
|
||||
self.performAction(self.initialState)
|
||||
else:
|
||||
# Alway let use know mouse is in the center
|
||||
self.performAction(-1)
|
||||
self.performAction(self.initialState)
|
||||
self.currItem = -1
|
||||
else:
|
||||
# Outside of the center
|
||||
@ -95,9 +96,9 @@ class PieMenu(NodePath, PandaObject):
|
||||
|
||||
if self.fUpdateOnlyOnChange:
|
||||
if (self.currItem != newItem):
|
||||
self.performAction(newItem)
|
||||
self.performAction(self.menuItems[newItem])
|
||||
else:
|
||||
self.performAction(newItem)
|
||||
self.performAction(self.menuItems[newItem])
|
||||
self.currItem = newItem
|
||||
# Continue task
|
||||
return Task.cont
|
||||
@ -111,11 +112,6 @@ class PieMenu(NodePath, PandaObject):
|
||||
def setItemOffset(self,newOffset):
|
||||
self.itemOffset = newOffset
|
||||
|
||||
def setNumItems(self,num):
|
||||
self.numItems = num
|
||||
self.degreesPerItem = 360.0 / self.numItems
|
||||
self.itemOffset = self.degreesPerItem / 2.0
|
||||
|
||||
def setUpdateOnlyOnChange(self,flag):
|
||||
self.fUpdateOnlyOnChange = flag
|
||||
|
||||
|
@ -9,7 +9,7 @@ def tkloop(self):
|
||||
# dooneevent will return 0 if there are no more events
|
||||
# waiting or 1 if there are still more.
|
||||
# DONT_WAIT tells tkinter not to block waiting for events
|
||||
while tkinter.dooneevent(tkinter.DONT_WAIT):
|
||||
while tkinter.dooneevent(tkinter.ALL_EVENTS | tkinter.DONT_WAIT):
|
||||
pass
|
||||
# Run forever
|
||||
return Task.cont
|
||||
@ -19,3 +19,5 @@ from TaskManagerGlobal import *
|
||||
|
||||
# Spawn this task
|
||||
taskMgr.spawnTaskNamed(Task.Task(tkloop), "tkloop")
|
||||
|
||||
|
||||
|
@ -1,120 +1,129 @@
|
||||
from PandaObject import *
|
||||
from Tkinter import *
|
||||
from Tree import *
|
||||
import Pmw
|
||||
|
||||
|
||||
class SceneGraphExplorer(Pmw.MegaWidget):
|
||||
"Graphical display of a scene graph"
|
||||
def __init__(self, root = render, parent = None, **kw):
|
||||
# Define the megawidget options.
|
||||
optiondefs = (
|
||||
('menuItems', ['Select'], None),
|
||||
)
|
||||
self.defineoptions(kw, optiondefs)
|
||||
|
||||
# Initialise superclass
|
||||
Pmw.MegaWidget.__init__(self, parent)
|
||||
|
||||
# Initialize some class variables
|
||||
self.root = root
|
||||
|
||||
# Create the components.
|
||||
|
||||
# Setup up container
|
||||
interior = self.interior()
|
||||
interior.configure(relief = GROOVE, borderwidth = 2)
|
||||
|
||||
# Create a label and an entry
|
||||
self._scrolledCanvas = self.createcomponent(
|
||||
'scrolledCanvas',
|
||||
(), None,
|
||||
Pmw.ScrolledCanvas, (interior,),
|
||||
hull_width = 200, hull_height = 400,
|
||||
usehullsize = 1)
|
||||
self._canvas = self._scrolledCanvas.component('canvas')
|
||||
self._canvas['scrollregion'] = ('0i', '0i', '2i', '4i')
|
||||
self._scrolledCanvas.resizescrollregion()
|
||||
self._scrolledCanvas.pack(padx = 5, pady = 5, expand=1, fill = BOTH)
|
||||
|
||||
self._canvas.bind('<ButtonPress-2>', self.mouse2Down)
|
||||
self._canvas.bind('<B2-Motion>', self.mouse2Motion)
|
||||
self._canvas.bind('<Configure>',
|
||||
lambda e, sc = self._scrolledCanvas:
|
||||
sc.resizescrollregion())
|
||||
|
||||
# Create the contents
|
||||
self._treeItem = SceneGraphExplorerItem(self.root)
|
||||
|
||||
self._node = TreeNode(self._canvas, None, self._treeItem,
|
||||
self['menuItems'])
|
||||
self._node.expand()
|
||||
|
||||
# Check keywords and initialise options based on input values.
|
||||
self.initialiseoptions(SceneGraphExplorer)
|
||||
|
||||
def mouse2Down(self, event):
|
||||
self._width = 1.0 * self._canvas.winfo_width()
|
||||
self._height = 1.0 * self._canvas.winfo_height()
|
||||
xview = self._canvas.xview()
|
||||
yview = self._canvas.yview()
|
||||
self._left = xview[0]
|
||||
self._top = yview[0]
|
||||
self._dxview = xview[1] - xview[0]
|
||||
self._dyview = yview[1] - yview[0]
|
||||
self._2lx = event.x
|
||||
self._2ly = event.y
|
||||
|
||||
def mouse2Motion(self,event):
|
||||
newx = self._left - ((event.x - self._2lx)/self._width) * self._dxview
|
||||
self._canvas.xview_moveto(newx)
|
||||
newy = self._top - ((event.y - self._2ly)/self._height) * self._dyview
|
||||
self._canvas.yview_moveto(newy)
|
||||
self._2lx = event.x
|
||||
self._2ly = event.y
|
||||
self._left = self._canvas.xview()[0]
|
||||
self._top = self._canvas.yview()[0]
|
||||
|
||||
|
||||
class SceneGraphExplorerItem(TreeItem):
|
||||
|
||||
"""Example TreeItem subclass -- browse the file system."""
|
||||
|
||||
def __init__(self, nodePath):
|
||||
self.nodePath = nodePath
|
||||
|
||||
def GetText(self):
|
||||
type = self.nodePath.node().getType().getName()
|
||||
name = self.nodePath.getName()
|
||||
return type + " " + name
|
||||
|
||||
def IsEditable(self):
|
||||
return issubclass(self.nodePath.node().__class__, NamedNode)
|
||||
|
||||
def SetText(self, text):
|
||||
try:
|
||||
self.nodePath.node().setName(text)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def GetIconName(self):
|
||||
if not self.IsExpandable():
|
||||
return "sphere2" # XXX wish there was a "file" icon
|
||||
|
||||
def IsExpandable(self):
|
||||
return self.nodePath.getNumChildren() != 0
|
||||
|
||||
def GetSubList(self):
|
||||
sublist = []
|
||||
for nodePath in self.nodePath.getChildrenAsList():
|
||||
item = SceneGraphExplorerItem(nodePath)
|
||||
sublist.append(item)
|
||||
return sublist
|
||||
|
||||
def OnSelect(self):
|
||||
messenger.send('SGEFlashNodePath', [self.nodePath])
|
||||
|
||||
def MenuCommand(self, command):
|
||||
messenger.send('SGE' + command + 'NodePath', [self.nodePath])
|
||||
|
||||
|
||||
from PandaObject import *
|
||||
from Tkinter import *
|
||||
from Tree import *
|
||||
import Pmw
|
||||
|
||||
class SceneGraphExplorer(Pmw.MegaWidget):
|
||||
"Graphical display of a scene graph"
|
||||
def __init__(self, root = render, parent = None, **kw):
|
||||
# Define the megawidget options.
|
||||
optiondefs = (
|
||||
('menuItems', ['Select'], None),
|
||||
)
|
||||
self.defineoptions(kw, optiondefs)
|
||||
|
||||
# Initialise superclass
|
||||
Pmw.MegaWidget.__init__(self, parent)
|
||||
|
||||
# Initialize some class variables
|
||||
self.root = root
|
||||
|
||||
# Create the components.
|
||||
|
||||
# Setup up container
|
||||
interior = self.interior()
|
||||
interior.configure(relief = GROOVE, borderwidth = 2)
|
||||
|
||||
# Create a label and an entry
|
||||
self._scrolledCanvas = self.createcomponent(
|
||||
'scrolledCanvas',
|
||||
(), None,
|
||||
Pmw.ScrolledCanvas, (interior,),
|
||||
hull_width = 200, hull_height = 400,
|
||||
usehullsize = 1)
|
||||
self._canvas = self._scrolledCanvas.component('canvas')
|
||||
self._canvas['scrollregion'] = ('0i', '0i', '2i', '4i')
|
||||
self._scrolledCanvas.resizescrollregion()
|
||||
self._scrolledCanvas.pack(padx = 5, pady = 5, expand=1, fill = BOTH)
|
||||
|
||||
self._canvas.bind('<ButtonPress-2>', self.mouse2Down)
|
||||
self._canvas.bind('<B2-Motion>', self.mouse2Motion)
|
||||
self._canvas.bind('<Configure>',
|
||||
lambda e, sc = self._scrolledCanvas:
|
||||
sc.resizescrollregion())
|
||||
|
||||
# Create the contents
|
||||
self._treeItem = SceneGraphExplorerItem(self.root)
|
||||
|
||||
self._node = TreeNode(self._canvas, None, self._treeItem,
|
||||
self['menuItems'])
|
||||
self._node.expand()
|
||||
|
||||
# Check keywords and initialise options based on input values.
|
||||
self.initialiseoptions(SceneGraphExplorer)
|
||||
|
||||
def update(self):
|
||||
""" Refresh scene graph explorer """
|
||||
self._node.update()
|
||||
|
||||
def mouse2Down(self, event):
|
||||
self._width = 1.0 * self._canvas.winfo_width()
|
||||
self._height = 1.0 * self._canvas.winfo_height()
|
||||
xview = self._canvas.xview()
|
||||
yview = self._canvas.yview()
|
||||
self._left = xview[0]
|
||||
self._top = yview[0]
|
||||
self._dxview = xview[1] - xview[0]
|
||||
self._dyview = yview[1] - yview[0]
|
||||
self._2lx = event.x
|
||||
self._2ly = event.y
|
||||
|
||||
def mouse2Motion(self,event):
|
||||
newx = self._left - ((event.x - self._2lx)/self._width) * self._dxview
|
||||
self._canvas.xview_moveto(newx)
|
||||
newy = self._top - ((event.y - self._2ly)/self._height) * self._dyview
|
||||
self._canvas.yview_moveto(newy)
|
||||
self._2lx = event.x
|
||||
self._2ly = event.y
|
||||
self._left = self._canvas.xview()[0]
|
||||
self._top = self._canvas.yview()[0]
|
||||
|
||||
|
||||
class SceneGraphExplorerItem(TreeItem):
|
||||
|
||||
"""Example TreeItem subclass -- browse the file system."""
|
||||
|
||||
def __init__(self, nodePath):
|
||||
self.nodePath = nodePath
|
||||
|
||||
def GetText(self):
|
||||
type = self.nodePath.node().getType().getName()
|
||||
name = self.nodePath.getName()
|
||||
return type + " " + name
|
||||
|
||||
def IsEditable(self):
|
||||
return issubclass(self.nodePath.node().__class__, NamedNode)
|
||||
|
||||
def SetText(self, text):
|
||||
try:
|
||||
self.nodePath.node().setName(text)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def GetIconName(self):
|
||||
if not self.IsExpandable():
|
||||
return "sphere2" # XXX wish there was a "file" icon
|
||||
|
||||
def IsExpandable(self):
|
||||
return self.nodePath.getNumChildren() != 0
|
||||
|
||||
def GetSubList(self):
|
||||
sublist = []
|
||||
for nodePath in self.nodePath.getChildrenAsList():
|
||||
item = SceneGraphExplorerItem(nodePath)
|
||||
sublist.append(item)
|
||||
return sublist
|
||||
|
||||
def OnSelect(self):
|
||||
messenger.send('SGENodePath_Flash', [self.nodePath])
|
||||
|
||||
def MenuCommand(self, command):
|
||||
messenger.send('SGENodePath_' + command, [self.nodePath])
|
||||
|
||||
|
||||
def explore(nodePath):
|
||||
tl = Toplevel()
|
||||
tl.title('Explore: ' + nodePath.getName())
|
||||
sge = SceneGraphExplorer(parent = tl, root = nodePath)
|
||||
sge.pack(expand = 1, fill = 'both')
|
||||
return sge
|
||||
|
Loading…
x
Reference in New Issue
Block a user