I want to access the node of my model in niantic studio editor but i am not able to find it. how can i find a node of the model

Providing the code

import * as ecs from '@8thwall/ecs'

const {THREE} = (window as any)

// Components used by the Tap Place spawner
const {BoxGeometry, Material, Position, Quaternion, Scale, Shadow, ScaleAnimation} = ecs
const {vec3, quat} = ecs.math

const rgb = (color: number) => ({
  r: (color >> 16) % 256,  // eslint-disable-line no-bitwise
  g: (color >> 8) % 256,   // eslint-disable-line no-bitwise
  b: color % 256,
})

const componentsForClone = [
  Position, Quaternion, Scale, Shadow, BoxGeometry, Material, ScaleAnimation, ecs.PositionAnimation,
  ecs.RotateAnimation, ecs.CustomPropertyAnimation, ecs.CustomVec3Animation, ecs.FollowAnimation,
  ecs.LookAtAnimation, ecs.GltfModel, ecs.Collider, ecs.ParticleEmitter, ecs.Ui, ecs.Audio,
]

const cloneComponents = (sourceEid, targetEid, world) => {
  componentsForClone.forEach((component) => {
    if (component.has(world, sourceEid)) {
      const properties = component.get(world, sourceEid)
      component.set(world, targetEid, {...properties})
    }
  })
}

const q = quat.zero()
const v = vec3.zero()
const touchPoint = vec3.zero()
let isSpawned = false
let newEid = null

function findNodeByName(object3D, targetName) {
  let targetNode = null

  object3D.traverse((child) => {
    if (child.name === targetName) {
      targetNode = child
    }
  })

  return targetNode
}
ecs.registerComponent({
  name: 'Tap Place',
  schema: {
    entityToSpawn: ecs.eid,  // Entity ID for the entity to spawn
    groundEntity: ecs.eid,  // Entity ID for the ground object
    minScale: ecs.f32,  // Minimum scale for the spawned entity
    maxScale: ecs.f32,  // Maximum scale for the spawned entity
  },
  schemaDefaults: {
    minScale: 5.0,  // Default minimum scale is 1.0
    maxScale: 10.0,  // Default maximum scale is 3.0
  },
  stateMachine: ({world, eid, schemaAttribute}) => {
    const {groundEntity, entityToSpawn, minScale, maxScale} = schemaAttribute.get(eid)

    const raycaster = new THREE.Raycaster()
    const mouse = new THREE.Vector2()
    let lastInteractionTime = 0

    function handleInteraction(event) {
      if (!groundEntity) {
        console.error('Ground entity not set in schema')
        return
      }
      const newGroundEntity = schemaAttribute.get(eid).groundEntity
      const currentTime = Date.now()
      if (currentTime - lastInteractionTime < 500) {
        return
      }
      lastInteractionTime = currentTime

      if (event.touches) {
        mouse.x = (event.touches[0].clientX / window.innerWidth) * 2 - 1
        mouse.y = -(event.touches[0].clientY / window.innerHeight) * 2 + 1
      } else {
        mouse.x = (event.clientX / window.innerWidth) * 2 - 1
        mouse.y = -(event.clientY / window.innerHeight) * 2 + 1
      }

      raycaster.setFromCamera(mouse, world.three.activeCamera)

      const groundObject = world.three.entityToObject.get(newGroundEntity)

      if (!groundObject) {
        console.error('Ground object not found for entity ID:', ecs)
        return
      }

      const intersects = raycaster.intersectObject(groundObject, true)

      if (intersects.length > 0 && !isSpawned) {
        touchPoint.setFrom(intersects[0].point)

        const prompt = document.getElementById('promptText')
        if (prompt) {
          prompt.style.display = 'none'
        }

        newEid = world.createEntity()

        const randomScale = Math.random() * (maxScale - minScale) + minScale

        if (entityToSpawn) {
          // Clone an entity at the target position, with an initial scale of zero.
          cloneComponents(entityToSpawn, newEid, world)
          Position.set(world, newEid, touchPoint)
          Scale.set(world, newEid, v.makeZero())
          const spawnedObject = world.three.entityToObject.get(newEid)

          console.log('world scene', componentsForClone)
          if (spawnedObject) {
            console.log('Node names in the spawned model:')
            const baseNode = findNodeByName(world.scene, 'Base')
            if (baseNode) {
              console.log('Node "Base" found:', baseNode)
              // Perform operations on baseNode, like changing its properties
            }
          } else {
            console.error('Could not find Object3D for newEid:', newEid)
          }
          isSpawned = true
        } else {
          // If no clone entity is indicated, spawn a box instead.
          Position.set(world, newEid, v.setXyz(touchPoint.x, randomScale / 2, touchPoint.z))
          Quaternion.set(world, newEid, q.makeYDegrees(Math.random() * 360))
          Scale.set(world, newEid, v.makeZero())
          Shadow.set(world, newEid, {castShadow: true, receiveShadow: false})
          BoxGeometry.set(world, newEid, {width: 1, height: 1, depth: 1})
          Material.set(world, newEid, rgb(0xAE00FF))
        }

        ScaleAnimation.set(world, newEid, {
          fromX: 0,
          fromY: 0,
          fromZ: 0,
          toX: randomScale,
          toY: randomScale,
          toZ: randomScale,
          duration: 500,
          loop: false,
          easeIn: true,
          easeOut: true,
        })
      }
    }

    function playAnimation() {
      const randomScale = Math.random() * (maxScale - minScale) + minScale
      ScaleAnimation.set(world, newEid, {
        fromX: 0,
        fromY: 0,
        fromZ: 0,
        toX: randomScale,
        toY: randomScale,
        toZ: randomScale,
        duration: 500,
        loop: false,
        easeIn: true,
        easeOut: true,
      })
    }

    ecs.defineState('default').initial().onEnter(() => {
      window.addEventListener('click', handleInteraction)
      window.addEventListener('touchstart', handleInteraction)
    }).onExit(() => {
      window.removeEventListener('click', handleInteraction)
      window.removeEventListener('touchstart', handleInteraction)
    })
  },
})

Hi! Welcome to the forums!

I’d be happy to help, first could you provide a little context as to what you’re trying to achieve?

i have a 3d model (format glb) , it has multiple childs, i want to change the material of one of it’s child, basically i want to play the video texture on it’s child’s materialz

the code i am using right now is mentioned below , but it is not working

import * as ecs from '@8thwall/ecs'

const {THREE} = (window as any)

// Components used by the Tap Place spawner
const {BoxGeometry, Material, Position, Quaternion, Scale, Shadow, ScaleAnimation} = ecs
const {vec3, quat} = ecs.math

const rgb = (color: number) => ({
  r: (color >> 16) % 256,  // eslint-disable-line no-bitwise
  g: (color >> 8) % 256,   // eslint-disable-line no-bitwise
  b: color % 256,
})

const componentsForClone = [
  Position, Quaternion, Scale, Shadow, BoxGeometry, Material, ScaleAnimation, ecs.PositionAnimation,
  ecs.RotateAnimation, ecs.CustomPropertyAnimation, ecs.CustomVec3Animation, ecs.FollowAnimation,
  ecs.LookAtAnimation, ecs.GltfModel, ecs.Collider, ecs.ParticleEmitter, ecs.Ui, ecs.Audio,
]

const cloneComponents = (sourceEid, targetEid, world) => {
  componentsForClone.forEach((component) => {
    if (component.has(world, sourceEid)) {
      const properties = component.get(world, sourceEid)
      component.set(world, targetEid, {...properties})
    }
  })
}

const q = quat.zero()
const v = vec3.zero()
const touchPoint = vec3.zero()
let isSpawned = false
let newEid = null

function findNodeByName(object3D, targetName) {
  let targetNode = null

  object3D.traverse((child) => {
    if (child.name === targetName) {
      targetNode = child
    }
  })

  return targetNode
}
ecs.registerComponent({
  name: 'Tap Place',
  schema: {
    entityToSpawn: ecs.eid,  // Entity ID for the entity to spawn
    groundEntity: ecs.eid,  // Entity ID for the ground object
    minScale: ecs.f32,  // Minimum scale for the spawned entity
    maxScale: ecs.f32,  // Maximum scale for the spawned entity
  },
  schemaDefaults: {
    minScale: 5.0,  // Default minimum scale is 1.0
    maxScale: 10.0,  // Default maximum scale is 3.0
  },
  stateMachine: ({world, eid, schemaAttribute}) => {
    const {groundEntity, entityToSpawn, minScale, maxScale} = schemaAttribute.get(eid)

    const raycaster = new THREE.Raycaster()
    const mouse = new THREE.Vector2()
    let lastInteractionTime = 0

    function handleInteraction(event) {
      if (!groundEntity) {
        console.error('Ground entity not set in schema')
        return
      }
      const newGroundEntity = schemaAttribute.get(eid).groundEntity
      const currentTime = Date.now()
      if (currentTime - lastInteractionTime < 500) {
        return
      }
      lastInteractionTime = currentTime

      if (event.touches) {
        mouse.x = (event.touches[0].clientX / window.innerWidth) * 2 - 1
        mouse.y = -(event.touches[0].clientY / window.innerHeight) * 2 + 1
      } else {
        mouse.x = (event.clientX / window.innerWidth) * 2 - 1
        mouse.y = -(event.clientY / window.innerHeight) * 2 + 1
      }

      raycaster.setFromCamera(mouse, world.three.activeCamera)

      const groundObject = world.three.entityToObject.get(newGroundEntity)

      if (!groundObject) {
        console.error('Ground object not found for entity ID:', ecs)
        return
      }

      const intersects = raycaster.intersectObject(groundObject, true)

      if (intersects.length > 0 && !isSpawned) {
        touchPoint.setFrom(intersects[0].point)

        const prompt = document.getElementById('promptText')
        if (prompt) {
          prompt.style.display = 'none'
        }

        newEid = world.createEntity()

        const randomScale = Math.random() * (maxScale - minScale) + minScale

        if (entityToSpawn) {
          // Clone an entity at the target position, with an initial scale of zero.
          cloneComponents(entityToSpawn, newEid, world)
          Position.set(world, newEid, touchPoint)
          Scale.set(world, newEid, v.makeZero())
          const spawnedObject = world.three.entityToObject.get(newEid)

          console.log('world scene', world.getChildren(newEid))
          console.log('material', world.scene.children[7].children.length)
          if (spawnedObject) {
            console.log('Node names in the spawned model:')
            const baseNode = findNodeByName(world.scene, 'Base')
            if (baseNode) {
              console.log('Node "Base" found:', baseNode)
              // Perform operations on baseNode, like changing its properties
            }
          } else {
            console.error('Could not find Object3D for newEid:', newEid)
          }
          isSpawned = true
        } else {
          // If no clone entity is indicated, spawn a box instead.
          Position.set(world, newEid, v.setXyz(touchPoint.x, randomScale / 2, touchPoint.z))
          Quaternion.set(world, newEid, q.makeYDegrees(Math.random() * 360))
          Scale.set(world, newEid, v.makeZero())
          Shadow.set(world, newEid, {castShadow: true, receiveShadow: false})
          BoxGeometry.set(world, newEid, {width: 1, height: 1, depth: 1})
          Material.set(world, newEid, rgb(0xAE00FF))
        }

        ScaleAnimation.set(world, newEid, {
          fromX: 0,
          fromY: 0,
          fromZ: 0,
          toX: randomScale,
          toY: randomScale,
          toZ: randomScale,
          duration: 500,
          loop: false,
          easeIn: true,
          easeOut: true,
        })
      }
    }

    function playAnimation() {
      const randomScale = Math.random() * (maxScale - minScale) + minScale
      ScaleAnimation.set(world, newEid, {
        fromX: 0,
        fromY: 0,
        fromZ: 0,
        toX: randomScale,
        toY: randomScale,
        toZ: randomScale,
        duration: 500,
        loop: false,
        easeIn: true,
        easeOut: true,
      })
    }

    ecs.defineState('default').initial().onEnter(() => {
      window.addEventListener('click', handleInteraction)
      window.addEventListener('touchstart', handleInteraction)
    }).onExit(() => {
      window.removeEventListener('click', handleInteraction)
      window.removeEventListener('touchstart', handleInteraction)
    })
  },
})

@GeorgeButler
any idea how can we solve it ?

Hey Amit!

You need to traverse the nodes on the model. Here’s an example component that sets the material of every material on a GLTF

import * as ecs from '@8thwall/ecs'

const {THREE} = (window as any)

const applyHiderMaterial = (mesh: any) => {
  const hiderMaterial = new THREE.MeshStandardMaterial()
  hiderMaterial.colorWrite = false

  if (!mesh) {
    return
  }
  if (mesh.material) {
    mesh.material = hiderMaterial
  }
  mesh.traverse((node: any) => {
    if (node.isMesh) {
      node.material = hiderMaterial
    }
  })
}

ecs.registerComponent({
  name: 'hider-material',
  schema: {
    targetEntity: ecs.eid,  // Entity ID for the entity to apply the hider material
  },
  data: {
    applied: ecs.boolean,
  },
  add: (world, component) => {
    const {targetEntity} = component.schema

    if (!targetEntity) {
      console.error('Target entity not set in schema')
      return
    }

    component.data.applied = false
  },
  tick: (world, component) => {
    const {targetEntity} = component.schema

    if (component.data.applied) {
      return
    }

    const object3D = world.three.entityToObject.get(targetEntity)
    if (object3D && object3D.userData.gltf) {
      applyHiderMaterial(object3D)
      component.data.applied = true
    }
  },
})