SOLVED Directly create Redshift standard surface for RS node space

Hello, Is there possibale to create a standard surface directly in new node editor (not expresso) ?

When I create a Redshift node material it always return a old RS material by default. now my solution is add a new standard surface shader and remove the old RS material , Is there a smart way to do this ?

(by the way, I know I can use CallCommand fuction , but I working a a custom API with Redshift , so I need a controllable way )

Here is a little lines I do this :

import c4d
import maxon

StandardMaterialAssetID = maxon.Id("com.redshift3d.redshift4c4d.nodes.core.standardmaterial")
StandardOutputPortID = maxon.Id("com.redshift3d.redshift4c4d.nodes.core.standardmaterial.outcolor")
OutputMaterialAssetID = maxon.Id("com.redshift3d.redshift4c4d.node.output")
OutputSurfacePortID = maxon.Id("com.redshift3d.redshift4c4d.node.output.surface")

def CreateNodeMat(matname):
    mat = c4d.BaseMaterial(c4d.Mmaterial)
    nodeMaterial = mat.GetNodeMaterialReference()
    nodespaceId = maxon.Id("com.redshift3d.redshift4c4d.class.nodespace")
    addedGraph = nodeMaterial.AddGraph(nodespaceId)
    nimbusRef = mat.GetNimbusRef(nodespaceId)
    graph = nimbusRef.GetGraph()
    endNodePath = nimbusRef.GetPath(maxon.NIMBUS_PATH.MATERIALENDNODE)
    endNode = graph.GetNode(endNodePath)
    predecessor = list()
    maxon.GraphModelHelper.GetDirectPredecessors(endNode, maxon.NODE_KIND.NODE, predecessor)
    bsdfNode = predecessor[0]
    bsdfNodeInputs = bsdfNode.GetInputs()

    with graph.BeginTransaction() as transaction:
        STM = graph.AddChild('', StandardMaterialAssetID, maxon.DataDictionary())
        inPort = endNode.GetInputs().FindChild("com.redshift3d.redshift4c4d.node.output.surface")
        outPort = STM.GetOutputs().FindChild("com.redshift3d.redshift4c4d.nodes.core.standardmaterial.outcolor")
        outPort.Connect(target = inPort, modes=maxon.WIRE_MODE.NORMAL, reverse=False)

if __name__ == "__main__":
    CreateNodeMat("RS Node STD")


When you call AddGraph, the delegate function registered for the nodespace to create a material is executed. That is why it create a default redshift node material with the default endNode and the default RS Material node.

The only way to do it for now is exactly what you are doing.

One remark i should have comment in our examples,

addedGraph = nodeMaterial.AddGraph(nodespaceId)
nimbusRef = mat.GetNimbusRef(nodespaceId)
graph = nimbusRef.GetGraph()

addedGraph is the same as graph, nimbusRef are sometimes useful, but if you are just manipulating existing graph, they are not.


@m_magalhaes Thanks

That' ok , Maybe I should create a specific function to do this task😊

And your tips:

graph1 = nodeMaterial.AddGraph(nodespaceId)
graph2 = mat.GetNodeMaterialReference().GetNimbusRef(nodespaceId).GetGraph()

gragh1 is the same as gragh2 ? In Chinese laguage the word NimbusRef is hard to understand , I read the python document , is that mean a list a material's node space ? like :Mat[arnold spcae, redshift space]

So the gragh2 fuction get the redshift spcae and get the gragh nodes for redshift only ?


A material object inherit from BaseList2D object. That BaseList2D can store multiple graphs, one for each space. NimbusBaseInterface manages NodesGraphModelInterface. From an external point of view, the NimBusRef is just a hook to attach a NodeGraph to a Material. Internally, it manages the technical aspect of a NodeGraphModel.

NodeMaterial.GetGraph(self, spaceId)
NodeMaterial.AddGraph(self, spaceId)
all those functions return the same maxon.NodesGraphModelRef


Thanks for that explain.