Copy Material with Current State to Object



  • Is there a way to copy the material associated with the texture tag when I use Current State to Object? Is there a line I can add to my code? I need the new geometry to have its own material that is separate from the original object's material. Thanks.

    # Current State to Object
            return_value = c4d.utils.SendModelingCommand(
                            command = c4d.MCOMMAND_CURRENTSTATETOOBJECT,
                            list = [doc.SearchObject("S" + str (item))],
                            mode = c4d.MODELINGCOMMANDMODE_ALL,
                            bc = settings,
                            doc = doc)
    


  • Hi,

    at least I am not aware of any functionality of CSO in this regard. I also do not think that Cinema has such a function at all (but I might be wrong about this). You will have to clone your materials manually and relink them. Something like the following:

    import c4d
    
    def clone_and_relink_materials(node):
        """Clones all unique materials assigned to an object and sets the links to the the cloned materials in the respective material tags.
    
        Args:
            node (``c4d.BaseObject``): The object to clone the materials for.
        
        Returns:
            tuple[bool, list[c4d.BaseMaterial]]: If the cloning has been successful and the cloned materials.
        """
        # Get out if node is not a BaseObject.
        if not isinstance(node, c4d.BaseObject):
            return False, []
    
        # A hashmap for the materials and the document the node is attached to.
        clones = {}
        doc = node.GetDocument()
        # Go over all tags of the object.
        for tag in node.GetTags():
            # Step over non-material tags and material tags that do not have a
            # material.
            if not tag.CheckType(c4d.Ttexture):
                continue
            elif tag[c4d.TEXTURETAG_MATERIAL] is None:
                continue
    
            # Get the material and hash it, so that we can keep track of which
            # material has been cloned and which not (in case there are multiple
            # material tags referencing the same material).
            material = tag[c4d.TEXTURETAG_MATERIAL]
            nid = material.FindUniqueID(c4d.MAXON_CREATOR_ID)
            # This a newly encountered material (in this object)
            if nid not in clones:
                # Clone the material, change its name and insert it into the
                # document.
                clone = material.GetClone(c4d.COPYFLAGS_NONE)
                clone.SetName(clone.GetName() + "_clone")
                doc.InsertMaterial(clone)
                clones[nid] = clone
            # Get the cloned material for the material referenced in the
            # material tag and set the reference in the material tag to the
            # clone.
            tag[c4d.TEXTURETAG_MATERIAL] = clones[nid]
            tag.Message(c4d.MSG_UPDATE)
        return True, clones.values()
            
    def main():
        success, materials = clone_and_relink_materials(op)
        print "success:", success
        print "cloned materials:", materials
        c4d.EventAdd()
    
    if __name__=='__main__':
        main()
    

    Note that this solution is not material-tag agnostic, i.e. will not work in any environment that does not rely on Ttexture tags to assign materials to an object.

    Cheers,
    zipit



  • Thanks, zipit, much appreciated. :)



  • Hello,

    For your next threads, please help us keeping things organised and clean. I know it's not your priority but it really simplify our work here.

    I've added the tags and marked this thread as a question so when you considered it as solved, please change the state :)

    Nothing more to add, thanks @zipit for you answer :)

    Cheers,
    Manuel



  • Got it. Thanks, again, zipit for you answer. :)


Log in to reply