Hello,
I am currently using the Studio:World Effects template to create my scene.
I need help with making the object disapear unless I tap on the screen (meaning that the scene should only open to the UI element, and the object only show up when I tap), and the UI element to disappear once I tap.
I would also love to know how I can prompt audio with the tap as well. Thank you so much.
Below is my 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()
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: 1.0, // Default minimum scale is 1.0
maxScale: 3.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
const toFinished = ecs.defineTrigger()
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:', newGroundEntity)
return
}
const intersects = raycaster.intersectObject(groundObject, true)
if (intersects.length > 0) {
touchPoint.setFrom(intersects[0].point)
const prompt = document.getElementById('promptText')
if (prompt) {
prompt.style.display = 'none'
}
const 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())
} 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,
})
toFinished.trigger()
}
}
ecs.defineState('finished')
ecs.defineState('tapping')
.initial()
.onEnter(() => {
window.addEventListener('click', handleInteraction)
window.addEventListener('touchstart', handleInteraction)
})
.onExit(() => {
window.removeEventListener('click', handleInteraction)
window.removeEventListener('touchstart', handleInteraction)
})
.onTrigger(toFinished, 'finished')
},
})
@GeorgeButler Hi George, I met with Pablo a few weeks ago about a technical issue as well. Was hoping to hear your thoughts on this, thanks a lot!