administrators

Private

Posts

  • RE: TimeLine DopeSheet not update

    Hey, good news, this is fixed in the upcoming hotfix (2026.3.2).

  • RE: Programmatically created Redshift Lights in an Object Plugin converts lights into Null-Objekts without an function after making Objekt-Plugin editable

    Hey @ThomasB,

    so, I had a look and figured it out. When you diff the two objects from my file, there are quite few differences (as I was not 100% faithful in copying all values), but the culprit is this:
    cef8fb22-88d1-4073-8b29-1e2958c0db14-image.png

    The RS Light uses a standard light to accomplish its VP representation. When you disable the 'Illumination' checkmark, the RS Light GetVirtualObjects will simply return a null object, i.e., the behavior you experienced. I filed a ticket for this (ITEM#651586 Inconsistent Redshift Light 'Make Editable' behavior), as I would consider this so unintuitive that it borders on a bug. But this is outside of the SDK/Cinema 4D domain, so I cannot just fix it myself.

    In Python, there is currently no way to fix this on your side. The message MSG_CURRENTSTATE_END is not wrapped for Python (with it you can manipulate the output of a "Make Editable" action before it is inserted). The other route, the build flags on HierarchyHelp are also not possible in Python either, because HierarchyHelp is also not wrapped for Python.

    But I just changed the latter route, and in the next major update you will be able to react to build flags. There will also be a new code example named py-objectdata_buildflags_2027 which showcases this feature. You can then react to your object being made editable, built for rendering, built for export, etc. and react by changing its output.

    In your case you would then probably not disable the illumination when your object is being made editable. So, for now, you either have to live with the behavior, or turn on "preview > illumination".

    Cheers,
    Ferdinand

    Result

    The output, i.e., diff, with the offending line highlighted.
    d0a8e14c-d913-4990-9ec5-29e4a5150cf3-image.png

    Code

    This assumes my scene from above with everything deleted but the two objects.

    import c4d
    import mxutils
    import difflib
    
    doc: c4d.documents.BaseDocument  # The currently active document.
    op: c4d.BaseObject | None  # The primary selected object in `doc`. Can be `None`.
    
    def main() -> None:
        """Called by Cinema 4D when the script is being executed.
        """
        data: list[str] = [
            mxutils.GetParameterTreeString(node) 
            for node in mxutils.IterateTree(doc.GetFirstObject(), True)
        ]
    
        # Diff the first two strings in the list and print the result to the console.
        if len(data) < 2:
            return c4d.gui.MessageDialog("Not enough data to perform diff.")
        
        a: str = data[0]
        b: str = data[1]
    
        diff: list[str] = list(difflib.unified_diff(a.splitlines(), b.splitlines(), lineterm=''))
        if not diff:
            print("No differences found.")
        
        print("\n".join(diff))
        print("\n\n" + "=" * 80 + "\n\n")
        print(a)
        print("\n" + "-" * 80 + "\n")
        print(b)
        
        c4d.EventAdd()
        
    
    if __name__ == '__main__':
        main()
    
  • RE: Programmatically created Redshift Lights in an Object Plugin converts lights into Null-Objekts without an function after making Objekt-Plugin editable

    Thanks, I will have a look. This all is starting to make sense now. We rewrote the RS Light and Camera objects a while ago. And at least the RS Camera object is not absolutely non-trivial to operate. This either sounds like that you have to jump through specific hoops or there is a bug in the importer code, that transforms pre 2024 Light and Camera objects (I think this was when we revamped them).

    It might take me a week or so to figure this out. When this is very urgent for you, I would recommend fixing the scene(s) by manually recreating the lights. You could probably also automate this by just selectively copying data (which is likely going to be the solution I am going to provide, unless I come to the conclusion that this must be fixed on our side, as for example the importer being faulty).

    Cheers,
    Ferdinand

  • RE: Programmatically created Redshift Lights in an Object Plugin converts lights into Null-Objekts without an function after making Objekt-Plugin editable

    Hey @ThomasB,

    I do not think that this is an API issue. I do not meant with that that I will not help you, as this still happens in the context of a plugin, I say this simply to classify the issue.

    When I try to manually open your build_1.c4d file, it loads in 2026.2.0 but when I then press C on that light in question, I get exactly the output you report. And I cannot really explain why as this is just a normal rectangle shape area light (well, I sort of can, see below 😄 ).

    26b330be-2ffb-4079-94bd-e35821b41c29-image.png

    The plot however thickens when I try to open the file with 2026.3.1:

    3f42e837-826c-4145-87ae-9436d31c51f2-image.png

    This file seems to be somehow corrupted. After some poking around I manged to create this build_2.c4d which loads in 2026.3. But the light still did not work correctly. I then created a new RS light instance and copied over the whole data container via Get/SetData, which again resulted in a broken light. Only when I manually recreated the light by manually copying values, I ended up with a valid light. Which then also revealed that this light should have a much different light representation in the VP.

    Your light:

    8bb73cb1-8cf6-4851-9001-83dff031795e-image.png

    The manual copy:

    31f028b3-6054-4078-b9c0-82f04b49b7a9-image.png

    I.e., you seem to have there a fundamentally corrupted scene and especially light objects. The fact that I could reproduce this with a fresh light instance and a Get/SetData copy indicates this the data container of the light is corrupted. We could now start comparing the data containers of your light and the manually created one, to dive deeper, but I think I stop here for now. Did you programmatically modify this scene? Because your plugin only seems to load it. The question is now if you have more scenes like this. Otherwise I would just use my fixed scene (which also contains the fixed light) and move one.

    Cheers,
    Ferdinand

    PS: Okay, now I see it, the actual scene in much more complex.

    When you want to dig deeper yourself, a great tool to debug this would be mxutils.GetContainerTreeString. You can just dump both containers and then either visually compare them or use a diff tool. Or you use mxutils.GetParameterTreeString directly on the light objects.

  • RE: Sub materials links and undo

    @DronKozy

    Yeah, I got the general direction, that you are probably implementing a material mixer type of material/shader. When you implement a full render engine binding, you should go the event notification route, as I am sure you can then easily handle the (slight) complexity that comes with them.

    Regarding the architecture, in principle you can do with whatever you want. As Maxon employee I would of course recommend to use our Nodes API (what you call 'native'). The SDK contains both code examples and documentation about this. But this biggest flaw of the Nodes API is probably that it is not entirely non-trivial. But implementing a full node editor also requires a relatively high level of expertise about our APIs, although in different areas.

    Currently Redshift, Vray, Arnold, and CentiLeo use the Nodes API and all other render engines (Corona, Octane, Cycles, etc.) use either a completely custom system or the old Xpresso Nodes API.

    Cheers,
    Ferdinand

    PS: When you are developing a render engine binding, you might want to consider our Maxon Registered Developer Program.

  • RE: Programmatically created Redshift Lights in an Object Plugin converts lights into Null-Objekts without an function after making Objekt-Plugin editable

    Hello @ThomasB,

    I am sorry that you had a bad experience in the RS forum. Can you show me the actual code where you add the RS light object in code? Because I see no Orslight in your snippet? Or when you load an asset, share that asset? When I do a quick test with a Python generator object, this works fine for me.

    Cheers,
    Ferdinand

    PS: The plugin link you shared only contains an encrypted plugin (pypv) which not only makes it harder for me to get to the source code, I also cannot run such plugin on company hardware before I cracked it and can reasonably say that it does not contain dangerous code. Could you please share an unencrypted version?

  • RE: Sub materials links and undo

    Hello @DronKozy,

    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

    I am afraid there is no really good way to do what you want to do. Without example code, I also have to somewhat guess what is going on. As lined out in our support procedures, we recommend to always accompany questions with compileable code.

    I it is a bit fuzzy to me what you are doing, please tell me when I got it wrong. You have a BaseMaterial implementation which itself has LINK parameters which link to other materials. You now want to update MATPREVIEW parameter manually when your dependencies update.

    Tracking Changes

    Cinema generally follows an opt-out and not an opt-in update/message model. E.g., all objects get their GetVirtualObjects method called on each scene update, and it is then up to the object to decide if they actually want to update or just keep using their existing cache.

    The evaluation of materials happens at render time, so there is no direct function which is called or message which is sent to your plugin when something in the scene is being updated. The messages you are using somewhat go into that direction, but you misunderstood a bit their purpose. MSG_UPDATE is sent when an external entity wants to inform a node that it modified dependent data and that the node should update its internal data (outside of the general scene state rebuild). It is not a message that is being sent each time the node has been updated. I could for example get a point object, modify its points, and then not send that message and that would be totally valid code. The object would only update once Cinema 4D reevaluates the object on its own, but sometimes this is desirable. For user interactions, Cinema 4D will usually send this message, but its purpose is still a bit different from what you think it is. The same goes for MSG_CHANGE.

    The way to track changes in Cinema 4D, is the dirty system found on C4Datom. Cinema will usually automatically entail updates when the dirtiness of something changed, e.g., when a user changed the parameters of a node. The problem is that for LINK parameters (and also shader links), changes to the linked node do not count towards the data dirtiness of the node. Or in other words, Cinema does not consider a node A to be changed when the node B changed to which A links. For something like objects this is not really a problem due to the out-out update model, for material previews this means you can get event starved. The video below demonstrates the effect.

    Well, how do I solve this?

    What you do - a material that links other materials and in some shape or form drives its own material preview updates - is simply not intended. So, we have to get a bit creative.

    Piggybacking on other messages

    Just hook into a message that is being sent all the time. Objects and tags for example receive MSG_GETREALCAMERADATA and MSG_GETCUSTOMICON_SETTINGS each time a scene update ran. But I think you will not get these messages in a BaseMaterial. As I said, there is a good chance that you get event starved in a material. I would put a print statement into you message function, printing out the message ID, and then just start interacting with the scene, adding a cube, changing your linked material. To see if anything sticks to the wall, if there is a message ID you can piggy back on.

    Event Notifications

    ⚠ Event notifications are private for a reason. You can easily crash Cinema 4D with them when misused. The type of event notifications we use here, message notifications, are however relatively harmless.

    An alternative could be cinema::AddEventNotification. With event notifications, you can hook into the message stream of other nodes among other things. So, the idea would be:

    1. In your MyMaterialData::Message, listen for MSG_DESCRIPTION_POSTSETPARAMETER, to catch the moment when the user sets a new linked material (which will count as an update for your material).
    2. Then call myMaterialNode->AddEventNotification(materialThatHasBeenSet, NOTIFY_EVENT::MESSAGE, NOTIFY_EVENT_FLAG::NONE, nullptr);
    3. In your MyMaterialData::Message, listen for MSG_NOTIFY_EVENT and then do something like this:
    if (type == MSG_NOTIFY_EVENT && data)
    {
        const NotifyEventData* const notifyData = (NotifyEventData*)data;
        if (notifyData->eventid == NOTIFY_EVENT::MESSAGE && notifyData->event_data)
        {
            NotifyEventMsg* messageData = (NotifyEventMsg*)notifyData->event_data;
    
            // Now we are basically inside the ::Message function of the linked material #materialThatHasBeenSet. We could 
            // for example react to a parameter change.
            if (messageData->msg_id == MSG_DESCRIPTION_POSTSETPARAMETER)
            {
                // Do something when the linked material changed
            }
        }
    }
    

    All in all, this is not a trivial problem to solve. When you run into more issues, please provide a minimal reproducible example code, so we can help you better.

    Cheers,
    Ferdinand

  • RE: GetWorkplaneMatrix is broken in Cinema 4D 2026.3

    This will be fixed in the next upcoming hotfix.

  • RE: GetWorkplaneMatrix is broken in Cinema 4D 2026.3

    Hey @peter_horvath,

    thanks for the files, I will keep you posted here.

    Cheers,
    Ferdinand