Avoiding invalidating saved scenes when implementing Read/Write
-
@PluginStudent said in Avoiding invalidating saved scenes when implementing Read/Write:
I still don't get what data would be too complex to write into a
BaseContainer
.'Too complex' might be the wrong wording, it's more like the data is laid-out into classes with relations within each other. Again, storing this data within the
NodeData
's container is technically possible, but quite inefficient.You can store raw memory in a BaseContainer.
If you only want to read/write to the document'sBaseContainer
, you could listen to the MSG_DOCUMENTINFO sent when the document is loaded and saved.I guess that's going to be a mixture I'm going to utilise. Thank you!
Maybe someone from Maxon could look into this issue, I think it's quite important to communicate to plug-in developers that making a
SceneHook
write into aHyperFile
will invalidate the scene file for future use without the respective plug-in. -
hi,
creating a scenhook or any kind of plugin will not make the hyperfile structure invalid. A
SceneHookData
inherit fromNodeData
.
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 -
@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 ofmaxon::HashMap<C4DUuid, Descriptor>
whereDescriptor
is astruct
laid out basically as written in theWrite
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.
-
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 returnSUPER::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 -
@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 theUInt32
doesn't cause any problem.EDIT: fixed some words/typos
-
@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 -
@m_magalhaes Nice!
As I understand, any call of
WriteUuid
on theHyperFile
will cause this issue.Just my luck to stumble on an unknown bug.
Thanks for your support, @m_magalhaes !
-
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 -
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 theHyperFile
.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.
-
-
@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!
-
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