Store generator's property



  • Hi everyone,

    I'm completely misunderstand how to store object's related data.
    Read few posts, but there are common words only... Not sure there would be Read/Write/Copy overrides...

    I'd like to have a selection tag on the Generator object based on UI's bool (CHECKBOX_ID).
    If it's already exist - then use existing, otherwise add it automatically.
    Link should be updated after save/open

    Please point me to a solution, if any.

    CHECKBOX_ID = 1001
    SOME_ID = 5000
    SOME_ID_TAG = 5001
    
    class GeneratorPlugin(c4d.plugins.ObjectData):
      def Init(self, op):
        if op is None: raise RuntimeError("Failed to retrieves op.")
        self.InitAttr(op, bool, CHECKBOX_ID)
        op[CHECKBOX_ID] = True
    
        bc = op[SOME_ID]
        if bc is None:
          print "Data Not Exist"
          bc = c4d.BaseContainer()
          bc[SOME_ID] = c4d.BaseContainer()
        else:
          print "Data Exist", bc.GetLink(SOME_ID_TAG)
        op[SOME_ID] = bc
    
      def GetVirtualObjects(self, op, hh):
        if op is None or hh is None: raise RuntimeError("Failed to retrieves op or hh.")
    
        tmpSel = c4d.BaseSelect()
        # some calculations
    
        tag = op[SOME_ID].GetLink(SOME_ID_TAG)
        if op[CHECKBOX_ID]:
          if not tag:
            tag = c4d.SelectionTag(c4d.Tpolygonselection)
            op.InsertTag(tag)
            op[SOME_ID].SetLink(SOME_ID_TAG, tag)
          tmpSel.CopyTo(tag.GetBaseSelect())
        elif tag:
          tag.Remove()
          op[SOME_ID].RemoveData(SOME_ID_TAG)
    
    


  • hello,

    The BaseContainer of an object is saved automatically with the document. As long as you are storing your data in the object's BaseContainer, you don't have to worry to save them with the document.

    Read/Write/Copy need to be override when you are storing data somewhere else. In most of the case, If one of those function is implemented, you have to implement all of them.

    GVO (GetVirtualObjects) isn't the right place to change the scene. See information about threading

    To know if you are on the main thread or not you can use GeIsMainThread

    The right place to do something like this is the Message function.
    You can react to the message MSG_DESCRIPTION_POSTSETPARAMETER to apply some modifications when a parameter have been changed.
    You can also react to the message MSG_MENUPREPARE that is sent before the object is inserted in the scene.

    Be careful that this selection tag shouldn't be moved from the generator (or it will be reset)
    To avoid that, you can change its bit using ChangeNBit

    Here are an example of what you want to do.

        def CreateSelectionTag(self, node):
            #Creates a selection tag. Remove the tag first if it already exist
            bc = node.GetDataInstance()
            if bc is None:
                return False
            tag = bc.GetLink(ID_TAGLINK)
            if tag:
                tag.Remove()
                bc.RemoveIndex(ID_TAGLINK)
    
            tag = c4d.SelectionTag(c4d.Tpolygonselection)
            if tag is None:
                return False
            tag.ChangeNBit(c4d.NBIT_NO_DELETE, c4d.NBITCONTROL_SET);
            tag.ChangeNBit(c4d.NBIT_NO_DD, c4d.NBITCONTROL_SET);
            node.InsertTag(tag)
            bc.SetLink(ID_TAGLINK, tag)
            return True
            
    
        def RemoveSeletionTag(self, node):
            # Remove the tag 
            bc = node.GetDataInstance()
            if bc is None:
                return False
            tag = bc.GetLink(ID_TAGLINK)
            if tag is None:
                return False
            tag.Remove()
            bc.RemoveIndex(ID_TAGLINK)
            return True
    
        def Init(self, op):
            op[ID_CHECKBOX] = True
            return True
        
        def Message(self, node, type, data):
            # MSG_MENUPREPARE is sent before the object (generator here) is inserted in the scene. This is a nice moment to add any tag to the node
            if type == c4d.MSG_MENUPREPARE:
                print ("Message mainthread ? ", c4d.threading.GeIsMainThread())
                self.CreateSelectionTag(node)
            # MSG_DESCRIPTION_POSTSETPARAMETER is sent if a parameter have changed. Check here if we should add or remove a tag.
            elif type == c4d.MSG_DESCRIPTION_POSTSETPARAMETER:
                print ("Message mainthread ? ", c4d.threading.GeIsMainThread())
                if data['descid'][0].id == ID_CHECKBOX:
                    if node[ID_CHECKBOX]:
                        return self.CreateSelectionTag(node)
                    else:
                        return self.RemoveSeletionTag(node)
            return True
    
        
        
      
        # Override method, should generate and return the object.
        def GetVirtualObjects(self, op, hierarchyhelp):
            print ("GVO mainthread ? ", c4d.threading.GeIsMainThread())
            if op[ID_CHECKBOX]:
                bc = op.GetDataInstance()
                tag = bc.GetLink(ID_TAGLINK)
                if tag:
                    print ("the tag is", tag)
                else:
                    print ("this should never happen")
            else:
                bc = op.GetDataInstance()
                tag = bc.GetLink(ID_TAGLINK)
                if tag:
                    print ("this should never happen")
                else:
                    print ("there's no tag and box isn't checked")
    
    
    

    Cheers,
    Manuel



  • Oh, such a rocket science!
    Many thanks Manuel, it seems it works super fine.

    @m_magalhaes said in Store generator's property:

        if op[ID_CHECKBOX]:
            bc = op.GetDataInstance()
            tag = bc.GetLink(ID_TAGLINK)
            if tag:
                print ("the tag is", tag)
            else:
                print ("this should never happen")
        else:
            bc = op.GetDataInstance()
            tag = bc.GetLink(ID_TAGLINK)
            if tag:
                print ("this should never happen")
            else:
                print ("there's no tag and box isn't checked")


  • hi

    can we considered this thread as resolved ?

    Cheers,
    Manuel


Log in to reply