Setting clone child as constrain target



  • On 22/05/2017 at 04:24, xxxxxxxx wrote:

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

    ---------
    I have a Cloner with a Sphere as child and count set to 3._<_o:_<_o:p_>_o:p>
    Now I want to access the second cloner object and set it as target in the Constrain-Clamp Tag. 
    So, I do a CurrentStateToObject and get the second (child) _<_o:_<_o:p_>_
    Note: I do not insert the new object, so it is just_<_o:_<_o:p_>_ory(?).
    Then I create the Constrain tag and put this second (child) object_<_o:_<_o:p_>_ Target field.
    Here the high level code.

      
    ModelingCommandData cd;  
    cd.doc = GetActiveDocument();  
    cd.op = obj;  
    SendModelingCommand(MCOMMAND_CURRENTSTATETOOBJECT, cd);
    cstObject = (BaseObject* )cd.result->GetIndex(0);
      
    //get object
    BaseObject* ob = cstObject->GetDown();  
    ob = ob->GetNext();                          
      
    //set target in constrain - clamp tag  
    res = constraintTag->SetParameter(50001, ob, DESCFLAGS_SET_0);  
     
    

    I can see that I get the correct object (sphere 1), but the Constrain – Clamp Tag field stays emp_<_o:_<_o:p_>_
    In python this is working and the field is filled with: Cloner / Sphere 1 / Sphere 1
    Any hints?
    -Pim



  • On 22/05/2017 at 08:15, xxxxxxxx wrote:

    IMHO. Using SMC like this is rather ugly. And asking for crashes if it's called too many times, too quickly.
    If you're not married to using a constraint tag. I can show you how to constrain an object to a specific clone by directly getting it's position data from the Cloner Object. Without using a constraint tag and doing that nasty SMC stuff.

    -ScottA



  • On 22/05/2017 at 08:42, xxxxxxxx wrote:

    The thing is that I do not know which specific clone.

    The user selects an object, which can be a clone.
    After that, I get the selected object using PickObject().

    Everything is ok, if the selected object is not a clone.

    -Pim

    Note. I would love to see your suggested solution.



  • On 22/05/2017 at 08:47, xxxxxxxx wrote:

    Could it be that after I do the MCOMMAND_CURRENTSTATETOOBJECT, the object is not yet in the hierarchy, only in memory. And thus I can not us it as a constrain?

    -Pim



  • On 22/05/2017 at 08:50, xxxxxxxx wrote:

    NP.
    This might not solve your problem. But it might be useful for some other project.

    //This will lock a Null object to the second clone in a ClonerObject. Similar to using a constraint tag  
      
    #include "c4d_baseeffectordata.h"  
      
      
      BaseObject *target = doc->SearchObject("Null");  
      if (!target) return false;  
      Matrix targetMtx = target->GetMg();  
      
      //The cloner object  
      BaseObject *clonerObj = doc->SearchObject("Cloner");  
      if (!clonerObj || clonerObj->GetType() != 1018544) return false;  
      
      //Get the hidden MoData tag that is on the cloner object  
      BaseTag *moTag = clonerObj->GetTag(ID_MOTAGDATA);  
      if (!moTag) return false;  
      
      //Retrieve the MoData  
      GetMoDataMessage msg_data;  
      if (!moTag->Message(MSG_GET_MODATA, &msg_data)) return false;  
      
      if (msg_data.modata)  
      {  
          //Get the matrix data for the clones  
          MoData *md = msg_data.modata;  
          MDArray<Matrix>mtx = md->GetMatrixArray(MODATA_MATRIX);  
            
          //The Global Position of the second clone  
          Vector clonePos = mtx[2].off * clonerObj->GetMg();  
      
          //Lock the Null object to the position of the second clone  
          targetMtx.off = clonePos;          
          target->SetMg(targetMtx);          
      }
    

    -ScottA



  • On 22/05/2017 at 09:11, xxxxxxxx wrote:

    Thanks for the code. I am certain it will be helpful in other plugins.
    Again something for the "big book with solutions".



  • On 22/05/2017 at 09:16, xxxxxxxx wrote:

    Originally posted by xxxxxxxx

    Could it be that after I do the MCOMMAND_CURRENTSTATETOOBJECT, the object is not yet in the hierarchy, only in memory. And thus I can not us it as a constrain?

    It has indeed something to do with issue.

    If I, for test purposes, insert the resulting object (of the CSTO), then it works.

    GetActiveDocument()->InsertObject(cstObject, nullptr, nullptr);  
    EventAdd();
    

    So the question is, how to use a "virtual object(?)" - an object that is only in memory - as a target?

    -Pim



  • On 22/05/2017 at 09:32, xxxxxxxx wrote:

    Originally posted by xxxxxxxx

    Originally posted by xxxxxxxx

    Could it be that after I do the MCOMMAND_CURRENTSTATETOOBJECT, the object is not yet in the hierarchy, only in memory. And thus I can not us it as a constrain?

    It has indeed something to do with issue.

    If I, for test purposes, insert the resulting object (of the CSTO), then it works.

    GetActiveDocument()->InsertObject(cstObject, nullptr, nullptr);  
    EventAdd();
    

    So the question is, how to use a "virtual object(?)" - an object that is only in memory - as a target?

    Can I do something with the cache of the object?

    -Pim



  • On 23/05/2017 at 09:47, xxxxxxxx wrote:

    Hi Pim,

    the problem is indeed the clone not being part of the document. In the constraint tag the reference to the object is stored as a BaseLink and such gets resolved in the context of a document. And here we run into issues with clones from a Cloner. That's unfortunately not the usual use-case of the constraint tag. And I'm not sure yet, if we have a workaround in this case. Probably "easiest" would be to create your own Constraint TagData plugin, which takes care of this special situation.



  • On 25/05/2017 at 01:01, xxxxxxxx wrote:

    Hi Andreas,

    Thanks for the reply. I solved the issue using the cache.
    Here the test code I used.

    			obj = GetActiveDocument()->SearchObject("Object with constraint tag");
    			constraintTag = obj->GetTag(1019364);				//Constraint Tag = 1019364
    			clonerObj = GetActiveDocument()->SearchObject("Cloner object");
      
    			clone = clonerObj->GetCache();
    			// get second clone
    			if (clone) {
    				   clone = clone->GetDown();
    				   clone = clone->GetNext();
      
       //set target
    				   res = constraintTag->SetParameter(ID_CA_CONSTRAINT_TAG_CLAMP, TRUE, DESCFLAGS_SET_0);
    				   res = constraintTag->SetParameter(50001, clone, DESCFLAGS_SET_0);			
    			}
    

    -Pim



  • On 29/05/2017 at 02:42, xxxxxxxx wrote:

    Hi Pim,

    well, as I said before, you are probably leaving the tested areas by linking a cache object into the Constraint tag. But if it works for you, fine. One thing we didn't talk about so far, is the context where you try to do this? Is it in a NodeData plugin or rather CommandData?



  • On 30/05/2017 at 03:58, xxxxxxxx wrote:

    Yes, I place a cache object in the target field of the constraint.
    The setting of the constraint is done in a CommandData plugin.

    -Pim


Log in to reply