Your browser does not seem to support JavaScript. As a result, your viewing experience will be diminished, and you have been placed in read-only mode.
Please download a browser that supports JavaScript, or enable it if it's disabled (i.e. NoScript).
On 09/11/2013 at 01:08, xxxxxxxx wrote:
User Information: Cinema 4D Version: Platform: Language(s) :
--------- I have several BaseArrays "floating around" in memory. And some Null objects who are created at runtime and inserted into the document. When I save, close and reopen the C4D project file, the Null objects are there, as I left them. The BaseArrays are gone, as expected. Is there a way for the doument to also save a BaseArray? In My case, the BaseArray contains classes, who hold certain values like Real, Integers or Vectors.
I know how to serialize objects like this (making a long string out of the object ans store it in a file), so this question is not about that. The question is to what extent it would be possible to tell the BaseDocument in a [magical] way to also store the BaseArray, warts and all. And when opening the project file again - poof - like magic, the BaseArray is there again, like magic I woulkd like to say..
On 09/11/2013 at 04:47, xxxxxxxx wrote:
That is an interesting question. Looking at the documentation for BaseArray, there is no Read()/Write() implementation. That might be because you determine the type being stored within it (??) and BaseArray has not been designed to handle permanent storage facilities directly (i.e.: files). What you might need to do is go through the members stored in the BaseArray and save/load them to/from file from your plugin's Write()/Read() methods and then, on Read(), store them into your BaseArray (using Append() or whatever).
The 'magical' way is by using Read()/Write() to retain and reconstruct elements not stored in the plugin's BaseContainer (Descriptions).
Note: If you are storing class instances in the BaseArray, it may be wise to implement your own Read()/Write() methods for the class, passing the HyperFile* from your plugin, so that the saving of the class's member variables is encapsulated.
For instance:
class MyClass { Real fReal; Vector vVector; Bool Write(HyperFile* hf) { if (!hf->WriteReal(fReal)) return FALSE; if (!hf->WriteVector(vVector)) return FALSE; return TRUE; } Bool Read(HyperFile* hf) { if (!hf->ReadReal(&fReal)) return FALSE; if (!hf->ReadVector(&vVector)) return FALSE; return TRUE; } };
On 09/11/2013 at 05:34, xxxxxxxx wrote:
Yes I see there are several (many) predefined ways to write common classes to the hyperfile, even Matrices. I understand a complex class cannot be written just like that, so I accept this. In any case, these Write / Read methods come in very handy and saves time and code. When reading the docs earlier today, I saw it mentioned somewhere that "plugin developers should not use Read / Write methods" or something like this, but I cannot find the chapter where it was mentioned.
On 09/11/2013 at 07:01, xxxxxxxx wrote:
Howdy,
Originally posted by xxxxxxxx ...When reading the docs earlier today, I saw it mentioned somewhere that "plugin developers should not use Read / Write methods" or something like this, but I cannot find the chapter where it was mentioned...
Originally posted by xxxxxxxx
...When reading the docs earlier today, I saw it mentioned somewhere that "plugin developers should not use Read / Write methods" or something like this, but I cannot find the chapter where it was mentioned...
this?:
Note: It is recommended to store as much as possible in the [BaseContainer](file:///Users/danlibisch/Documentation/C4D%20Manuals/R10%20SDK/pages/c4d_basecontainer/class_BaseContainer44.html) as CINEMA 4D will handle the reading of those values automatically. Only use member variables when necessary. Important: If you implement at least one of [Read()](file:///Users/danlibisch/Documentation/C4D%20Manuals/R10%20SDK/pages/c4d_nodedata/class_NodeData872.html#read4), [Write()](file:///Users/danlibisch/Documentation/C4D%20Manuals/R10%20SDK/pages/c4d_nodedata/class_NodeData872.html#write5) and [CopyTo()](file:///Users/danlibisch/Documentation/C4D%20Manuals/R10%20SDK/pages/c4d_nodedata/class_NodeData872.html#copyto7), you must usually implement all three. Otherwise data might be lost.
Note: It is recommended to store as much as possible in the [BaseContainer](file:///Users/danlibisch/Documentation/C4D%20Manuals/R10%20SDK/pages/c4d_basecontainer/class_BaseContainer44.html) as CINEMA 4D will handle the reading of those values automatically. Only use member variables when necessary.
Important: If you implement at least one of [Read()](file:///Users/danlibisch/Documentation/C4D%20Manuals/R10%20SDK/pages/c4d_nodedata/class_NodeData872.html#read4), [Write()](file:///Users/danlibisch/Documentation/C4D%20Manuals/R10%20SDK/pages/c4d_nodedata/class_NodeData872.html#write5) and [CopyTo()](file:///Users/danlibisch/Documentation/C4D%20Manuals/R10%20SDK/pages/c4d_nodedata/class_NodeData872.html#copyto7), you must usually implement all three. Otherwise data might be lost.
In my opinion, you should handle it the way Robert described. It wouldn't surprise me a bit if we could access the internal source code to "ReadVector()" it might have 3 "ReadReal()" calls within that function.
Adios, Cactus Dan
On 10/11/2013 at 04:12, xxxxxxxx wrote:
Hi ingvarai,
check this out:
> > /* Copyright (c) 2013 Niklas Rosenstein > * > * Permission is hereby granted, free of charge, to any person obtaining a copy > * of this software and associated documentation files (the "Software"), to deal > * in the Software without restriction, including without limitation the rights > * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell > * copies of the Software, and to permit persons to whom the Software is > * furnished to do so, subject to the following conditions: > * > * The above copyright notice and this permission notice shall be included in > * all copies or substantial portions of the Software. > * > * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE > * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER > * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, > * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN > * THE SOFTWARE. */ > > #include <c4d.h> > > > /* This class describes the interface for the writer and reader class that > > > is given as a template parameter to the ReadArray() and WriteArray() > > > functions. */ > class HyperFileRW { > > public: > > Bool Read(HyperFile* hf, Real* dest, LONG disklevel) { > return hf->ReadReal(dest); > } > > Bool Read(HyperFile* hf, LONG* dest, LONG disklevel) { > return hf->ReadLong(dest); > } > > Bool Read(HyperFile* hf, Vector* dest, LONG disklevel) { > return hf->ReadVector(dest); > } > > Bool Read(HyperFile* hf, Matrix* dest, LONG disklevel) { > return hf->ReadMatrix(dest); > } > > /* More possible overloaded methods ... */ > > Bool Write(HyperFile* hf, const Real value) { > return hf->WriteReal(value); > } > > Bool Write(HyperFile* hf, const LONG value) { > return hf->WriteLong(value); > } > > Bool Write(HyperFile* hf, const Vector& value) { > return hf->WriteVector(value); > } > > Bool Write(HyperFile* hf, const Matrix& value) { > return hf->WriteMatrix(value); > } > > /* More possible overloaded methods ... */ > > }; > > /* Write an array to a HyperFile. */ > template <typename ArrayClass, typename WriterClass> > Bool WriteArray(HyperFile* hf, ArrayClass& array, WriterClass writer) { > /* Write the size of the array. */ > LONG count = array.GetCount(); > if (!hf->WriteLong(count)) return FALSE; > > /* And now each and every element. */ > ArrayClass::ConstIterator it = array.Begin(); > for (; it != array.End(); it++) { > if (!writer.Write(hf, *it)) return FALSE; > } > > return TRUE; > } > > /* Read an array from a HyperFile. */ > template <typename Datatype, typename ArrayClass, typename ReaderClass> > Bool ReadArray(HyperFile* hf, ArrayClass& array, ReaderClass reader, LONG disklevel) { > /* Read the size of the array. */ > LONG size; > if (!hf->ReadLong(&size)) return FALSE; > > /* Resize the array and fill in the values. */ > array.Resize(size); > ArrayClass::Iterator it = array.Begin(); > Datatype value; > for (; it != array.End(); it++) { > if (!reader.Read(hf, &value, disklevel)) return FALSE; > *it = value; > } > > return TRUE; > } > > > Bool PluginStart() { > GePrint("-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-"); > GePrint("PluginStart(), running write/read tests..."); > > /* In-memory file. */ > AutoAlloc<MemoryFileStruct> mfs; > if (!mfs) { > GePrint("Could not allocate MemoryFileStruct."); > return FALSE; > } > > /* Write Test */ > /* ---------- */ > > /* Allocate the HyperFile. */ > AutoAlloc<HyperFile> hf; > if (!hf) { > GePrint("Could not allocate HyperFile."); > return FALSE; > } > > /* Open a new HyperFile with the in-memory file. */ > Filename mem; > mem.SetMemoryWriteMode(mfs); > if (!hf->Open(0, mem, FILEOPEN_WRITE, FILEDIALOG_NONE)) { > GePrint("Could not open HyperFile in WRITE mode."); > return FALSE; > } > > /* Create an array of vectors. */ > c4d_misc::BaseArray<Vector> source_array; > source_array.Resize(100); > for (LONG i=0; i < 100; i++) source_array = Vector(SNoise(i), SNoise(i * i), SNoise(1 * 3 + 2)); /* And write the array to the file. */ > if (!WriteArray(hf, source_array, HyperFileRW())) { > GePrint("Failed to write array."); > return FALSE; > } > > /* Close the HyperFile and report about our success. */ > hf->Close(); > GePrint("Array successfully written!"); > > /* Read Test */ > /* --------- */ > > /* Retrieve a pointer to the data of the MemoryFileStruct. */ > void* data = NULL; > VLONG data_size = -1; > mfs->GetData(data, data_size, FALSE); > if (!data) { > GePrint("Could not obtain data-pointer from MemoryFileStruct."); > return FALSE; > } > > /* And open the HyperFile in READ mode. */ > hf.Free(); > hf.Assign(HyperFile::Alloc()); > if (!hf) { > GePrint("Could not allocated HyperFile."); > return FALSE; > } > mem.SetMemoryReadMode(data, data_size); > if (!hf->Open(0, mem, FILEOPEN_READ, FILEDIALOG_NONE)) { > GePrint("Could not open HyperFile in READ mode."); > return FALSE; > } > > /* Read the array. */ > c4d_misc::BaseArray<Vector> read_array; > Bool result = ReadArray<Vector, c4d_misc::BaseArray<Vector>, HyperFileRW>( > hf, read_array, HyperFileRW(), 0); > if (!result) { > GePrint("Could not read array."); > return FALSE; > } > > GePrint("Array successfully read from HyperFile, checking results.."); > > /* Do they have the same size? */ > if (source_array.GetCount() != read_array.GetCount()) { > GePrint("> Sizes do not equal."); > return FALSE; > } > > /* Are the values equal? */ > c4d_misc::BaseArray<Vector>::Iterator it1 = source_array.Begin(); > c4d_misc::BaseArray<Vector>::Iterator it2 = read_array.Begin(); > LONG index = 0; > for (; it1 != source_array.End() && it2 != read_array.End(); it1++, it2++, index++) { > if (*it1 != *it2) { > GePrint("> Elements at index " + LongToString(index) + " do not equal."); > return FALSE; > } > } > > GePrint("A pure success!"); > return TRUE; > } > > Bool PluginMessage(LONG type, void* pData) { > switch (type) { > case C4DPL_INIT_SYS: > return resource.Init(); > }; > return TRUE; > } > > void PluginEnd() { > } You can easily use this to write any data you like. Best, -Niklas __
On 10/11/2013 at 11:20, xxxxxxxx wrote:
Niklas - a million thanks for this, absolutely fantastic! I will definitely use this one, sehr nett von Dir!
-Ingvar