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

    Possible to save BaseArray with document?

    SDK Help
    0
    6
    473
    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 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..

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

        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;  
          }  
        };
        
        1 Reply Last reply Reply Quote 0
        • H
          Helper
          last edited by

          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.

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

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

            this?:

            Note:  It is recommended to store as much as possible in the BaseContainer[URL-REMOVED] 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()[URL-REMOVED], Write()[URL-REMOVED] and CopyTo()[URL-REMOVED], 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


            [URL-REMOVED] @maxon: This section contained a non-resolving link which has been removed.

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

              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
              __

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

                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

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