While I’ve worked in the Cloud Editor in the past, I’m new to Niantic Studio (and the new API) and I would really appreciate some help with writing a custom component that transfers an entity group from being pinned to an image target, to being SLAM-tracked.
Problem summary
Here’s the basic rundown of the project:
I have a mural of Martin Luther King on an office wall as an image target that, when scanned, displays a group of entities (a lectern and a set of three microphones). These entities are all parented to an empty object, called “mlk-content,” so that they can be positioned as a group. The entity-group is then parented to the image target (called, “mlkMural”):
Once the “mlk-content” entity group appears, I need for them to stay pinned in place within the room and remain visible/interactable, even when the mural image-target is no longer visible. In other words, I’m trying to enable users to look around the lectern and microphones, which means they will occasionally need to turn away from the mural.
Proposed design approach
My approach to this was to have the lectern/microphone entity group initially parented to the image target, so that they will be positioned relative to the mural, and then use a custom component called, “transferToWorldTracking.ts” that would do the following:
- listen for the image-target found event
- when found, it would store the entity group’s worldTransform into a variable
- re-parent the entity group from the image target, to a root level empty entity (called, “worldRoot”)
- re-apply the entity group’s worldTransform
- allow the entity group to remain SLAM-tracked from then on, so that it no longer needs the image target in view.
The transferring of the entity group from image-tracking to SLAM-tracking would only happen once, after the initial finding of the image target (and positioning of its child entities).
First, of all, is this a sound approach for handling this, or is there a better way?
Second, here is my custom component script, as far as I was able to figure it out:
Code snippet
import * as ecs from '@8thwall/ecs'
ecs.registerComponent({
name: 'transferToWorldTracking',
schema: {
imageAnchor: ecs.eid,
imageAnchorName: ecs.string,
contentToTransfer: ecs.eid,
worldRoot: ecs.eid,
},
schemaDefaults: {
imageAnchorName: '',
},
data: {
transferred: ecs.boolean,
},
stateMachine: ({world, eid, schemaAttribute, dataAttribute}) => {
ecs.defineState('default')
.initial()
.listen(world.events.globalId, 'reality.imagefound', (e) => {
const {name} = e.data as any
const {imageAnchorName} = schemaAttribute.get(eid)
const {imageAnchor} = schemaAttribute.get(eid)
const {contentToTransfer} = schemaAttribute.get(eid)
const {worldRoot} = schemaAttribute.get(eid)
if (name === imageAnchorName) {
if (this.transferred) return
this.transferred = true
// store transform for the content attachd to image target
// re-parent the content from the image target to the world (SLAM)
world.setParent(contentToTransfer, worldRoot)
// restore content's world transform now that it is pinned to world
// world.transform.setWorldTransform()
}
})
},
})
(I havent’ been able to figure out how to store the worldTransform without TypeError(s).)
Can anyone help me out with this, or at least point me in the right direction?
Thank you!!
