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

@ -82,5 +82,7 @@ def planeIntersect (lineOrigin, lineDir, planeOrigin, normal):
hitPt = lineDir * t
return hitPt + lineOrigin
def roundTo(value, divisor):
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()
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,8 +449,7 @@ 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,
composeMatrix(mBase2NewBase, UNIT_VEC, VBase3(h,p,r), ZERO_VEC,
CSDefault)
mBase2Widget = base.getMat(direct.widget)
mWidget2Parent = direct.widget.getMat()

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!!'
@ -64,17 +68,16 @@ class SelectedNodePaths(PandaObject):
# 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

@ -3,7 +3,6 @@ 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):
@ -53,6 +52,10 @@ class SceneGraphExplorer(Pmw.MegaWidget):
# 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()
@ -112,9 +115,15 @@ class SceneGraphExplorerItem(TreeItem):
return sublist
def OnSelect(self):
messenger.send('SGEFlashNodePath', [self.nodePath])
messenger.send('SGENodePath_Flash', [self.nodePath])
def MenuCommand(self, command):
messenger.send('SGE' + command + 'NodePath', [self.nodePath])
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