diff --git a/src/components/map/MapControls.js b/src/components/map/MapControls.js index 7f5bfdf..9090bf0 100644 --- a/src/components/map/MapControls.js +++ b/src/components/map/MapControls.js @@ -1,4 +1,4 @@ -import React, { useState, Fragment, useRef } from "react"; +import React, { useState, Fragment } from "react"; import { IconButton, Flex, Box } from "theme-ui"; import RadioIconButton from "./controls/RadioIconButton"; @@ -144,9 +144,6 @@ function MapContols({ ); } - const controlsRef = useRef(); - const settingsRef = useRef(); - function getToolSettings() { const Settings = toolsById[selectedToolId].SettingsComponent; if (Settings) { @@ -161,7 +158,6 @@ function MapContols({ borderRadius: "4px", }} p={1} - ref={settingsRef} > {controls} diff --git a/src/components/map/MapDice.js b/src/components/map/MapDice.js index 87e3b63..fc64c04 100644 --- a/src/components/map/MapDice.js +++ b/src/components/map/MapDice.js @@ -1,200 +1,39 @@ -import React, { useRef, useState, useCallback } from "react"; -import * as BABYLON from "babylonjs"; -import { Box } from "theme-ui"; +import React, { useState } from "react"; +import { Flex, IconButton } 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"; +import ExpandMoreDiceIcon from "../../icons/ExpandMoreDiceIcon"; +import DiceTray from "./dice/DiceTray"; 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]); - } - } + const [isExpanded, setIsExpanded] = useState(false); return ( - - -
setIsExpanded(!isExpanded)} + sx={{ + transform: `rotate(${isExpanded ? "0" : "180deg"})`, + display: "block", + backgroundColor: "overlay", + borderRadius: "50%", }} + m={2} > - {dieNumbers.map((num, index) => ( -

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

- ))} -

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

-
-
- - - - - - -
-
+ + + + ); } diff --git a/src/components/map/MapDiceScene.js b/src/components/map/dice/DiceScene.js similarity index 98% rename from src/components/map/MapDiceScene.js rename to src/components/map/dice/DiceScene.js index 07c8780..9f4605c 100644 --- a/src/components/map/MapDiceScene.js +++ b/src/components/map/dice/DiceScene.js @@ -3,7 +3,7 @@ import * as BABYLON from "babylonjs"; import * as AMMO from "ammo.js"; import "babylonjs-loaders"; -function MapDiceScene({ onSceneMount }) { +function DiceScene({ onSceneMount }) { const sceneRef = useRef(); const engineRef = useRef(); const canvasRef = useRef(); @@ -121,4 +121,4 @@ function MapDiceScene({ onSceneMount }) { ); } -export default MapDiceScene; +export default DiceScene; diff --git a/src/components/map/dice/DiceTray.js b/src/components/map/dice/DiceTray.js new file mode 100644 index 0000000..850e1dd --- /dev/null +++ b/src/components/map/dice/DiceTray.js @@ -0,0 +1,209 @@ +import React, { useRef, useState, useCallback, useEffect } 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 "./DiceScene"; + +function DiceTray({ isOpen }) { + const sceneRef = useRef(); + const dieRef = useRef([]); + const dieSleepRef = useRef([]); + const [dieNumbers, setDieNumbers] = useState([]); + + const sceneSleepRef = useRef(true); + + useEffect(() => { + if (!isOpen) { + sceneSleepRef.current = true; + } else { + sceneSleepRef.current = false; + } + }, [isOpen]); + + 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", -35, 0, Math.PI / 2); + createWall("wallBottom", 0, 35, Math.PI); + createWall("wallLeft", 35, 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; + const shouldSleep = sceneSleepRef.current; + if (die.length === 0 || shouldSleep) { + 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 DiceTray; diff --git a/src/icons/ExpandMoreDiceIcon.js b/src/icons/ExpandMoreDiceIcon.js new file mode 100644 index 0000000..69a60d9 --- /dev/null +++ b/src/icons/ExpandMoreDiceIcon.js @@ -0,0 +1,18 @@ +import React from "react"; + +function ExpandMoreDiceIcon() { + return ( + + + + + ); +} + +export default ExpandMoreDiceIcon;