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

    Topics created by kbar

    • kbarK

      How to Encrypt Python Plugins without a License?

      Cinema 4D SDK
      • python 2025 • • kbar
      2
      0
      Votes
      2
      Posts
      124
      Views

      ferdinandF

      Hey @kbar,

      thank you for reaching out to us. Please remember creating new topics instead of posting in older one's, so that our forum remains a searchable database. I have forked your question.

      I understand the necessity and use case for this, but in the proposed form, this is not possible. At least not without more work than it makes sense to invest here. Because the license validation is one of the first steps in the boot sequence of Cinema 4D, and trying to evaluate a command line argument and use all the components of our API necessary to encrypt a file could easily lead to problems (as these modules might not have been loaded yet).

      What we could think about is offering this as a standalone tool. The issue is here that we cannot just ship the source for that tool (for third parties to compile it themself) as the source would then also be known to bad actors. And shipping it as a binary would be extra work. An alternative could be a REST service, but that is also extra work (but less than the former route). I currently have no time for either of this. At the end of the year I will probably do some website work, then we could think about the REST route. But it is likely that I then also do not have time for this.

      As an MRD, you also have the option to ask in our beta forums or make a source code sharing request. In the end, this is very simple code and could probably easily emulated with a couple of lines of Python code. That is probably the most sensible route, but we would have to involve PMs etc. here, if we are willing to do that. I myself am even not sure if I would greenlight such request due to the sensitive nature of the topic.

      So, unfortunately, there is no clear cut route here, although I definitely can see the use case.

      Cheers,
      Ferdinand

    • kbarK

      How to handle AddDependence hh deprecation in 2024 onwards

      Cinema 4D SDK
      • python 2024 2025 • • kbar
      6
      0
      Votes
      6
      Posts
      925
      Views

      ferdinandF

      Hey @kbar,

      Thank you for reaching out to us and the heads up, much appreciated. Looks like we forgot to update the function documentation, because the change is in the change notes. I updated the docs for the upcoming release.

      Cheers,
      Ferdinand

    • kbarK

      How to correctly get maxon::NimbusInterface?

      Cinema 4D SDK
      • 2023 2024 c++ • • kbar
      2
      0
      Votes
      2
      Posts
      420
      Views

      O

      Hi Kent,
      the cast is safe. In the public API, NimbusInterface is an incomplete type. Only NimbusBaseInterface is defined there. But internally, NimbusInterface is derived from NimbusBaseInterface, therefore you can safely do the cast.

    • kbarK

      BaseBitmap Save TIF with LZW and save EXR using ZIP

      Cinema 4D SDK
      • 2024 c++ windows • • kbar
      4
      0
      Votes
      4
      Posts
      599
      Views

      ferdinandF

      Hey Kent,

      it depends a bit on the context. Generally, yes, flags and parameters passed to a BaseBitmap are piped through to the underlying ImageRef. But as I hinted at with the TIF settings for BaseBitmap::Save, some stuff is also ignored.

      For fundamental stuff like initializing a bitmap with a channel depth, color format, etc., I am not aware of cases where flags are being ignored. But as I wrote in my pseudocode example, the exact nature of the BaseBitmap::GetImageRef is also quite important.

      My very high level advice would be, use the Maxon Image API directly for simple things like loading, color converting, or saving an image, but avoiding it for complex tasks like for example assembling a multi layer image or drawing (not possible at all in the public API apart from 'dumb' pixel by pixel drawing). The problem with this is that when you must have a BaseBitmap output. Because while you can get an ImageRef from a BaseBitmap instance, there is no 'sane' public way to construct a BaseBitmap from an ImageRef you can of course copy over the buffer manually (not so sane) and there is a private way to do this but has its pitfalls (but is possible to do with the public API).

      As I said, I would invite you to reach out to us with some code and a concrete use case when you get stuck, I will then be able able to help you specifically.

      Cheers,
      Ferdinand

      PS: We recently dropped the term 'classic API' in favour of 'Cinema API'. We also capitalize now 'Maxon API'. Just saying this for clarity.

    • kbarK

      How to use GetAllNimbusRefs in 2023

      Cinema 4D SDK
      • 2023 c++ windows • • kbar
      5
      0
      Votes
      5
      Posts
      879
      Views

      kbarK

      Thanks @ferdinand! Appreciate everything you do. Also what the rest of the sdk support and docs team are doing! Not an easy job keeping on top of all these changes.

    • kbarK

      Plugin Developer Job opening at Greyscalegorilla

      General Talk
      • jobs • • kbar
      2
      1
      Votes
      2
      Posts
      751
      Views

      L

      @kbar
      I am interested in c4d (also cg) plugin development.
      But your requirements are a little bit high for me, especially "Strong proficiency in C++ programming language".
      I can use c++ for programming but not strongly. But I can also make a c++ plugin like this:
      Set View.gif
      A part of my code:
      A part of my code.png

    • kbarK

      Message on "Quit and Free License"

      Cinema 4D SDK
      • c++ • • kbar
      2
      0
      Votes
      2
      Posts
      544
      Views

      ferdinandF

      Hey @kbar,

      Thank you for reaching out to us. In the public API there is only what you can find in Plugin Licensing Manual. The natural solution for this would be an observable to which you can attach, but there is none in the public API.

      What you could do is try workarounds:

      Register a MessageData plugin and check periodically yourself. This might work okay for certain license change events, but when the license change induces a shutdown of Cinema 4D (a user released a license for example), you might get event starved. So, this is not great. Hook into the shutdown of Cinema 4D itself. When we want to specifically target the event that a license is being released, we can build upon the fact that Cinema 4D will then shut down. MAXON_INITIALIZATION: This is a bad choice in this case, because when the shutdown delegate of MAXON_INITIALIZATION is running, most registries already have been shut down. So, I would not be surprised, if all the license stuff is not working anymore at this point (I have not checked though). The advantage is here that MAXON_INITIALIZATION often makes for nicer looking code than PluginMessage. PluginMessage: Hook into the shutdown sequence of Cinema 4D, and check the license state there. C4DPL_ENDACTIVITY is the best event to start with.

      The problem is here that I do not know how licenses behave when a user releases a license. The idea would be to check for example on shutdown, if there is still a commercial license bound to this instance:

      // Create the ID for a commercial Cinema 4D license. maxon::InternedId feature; feature.Init("net.maxon.license.app.cinema4d-release~commercial"_s) iferr_return; // Check if the given #feature is active in the current license of this instance. if (!CheckLicenseFeature(feature)) ReleasePluginLicense(userId);

      But it could very well be that it takes some time before a released license 'kicks in' in a shutdown process and that you must go further into no-mans-land than C4DPL_ENDACTIVITY (where more and more services will be shut down). Internally, we have a licensing API which has observables which communicate such events. I will bring up the subject internally if we can make the framework fully or partially public.

      Cheers,
      Ferdinand

    • kbarK

      How to set options when saving TIF file

      Cinema 4D SDK
      • 2023 c++ • • kbar
      2
      0
      Votes
      2
      Posts
      396
      Views

      ferdinandF

      Hello @kbar,

      Thank you for reaching out to us. You cannot do what you want to do from the classic API. When we use the classic API interface BaseBitmap::Save internally, we always pass nullptr or the empty container when saving a FILTER_TIF. There is unfortunately no classic API translation layer anymore for this aspect of TIFF saving.

      But you can get the underlying ImageRef with BaseBitmap::GetImageRef and then use the Image API directly to save things as you want them to be saved:

      Saving an ImageRef to Disk maxon::MEDIASESSION::TIFF::EXPORT Namespace

      Note that other than in the classic API, image data is expressed by more than one type in the maxon API. To save a plain ImageRef, you will have first to insert it into a ImageTextureRef via ::AddChildren, as only it has the ::Save method.

      Cheers,
      Ferdinand

    • kbarK

      "maxon::GenericData &extraData" is not documented

      Cinema 4D SDK
      • 2024 • • kbar
      2
      0
      Votes
      2
      Posts
      468
      Views

      ferdinandF

      Hey @kbar,

      Thank you for reaching out to us and pointing out the missing documentation. I will fix that. In the mean time I would recommend having a look at the Gradient and Field Sampling example in the migration guide, as I did explain the principal changes there.

      In short, extraData is the means with which sampling has been made const. Before, sampling did change the field instance, now the to be mutated data has been separated out into that 'extra data', and you get your extraData when initializing the sampling. In the example I covered Sample, but things translate directly to DirectSample.

      Cheers,
      Ferdinand

      Code from the migration guide:

      iferr_scope; // #field is a #FieldObject sampled by the #BaseObject #effector. See the full example for details. // The input location we want to sample and the output data. We are only interested in sampling // FIELDSAMPLE_FLAG::VALUE, i.e., the field influence value of the field at point x. FieldInput inputs(Vector(0, 50, 0)); FieldOutput outputs; outputs.Resize(inputs.GetCount(), FIELDSAMPLE_FLAG::VALUE) iferr_return; FieldOutputBlock outputBlock = outputs.GetBlock(); // Create the field info for sampling the sample data #inputs for the caller #effector. const FieldInfo info = FieldInfo::Create(effector, inputs, FIELDSAMPLE_FLAG::VALUE) iferr_return; // Sample the field. In 2024.0 we now must pass on the extra data generated by the sampling // initialization so that #field can remain const for this operation. maxon::GenericData extraData = field->InitSampling(info) iferr_return; field->Sample(inputs, outputBlock, info, extraData, FIELDOBJECTSAMPLE_FLAG::NONE) iferr_return; // Iterate over the output values. for (const maxon::Float value : outputBlock._value) ApplicationOutput("Sampled value: @", value); field->FreeSampling(info, extraData);
    • kbarK

      How to find and delete a node in a NodeGraph?

      Cinema 4D SDK
      • c++ 2023 • • kbar
      5
      0
      Votes
      5
      Posts
      1.4k
      Views

      kbarK

      @ferdinand said in How to find and delete a node in a NodeGraph?:

      Fig. I: The two IDs are displayed in the node editor info panel for the selected node. Make sure to have Preferences\Node Editor\Ids enabled to also see the node ID in addition to the asset ID.

      I didn't know about this! I have been copying and pasting the selected nodes into a text editor up until now, which in itself is a very cool feature.

    • kbarK

      How many C++ and Python devs do we have here?

      General Talk
      • • • kbar
      5
      7
      Votes
      5
      Posts
      1.4k
      Views

      Leo_SaramagoL

      I'm looking for a C++ developer. I wrote a prototype in Python that needs some love... It's meant to become a real plug-in. Yes, there's a budget. Hey, @a_block , how can I reach you? Anybody else interested? Please, reply to this, let's talk. Thanks for your time.

    • kbarK

      ActiveObjectManager_SetObject to display BaseObject in a GetListHead

      Cinema 4D SDK
      • c++ sdk • • kbar
      2
      0
      Votes
      2
      Posts
      413
      Views

      ferdinandF

      Hello @kbar,

      Thank you for reaching out to us. This is a tricky one to answer, and my first instinct was that this is not too surprising due to what you do with your GeListHead, but the devil lies in the detail.

      In general, I would say that the safest route would be the one many of our implementations take: Displaying elements that are not part of the "standardized" branches of a scene graph via a DescriptionCustomGui wrapped by a custom GUI of yours which is part of a description of a (set of) node type(s) you provide. The FieldList data type/GUI does this for example.

      Overview Simply adding a custom branch in form of a GeListHead to a node of your choice will not make this custom branch discoverable via BranchInfo. This is because there is hard-coded data in the Cinema 4D core for this branch discovery. You can of course manually traverse the branches of your node. In the Attribute Manager SetObject implementation, this hardcoded branch structure is not being checked directly as far as I can see, but the Attribute Manger modes rely implicitly on it. You can register new Attribute Manger modes with ActiveObjectManager_RegisterMode which binds than that mode to a hook as for example shown in [1] (for materials in this case), see the MESSAGEHOOK documentation for details. It shows the case for tags as used internally. The object mode case is much more complex, but it will effectively fail on AOM_MSG_GETATOMLIST in your scene setup because the traversal done there assumes objects to appear in "object " branches only - which is not true in your case. Solutions I personally would still consider the DescriptionCustomGui route the safest way, especially because the GUI has the DESCRIPTION_OBJECTSNOTINDOC flag which allows you to also display orphaned nodes. Implement your custom attribute manager mode, which can deal with your custom scene traversal structure and mark your nodes with NBIT_ACTIVE so that the hook can find them. Regarding Xpresso nodes: They have their own branches which are respected in the AM implementation. As a warning: There are also quite a few hacks in the AM for Nodes API and shader nodes, especially regarding the traversal. In general, I would consider this non-regular scene structure of yours a problem with the AM because of how often Cinema 4D internally relies on a specific makeup of branches. It could very well be that you implement your AM mode, and everything will then work fine, but I cannot guarantee that. Which is a further point why I personally would gravitate towards the first solution.

      Cheers,
      Ferdinand

      [1]:

      static GeData MaterialMessageHook(const BaseContainer &msg, void *data) { switch (msg.GetId()) { case AOM_MSG_ISENABLED: return true; case AOM_MSG_GETATOMLIST: { BaseDocument *doc = GetActiveDocument(); if (!doc) break; doc->GetActiveMaterials(*((AtomArray*)data)); return true; } break; } return false; }
    • kbarK

      DragDrop Model from UserArea into Viewport or Object Manager

      Bugs
      • c++ r20 s26 sdk • • kbar
      2
      0
      Votes
      2
      Posts
      914
      Views

      M

      Hi Kent, so far for the moment the viewport drop operation are more related to scene management rather than scene creation. By that I means except for an asset being loaded which create new elements (scene, object, material, etc...) other drag command are just here to act on the active object.

      So regarding drag operation for file, only DRAGTYPE_FILENAME_IMAGE is allowed and an object should be selected, then a texture tag will be applied to this object and a new material with the texture will be automatically assigned. DRAGTYPE_FILENAME_SCENE is not supported.

      For DRAGTYPE_ATOMARRAY it is only allowed for some particular categories, like layers to be applied on the active object or even materials for the same condition, so in any case the layer/material should already be part of the scene.

      So for the moment the only workaround would be to create your own temporary asset and pass this asset to be inserted into the document. For more information about the asset API I let you read Asset API - Handbook but this is S26.0+ only.

      Cheers,
      Maxime.

    • kbarK

      maxon::Url 206 partial content

      Cinema 4D SDK
      • c++ r20 s26 • • kbar
      7
      0
      Votes
      7
      Posts
      1.3k
      Views

      ferdinandF

      Hey @kbar,

      sure, no pressure and that all sounds reasonable, I was just offering options. And to be clear here: I am not optimistic for this being user fixable. But you never know for sure until you have tried.

      Cheers,
      Ferdinand

    • kbarK

      How to find the CallCommand id for Redshift 'Convert and Replace with Nodes'

      Cinema 4D SDK
      • c++ r25 sdk • • kbar
      6
      0
      Votes
      6
      Posts
      1.0k
      Views

      ferdinandF

      Hey @everyone,

      Yes, the Script Log can be quite handy, especially in cases like these where no symbols do exist. But one should also keep in mind that integer identifiers can sometimes change, and we do not publish such information then. It is therefore best to use the symbols when they exist, as doing so will avoid that problem.

      Cheers,
      Ferdinand

    • kbarK

      Programmatically create a palette?

      Cinema 4D SDK
      • c++ sdk • • kbar
      4
      0
      Votes
      4
      Posts
      1.4k
      Views

      ferdinandF

      Hello @ECHekman,

      It is very unlikely that this will ever change unless we do a fundamental rewrite of our UI core (which itself is not that unlikely but there are no current concrete plans or an ETA, Cinema 4D could keep using its current UI core for another decade).

      What Redshift, or more concretely things like the foreground object, are doing, is not loading or modifying palettes. They are modifying the state of the command via CMD_HIDDEN. For things where you usually do not have control over the command implementation, you can register a CommandGetStateDelegate for a specific command ID. This delegate will be called whenever the state of the command is queried, and you can then modify the state as you see fit.

      Cheers,
      Ferdinand

      Code // Demonstrates how to register a CommandGetStateDelegate for a specific command ID, allowing us to // override the CommandData::GetState behavior of the command, i.e., how its enabled/checked/ // hidden (and more) behavior is. // // Doing this is usually only necessary if the command implementation is not under our control, as // for example, for scene elements (NodeData, ObjectData, etc.) where we usually do not implement the // command ourselves but let Cinema 4D handle it. // // NEVER IMPLEMENT ANY STATE DELEGATES FOR COMMANDS THAT YOU DO NOT OWN. // This is the state handler for the foreground object command. It will hide the command if the active // renderer is Redshift. namespace maxon { MAXON_DECLARATION_REGISTER(CommandGetStateDelegates, NumToString<Oforeground>::value) { CommandGetStateDelegate delegate = [](cinema::BaseDocument* doc) -> Int32 { Int32 state = cinema::CMD_ENABLED; if (doc) { cinema::RenderData* rd = doc->GetActiveRenderData(); if (rd) { const Bool isRedshiftActiveRenderer = rd->GetDataInstance()->GetInt32(RDATA_RENDERENGINE) == VPrsrenderer; if (isRedshiftActiveRenderer) state |= cinema::CMD_HIDDEN; } } return state; }; return delegate; } } // namespace maxon
    • kbarK

      How to open Script Manager and set what Script it is showing?

      Cinema 4D SDK
      • c++ • • kbar
      3
      0
      Votes
      3
      Posts
      452
      Views

      mikeudinM

      @kbar I think much better to create your own Edit Script dialog with blackjack and... Save and Execute Buttons. Use GeDialog.AddMultiLineEditText with a flags DR_MULTILINE_SYNTAXCOLOR and DR_MULTILINE_PYTHON.

    • kbarK

      Ray Tracing In One Weekend

      Cinema 4D SDK
      • c++ • • kbar
      4
      3
      Votes
      4
      Posts
      794
      Views

      fwilleke80F

      Cool! Thanks for your community work, Kent!

    • kbarK

      Add Database to the Asset Browser

      Cinema 4D SDK
      • c++ r25 s26 sdk • • kbar
      2
      0
      Votes
      2
      Posts
      425
      Views

      ferdinandF

      Hey @kbar,

      thank you for reaching out to us. How to add asset databases and others things are all explained in the Asset API Handbook. Your specific case is dealt with in the example Add User Databases.

      You can technically also take a route via the Asset Browser preferences in the Cinema 4D Preferences dialog and the GUI gadget showing these database entries, completely ignoring the Asset API, but I would not recommend doing this.

      Cheers,
      Ferdinand