Make editable returning strangely



  • 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



  • 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.



  • 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



  • 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.



  • 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?



  • 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



  • 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?



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

    Cheers
    Manuel



  • 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



  • I understand, that makes sense to me.

    Thank you for the help.

    Dan


Log in to reply