Files
pronature-platform/src/components/InteractiveObjects/ClassicPuzzle.js
T
2026-02-04 18:12:19 +02:00

89 lines
3.5 KiB
JavaScript

import { Color, Group, DoubleSide, RepeatWrapping, MeshStandardMaterial } from "three"
import { EventManager } from '@/lib/EventManager';
import { centerOrigin } from "@/lib/MeshUtils";
class ClassicPuzzle extends EventManager {
emits = ['finish', 'interaction']
constructor(engine, data, objPrefix='Plane'){
super();
const container = new Group();
const that = this;
return new Promise(async (resolve, reject)=>{
let gltf = await engine.load(`puzzle-${data.dimension}.glb`, '/static/meshes/classic-puzzle/');
let map = await engine.loadTexture(data.$go.asset.name);
map.wrapS = RepeatWrapping;
map.wrapT = RepeatWrapping;
map.flipY = false;
map.needsUpdate = true;
let dragZone = gltf.scene.getObjectByName('DragZone');
dragZone.material.side = DoubleSide;
let eventsFn= {
start(){
that.dispatchEvent({type:'interaction'});
},
drag(){},
end(e){
if (Math.abs(e.o.position.x)<.1 && Math.abs(e.o.position.y)<.1){
e.o.position.set(0,0,0);
engine.draggable.remove(e.o);
e.o.material = doneMaterial;
done++;
if (done == pCount){
doneMaterial.emissiveIntensity = .5;
engine.motionQueue.add({
o: doneMaterial,
t:1.5,
d:1,
a:{ emissiveIntensity:0 },
f:()=>{
that.dispatchEvent({type:'finish'})
}
});
}
}
}
}
let pCount = 0;
dragZone.visible = false;
let defaultMaterial = new MeshStandardMaterial({
map, emissiveIntensity: 0.05, lightMapIntensity: 10, side:DoubleSide, roughness: 1, metalness: 0,
})
gltf.scene.children.forEach((o, i)=>{
if (o.name.startsWith(objPrefix)){
let pp = o.clone();
container.add(pp);
defaultMaterial.emissiveMap ??= pp.material.emissiveMap;
pp.material = defaultMaterial;
pp.position.set(2*Math.random()-1, 2*Math.random() - 1, 0.01*(i+1));
engine.draggable.add(pp, dragZone, eventsFn);
pCount++;
}
});
let doneMaterial = defaultMaterial.clone();
doneMaterial.emissive = new Color(10,114,10);
defaultMaterial.emissive = new Color(114,10,10);
engine.motionQueue.add(
{
o: defaultMaterial,
r: true,
t:1.5,
d:1,
rd:true,
a:{emissiveIntensity:function(k){return .05*Math.sin(k*3.14);}}
});
let done0 = container.children[Math.floor(Math.random() * container.children.length)];
let done = 1;
done0.material = doneMaterial;
done0.position.set(0,0,0);
engine.draggable.remove(done0)
container.add(dragZone);
this.object = centerOrigin(container);
resolve(this);
})
}
}
export { ClassicPuzzle }