Added expand controls to map dice
This commit is contained in:
@@ -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 (
|
||||
<Box
|
||||
<Flex
|
||||
sx={{
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: "500px",
|
||||
height: "500px",
|
||||
borderRadius: "4px",
|
||||
flexDirection: "column",
|
||||
alignItems: "flex-start",
|
||||
}}
|
||||
bg="overlay"
|
||||
m={2}
|
||||
ml={1}
|
||||
>
|
||||
<Scene onSceneMount={handleSceneMount} />
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: "8px",
|
||||
left: "50%",
|
||||
transform: "translateX(-50%)",
|
||||
display: "flex",
|
||||
color: "white",
|
||||
<IconButton
|
||||
aria-label={isExpanded ? "Hide Dice Tray" : "Show Dice Tray"}
|
||||
title={isExpanded ? "Hide Dice Tray" : "Show Dice Tray"}
|
||||
onClick={() => setIsExpanded(!isExpanded)}
|
||||
sx={{
|
||||
transform: `rotate(${isExpanded ? "0" : "180deg"})`,
|
||||
display: "block",
|
||||
backgroundColor: "overlay",
|
||||
borderRadius: "50%",
|
||||
}}
|
||||
m={2}
|
||||
>
|
||||
{dieNumbers.map((num, index) => (
|
||||
<h3 key={index}>
|
||||
{num || "?"}
|
||||
{index === dieNumbers.length - 1 ? "" : "+"}
|
||||
</h3>
|
||||
))}
|
||||
<h3>
|
||||
{dieNumbers.length > 0 &&
|
||||
`= ${dieNumbers.reduce((a, b) => (a || 0) + (b || 0))}`}
|
||||
</h3>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
bottom: "24px",
|
||||
left: "50%",
|
||||
transform: "translateX(-50%)",
|
||||
}}
|
||||
>
|
||||
<button onClick={() => handleAddDice(ColorDice, "d20")}>
|
||||
Add color d20
|
||||
</button>
|
||||
<button onClick={() => handleAddDice(GemStoneDice, "d20")}>
|
||||
Add gem d20
|
||||
</button>
|
||||
<button onClick={() => handleAddDice(GlassDice, "d20")}>
|
||||
Add glass d20
|
||||
</button>
|
||||
<button onClick={() => handleAddDice(MetalDice, "d20")}>
|
||||
Add metal d20
|
||||
</button>
|
||||
<button onClick={() => handleAddDice(MetalStoneDice, "d20")}>
|
||||
Add metal stone d20
|
||||
</button>
|
||||
<button onClick={() => handleAddDice(WoodDice, "d20")}>
|
||||
Add wood d20
|
||||
</button>
|
||||
</div>
|
||||
</Box>
|
||||
<ExpandMoreDiceIcon />
|
||||
</IconButton>
|
||||
<DiceTray isOpen={isExpanded} />
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user