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

    Saving and Loading an AtomArray?

    SDK Help
    0
    7
    580
    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.
    • H
      Helper
      last edited by

      On 31/01/2013 at 04:07, xxxxxxxx wrote:

      User Information:
      Cinema 4D Version:   R10-R14 
      Platform:   Windows  ;   Mac OSX  ; 
      Language(s) :     C++  ;

      ---------
      In my latest plugin, the user can drag-and-drop a set of Point Selection or Polygon Selection tags as a way to denote the groups on a polygon object.  These are stored in a persistent AtomArray and displayed by name in a SimpleListView in a GeDialog associated with a Tag plugin.  When the document is saved, I would like the my plugin tag to retain a reference to these selection tags (with Write/Read).  I could go the naive route and simply write the names but it would be better if I could write BaseLinks or something like that.  Since Hyperfile has no WriteLink() or similar, what alternative is there?  Could I set up a BaseContainer and fill it with the links using SetLink() and then use the links on read to reestablish the elements in the AtomArray.

      A bit convoluted but your ideas are much appreciated!

      Thanks,

      1 Reply Last reply Reply Quote 0
      • H
        Helper
        last edited by

        On 31/01/2013 at 04:45, xxxxxxxx wrote:

        Hi Robert,

        Have you considered converting the references to BaseLinks when writing, then reading
        BaseLinks from the HyperFile again and converting them back into the AtomArray?

        Some pseudo code for the reading mechanism (because I don't have the SDK with me) :

            Bool MyTagData::Read(GeListNode\* node, HyperFile\* hf) {
                if (!TagData::Read(node, hf))
                    return FALSE;
        
                LONG count;
                if (!hf->ReadLong(&count)) return FALSE;
                if (count < 0) return FALSE;
        
                if (this->array)
                    this->array->Flush();
                else
                    this->array = AtomArray::Alloc();
        
                BaseDocument\* doc = node->GetDocument();
                BaseLink\* link = BaseLink::Alloc();
                for (LONG i=0; i < count; i++) {
                    if (!link->Read(hf)) {
                        BaseLink::Free(link);
                        return FALSE;
                    }
        
                    C4DAtomGoal\* goal = link->GetLink(doc);
                    this->array->Append(goal);
                }
        
                BaseLink::Free(link);
                return TRUE;
            }
        

        I'm pretty sure this code won't compile, but I hope it can demonstrate what my approach was.

        Best,
        Nik

        1 Reply Last reply Reply Quote 0
        • H
          Helper
          last edited by

          On 31/01/2013 at 05:45, xxxxxxxx wrote:

          That's why I was asking. 😉

          I could allocate an array of BaseLinks with atomarray->GetCount() elements and SetLink() each.  Will have to see how robust this is.

          Thanks!

          1 Reply Last reply Reply Quote 0
          • H
            Helper
            last edited by

            On 31/01/2013 at 05:47, xxxxxxxx wrote:

            Hi Robert,

            You can indirectly save BaseLinks in a HyperFile with HyperFile::WriteGeData().

            1 Reply Last reply Reply Quote 0
            • H
              Helper
              last edited by

              On 31/01/2013 at 10:07, xxxxxxxx wrote:

              So far, no go.  I am not getting the BaseLinks read back in.  Here is the code:

              // NodeData.Read - Read data from HyperFile  
              //*---------------------------------------------------------------------------*  
              Bool SymMorphyTag::Read(GeListNode* node, HyperFile* hf, LONG level)  
              //*---------------------------------------------------------------------------*  
              {  
                if (!node)                return FALSE;  
                if (!hf)                return FALSE;  
                BaseContainer*    bc =    ((BaseTag* )node)->GetDataInstance();  
                if (!bc)                return MessageSystem::Throw(GeLoadString(KDZERR_GENERAL), "SymMorphyTag.Read.bc");  
                if (bodypartArray)  
                {  
                    LONG        vcnt =                    bc->GetLong(TSYMMORPHY_BODYPARTCOUNT);  
                    if (vcnt)  
                    {  
                        BaseDocument*    doc =    hf->GetDocument();  
                        if (!doc)                return MessageSystem::Throw(GeLoadString(KDZERR_GENERAL), "SymMorphyTag.Read.doc");  
                        BaseLink*        bpBL =    BaseLink::Alloc();  
                        if (!bpBL)  
                        {  
                            bc->SetLong(TSYMMORPHY_BODYPARTCOUNT, 0L);  
                            return MessageSystem::Throw(GeLoadString(KDZERR_MEMORY), "SymMorphyTag.Read.bpBL");  
                        }  
                        BaseList2D*        bl2d =    NULL;  
                        for (LONG i = 0L; i != vcnt; ++i)  
                        {  
                            if (!bpBL->Read(hf))  
                            {  
                                BaseLink::Free(bpBL);  
                                return MessageSystem::Throw(GeLoadString(KDZERR_FILE), "SymMorphyTag.Read.bpBL");  
                            }  
                            bl2d =        bpBL->GetLink(doc);  
                            if (bl2d)  
                            {  
                                // NOT GETTING ANY GEPRINTS!!!!  
                                GePrint(bl2d->GetName());  
                                if (!bodypartArray->Append(bpBL->GetLink(doc)))  
                                {  
                                    BaseLink::Free(bpBL);  
                                    return MessageSystem::Throw(GeLoadString(KDZERR_FILE), "SymMorphyTag.Read.bodypartArray.Append");  
                                }  
                            }  
                        }  
                        BaseLink::Free(bpBL);  
                    }  
                    else MessageSystem::Throw(GeLoadString(KDZERR_GENERAL), "SymMorphyTag.Read.bodypartArray.Count");  
                }  
                return TRUE;  
              }  
              // NodeData.Write - Write data to HyperFile  
              //*---------------------------------------------------------------------------*  
              Bool SymMorphyTag::Write(GeListNode* node, HyperFile* hf)  
              //*---------------------------------------------------------------------------*  
              {  
                if (!node)                return FALSE;  
                if (!hf)                return FALSE;  
                BaseContainer*    bc =    ((BaseTag* )node)->GetDataInstance();  
                if (!bc)                return MessageSystem::Throw(GeLoadString(KDZERR_GENERAL), "SymMorphyTag.Write.bc");  
                if (bodypartArray)  
                {  
                    LONG        vcnt =                        bodypartArray->GetCount();  
                    if (vcnt)  
                    {  
                        BaseLink*        bpBL =    BaseLink::Alloc();  
                        if (!bpBL)                return MessageSystem::Throw(GeLoadString(KDZERR_MEMORY), "SymMorphyTag.Write.bpBL");  
                        for (LONG i = 0L; i != vcnt; ++i)  
                        {  
                            bpBL->SetLink((C4DAtomGoal* )bodypartArray->GetIndex(i));  
                            if (!bpBL->Write(hf))  
                            {  
                                BaseLink::Free(bpBL);  
                                return MessageSystem::Throw(GeLoadString(KDZERR_FILE), "SymMorphyTag.Write.bpBL");  
                            }  
                        }  
                        BaseLink::Free(bpBL);  
                        bc->SetLong(TSYMMORPHY_BODYPARTCOUNT, vcnt);  
                    }  
                }  
                return TRUE;  
              }
              
              1 Reply Last reply Reply Quote 0
              • H
                Helper
                last edited by

                On 31/01/2013 at 11:12, xxxxxxxx wrote:

                Hello Robert,

                I think at the point the object is read, the tags have not been read yet, although the links would
                be valid. You can read them, but you have to evaluate them at a later time, for example at the
                first message sent to your object after reading was done.

                /**
                 * Copyright (C) 2013, Niklas Rosenstein
                 * You are allowed to use and/or modify this code for private or
                 * commercial use.
                 **/
                  
                #include <c4d.h>
                #include <ge_dynamicarray.h>
                  
                class TestObject : public ObjectData {
                  
                    public:
                  
                    LONG count;
                    BaseLink** array;
                  
                    static NodeData* Alloc() { return gNew TestObject; }
                  
                    TestObject() : ObjectData(), array(NULL) {
                    }
                  
                    ~TestObject() {
                        if (array) {
                            for (LONG i=0; i < count; i++) {
                                BaseLink::Free(array[i]);
                            }
                            GeFree(array);
                            array = NULL;
                        }
                    }
                  
                    // Overrides: ObjectData
                  
                    Bool Message(GeListNode* node, LONG type, void* pData) {
                        if (!ObjectData::Message(node, type, pData)) return FALSE;
                  
                        if (array) {
                            BaseDocument* doc = node->GetDocument();
                            GeDebugOut("%d BaseLinks were read in!", count, type);
                  
                            for (LONG i=0; i < count; i++) {
                                BaseLink* link = array[i];
                                BaseTag* tag = (BaseTag* ) link->GetLink(doc);
                                BaseLink::Free(link);
                  
                                if (tag) {
                                    // Requires a DEBUG build!
                                    GeDebugOut("    - " + tag->GetName());
                                }
                                else {
                                    GeDebugOut("    - <NULL>");
                                }
                            }
                            GeFree(array);
                            array = NULL;
                        }
                  
                        return TRUE;
                    }
                  
                    Bool Read(GeListNode* node, HyperFile* hf, LONG level) {
                        if (!ObjectData::Read(node, hf, level)) return FALSE;
                        if (!hf->ReadLong(&count)) return FALSE;
                  
                        if (array) {
                            GeFree(array);
                        }
                        array = (BaseLink** ) GeAlloc(sizeof(BaseLink** ) * count);
                        if (!array) return FALSE;
                  
                        for (LONG i=0; i < count; i++) {
                            BaseLink* link = BaseLink::Alloc();
                            if (!link) return FALSE;
                            if (!link->Read(hf)) {
                                BaseLink::Free(link);
                                return FALSE;
                            }
                  
                            array[i] = link;
                        }
                  
                        return TRUE;
                    }
                  
                    Bool Write(GeListNode* node, HyperFile* hf) {
                        if (!ObjectData::Write(node, hf)) return FALSE;
                  
                        AutoAlloc<AtomArray> tags;
                        AutoAlloc<BaseLink> link;
                        if (!tags || !link) return FALSE;
                  
                        // Fill the *tags* array with all tags on the host object.
                        BaseTag* tag = ((BaseObject* )node)->GetFirstTag();
                        while (tag) {
                            tags->Append(tag);
                            tag = tag->GetNext();
                        }
                  
                        // Write the number of tags to the file.
                        LONG count = tags->GetCount();
                        if (!hf->WriteLong(count)) return FALSE;
                  
                        // Write the tag-links to the file.
                        for (LONG i=0; i < count; i++) {
                            tag = (BaseTag* ) tags->GetIndex(i);
                            link->SetLink(tag);
                            link->Write(hf);
                        }
                  
                        return TRUE;
                    }
                  
                };
                  
                Bool PluginStart() {
                    return RegisterObjectPlugin(
                        1000001, "BaseLink Writer", 0, TestObject::Alloc, "", NULL, 0);
                }
                Bool PluginMessage(LONG type, void* pData) {
                    return TRUE;
                }
                  
                void PluginEnd() {
                }
                

                Best,
                Niklas


                1 Reply Last reply Reply Quote 0
                • H
                  Helper
                  last edited by

                  On 31/01/2013 at 22:00, xxxxxxxx wrote:

                  That the tags have not been read into the document yet has come to mind as the possible issue.  So, looks like I will need to store the links and then fill in the atomarray with the receipt of MSG_MULTI_DOCUMENTIMPORTED in Message().  Wish me luck! 🍺

                  Update: That did the trick!

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