• 0 Votes
    4 Posts
    78 Views
    ferdinandF
    Hey @vaishhg, As I tried to explain there are no nested dependencies. *.rs is a full blown scene file format which can express geometry, curves, simulation data, materials and more. When you save a Cinema 4D scene as *.rs al data in it is exported to that format, including the "nested" case where a *.c4d scene is referencing a *.c4d scene. So when you start out with this *.c4d scene: Scene.c4d +-- Objects +-- Cloner ( creates 5 instances) +-- Cube Generator +-- Cache +-- Polygon Object +-- Tags +-- Material Tag (references 'Red Material') +-- Materials +-- Red Material And then export it to Scene.rs, you get this (this is not an actual depiction of the file format, just a visualization of what happens, rs is not an open format). Scene.rs +-- Objects +-- Cube.0 [Red Material] +-- Cube.1 [Red Material] +-- Cube.2 [Red Material] +-- Cube.3 [Red Material] +-- Cube.4 [Red Material] +-- Materials +-- Red Material (contains Red Material definition) If you load that file back into Cinema 4D you get this. All data - that these are 5 separate cubes with a red material each - resides in the Redshift core only, we only see a proxy in Cinema 4D, hence the name "RS Proxy Object". It is the Redshift Core which will resolve the data in the RS file at render time. ReferencingScene.c4d +-- Objects +-- RS Proxy Object.0 (loads Scene.rs) +-- Cache (will be empty by default, there is literally no data in the c4d core, only when we set 'Preview' to 'Mesh' there will be a cache so that the viewport can display something) +-- Polygon Object (one blob representing all 5 cubes and no material information) +-- RS Proxy Object.1 (loads Scene.rs) +-- Cache +-- Polygon Object When we now export ReferencingScene.c4d to ReferencingScene.rs we get this. Because when the exporter runs, it will encounter the two RS Proxy Objects when flattening the c4d scene and do what you cannot do, grab the rs scene data from the referenced Scene.rs files and inline that into the new ReferencingScene.rs file. So we end up with 10 cubes in total, each with the red material assigned. ReferencingScene.rs +-- Objects +-- Cube.0 [Red Material] (from RS Proxy Object.0) +-- Cube.1 [Red Material] ... +-- Cube.2 [Red Material] ... +-- Cube.3 [Red Material] ... +-- Cube.4 [Red Material] ... +-- Cube.0 [Red Material] (from RS Proxy Object.1) +-- Cube.1 [Red Material] ... +-- Cube.2 [Red Material] ... +-- Cube.3 [Red Material] ... +-- Cube.4 [Red Material] ... +-- Materials +-- Red Material (contains Red Material definition) And when we load that back into Cinema 4D we get this: SecondGeneration.c4d +-- Objects +-- RS Proxy Object.0 (loads ReferencingScene.rs) +-- Cache +-- Polygon Object (one blob representing all 10 cubes and no material information) The TLDR is that the Redshift Core can read *.rs files and the Cinema API cannot, it can only write them or load them via an RS Proxy Object. And there is no 'resolving [...] the full proxy chain' as you put it. An *.rs scene file is just a discrete scene representation that contains does not know concepts such as generators or assets known to the Cinema API/Core. When export a *.c4d scene that references *.rs files all data is just flattened into a single *.rs file (again, what I showed under the *.rs formats above was just a visualization, not the actual file format). There is currently no way to do what you want to do, even if you would request access to the Redshift Core C++ SDK. Because the RS file format is a GPU scene file format and very deeply integrated into the core. Even the RS Core SDK does not expose functionalities to read RS files to CPU memory structures. Cheers, Ferdinand
  • Creating custom asset nodes via Python API

    2026 python windows
    2
    0 Votes
    2 Posts
    54 Views
    ferdinandF
    Hey @itstanthony, Thank you for reaching out to us and sorry, I am somehow overlooked this topic. It is rather hard for me to reproduce what you did there since I am lacking that asset of yours. I understand that the nodes API in total but also its simplified variant of graph descriptions are not trivial, but I would recommend having a look at Graph Descriptions: Referencing Entities, it is all explained there. You can either reference entities by their human readable name (English only at the moment) or by their ID. When you use an ID reference, you must use the hashtag prefix so that the graph description parser knows that it is meant to be an ID. E.g., #com.maxon.nodes.stuff or #2348twiugrfjwsgrrwo4. You can also use lazy references but I won't get into that here. So, you either must prefix the ID with a hashtag or you can just use the plain name of your node which seems to be "Normal Blender AOV". The danger with names is always, especially for user designed nodes, that there will be a name collision. Graph descriptions work by building a cache of IDs and labels right in a node space right before the description is executed. It does not matter if a node is native or not. The alure of graph descriptions is of course to use human readable identifiers. I would recommend naming custom nodes with a prefix to make name collisions less likely. E.g. instead of naming a node "Normal Blender", one could name it "MXN Normal Blender" where "MXN would stand for Maxon and would have to be customized to your company/name. Cheers, Ferdinand Example I created a Redshift node asset called "DoubleNoise": [image: 1769419202986-c5f80076-9856-4862-a45a-93f7c96d0973-image.png] And then instantiated it like this. You can also access the ports just like for builtin nodes via their human readable name. import math import maxon from maxon import GraphDescription GraphDescription.ApplyDescription( GraphDescription.GetGraph(name="foo"), { GraphDescription.Type: "DoubleNoise", } ) [image: 1769419296980-035fcdc3-9886-448d-8be3-5f762ee3608d-image.png]
  • how to detect obj selected in InExcludeData()?

    2025 python
    7
    0 Votes
    7 Posts
    104 Views
    chuanzhenC
    @ferdinand Thank you. hope this can be updated in the document
  • Finding out the latest asset version number/string via python

    python 2026
    7
    0 Votes
    7 Posts
    119 Views
    M
    Hi Ferdinant, Great! Thank you for your support - I really appreciate it! with... asset: maxon.AssetDescription = repo.FindLatestAsset( maxon.AssetTypes.File(), aid, maxon.Id(), maxon.ASSET_FIND_MODE.LATEST) version_string: str = maxon.AssetInterface.GetVersionString(asset) version_string = version_string[:-19].strip() #deleting the timestamp I could filter out the Version String. Thank you again for your help. Cheers, MPB
  • Getting some weird console output from GeDialog.Timer()

    python 2026
    3
    0 Votes
    3 Posts
    49 Views
    B
    Thank you @Dunhou ! That solved it!
  • Object-level "Show Help" (CMD+F1) for ObjectData plugins?

    macos 2025 2026 python
    2
    0 Votes
    2 Posts
    61 Views
    ferdinandF
    Hey @lasselauch, Thank you for reaching out to us. I am not 100% sure that I am understanding you correctly. You basically want to hook into this menu entry, right? [image: 1768249550647-650df545-8d6c-4444-a525-a4fe70bee750-image.png] That is not possible at the moment. Because what this thing does, is gather information from the description of the selected entity or the active dialog and with that data calls cinema::OpenHelpBrowser (at least the backend version of that function). This is not even a dedicated command, just a switch case within the abstracted dialog menu handling. So, this is custom built for help.maxon.net. It would not be impossible to isolate this so that there could be either a dedicated plugin hook for this or it somehow reusing the existing RegisterPluginHelpDelegate (the C++ variant of the Python hook you used). But that would be quite a bit of work, and you would also have to answer if that justifies the overhead of calling all hooks each time a user presses that button/menu entry (but you could also argue that the overhead of RegisterPluginHelpDelegate is even worse). I can see the allure of "Show Help" working for third parties, but I doubt many people would use it and the current system is very Maxon centric which are not good arguments for going for this. On top of this, in theory, it would have to support both NodeData entities and dialogs (because the menu entry works for both). We could only support nodes, but there I would just recommend the proven and tested workflow of including a base description at the end of your nodes, which places there a bitmap icon branding that is clickable or just a button. I talked a bit in the all new Licensing Manual videos and code about this workflow. edit: An alternative could be to offer a hook into OpenHelpBrowser but there you probably then run into problems with dialogs as the back end function splits into two signatures (which do not exist in the frontend). Also solvable but again extra work that can hardly be justified but the few users this will have. I am not strictly against adding such hook, but I currently do not see a good cost/effect ratio unless this thread is flooded with third party developers stating otherwise. Cheers, Ferdinand
  • How to access animation tracks for a GraphNode in a capsule

    2026 python
    3
    0 Votes
    3 Posts
    101 Views
    K
    Hi @ferdinand , Thank you for your detailed answer. I will look into the details and try to understand the concepts. For now the issue is solved. Thank you as always.
  • CommandData.Message() implementation and Message concepts

    python 2023
    5
    0 Votes
    5 Posts
    943 Views
    K
    @John_Do said in CommandData.Message() implementation and Message concepts: seasoned baselislienhanMO
  • 0 Votes
    3 Posts
    181 Views
    lasselauchL
    Thank you, Ferdinand. (Again!) That was exactly what I needed. It's working great now! Thanks for taking the time to answer this so thoroughly and quickly! Cheers, Lasse
  • How to change the Node spaces

    python 2025 windows
    2
    0 Votes
    2 Posts
    104 Views
    ferdinandF
    Hello @gelobui, Welcome to the Maxon developers forum and its 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 procedures. You did not do anything wrong, we point all new users to these rules. Forum Overview: Provides a broad overview of the fundamental structure and rules of this forum, such as the purpose of the different sub-forums or the fact that we will ban users who engage in hate speech or harassment. Support Procedures: Provides a more in detail overview of how we provide technical support for APIs here. This topic will tell you how to ask good questions and limits of our technical support. Forum Features: Provides an overview of the technical features of this forum, such as Markdown markup or file uploads. It is strongly recommended to read the first two topics carefully, especially the section Support Procedures: How to Ask Questions. About your First Question It depends a bit on how you mean your question. There is GetActiveNodeSpaceId which allows you to get the ID of the current node space. But there is no setting equivalent of that function. So, you cannot set a node space by its ID. What you can do, is call the command which switches node spaces. These are however dynamically assigned and can have a different meaning, depending on how many render engines are installed. You can just check the script log after changing the space. On this installation I have for example no extra render engines or node spaces installed, therefore Redshift is there 72000, 4. [image: 1765458881919-a0da1ed7-7add-456e-a8cc-63d8bd1ced2a-image.png] But on this machine I have the C++ SDK installed and therefore the Example nodes space, so Redshift is now 72000, 5: [image: 1765459007165-49b0838b-49d5-4f14-b638-811d8d26ada4-image.png] When you really want to do this in a fail safe manner, you would have to parse the menu of Cinema 4D to know with which sub-id to call CallCommand. Cheers, Ferdinand
  • Educational Licenses

    python windows 2025
    9
    1
    0 Votes
    9 Posts
    473 Views
    DunhouD
    @ferdinand Thanks for your great examples! Very helpful!
  • How to get edge 'island' selection

    python 2026
    6
    1
    0 Votes
    6 Posts
    264 Views
    ferdinandF
    Hey @BretBays, Let me answer a few things, I although I still have the feeling we are not at the bottom of things yet. So my idea(based off a maya tool used at work) is to be able to select those loops myself with edges, and have it run the interpolation on all the loops at once(well, at once as far as clicking apply once and it does each loop for you). You can of course implement a point, edge, or polygon loop or ring selection yourself. But my advice would be to use the builtin tool programmatically unless you really have to implement your own tool. Because while a simple loop selection is relatively trivial, a production level loop tool is then quite a bit of work, due to all the edge cases you have to handle. The issues I am running into is that it seems like working with edge selections is very cumbersome in Cinema. [...] I don't know I just am having a hard time wrapping my head around these concepts in Cinema. Is it possible to pass in an edge ID and work with edge ID's or do you have to go through the polygon info and all of that to get them? Cinema 4D does not store edges explicitly, as this would unnecessarily increase the size of a scene. One can sufficiently describe polygonal geometry as a set of points for the vertices, and a set of ordered quadruples of point indices for each polygon. This is common practice in 3D applications and called 'indexed face set'. You always have to go through the polygons and points to work with edges. Edges are effectively just a smoke and mirrors convenience feature for end users. One could argue how much front-end wrappers for edges an API requires to be easy to use, but I would say Cinema 4D is there at least okay. You can find helper functions for edges on PolygonObject and SendModelingCommand supports edge selections directly. In short, for each perceived user edge E_p, exist n 'real' or 'raw' edges for the indexed face set, where n is either 1 or 2 when the is mesh manifold (or larger when non-manifold). If n=1, then E_p is a boundary edge, otherwise it is an internal edge shared by two polygons. This is due to these two polygons having two have opposite winding orders for that shared edge when the polygons are meant to face into the same direction. The following diagram illustrates this (arrows indicate the winding order of the polygons): a- → -b b- → -e | | | | ↑ P ↓ ↑ Q ↓ | | | | d- ← -c c- ← -f Fig. 1: Two polygons P and Q sharing the user perceived edge E_p defined by the points b and c. The lower case labels denote unique point identifiers in the indexed face set, not a point order within the polygon. The polygon P is defined as (a, b, c, d) and the polygon Q as (b, e, f, c), i.e., a and b are the first vertex of each polygon respectively. The arrows describe the winding order of the polygons. The global raw edge index is defined as rawEdgeIndex = polygonIndex * 4 + localEdgeIndex. E.g., when P would have the polygon index 2 and Q the polygon index 6, then the user perceived edge E_p would correspond to the two raw edges indices p_bc = 2 * 4 + 1 = 8 (edge bc in P which is the second edge, i.e. local index 1) and q_cb = 6 * 4 + 3 = 27 (edge cb in Q which is the fourth edge, i.e. local index 3). Here are some code examples and forum posts about working with edges in Cinema 4D's Python API: geometry_polgyon_edges_2024: This is the official example script showing how to work with polygon edges in Cinema 4D 2024. It explains how to access and identify edges in a polygon object. Select Edges by Length: An example that shows how to select edges based on their length. Select Polygons Facing into the Same Direction: Not directly related to edges, but I talk here about the fundamental concept of a winding order, which is important when working with polygon edges. Cheers, Ferdinand
  • KeyFrame User Data from Xpresso driven User Data

    python
    3
    2
    0 Votes
    3 Posts
    128 Views
    ferdinandF
    Hey @JoelJohera, it is kind of hard to follow your question and solution, as the former lacks a scene for context and for the latter I am not quite sure what you fixed. But when it works for you I am happy Cheers, Ferdinand
  • BaseLink across documents

    c++
    4
    0 Votes
    4 Posts
    198 Views
    ferdinandF
    Hey @WickedP, As I hinted at above, markers are eternally persistent. I.e., you can unload, load, and modify a scene S or the non-cache* node N in it, the node N will always have the same marker. The flag you found has a very special purpose and also very misleading documentation (I just fixed that). Each node in a scene must have a unique marker, as otherwise not only BaseLink but also things like undo and more won't work properly when not each node has exactly one marker and each marker exactly one node (i.e., a bijective or 'one-to-one' relation). But there can be bad actors such as bugs in our codebase or third party plugins which violate that rule. To combat that, Cinema 4D checks the uniqueness of markers of nodes when a scene is being loaded. When it finds duplicate markers, it will open a question dialog, asking the user if he/she wants to repair that scene. When the user says 'yes', only the nodes which had duplicate markers will get a new marker each (so that they are in a bijective marker relation again). This flag you found will suppress this whole behavior, i.e., it will let you load corrupted scenes as is. I would not recommend using it. I am currently not 100% sure what happens when your LoadDocument call is not DIALOGSALLOWED, it looks a bit like that this check then always never runs (which sounds a bit dangerous). Cheers, Ferdinand edit: okay now I see it, the question dialog part has been commented out, so this runs always without asking the user (and with that also without DIALOGSALLOWED), unless you pass the flag NONEWMARKERS. [*] Object and other nodes in caches, i.e., the partial scene graph returned by BaseObject::GetCache and generated by ObjectData::GetVirtualObjects, are allocated each time the cache is being built and therefore also have a new marker each time. But you cannot (or better should not) try to build base links, undos, xrefs, etc. for object and other nodes in caches. TLDR: Markers do not work for caches.
  • Dynamically Add Massign to Material in Material Editor

    c++
    2
    0 Votes
    2 Posts
    105 Views
    ferdinandF
    Hey @ECHekman, I currently use INCLUDE Massign in my .res file. However i would like to do this dynamically so that I can change the order at which it is placed in the Material Editor and Attribute Editor. Is there a way to do this? There is no INCLUDE which you could call programmatically in GetDDescription, but there is Description::LoadDescription. When Cinema 4D is asking you to update a certain part of your description, you could try to call it on your description instance but not with its id, but Massign. This is however very likely to fail or cause crashes, because your description is already being processed, I never tried this myself though. Another approach could be to allocate a dummy description, then load your resource (e.g., Massign) into that dummy description, to then copy parameters bit by bit into your active/actual description passed into GetDDescription. But the whole approach of a 'dynamic include' is a bit backwards without context why it has to be this way. Because when you dynamically include something, this also means you have to remove existing data where it shall not be included anymore. Which is possible but unnecessary extra work. Also copying a whole partial description is not a great idea performance wise, GetDDescription is being called a lot. The better approach would be to just include your partial description in your res file in the a place where it might appear and then dynamically change the parent of that container. As this workflow would be the common dynamic description workflow. Additionally Also is there a way to hide settings from the Obaselist group or hide settings in the Material Editor but keep them in the Attribute editor? No, both managers are more or less just a DescriptionCustomGui, they will always show the same data, unless you have access to the implementation (which you do not). When you would implement your own material dialog, with your own DescriptionCustomGui in it, you could mangle what is shown in this particular description view to your liking, there are multiple methods to highlight, filter, and modify a description on that class. To operate this dialog you would then set this description GUI to the material, shader or whatever BaseList2D you want to display, and then either filter or outright modify the description which is being displayed. Cheers, Ferdinand
  • Adjust spline layers settings in Field Force Objects with Python?

    r25 python
    2
    0 Votes
    2 Posts
    155 Views
    ferdinandF
    Hey @Simon-Lucas, Welcome to the Maxon developers forum and its 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 procedures. You did not do anything wrong, we point all new users to these rules. Forum Overview: Provides a broad overview of the fundamental structure and rules of this forum, such as the purpose of the different sub-forums or the fact that we will ban users who engage in hate speech or harassment. Support Procedures: Provides a more in detail overview of how we provide technical support for APIs here. This topic will tell you how to ask good questions and limits of our technical support. Forum Features: Provides an overview of the technical features of this forum, such as Markdown markup or file uploads. It is strongly recommended to read the first two topics carefully, especially the section Support Procedures: How to Ask Questions. About your First Question Do you really mean you are on R25? Or do you mean you are on 2025? Anyway, please share an example scene and the code you have so far. Otherwise we won't be able to help you. Cheers, Ferdinand
  • VertexMap Display (Behavior Equivalent to Double-Click)

    2026 python windows
    3
    0 Votes
    3 Posts
    135 Views
    ymoonY
    @ferdinand Thank you. It works well. --> tag.Message(c4d.MSG_EDIT)
  • 0 Votes
    5 Posts
    273 Views
    chuanzhenC
    @ferdinand Thanks for reply Other channels(BOX,X-Ray....) also seem to be unfeasible, and currently it seems only can accept this limitation (affected by depth of field) Due to the current not to transfer to C++, some plugin ideas are indeed somewhat unusual only using some simple C4D drawings to generate Bitmaps, so I did not pay attention to the handling of Ocio. I will carefully read the manual on this aspect in the document.
  • How do I return a list of names and ids for a drop down menu?

    windows python 2025
    3
    0 Votes
    3 Posts
    147 Views
    ferdinandF
    Hey @lionlion44, yes, that is the correct answer. The subject comes up from time to time, here is an answer of mine which is about the very case of yours - discovering substance channels. Cheers, Ferdinand
  • How to get the fully resolved file path of an upcoming rendering?

    2
    0 Votes
    2 Posts
    141 Views
    ferdinandF
    Hey @BigRoy, Thank you for reaching out to us and your question. We do not allow for topics that are a collection of questions from one user. New questions mandate new topics, unless they are clear follow up questions on an existing topic. The reason for this is so that this forum remains a searchable database. Please create new topics on your own in the future. I have forked your topic. Your topic is also lacking an actual question. Here I can infer your question, but for more complex subjects I might not be able to. It is important to have a literal question close to the start of your topic. See Support Procedures: How to Ask Questions and the examples below for what makes a good technical question. From the context I am assuming here the question is: Is there an API function that returns the full physical file path of a rendered file for a given render setting and in particular the Save > Name format? [image: 1762787643631-34d82dba-bf2f-411a-8489-a8dccc5d9f77-image.png] The answer is unfortunately that no such function exists. When you need this feature, you have to hard code it yourself. Cheers, Ferdinand