How to connect new ports and node ports in the group?
-
I would appreciate it if you could demonstrate the correct way to connect the red lines in the chart.import c4d import maxon from redshift_api import redshift_id as rsID def create_psr(): mat = doc.GetActiveMaterial() if mat is None: raise ValueError("There is no selected BaseMaterial") nodeMaterial = mat.GetNodeMaterialReference() if nodeMaterial is None: raise ValueError("Cannot retrieve node material reference") nodespaceId = c4d.GetActiveNodeSpaceId() nimbusRef = mat.GetNimbusRef(nodespaceId) if nimbusRef is None: raise ValueError("Cannot retrieve the nimbus ref for that node space") graph = nimbusRef.GetGraph() if graph is None: raise ValueError("Cannot retrieve the graph of this nimbus ref") root = graph.GetRoot() nodes = [] root.GetChildren(nodes, maxon.NODE_KIND.NODE) with graph.BeginTransaction() as transaction: TexNodeID: maxon.Id = maxon.Id(rsID.StrNodeID("texturesampler")) rsmathabsvectorID: maxon.Id = maxon.Id(rsID.StrNodeID("rsmathabsvector")) rsmathabsID: maxon.Id = maxon.Id(rsID.StrNodeID("rsmathabs")) TexNode: maxon.GraphNode = graph.AddChild(maxon.Id(), TexNodeID) P_rsmathabsvector: maxon.GraphNode = graph.AddChild(maxon.Id(), rsmathabsvectorID) S_rsmathabsvector: maxon.GraphNode = graph.AddChild(maxon.Id(), rsmathabsvectorID) R_rsmathabs: maxon.GraphNode = graph.AddChild(maxon.Id(), rsmathabsID) TexNodeScaleInputPort: maxon.GraphNode = TexNode.GetInputs().FindChild( rsID.StrPortID("texturesampler", "scale")) TexNodeOffsetInputPort: maxon.GraphNode = TexNode.GetInputs().FindChild( rsID.StrPortID("texturesampler", "offset")) TexNodeRotateInputPort: maxon.GraphNode = TexNode.GetInputs().FindChild( rsID.StrPortID("texturesampler", "rotate")) P_rsmathabsvectorOutPort: maxon.GraphNode = P_rsmathabsvector.GetOutputs().FindChild( rsID.StrPortID("rsmathabsvector", "out")) S_rsmathabsvectorOutPort: maxon.GraphNode = S_rsmathabsvector.GetOutputs().FindChild( rsID.StrPortID("rsmathabsvector", "out")) R_rsmathabOutPort: maxon.GraphNode = R_rsmathabs.GetOutputs().FindChild( rsID.StrPortID("rsmathabs", "out")) P_rsmathabsvectorInputPort: maxon.GraphNode = P_rsmathabsvector.GetInputs().FindChild( rsID.StrPortID("rsmathabsvector", "input")) S_rsmathabsvectorInputPort: maxon.GraphNode = S_rsmathabsvector.GetInputs().FindChild( rsID.StrPortID("rsmathabsvector", "input")) R_rsmathabInputPort: maxon.GraphNode = R_rsmathabs.GetInputs().FindChild( rsID.StrPortID("rsmathabs", "input")) P_rsmathabsvectorOutPort.Connect(TexNodeScaleInputPort, modes=maxon.WIRE_MODE.NORMAL, reverse=False) S_rsmathabsvectorOutPort.Connect(TexNodeOffsetInputPort, modes=maxon.WIRE_MODE.NORMAL, reverse=False) R_rsmathabOutPort.Connect(TexNodeRotateInputPort, modes=maxon.WIRE_MODE.NORMAL, reverse=False) GroupNodes = [] GroupNodes.append(TexNode) GroupNodes.append(P_rsmathabsvector) GroupNodes.append(S_rsmathabsvector) GroupNodes.append(R_rsmathabs) TexNodeScaleOutPort: maxon.GraphNode = TexNode.GetInputs().FindChild( rsID.StrPortID("texturesampler", "scale")) groupRoot = maxon.GraphNode() groupRoot = graph.MoveToGroup(groupRoot, maxon.Id("PSRgroupID"), GroupNodes) P_InputPort = maxon.GraphModelHelper.CreateInputPort(groupRoot, "scaleid", "缩放") S_InputPort = maxon.GraphModelHelper.CreateInputPort(groupRoot, "offsetid", "偏移") R_InputPort = maxon.GraphModelHelper.CreateInputPort(groupRoot, "rotateid", "旋转") PSR_OutputPort = maxon.GraphModelHelper.CreateOutputPort(groupRoot, "psrid", "输出") transaction.Commit() c4d.EventAdd()
-
Hello @君心Jay,
Welcome to the Plugin Café forum and the Cinema 4D development community, it is great to have you with us!
Getting Started
Before creating your next postings, we would recommend making yourself accustomed with our Forum and Support Guidelines, as they line out details about the Maxon SDK Group support procedures. Of special importance are:
- Support Procedures: Scope of Support: Lines out the things we will do and what we will not do.
- Support Procedures: Confidential Data: Most questions should be accompanied by code but code cannot always be shared publicly. This section explains how to share code confidentially with Maxon.
- Forum Structure and Features: Lines out how the forum works.
- Structure of a Question: Lines out how to ask a good technical question. It is not mandatory to follow this exactly, but you should follow the idea of keeping things short and mentioning your primary question in a clear manner.
About your First Question
First of all there is no "correct" way of doing that. The pattern you should use depend on the context of your goal.
For example, looking at your code snippet it seems that the easiest way for you to make these connections would be to first connect the graph with the outside nodes and then use the MoveToGroup function, which would rewire the connections for you automatically.
This is, however, not the general case. If you would really like to manually wire these ports, you would simply need to find them inside the group and connect them normally using Connect function. The pitfall here is that once you move your sub-graph to the group, it changes its path. This basically means that you'd need to find these nodes using FindNodesByAssetId or GetInnerNodes functions.
Please refer to the draft sketch below that shows both approaches (you need to comment/uncomment corresponding function call in
main()
).Cheers,
IliaDraft sketch:
import c4d import maxon doc: c4d.documents.BaseDocument mat: c4d.BaseMaterial nimbusRef: maxon.NimbusBaseInterface graph: maxon.GraphModelInterface def main(): global doc, mat, nimbusRef, graph mat = doc.GetActiveMaterial() nimbusRef = mat.GetNimbusRef(c4d.GetActiveNodeSpaceId()) graph = nimbusRef.GetGraph() easy_way() # manual_wiring() class rsID: def StrNodeID(id: str) -> str: return "com.redshift3d.redshift4c4d.nodes.core." + id def StrPortID(nodeId: str, portId: str) -> str: return "com.redshift3d.redshift4c4d.nodes.core." + nodeId + "." + portId def easy_way(): with graph.BeginTransaction() as transaction: # The outside value node valNode: maxon.GraphNode = graph.AddChild(maxon.Id(), maxon.Id("net.maxon.node.type")) valPortOutput: maxon.GraphNode = valNode.GetOutputs().FindChild("out") # The inside ABS node absNode: maxon.GraphNode = graph.AddChild(maxon.Id(), maxon.Id(rsID.StrNodeID("rsmathabs"))) absPortInput: maxon.GraphNode = absNode.GetInputs().FindChild(rsID.StrPortID("rsmathabs", "input")) absPortOutput: maxon.GraphNode = absNode.GetOutputs().FindChild(rsID.StrPortID("rsmathabs", "out")) # Existing Standard material node stdMatNodes: list[maxon.GraphNode] = [] maxon.GraphModelHelper.FindNodesByAssetId(graph, maxon.Id(rsID.StrNodeID("standardmaterial")), True, stdMatNodes) matNode: maxon.GraphNode = stdMatNodes[0] matPortOpac: maxon.GraphNode = matNode.GetInputs().FindChild(rsID.StrPortID("standardmaterial", "opacity_color")) # Connect everything in place valPortOutput.Connect(absPortInput) absPortOutput.Connect(matPortOpac) # Move to group -> rewiring is handled automatically graph.MoveToGroup(maxon.GraphNode(), maxon.Id("PSRgroupID"), [absNode]) transaction.Commit() c4d.EventAdd() def manual_wiring(): with graph.BeginTransaction() as transaction: # The outside value node valNode: maxon.GraphNode = graph.AddChild(maxon.Id(), maxon.Id("net.maxon.node.type")) valPortOutput: maxon.GraphNode = valNode.GetOutputs().FindChild("out") # The inside ABS node absNode: maxon.GraphNode = graph.AddChild(maxon.Id(), maxon.Id(rsID.StrNodeID("rsmathabs"))) # Existing Standard material node stdMatNodes: list[maxon.GraphNode] = [] maxon.GraphModelHelper.FindNodesByAssetId(graph, maxon.Id(rsID.StrNodeID("standardmaterial")), True, stdMatNodes) matNode: maxon.GraphNode = stdMatNodes[0] matPortOpac: maxon.GraphNode = matNode.GetInputs().FindChild(rsID.StrPortID("standardmaterial", "opacity_color")) # Move to group straight away groupRoot = graph.MoveToGroup(maxon.GraphNode(), maxon.Id("PSRgroupID"), [absNode]) # Create group ports groupPortInputOutside: maxon.GraphNode = maxon.GraphModelHelper.CreateInputPort(groupRoot, "group_input_id", "grpInput") groupPortOutputOutside: maxon.GraphNode = maxon.GraphModelHelper.CreateOutputPort(groupRoot, "group_output_id", "grpOutput") # Connect group to the outside nodes valPortOutput.Connect(groupPortInputOutside) groupPortOutputOutside.Connect(matPortOpac) # Find innder node innerNodes: list[maxon.GraphNode] = [] maxon.GraphModelHelper.FindNodesByAssetId(graph, maxon.Id(rsID.StrNodeID("rsmathabs")), True, innerNodes) absNodeInner: maxon.GraphNode = innerNodes[0] # Find inner node ports absNodeInnerInput: maxon.GraphNode = absNodeInner.GetInputs().FindChild(rsID.StrPortID("rsmathabs", "input")) absNodeInnerOutput: maxon.GraphNode = absNodeInner.GetOutputs().FindChild(rsID.StrPortID("rsmathabs", "out")) # Connect inner node ports to group ports groupPortInputOutside.Connect(absNodeInnerInput) absNodeInnerOutput.Connect(groupPortOutputOutside) transaction.Commit() c4d.EventAdd() if __name__ == '__main__': main()
-
Hi @i_mazlov , thanks for the great answer.
I would like to further inquire about this issue:
-
if there are more than one "same id" nodes, how to make sure that the child of innerNodes list is the node we want, I test GraphNode.GetParent() and didn't return the "Group node" but return a path "Root", and I didn't found a method to check if a GraphNode is a child of a Group, how do we do that?
-
If we use GraphNode.GetInnerNodes(), is it a better choice for this case, and if there some hidden danger for this?
# Find innder node innerNodes: list[maxon.GraphNode] = [] groupRoot.GetInnerNodes(maxon.NODE_KIND.NODE,False,innerNodes)
Thanks for your time!
Cheers~
DunHou -
-
Hi there,
Taking inspiration from this topic, I added UniTransform to the my RenderFlow plugin and added AddUniTransform to my renderEngine library, those will be add on the next update.
Here is a quick preview, have fun.
Cheers~
DunHou -
Hi @i_mazlov , thanks for the great answer.
I've learned a lotCheers~
君心Jay -
Hi, @Dunhou ,
Regarding your questions.
if there are more than one "same id" nodes, how to make sure that the child of innerNodes list is the node we want
Nodes cannot have the same ID, so you can easily distinguish them by it (GetId() function) or search for it with FindNodesById() function. The way you determine if current node is what you're looking for depends on the criteria you apply to this node. For example, you can filter nodes by their AssetId (using FindNodesByAssetId() function call as I showed above) or you can filter them by name (FindNodesByName()), or you can list nodes by some arbitrary condition (or set of conditions) using ListAllNodes().
I didn't found a method to check if a GraphNode is a child of a Group
The GetParent() function should do this for you, for example:
with graph.BeginTransaction() as transaction: absNode: maxon.GraphNode = graph.AddChild(maxon.Id(), maxon.Id("com.redshift3d.redshift4c4d.nodes.core.rsmathabs")) groupRoot: maxon.GraphNode = graph.MoveToGroup(maxon.GraphNode(), maxon.Id("myFancyGroupId"), [absNode]) absNode = groupRoot.FindChild(absNode.GetId()) print(groupRoot.GetId()) print(absNode.GetParent().GetId()) transaction.Commit()
If we use GraphNode.GetInnerNodes(), is it a better choice for this case, and if there some hidden danger for this?
Yes, probably reducing the scope to node's children would be more efficient here. I assume in this particular case FindChild() function would have been the best choice. However, you wouldn't notice any performance difference on such a small graph.
Cheers,
Ilia -
Hi @i_mazlov ,
Thanks for your time, sorry for my bad that I use a confusing word for "id", I should say "asset id", but as you said, I can use ID to check this, for some reason, I overlooked this for a moment.
And the GetParent(), I found out that the culprit is GetSelectedNodes(), I use this to get a selected node(abs bode) but the return is "group", so what ever I try the return is 'Root'.
Thanks for all your works!
Cheers~
DunHou