*** empty log message ***

This commit is contained in:
Mark Mine 2001-01-03 22:54:21 +00:00
parent f3068ee1bc
commit 98eda01daa
10 changed files with 3136 additions and 3218 deletions

View File

@ -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))

View File

@ -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

View File

@ -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

View File

@ -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())

View File

@ -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):

View File

@ -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

View File

@ -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

View File

@ -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")

View File

@ -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