seSceneGraphExplorer.py 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. #################################################################
  2. # seSceneGraphExplorer.py
  3. # Originally from SceneGraphExplorer.py
  4. # Altered by Yi-Hong Lin, [email protected], 2004
  5. #
  6. # we need a customized SceneGraphExplorer.
  7. #
  8. # Do forget to check the seTree.
  9. #
  10. #################################################################
  11. from direct.showbase.DirectObject import DirectObject
  12. from Tkinter import IntVar, Frame, Label
  13. from seTree import TreeNode, TreeItem
  14. import Pmw, Tkinter
  15. # changing these strings requires changing sceneEditor.py SGE_ strs too!
  16. # This list of items will be showed on the pop out window when user right click on
  17. # any node on the graph. And, this is also the main reason we decide to copy from
  18. # the original one but not inherited from it.
  19. # Because except drawing part, we have changed a lot of things...
  20. DEFAULT_MENU_ITEMS = [
  21. 'Update Explorer',
  22. 'Separator',
  23. 'Properties',
  24. 'Separator',
  25. 'Duplicate',
  26. 'Remove',
  27. 'Add Dummy',
  28. 'Add Collision Object',
  29. 'Metadata',
  30. 'Separator',
  31. 'Set as Reparent Target',
  32. 'Reparent to Target',
  33. 'Separator',
  34. 'Animation Panel',
  35. 'Blend Animation Panel',
  36. 'MoPath Panel',
  37. 'Align Tool',
  38. 'Separator']
  39. class seSceneGraphExplorer(Pmw.MegaWidget, DirectObject):
  40. "Graphical display of a scene graph"
  41. def __init__(self, parent = None, nodePath = render, **kw):
  42. # Define the megawidget options.
  43. optiondefs = (
  44. ('menuItems', [], Pmw.INITOPT),
  45. )
  46. self.defineoptions(kw, optiondefs)
  47. # Initialise superclass
  48. Pmw.MegaWidget.__init__(self, parent)
  49. # Initialize some class variables
  50. self.nodePath = nodePath
  51. # Create the components.
  52. # Setup up container
  53. interior = self.interior()
  54. interior.configure(relief = Tkinter.GROOVE, borderwidth = 2)
  55. # Create a label and an entry
  56. self._scrolledCanvas = self.createcomponent(
  57. 'scrolledCanvas',
  58. (), None,
  59. Pmw.ScrolledCanvas, (interior,),
  60. hull_width = 200, hull_height = 300,
  61. usehullsize = 1)
  62. self._canvas = self._scrolledCanvas.component('canvas')
  63. self._canvas['scrollregion'] = ('0i', '0i', '2i', '4i')
  64. self._scrolledCanvas.resizescrollregion()
  65. self._scrolledCanvas.pack(padx = 3, pady = 3, expand=1, fill = Tkinter.BOTH)
  66. self._canvas.bind('<ButtonPress-2>', self.mouse2Down)
  67. self._canvas.bind('<B2-Motion>', self.mouse2Motion)
  68. self._canvas.bind('<Configure>',
  69. lambda e, sc = self._scrolledCanvas:
  70. sc.resizescrollregion())
  71. self.interior().bind('<Destroy>', self.onDestroy)
  72. # Create the contents
  73. self._treeItem = SceneGraphExplorerItem(self.nodePath)
  74. self._node = TreeNode(self._canvas, None, self._treeItem,
  75. DEFAULT_MENU_ITEMS + self['menuItems'])
  76. self._node.expand()
  77. self._parentFrame = Frame(interior)
  78. self._label = self.createcomponent(
  79. 'parentLabel',
  80. (), None,
  81. Label, (interior,),
  82. text = 'Active Reparent Target: ',
  83. anchor = Tkinter.W, justify = Tkinter.LEFT)
  84. self._label.pack(fill = Tkinter.X)
  85. # Add update parent label
  86. def updateLabel(nodePath = None, s = self):
  87. s._label['text'] = 'Active Reparent Target: ' + nodePath.getName()
  88. self.accept('DIRECT_activeParent', updateLabel)
  89. # Add update hook
  90. self.accept('SGE_Update Explorer',
  91. lambda np, s = self: s.update())
  92. # Check keywords and initialise options based on input values.
  93. self.initialiseoptions(seSceneGraphExplorer)
  94. def update(self):
  95. """ Refresh scene graph explorer """
  96. self._node.update()
  97. def mouse2Down(self, event):
  98. self._width = 1.0 * self._canvas.winfo_width()
  99. self._height = 1.0 * self._canvas.winfo_height()
  100. xview = self._canvas.xview()
  101. yview = self._canvas.yview()
  102. self._left = xview[0]
  103. self._top = yview[0]
  104. self._dxview = xview[1] - xview[0]
  105. self._dyview = yview[1] - yview[0]
  106. self._2lx = event.x
  107. self._2ly = event.y
  108. def mouse2Motion(self,event):
  109. newx = self._left - ((event.x - self._2lx)/self._width) * self._dxview
  110. self._canvas.xview_moveto(newx)
  111. newy = self._top - ((event.y - self._2ly)/self._height) * self._dyview
  112. self._canvas.yview_moveto(newy)
  113. self._2lx = event.x
  114. self._2ly = event.y
  115. self._left = self._canvas.xview()[0]
  116. self._top = self._canvas.yview()[0]
  117. def onDestroy(self, event):
  118. # Remove hooks
  119. self.ignore('DIRECT_activeParent')
  120. self.ignore('SGE_Update Explorer')
  121. def deSelectTree(self):
  122. self._node.deselecttree()
  123. def selectNodePath(self,nodePath, callBack=True):
  124. item = self._node.find(nodePath.id())
  125. if item!= None:
  126. item.select(callBack)
  127. else:
  128. print '----SGE: Error Selection'
  129. class SceneGraphExplorerItem(TreeItem):
  130. """Example TreeItem subclass -- browse the file system."""
  131. def __init__(self, nodePath):
  132. self.nodePath = nodePath
  133. def GetText(self):
  134. type = self.nodePath.node().getType().getName()
  135. name = self.nodePath.getName()
  136. return type + " " + name
  137. def GetTextForEdit(self):
  138. name = self.nodePath.getName()
  139. return name
  140. def GetKey(self):
  141. return self.nodePath.id()
  142. def IsEditable(self):
  143. # All nodes' names can be edited nowadays.
  144. return 1
  145. #return issubclass(self.nodePath.node().__class__, NamedNode)
  146. def SetText(self, text):
  147. try:
  148. messenger.send('SGE_changeName', [self.nodePath, text])
  149. except AttributeError:
  150. pass
  151. def GetIconName(self):
  152. return "sphere2" # XXX wish there was a "file" icon
  153. def IsExpandable(self):
  154. return self.nodePath.getNumChildren() != 0
  155. def GetSubList(self):
  156. sublist = []
  157. for nodePath in self.nodePath.getChildrenAsList():
  158. item = SceneGraphExplorerItem(nodePath)
  159. sublist.append(item)
  160. return sublist
  161. def OnSelect(self, callback):
  162. messenger.send('SGE_Flash', [self.nodePath])
  163. if not callback:
  164. messenger.send('SGE_madeSelection', [self.nodePath, callback])
  165. else:
  166. messenger.send('SGE_madeSelection', [self.nodePath])
  167. def MenuCommand(self, command):
  168. messenger.send('SGE_' + command, [self.nodePath])
  169. def explore(nodePath = render):
  170. tl = Toplevel()
  171. tl.title('Explore: ' + nodePath.getName())
  172. sge = seSceneGraphExplorer(parent = tl, nodePath = nodePath)
  173. sge.pack(expand = 1, fill = 'both')
  174. return sge