Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python 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. CJtheTiger
    3. Best
    • Profile
    • Following 0
    • Followers 0
    • Topics 17
    • Posts 53
    • Best 6
    • Controversial 0
    • Groups 0

    Best posts made by CJtheTiger

    • Free Python Plugin: Quad Disc

      Quad Disc

      After more time than I'd like to admit I'd like to show you my Quad Disc plugin.
      The plugin creates a primitive disc which consists solely of quads. No more triangles, no more weird deformations with Deformers, no more artefacts when using a Subdivision Surface.
      ccc1308d-8e89-4c89-aeb0-c0521b3d458c-Cinema_4D_m3jQZixz2X.gif
      https://github.com/YoYoFreakCJ/C4D-QuadDisc

      Installation and Usage

      Installation and usage instructions are in the GitHub readme.

      Comment

      Why not simply use a default Disc with a Remesher you ask? Because that would trigger a remesh everytime the radius of the disc changes, and controlling the poly count would be annoying. I ran into this a lot with a rig I'm working on right now, and that's why I created this plugin.

      I hope something like this will ship natively with a future C4D version. Feel free to steal this code. Just don't sell it.

      posted in General Talk plugin-information download
      CJtheTigerC
      CJtheTiger
    • RE: Error when removing bound joints

      Addition

      The error does not occur immediately when Remove is being called but after all operations of the plugin are finished and Cinema 4D takes over again.

      Code

      I uploaded the code to GitHub:
      https://github.com/YoYoFreakCJ/C4D-AdvancedIkSpline
      Note: the framework code is excluded.

      To reproduce the issue with this code:

      1. Build and run the plugin.
      2. In C4D in the Extensions menu choose Advanced IK Spline.
      3. In the Advanced IK Spline change the mode to Bind to make the joints show up in the object manager.
      4. Bind the joints to any geometry.
      5. In the Advanced IK Spline change the mode back to Setup.
      6. Change any of the parameters (e.g. Width).

      The plugin will crash after this.

      posted in Cinema 4D SDK
      CJtheTigerC
      CJtheTiger
    • RE: Register to object change

      I would like to add the solution I chose to close this topic.

      The Tag Solution did indeed work very well. Execute got called plenty of times and I was easily able to filter for the change of the object I was looking for.

      But what I actually did was create a whole new class deriving from ObjectData and listen to the message MSG_DESCRIPTION_POSTSETPARAMETER to perform my actions right then. In the first post I said that my plugin creates a null. I replaced all those nulls with my new ObjectData class. So my object hierarchy is similiar to this:

      • MainPluginObject : ObjectData -> Needs to be accessed by HelperObject.
        • HelperObject : ObjectData -> Accesses MainPluginObject in its Message function.

      Also note that thread awareness is required.

      The reason I chose this structure this is the following:

      I would like the user to Current State to Object my MainPluginObject. Before that the HelperObject might not be visible in the object manager depending on the values of some properties in MainPluginObject. But once CSTO is called I want all objects to be shown in the object manager. If I had chosen the Tag Solution the user might delete the tag by accident and break everything. Now of course the user can still break things by deleting or moving the HelperObject out of the hierarchy of MainPluginObject but this I already have to validate anyways. Having a similiar check in a tag just adds another point of error which I'd like to avoid.

      So I'll mark this as my answer after taking everything @ferdinand said into consideration.

      Again, thank you very much for your assistance! You never let us down! ❤

      posted in Cinema 4D SDK
      CJtheTigerC
      CJtheTiger
    • RE: NewObj error: no suitable conversion

      Hi @i_mazlov,

      no wonder I felt like I was missing something! And now that the iferr_scope is declared I have to bubble it up all the way and that's how I'll get proper error handling. Sweet!

      To be honest I read about error handling before but was hoping I could skip it during the prototyping phase. But now that I gotta do it, once I'm out of prototyping it'll even be a lot more stable. Plus I also gotta learn about References now which is probably a good idea.

      2c37be53-a3ce-4695-afdb-ab8d3410d19b-image.png

      Thanks for the quick help! Have a nice rest of the day!

      Best wishes,

      CJ

      posted in Cinema 4D SDK
      CJtheTigerC
      CJtheTiger
    • RE: Python: Localized Plugin Name

      It seems like I found the working combination.

      The STRINGTABLE in res\strings_en-US\c4d_strings.str must not be named. In my previous response I pasted the contents which as you can see started with STRINGTABLE omyobject whereas it should simply be STRINGTABLE without a name.

      • I guess this str-file cannot contain named STRINGTABLEs. My first suspicion was that the error was caused by trying to define two STRINGTABLEs with the same name (since I had another STRINGTABLE with that name in the description folder) but even choosing another name in the c4d_strings.str resulted in the same error. Only when removing the name did I get rid of the error.

      I added the plugin ID to both the res\c4d_symbols.h and the res\description\omyobject.h as an enum member called Omyobject.

      • Having the ID in res\c4d_symbols.h allows for having a value outside of description resources (i.e. dialogs) which I required for the plugin name, as @m_adam already explained.
      • Having the ID in res\description\omyobject.h allows for description resources to access an accordingly named value in the STRINGTABLE in res\strings_xx-XX\description\omyobject.str. It also defines c4d.Omyobject which I'm now using in c4d.plugins.RegisterObjectPlugin to access the plugin name in res\strings_xx-XX\c4d_strings.str.
        • Note that this requires the plugin ID to be defined in two places (res\c4d_symbols.h and res\description\omyobject.h) which decreases maintainability.
        • Also note that I'm using the plugin ID from the description header to get a value from a non-description STRINGTABLE which sure enough does work but is probably not the cleanest solution.

      Does this sort of sound right? Is this the intended way?

      posted in Cinema 4D SDK
      CJtheTigerC
      CJtheTiger
    • RE: How to properly load async data into C++ generator plugin?

      Good morning @Havremunken,

      Is there a particular message I am listening for? Or is there another way to be notified of a parameter change outside of GetVirtualObjects?

      In order to listen to parameter changes you can implement the Message function in your plugin and listen for the MSG_DESCRIPTION_POSTSETPARAMETER message. Cast the incoming data argument to DescriptionPostSetValue to extract the ID of the changed parameter and get the value through the node argument.

      Sample code taken from here and adjusted slightly:

      Bool OMyPlugin::Message(GeListNode* node, Int32 type, void* data) {
          BaseContainer* bc;
          ...
          if (type == MSG_DESCRIPTION_POSTSETPARAMETER)
          {
              // Get message data
              DescriptionPostSetValue* dparm = (DescriptionPostSetValue*)data;
              Int32 parameterId = (*(dparm->descid))[0].id;
              bc = static_cast<BaseObject*>(node)->GetDataInstance();
      
              switch (parameterId)
              {
              case FILE_PATH: // Check for the parameter ID of the file path parameter.
                  // Load the file via bc->GetString(FILE_PATH).
                  ApplicationOutput(bc->GetString(FILE_PATH));
                  break;
              }
          }
          ...
      }
      

      This way you could also initiate the cancellation of the current loading process in case the file path is being changed while a file is already being loaded. Alternatively you could lock the parameter in the description using GetDEnabling while the file is being loaded.

      From a UX point of view I recommend indicating the current processing status to the user so the user knows whether a file is loading or if the loading has finished/failed.

      And a personal flavor hint: I'm used to providing control buttons (Load/Start/Import/... and Cancel) for potential long running operations. This way it is clear and intuitive to the user how to use your object.

      Cheers,
      Daniel

      posted in Cinema 4D SDK
      CJtheTigerC
      CJtheTiger