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