Reparent object but keep world position

I would like to assign a new parent to my object but keep its position in the world. For example:

myParent.addChild(myChild);
myParent.transform.x = -2;
myParent.transform.z = 3;

Now when I assign myChild to another parent like this:
myNewParent.addChild(myChild);

The local transform will be reset to (0, 0), thus changing the world position of the object, which is not the behavior I’d expect. What I would expect is the local transform to be updated relative to the new parent. This is how things work in other 3D Editors like Unity, Blender etc.

Is there a way to reparent an object and keep the world position, preferable without messing around with the worldTransform?

I want to avoid worldTransform as there is no way to retrieve their current value on demand - pinLastValue on the worldTransform will always return zero, no matter at what point in the filter lifetime it is called.

I would really avoid using pinLastValue. I think it’s a relic of the past, and monitoring values is the way to go now. You can even get a single value, on demand, from a signal monitor (with a little bit of extra setup).


const R = require('Reactive')
const Scene = require('Scene')
const {log} = require('Diagnostics')

// call this whenever you need to grab the value of a point signal
function getPointSignalSnapshot(pointSignal){
  return new Promise((resolve, reject) => {
    const {x, y, z} = pointSignal
    R.monitorMany([x, y, z], {fireOnInitialValue: true}).take(1).subscribe((snapshot) => {
      const point = {
        x: snapshot.newValues[0],
        y: snapshot.newValues[1],
        z: snapshot.newValues[2]
      }
      resolve(point)
    })
  })
}

const init = (async function () {

  const plane = await Scene.root.findFirst('plane0')
  let pos = await getPointSignalSnapshot(plane.worldTransform.position)
  log(pos)

})()

It’s a little verbose, but you can stick this function in a separate file to keep your code clean :wink:

Anyway, this is the method I’d use to save the world position before reparenting the object. Then you can assign a new position after reparenting.

spark-point-signal-snapshot.zip (6.1 KB)

Thanks a lot for your help Josh, it’s working as expected. I also found another reliable way of getting snapshot values using the subscribeWithSnaphot signal watchers. In my case I needed to reparent the object as a result of a tap event and I could get the required values using:

TouchGestures.onTap(targetObj).subscribeWithSnapshot({
  objX: newParentObj.worldTransform.x,
  objY: newParentObj.worldTransform.y,
  objZ: newParentObj.worldTransform.z,
}, (event, snapshot) => {
  newParentObj.addChild(targetObj);
  targetObj.worldTransform.position = R.pack3(
    snapshot.objX, snapshot.objY, snapshot.objZ
  );
});

Cheers,
Andy