• 0 Votes
    4 Posts
    176 Views
    ferdinandF
    Hello @ECHekman, Thanks for providing the information that the init function should not modify the scene graph. Ill take this into account in the future. It is not only NodeData::Init but the majority of NodeData methods and the methods of derived classes that cannot modify the scene graph of a loaded document, as for example the scene graph they are attached to. The reason is that such methods, as for example NodeData::Init, TagData:Execute, ObjectData::GetVirtualObjects, and many more, run in their own threads to parallelize scene execution. Modifying the scene graph of a loaded document from a non-main-thread (i.e., parallel) context can lead to race conditions and access violations and are therefore strictly forbidden. Forbidden are primarily allocations and deallocations, parameter get/set access is allowed (as long as it does not allocate or deallocate a pointed object) but also discouraged outside of TagData::Execute. For details, see Cinema 4D Threads Manual. I went through that example you linked, but I' m a bit unclear why it is necessary to manually create the handling of a custom and parallel nodegraph branch when plugin GeListNodes are already graphs themselves? I am not quite sure how you mean 'parallel', but a GeListNode implements both hierarchal (i.e., tree) relations with InsertUnder, GetUp, GetDown, GetNext etc. and arbitrary (i.e., graph) relations with GetBranchInfo. The hierarchy of a node type, e.g., Obase - a BaseObject or Tmytag - your tag class, are always meant to be of the same type and follow the conventions of their base class. Tags are not meant to have children. You must implement your own branch to declare your own non-hierarchical relation between your plugin tag and your basic node. The workaround Maxime suggested, just implementing NodeData::CopyTo is unfortunately not valid. First of all, you must always implement all three serialization functions Read, Write, and CopyTo, you can never only implement only one of them. But storing nodes irregularly in this manner can lead to access violations as Cinema 4D is then not aware that this quasi-branch exists and might try to execute multiple things at once (via NodeData::GetAccessedObjects), leading to read/write access violations. Moreover, I am fairly sure that this might lead to event or call starvation when Cinema finds there such a dangling BaseList2D (NodeData) instance under your BaseTag (TagData). Or even worse, it will ignore completely it in some contexts, because tags are not supposed to have children. You must implement a branch in your case, I would recommend following the SDK example as it is slightly cleaner than the forum preview Maxime linked to. Cheers, Ferdinand
  • 0 Votes
    2 Posts
    142 Views
    ferdinandF
    Hey @Pheolix, 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 Your code looks generally good, especially for someone who is starting out with the API you did really well. With that being said, I do not really understand what you want to do: ... plugin that maps and arranges textures onto a pixel grid. The goal is to make it easier to create voxel-style or Minecraft-like models by linking real-world units (e.g., centimeters) to pixels. (for example, 1 pixel = 6.25 cm) A few pointers: A CommandData plugin is the perfect choice when you want to manipulate the scene without any restrictions and are fine with always having to press a button run your logic. Scene element plugins, e.g., objects, tags, etc. on the other hand will carry out their logic on their own when a scene update is invoked. But they come with the restriction that their major payload functions (ObjectData::Execucte, ObjectData::GetVirtualObjects, TagData::Execute, etc.) run in their own threads (so that scene execution is parallelized) and therefore are subject to threading restrictions (I am aware that you are on C++, but the Python docs are better on this subject). So, for example, in a TagData::Execute you would not be allowed to allocate a new UVW tag on the object that is also hosting your plugin tag. But you could implement a button in the description of the tag, which when clicked cerates your setup (because TagData::Message runs on the main thread and you therefore are there allowed to add and remove scene data). With TagData:Execute you could then continuously update the UVW tag you are targeting on each scene update (changing parameter values of other scene elements is fine when tags are executed). This workflow is not necessarily better than a command, I am just showing you an option. Commands are also easier to implement for beginners than a scene element. When you talk about units, you should be aware that both the object and texture coordinate system are unitless. What you see in edit fields, is just smoke and mirrors. We recently talked here about this subject. You did get the major gist of our error handling but what you do with maxon::Failed is not quite correct. It is meant to test the return value of a Result<T> for having returned an error instance instead of T. When you want to indicate an error, you must return an error, e.g.,: // Not correct. if (!doc || !selectedObject || !bitmap || !foundTag) return maxon::FAILED;T // This is how one indicates that a function failed because something was a nullptr. if (!doc || !selectedObject || !bitmap || !foundTag) return maxon::NullptrError(MAXON_SOURCE_LOCATION, "Could not get hold of scene data."_s); // For a function which is of type Result<void>, its also totally fine to do this on an error. void functions // can fail successfully, it is up to you to decide if an error is critical enough to halt execution of if you just // want it to silently terminate. if (!doc || !selectedObject || !bitmap || !foundTag) return maxon::OK; // we are okay with failing here. For details see Error handling and Error Types Cheers, Ferdinand
  • 0 Votes
    3 Posts
    168 Views
    gheyretG
    Thank you for the C++ code—it's been very helpful! Cheers!
  • 0 Votes
    4 Posts
    227 Views
    M
    I'm not sure I understand you correctly, you do not have to use QuickTabRadio bar with resource, you just retrieve the int value of the parameter, in the case of the previous example I share with a GetInt32(c4d.MGCLONER_VOLUMEINSTANCES_MODE). If you can provide a code example of what is blocking you that would be nice. You can find a non-exhaustive list of type of control available in *res file within the C++ documentation in Description Resource. Cheers, Maxime.
  • 0 Votes
    3 Posts
    189 Views
    Viktor VelickoV
    Thank you, Maxim. No further testing is needed—this works very well. I’m calling it from the ToolData::MouseInput() callback at the end, which is sufficient. The panel updates nicely after the mouse event finishes (on mouse up). SendCoreMessage(COREMSG_CINEMA, BaseContainer(COREMSG_CINEMA_FORCE_AM_UPDATE)); GeUpdateUI(); You can close this thread. Thanks! V.
  • Set VERTEXCOLOR in PaintTool

    python r25 windows
    3
    0 Votes
    3 Posts
    134 Views
    R
    @m_adam Thank you so much for the help, that works perfectly and thank you for showing me both methods, that's very helpful and appreciated!
  • Hide RenderPost settings

    c++
    6
    2
    0 Votes
    6 Posts
    431 Views
    N
    Thank you both!
  • 0 Votes
    2 Posts
    171 Views
    M
    Hey you need to react to MSG_GETCUSTOM_NAME_ADDITION and return a dict with the expected string with the "res" key. You need to register your object with c4d.OBJECT_CUSTOM_NAME_ADDITION to have the additional name displayed in the Object Manager. Cheers, Maxime.
  • DescID and DescLevel for Shader Layers and properties

    2025 python windows
    11
    1
    0 Votes
    11 Posts
    549 Views
    A
    @ferdinand Thank you for your in-depth analysis. It would have taken me way too long to figure this out lol, especially finding "CUSTOMDATA_BLEND_LIST". The first example seems to work for me, but like you said, it may not be reliable. The Python node example also works great. Again, thank you for your time.
  • exporting usd with python

    2025 python windows
    2
    0 Votes
    2 Posts
    209 Views
    ferdinandF
    Hey @lionlion44, Thank you for reaching out to us. I doubt that this will not work in Python, it is just that we have not documented the symbols there yet. But you can find them in the C++ docs: [image: 1757607809636-6e23eada-2198-4c34-84bf-a576bbdd0ef9-image.png] I.e., it will be c4d.FORMAT_USDIMPORT and c4d.FORMAT_USDEXPORT. Cheers, Ferdinand
  • GetRad() / GetMp() update issue

    windows python 2025
    2
    0 Votes
    2 Posts
    201 Views
    ferdinandF
    Hey @datamilch, Thank you for reaching out to us. GetRad and GetMp express the locally aligned bounding box of an object. I.e., the bounding box in the coordinate system of the object. For a world space aligned bounding box we once had this thread, the Cinema API does not offer this out of the box. So, transforming an object will never change its bounding box. What will change the bounding box of an object, is changing its size or changing the parameters of a generator object. When you change the parameters of a generator or when your instantiate a new object, you will have to execute the passes (BaseDocument.ExecutePasses) on a document that contains the object to see the correct bounding box - or wait for the next scene update. PS: Your script is also running illegal code. You cannot modify the active document off-main-thread. I assume the is a script for a Python generator object. Its main function runs off-main-thread and you call there your csto which in turn calls SendModelingCommand on the active document. This will all sooner or later crash. https://developers.maxon.net/docs/py/2025_3_1/manuals/manual_threading.html#threading-information Cheers, Ferdinand
  • Can I get keyboard input mode?

    windows python c++ 2025
    4
    1
    0 Votes
    4 Posts
    284 Views
    ferdinandF
    Hey @Dunhou, I have edited your posting. It is fine to mention the beta forum, but we would rather not see its name written here. When you are talking about 'C++', I assume you are talking here about the Windows SDK/API, as for example GetGUIThreadInfo. I would doubt that you get very far with that here. Cinema 4D is very OS agnostic and we have our whole GUI decoupled from the OS. The little rename window in our tree view control is not an OS rename dialog. I am not even sure if this is something with an HWND handle which you could address so that you could intercept keyboard events to it, or if this is just a virtual window within our API. For this IMM thing to work, we would have to use the IME API in Cinema 4D, so that our text edit gadgets support it. I also do not quite understand what you are trying to do. The missing piece is here probably that our text edit gadget does not send its current content to the IME API (at a glance, via ImmSetCompositionStringW as shown here). And as a third party, you cannot really fix that. Because you (a) do not own the implementation and you (b) are not informed about an edit event, so you cannot just write a plugin which sends the object name to the IME API. Cheers, Ferdinand
  • Finding, Renaming, and Updating all References to Assets

    python 2025
    3
    3
    0 Votes
    3 Posts
    316 Views
    d_keithD
    Thanks for the response! I appreciate the ASSETDATA_FLAG_MULTIPLEUSE tip. My hope was that there was some sort of existing RenameAsset SDK method that would also update all references to that asset without implementing custom handling for various element types (Redshift Nodal Material, Cinema 4D Classic Material, Arnold Dome Light, XRef, etc). Evidently such a public python SDK method doesn't exist. My example code was texture specific as that's the part of the problem that's most pressing to me and I was able to implement with custom per-type handling - if I manage to get other types working, I'll attempt to update over time.
  • 0 Votes
    4 Posts
    195 Views
    ferdinandF
    Hey, thanks for the extended code, but I still cannot run this, as it is only a fragment So, I only have a very rough understanding of what is going wrong. A likely issue apart from you just having a bug in your hit logic, is that you use the wrong coordinate system. if msg[c4d.BFM_INPUT_DEVICE] == c4d.BFM_INPUT_MOUSE \ and msg[c4d.BFM_INPUT_CHANNEL] == c4d.BFM_INPUT_MOUSELEFT \ and msg[c4d.BFM_INPUT_VALUE]: local_x = msg[c4d.BFM_INPUT_X] local_y = msg[c4d.BFM_INPUT_Y] scroll_y = self.dialog.get_scroll_offset() I would have to check myself, but there is some inconsistency with which dialogs send mouse input messages regarding the used coordinate system. Sometimes they send messages in the coordinate system of the dialog and sometimes messages in the coordinate system of the gadget. Just print out your (local_x and local_y) and check if the values make sense as local coordinates as you seem to treat them. On GeUserArea are multiple coordinate conversion methods. I think BFM_INPUT in this context is in local user area coordinates but I am not sure, it could also be that you have to convert them. The other thing is of course that you add this self.dialog.get_scroll_offset() on top of things. I assume this is sourced by something like GeDialog.GetVisibleArea? There you could also unintentionally mix coordinate systems. Cheers, Ferdinand
  • 0 Votes
    2 Posts
    231 Views
    ferdinandF
    Hello @writing-qi, 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 Please familiarize yourself with our support guidelines, your first question is composed out of multiple explicit and implicit questions and also lacks executable code, which makes it rather hard to answer. GetDescription() returns parameters but all show "Access Failed" There is no such error in our API. I assume you mean an error like this instead: AttributeError: Parameter value not accessible (object unknown in Python). The Cinema 4D API is primarily a C++ API and therefore exist data types that simply have not been ported to Python. For example, many objects have the parameters ID_BASELIST_ICON_PRESET_BUTTONS and ID_BASELIST_NODESPACE_ADD_REMOVE_BUTTONS (which are usually hidden) and when you try to access them, it will raise an error, because the respective data types simply have not been wrapped, so the Python API has no idea what to do with the data held by these parameters. In Redshift, which started out as a third party plugin and is still an optional feature of Cinema 4D, many data types have never been ported to Python which makes them simply inaccessible. But Redshift usually decomposes their data via channel decomposition. I.e., the parameter for a "Texture" (CUSTOMDATATYPE_RSFILE) itself is not exposed, but its sub channels such as the path, tiling, etc. are. This has been discussed quite a few times before on the forum, for example here. What is the correct API to enumerate all parameters in RS Shader Graph? Well, descriptions are the tool for that, but descriptions also contain things where you cannot get/set a parameter, either because the data type is not exposed to Python or simply because there is nothing to get and set. The next SDK release will also contain a function called mxutils.GetParameterTreeString which allows you to visualize the sensible parameters of a scene element. But neither it nor c4d.Description.__iter__ will automatically unfold sub-channels. E.g., when you come along a node which has a parameter of type DYTPE_VECTOR at ID_MY_VECTOR_PRAM, the description will yield you a parameter at ID_MY_VECTOR_PRAM but not its sub-channels (ID_MY_VECTOR_PRAM, VECTOR_X), (ID_MY_VECTOR_PRAM, VECTOR_Y), and (ID_MY_VECTOR_PRAM, VECTOR_Z). The same goes for Redshift datatypes, when you come across a parameter of type CUSTOMDATATYPE_RSFILE, e.g., for the 'Image > File' (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0) parameter of an RS Texture node. The description will list the parameter for REDSHIFT_SHADER_TEXTURESAMPLER_TEX0 for that node but not its nested parameters, such as [c4d.REDSHIFT_SHADER_TEXTURESAMPLER_TEX0,c4d.REDSHIFT_FILE_PATH], [..,c4d.REDSHIFT_FILE_LAYER], [...,c4d.REDSHIFT_FILE_COLORSPACE], etc. will not be listed. I am afraid there is no abstracted way to solve this in Python. You would need access to the datatype registries which you do not have in Python. And even in the public C++ API, I currently do not see a way to do this. You need access to our internal API to be able to query a data type for the sub-channels it does register. But you could of course just hardcode the cases, I have given a small example below for CUSTOMDATATYPE_RSFILE, it is not that much work for one data type. But Redshift did use a lot of custom data types in its old Xpresso system, so wrapping them all could be a bit of work (but should still be doable). Cheers, Ferdinand Output For this graph: [image: 1755687318630-72414249-863b-4c13-8acd-5247941e64b3-image.png] RS Xpresso Material: <c4d.BaseMaterial object called RS C4D Shader/RS Shader Graph with ID 1036224 at 1819322820416> Found Xpresso node: <c4d.modules.graphview.GvNode object called Shader Graph/XGroup with ID 1001102 at 1818547015360> Parameter 'Icon File / ID'(c4d.ID_BASELIST_ICON_FILE) = Parameter 'Icon Color'(c4d.None) = 0 Parameter 'Color'(c4d.ID_BASELIST_ICON_COLOR) = Vector(0, 0, 0) Parameter ''(c4d.ID_BASELIST_ICON_PRESET_BUTTONS) = Inaccessible in Python Parameter 'Name'(c4d.ID_BASELIST_NAME) = Shader Graph Parameter 'Layer'(c4d.ID_LAYER_LINK) = None Parameter ''(c4d.ID_BASELIST_NODESPACE_ADD_REMOVE_BUTTONS) = Inaccessible in Python Parameter 'Enabled'(c4d.ID_GVBASE_ENABLE) = 1 Parameter 'Title Color'(c4d.ID_GVBASE_COLOR) = Vector(0.38, 0.384, 0.392) Parameter 'Remark'(c4d.ID_GVBASE_REMARK) = Parameter 'Inputs First'(c4d.GV_GROUP_INPUTS_FIRST) = 0 Parameter 'Active'(c4d.GV_GROUP_ACTIVE) = 0 Found Xpresso node: <c4d.modules.graphview.GvNode object called Output/Output with ID 1001101 at 1819032444352> Parameter 'Icon File / ID'(c4d.ID_BASELIST_ICON_FILE) = Parameter 'Icon Color'(c4d.None) = 0 Parameter 'Color'(c4d.ID_BASELIST_ICON_COLOR) = Vector(0, 0, 0) Parameter ''(c4d.ID_BASELIST_ICON_PRESET_BUTTONS) = Inaccessible in Python Parameter 'Name'(c4d.ID_BASELIST_NAME) = Output Parameter 'Layer'(c4d.ID_LAYER_LINK) = None Parameter ''(c4d.ID_BASELIST_NODESPACE_ADD_REMOVE_BUTTONS) = Inaccessible in Python Parameter 'Enabled'(c4d.ID_GVBASE_ENABLE) = 1 Parameter 'Title Color'(c4d.ID_GVBASE_COLOR) = Vector(0.286, 0.329, 0.463) Parameter 'Remark'(c4d.ID_GVBASE_REMARK) = Parameter 'Material ID'(c4d.GV_REDSHIFT_OUTPUT_MATERIAL_ID) = 0 Found Xpresso node: <c4d.modules.graphview.GvNode object called RS Material/RS Shader with ID 1001101 at 1819032542400> Parameter 'Icon File / ID'(c4d.ID_BASELIST_ICON_FILE) = Parameter 'Icon Color'(c4d.None) = 0 Parameter 'Color'(c4d.ID_BASELIST_ICON_COLOR) = Vector(0, 0, 0) Parameter ''(c4d.ID_BASELIST_ICON_PRESET_BUTTONS) = Inaccessible in Python Parameter 'Name'(c4d.ID_BASELIST_NAME) = RS Material Parameter 'Layer'(c4d.ID_LAYER_LINK) = None Parameter ''(c4d.ID_BASELIST_NODESPACE_ADD_REMOVE_BUTTONS) = Inaccessible in Python Parameter 'Enabled'(c4d.ID_GVBASE_ENABLE) = 1 Parameter 'Title Color'(c4d.ID_GVBASE_COLOR) = Vector(0.529, 0.345, 0.333) Parameter 'Remark'(c4d.ID_GVBASE_REMARK) = Parameter 'Version'(c4d.GV_REDSHIFT_SHADER_META_VERSION) = 17 Parameter 'Shader Class'(c4d.GV_REDSHIFT_SHADER_META_CLASSNAME) = Material Parameter 'preset'(c4d.REDSHIFT_SHADER_MATERIAL_PRESET) = 65536 Parameter 'diffuse_color'(c4d.REDSHIFT_SHADER_MATERIAL_DIFFUSE_COLOR) = Vector(0.5, 0.5, 0.5) Parameter 'diffuse_weight'(c4d.REDSHIFT_SHADER_MATERIAL_DIFFUSE_WEIGHT) = 1.0 Parameter 'diffuse_roughness'(c4d.REDSHIFT_SHADER_MATERIAL_DIFFUSE_ROUGHNESS) = 0.0 Parameter 'transl_color'(c4d.REDSHIFT_SHADER_MATERIAL_TRANSL_COLOR) = Vector(0.5, 0.5, 0.5) Parameter 'transl_weight'(c4d.REDSHIFT_SHADER_MATERIAL_TRANSL_WEIGHT) = 0.0 Parameter 'refl_color'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_COLOR) = Vector(1, 1, 1) Parameter 'refl_weight'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_WEIGHT) = 1.0 Parameter 'refl_roughness'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_ROUGHNESS) = 0.0 Parameter 'refl_samples'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_SAMPLES) = 16 Parameter 'refl_brdf'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_BRDF) = 0 Parameter 'refl_aniso'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_ANISO) = 0.0 Parameter 'refl_aniso_rotation'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_ANISO_ROTATION) = 0.0 Parameter 'refl_fresnel_mode'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_FRESNEL_MODE) = 3 Parameter 'refl_reflectivity'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_REFLECTIVITY) = Vector(0.04, 0.04, 0.04) Parameter 'refl_edge_tint'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_EDGE_TINT) = Vector(0, 0, 0) Parameter 'refl_ior3'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_IOR3) = Vector(1.5, 1.5, 1.5) Parameter 'refl_k3'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_K3) = Vector(0, 0, 0) Parameter 'refl_metalness'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_METALNESS) = 0.0 Parameter 'refl_ior'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_IOR) = 1.5 Parameter 'sheen_color'(c4d.REDSHIFT_SHADER_MATERIAL_SHEEN_COLOR) = Vector(1, 1, 1) Parameter 'sheen_weight'(c4d.REDSHIFT_SHADER_MATERIAL_SHEEN_WEIGHT) = 0.0 Parameter 'sheen_roughness'(c4d.REDSHIFT_SHADER_MATERIAL_SHEEN_ROUGHNESS) = 0.30000001192092896 Parameter 'sheen_samples'(c4d.REDSHIFT_SHADER_MATERIAL_SHEEN_SAMPLES) = 64 Parameter 'refr_color'(c4d.REDSHIFT_SHADER_MATERIAL_REFR_COLOR) = Vector(1, 1, 1) Parameter 'refr_weight'(c4d.REDSHIFT_SHADER_MATERIAL_REFR_WEIGHT) = 0.0 Parameter 'refr_roughness'(c4d.REDSHIFT_SHADER_MATERIAL_REFR_ROUGHNESS) = 0.0 Parameter 'refr_samples'(c4d.REDSHIFT_SHADER_MATERIAL_REFR_SAMPLES) = 8 Parameter 'refr_ior'(c4d.REDSHIFT_SHADER_MATERIAL_REFR_IOR) = 1.5 Parameter 'refr_use_base_IOR'(c4d.REDSHIFT_SHADER_MATERIAL_REFR_USE_BASE_IOR) = 1 Parameter 'refr_abbe'(c4d.REDSHIFT_SHADER_MATERIAL_REFR_ABBE) = 0.0 Parameter 'refr_thin_walled'(c4d.REDSHIFT_SHADER_MATERIAL_REFR_THIN_WALLED) = 0 Parameter 'ss_unitsMode'(c4d.REDSHIFT_SHADER_MATERIAL_SS_UNITSMODE) = 0 Parameter 'refr_transmittance'(c4d.REDSHIFT_SHADER_MATERIAL_REFR_TRANSMITTANCE) = Vector(1, 1, 1) Parameter 'refr_absorption_scale'(c4d.REDSHIFT_SHADER_MATERIAL_REFR_ABSORPTION_SCALE) = 0.009999999776482582 Parameter 'ss_extinction_coeff'(c4d.REDSHIFT_SHADER_MATERIAL_SS_EXTINCTION_COEFF) = Vector(0, 0, 0) Parameter 'ss_extinction_scale'(c4d.REDSHIFT_SHADER_MATERIAL_SS_EXTINCTION_SCALE) = 0.009999999776482582 Parameter 'ss_scatter_coeff'(c4d.REDSHIFT_SHADER_MATERIAL_SS_SCATTER_COEFF) = Vector(1, 1, 1) Parameter 'ss_amount'(c4d.REDSHIFT_SHADER_MATERIAL_SS_AMOUNT) = 0.0 Parameter 'ss_phase'(c4d.REDSHIFT_SHADER_MATERIAL_SS_PHASE) = 0.0 Parameter 'ss_samples'(c4d.REDSHIFT_SHADER_MATERIAL_SS_SAMPLES) = 16 Parameter 'ms_amount'(c4d.REDSHIFT_SHADER_MATERIAL_MS_AMOUNT) = 0.0 Parameter 'ms_radius_scale'(c4d.REDSHIFT_SHADER_MATERIAL_MS_RADIUS_SCALE) = 100.0 Parameter 'ms_mode'(c4d.REDSHIFT_SHADER_MATERIAL_MS_MODE) = 1 Parameter 'ms_samples'(c4d.REDSHIFT_SHADER_MATERIAL_MS_SAMPLES) = 64 Parameter 'ms_include_mode'(c4d.REDSHIFT_SHADER_MATERIAL_MS_INCLUDE_MODE) = 1 Parameter 'ms_color0'(c4d.REDSHIFT_SHADER_MATERIAL_MS_COLOR0) = Vector(1, 0.9, 0.7) Parameter 'ms_weight0'(c4d.REDSHIFT_SHADER_MATERIAL_MS_WEIGHT0) = 1.0 Parameter 'ms_radius0'(c4d.REDSHIFT_SHADER_MATERIAL_MS_RADIUS0) = 1.0 Parameter 'ms_color1'(c4d.REDSHIFT_SHADER_MATERIAL_MS_COLOR1) = Vector(1, 0.9, 0.7) Parameter 'ms_weight1'(c4d.REDSHIFT_SHADER_MATERIAL_MS_WEIGHT1) = 0.0 Parameter 'ms_radius1'(c4d.REDSHIFT_SHADER_MATERIAL_MS_RADIUS1) = 1.0 Parameter 'ms_color2'(c4d.REDSHIFT_SHADER_MATERIAL_MS_COLOR2) = Vector(1, 0.9, 0.7) Parameter 'ms_weight2'(c4d.REDSHIFT_SHADER_MATERIAL_MS_WEIGHT2) = 0.0 Parameter 'ms_radius2'(c4d.REDSHIFT_SHADER_MATERIAL_MS_RADIUS2) = 1.0 Parameter 'coat_color'(c4d.REDSHIFT_SHADER_MATERIAL_COAT_COLOR) = Vector(1, 1, 1) Parameter 'coat_weight'(c4d.REDSHIFT_SHADER_MATERIAL_COAT_WEIGHT) = 0.0 Parameter 'coat_roughness'(c4d.REDSHIFT_SHADER_MATERIAL_COAT_ROUGHNESS) = 0.0 Parameter 'coat_samples'(c4d.REDSHIFT_SHADER_MATERIAL_COAT_SAMPLES) = 16 Parameter 'coat_brdf'(c4d.REDSHIFT_SHADER_MATERIAL_COAT_BRDF) = 0 Parameter 'coat_fresnel_mode'(c4d.REDSHIFT_SHADER_MATERIAL_COAT_FRESNEL_MODE) = 3 Parameter 'coat_reflectivity'(c4d.REDSHIFT_SHADER_MATERIAL_COAT_REFLECTIVITY) = Vector(0.027, 0.027, 0.027) Parameter 'coat_ior3'(c4d.REDSHIFT_SHADER_MATERIAL_COAT_IOR3) = Vector(1.4, 1.4, 1.4) Parameter 'coat_ior'(c4d.REDSHIFT_SHADER_MATERIAL_COAT_IOR) = 1.399999976158142 Parameter 'coat_transmittance'(c4d.REDSHIFT_SHADER_MATERIAL_COAT_TRANSMITTANCE) = Vector(1, 1, 1) Parameter 'coat_thickness'(c4d.REDSHIFT_SHADER_MATERIAL_COAT_THICKNESS) = 0.10000000149011612 Parameter 'coat_bump_input'(c4d.REDSHIFT_SHADER_MATERIAL_COAT_BUMP_INPUT) = Vector(0, 0, 0) Parameter 'overall_color'(c4d.REDSHIFT_SHADER_MATERIAL_OVERALL_COLOR) = Vector(1, 1, 1) Parameter 'opacity_color'(c4d.REDSHIFT_SHADER_MATERIAL_OPACITY_COLOR) = Vector(1, 1, 1) Parameter 'emission_color'(c4d.REDSHIFT_SHADER_MATERIAL_EMISSION_COLOR) = Vector(0, 0, 0) Parameter 'emission_weight'(c4d.REDSHIFT_SHADER_MATERIAL_EMISSION_WEIGHT) = 0.0 Parameter 'bump_input'(c4d.REDSHIFT_SHADER_MATERIAL_BUMP_INPUT) = Vector(0, 0, 0) Parameter 'depth_override'(c4d.REDSHIFT_SHADER_MATERIAL_DEPTH_OVERRIDE) = 0 Parameter 'refl_depth'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_DEPTH) = 3 Parameter 'refl_enablecutoff'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_ENABLECUTOFF) = 0 Parameter 'refl_cutoff'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_CUTOFF) = 0.009999999776482582 Parameter 'skip_inside_refl'(c4d.REDSHIFT_SHADER_MATERIAL_SKIP_INSIDE_REFL) = 1 Parameter 'refr_depth'(c4d.REDSHIFT_SHADER_MATERIAL_REFR_DEPTH) = 5 Parameter 'refr_enablecutoff'(c4d.REDSHIFT_SHADER_MATERIAL_REFR_ENABLECUTOFF) = 0 Parameter 'refr_cutoff'(c4d.REDSHIFT_SHADER_MATERIAL_REFR_CUTOFF) = 0.009999999776482582 Parameter 'combined_depth'(c4d.REDSHIFT_SHADER_MATERIAL_COMBINED_DEPTH) = 6 Parameter 'diffuse_direct'(c4d.REDSHIFT_SHADER_MATERIAL_DIFFUSE_DIRECT) = 1.0 Parameter 'diffuse_indirect'(c4d.REDSHIFT_SHADER_MATERIAL_DIFFUSE_INDIRECT) = 1.0 Parameter 'refl_direct'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_DIRECT) = 1.0 Parameter 'refl_indirect'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_INDIRECT) = 1.0 Parameter 'refl_isGlossiness'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_ISGLOSSINESS) = 0 Parameter 'coat_direct'(c4d.REDSHIFT_SHADER_MATERIAL_COAT_DIRECT) = 1.0 Parameter 'coat_indirect'(c4d.REDSHIFT_SHADER_MATERIAL_COAT_INDIRECT) = 1.0 Parameter 'coat_isGlossiness'(c4d.REDSHIFT_SHADER_MATERIAL_COAT_ISGLOSSINESS) = 0 Parameter 'sheen_direct'(c4d.REDSHIFT_SHADER_MATERIAL_SHEEN_DIRECT) = 1.0 Parameter 'sheen_indirect'(c4d.REDSHIFT_SHADER_MATERIAL_SHEEN_INDIRECT) = 1.0 Parameter 'sheen_isGlossiness'(c4d.REDSHIFT_SHADER_MATERIAL_SHEEN_ISGLOSSINESS) = 0 Parameter 'refr_isGlossiness'(c4d.REDSHIFT_SHADER_MATERIAL_REFR_ISGLOSSINESS) = 0 Parameter 'decoupleIORFromRoughness'(c4d.REDSHIFT_SHADER_MATERIAL_DECOUPLEIORFROMROUGHNESS) = 0 Parameter 'shadow_opacity'(c4d.REDSHIFT_SHADER_MATERIAL_SHADOW_OPACITY) = 0.0 Parameter 'affects_alpha'(c4d.REDSHIFT_SHADER_MATERIAL_AFFECTS_ALPHA) = 1 Parameter 'block_volumes'(c4d.REDSHIFT_SHADER_MATERIAL_BLOCK_VOLUMES) = 1 Parameter 'energyCompMode'(c4d.REDSHIFT_SHADER_MATERIAL_ENERGYCOMPMODE) = 1 Parameter 'overallAffectsEmission'(c4d.REDSHIFT_SHADER_MATERIAL_OVERALLAFFECTSEMISSION) = 0 Parameter 'refl_endmode'(c4d.REDSHIFT_SHADER_MATERIAL_REFL_ENDMODE) = 1 Parameter 'anisotropy_orientation'(c4d.REDSHIFT_SHADER_MATERIAL_ANISOTROPY_ORIENTATION) = 2 Parameter 'anisotropy_uvChannel'(c4d.REDSHIFT_SHADER_MATERIAL_ANISOTROPY_UVCHANNEL) = Parameter 'anisotropy_tangentChannel'(c4d.REDSHIFT_SHADER_MATERIAL_ANISOTROPY_TANGENTCHANNEL) = Found Xpresso node: <c4d.modules.graphview.GvNode object called Baked Texture/RS Shader with ID 1001101 at 1819592565952> Parameter 'Icon File / ID'(c4d.ID_BASELIST_ICON_FILE) = Parameter 'Icon Color'(c4d.None) = 0 Parameter 'Color'(c4d.ID_BASELIST_ICON_COLOR) = Vector(0, 0, 0) Parameter ''(c4d.ID_BASELIST_ICON_PRESET_BUTTONS) = Inaccessible in Python Parameter 'Name'(c4d.ID_BASELIST_NAME) = Baked Texture Parameter 'Layer'(c4d.ID_LAYER_LINK) = None Parameter ''(c4d.ID_BASELIST_NODESPACE_ADD_REMOVE_BUTTONS) = Inaccessible in Python Parameter 'Enabled'(c4d.ID_GVBASE_ENABLE) = 1 Parameter 'Title Color'(c4d.ID_GVBASE_COLOR) = Vector(0.663, 0.624, 0.424) Parameter 'Remark'(c4d.ID_GVBASE_REMARK) = Parameter 'Version'(c4d.GV_REDSHIFT_SHADER_META_VERSION) = 17 Parameter 'Shader Class'(c4d.GV_REDSHIFT_SHADER_META_CLASSNAME) = TextureSampler Parameter 'tex0'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_TEX0) = Inaccessible in Python Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1000) = Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1010) = Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1011) = Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1001) = 0 Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1006) = <c4d.BaseTime object at 0x000001A85FC0EDC0> Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1007) = <c4d.BaseTime object at 0x000001A85FC1F440> Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1009) = 0 Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1003) = 0 Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1004) = 0 Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1005) = 30 Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1008) = 0 Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1002) = 0 Parameter 'tex0_layername'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_TEX0_LAYERNAME) = Parameter 'tex0_colorSpace'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_TEX0_COLORSPACE) = Parameter 'tex0_gamma'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_TEX0_GAMMA) = 1.0 Parameter 'tspace_id'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_TSPACE_ID) = Parameter 'mirrorU'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_MIRRORU) = 0 Parameter 'mirrorV'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_MIRRORV) = 0 Parameter 'wrapU'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_WRAPU) = 1 Parameter 'wrapV'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_WRAPV) = 1 Parameter 'scale'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_SCALE) = Vector(1, 1, 0) Parameter 'offset'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_OFFSET) = Vector(0, 0, 0) Parameter 'rotate'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_ROTATE) = 0.0 Parameter 'color_multiplier'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_COLOR_MULTIPLIER) = Vector(1, 1, 1) Parameter 'color_offset'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_COLOR_OFFSET) = Vector(0, 0, 0) Parameter 'alpha_multiplier'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_ALPHA_MULTIPLIER) = 1.0 Parameter 'alpha_offset'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_ALPHA_OFFSET) = 0.0 Parameter 'alpha_is_luminance'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_ALPHA_IS_LUMINANCE) = 0 Parameter 'invalid_color'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_INVALID_COLOR) = Inaccessible in Python Parameter 'filter_enable_type'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_FILTER_ENABLE_TYPE) = 2 Parameter 'filter_bicubic'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_FILTER_BICUBIC) = 0 Parameter 'prefer_sharp'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_PREFER_SHARP) = 1 Parameter 'mip_bias'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_MIP_BIAS) = 0.0 Parameter 'tone_map_enable'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_TONE_MAP_ENABLE) = 0 Parameter 'default_uv_if_invalid'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_DEFAULT_UV_IF_INVALID) = 1 Found Xpresso node: <c4d.modules.graphview.GvNode object called C4D Brick Shader/C4D Shader with ID 1001101 at 1819592570688> Parameter 'Icon File / ID'(c4d.ID_BASELIST_ICON_FILE) = Parameter 'Icon Color'(c4d.None) = 0 Parameter 'Color'(c4d.ID_BASELIST_ICON_COLOR) = Vector(0, 0, 0) Parameter ''(c4d.ID_BASELIST_ICON_PRESET_BUTTONS) = Inaccessible in Python Parameter 'Name'(c4d.ID_BASELIST_NAME) = C4D Brick Shader Parameter 'Layer'(c4d.ID_LAYER_LINK) = None Parameter ''(c4d.ID_BASELIST_NODESPACE_ADD_REMOVE_BUTTONS) = Inaccessible in Python Parameter 'Enabled'(c4d.ID_GVBASE_ENABLE) = 1 Parameter 'Title Color'(c4d.ID_GVBASE_COLOR) = Vector(0.424, 0.392, 0.541) Parameter 'Remark'(c4d.ID_GVBASE_REMARK) = Parameter 'Width'(c4d.GV_REDSHIFT_BAKER_TEXTURE_WIDTH) = 128 Parameter 'Height'(c4d.GV_REDSHIFT_BAKER_TEXTURE_HEIGHT) = 128 Parameter 'Depth'(c4d.GV_REDSHIFT_BAKER_TEXTURE_DEPTH) = 0 Parameter 'Shader'(c4d.GV_REDSHIFT_BAKER_SHADER) = <c4d.BaseShader object called Brick/Brick with ID 5804 at 1822672588480> Found Xpresso node: <c4d.modules.graphview.GvNode object called file_730884e9656be535~/RS Shader with ID 1001101 at 1819592599488> Parameter 'Icon File / ID'(c4d.ID_BASELIST_ICON_FILE) = Parameter 'Icon Color'(c4d.None) = 0 Parameter 'Color'(c4d.ID_BASELIST_ICON_COLOR) = Vector(0, 0, 0) Parameter ''(c4d.ID_BASELIST_ICON_PRESET_BUTTONS) = Inaccessible in Python Parameter 'Name'(c4d.ID_BASELIST_NAME) = file_730884e9656be535~ Parameter 'Layer'(c4d.ID_LAYER_LINK) = None Parameter ''(c4d.ID_BASELIST_NODESPACE_ADD_REMOVE_BUTTONS) = Inaccessible in Python Parameter 'Enabled'(c4d.ID_GVBASE_ENABLE) = 1 Parameter 'Title Color'(c4d.ID_GVBASE_COLOR) = Vector(0.663, 0.624, 0.424) Parameter 'Remark'(c4d.ID_GVBASE_REMARK) = Parameter 'Version'(c4d.GV_REDSHIFT_SHADER_META_VERSION) = 17 Parameter 'Shader Class'(c4d.GV_REDSHIFT_SHADER_META_CLASSNAME) = TextureSampler Parameter 'tex0'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_TEX0) = Inaccessible in Python Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1000) = asset:///file_730884e9656be535~.jpg?name=back-2.jpg&db=MaxonAssets.db (assets.maxon.net) Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1010) = Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1011) = Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1001) = 0 Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1006) = <c4d.BaseTime object at 0x000001A797214AC0> Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1007) = <c4d.BaseTime object at 0x000001A79721BFC0> Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1009) = 0 Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1003) = 0 Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1004) = 0 Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1005) = 30 Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1008) = 0 Sub-channel parameter (REDSHIFT_SHADER_TEXTURESAMPLER_TEX0, 1002) = 0 Parameter 'tex0_layername'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_TEX0_LAYERNAME) = Parameter 'tex0_colorSpace'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_TEX0_COLORSPACE) = Parameter 'tex0_gamma'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_TEX0_GAMMA) = 1.0 Parameter 'tspace_id'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_TSPACE_ID) = Parameter 'mirrorU'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_MIRRORU) = 0 Parameter 'mirrorV'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_MIRRORV) = 0 Parameter 'wrapU'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_WRAPU) = 1 Parameter 'wrapV'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_WRAPV) = 1 Parameter 'scale'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_SCALE) = Vector(1, 1, 0) Parameter 'offset'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_OFFSET) = Vector(0, 0, 0) Parameter 'rotate'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_ROTATE) = 0.0 Parameter 'color_multiplier'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_COLOR_MULTIPLIER) = Vector(1, 1, 1) Parameter 'color_offset'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_COLOR_OFFSET) = Vector(0, 0, 0) Parameter 'alpha_multiplier'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_ALPHA_MULTIPLIER) = 1.0 Parameter 'alpha_offset'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_ALPHA_OFFSET) = 0.0 Parameter 'alpha_is_luminance'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_ALPHA_IS_LUMINANCE) = 0 Parameter 'invalid_color'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_INVALID_COLOR) = Inaccessible in Python Parameter 'filter_enable_type'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_FILTER_ENABLE_TYPE) = 2 Parameter 'filter_bicubic'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_FILTER_BICUBIC) = 0 Parameter 'prefer_sharp'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_PREFER_SHARP) = 1 Parameter 'mip_bias'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_MIP_BIAS) = 0.0 Parameter 'tone_map_enable'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_TONE_MAP_ENABLE) = 0 Parameter 'default_uv_if_invalid'(c4d.REDSHIFT_SHADER_TEXTURESAMPLER_DEFAULT_UV_IF_INVALID) = 1 Code """Prints the parameter values of all Xpresso nodes attached to the materials of a document. Adds custom handling for the Redshift data type `CUSTOMDATATYPE_RSFILE` to unfold its sub-channels. Note: This script requires Cinema 4D 2025.0.0 or higher to run because it uses mxutils.RecurseGraph to find all Xpresso nodes in a material. The general approach of this script can however be applied to much older versions of Cinema 4D (up to R21 guaranteed, maybe even older versions). """ import c4d import mxutils doc: c4d.documents.BaseDocument # The currently active document. op: c4d.BaseObject | None # The primary selected object in `doc`. Can be `None`. # A bunch of data types to step over in descriptions because we do not care about them. NO_VALUE_TYPES: list[int] = [ c4d.DTYPE_BUTTON, c4d.DTYPE_CHILDREN, c4d.DTYPE_CHILDS, c4d.DTYPE_DYNAMIC, c4d.DTYPE_GROUP, c4d.DTYPE_MULTIPLEDATA, c4d.DTYPE_NONE, c4d.DTYPE_SEPARATOR, c4d.DTYPE_SUBCONTAINER, c4d.DTYPE_POPUP ] def main() -> None: """Called by Cinema 4D when the script is being executed. """ # Iterate over all materials in the document, stepping over everything that is not an # RS Xpresso material. for material in doc.GetMaterials(): if not material.CheckType(c4d.Mrsgraph): continue # Iterate over all Xpresso nodes owned by this material. #RecurseGraph is a 2025.0.0+ feature. # You can achieve the same effect with the Redshift API in earlier versions of Cinema 4D. But # since you did not share your code, I took this shortcut instead of writing some lengthy code # to find all RS Xpresso nodes for this material. print(f"RS Xpresso Material: {material}") for node in mxutils.RecurseGraph(material, yieldBranches=True, nodeFilter=[c4d.GVbase]): print(f"\tFound Xpresso node: {node}") # Iterate over the description of the node, stepping over all irrelevant data types. description: c4d.Description = node.GetDescription(c4d.DESCFLAGS_DESC_0) data: c4d.BaseContainer pid: c4d.DescID for data, pid, _ in description: if pid[0].dtype in NO_VALUE_TYPES: continue # Now we try to access the data at #pid. This can fail because the data type of #pid # might not be accessible in Python. value: any | None = None try: value = node[pid] except: value = "Inaccessible in Python" print(f"\t\tParameter '{data[c4d.DESC_NAME]}'(c4d.{data[c4d.DESC_IDENT]}) = {value}") # Hardcode one of the data types (CUSTOMDATATYPE_RSFILE) and unfold its sub-channels. if pid[0].dtype == c4d.CUSTOMDATATYPE_RSFILE and len(pid) == 1: for subChannel in (c4d.REDSHIFT_FILE_PATH, c4d.REDSHIFT_FILE_LAYER, c4d.REDSHIFT_FILE_COLORSPACE, c4d.REDSHIFT_FILE_ANIMATION_MODE, c4d.REDSHIFT_FILE_ANIMATION_RANGE_START, c4d.REDSHIFT_FILE_ANIMATION_RANGE_END, c4d.REDSHIFT_FILE_ANIMATION_LOOP_COUNT, c4d.REDSHIFT_FILE_ANIMATION_FRAME_START, c4d.REDSHIFT_FILE_ANIMATION_FRAME_END, c4d.REDSHIFT_FILE_ANIMATION_FRAME_RATE, c4d.REDSHIFT_FILE_ANIMATION_FRAME_OFFSET, c4d.REDSHIFT_FILE_ANIMATION_TIMING_MODE): try: value = node[pid[0].id, subChannel] except: # This, that the sub-chanel is inaccessible too, can also happen, as the # sub-channel could be as much an unwrapped data type as its parent # parameter. Technically, a DescID can be composed out of three # DescLevel, i.e., you could have a parameter X with N sub-channels # where each of the sub-channels could also have N sub-channels, e.g., # (ID_FOO, ID_SUB_1, ID_SUB_1_1). None of these sub-channels has to use # a data type that is wrapped in Python. But something like this is # rather rare. Parameters where the first desc level is not some kind of # container (e.g., DTYPE_SUBCONTAINER), usually only decomposes into # atomic data types that can also be read from Python. But there is no # hard guarantee that this is the case. value = "Sub-channel is inaccessible in Python" print(f"\t\t\tSub-channel parameter ({data[c4d.DESC_IDENT]}, " f"{subChannel}) = {value}") if __name__ == '__main__': main()
  • Script to change parameters across all similar nodes material

    Moved 2025 python
    3
    0 Votes
    3 Posts
    285 Views
    A
    okay the docs you gave were great for insight working code to change parameter of roughness for x given mat selections import c4d import maxon from maxon import GraphDescription doc = c4d.documents.GetActiveDocument() # Get selected materials directly selected_materials = doc.GetActiveMaterials() # Modify roughness for each selected material for material in selected_materials: graph = GraphDescription.GetGraph(material, nodeSpaceId=maxon.NodeSpaceIdentifiers.RedshiftMaterial) GraphDescription.ApplyDescription(graph, { "$query": { "$type": "Standard Material" }, "Reflection/Roughness": 1 }) c4d.EventAdd()
  • Motion Blur, ExecutePasses in VideoPostData

    c++ 2025
    2
    0 Votes
    2 Posts
    211 Views
    ferdinandF
    Hello @Aaron, Thank you for reaching out to us. Please follow our support procedures. You should consolidate your postings until we answer, i.e., update your last posting instead of creating new ones. I have consolidated your postings for you. You should also spend more time on making your problems reproducible for us. I know it can be easy to overlook in the heat of the battle but your question(s) are not as obvious to me as you probably think they are. As lined out in our support procedures, example code and/or scene data is usually required. I cannot answer every possible angle and interpretation this topic of yours could take, but I can state three things which come to mind when reading your two postings. What's the way to get several steps of motion blur transformation matrices for BaseObjects of the BaseDocument. That is simply not possible. A document has no notion of motion blur as it is a render effects implemented by a render engine, not something documents implement. Cinema's time system BaseTime allows for sub-frame accuracy, e.g., you could set a 10fps document to BaseTime(i, 30) and with that step with three sub-frames through the document. Simple things like position animations or other interpolated values will also work doing this. But simulations might yield different results than stepping with the natural frame rate through the document. And the most important thing is that there is absolutely no guarantee that this approach will result in 'matrices', i.e., transforms, that will match with what a render engine produces when you add some kind of sub-frame-based motion blur. Using this BaseTime approach is one way how the render engine could do it, but since render engines always have their own scene format, they could also do the calculation there, yielding different results than what Cinema's animation system would yield. When we want to add Motion Blur and call document->ExecutePasses(...) for some time then this POC is flushed and has no polygons or vertices, so it's not collected and can't be rendered It is too opaque for me what you are doing there to give a real answer, but: There is no guarantee that the caches of an object are built at any point except for when a render engine gets a scene state to render or inside GetVirtualsObjects when you manually build your dependent objcts. Usually, caches are built but depending on where you are, the cache of another object might not have been built or updated yet, resulting in either an empty cache or you looking at the cache output from the previous scene update. ExecutePasses has become a bit too popular tool recently. I guess that is partially my fault, because I have shown its usage in some examples. But executing the passes on a document is a very expensive operation and should only be carried out when absolutely necessary. I would absolutely not be surprised if something like liquids do not support stepping through a document with a frame rate lower than the documents frame rate. But without concrete data and example code I am just guessing. Cheers, Ferdinand
  • How to Modify Button Parameters?

    python
    2
    1
    0 Votes
    2 Posts
    197 Views
    ferdinandF
    Hey @Ross, Thank you for reaching out to us. You are right, we cannot support third party APIs, but questions about our API do not automatically become moot or out of scope of support, just because they happen in the context of a plugin. We will of course still answer such questions. We will just never write code for a third-party API or test user code that requires a plugin. Your question '[I] need help modifying the "Import Type" button parameters of an ImageTexture node' is however ambiguous. A parameter is Cinema 4D slang for an element in a description, one of the ways of how Cinema 4D defines UIs. This includes things that users would naturally call a parameter such as a textbox holding a string, a number edit holding a float, or a combo box holding a selection, i.e., things that hold a value. But it also includes things that are just part of the UI of a node that cannot hold a value, e.g., a group, a separator, or a button. When someone talks about 'modifying' a parameter I would usually assume that they talk about changing the description of a node, specifically at that parameter. E.g., changing the label of a button, adding or removing elements to/from a drop down, disabling an element, etc. You can only do this for nodes you own, i.e., implement yourself. You cannot change the UI of alien elements, because for you their description is read only. But I assume you are actually talking here about getting or setting the parameter of an element, e.g., set a float slider to the value '4.13'. What gets a bit in the way here in your case, is that Cinema 4D summarizes everything under the label of paramater, even things that do not naturally have a value which could be gotten or set. So, I assume you want to press this button, for that you have two options: Call c4d.CallButton Send the message c4d.MSG_DESCRIPTION_COMMAND Please note that both approaches are restricted to being called from the main thread only when the scene element upon which they are called is part of a loaded scene. E.g., calling one of them on a node in the active document from outside of the main thread: forbidden. Calling them from inside a GetVirtualObjects (or any other off-main thread context) on a scene element in a dummy document which has been constructed just for this purpose and is not loaded by Cinema 4D: absolutely fine. Cheers, Ferdinand
  • 0 Votes
    8 Posts
    432 Views
    A
    @ferdinand said in BaseBitmap.Init("somefile.exr") crashes with multiple std::thread: omp #parallel Sorry for late reply, I am not advocating for std::threads, I understand your design explanation. The omp #parallel thing is OpenMP directive to launch parallel threads. It's an old but simple method. Actually I have made a solution by exploiting Cinema way of launching threads and it works fine. However, I hope it would be good to make BaseBitmap->Init a thread safe and independent call from other C4D threads and resources. I will collect an example for you with exr images soon. Cheers, Aaron
  • How to get explicit import node space?

    windows python 2025
    3
    1
    0 Votes
    3 Posts
    215 Views
    DunhouD
    Thanks @ferdinand for your great solution! Cheers~ DunHou