Object in memory and SetLink()



  • On 01/11/2014 at 22:38, xxxxxxxx wrote:

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

    ---------
    Hi Folks,
     
    is it possible to put an object held in memory into a custom gui link field? I've copied and pasted some code I was using elsewhere that sets an object from the AM (drag and drop etc) but the process doesn't appear to work for objects in memory. The objects are made via GetClone() of an object that's dragged into the link field. When the link fields are redrawn however, I cannot see the object in the link. Process is a bit like as follow:
     
    (Plugin is an object generator, links are made inside a customgui plugin)
     
    1. Drag and drop an object into the link field
    2. Check that object is not null
    3. If not null, clone to class level reference: obj_cl = obj->GetClone(COPYFLAGS_0,NULL)
    4. Flush and redraw the link field(s)
    5. Apply object in memory to the new link field
    6. Test print object's name
     
    Code is simple, follows a similar process to the below:

    BaseDocument *doc = GetActiveDocument();  
    BaseList2D *List_Link = LinkFields->GetLink(doc);   
    BaseObject *obj = (BaseObject* )List_Link;  
       
    if(obj != NULL)  
    {  
     // FUNCTION CALLED TO CLONE OBJECT  
     My_Obj->CloneObject(Link_id,obj);  // see function below)
     
     (..flush tab, redraw links here - needed for another purpose..)  
        
     // LinkFields = class level customgui link element  
     // Apply the cloned object to the newly drawn link field  
       
     LinkFields->SetLink(Obj_cl);  
       
     // Obj_cl is valid (GetName() print's fine) but doesn't show in link field  
    }
     
     void PLUGIN_OBJECT::CloneObject(int id,BaseObject* obj)  
     {  
      // Note: Link_id is just an index (int). Not used in this example.  
      //       Obj_cl is class level baseobject variable.  
         
      Obj_cl = obj->GetClone(COPYFLAGS_0,NULL);  
      GePrint("Cloned object's name = " + Obj_cl->GetName());  
         
      // Cloned object's name prints fine.  
     }
    

    Only two rules need to be followed, the object must be a clone, and the clone must sit in memory. If the above doesn't work because it's just not possible, then is there a workaround (something else) I could use/do instead?
     
    Cheers,
     
    WP.
     
    P.S. just an after thought, can a dialog's AddEditText() field receive a drag and drop message?



  • On 02/11/2014 at 00:38, xxxxxxxx wrote:

    Ok, never mind this one, I've decided to use a combination of a link field and text field. Just switching between their hidden status as needed. Works enough to use.
     
    WP.



  • On 02/11/2014 at 06:33, xxxxxxxx wrote:

    Not sure if this should go in a new thread or not, but two queries regarding the cloned object:
    1. Do cloned objects retain their animated state?
    2. If yes, how can I animate their status in a generator object?
     
    What I'm wanting to do, is get the cloned object's animate state on a per frame basis, but independently of the actual document time. I'm using the plugin's Execute() function to update things, so anything that I can get working in their would be a treat.
     
    WP.



  • On 03/11/2014 at 01:27, xxxxxxxx wrote:

    Hello,

    When you want to access objects that are (no longer) part of a document you can try ForceGetLink().

    GetClone() will create an object with animation tracks as long you don't set the flag. COPYFLAGS_NO_ANIMATION.

    The state of an object may depend on the state of other objects. So to get the state of an object at a certain frame you could create a virtual temporary BaseDocument and add the clones. Then you could set the current frame for that temporary document and animate the set frame (via ExecutePasses()).

    best wishes,
    Sebastian



  • On 05/11/2014 at 07:21, xxxxxxxx wrote:

    I'm not sure if this is related or not, but I'm having an issue with an ACCESS_VIOLATION when I do the above. I've read that you're not suppose to do any modifying etc in an ObjectData plugin, unless it's via the Message() method. With that in mind, I've set up a test for any change in frame in the AddToExecution() method, and if a change is found, I send a MSG_UPDATE which then iterates through a group of objects in memory and animates them via the setup above (all done in a document held in memory) and returns them for drawing in GVO.
     
    The problem is that once I do this, I then get crashes at random times during playback of the scene, or scrubbing, or even while it's just sitting their doing nothing. They all seem to happen once I've added a dynamic link into one of the plugin's tabs, and after I've added an object to the link. I should probably mention here that once the object is dropped in the link, I get a clone of it, remove it from the link, and instead replace the link with a text input field with the object's name.
     
    The errors range from this:

    // In header file mlock.c  (what is this header?)
    void __cdecl _unlock (  
            int locknum  
            )  
    {  
            /*  
             * leave the critical section.  
             */  
            LeaveCriticalSection( _locktable[locknum].lock );  
    }  // <--- arrow points here
     
    // Debugging is stopped with a message saying that this will be the next function to run, and an arrow pointing to the last bracket of the above funtion
    

    to this:

    No Source Available  
    There is no source code available for the current location.  
    To investigate further, try one of these options:  
    Browse to Find Source  
    Show Disassemly  
    ...  
    Call stack location:  
    CINEMA 4d.exe!00d6dbc3()
    

    The crash file generated gives me nothing to go on either as there's no mention of my plugin except for being listed in the "Loaded_Plugins".
     
    Without any workable feedback from GePrint()'ing or debugging is VS (the messages above mean nothing to me!), I have no idea of what's causing it, or how to find the problematic code. How do I go about debugging what's going on here? Or if there's a simple explanation, what am I doing wrong?
     
    Cheers,
     
    WP.



  • On 06/11/2014 at 00:59, xxxxxxxx wrote:

    Hello,

    the crashes you describe seem to be caused by accessing resources that are no longer available (mlock.c is part of the C-runtime). Without more details it's impossible to say what causes this.

    One thing may be how you handle ownership of your (temporary) objects. Do you return the objects managed in you temporary document directly in GetVirtualObjects()? I suggest to return a copy instead so that the temporary document can safely delete the objects it manages when it is destroyed.

    best wishes,
    Sebastian



  • On 06/11/2014 at 02:11, xxxxxxxx wrote:

    Hi Sebastian,
     
    I thought the handling of the objects might be the cause of the issue, but neither of the debugging ways seemed to be telling me anything that might be wrong with them.
     
    The way I'm holding the objects is a bit like the following:

    // pseudo code
     
    class My_Object : public ObjectData
    {
        struct My_Obj_Struct
        {
            BaseObject *Obj;
            // custom functions for object
        }
     
        // The struct objects are held in a vector
        std::vector< My_Obj_Struct > Links;
     
        // Master base object used in the GVO
        // return. Object is allocated as an Onull
        // in the constructor. It is freed in the
        // deconstructor.
        BaseObject *MasterNull;
     
        BaseObject* GetVirtualObjects(BaseObject* op,HierarchyHelp* hh)
        {
            if(MasterNull->CheckCache(hh) == TRUE)
            {
                ReapplyClonedObjects(1);
            }
     
            return MasterNull;
        }
     
        void ReapplyClonedObjects(int id)
        {
            if(Links[id].Obj != NULL)
            {
                Links[id].Obj->Remove();
                Links[id].Obj->InsertUnderLast(MasterNull);
            }
        }
    }
    

    For the purpose of the above, I've removed the temporary document used for animating the objects. The crashes occur without it. I've also used only the first indexed struct object to add to the MasterNull object. The vector of struct My_Obj_Struct is sized/resized for x objects plus 1. So one object = two indexes. Container index "0" I use as a template.
     
    I know the objects are good to begin with as I can see them in the viewport (most of the time it gets to here). If it makes it this far, I can playback the scene until it crashes on a random frame. The objects are in the viewport during playback.
     
    WP.



  • On 06/11/2014 at 05:58, xxxxxxxx wrote:

    Hello,

    there are several issues with your code. First, you shouldn't store a pointer to the created object (*MasterNull). Cinema will store the objects created in GetVirtualObjects() in a cache; also the undo system may handle your object and create different versions of it. So at some point Cinema may delete the cache and it's content, so that your pointer will become invalid. You should re-create your object in GetVirtualObjects() and let Cinema handle the ownership.

    Also, please don't use lists and vectors from the standard library. The SDK offers multiple list and array types like AtomArray, BaseArray or PointerArray.

    I hope this helps you.

    Best wishes,
    Sebastian



  • On 06/11/2014 at 19:24, xxxxxxxx wrote:

    Hi Sebastian,
     
    I use the master null object so that a number of objects can be added as children to it before I return it. But in considering the GVO process, I think I'll change it so that as you say, GVO rebuilds it without a master null object pointer in the first place. I'll change that.
     
    Re Cinema's containers, perhaps a conversation for another topic, but I feel far more comfortable with the standard library than with Cinema's. There are a few reasons also, some include: it leaves the possibility of transferring plugin engines to other platforms (though not in the pipeline at the moment), I can also go do general c++ searches before bugging the fine folk here, and because the standard library is just that - a standard library. But mostly because I just feel more comfortable with them!
     
    WP.



  • On 06/11/2014 at 22:57, xxxxxxxx wrote:

    Well, the news isn't great. I'm now using StopAllThreads() and cloning the held object on each frame in GVO and returning the new clone under a null object (also made in GVO). But the ACCESS_VIOLATION error still pops up, and is still random. I've had the same problems with BaseLinkArray I think it was (which I remembered I tried before going down the std::vector< MyStruct > route).
    Maybe I need to start from scratch again. How can I safely store an array of objects in an ObjectData plugin, that I can use to draw with in GVO?
     
    Cheers Big smile
     
    WP.



  • On 07/11/2014 at 03:12, xxxxxxxx wrote:

    Can`t you store them in a temp doc and grab them from there when needed?



  • On 07/11/2014 at 06:36, xxxxxxxx wrote:

    Hello,

    One should not use the standard library because we cannot give support on any problems with that.

    Please be aware that GetVirtualObjects() is not about "drawing" objects. This function will create objects that will become part of the scene. Cinema will use the created objects to store them in a cache; may use them to apply a deformation and may delete them if needed.

    Storing objects should be no problem. I just tried it using a BaseArray. Just make sure you handle the allocation and deletion of these objects correctly.

    Best wishes,
    Sebastian


Log in to reply