TreeView for ObjectData plugin
-
Hello!
Can't figure out how to add TreeView gui to ObjectData attributes interface.
There is some tips here, but is not clear how it can be used in python.️
Here is a sample code what i want to implement./res/description/Otestgen.h
enum { Otestgen = 100500, TG_TEST_GROUP = 1000, TG_TAGSGROUP_GROUP = 1001, TG_TAGS = 1002, };
/res/description/Otestgen.res
CONTAINER Otestgen { INCLUDE Obase; NAME Otestgen; GROUP ID_OBJECTPROPERTIES { } GROUP TG_TEST_GROUP { DEFAULT 1; GROUP TG_TAGSGROUP_GROUP { DEFAULT 1; ITEMTREE TG_TAGS { } } } }
/res/strings_us/description/Otestgen.str
STRINGTABLE Otestgen { Otestgen "TestGen"; TG_TEST_GROUP "Test"; TG_TAGSGROUP_GROUP ""; TG_TAGS "Tags"; }
/testgen.pyp
import c4d import os def load_bitmap(path): path = os.path.join(os.path.dirname(__file__), path) bmp = c4d.bitmaps.BaseBitmap() if bmp.InitWith(path)[0] != c4d.IMAGERESULT_OK: bmp = None return bmp class tagObject(object): """ Class which represent a texture, aka an Item in our list """ name = "Default" _checked = True _selected = False def __init__(self, name): self.name = name @property def IsSelected(self): return self._selected def Select(self): self._selected = True def Deselect(self): self._selected = False def __repr__(self): return str(self) def __str__(self): return self.name class ListView(c4d.gui.TreeViewFunctions): def __init__(self): self.tagList = list() # Store all objects we need to display in this list def IsResizeColAllowed(self, root, userdata, lColID): return True def IsTristate(self, root, userdata): return False def GetColumnWidth(self, root, userdata, obj, col, area): if col == ID_NAME: return 200 return 80 # All have the same initial width def IsMoveColAllowed(self, root, userdata, lColID): # The user is allowed to move all columns. # TREEVIEW_MOVE_COLUMN must be set in the container of AddCustomGui. return False def GetFirst(self, root, userdata): """ Return the first element in the hierarchy, or None if there is no element. """ rValue = None if not self.tagList else self.tagList[0] return rValue def GetNext(self, root, userdata, obj): """ Returns the next Object to display after arg:'obj' """ rValue = None pList = self.tagList currentObjIndex = pList.index(obj) nextIndex = currentObjIndex + 1 if nextIndex < len(pList): rValue = pList[nextIndex] return rValue def GetPred(self, root, userdata, obj): """ Returns the previous Object to display before arg:'obj' """ pList = self.tagList currentObjIndex = pList.index(obj) nextIndex = currentObjIndex - 1 if nextIndex < len(pList): rValue = pList[nextIndex] def GetId(self, root, userdata, obj): """ Return a unique ID for the element in the TreeView. """ return hash(obj) def Select(self, root, userdata, obj, mode): """ Called when the user selects an element. """ if mode == c4d.SELECTION_NEW: for preset in self.tagList: preset.Deselect() obj.Select() elif mode == c4d.SELECTION_ADD: obj.Select() elif mode == c4d.SELECTION_SUB: obj.Deselect() def IsSelected(self, root, userdata, obj): """ Returns: True if *obj* is selected, False if not. """ return obj.IsSelected def SetCheck(self, root, userdata, obj, column, checked, msg): """ Called when the user clicks on a checkbox for an object in a `c4d.LV_CHECKBOX` column. """ if checked: obj.checked = True else: obj.checked = False def IsChecked(self, root, userdata, obj, column): """ Returns: (int): Status of the checkbox in the specified *column* for *obj*. """ if obj.checked: return c4d.LV_CHECKBOX_CHECKED | c4d.LV_CHECKBOX_ENABLED else: return c4d.LV_CHECKBOX_ENABLED def GetName(self, root, userdata, obj): """ Returns the name to display for arg:'obj', only called for column of type LV_TREE """ return str(obj) # Or obj.presetType def SetName(self, root, userdata, obj, name): """ Returns the name to display for arg:'obj', only called for column of type LV_TREE """ obj.name = name def ContextMenuCall(self, root, userdata, obj, lColumn, lCommand): """ The user executes an entry of the context menu. Returns: (bool): True if the event was handled, False if not. """ if lCommand == c4d.ID_TREEVIEW_CONTEXT_RESET: print ('Call Reset') return True if lCommand == c4d.ID_TREEVIEW_CONTEXT_REMOVE: print ('Call Remove All') return True def DoubleClick(self, root, userdata, obj, col, mouseinfo): """ Called when the user double-clicks on an entry in the TreeView. Returns: (bool): True if the double-click was handled, False if the default action should kick in. The default action will invoke the rename procedure for the object, causing `SetName()` to be called. """ return False def DeletePressed(self, root, userdata): """Called when a delete event is received.""" for preset in reversed(self.tagList): if preset.IsSelected: self.tagList.remove(preset) continue class TestGenData(c4d.plugins.ObjectData): PLUGIN_ID = 100500 #Example PLUgiN Id PLUGIN_NAME = 'TestGen' PLUGIN_INFO = c4d.OBJECT_GENERATOR PLUGIN_DESC = 'Otestgen' PLUGIN_ICON = load_bitmap('res/icons/TestGen.tiff') PLUGIN_DISKLEVEL = 0 # TreeView Column IDs. ID_CHECKBOX = 1 ID_NAME = 2 @classmethod def Register(cls): return c4d.plugins.RegisterObjectPlugin( cls.PLUGIN_ID, cls.PLUGIN_NAME, cls, cls.PLUGIN_DESC, cls.PLUGIN_INFO, cls.PLUGIN_ICON, cls.PLUGIN_DISKLEVEL) def __init__(self): self.SetOptimizeCache(True) def Init(self, node): # ?????? self.InitAttr(node, c4d.TreeViewCustomData, [res.TG_TAGS]) # How to Inint this CustomDataType attribute?? # ?????? return True def GetDDescription(self, node, description, flags): # Before adding dynamic parameters, load the parameters from the description resource if not description.LoadDescription(node.GetType()): return False singleID = description.GetSingleDescID() myTreeID = c4d.DescID(c4d.TG_TAGS) # ?????? # This is a way i think how to add TreeView to attributes. But how to connect TreeView class object to it? # ?????? if singleID is None or myTreeID.IsPartOf(singleID)[0]: # Add dynamic parameter bc = c4d.GetCustomDataTypeDefault(c4d.CUSTOMGUI_TREEVIEW) bc.SetInt32(c4d.DESC_CUSTOMGUI, c4d.CUSTOMGUI_TREEVIEW) bc.SetString(c4d.DESC_NAME, "Animators") bc.SetString(c4d.DESC_SHORT_NAME, "Animators"); bc.SetLong(c4d.DESC_ANIMATE, c4d.DESC_ANIMATE_OFF); bc.SetBool(c4d.TREEVIEW_OUTSIDE_DROP, False) bc.SetBool(c4d.TREEVIEW_HAS_HEADER, True) bc.SetBool(c4d.TREEVIEW_BORDER, c4d.BORDER_THIN_IN) bc.SetBool(c4d.TREEVIEW_HAS_HEADER, False) # True if the tree view may have a header line. bc.SetBool(c4d.TREEVIEW_HIDE_LINES, False) # True if no lines should be drawn. bc.SetBool(c4d.TREEVIEW_MOVE_COLUMN, True) # True if the user can move the columns. bc.SetBool(c4d.TREEVIEW_RESIZE_HEADER, False) # True if the column width can be changed by the user. bc.SetBool(c4d.TREEVIEW_FIXED_LAYOUT, True) # True if all lines have the same height. bc.SetBool(c4d.TREEVIEW_ALTERNATE_BG, True) # Alternate background per line. bc.SetBool(c4d.TREEVIEW_CURSORKEYS, True) # True if cursor keys should be processed. bc.SetBool(c4d.TREEVIEW_NOENTERRENAME, False) # Suppresses the rename popup when the user presses enter. bc.SetBool(c4d.TREEVIEW_NO_MULTISELECT, True) # Add TREEVIEW to the parameters in specified group if not description.SetParameter(myTreeID, bc, c4d.DescID(c4d.TG_TAGSGROUP_GROUP)): # group ID from above post return False def GetVirtualObjects(self, op, hh): return c4d.BaseObject(c4d.Ocube) if __name__ == '__main__': TestGenData.Register()
-
Hi Mike this is unfortunately not possible, even in C++ for more info please look at Info for ITEMTREE/customgui_itemtree.
Cheers,
Maxime.