administrators

Private

Posts

  • RE: Batching Slider messages

    Hey @SteveHill3D,

    it's okay, the start is always a bit chaotic. That snippet alone would have told me some things.

    Yes, sorry, MSG_DESCRIPTION_POSTSETPARAMETER is fired within the drag event (the parameter has still to be set). The final description event is MSG_DESCRIPTION_USERINTERACTION_END. But I still do not really understand what you are doing. What is triggering the updates? Just dragging one of the sliders will not update the tool in our edge cutter tool example (because it does not really implement the interactive mode that comes with description tools).

    So, the tool should either fire when you have keyboard or viewport inputs and implemented MouseInput or KeyboardInput. When you click Apply, it should call DoCommand. You can of course hook into Message to react to all sorts of things (and that is indeed how you implement the interactive mode), but you message implies that your tool fires on your own. Which it should not.

    Cheers,
    Ferdinand

  • RE: Advice on implementing undo/redo in a Tool

    Hey @SteveHill3D,

    Storing a tool state in a tag is possible, but a bit unusual. But generally you are on the right track. Tags are also internally often used as hidden data containers. When you write a modelling tool, you probably already found out that points and polygons are are actually stored in hidden tags on objects.

    I am not sure though if using tags in tools is a good advice, as injecting all that data all the time into the scene graph is probably not the fastest. It depends a bit on what you are doing, but in general the solution is a bit unusual.

    Cheers,
    Ferdinand

  • RE: Batching Slider messages

    Hey @SteveHill3D,

    Thank you for reaching out to us. It depends a bit on what is your 'tool'. When it is a 'classic' tool, i.e., implemented as a ToolData with a GeDialog, then BFM_DRAGEND would be the way to sort out BFM_ACTION events for a slider that are the final action of a drag event. When you search for the message symbol BFM_DRAGEND and its sibling symbols BFM_DRAGSTART and BFM_ACTION_INDRAG here on the forum, you will find multiple code examples around the topic of sliders. I think there are also some examples in the C++ SDK.

    When your tool is a DescriptionToolData, i.e., a node in disguise, then you cannot handle drag events yourself. Your tool should fire on its own only after MSG_DESCRIPTION_POSTSETPARAMETER has fired for your node, i.e., after the final value of a drag event for some slider has been set.

    Please have a look at our Support Procedures, we require users to post code for pretty much all questions, as it minimizes the guess work on our side. As for example me here writing about two cases.

    Cheers,
    Ferdinand

  • RE: Tile rendering with Cinema 4D

    @karthikbp

    As far as I can see this at a glance, this seems to be correct. You already did the most important thing by using RDATA_RENDERREGION and not some camera cropping tricks, so it renders with the full scene data for each tile.

    There is however one issue, and it depends on the render engine how it is handled. At verbatim, kernels applied to your rendering (e.g., a box filter) will be slightly wrong, because for the the seams of a tile, there is data missing (the seam pixels of the neighboring tile) which would exist in a full rendering. E.g., when you have this,

    --------------- ----------------
                  x y
        Tile A    x y    Tile B
                  x y
    --------------- ----------------
    

    a rendering split into two tiles Tile A and Tile B, where x are the 'seam pixels' of Tile A and y are the seam pixels of Tile B. If you would have rendered the whole image in one go, processing one of the xs with a kernel would have included neighboring pixels, i.e., also what is now the seam pixels y of the other tile. So, at the borders of the tile, any filter kernels you will apply will not be quite the same.

    To prevent that issue, Redshift does render region tiles with an extra border of the maximum size of the kernels used for that rendering. But the standard renderer does not do that. Other render engines which might support our render region setting might not do that either. In such cases, you would have to either live with the small error or render with an extra border yourself, depending on the kernels that will be used., and then crop the final result back.

    Cheers,
    Ferdinand

  • RE: 2025 SDKs missing files

    Hello @atg,

    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 can see why would think that, but you mixed things there a bit up. The CMake SDK build system was introduced with 2025.2.0 and became the standard with 2026.0.0. Between 2025.2 and 2025.3 we supported both build systems as a grace period for developers to get accustomed.

    Chances are very good, that you can just copy the CMake setup, i.e., the cmake folder and files such as CMakeLists.txt, CMakePresets.json, and sdk_modules.txt to a 2025.0 folder and it will generate a correct build system for you.

    But the supported range is only 2025.2+. For older projects you would have to use the old project tool based build system. Since I know what you are trying to do, I would recommend trying copying before you get into the old build system of ours.

    Cheers,
    Ferdinand

    edit: You will only find the old project tool tooling in old extended SDKs which supported it, such as 2025.2 or 2025.0.1

  • RE: CUSTOMGUI_QUICKTAB trigger twice when click

    hey @Gene,

    So, you were just trying to add information for future readers? That is of course very welcome and explains my inability to extract a question from your posting.

    I would not have been that generous with the word bug either. Since this has never been fixed, chances are high that we came to the same conclusion internally.

    In general, you should not expect Command calling patterns to make perfect sense in every case. There are multiple cases where Command is triggered more often than one would think at first glance. I would also not try to interpret some deeper sense into all that.

    Cheers,
    Ferdinand

  • RE: CUSTOMGUI_QUICKTAB trigger twice when click

    Hey @Gene,

    Thread-necromancy is often not so good, because it almost always derails the original topic and often also lacks in clarity. I also here do not understand what your concrete question is?

    When I click on the Quicktab, the first event returns True, while the second returns False.

    What do you mean by "the event returns true"? It is you, the developer, who returns the result for an event (or you do not handle it at all). Are you talking about something like BFM_ACTION_VALUE?

    If I drag over two entries on the Quicktab gadget (click on one entry, then drag to the next entry and let go of the mouse,) Command triggers three times, msg[c4d.BFM_ACTION_INDRAG] returns True the first two times and False for the last one. Also, the first entry returns True for its IsSelected() check on mouse down. After dragging, the the second entry's IsSelected() is True. Second entry's IsSelected() is also true when I let go of the mouse.

    I do not see any question here, so what is the goal?

    Regarding Command triggering twice, is it because of the mouse events?

    GeDialog.Command is just a convenience wrapper for GeDialog.Message events (most from the BFM_ACTION family). If you want the full picture, use Message. I struggle to see a tangible question which I could answer, what do you want to achieve?

    Yes, some controls fire multiple times in Command, it is impossible (and also somewhat futile) to reconstruct the reason for each of them. Someone thought at some point it would be convenient to forward this kind of event to Command for some feature in Cinema 4D.

    I am not familiar with the exact issue discussed in this topic, but at a glance, what Maxime wrote then looks a bit overkill with the hashing, I would just store the last selected element and be done with it. Alternatively you could design your code so that you do not tie any heavy logic to a tab being activated (which is IMHO not a great idea in general), so that you do not mind when such code runs multiple times.

    Cheers,
    Ferdinand

    class MyDialog (c4d.gui.GeDialog):
        ID_TAB_1: int = 10000
        ID_TAB_2: int = 10001
    
        IDS_TABS: tuple[int, ...] = (ID_TAB_1, ID_TAB_2)
    
        def __init__(self) -> None:
            self._activeTab: int = MyDialog.ID_TAB_1
    
        def Command(self, cid: int, msg: c4d.BaseContainer) -> bool:
            """
            """
            if cid == self._activeTab:
                return True
            elif cid in MyDialog.IDS_TABS:
                self._activeTab = cid
    
            if cid is MyDialog.ID_TAB_1:
                foo()
            elif cid is MyDialog.ID_TAB_2:
                bar()
    
            return True
    
  • RE: How to detect Global Illumination state via Python API?

    Hey @mfersaoui,

    Thank you for reaching out to us. The question is a bit ambiguous. What it entails when 'Global Illumination is enabled' (or not), differs from render engine to render engine. There is neither an abstracted switch to toggle GI in all render engines, nor a flag which would signal of GI is enabled or not.

    So, the first thing you would have to do, is read RDATA_RENDERENGINE and then branch of based on that. For the standard renderer, you would then check if the GI post effect is loaded and enabled. For Redshift you would get the RS post effect and then check there if has GI enabled.

    You can find the post effect symbols here: VideoPost Types

    Cheers,
    Ferdinand

    Some example code for searching the post effects in some render data.

    # Get the active render data of the document.
    renderData: c4d.documents.RenderData = doc.GetActiveRenderData()
    
    # Set the active render engine to Redshift.
    renderData[c4d.RDATA_RENDERENGINE] = c4d.VPrsrenderer
    
    # Iterate over all video post effects and remove any effect not compatible with the Redshift 
    # render engine and finally make sure the Redshift video post effect itself is present. We do 
    # not remove the effects in place in the loop, as that would mess up the iteration because nodes
    # effectively work as a linked list.
    removeEffects: list[c4d.documents.BaseVideoPost] = []
    foundRedshiftEffect: bool = False
    for effect in mxutils.IterateTree(renderData.GetFirstVideoPost(), True):
        # This is the Redshift video post effect.
        if effect.GetType() == c4d.VPrsrenderer:
            foundRedshiftEffect = True
            continue
        # This is some effect not compatible with Redshift.
        elif not effect.RenderEngineCheck(c4d.VPrsrenderer):
            removeEffects.append(effect)
    
    # Remove all the video post effects we marked for removal.
    for effect in removeEffects:
        effect.Remove()
    
    # And add the Redshift video post effect if it was not found yet. Note that there is no hard
    # guarantee that a render engine uses the same ID for its video post effect as the render 
    # engine ID (VPrsrenderer in this case). But it is a very common convention, check with your
    # render engine vendor for details.
    if not foundRedshiftEffect:
        redshiftEffect: c4d.documents.BaseVideoPost = mxutils.CheckType(
            c4d.documents.BaseVideoPost(c4d.VPrsrenderer))
        renderData.InsertVideoPost(redshiftEffect)
    
  • RE: Advice on implementing undo/redo in a Tool

    Hey @SteveHill3D,

    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

    You could look at our edgecuttool.cpp C++ SDK example, it demonstrates both the usage of undos and cinema::InteractiveModeling_Restart, i.e., rolling updates. In some cases InteractiveModeling_Restart will not cut it you have to un-roll your undos yourself or even not use undos at all for rolling updates and instead work with a tool finalization logic.

    By chance I just wrote an example for the latter for the upcoming Python SDK. You will not be able to run it, as the customer release version is missing the Python API to deal with SDS weights, but you can have a look at its code. The idea is simple: Establish a ground truth and operate based on that. But for modelling tools and especially tools that add or remove geometry using undos and InteractiveModeling_Restart should be preferred when possible, as it will be usually faster, as the cinema core can pull some tricks you cannot as a third party.

    Cheers,
    Ferdinand

    Please understand that this example is a preview and might be subject to change.
    py-cmd_tool_finalization_2026_2.zip

  • RE: Tile rendering with Cinema 4D

    Hey @karthikbp,

    Thank you for reaching out to us. And sorry, I somehow overlooked your topic. Yes, that is how I would have done it too, via RDATA_RENDERREGION_LEFT, etc. The 2026.2 Python SDK will contain new rendering examples, that could be something I could add, as tile rendering is something that comes up from time to time.

    As a fair warning: Your code will not respect OCIO, i.e., the images will have the wrong colors. Since you marked this as 2026, where OCIO is the color management standard, this would apply to all documents. See open_color_io_2025_2.py for an example how to do it correctly. The next release will streamline things there quite a bit.

    Cheers,
    Ferdinand