Storing Dynamic Lists/Arrays/vectors/etc..



  • On 16/04/2014 at 16:45, xxxxxxxx wrote:

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

    ---------
    Say i wanted to dynamically store a short list of values - how would i achieve this?

    The C4D docs recommend using BaseContainer to store data and retrieve using the typed methods ie GetLong, GetBool, GetVector, etc etc..

    But say i need to hold a multidimensional array ( or just an array ) of data - how do i go about that?

    Would i have to register for example std::vector as a customdatatype and use SetData() to store it?

    Specifically what i am trying to do is store the UCHAR* pointer to the array created by BaseSelect.ToArray() inside a container so that i can retrieve it later.  To complicate matters, the number of UCHARs i have to store is variable.  I cant see a way to do this..

    Alternatively, if there is another way of storing the contents of a bunch of BaseSelect objects or their data for later retrieval i`d like to know it!  There is no GeData equivalent for it or any compatible lists that i can see..

    I`m probably completely overthinking this as a C++/C4D API noob, but at this point going round in circles and would appreciate some advice :)



  • On 16/04/2014 at 23:18, xxxxxxxx wrote:

    To store a variable-length array of data, you could use the SDK's GeDynamicArray or GeAutoDynamicArray classes. They seem to work quite well for things like that.

    Steve



  • On 17/04/2014 at 14:24, xxxxxxxx wrote:

    GeDynamicArray and GeAutoDynamicArray are deprecated and should be replaced by BaseArray or
    BlockArray (starting with R13). They Ge~ arrays are very very slow.

    You can make a customdatatype for it if you want the data to be accessible by the user, for instance
    via XPresso or display it in the UI. If you do not want this and just need the data internally, you can
    keep it as a member of your plugin class and manage the data in CopyTo(), Read() and Write().

    Since you are talking about the data of a BaseSelect object, you could store the BaseSelect
    directly and use the BaseSelect::Write() and Read() methods instead of managing the array
    yourself.

    Something like this maybe

    class MyPlugin : public ObjectData {
      
        AutoFree<BaseSelect> m_sel;
      
    public:
      
        // ObjectData
      
        // NodeData
      
        virtual Bool Write(GeListNode* node, HyperFile* hf) {
            // Write if there is a selection stored.
            if (!hf->WriteBool(nullptr != m_sel)) return false; // file error
      
            // Write the selection if there is one.
            if (nullptr != m_sel) {
                m_sel->Write(hf);
            }
      
            return true;
        }
      
        virtual Bool Read(GeListNode* node, HyperFile* hf, Int32 level) {
            // Read if there is a selection stored.
            Bool has_selection;
            if (!hf->ReadBool(&has_selection)) return false; // file error
      
            // Read the selection if there is one.
            if (has_selection) {
                m_sel.Assign(BaseSelect::Alloc());
                if (nullptr == m_sel) return false; // memory error
                if (!m_sel->Read(hf)) return false; // file error
            }
      
            return true;
        }
      
        virtual Bool CopyTo(NodeData* dest_, GeListNode* snode, GeListNode* dnode,
                    COPYFLAGS flags, AliasTrans* trans)
        {
            MyPlugin* dest = static_cast<MyPlugin*>(dest_);
            if (nullptr == dest) return false;
      
            if (nullptr == m_sel)
                dest->m_sel.Free();
            else {
                dest->m_sel.Assign(BaseSelect::Alloc());
                if (nullptr == dest->m_sel) return false; // memory error
                m_sel->CopyTo(dest->m_sel);
            }
      
            return ObjectData::CopyTo(dest, snode, dnode, flags, trans);
        }
      
    };
    

    Depends on your needs.

    Best,
    -Niklas



  • On 17/04/2014 at 15:15, xxxxxxxx wrote:

    What the heck is a "BlockArray" Confused
    Is that one really available in R13?

    The only undocumented array in R13 I knew about is GeTempDynArray

    -ScottA



  • On 17/04/2014 at 16:34, xxxxxxxx wrote:

    Ah excuse me, the c4d_misc/ stuff (including BaseArray, BlockArray, HashMap, etc.) was introduced
    with R14. I think in R13 you should stick to the Ge~ Arrays (but they are damn slow. Maybe use the
    STL containers then).

    Here's a benchmark Jack did some time ago: https://plugincafe.maxon.net/topic/7185/8213_storing-objects-in-a-list&PID=34166#34166

    Best,
    -Niklas



  • On 17/04/2014 at 16:51, xxxxxxxx wrote:

    NP.
    I just wanted to make sure I wasn't missing something.

    -ScottA



  • On 18/04/2014 at 04:10, xxxxxxxx wrote:

    Ah excuse me, the c4d_misc/ stuff (including BaseArray, BlockArray, HashMap, etc.) was introduced
    with R14. I think in R13 you should stick to the Ge~ Arrays (but they are damn slow. Maybe use the
    STL containers then).

    Another way is to copy  c4d_misc/ from R14 to R13 SDK and then use there.
    I have tried this and it was working at least with BaseArray.



  • On 18/04/2014 at 06:37, xxxxxxxx wrote:

    Thanks a lot for the info Niklas.  I`ll look into using write()/read() and using hyperfile..

    I was in the process of moving all my class variables into BaseContainers as this seems to be the advised way to do it, when i hit a wall with my std::vectors - so i assume i just keep those as class level variables.

    Same really with the ToArray() function of BaseSelect which creates a UCHAR pointer to an internal array.  I found with this there was no way to move it inside my BaseContainer and had trouble storing the pointers inside a standard array or vector ( probably as UCHAR is c4d not std ).

    I`ll have a look at using BaseArray..

    Originally posted by xxxxxxxx

    Another way is to copy  c4d_misc/ from R14 to R13 SDK and then use there.
    I have tried this and it was working at least with BaseArray.

    So does that mean plugins created that way using BaseArray will run in any R13?  Im working with R14 but would be interested to know if i use BaseArray in that way if itll run on R13..



  • On 18/04/2014 at 09:53, xxxxxxxx wrote:

    Remo can you please explain further?
    I can't figure out what you're talking about.

    c4d_misc is a folder found in: resource\_api. Not in the cinema4dsdk files.
    If I copy the c4d_misc folder into the R13 resource\_api folder VS can't find it.
    If I copy the c4d_misc folder into the R13 cinema4dsdk source folder VS can't find it.

    Plus. Aren't the types different in R14 from R13?
    Can you please clarify how you're adding "c4d_misc" to the R13 SDK?

    -ScottA



  • On 20/04/2014 at 04:39, xxxxxxxx wrote:

    Copy c4d_misc
    from ..\CINEMA_4D_R14\resource\_api
    to     ..\CINEMA_4D_R13\resource\_api

    Add c4d_misc path to your R13 solution, just look how it is already done in R14 solution/project.
    Add all the files from c4d_misc to you solution/project.

    > Plus. Aren't the types different in R14 from R13?
    No, but R15 have new types/names.

    This does not work with R12 sadly.

    By the way BaseSelect has "compressed" representation so use it until you really need an array.
    BaseConteiner is well for not too may different values, but if you wan to store 100000 values of the same type then it will be slow and consume a lot of memory.
    std::vector or c4d_misc::BaseArray should be used in such cases.
    For std::vector one could create custom allocator that uses C4D memory system by the way.



  • On 20/04/2014 at 08:10, xxxxxxxx wrote:

    Thanks anyway.
    But I just can't get it to work. I need more detailed instructions on how to add it to the project.
    I've tried everything I can think of. But it refuses to compile.
    I keep getting errors like this: defaultallocator.h line 59 can't find allocator...blah,blah,blah.

    I tried to add the misctest.cpp file to my R13 cinema4dsdk project this morning to see if that would help.
    Not only did it not work. But it also messed up the project and now I'm getting "no such file "c4d.h".
    Now I have to figure out how to fix that. 😠

    -ScottA



  • On 20/04/2014 at 08:34, xxxxxxxx wrote:

    Wouldn`t you have to recompile the API lib file?

    Only other thing i can think of is adding the R14 property sheets..



  • On 20/04/2014 at 11:53, xxxxxxxx wrote:

    Just try to mimic R14 API settings in R13 for c4d_misc.
    I can not remember what exactly need to be done but it was pretty straightforward.
    One problem that I could think about would be Visual Studio version, I have used VS2012.
    VS2010 could not work.

    Add all the files from c4d_misc to the "_api" solution just like this.
    Source Files -> c4d_misc -> debugglobals.cpp

    Compiles here fine using VS2012.

    > Wouldn`t you have to recompile the API lib file?
    Of course you will need to do this.

    > Only other thing i can think of is adding the R14 property sheets..
    This should be not necessary.



  • On 20/04/2014 at 12:48, xxxxxxxx wrote:

    Thanks anyway. But it's not working for me.
    I need to see someone do it in a video from start to finish to see what I'm doing wrong.
    *But that's too much trouble. And I don't really need it that badly. GeArrays work fine for me in R13 anyway.

    If I really want to play around with BaseArray. I can use my R14 or R15 demos and compile and use the SDK in them to play with it.

    Have a Happy Easter guys,
    -SocttA


Log in to reply