Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware 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

    Avoiding invalidating saved scenes when implementing Read/Write

    Cinema 4D SDK
    c++ sdk
    4
    18
    2.0k
    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.
    • ManuelM
      Manuel
      last edited by

      hi,

      creating a scenhook or any kind of plugin will not make the hyperfile structure invalid. A SceneHookData inherit from NodeData.
      It does check if the plugin exist or not before calling the Read function.

      I couldn't reproduce the file structure error you are talking about.
      Maybe because my data structure is too simple (just a Int32)
      Can you try with a simplified data structure ? Share a simplified version of your code ? you can use [email protected]

      Cheers,
      Manuel

      MAXON SDK Specialist

      MAXON Registered Developer

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

        @m_magalhaes Interesting, I just tried that myself, writing/reading only an Int32 does not invalidate the file, even after the plug-in is removed. It seems like my previous suspicion was right and it's my code that is invalidating the structure.

        Alright, this is my (somewhat modified) code which writes into the HyperFile:

        Bool MySceneHookData::Write(GeListNode * node, HyperFile * hf)
        {
            if (!hf->WriteUInt32(UInt32(_descriptors.GetCount())))
                return false;
            
            for (auto entry = _descriptors.Begin(); entry != _descriptors.End(); ++entry)
            {
                auto & desc = entry->GetValue();
                
                if (
                    !hf->WriteUuid(entry->GetKey()) ||
                    !hf->WriteString(desc.name) ||
                    !hf->WriteTime(desc.minTime) ||
                    !hf->WriteTime(desc.maxTime)
                    )
                    return false;
            }
            
            if (!hf->WriteUuid(_activeKey))
                return false;
            
            return SceneHookData::Write(node, hf);
        }
        

        In my code, _descriptors is an instance of maxon::HashMap<C4DUuid, Descriptor> where Descriptor is a struct laid out basically as written in the Write function.

        Now after reading the articles linked by @PluginStudent I realised that I should make use of chunks when writing data collections. I didn't come around to change that yet, though I definitely will do that now that I know the code should work.

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

          hi,

          I still cannot reproduce your issue.

          Some remark about your code, you can use maxon::Uuid instead of C4DUuid look at that manual for more information.
          You don't need to return SUPER::Write you can simply return true or false.

          and yes @PluginStudent is almost always right ^^ (and almost is just to not say always :p)

          Cheers,
          Manuel

          MAXON SDK Specialist

          MAXON Registered Developer

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

            @m_magalhaes said in Avoiding invalidating saved scenes when implementing Read/Write:

            Some remark about your code, you can use maxon::Uuid instead of C4DUuid look at that manual for more information.

            I guess it would've been helpful to mention that earlier, but I'm "stuck" at R16 and as far as I know, that's not yet implemented in this version.

            You don't need to return SUPER::Write you can simply return true or false.

            Oh well that's actually something I "corrected" after I began this thread. I saw that in an example for HyperFile handling so I just repeated it.

            I still cannot reproduce your issue.

            Well that's weird. I created a new document within Cinema, only added a single Sphere object, and even without any data within my SceneHook I can reproduce this issue. So essentially, my code executes two things:

            hf->WriteUInt32(0);
            /* code that won't be executed anyway */
            hf->WriteUuid(C4DUuid());
            

            Which seems to be enough to invalidate the scene file without the plug-in installed.

            Lo and behold! What seems to be the problem (in my case, anyway) is writing the C4DUuid last, because writing just the UInt32 doesn't cause any problem.

            EDIT: fixed some words/typos

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

              @doppelgamer said in Avoiding invalidating saved scenes when implementing Read/Write:

              hf->WriteUuid(C4DUuid());

              ok, this is definitely causing issue. If you just try to open the file you just saved, you have invalid file structure.

              I've opened a bug report entry for that one and send an email to our devs.

              Cheers,
              Manuel

              MAXON SDK Specialist

              MAXON Registered Developer

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

                @m_magalhaes Nice!

                As I understand, any call of WriteUuid on the HyperFile will cause this issue.

                Just my luck to stumble on an unknown bug. 😅

                Thanks for your support, @m_magalhaes !

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

                  hi,

                  well not "any" but this one does. I'm not even sure if it's the call itself that does it.
                  If you do that in your own HyperFile for example, there's no problem.

                  Cheers,
                  Manuel

                  MAXON SDK Specialist

                  MAXON Registered Developer

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

                    So as I'm most likely going to not be able to make use of this fix when it rolls out, I had to resort to "hack" the C4DUuid into the HyperFile.

                    Writing:

                    C4DUuid uuid;
                    hf->WriteMemory(&uuid, sizeof(uuid))
                    

                    Reading:

                    bool read_uuid_hack(HyperFile * hf, C4DUuid * uuid)
                    {
                        Int size;
                        void * data = nullptr;
                        
                        if (!hf->ReadMemory(&data, &size))
                            return false;
                        
                        bool matched = (size == sizeof(*uuid));
                        
                        if (matched && uuid != nullptr)
                            *uuid = *reinterpret_cast<C4DUuid *>(data);
                        
                        DeleteMem(data);
                        
                        return matched;
                    }
                    

                    Using this "hack" avoids invalidating the file.

                    I'm aware of the risks that come with this and I would generally strongly advise against it, but since these UUIDs are only used to identify items internally within my plug-in it won't do any harm.

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

                      hi,

                      or just use GetString to retrieve Uiid in a string form and CopyFrom to create your c4duuid.

                      But as you are stuck in R16 i didn't test it. (CopyFrom is returning a maxon::Result<void> now)

                      Cheers,
                      Manuel

                      MAXON SDK Specialist

                      MAXON Registered Developer

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

                        @m_magalhaes Ah you're right, for some reason I overlooked those methods.

                        So for writing:

                        hf->WriteString(uuid.GetString());
                        

                        And for reading:

                        C4DUuid uuid;
                        String uuidString;
                        
                        hf->ReadString(&uuidString);
                        uuid.CopyFrom(uuidString);
                        

                        Much cleaner and actually supported by Cinema.

                        Very nice, that solved my issue in a satisfactory way! 🙂

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

                          hi,

                          back to the subject, i was tracking the bug and I discovered it was on my chair. After messing around too much about the code, I was doing something very wrong.

                          when you register your scenehook what is the level ? (last parameter of RegisterSceneHookPlugin)

                          Cheers,
                          Manuel

                          MAXON SDK Specialist

                          MAXON Registered Developer

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