[SOLVED] Retain global position and scale of element when reparenting

My current hierarchy looks like this

2D Screen
-ParentOne (Image Element covering left half of 2D screen)
-Child (Image Element covering left half of ParentOne)
-ParentTwo (Image Element covering right half of 2D screen)

When I call Child.reparent(ParentTwo,0); my hierarchy will change to this.
-2D Screen
-ParentOne
-ParentTwo
-Child (Now Image Element covering left half of ParentTwo)

Since the local position and local scale data is retained instead of the global data, the Child Image element will pop into the left half of ParentTwo. I’d like to retain the global position and scale so after calling reparent the Child object will stay in the same global position/scale it was in. I’m not sure how to do it.

I’m thinking it would work something like
//Store parent info
Child.reparent(ParentTwo,0);
//Reapply stored parent info

but I’m not sure what Info I’d need to store and how to re-apply it. Thanks for the help!

Does it work if you save the position / rotation / scale of the child first and then reset them after reparenting? Something like:

var pos = child.getPosition().clone();
var rot = child.getRotation().clone();
var scale = child.getScale().clone();
child.reparent...
child.setPosition(pos);
child.setRotation(rot);
child.setLocalScale(scale); 
1 Like

That gets me two for three. I’ve been able to get the position and rotation to stick this way. However using getLocalScale and setLocalScale doesn’t bring in the right values. I don’t see a global getScale or setScale in the docs and I’d need that to get the right values.

Also this problem gets more tricky because I’m using the new UI stuff. My entity.scale is correct by default (because all of my scales are 1,1,1). But I need a way to get the right Element data to fill in at the new parent.

Yeah that’s a bit tricky. If you are using uniform scale (so if scale.x, scale.y, scale.z are equal) you could do something like this:

var mat = child.getWorldTransform().clone();
var parentMat = parent2.getWorldTransform().clone().invert();
mat.mul2(parentMat, mat);
var pos = mat.getTranslation();
var rot = new pc.Quat().setFromMat4(mat);
var scale = mat.getScale();

child.reparent(parent2);    
        
child.setLocalPosition(pos);
child.setLocalRotation(rot);
child.setLocalScale(scale);

What this does basically is it gets the world transform of the child, transforms it into the new parent’s space and then gets the position, rotation, scale from the transformed matrix and assigns them to the reparented child.

2 Likes

Thanks a lot! I am facing the same problem and it works prefectly!

And what should be changed here in case the scale isn’t uniform?

1 Like