SceneGraphUI.py 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. """
  2. Defines Scene Graph tree UI
  3. """
  4. import wx
  5. import cPickle as pickle
  6. from pandac.PandaModules import *
  7. import ObjectGlobals as OG
  8. class SceneGraphUIDropTarget(wx.TextDropTarget):
  9. def __init__(self, editor):
  10. print "in SceneGraphUIDropTarget::init..."
  11. wx.TextDropTarget.__init__(self)
  12. self.editor = editor
  13. def OnDropText(self, x, y, text):
  14. print "in SceneGraphUIDropTarget::OnDropText..."
  15. self.editor.ui.sceneGraphUI.changeHierarchy(text, x, y)
  16. class SceneGraphUI(wx.Panel):
  17. def __init__(self, parent, editor):
  18. wx.Panel.__init__(self, parent)
  19. self.editor = editor
  20. self.tree = wx.TreeCtrl(self, id=-1, pos=wx.DefaultPosition,
  21. size=wx.DefaultSize, style=wx.TR_MULTIPLE|wx.TR_DEFAULT_STYLE,
  22. validator=wx.DefaultValidator, name="treeCtrl")
  23. self.root = self.tree.AddRoot('render')
  24. self.tree.SetItemPyData(self.root, "render")
  25. self.shouldShowPandaObjChildren = False
  26. sizer = wx.BoxSizer(wx.VERTICAL)
  27. sizer.Add(self.tree, 1, wx.EXPAND, 0)
  28. self.SetSizer(sizer); self.Layout()
  29. parentSizer = wx.BoxSizer(wx.VERTICAL)
  30. parentSizer.Add(self, 1, wx.EXPAND, 0)
  31. parent.SetSizer(parentSizer); parent.Layout()
  32. parent.SetDropTarget(SceneGraphUIDropTarget(self.editor))
  33. self.tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.onSelected)
  34. self.tree.Bind(wx.EVT_TREE_BEGIN_DRAG, self.onBeginDrag)
  35. def reset(self):
  36. #import pdb;set_trace()
  37. itemList = list()
  38. item, cookie = self.tree.GetFirstChild(self.root)
  39. while item:
  40. itemList.append(item)
  41. item, cookie = self.tree.GetNextChild(self.root, cookie)
  42. for item in itemList:
  43. self.tree.Delete(item)
  44. def traversePandaObjects(self, parent, objNodePath):
  45. itemId = self.tree.GetItemPyData(parent)
  46. i = 0
  47. for child in objNodePath.getChildren():
  48. namestr = "%s.%s"%(child.node().getType(), child.node().getName())
  49. newItem = self.tree.PrependItem(parent, namestr)
  50. newItemId = "%s.%s"%(itemId, i)
  51. self.tree.SetItemPyData(newItem, newItemId)
  52. # recursing...
  53. self.traversePandaObjects(newItem, child)
  54. i = i + 1
  55. def addPandaObjectChildren(self, parent):
  56. # first, find Panda Object's NodePath of the item
  57. itemId = self.tree.GetItemPyData(parent)
  58. if itemId == "render":
  59. return
  60. obj = self.editor.objectMgr.findObjectById(itemId)
  61. if obj is None:
  62. return
  63. objNodePath = obj[OG.OBJ_NP]
  64. self.traversePandaObjects(parent, objNodePath)
  65. item, cookie = self.tree.GetFirstChild(parent)
  66. while item:
  67. # recursing...
  68. self.addPandaObjectChildren(item)
  69. item, cookie = self.tree.GetNextChild(parent, cookie)
  70. def removePandaObjectChildren(self, parent):
  71. # first, find Panda Object's NodePath of the item
  72. itemId = self.tree.GetItemPyData(parent)
  73. if itemId == "render":
  74. return
  75. obj = self.editor.objectMgr.findObjectById(itemId)
  76. if obj is None:
  77. self.tree.Delete(parent)
  78. return
  79. item, cookie = self.tree.GetFirstChild(parent)
  80. while item:
  81. # recurse...
  82. itemToRemove = item
  83. # continue iteration to the next child
  84. item, cookie = self.tree.GetNextChild(parent, cookie)
  85. self.removePandaObjectChildren(itemToRemove)
  86. def getTreeItem(self, parent, itemId):
  87. item, cookie = self.tree.GetFirstChild(parent)
  88. while item:
  89. if itemId == self.tree.GetItemPyData(item):
  90. return item
  91. child = None
  92. if self.tree.ItemHasChildren(item):
  93. child = self.getTreeItem(item, itemId)
  94. if child is not None:
  95. return child
  96. # continue iteration to the next child
  97. item, cookie = self.tree.GetNextChild(parent, cookie)
  98. return None
  99. def add(self, item):
  100. #import pdb;pdb.set_trace()
  101. if item is None:
  102. return
  103. obj = self.editor.objectMgr.findObjectByNodePath(NodePath(item))
  104. if obj is None:
  105. return
  106. parentNodePath = obj[OG.OBJ_NP].getParent()
  107. parentObj = self.editor.objectMgr.findObjectByNodePath(parentNodePath)
  108. #import pdb;pdb.set_trace()
  109. if parentObj is None:
  110. parent = self.root
  111. else:
  112. parent = self.getTreeItem(self.root, parentObj[OG.OBJ_UID])
  113. namestr = "%s_%s"%(obj[OG.OBJ_DEF].name, obj[OG.OBJ_UID])
  114. newItem = self.tree.AppendItem(parent, namestr)
  115. self.tree.SetItemPyData(newItem, obj[OG.OBJ_UID])
  116. # adding children of PandaObj
  117. if self.shouldShowPandaObjChildren:
  118. self.addPandaObjectChildren(newItem)
  119. self.tree.Expand(self.root)
  120. def traverse(self, parent, itemId):
  121. print "in traverse for itemId=%s..." %repr(itemId)
  122. # prevent from traversing into self
  123. if itemId == self.tree.GetItemPyData(parent):
  124. return None
  125. # main loop - serching for an item with an itemId
  126. item, cookie = self.tree.GetFirstChild(parent)
  127. while item:
  128. # if the item was found - return it
  129. if itemId == self.tree.GetItemPyData(item):
  130. return item
  131. # the tem was not found - checking if it has children
  132. if self.tree.ItemHasChildren(item):
  133. # item has children - delving into it
  134. child = self.traverse(item, itemId)
  135. if child is not None:
  136. return child
  137. # continue iteration to the next child
  138. item, cookie = self.tree.GetNextChild(parent, cookie)
  139. return None
  140. def reParent(self, parent, newParent):
  141. #import pdb;set_trace()
  142. # main loop - iterating over item's children
  143. item, cookie = self.tree.GetFirstChild(parent)
  144. while item:
  145. data = self.tree.GetItemText(item)
  146. itemId = self.tree.GetItemPyData(item)
  147. newItem = self.tree.AppendItem(newParent, data)
  148. self.tree.SetItemPyData(newItem, itemId)
  149. # if an item had children, we need to re-parent them as well
  150. if self.tree.ItemHasChildren(item):
  151. # recursing...
  152. self.reParent(item, newItem)
  153. # continue iteration to the next child
  154. item, cookie = self.tree.GetNextChild(parent, cookie)
  155. def changeHierarchy(self, data, x, y):
  156. itemText = data.split('_')
  157. itemId = itemText[-1] # uid is the last token
  158. parent = self.tree.GetRootItem()
  159. item = self.traverse(parent, itemId)
  160. if item is None:
  161. return
  162. dragToItem, flags = self.tree.HitTest(wx.Point(x, y))
  163. if dragToItem.IsOk():
  164. # prevent draging into itself
  165. if dragToItem == item:
  166. return
  167. newItem = self.tree.AppendItem(dragToItem, data)
  168. self.tree.SetItemPyData(newItem, itemId)
  169. self.reParent(item, newItem)
  170. oldParent = self.tree.GetItemParent(item)
  171. self.tree.Delete(item)
  172. obj = self.editor.objectMgr.findObjectById(itemId)
  173. itemId = self.tree.GetItemPyData(dragToItem)
  174. dragToItemObj = None
  175. if itemId != "render":
  176. dragToItemObj = self.editor.objectMgr.findObjectById(itemId)
  177. objNodePath = obj[OG.OBJ_NP]
  178. if dragToItemObj is None:
  179. objNodePath.wrtReparentTo(render)
  180. else:
  181. objNodePath.wrtReparentTo(dragToItemObj[OG.OBJ_NP])
  182. if self.shouldShowPandaObjChildren:
  183. self.removePandaObjectChildren(oldParent)
  184. self.addPandaObjectChildren(oldParent)
  185. self.removePandaObjectChildren(dragToItem)
  186. self.addPandaObjectChildren(dragToItem)
  187. def showPandaObjectChildren(self):
  188. itemList = list()
  189. self.shouldShowPandaObjChildren = not self.shouldShowPandaObjChildren
  190. item, cookie = self.tree.GetFirstChild(self.root)
  191. while item:
  192. itemList.append(item)
  193. item, cookie = self.tree.GetNextChild(self.root, cookie)
  194. #import pdb;set_trace()
  195. for item in itemList:
  196. if self.shouldShowPandaObjChildren:
  197. self.addPandaObjectChildren(item)
  198. else:
  199. self.removePandaObjectChildren(item)
  200. # continue iteration to the next child
  201. def delete(self, itemId):
  202. item = self.traverse(self.root, itemId)
  203. if item:
  204. self.tree.UnselectItem(item)
  205. self.tree.Delete(item)
  206. def select(self, itemId):
  207. item = self.traverse(self.root, itemId)
  208. if item:
  209. if not self.tree.IsSelected(item):
  210. self.tree.SelectItem(item)
  211. def deSelect(self, itemId):
  212. item = self.traverse(self.root, itemId)
  213. if item is not None:
  214. self.tree.UnselectItem(item)
  215. def onSelected(self, event):
  216. itemId = self.tree.GetItemPyData(event.GetItem())
  217. if itemId:
  218. obj = self.editor.objectMgr.findObjectById(itemId);
  219. if obj:
  220. selections = self.tree.GetSelections()
  221. if len(selections) > 1:
  222. base.direct.select(obj[OG.OBJ_NP], fMultiSelect = 1, fLEPane = 0)
  223. else:
  224. base.direct.select(obj[OG.OBJ_NP], fMultiSelect = 0, fLEPane = 0)
  225. def onBeginDrag(self, event):
  226. item = event.GetItem()
  227. if item != self.tree.GetRootItem(): # prevent dragging root item
  228. text = self.tree.GetItemText(item)
  229. print "Starting SceneGraphUI drag'n'drop with %s..." % repr(text)
  230. tdo = wx.TextDataObject(text)
  231. tds = wx.DropSource(self.tree)
  232. tds.SetData(tdo)
  233. tds.DoDragDrop(True)