import React, { useRef, useState, useCallback } from "react"; import * as BABYLON from "babylonjs"; import { Box } from "theme-ui"; import environment from "../../dice/environment.dds"; import ColorDice from "../../dice/color/ColorDice"; import GemStoneDice from "../../dice/gemStone/GemStoneDice"; import GlassDice from "../../dice/glass/GlassDice"; import MetalDice from "../../dice/metal/MetalDice"; import MetalStoneDice from "../../dice/metalStone/MetalStoneDice"; import WoodDice from "../../dice/wood/WoodDice"; import Scene from "./MapDiceScene"; function MapDice() { const sceneRef = useRef(); const dieRef = useRef([]); const dieSleepRef = useRef([]); const [dieNumbers, setDieNumbers] = useState([]); const handleSceneMount = useCallback(({ scene, engine }) => { sceneRef.current = scene; initializeScene(scene); engine.runRenderLoop(() => update(scene)); }, []); async function initializeScene(scene) { var ground = BABYLON.Mesh.CreateGround("ground", 100, 100, 2, scene); ground.physicsImpostor = new BABYLON.PhysicsImpostor( ground, BABYLON.PhysicsImpostor.BoxImpostor, { mass: 0, friction: 100.0 }, scene ); ground.isVisible = false; function createWall(name, x, z, yaw) { let wall = BABYLON.Mesh.CreateBox( name, 50, scene, true, BABYLON.Mesh.DOUBLESIDE ); wall.rotation = new BABYLON.Vector3(0, yaw, 0); wall.position.z = z; wall.position.x = x; wall.physicsImpostor = new BABYLON.PhysicsImpostor( wall, BABYLON.PhysicsImpostor.BoxImpostor, { mass: 0, friction: 1.0 }, scene ); wall.isVisible = false; } createWall("wallTop", 0, -35, 0); createWall("wallRight", -39, 0, Math.PI / 2); createWall("wallBottom", 0, 35, Math.PI); createWall("wallLeft", 39, 0, -Math.PI / 2); var roof = BABYLON.Mesh.CreateGround("roof", 100, 100, 2, scene); roof.physicsImpostor = new BABYLON.PhysicsImpostor( roof, BABYLON.PhysicsImpostor.BoxImpostor, { mass: 0, friction: 1.0 }, scene ); roof.position.y = 10; roof.isVisible = false; scene.environmentTexture = BABYLON.CubeTexture.CreateFromPrefilteredData( environment, scene ); scene.environmentIntensity = 1.5; } function update(scene) { const die = dieRef.current; if (die.length === 0) { return; } for (let i = 0; i < die.length; i++) { const dice = die[i]; const diceAsleep = dieSleepRef.current[i]; const speed = dice.physicsImpostor.getLinearVelocity().length(); if (speed < 0.01 && !diceAsleep) { let highestDot = -1; let highestLocator; for (let locator of dice.getChildTransformNodes()) { let dif = locator .getAbsolutePosition() .subtract(dice.getAbsolutePosition()); let direction = dif.normalize(); const dot = BABYLON.Vector3.Dot(direction, BABYLON.Vector3.Up()); if (dot > highestDot) { highestDot = dot; highestLocator = locator; } } dieSleepRef.current[i] = true; const newNumber = parseInt(highestLocator.name.slice(8)); setDieNumbers((prevNumbers) => { let newNumbers = [...prevNumbers]; newNumbers[i] = newNumber; return newNumbers; }); } else if (speed > 0.5 && diceAsleep) { dieSleepRef.current[i] = false; setDieNumbers((prevNumbers) => { let newNumbers = [...prevNumbers]; newNumbers[i] = null; return newNumbers; }); } } if (scene) { scene.render(); } } async function handleAddDice(style, type) { const scene = sceneRef.current; if (scene) { const instance = await style.createInstance(type, scene); dieRef.current.push(instance); dieSleepRef.current.push(false); setDieNumbers((prevNumbers) => [...prevNumbers, null]); } } return (
{dieNumbers.map((num, index) => (

{num || "?"} {index === dieNumbers.length - 1 ? "" : "+"}

))}

{dieNumbers.length > 0 && `= ${dieNumbers.reduce((a, b) => (a || 0) + (b || 0))}`}

); } export default MapDice;