Detecting Parameters & Connecting XPresso Ports

On 03/12/2015 at 18:33, xxxxxxxx wrote:

Hi,

I'm trying to write a script that duplicates an object and connects all animatable parameters of the new object, with the corresponding parameters of the source object via Xpresso. So far, I've been able to achieve the basics (clone object, create XPresso tag & nodes, link parameters) :

However, I'm still struggling with the following issues/questions:

1. How do I get Cinema 4D to show that a parameter has been linked as an input/output via XPresso? Something like this:

2. How do I determine if a parameter in an object's description is animatable? For example: "Size.x" can be keyed but "Size" cannot be.

Here is my current code, I'd be very interested in any suggestions you may have:

  
"""Name-US: CV-Make Replicant   
Description-US: Duplicates the selected object and links all parameters via Xpresso.   
  
USAGE INSTRUCTIONS   
------------------   
  
1. Select an object.   
2. Run "Scripts > CV-Make Replicant"   
  
LICENSE   
-------   
  
Copyright (C) 2015 Maxon Computer, Inc.   
Programming: Donovan Keith <[email protected]>   
  
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE   
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR   
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR   
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.   
"""   
  
#====== IMPORTS ======#   
  
import c4d   
  
#====== GLOBALS ======#   
  
PLUGIN_ID = None   
PLUGIN_VERSION = "0.01"   
  
#====== UTILS ======#   
  
def AddObjectNode(node_master, obj, x=0) :   
    """Adds and returns an object node into Xpresso graph's node_master"""   
       
    obj_node = node_master.CreateNode(parent=node_master.GetRoot(), id=c4d.ID_OPERATOR_OBJECT, x=x, y=50)   
    obj_node[c4d.GV_OBJECT_OBJECT_ID] = obj   
    return obj_node   
  
#====== MAIN ======#   
  
def main() :   
    doc.StartUndo()   
       
    #Get the active objects   
    active_objects = doc.GetActiveObjects(flags=c4d.GETACTIVEOBJECTFLAGS_CHILDREN)   
       
    for source in active_objects:   
        #Make and insert a copy of the selected object   
        destination = source.GetClone()   
        destination.SetName(source.GetName() + " Replicant")   
        doc.InsertObject(destination, pred=source)   
        doc.AddUndo(c4d.UNDOTYPE_NEW, destination)   
       
        #Create XPresso Tag   
        xpresso_tag = c4d.modules.graphview.XPressoTag()   
        node_master = xpresso_tag.GetNodeMaster()   
  
        #Add the Tag to the destination object   
        destination.InsertTag(xpresso_tag)   
  
        #Add a Node for the source object   
        source_node = AddObjectNode(node_master, source, x=50)   
        dest_node = AddObjectNode(node_master, destination, x=300)   
  
  
        #Add and link ports for all parameters, except:   
        banned_ids = [   
            c4d.ID_BASELIST_NAME,   
            c4d.ID_LAYER_LINK,   
            c4d.ID_BASEOBJECT_VISIBILITY_EDITOR,   
            c4d.ID_BASEOBJECT_VISIBILITY_RENDER,   
            c4d.ID_BASEOBJECT_USECOLOR,   
            c4d.ID_BASEOBJECT_COLOR,   
            c4d.ID_BASEOBJECT_GENERATOR_FLAG,   
            c4d.ID_BASEOBJECT_XRAY   
        ]   
  
        banned_types = [   
            c4d.CUSTOMGUI_BUTTON,   
            c4d.CUSTOMGUI_STATICTEXT,   
            c4d.CUSTOMGUI_SEPARATOR,   
            c4d.CUSTOMGUI_PROGRESSBAR   
        ]   
  
  
        #Loop through all parameters of the active   
        source_obj_description = source.GetDescription(flags=c4d.DESCFLAGS_DESC_0)   
        for bc, descid, groupid in source_obj_description:   
            id = descid[0].id   
            if id in banned_ids:   
               continue   
  
            data_type = bc[c4d.DESC_CUSTOMGUI]   
            if (data_type is not None) and (data_type not in banned_types) :   
               #Add a output port   
               output_port = source_node.AddPort(c4d.GV_PORT_OUTPUT, descid)   
  
               #Tell C4D that it should display the Output port???   
               bc[c4d.DESC_OUTPORT] = True   
  
               #Add an input port   
               input_port = dest_node.AddPort(c4d.GV_PORT_INPUT, descid, flag=c4d.GV_PORT_FLAG_IS_VISIBLE)   
  
               #Link the two   
               output_port.Connect(input_port)   
  
        source.Message(c4d.MSG_CHANGE)   
        destination.Message(c4d.MSG_CHANGE)   
        doc.AddUndo(c4d.UNDOTYPE_NEW, xpresso_tag)   
       
    c4d.EventAdd()   
    doc.EndUndo()   
  
if __name__=='__main__':   
    main()   

On 04/12/2015 at 03:38, xxxxxxxx wrote:

Hello,

if you want to find out if a parameter is animateable you can check the DESC_ANIMATE parameter of the description. But you are asking if a parameter has a subdescription. Since the Description is very limited in Python I guess the best solution is to check if the parameter is question is a vector or color and to handle the subparameters manually.

The BaseContainer returned by GetDescription() is a copy so changing this BaseContainer won't do anything.

The Xpresso usage of a parameter is only displayed in the Attribute Manager if the connection between the Object Operator and the referenced object is created properly. To do this one would have to use OperatorSetData() which is only available in C++.

The Object Operator is able to fix this connection. This is done for example when the document is merged with another document. So a "hack" would be to send the MSG_DOCUMENTINFO_TYPE_LOAD message. Something like this:

  
doc.SendInfo(c4d.MSG_DOCUMENTINFO_TYPE_LOAD, c4d.FORMAT_C4DIMPORT, "", None, False)  

best wishes,
Sebastian

On 04/12/2015 at 11:41, xxxxxxxx wrote:

Hi Sebastian,

That hack does the trick! I never would have found that. Thank you. I assume this will be pretty slow on large scenes as it will force a full reload?
Thanks!

Donovan