Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login
    1. Maxon Developers Forum
    2. simonator420
    3. Topics
    S
    • Profile
    • Following 0
    • Followers 0
    • Topics 4
    • Posts 7
    • Best 1
    • Controversial 0
    • Groups 0

    Topics created by simonator420

    • S

      HideElement in Cinema 4D 2024

      Cinema 4D SDK
      • 2024 python • • simonator420
      4
      0
      Votes
      4
      Posts
      699
      Views

      DunhouD

      Yes @simonator420 , it worked in 2023, and not worked any more in 2024, I also found that strange behavior in HideElement() and confused me for a while.

    • S

      Redshift Standard Material base Properties

      Bugs
      • • • simonator420
      3
      0
      Votes
      3
      Posts
      1.3k
      Views

      ferdinandF

      Hey @simonator420,

      Thank you for reaching out to us. And thank you @Dunhou for providing a solution. You should however be aware that Dunhou's solution requires his proprietary library as he states below. I think you should give it a spin because it is quite useful.

      When you must remain within the bounds of the Cinema 4D standard library, find an example for how to do that below.

      Cheers,
      Ferdinand

      PS: I have added the example below to the code examples of the upcoming release alongside the standard renderer example.

      Result:
      2f242653-ad67-4010-a78a-277f5953b856-image.png

      Code:

      #coding: utf-8 """Demonstrates setting up a Redshift node material composed out of multiple nodes. Creates a new node material with a graph in the Redshift material space, containing two texture nodes and a mix node, in addition to the default core material and material node of the material. Topics: * Creating a node material and adding a graph * Adding nodes to a graph * Setting the value of ports without wires * Connecting ports with a wires * (Asset API): Using texture assets in a node graph """ __author__ = "Ferdinand Hoppe" __copyright__ = "Copyright (C) 2023 MAXON Computer GmbH" __date__ = "01/09/2023" __license__ = "Apache-2.0 License" __version__ = "2023.2.0" import c4d import maxon doc: c4d.documents.BaseDocument # The active document. def main() -> None: """Runs the example. """ # The asset URLs for the "RustPaint0291_M.jpg" and "Sketch (HR basic026).jpg" texture assets in # "tex/Surfaces/Dirt Scratches & Smudges/". These could also be replaced with local texture URLs, # e.g., "file:///c:/textures/stone.jpg". These IDs can be discovered with the #-button in the info # area of the Asset Browser. urlTexRust: maxon.Url = maxon.Url(r"asset:///file_edb3eb584c0d905c") urlTexSketch: maxon.Url = maxon.Url(r"asset:///file_3b194acc5a745a2c") # The node asset IDs for the two node types to be added in the example; the texture node and the # mix node. These and all other node IDs can be discovered in the node info overlay in the # bottom left corner of the Node Editor. Open the Cinema 4D preferences by pressing CTRL/CMD + E # and enable Node Editor -> Ids in order to see node and port IDs in the Node Editor. idTextureNode: maxon.Id = maxon.Id("com.redshift3d.redshift4c4d.nodes.core.texturesampler") idMixNode: maxon.Id = maxon.Id("com.redshift3d.redshift4c4d.nodes.core.rscolormix") idCoreMaterialNode: maxon.Id = maxon.Id("com.redshift3d.redshift4c4d.nodes.core.material") # 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.AddGraph( maxon.Id("com.redshift3d.redshift4c4d.class.nodespace")) if graph.IsNullValue(): raise RuntimeError("Could not add RS graph to material.") doc.InsertMaterial(material) c4d.EventAdd() # Attempt to find the core material node contained in the default graph setup. result: list[maxon.GraphNode] = [] maxon.GraphModelHelper.FindNodesByAssetId(graph, idCoreMaterialNode, True, result) if len(result) < 1: raise RuntimeError("Could not find standard node in material.") standardNode: maxon.GraphNode = result[0] # Start modifying the graph by opening a transaction. Node graphs follow a database like # transaction model where all changes are only finally applied once a transaction is committed. 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) # Set the default value of the 'Mix Amount' port, i.e., the value the port has when no # wire is connected to it. This is equivalent to the user setting the value to "0.5" in # the Attribute Manager. mixAmount: maxon.GraphNode = mixNode.GetInputs().FindChild( "com.redshift3d.redshift4c4d.nodes.core.rscolormix.mixamount") mixAmount.SetDefaultValue(0.5) # Set the path sub ports of the 'File' ports of the two image nodes to the texture URLs # established above. Other than for the standard node space image node, the texture is # expressed as a port bundle, i.e., a port which holds other ports. The texture of a texture # node is expressed as the "File" port, of which "Path", the URL, is only one of the possible # sub-ports to set. 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 fore- and background port of the blend node and the color port of the BSDF node. 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") coreDiffusePort: maxon.GraphNode = standardNode.GetInputs().FindChild( "com.redshift3d.redshift4c4d.nodes.core.material.diffuse_color") # Wire up the two texture nodes to the blend node and the blend node to the BSDF node. rustTexColorOutPort.Connect(mixInput1Port, modes=maxon.WIRE_MODE.NORMAL, reverse=False) sketchTexColorOutPort.Connect(mixInput2Port, modes=maxon.WIRE_MODE.NORMAL, reverse=False) mixColorOutPort.Connect(coreDiffusePort, modes=maxon.WIRE_MODE.NORMAL, reverse=False) # Finish the transaction to apply the changes to the graph. transaction.Commit() # Insert the material into the document and push an update event. doc.InsertMaterial(material) c4d.EventAdd() if __name__ == "__main__": main()
    • S

      TreeView DropDown Menu

      Cinema 4D SDK
      • • • simonator420
      3
      0
      Votes
      3
      Posts
      828
      Views

      ferdinandF

      Hello @simonator420,

      Thank you for reaching out to us. As announced here, Maxon is currently conducting a company meeting. Please understand that our capability to answer questions is therefore limited at the moment.

      I am slightly confused about the nature of your questions, especially in the context of the reply from @mogh. TreeViewFunctions.GetDropDownMenu lets you define the content of drop down menus in a TreeView, and the slightly ill named SetDropDownMenu lets you react to an item being selected in such menu.

      The 'problem' with your code snippet is that you do not differentiate the drop down gadgets which are set in GetDropDownMenu. Like many methods of TreeViewFunctions it is called for each cell in the tree view table, where lColumn denotes the column as defined in your TreeViewCustomGui.SetLayout call, and obj denotes an item in your root, so sort of the row in the tree.

      lColumn becomes meaningless when your tree view has only one column of type LV_DROPDOWN. How to make sense of obj, depends on the shape of the data you passed as root. When root root is just a list[object], you could for example alternate between even and odd rows like this.

      def GetDropDownMenu( self, root: list[object], userdata: any, obj: object, lColumn: int, menuInfo: dict): """Simple example for defining the menu content based on the position of #obj in #root. """ index: int = root.index(obj) if index % 2 == 0: menuInfo["menu"][1000] = "Even row first option" menuInfo["menu"][1001] = "Even row second option" else: menuInfo["menu"][1000] = "Odd row first option" menuInfo["menu"][1001] = "Odd row second option" menuInfo["state"] = int(menuInfo["state"])

      In practice, the content of a drop down is more likely to be determined based on the fields of obj (e.g., if obj.a == "foo" then Menu1 else Menu2)rather than its relative position in root (be it a list-like or tree-like data structure).

      Cheers,
      Ferdinand

    • S

      Inserting items into dropbox to TreeView

      Cinema 4D SDK
      • • • simonator420
      4
      0
      Votes
      4
      Posts
      650
      Views

      M

      Hi @simonator420 for this purpose you have to define GetDropDownMenu and SetDropDownMenu.

      GetDropDownMenu is called by Cinema 4D to retrieve the content of the menu to display from the menuInfo dictionary. For more information about this dictionary please have a look at TreeViewDropDownMenuInfo Dict.
      SetDropDownMenu is called by Cinema 4D when the user select a value from the dropdown.

      Find bellow an implementation example:

      def GetDropDownMenu(self, root, userdata, obj: Entry, lColumn, menuInfo): menuInfo["entry"] = 1001 # Select teh second entry menuInfo["menu"][1000] = "First Entry" menuInfo["menu"][1001] = "Second Entry" menuInfo["menu"][1002] = "ThirdEntry" menuInfo["state"] = int(menuInfo["state"]) # Workaround to not have warning in Cinema 4D. Will be fixed in the next C4D version. def SetDropDownMenu(self, root, userdata, obj, lColumn, entry): print(f"User selected the entry with the ID: {entry}")

      Finally note that due to an issue that will be fixed in the upcoming version of Cinema 4D, even if you do not change the state, you need to override it to an int value otherwise it will print an error in the console (this is not blocking but still).

      Cheers,
      Maxime.