Advertisement
Guest User

TreeView C4D Python [Material]

a guest
Nov 15th, 2022
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.99 KB | None | 0 0
  1. """Example for setting the column width of a tree view by the width of its
  2. items.
  3.  
  4. The only changes which have been made in comparison to the original code can
  5. be found in TextureObject.__init__(), TextureObject.RandomString() and
  6. ListView.GetColumnWidth(). The tree view items #TextureObject now generate
  7. random #texturePath and #otherData strings and the treeview scales its columns
  8. to the length of these strings.
  9.  
  10. Adapted from:
  11. https://plugincafe.maxon.net/topic/10654/14102_using-customgui-listview/2
  12. """
  13. import c4d
  14. import random
  15.  
  16. # Be sure to use a unique ID obtained from http://www.plugincafe.com/.
  17. PLUGIN_ID = 1000010 # TEST ID ONLY
  18.  
  19. # TreeView Column IDs.
  20. ID_CHECKBOX = 1
  21. ID_NAME = 2
  22. ID_OTHER = 3
  23. ID_LONGFILENAME = 4
  24.  
  25. # A tuple of characters to select from (a-z).
  26. CHARACTERS = tuple( chr ( n) for n in range(97, 122))
  27. doc = c4d.documents.GetActiveDocument()
  28.  
  29. class ListView(c4d.gui.TreeViewFunctions):
  30.  
  31. def __init__(self):
  32. """
  33. """
  34. # Add ten mock data texture objects.
  35. #self.listOfTexture = [TextureObject() for _ in range(20)]
  36. self.listOfTexture = doc.GetMaterials()
  37. print (self.listOfTexture)
  38.  
  39. def IsResizeColAllowed(self, root, userdata, lColID):
  40. return True
  41.  
  42. def IsTristate(self, root, userdata):
  43. return False
  44.  
  45. def GetColumnWidth(self, root, userdata, obj, col, area):
  46. """Measures the width of cells.
  47.  
  48. Although this function is called #GetColumnWidth and has a #col, it is
  49. not only executed by column but by cell. So, when there is a column
  50. with items requiring the width 5, 10, and 15, then there is no need
  51. for evaluating all items. Each item can return its ideal width and
  52. Cinema 4D will then pick the largest value.
  53.  
  54. Args:
  55. root (any): The root node of the tree view.
  56. userdata (any): The user data of the tree view.
  57. obj (any): The item for the current cell.
  58. col (int): The index of the column #obj is contained in.
  59. area (GeUserArea): An already initialized GeUserArea to measure
  60. the width of strings.
  61.  
  62. Returns:
  63. TYPE: Description
  64. """
  65. # The default width of a column is 80 units.
  66. width = 80
  67. # Replace the width with the text width. area is a prepopulated
  68. # user area which has already setup all the font stuff, we can
  69. # measure right away.
  70.  
  71. if col == ID_NAME:
  72. return area.DrawGetTextWidth(obj.texturePath) + 5
  73. if col == ID_OTHER:
  74. return area.DrawGetTextWidth(obj.otherData) + 5
  75. if col == ID_LONGFILENAME:
  76. return area.DrawGetTextWidth(obj.longfilename) + 5
  77.  
  78. return width
  79.  
  80. def IsMoveColAllowed(self, root, userdata, lColID):
  81. # The user is allowed to move all columns.
  82. # TREEVIEW_MOVE_COLUMN must be set in the container of AddCustomGui.
  83. return True
  84.  
  85. def GetFirst(self, root, userdata):
  86. """
  87. Return the first element in the hierarchy, or None if there is no element.
  88. """
  89. rValue = None if not self.listOfTexture else self.listOfTexture[0]
  90. return rValue
  91.  
  92. def GetDown(self, root, userdata, obj):
  93. """
  94. Return a child of a node, since we only want a list, we return None everytime
  95. """
  96. return None
  97.  
  98. def GetNext(self, root, userdata, obj):
  99. """
  100. Returns the next Object to display after arg:'obj'
  101. """
  102. rValue = None
  103. currentObjIndex = self.listOfTexture.index(obj)
  104. nextIndex = currentObjIndex + 1
  105. if nextIndex < len(self.listOfTexture):
  106. rValue = self.listOfTexture[nextIndex]
  107.  
  108. return rValue
  109.  
  110. def GetPred(self, root, userdata, obj):
  111. """
  112. Returns the previous Object to display before arg:'obj'
  113. """
  114. rValue = None
  115. currentObjIndex = self.listOfTexture.index(obj)
  116. predIndex = currentObjIndex - 1
  117. if 0 <= predIndex < len(self.listOfTexture):
  118. rValue = self.listOfTexture[predIndex]
  119.  
  120. return rValue
  121.  
  122. def GetId(self, root, userdata, obj):
  123. """
  124. Return a unique ID for the element in the TreeView.
  125. """
  126. return hash(obj)
  127.  
  128. def Select(self, root, userdata, obj, mode):
  129. """
  130. Called when the user selects an element.
  131. """
  132. if mode == c4d.SELECTION_NEW:
  133. for tex in self.listOfTexture:
  134. tex.Deselect()
  135. obj.Select()
  136. elif mode == c4d.SELECTION_ADD:
  137. obj.Select()
  138. elif mode == c4d.SELECTION_SUB:
  139. obj.Deselect()
  140.  
  141. def IsSelected(self, root, userdata, obj):
  142. """
  143. Returns: True if *obj* is selected, False if not.
  144. """
  145. return obj.IsSelected
  146.  
  147. def SetCheck(self, root, userdata, obj, column, checked, msg):
  148. """
  149. Called when the user clicks on a checkbox for an object in a
  150. `c4d.LV_CHECKBOX` column.
  151. """
  152. if checked:
  153. obj.Select()
  154. else:
  155. obj.Deselect()
  156.  
  157. def IsChecked(self, root, userdata, obj, column):
  158. """
  159. Returns: (int): Status of the checkbox in the specified *column* for *obj*.
  160. """
  161. if obj.IsSelected:
  162. return c4d.LV_CHECKBOX_CHECKED | c4d.LV_CHECKBOX_ENABLED
  163. else:
  164. return c4d.LV_CHECKBOX_ENABLED
  165.  
  166. def GetName(self, root, userdata, obj):
  167. """
  168. Returns the name to display for arg:'obj', only called for column of type LV_TREE
  169. """
  170. return str(obj) # Or obj.texturePath
  171.  
  172. def DrawCell(self, root, userdata, obj, col, drawinfo, bgColor):
  173. """
  174. Draw into a Cell, only called for column of type LV_USER
  175. """
  176. if col in (ID_OTHER, ID_LONGFILENAME):
  177. text = obj.otherData if col == ID_OTHER else obj.longfilename
  178. canvas = drawinfo["frame"]
  179. textWidth = canvas.DrawGetTextWidth(text)
  180. textHeight = canvas.DrawGetFontHeight()
  181. xpos = drawinfo["xpos"]
  182. ypos = drawinfo["ypos"] + drawinfo["height"]
  183.  
  184. if (drawinfo["width"] < textWidth):
  185. while (drawinfo["width"] < textWidth):
  186. if len(text) <= 4:
  187. text = "..."
  188. break
  189. text = text[:-4] + "..."
  190. textWidth = canvas.DrawGetTextWidth(text)
  191.  
  192. textWidth = canvas.DrawGetTextWidth(text)
  193. drawinfo["frame"].DrawText(text, xpos, ypos - int(textHeight * 1.1))
  194.  
  195. def DoubleClick(self, root, userdata, obj, col, mouseinfo):
  196. """
  197. Called when the user double-clicks on an entry in the TreeView.
  198.  
  199. Returns:
  200. (bool): True if the double-click was handled, False if the
  201. default action should kick in. The default action will invoke
  202. the rename procedure for the object, causing `SetName()` to be
  203. called.
  204. """
  205. c4d.gui.MessageDialog("You clicked on " + str(obj))
  206. return True
  207.  
  208. def DeletePressed(self, root, userdata):
  209. "Called when a delete event is received."
  210. for tex in reversed(self.listOfTexture):
  211. if tex.IsSelected:
  212. self.listOfTexture.remove(tex)
  213.  
  214. class TestDialog(c4d.gui.GeDialog):
  215. _treegui = None # Our CustomGui TreeView
  216. _listView = ListView() # Our Instance of c4d.gui.TreeViewFunctions
  217.  
  218. def CreateLayout(self):
  219. # Create the TreeView GUI.
  220. customgui = c4d.BaseContainer()
  221. customgui.SetBool(c4d.TREEVIEW_BORDER, c4d.BORDER_THIN_IN)
  222. customgui.SetBool(c4d.TREEVIEW_HAS_HEADER, True) # True if the tree view may have a header line.
  223. customgui.SetBool(c4d.TREEVIEW_HIDE_LINES, True) # True if no lines should be drawn.
  224. customgui.SetBool(c4d.TREEVIEW_MOVE_COLUMN, True) # True if the user can move the columns.
  225. customgui.SetBool(c4d.TREEVIEW_RESIZE_HEADER, True) # True if the column width can be changed by the user.
  226. customgui.SetBool(c4d.TREEVIEW_FIXED_LAYOUT, True) # True if all lines have the same height.
  227. customgui.SetBool(c4d.TREEVIEW_ALTERNATE_BG, True) # Alternate background per line.
  228. customgui.SetBool(c4d.TREEVIEW_CURSORKEYS, True) # True if cursor keys should be processed.
  229. customgui.SetBool(c4d.TREEVIEW_NOENTERRENAME, False) # Suppresses the rename popup when the user presses enter.
  230.  
  231. self._treegui = self.AddCustomGui(1000, c4d.CUSTOMGUI_TREEVIEW, "", c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, 300, 300, customgui)
  232. if not self._treegui:
  233. print("[ERROR]: Could not create TreeView")
  234. return False
  235.  
  236. self.AddButton(1001, c4d.BFH_CENTER, name="Add")
  237. return True
  238.  
  239. def InitValues(self):
  240. # Initialize the column layout for the TreeView.
  241. layout = c4d.BaseContainer()
  242. layout.SetLong(ID_CHECKBOX, c4d.LV_CHECKBOX)
  243. layout.SetLong(ID_NAME, c4d.LV_TREE)
  244. layout.SetLong(ID_LONGFILENAME, c4d.LV_USER)
  245. layout.SetLong(ID_OTHER, c4d.LV_USER)
  246. self._layout = layout
  247. self._treegui.SetLayout(4, layout)
  248.  
  249. # Set the header titles.
  250. self._treegui.SetHeaderText(ID_CHECKBOX, "Check")
  251. self._treegui.SetHeaderText(ID_NAME, "Name")
  252. self._treegui.SetHeaderText(ID_LONGFILENAME, "Long Filename")
  253. self._treegui.SetHeaderText(ID_OTHER, "Other")
  254.  
  255. self._treegui.Refresh()
  256.  
  257. # Set TreeViewFunctions instance used by our CUSTOMGUI_TREEVIEW
  258. self._treegui.SetRoot(self._treegui, self._listView, None)
  259. return True
  260.  
  261. def Command(self, id, msg):
  262. # Click on button
  263. if id == 1001:
  264.  
  265. '''
  266. # Add data to our DataStructure (ListView)
  267. newID = int(len(self._listView.listOfTexture) + 1)
  268. # print(newID)
  269. # newID = "T{}".format(newID)
  270. # print(newID)
  271. # tex = TextureObject(newID)
  272. tex = TextureObject()
  273. tex.texturePath = "Some new data"
  274. tex.longfilename = TextureObject.RandomString(20, 40)
  275. self._listView.listOfTexture.append(tex)
  276. self._treegui.Refresh()
  277. '''
  278. pass
  279.  
  280. return True
  281.  
  282. class MenuCommand(c4d.plugins.CommandData):
  283. dialog = None
  284.  
  285. def Execute(self, doc):
  286. if self.dialog is None:
  287. self.dialog = TestDialog()
  288. return self.dialog.Open(c4d.DLG_TYPE_ASYNC, PLUGIN_ID, defaulth=600, defaultw=600)
  289.  
  290. def RestoreLayout(self, sec_ref):
  291. if self.dialog is None:
  292. self.dialog = TestDialog()
  293. return self.dialog.Restore(PLUGIN_ID, secret=sec_ref)
  294.  
  295. def main():
  296. c4d.plugins.RegisterCommandPlugin(
  297. PLUGIN_ID, "Python TreeView Example REVISED", 0, None, "Python TreeView Example", MenuCommand())
  298.  
  299.  
  300. if __name__ == "__main__":
  301. main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement