Plugin Cafe Homepage
Forum Home Forum Home > Plugin Cafe > SDK Help
  New Posts New Posts
  FAQ FAQ  Forum Search   Register Register  Login Login

Setting clone child as constrain target

 Post Reply Post Reply
Author
Message
pgrooff View Drop Down
Member
Member


Joined: 2010 Nov 05
Online Status: Offline
Posts: 745
Post Options Post Options   Quote pgrooff Quote  Post ReplyReply Direct Link To This Post Topic: Setting clone child as constrain target
    Posted: 2017 May 22 at 4:24am

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.

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

Note: I do not insert the new object, so it is just in memory(?).

Then I create the Constrain tag and put this second (child) object in the 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 empty?

In python this is working and the field is filled with: Cloner / Sphere 1 / Sphere 1

Any hints?

-Pim

Back to Top
ScottA View Drop Down
Member
Member


Joined: 2011 Jan 07
Online Status: Offline
Posts: 2288
Post Options Post Options   Quote ScottA Quote  Post ReplyReply Direct Link To This Post Posted: 2017 May 22 at 8:15am
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
Back to Top
pgrooff View Drop Down
Member
Member


Joined: 2010 Nov 05
Online Status: Offline
Posts: 745
Post Options Post Options   Quote pgrooff Quote  Post ReplyReply Direct Link To This Post Posted: 2017 May 22 at 8:42am
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.
Back to Top
pgrooff View Drop Down
Member
Member


Joined: 2010 Nov 05
Online Status: Offline
Posts: 745
Post Options Post Options   Quote pgrooff Quote  Post ReplyReply Direct Link To This Post Posted: 2017 May 22 at 8:47am
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
Back to Top
ScottA View Drop Down
Member
Member


Joined: 2011 Jan 07
Online Status: Offline
Posts: 2288
Post Options Post Options   Quote ScottA Quote  Post ReplyReply Direct Link To This Post Posted: 2017 May 22 at 8:50am
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
Back to Top
pgrooff View Drop Down
Member
Member


Joined: 2010 Nov 05
Online Status: Offline
Posts: 745
Post Options Post Options   Quote pgrooff Quote  Post ReplyReply Direct Link To This Post Posted: 2017 May 22 at 9:11am
Thanks for the code. I am certain it will be helpful in other plugins.
Again something for the "big book with solutions".

Back to Top
pgrooff View Drop Down
Member
Member


Joined: 2010 Nov 05
Online Status: Offline
Posts: 745
Post Options Post Options   Quote pgrooff Quote  Post ReplyReply Direct Link To This Post Posted: 2017 May 22 at 9:16am
Originally posted by pgrooff

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
Back to Top
pgrooff View Drop Down
Member
Member


Joined: 2010 Nov 05
Online Status: Offline
Posts: 745
Post Options Post Options   Quote pgrooff Quote  Post ReplyReply Direct Link To This Post Posted: 2017 May 22 at 9:32am
Originally posted by pgrooff

Originally posted by pgrooff

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
Back to Top
Andreas Block View Drop Down
Forum Moderator
Forum Moderator
Avatar

Joined: 2014 Oct 01
Location: Hannover
Online Status: Offline
Posts: 1496
Post Options Post Options   Quote Andreas Block Quote  Post ReplyReply Direct Link To This Post Posted: 2017 May 23 at 9:47am
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.

Cheers,
Andreas
SDK Support Engineer
Back to Top
pgrooff View Drop Down
Member
Member


Joined: 2010 Nov 05
Online Status: Offline
Posts: 745
Post Options Post Options   Quote pgrooff Quote  Post ReplyReply Direct Link To This Post Posted: 2017 May 25 at 1:01am
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
Back to Top
Andreas Block View Drop Down
Forum Moderator
Forum Moderator
Avatar

Joined: 2014 Oct 01
Location: Hannover
Online Status: Offline
Posts: 1496
Post Options Post Options   Quote Andreas Block Quote  Post ReplyReply Direct Link To This Post Posted: 2017 May 29 at 2:42am
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?

Cheers,
Andreas
SDK Support Engineer
Back to Top
pgrooff View Drop Down
Member
Member


Joined: 2010 Nov 05
Online Status: Offline
Posts: 745
Post Options Post Options   Quote pgrooff Quote  Post ReplyReply Direct Link To This Post Posted: 2017 May 30 at 3:58am
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
Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down

Bulletin Board Software by Web Wiz Forums® version 9.61 [Free Express Edition]
Copyright ©2001-2009 Web Wiz

This page was generated in 0.113 seconds.