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

    Error when removing bound joints

    Cinema 4D SDK
    c++ 2023
    2
    4
    748
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • CJtheTigerC
      CJtheTiger
      last edited by

      Requirement

      • C++ object plugin creates joints under the plugin object.
      • Properties on the plugin object define the joints hierarchy and properties.
      • Changing the properties should delete and re-create the joints.
      • The user may bind the joints to geometry. Weights do not have to persist upon re-creation of the joints.

      Issue

      • When the joints are bound to geometry the plugin crashes upon removing the joints via code. No specific error message is provided.
      • Removing the joints from the weight tag or deleting the weight tag on the geometry prevents the error from occuring.

      Code

      The joints are being removed using this code:

      BaseObject* child = op->GetDown();
      while (child)
      {
          child->Remove();
          child = op->GetDown();
      }
      

      This code is either executed from the Message or Main thread.

      What can I do to prevent the error from occuring or analyzing this error further?

      Cinema 4D 2023.1.3

      1 Reply Last reply Reply Quote 0
      • CJtheTigerC
        CJtheTiger
        last edited by

        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.

        1 Reply Last reply Reply Quote 1
        • M
          m_adam
          last edited by

          Hi @CJtheTiger, sorry for the delay took me some time to properly understand everything.
          First of all with the next release it does not crash anymore.

          With 2023.1 it still does and the only way would be to either as you did remove the weight tag or call AddUndo(UNDOTYPE_DELETEOBJ) before you remove a bone. With that said taking in consideration your setup creating an undo is not something you would want (at least I think).
          Internally the weight tags, cache the joint list and re-use it so that's why it was crashing (due to a missing nullptr check). But with the next version this is properly handled so it does not crash anymore. Still to properly notify the weight tag that a bones needs to be removed you need to add an undo UNDOTYPE_DELETEOBJ. So the best option would be to to manually delete your bones from all weight tags with something like:

          typedef Bool(*IterationCallback)(BaseObject* op);
          void RecurseHierarchy(BaseObject* op, IterationCallback callback)
          {
          	while (op)
          	{
          		if (callback(op))
          		RecurseHierarchy(op->GetDown(), callback);
          		op = op->GetNext();
          	}
          }
          
          void AdvancedIkSpline::clear(BaseObject* op)
          {
          	BaseObject* directChild = op->GetDown();
          	while (directChild)
          	{
          		RecurseHierarchy(directChild, [](BaseObject* child) {
          			CAWeightTag* weightTag = nullptr;
          			Int32 dummy;
          
          			if (child->GetType() != Ojoint)
          				return true;
          
          			weightTag = static_cast<CAJointObject*>(child)->GetWeightTag(dummy);
          
          			// Remove from all Weight Tags
          			while (weightTag)
          			{
          				weightTag->RemoveJoint(child);
          				weightTag = static_cast<CAJointObject*>(child)->GetWeightTag(dummy);
          			}
          
          			return true;
          		});
          
          		directChild->Remove();
          		directChild = op->GetDown();
          	}
          }
          

          In any case I would say the workflow is a bit wanky, and you have to understand Cinema 4D was never designed to support that an object create/delete objects in the scene.

          Cheers,
          Maxime.

          MAXON SDK Specialist

          Development Blog, MAXON Registered Developer

          1 Reply Last reply Reply Quote 1
          • CJtheTigerC
            CJtheTiger
            last edited by

            Thank you very much Maxime, both for the solution and the explanation. The code works perfectly. Also thanks for fixing this bug. Out of curiosity: Was this causing issues anywhere else?

            For completion sake: I do need to add a directChild->Free() after directChild->Remove(), correct?

            Still gonna mark this as answered as the core issue has been solved with flying colors. Thanks again!

            1 Reply Last reply Reply Quote 0
            • First post
              Last post