Awesome, thanks @i_mazlov
Very nice approach to create an User Data entry.
How can I find this kind of information when it is not documented, as I suppose there are other UD options without a symbol defined?
Awesome, thanks @i_mazlov
Very nice approach to create an User Data entry.
How can I find this kind of information when it is not documented, as I suppose there are other UD options without a symbol defined?
Hi,
I'm creating User Data through Python and I'm able to create a dropdown list (combobox) with this:
cycle = c4d.GetCustomDataTypeDefault(c4d.DTYPE_LONG)
cycle[c4d.DESC_CUSTOMGUI] = c4d.CUSTOMGUI_CYCLE
But this is not what I want at all, but the old and classic radio button, as below.
I'd expect to find something like 'c4d.CUSTOMGUI_RADIOBUTTONS' in the documentation, but there is nothing even close to this.
Is it possible to be created in Python?
Thanks @ferdinand, you answered my question brilliantly, as you always do.
Cheers
Hey guys, how is it going with this BUG?
Is it gonna be fixed soon?
Thanks
Hi there,
In a ShaderGraph material I'm able to flip the spline in a Scalar Ramp node as well as invert the gradient in a Ramp node by using:
Flip()
InvertKnots()
Do we have similar methods for the Maxon API?
Do I need to invert the knots and points one by one manually?
If so I'd appreciate any examples.
Thanks a lot
Hey @m_adam ,
Thanks for your help. It works now.
However, I'm wondering how I would have known that I needed to set the scaffold ID to the node. The documentation doesn't seem to explicitly mention this step. I might be wrong, but for someone without strong knowledge of the API, I'd never thought that way. I would rather added the selected nodes to a group, as this is what a scaffol is. Does that make sense?
As a side note, after adding the nodes to the scaffold group, they appear messy, actually the nodes are nicely arranged inside the group, but the scaffold is overlapping other nodes. This is likely related to the bug we discussed here: https://developers.maxon.net/forum/post/73446. Am I right?
Cheers
Hi, I've been searching for examples on how to add nodes to a scaffold group in Python, but there is nothing available and the documentation is not helping too much as well....
This is what I was trying to do, creating a material based on the example from github and adding a scaffold and then trying to move some nodes into it. But of course it is not working as this is just an attempt from a trial and error.
Any help would be appreciated.
Thanks
import c4d
import maxon
doc: c4d.documents.BaseDocument
def main():
urlTexRust: maxon.Url = maxon.Url(r"asset:///file_edb3eb584c0d905c")
urlTexSketch: maxon.Url = maxon.Url(r"asset:///file_3b194acc5a745a2c")
# The node asset IDs
idTextureNode: maxon.Id = maxon.Id("com.redshift3d.redshift4c4d.nodes.core.texturesampler")
idMixNode: maxon.Id = maxon.Id("com.redshift3d.redshift4c4d.nodes.core.rscolormix")
idRsStandardMaterial: maxon.Id = maxon.Id("com.redshift3d.redshift4c4d.nodes.core.standardmaterial")
# Instantiate a material, get its node material and the graph for the RS material space.
material: c4d.BaseMaterial = c4d.BaseMaterial(c4d.Mmaterial)
if not material:
raise MemoryError(f"{material = }")
nodeMaterial: c4d.NodeMaterial = material.GetNodeMaterialReference()
graph: maxon.GraphModelRef = nodeMaterial.CreateDefaultGraph(
maxon.Id("com.redshift3d.redshift4c4d.class.nodespace"))
if graph.IsNullValue():
raise RuntimeError("Could not add RS graph to material.")
# Get the Standard Material node
result: list[maxon.GraphNode] = []
maxon.GraphModelHelper.FindNodesByAssetId(graph, idRsStandardMaterial, True, result)
if len(result) < 1:
raise RuntimeError("Could not find RS Standard node in material.")
standardNode: maxon.GraphNode = result[0]
with graph.BeginTransaction() as transaction:
# Add two texture nodes and a blend node to the graph.
rustTexNode: maxon.GraphNode = graph.AddChild(maxon.Id(), idTextureNode)
sketchTexNode: maxon.GraphNode = graph.AddChild(maxon.Id(), idTextureNode)
mixNode: maxon.GraphNode = graph.AddChild(maxon.Id(), idMixNode)
mixAmount: maxon.GraphNode = mixNode.GetInputs().FindChild(
"com.redshift3d.redshift4c4d.nodes.core.rscolormix.mixamount")
mixAmount.SetDefaultValue(0.5)
# Get the ports and set the values
pathRustPort: maxon.GraphNode = rustTexNode.GetInputs().FindChild(
"com.redshift3d.redshift4c4d.nodes.core.texturesampler.tex0").FindChild("path")
pathSketchPort: maxon.GraphNode = sketchTexNode.GetInputs().FindChild(
"com.redshift3d.redshift4c4d.nodes.core.texturesampler.tex0").FindChild("path")
pathRustPort.SetDefaultValue(urlTexRust)
pathSketchPort.SetDefaultValue(urlTexSketch)
# Get the color output ports of the two texture nodes and the color blend node.
rustTexColorOutPort: maxon.GraphNode = rustTexNode.GetOutputs().FindChild(
"com.redshift3d.redshift4c4d.nodes.core.texturesampler.outcolor")
sketchTexColorOutPort: maxon.GraphNode = sketchTexNode.GetOutputs().FindChild(
"com.redshift3d.redshift4c4d.nodes.core.texturesampler.outcolor")
mixColorOutPort: maxon.GraphNode = mixNode.GetOutputs().FindChild(
"com.redshift3d.redshift4c4d.nodes.core.rscolormix.outcolor")
# Get the ports
mixInput1Port: maxon.GraphNode = mixNode.GetInputs().FindChild(
"com.redshift3d.redshift4c4d.nodes.core.rscolormix.input1")
mixInput2Port: maxon.GraphNode = mixNode.GetInputs().FindChild(
"com.redshift3d.redshift4c4d.nodes.core.rscolormix.input2")
stdBaseColorInPort: maxon.GraphNode = standardNode.GetInputs().FindChild(
"com.redshift3d.redshift4c4d.nodes.core.standardmaterial.base_color")
# Connect the nodes
rustTexColorOutPort.Connect(mixInput1Port, modes=maxon.WIRE_MODE.NORMAL, reverse=False)
sketchTexColorOutPort.Connect(mixInput2Port, modes=maxon.WIRE_MODE.NORMAL, reverse=False)
mixColorOutPort.Connect(stdBaseColorInPort, modes=maxon.WIRE_MODE.NORMAL, reverse=False)
transaction.Commit()
# Find all the texture nodes
tex_nodes = []
maxon.GraphModelHelper.FindNodesByAssetId(graph, idTextureNode, True, tex_nodes)
################################
# my attempt of grouping the texture nodes in a Scaffold
#
with graph.BeginTransaction() as transaction:
scaffold = graph.AddChild(maxon.Id(), maxon.Id("net.maxon.node.scaffold"))
graph.MoveToGroup(scaffold, maxon.Id("idOfMyGroup"), tex_nodes)
transaction.Commit()
#
################################
doc.InsertMaterial(material)
doc.SetActiveMaterial(material)
c4d.EventAdd()
if __name__ == "__main__":
main()
Thanks @Dunhou, I appreciate your reply confirms what seems to be a bug, and I wonder if @m_adam could confirm it based on the working code I provided, which demonstrates the issue in a simple way.
Hi there, I'm adding nodes to an existing node material and I'm not being able to get a nice and organized result in the node editor, even after all connections are done.
However, if I create a material from scratch, then add the nodes and connect them the same way, the node editor finds an optimized way to organize the graph and the result is nice as expected.
So, these are the 2 approaches and the result:
1- add and connect nodes within an existing material - the new nodes are overlapping each other
2- create the material and then add and connect the nodes within it - the new nodes are nicely organized
How can I get a nice result with approach 1?
I used the example create_redshift_nodematerial_2024.py for the approach 2.
For the approach 1 I'm commenting the line:
createRSMaterial()
import c4d
import maxon
doc: c4d.documents.BaseDocument # The active document.
def createRSMaterial():
urlTexRust: maxon.Url = maxon.Url(r"asset:///file_edb3eb584c0d905c")
urlTexSketch: maxon.Url = maxon.Url(r"asset:///file_3b194acc5a745a2c")
# The node asset IDs
idTextureNode: maxon.Id = maxon.Id("com.redshift3d.redshift4c4d.nodes.core.texturesampler")
idMixNode: maxon.Id = maxon.Id("com.redshift3d.redshift4c4d.nodes.core.rscolormix")
idRsStandardMaterial: maxon.Id = maxon.Id("com.redshift3d.redshift4c4d.nodes.core.standardmaterial")
# Instantiate a material, get its node material and the graph for the RS material space.
material: c4d.BaseMaterial = c4d.BaseMaterial(c4d.Mmaterial)
if not material:
raise MemoryError(f"{material = }")
nodeMaterial: c4d.NodeMaterial = material.GetNodeMaterialReference()
graph: maxon.GraphModelRef = nodeMaterial.CreateDefaultGraph(
maxon.Id("com.redshift3d.redshift4c4d.class.nodespace"))
if graph.IsNullValue():
raise RuntimeError("Could not add RS graph to material.")
# Get the Standard Material node
result: list[maxon.GraphNode] = []
maxon.GraphModelHelper.FindNodesByAssetId(graph, idRsStandardMaterial, True, result)
if len(result) < 1:
raise RuntimeError("Could not find RS Standard node in material.")
standardNode: maxon.GraphNode = result[0]
with graph.BeginTransaction() as transaction:
# Add two texture nodes and a blend node to the graph.
rustTexNode: maxon.GraphNode = graph.AddChild(maxon.Id(), idTextureNode)
sketchTexNode: maxon.GraphNode = graph.AddChild(maxon.Id(), idTextureNode)
mixNode: maxon.GraphNode = graph.AddChild(maxon.Id(), idMixNode)
mixAmount: maxon.GraphNode = mixNode.GetInputs().FindChild(
"com.redshift3d.redshift4c4d.nodes.core.rscolormix.mixamount")
mixAmount.SetDefaultValue(0.5)
# Get the ports and set the values
pathRustPort: maxon.GraphNode = rustTexNode.GetInputs().FindChild(
"com.redshift3d.redshift4c4d.nodes.core.texturesampler.tex0").FindChild("path")
pathSketchPort: maxon.GraphNode = sketchTexNode.GetInputs().FindChild(
"com.redshift3d.redshift4c4d.nodes.core.texturesampler.tex0").FindChild("path")
pathRustPort.SetDefaultValue(urlTexRust)
pathSketchPort.SetDefaultValue(urlTexSketch)
# Get the color output ports of the two texture nodes and the color blend node.
rustTexColorOutPort: maxon.GraphNode = rustTexNode.GetOutputs().FindChild(
"com.redshift3d.redshift4c4d.nodes.core.texturesampler.outcolor")
sketchTexColorOutPort: maxon.GraphNode = sketchTexNode.GetOutputs().FindChild(
"com.redshift3d.redshift4c4d.nodes.core.texturesampler.outcolor")
mixColorOutPort: maxon.GraphNode = mixNode.GetOutputs().FindChild(
"com.redshift3d.redshift4c4d.nodes.core.rscolormix.outcolor")
# Get the ports
mixInput1Port: maxon.GraphNode = mixNode.GetInputs().FindChild(
"com.redshift3d.redshift4c4d.nodes.core.rscolormix.input1")
mixInput2Port: maxon.GraphNode = mixNode.GetInputs().FindChild(
"com.redshift3d.redshift4c4d.nodes.core.rscolormix.input2")
stdBaseColorInPort: maxon.GraphNode = standardNode.GetInputs().FindChild(
"com.redshift3d.redshift4c4d.nodes.core.standardmaterial.base_color")
# Connect the nodes
rustTexColorOutPort.Connect(mixInput1Port, modes=maxon.WIRE_MODE.NORMAL, reverse=False)
sketchTexColorOutPort.Connect(mixInput2Port, modes=maxon.WIRE_MODE.NORMAL, reverse=False)
mixColorOutPort.Connect(stdBaseColorInPort, modes=maxon.WIRE_MODE.NORMAL, reverse=False)
transaction.Commit()
doc.InsertMaterial(material)
doc.SetActiveMaterial(material)
c4d.EventAdd()
def main():
# create a RS material
createRSMaterial()
# Get the material
material = doc.GetActiveMaterial()
# Check if the material exists and is a node material
if not material or not material.IsInstanceOf(c4d.Mmaterial):
return
# Get the node material
nodeMaterial = material.GetNodeMaterialReference()
nodespaceId = c4d.GetActiveNodeSpaceId()
rsNodeSpaceId = maxon.Id("com.redshift3d.redshift4c4d.class.nodespace")
if nodespaceId != rsNodeSpaceId:
return
# Get the graph
try: graph = nodeMaterial.GetGraph(nodespaceId)
except: return
# Set the asset IDs
idTextureNode = maxon.Id("com.redshift3d.redshift4c4d.nodes.core.texturesampler")
idColorCorrection = maxon.Id("com.redshift3d.redshift4c4d.nodes.core.rscolorcorrection")
# Find all the texture nodes
tex_nodes = []
maxon.GraphModelHelper.FindNodesByAssetId(graph, idTextureNode, True, tex_nodes)
if not tex_nodes:
return
for node in tex_nodes:
for out_port in node.GetOutputs().GetChildren():
for dest_port, wires in out_port.GetConnections(maxon.PORT_DIR.OUTPUT, None, maxon.Wires.All(), maxon.WIRE_MODE.ALL):
with graph.BeginTransaction() as transaction:
# Remove existing connection
maxon.GraphModelHelper.RemoveConnection(out_port, dest_port)
# Create node
colorCorrectionNode = graph.AddChild(maxon.Id(), idColorCorrection)
# Get the ports
cc_inPort = colorCorrectionNode.GetInputs().FindChild("com.redshift3d.redshift4c4d.nodes.core.rscolorcorrection.input")
cc_outPort = colorCorrectionNode.GetOutputs().FindChild("com.redshift3d.redshift4c4d.nodes.core.rscolorcorrection.outcolor")
# Connect the nodes
cc_outPort.Connect(dest_port, modes=maxon.WIRE_MODE.NORMAL, reverse=False)
out_port.Connect(cc_inPort, modes=maxon.WIRE_MODE.NORMAL, reverse=False)
transaction.Commit()
doc.InsertMaterial(material)
c4d.EventAdd()
if __name__ == "__main__":
main()