On 27/07/2014 at 11:56, xxxxxxxx wrote:
Hi there,
is it possible to transform the main object from my objectplugin without transforming the children?
Move, scale or rotate the object but the children stay the same.
Thanks,
Martin
On 27/07/2014 at 11:56, xxxxxxxx wrote:
Hi there,
is it possible to transform the main object from my objectplugin without transforming the children?
Move, scale or rotate the object but the children stay the same.
Thanks,
Martin
On 28/07/2014 at 08:32, xxxxxxxx wrote:
You could set up a double null. What you do the the parent just do the opposite to the child null and parent everything under that, possibly even a third so the values aren't being changed directly. It will take a little bit of math to get the rotation ans scale working correctly but shouldn't be to hard.
On 28/07/2014 at 15:14, xxxxxxxx wrote:
thank you for answering,
it sounds like a workaround to me? or I did´nt get it exactly. Why I do need null objects and translation matrices?
What I´m tring to do with my objectplugin is something like this. Inside the Message function, store
the children´s matrices before moving the axis of the parentobject and write it back when finished.
But the childrenMatr-List is not updated properly.
def Message(self, node, type, data) :
inst = node.GetDataInstance()
childrenMatr=[]
if type== c4d.MSG_MOVE_START:
print "start transform"
childrenMatr=[]
children= node.GetChildren()
for ch in children:
childrenMatr.append([ch,ch.GetMg()])
print childrenMatr, "before"
if type== c4d.MSG_MOVE_FINISHED:
print "finished transform"
print childrenMatr,"after"
for i in childrenMatr:
i[0].SetMg(i[1])
or much better will be to realize it in real time, like for example with my self written handels:
def SetHandle(self, op, hit_id, p, info) :
data = op.GetDataInstance()
if data is None: return
p= abs(p)
size= data.GetVector(10001)
val = (p-info.position)*info.direction
if hit_id is 0:
data.SetVector(10001,c4d.Vector(size.x+val,size.y,size.z))
if data.GetBool(10002)== 1:#lockproportions
data.SetVector(10001,c4d.Vector(size.x+val,size.x+val,size.x+val))
elif hit_id is 1:
data.SetVector(10001,c4d.Vector(size.x,size.y+val,size.z))
if data.GetBool(10002)== 1:#lockproportions
data.SetVector(10001,c4d.Vector(size.y+val,size.y+val,size.y+val))
elif hit_id is 2:
data.SetVector(10001,c4d.Vector(size.x,size.y,size.z+val))
if data.GetBool(10002)== 1:#lockproportions
data.SetVector(10001,c4d.Vector(size.z+val,size.z+val,size.z+val))
def MoveHandle(self, op, undo, mouse_pos, hit_id, qualifier, bd) :
mg = op.GetUpMg() * undo.GetMl()
info = c4d.HandleInfo()
self.GetHandle(op, hit_id, info)
self.SetHandle(op, hit_id , (info.CalculateNewPosition(bd, mg, mouse_pos)), info)
return True
Thanks for any help!
Martin
On 28/07/2014 at 17:24, xxxxxxxx wrote:
What you need to do is move the parent object.
Then move the children objects the same amount...but in the inverse direction to put them back where they originally were.
import c4d
def main() :
obj = doc.GetActiveObject()
mg_old = obj.GetMg() #Save the parent's old matrix
mg_new = c4d.Matrix() #This will be the parent's new matrix
mg_new.off = c4d.Vector(-610,0,0) #Move the selected parent object to this location
obj.SetMg(mg_new) #Apply the new matrix to the parent object
obj.Message(c4d.MSG_UPDATE)
mg_new = ~mg_new #Invert new matrix - needed later
#Cycle through children
obj = obj.GetDown()
while obj:
ml_child = obj.GetMl() #Get child's local matrix
#Bring it into the child's old global space by multiplying
#with the parent's old global matrix
mg_old_child = mg_old * ml_child
#Set the child's new local matrix by multiplying
#with the parent's inverted new global matrix
obj.SetMl(mg_new * mg_old_child)
obj.Message(c4d.MSG_UPDATE)
obj = obj.GetNext()
c4d.EventAdd()
if __name__=='__main__':
main()
-ScottA
On 29/07/2014 at 01:36, xxxxxxxx wrote:
Hey Scott,
thanks for the reply!
It´s a workaround, too.
As I mentioned before:
"Why I do need null objects and translation matrices?"
A global matrix is only relativ to the scene origin, therefore the hierarchy has no influence.
I can store the children global matrices and write it back
Code below shows a much simpler approach of what you are doing:
My problem is to do this in real time if the user move the axis of my objectplugins mainobject.
I can not find the right routine to detect the motion of the axis.
Thanks for any help!
Martin
def main() :
if op is None:return
childrenMatr=[]
children= op.GetChildren()
for ch in children:
childrenMatr.append([ch,ch.GetMg()])
parentMatr= op.GetMg()
#fake movement
op.SetMg(c4d.Matrix((parentMatr.off+c4d.Vector(200,0,0)),parentMatr.v1,parentMatr.v2,parentMatr.v3,))
op.Message(c4d.MSG_UPDATE)
for i in childrenMatr:
i[0].SetMg(i[1])
c4d.EventAdd()
if __name__=='__main__':
main()
On 29/07/2014 at 09:18, xxxxxxxx wrote:
The code I posted is just another way to do it. And it might be a bit faster for larger hierarchies.
Lists can become slow if you store too much data in them. But either way should work.
I'm confused about what your actual problem is?
You asked how to transform the parent without moving the children. Yet you already knew how to do it (using lists).
Now you're asking how to detect the direction that the user is dragging the parent object. Which is something that I'm guessing you also already know how to do using a class member variable to store the original position. And comparing the current position with that logged position.
You know how to move the parent without moving the children(actually move them back).
You seem to know how to get the direction of travel the parent is being dragged by the user.
So what is that's the problem you're having?
What is happening when you apply your parent's dragged vector to your "Send children home" code?
Is there a lag or some other problem?
-ScottA
On 29/07/2014 at 15:29, xxxxxxxx wrote:
Hi Scott,
I didn´t see that coming, doing all the calculations is faster than only storing values .
Your code is faster!
Tested it with a million objects and it was round about 100ms faster.
Great, thank you for the hint.
That is indeed a reason for the translation matrix.
My question was about all the tasks in this field.
I don´t know how to detect the axis and the transformation mode.
I´m only able to detect the handles I wrote by myself, but not the c4d axis
and if the user is in scale, rotation or move mode.
Martin
On 29/07/2014 at 16:11, xxxxxxxx wrote:
This stuff?
import c4d
def main() :
activetool = doc.GetAction() #Get the current active tool
print activetool
#200000088 == Move mode is active
#200000089 == Scale mode is active #These are the ID#s for the Move, Scale, and Rotate tools
#200000090 == Rotate mode is active
#Example for setting the move tool
#If the move tool is not active...activate it
if activetool != 200000088:
doc.SetAction(200000088)
#This is new in R14++ for getting the state of the axis tool
AxisMode = doc.IsAxisEnabled()
print AxisMode
c4d.EventAdd()
if __name__=='__main__':
main()
-ScottA
On 31/07/2014 at 03:09, xxxxxxxx wrote:
kind of...
hence the object plugin mainobject is like a parametrical object
AxisMode = doc.IsAxisEnabled()
print AxisMode
the axismode is never enabled, even if the user checked the button.
got it now, I guess !
easiest way I found out is to get the object´s drawpass, read the change of information and do a recalculation for the children.
like:
def Draw(self, node, drawpass, bd, bh) :
if drawpass==c4d.DRAWPASS_OBJECT:
self.GetAxisMotion(node, node.GetAbsPos(), node.GetAbsRot(), node.GetAbsScale(), node.GetRad()*2)
and inside the self.GetAxisMotion() function I can recalculate the children´s matrices like you showed above:
def GetAxisMotion(self, node, pos, rot, sca, bbox) :
doc = c4d.documents.GetActiveDocument()
if doc.GetMode()==c4d.Mmodel: #model mode or 11
print bbox
elif doc.GetMode()==c4d.Mobject: #object mode or 1
print sca
print pos
print rot
Thanks for the help
and your patience Scott
Cheers
Martin
On 31/07/2014 at 07:38, xxxxxxxx wrote:
Glad you got it worked out.
I didn't understand that you were looking for a sort of trigger event that would execute your Move Parent code.
Dirty can sometimes help you detect when an object is moved too:
#Get & Set the object's dirty value
getDirt = op.GetDirty(c4d.DIRTY_DATA|c4d.DIRTY_MATRIX |c4d.DIRTY_CHILDREN|c4d.DIRTY_CACHE|c4d.DIRTY_SELECT)
setDirt = op.SetDirty(c4d.DIRTY_DATA|c4d.DIRTY_MATRIX |c4d.DIRTY_CHILDREN|c4d.DIRTY_CACHE|c4d.DIRTY_SELECT)
-ScottA