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()