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

    Why ToolData Plugin Not Keeping the Input Data Values to the GUI Widgets SubDialog?

    Cinema 4D SDK
    python r21 r19
    2
    4
    835
    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.
    • A
      Ashton_FCS_PluginDev
      last edited by m_adam

      User Information:
      Cinema 4D Version: R19/R21;
      Platform: Windows ;
      Language(s) : Python ;

      Hello Everyone!
      This my first time making a tool data plugin. Now the problem is in R21 I drag the object into the link box and it don't stay and when I change the tool data or the settings dont stay , and i did this with other c4d gui widgets , eg: combobox, it just reset to the default value you set in the GeDialog.InitValues(). Now in R19 I drag the object into the link box and it stay but when I change the tool data or the settings dont stay.
      You can see the short streamable videos below on what is happen inside C4D and take look at the code also. I hope there a easy fix for this problem and not a bug. lol
      Inside R21: Video
      Inside R19: Video

      Code:

      import c4d
      from c4d import plugins, gui, bitmaps, documents, storage, utils
      import os
      import sys
      
      PLUGIN_ID = 1054512
      
      def GetDataFromLinkBox(ui_ins, uiLinkID):
          DATA = ui_ins.FindCustomGui(uiLinkID, c4d.CUSTOMGUI_LINKBOX).GetLink()
          objDATA = DATA
          objName = DATA.GetName()
          objGUID = DATA.GetGUID()
          return objDATA, objName, objGUID
      
      class DemoDialog(gui.SubDialog):
      
          UIDATA_PARAMETERS = {}
          LinkBC = c4d.BaseContainer()
          IDUI_CUSTOMGRP_LINK1 = 1003
      
          def __init__(self, arg):
              # Checks if the argument passed is a dictionary
              if not isinstance(arg, dict):
                  raise TypeError("arg is not a dict.")
              self.UIDATA_PARAMETERS = arg
      
          def CreateLayout(self):
              ui = self
              ui.GroupBegin(0, c4d.BFH_SCALEFIT, 2, 0, "")
              ui.AddStaticText(0, c4d.BFH_RIGHT, 0, 12, "Object:", c4d.BORDER_WITH_TITLE_BOLD)
              ui.AddCustomGui(ui.IDUI_CUSTOMGRP_LINK1, c4d.CUSTOMGUI_LINKBOX, "", c4d.BFH_MASK, 240, 12, ui.LinkBC)            
              ui.GroupEnd()
              return True
      
          def Command(self, id, msg):
      
              if id == self.IDUI_CUSTOMGRP_LINK1:
                 obj, objName, objID = GetDataFromLinkBox(ui_ins=self, uiLinkID=self.IDUI_CUSTOMGRP_LINK1)
                 self.UIDATA_PARAMETERS['grouplink'] = obj
                 self.UIDATA_PARAMETERS['grouplinkGUID'] = objID
                 print("Linked Object:{0} | ID:{1} | GUI-ID:{2}").format( objName, objID, id )
      
              return True
      
      class ToolDemo(plugins.ToolData):
      
          def __init__(self):
              self.UI_DATA = { 'grouplink':None, 'grouplinkGUID':None }
      
          def GetState(self, doc):
              if doc.GetMode()==c4d.Mpaint:
                  return 0
              return c4d.CMD_ENABLED 
          def InitDefaultSettings(self, doc, data):
              pass
              # expects None as return value
          def InitTool(self, doc, data, bt):
              return True
          def KeyboardInput(self, doc, data, bd, win, msg):
              return True
          def MouseInput(self, doc, data, bd, win, msg):
              return True
          def GetCursorInfo(self, doc, data, bd, x, y, bc):
              return True
              
          def AllocSubDialog(self, bc):     
              return DemoDialog(getattr(self, "UI_DATA", self.UI_DATA))
      
      if __name__ == "__main__":
          bmp = bitmaps.BaseBitmap()
          dir, file = os.path.split(__file__)
          fn = os.path.join(dir, "res", "tool_icon.tif")
          bmp.InitWith(fn)
          plugins.RegisterToolPlugin(id=PLUGIN_ID, 
                                      str="MyPyToolDemo",
                                      info=0, 
                                      icon=bmp, 
                                      help="Tool",
                                      dat=ToolDemo())
      

      And I am just wondering is c4d.plugins.SculptBrushToolData is better system than c4d.plugins.ToolData. Cause it look like description .res.. UI is for the tool plugin is more easy, like Node Data, Object Data Tags etc....
      Any help would be very much appreciated.

      cheers, Ashton

      1 Reply Last reply Reply Quote 0
      • ManuelM
        Manuel
        last edited by

        hi,

        you have to store a link to your gadget and add an InitValues function to your dialog like so

        in the create layout:

        self.link = ui.AddCustomGui(ui.IDUI_CUSTOMGRP_LINK1, c4d.CUSTOMGUI_LINKBOX, "", c4d.BFH_MASK, 240, 12, ui.LinkBC)            
        

        and add that function

           def InitValues(self):
            
                self.link.SetLink(self.UIDATA_PARAMETERS['grouplink'])
                return True
        

        Cheers,
        Manuel

        MAXON SDK Specialist

        MAXON Registered Developer

        A 1 Reply Last reply Reply Quote 0
        • A
          Ashton_FCS_PluginDev @Manuel
          last edited by

          @m_magalhaes Thank you! and it makes sense.👍 Heres a update of the code and Demo Video. And hope it helps anyone who might need this or was wondering how a simple Tool Data GUI works.
          172b5199-9a7e-42d0-bf04-85d53307e59e-image.png
          You see I just add the AddComboBox, AddEditText for testing also. 😊 👍
          Code in .pyp file:

          #  // Imports for Cinema 4D //
          import c4d
          from c4d import plugins, gui, bitmaps, documents, storage, utils
          import os
          import sys
          
          PLUGIN_ID = 1054512
          
          def GetDataFromLinkBox(ui_ins, uiLinkID):
              DATA = ui_ins.FindCustomGui(uiLinkID, c4d.CUSTOMGUI_LINKBOX).GetLink()
              objDATA = DATA
              objName = DATA.GetName()
              objGUID = DATA.GetGUID()
              return objDATA, objName, objGUID
          
          def SetDataFromLinkBox(ui_ins, uiLinkID, Data):
              LinkWidget = ui_ins.FindCustomGui(uiLinkID, c4d.CUSTOMGUI_LINKBOX)
              LinkWidget.SetLink(Data)
              return True
          
          
          class DemoDialog(gui.SubDialog):
              # Main Properties
              UIDATA_PARAMETERS = {}
              LinkBC = c4d.BaseContainer()
              IDUI_CUSTOMGRP_LINK1 = 1003
              IDUI_GRG_OBJ_GUID = 1004
              MODE_MENU = 1005
              MODE_MENU_LIST = {
                                  "Mode 1":{'id':1, 'icon':"&i12298&"}, # (12298) # Model Icon Id (Eg:"&i12298&Model")
                                  "Mode 2":{'id':2, 'icon':"&i12139&"}, # (12139) # Points Icon Id
                                  "Mode 3":{'id':3, 'icon':"&i12187&"}  # (12187) # Polygons Icon Id
                               }
          
              def __init__(self, arg):
                  # Checks if the argument passed is a dictionary
                  if not isinstance(arg, dict):
                      raise TypeError("arg is not a dict.")
                  self.UIDATA_PARAMETERS = arg
          
              def CreateLayout(self):
                  """ Window GUI elements layout that display to the User. """
                  ui = self
                  ui.GroupBegin(0, c4d.BFH_MASK, 2, 2, "", c4d.BFV_GRIDGROUP_EQUALCOLS)
                  ui.AddStaticText(0, c4d.BFH_RIGHT, 0, 12, "Object:", c4d.BORDER_WITH_TITLE_BOLD)
                  ui.AddCustomGui(ui.IDUI_CUSTOMGRP_LINK1, c4d.CUSTOMGUI_LINKBOX, "", c4d.BFH_MASK, 240, 12, ui.LinkBC) 
                  ui.AddStaticText(0, c4d.BFH_RIGHT, 0, 12, "Object GUID:", c4d.BORDER_WITH_TITLE_BOLD)
                  ui.AddEditText(ui.IDUI_GRG_OBJ_GUID, c4d.BFH_MASK, 240, 12)   
                  ui.AddStaticText(0, c4d.BFH_RIGHT, 0, 12, "Modes:", c4d.BORDER_WITH_TITLE_BOLD)
                  ui.AddComboBox(ui.MODE_MENU, c4d.BFH_SCALEFIT, 100, 15, False)
                  for eachMode in sorted(ui.MODE_MENU_LIST):
                      itemMode = ui.MODE_MENU_LIST.get(str(eachMode))           
                      ui.AddChild(ui.MODE_MENU, itemMode['id'],  itemMode['icon']+str(eachMode))         
                  ui.GroupEnd()
                  return True
          
              def InitValues(self):
                  """ Called when the dialog is initialized by the GUI / GUI's startup values basically. """
                  SetDataFromLinkBox(ui_ins=self, uiLinkID=self.IDUI_CUSTOMGRP_LINK1, Data=self.UIDATA_PARAMETERS['grouplink'])
                  self.SetString(self.IDUI_GRG_OBJ_GUID, self.UIDATA_PARAMETERS['grouplinkGUID'])
                  self.SetLong(self.MODE_MENU, self.UIDATA_PARAMETERS['modeSelect'])
                  return True
          
              def Command(self, id, msg):
                  """ Excuting Commands for UI Widget Elements Functions. """
                  if id == self.IDUI_CUSTOMGRP_LINK1:
                      obj, objName, objID = GetDataFromLinkBox(ui_ins=self, uiLinkID=self.IDUI_CUSTOMGRP_LINK1)
                      self.UIDATA_PARAMETERS['grouplink'] = obj
                      self.UIDATA_PARAMETERS['grouplinkGUID'] = objID
                      self.SetString(self.IDUI_GRG_OBJ_GUID, str(objID))
                      print("Linked Object:{0} | ID:{1} | GUI-ID:{2}").format( objName, objID, id )
          
                  if id == self.MODE_MENU:
                      for i in self.MODE_MENU_LIST:
                          getModeID = self.MODE_MENU_LIST.get(str(i))
                          if self.GetLong(self.MODE_MENU) == getModeID["id"]:
                              self.UIDATA_PARAMETERS['modeSelect']=getModeID["id"]
                  return True
          
          class PyToolDemo(plugins.ToolData):
          
              def __init__(self):
                  self.UI_DATA = { 'grouplink':None, 
                                   'grouplinkGUID':None,
                                   'modeSelect':2 }
          
              def GetState(self, doc):
                  if doc.GetMode()==c4d.Mpaint:
                      return 0
                  return c4d.CMD_ENABLED 
              def InitDefaultSettings(self, doc, data):
                  pass
              def InitTool(self, doc, data, bt):
                  return True
              def KeyboardInput(self, doc, data, bd, win, msg):
                  return True
              def MouseInput(self, doc, data, bd, win, msg):
                  return True
              def GetCursorInfo(self, doc, data, bd, x, y, bc):
                  return True
          
              def AllocSubDialog(self, bc):     
                  return DemoDialog(getattr(self, "UI_DATA", self.UI_DATA))
          
          if __name__ == "__main__":
              bmp = bitmaps.BaseBitmap()
              dir, file = os.path.split(__file__)
              fn = os.path.join(dir, "res", "tool_icon.tif")
              bmp.InitWith(fn)
              plugins.RegisterToolPlugin(id=PLUGIN_ID, 
                                          str="MyPyToolDemo",
                                          info=0, 
                                          icon=bmp, 
                                          help="Your Data Staying ToolData UI",
                                          dat=PyToolDemo())
          
          1 Reply Last reply Reply Quote 0
          • ManuelM
            Manuel
            last edited by Manuel

            hi,

            thanks a lot for sharing your code 🙂

            Don't forget to change the state of this thread to solved. (if it is)

            cheers,
            Manuel

            MAXON SDK Specialist

            MAXON Registered Developer

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