Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Register
    • Register
    • Login

    TreeView for ObjectData plugin

    Cinema 4D SDK
    python r23
    2
    2
    457
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • mikeudinM
      mikeudin
      last edited by mikeudin

      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.

      testgen.zip

      /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()
      

      Checkout my python tutorials, plugins, scripts, xpresso presets and more
      https://mikeudin.net

      1 Reply Last reply Reply Quote 0
      • M
        m_adam
        last edited by

        Hi Mike this is unfortunately not possible, even in C++ for more info please look at Info for ITEMTREE/customgui_itemtree.

        Cheers,
        Maxime.

        MAXON SDK Specialist

        Development Blog, MAXON Registered Developer

        1 Reply Last reply Reply Quote 0
        • First post
          Last post