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

    Make editable returning strangely

    Cinema 4D SDK
    r20 c++
    2
    10
    1.5k
    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.
    • D
      d_schmidt
      last edited by

      Hello! I'm working on a Object Plugin that I want to take an entire spline hierarchy and return a modified output. I was running into a problem though that when I use Make Editable (using the C key), it is only returning the first element in the hierarchy. I stripped it all the way down to this code and it's still happening. I used the following python code on it and it was able to return the correct hierarchy along with being live in the viewport. The only issue is when it is made editable.

      My python script's output is at the top, with the result of me making the plugin editable at the bottom.
      Screen Shot 2019-05-16 at 7.18.54 PM.png Screen Shot 2019-05-16 at 7.19.02 PM.png

      #include "c4d.h"
      #include "c4d_symbols.h"
      #include "c4d_general.h"
      
      class SimpleTest : public ObjectData
      {
          INSTANCEOF(SimpleTest, ObjectData)
      public:
          
          
          virtual Bool Init(GeListNode *node);
          
          virtual BaseObject* GetVirtualObjects(BaseObject *op, HierarchyHelp *hh);
          static NodeData *Alloc() { return NewObjClear(SimpleTest); }
           void CheckDirty( BaseObject* op,BaseDocument* doc);
          void HierarchyIterator(BaseObject* obj, maxon::BaseArray<BaseObject*>* objectlist);
          SplineObject* GetContour(BaseObject *op,BaseDocument *doc,Float lod,BaseThread *bt);
          
          Int32 childContourDirty;
          Int32 childGVODirty;
      };
      
      void SimpleTest::HierarchyIterator(BaseObject* obj, maxon::BaseArray<BaseObject*>* objectlist)
      {
          while (obj != nullptr)
          {
              
              
              HierarchyIterator(obj->GetDown(), objectlist);
              obj = obj->GetNext();
          }
          
      }
      
      void SimpleTest::CheckDirty( BaseObject* op,BaseDocument* doc)
      {
          BaseObject* child = op->GetDown();
          if(child == nullptr)
          {
              childContourDirty = -1;
              op->SetDirty(DIRTYFLAGS::DATA);
              return;
          }
          Int32 childDirty = child->GetDirty(DIRTYFLAGS::DATA | DIRTYFLAGS::MATRIX | DIRTYFLAGS::CACHE);
          
          
          if( childDirty != childContourDirty)
          {
              childContourDirty = childDirty;
              op->SetDirty(DIRTYFLAGS::DATA);
          }
      }
      BaseObject* SimpleTest::GetVirtualObjects(BaseObject *op, HierarchyHelp *hh)
      {
          
          if (op == nullptr || hh==nullptr)
          {
              return BaseObject::Alloc(Onull);
          }
          
          BaseObject* childspline = op->GetDown();
          
          if (childspline == nullptr)
          {
              SplineObject* temp = SplineObject::Alloc(0, SPLINETYPE::LINEAR);
              
              return temp;
          }
          
          Bool opDirty = op->IsDirty(DIRTYFLAGS::DATA | DIRTYFLAGS::MATRIX);
          Int32 childDirty = childspline->GetDirty(DIRTYFLAGS::DATA |DIRTYFLAGS::MATRIX | DIRTYFLAGS::CACHE);
          
         
          if (childDirty ==childGVODirty &&  !opDirty)
          {
              
              return op->GetCache();
          }
          op->NewDependenceList();
          op->AddDependence(hh, childspline);
          Bool dirty = FALSE;
          if (!dirty)
          {
              dirty = op->CheckCache(hh);
          }
          if (!dirty)
          {
              dirty = op->IsDirty(DIRTYFLAGS::DATA | DIRTYFLAGS::MATRIX);
              
          }
          if (!dirty)
          {
              dirty = !op->CompareDependenceList();
          }
          if (!dirty)
          {
              
              return op->GetCache(hh);
          }
          
          if (op->GetDown()!= nullptr)
          {
              SplineObject*obj =static_cast<SplineObject*>( op->GetDown()->GetClone(COPYFLAGS::NONE, nullptr));
              
            
              return obj;
          }
          return BaseObject::Alloc(Onull);
          
          
      }
      
      
      
      SplineObject* SimpleTest::GetContour(     BaseObject *      op,
                                           BaseDocument *      doc,
                                           Float      lod,
                                           BaseThread *      bt
                                           )
      {
          
          if (op->GetDown()!= nullptr)
          {
              SplineObject*obj =static_cast<SplineObject*>( op->GetDown()->GetClone(COPYFLAGS::NONE, nullptr));
              return obj;
          }
          SplineObject* temp = SplineObject::Alloc(0, SPLINETYPE::LINEAR);
          
          return temp;
          
          
      }
      
      
      Bool SimpleTest::Init(GeListNode *node)
      {
          BaseObject        *op = (BaseObject*)node;
          if (!op)
          {
              return FALSE;
          }
          
           childContourDirty = 0;
           childGVODirty = -1;
          return TRUE;
      }
      
      
      
      
      
      Bool RegisterSimpleTest()
      {
          AutoAlloc<BaseBitmap> bases;
          Filename bg;
          
          return RegisterObjectPlugin(1052851, "Simple Test"_s, OBJECT_GENERATOR| OBJECT_INPUT| OBJECT_ISSPLINE , SimpleTest::Alloc, "Simple Test"_s, bases, 0);
      }
      
      

      Python Script

      import c4d
      from c4d import gui
      
      # Main function
      def main():
          doc.InsertObject(op.GetCache().GetClone())
          c4d.EventAdd()
      
      # Execute main()
      if __name__=='__main__':
          main()
      

      I'm not really sure the issue, I've had trouble with caches in the past and any help would be greatly appreciated.

      Dan

      1 Reply Last reply Reply Quote 0
      • ManuelM
        Manuel
        last edited by

        hello,

        @d_schmidt is this related to this topic ?

        What i can tell is that the function GetContour is the one used when you edit the generator, and it only return one object and not a hierarchy. If you want to return a spline you have to merge all the spline you want in different segment.

        I don't understand what is your goal here (your code seem to be the result of lot's of test) so i can't really tell if you should only use GetVirtualObject or not even overload it.

        Can you provide a bit more information about your goal here, if you just want to modify the spline, why you didn't created a modifier ?

        Cheers
        Manuel.

        MAXON SDK Specialist

        MAXON Registered Developer

        D 1 Reply Last reply Reply Quote 0
        • D
          d_schmidt @Manuel
          last edited by

          Hi Manuel,

          It's based on the topic you linked, but I thought it was a self contained issues so I created a new thread. Sorry if I should have continued that thread.

          In regards to:

          What i can tell is that the function GetContour is the one used when you edit the generator, and it only return one object and not a hierarchy. If you want to return a spline you have to merge all the spline you want in different segment.

          What would be the best why to merge them? Just so I do it correctly.

          Can you provide a bit more information about your goal here, if you just want to modify the spline, why you didn't created a modifier ?

          My overall goal is more complicated. The end goal I'm working towards is being able to get all of the points of every object in the hierarchy underneath the plugin, regardless of object type. I would want to be able to know which points came from which object and able to do things like get polygons from polygon objects and the segments from splines. After getting all of that data I would generate a spline output.

          It's all a lot more complicated than I thought it would be though and I've been having quite a bit of trouble making the parts of it work. Hopefully that clears up what I'm looking to do!

          Thanks for the help!
          Dan

          1 Reply Last reply Reply Quote 0
          • ManuelM
            Manuel
            last edited by

            hello,

            As you said, your goal is not an easy one.

            If you want to merge the splines, you can create an "parent spline", walk trough the hierarchy and for each spline/object, add a segment to your parent spline and copy / paste all the points position in global space

            Issue you will find is that your spline can have different mode (bezier, cubic, linear ....) Of course if you only want to get the verticies position, it's not a problem anymore.

            For tracking the original point, there's no direct solution. You have to build something of your own.

            That said, i'm not sure you need to track the points. You can just walk the hierarchy and do your get polygon or segment. Storing the result in a BaseArray that you will use at the end to build your spline or whatever you want your generator to return ?

            Cheers
            Manuel.

            MAXON SDK Specialist

            MAXON Registered Developer

            1 Reply Last reply Reply Quote 0
            • D
              d_schmidt
              last edited by

              Hi Manuel,

              I think I understand! Definitely a few limitations but it seems doable.

              I had a follow up question about how the Text object behaves in Cinema, since making it editable can return multiple splines. When Separate Letters is checked the object returns multiple splines underneath a null, but not when the checkbox is off. Would that be via GVO() or GetContour()? Does the function that gets called depend on the Seperate Letters checkbox?

              Text Test.c4d

              Additionally when a Text object is made editable when Separate Letters is checked it no longer works underneath an Extrude object, which makes sense because of the null. But it works when its before its been made editable. Is this just because the null doesn't exist internally?

              1 Reply Last reply Reply Quote 0
              • ManuelM
                Manuel
                last edited by

                Hello,
                sorry for the delay, I have to dive a bit in the code.

                The TextSpline only use GetContour() while Mograph Text only use GetVirtualObject()

                The object Text Spline always return a single spline with segments. (even if PRIM_TEXT_SEPARATE is true)
                But :
                When you use "MakeEditable", there's a special case, if it's Osplinetext and PRIM_TEXT_SEPARATE is true, it does regenerate the spline and this time it return a hierarchy.

                In your GetContour(), if you return something else than a SplineObject (by casting the object), Cinema4D will crash. (it need function specific to a spline) and as we already know, it doesn't take into account the hierarchy.

                On the extrude you can activate the "hierarchical". (and now we know the text spline always return a single spline it does make sense you only need this option when you edit the object)

                About your project, something you can have a look into is Mesh Attributes and DataType If you create your own "merge" function you can be in charge to also copy / paste point information stored there.

                Cheers
                Manuel

                MAXON SDK Specialist

                MAXON Registered Developer

                D 1 Reply Last reply Reply Quote 1
                • D
                  d_schmidt @Manuel
                  last edited by

                  Hi Manuel, no worry about the wait! Thanks for the help.

                  When you say that there is a special case for the Text spline "Make Editable", do you mean core unique Cinema functionality? That's not something I can replicate, right?

                  1 Reply Last reply Reply Quote 0
                  • ManuelM
                    Manuel
                    last edited by Manuel

                    exactly, this is unique and can't be replicated.

                    Cheers
                    Manuel

                    MAXON SDK Specialist

                    MAXON Registered Developer

                    1 Reply Last reply Reply Quote 0
                    • ManuelM
                      Manuel
                      last edited by

                      hello,

                      just to be clear :

                      When i'm saying it can't be replicated, i'm talking about GetContour() can't return a hierarchy.

                      But GVO can. This is what the moText is doing, using GVO and not GetContour()

                      Cheers
                      Manuel

                      MAXON SDK Specialist

                      MAXON Registered Developer

                      1 Reply Last reply Reply Quote 0
                      • D
                        d_schmidt
                        last edited by

                        I understand, that makes sense to me.

                        Thank you for the help.

                        Dan

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