diff --git a/src/components/Modal.js b/src/components/Modal.js index 94b9eda..28526e0 100644 --- a/src/components/Modal.js +++ b/src/components/Modal.js @@ -16,7 +16,7 @@ function StyledModal({ isOpen={isOpen} onRequestClose={onRequestClose} style={{ - overlay: { backgroundColor: "rgba(0, 0, 0, 0.73)" }, + overlay: { backgroundColor: "rgba(0, 0, 0, 0.73)", zIndex: 100 }, content: { backgroundColor: theme.colors.background, top: "50%", diff --git a/src/components/dice/DiceButtons.js b/src/components/dice/DiceButtons.js index d314697..6e1fe8d 100644 --- a/src/components/dice/DiceButtons.js +++ b/src/components/dice/DiceButtons.js @@ -9,6 +9,8 @@ import D6Icon from "../../icons/D6Icon"; import D4Icon from "../../icons/D4Icon"; import D100Icon from "../../icons/D100Icon"; import ExpandMoreDiceTrayIcon from "../../icons/ExpandMoreDiceTrayIcon"; +import ShareDiceOnIcon from "../../icons/ShareDiceOnIcon"; +import ShareDiceOffIcon from "../../icons/ShareDiceOffIcon"; import DiceButton from "./DiceButton"; import SelectDiceButton from "./SelectDiceButton"; @@ -23,6 +25,8 @@ function DiceButtons({ onDiceLoad, diceTraySize, onDiceTraySizeChange, + shareDice, + onShareDiceChange, }) { const [currentDice, setCurrentDice] = useState(dice[0]); @@ -129,6 +133,14 @@ function DiceButtons({ > + + onShareDiceChange(!shareDice)} + > + {shareDice ? : } + ); } diff --git a/src/components/dice/DiceControls.js b/src/components/dice/DiceControls.js index e4bccf3..9e002a4 100644 --- a/src/components/dice/DiceControls.js +++ b/src/components/dice/DiceControls.js @@ -1,85 +1,20 @@ -import React, { useEffect, useState } from "react"; -import * as BABYLON from "babylonjs"; +import React from "react"; import DiceButtons from "./DiceButtons"; import DiceResults from "./DiceResults"; function DiceControls({ - diceRefs, - sceneVisibleRef, onDiceAdd, onDiceClear, onDiceReroll, onDiceLoad, diceTraySize, onDiceTraySizeChange, + shareDice, + onShareDiceChage, + diceRolls, + onDiceRollsChange, }) { - const [diceRolls, setDiceRolls] = useState([]); - - // Update dice rolls - useEffect(() => { - // Find the number facing up on a dice object - function getDiceRoll(dice) { - let number = getDiceInstanceRoll(dice.instance); - // If the dice is a d100 add the d10 - if (dice.type === "d100") { - const d10Number = getDiceInstanceRoll(dice.d10Instance); - // Both zero set to 100 - if (d10Number === 0 && number === 0) { - number = 100; - } else { - number += d10Number; - } - } else if (dice.type === "d10" && number === 0) { - number = 10; - } - return { type: dice.type, roll: number }; - } - - // Find the number facing up on a mesh instance of a dice - function getDiceInstanceRoll(instance) { - let highestDot = -1; - let highestLocator; - for (let locator of instance.getChildTransformNodes()) { - let dif = locator - .getAbsolutePosition() - .subtract(instance.getAbsolutePosition()); - let direction = dif.normalize(); - const dot = BABYLON.Vector3.Dot(direction, BABYLON.Vector3.Up()); - if (dot > highestDot) { - highestDot = dot; - highestLocator = locator; - } - } - return parseInt(highestLocator.name.slice(12)); - } - - function updateDiceRolls() { - const die = diceRefs.current; - const sceneVisible = sceneVisibleRef.current; - if (!sceneVisible) { - return; - } - const diceAwake = die.map((dice) => dice.asleep).includes(false); - if (!diceAwake) { - return; - } - - let newRolls = []; - for (let i = 0; i < die.length; i++) { - const dice = die[i]; - let roll = getDiceRoll(dice); - newRolls[i] = roll; - } - setDiceRolls(newRolls); - } - - const updateInterval = setInterval(updateDiceRolls, 100); - return () => { - clearInterval(updateInterval); - }; - }, [diceRefs, sceneVisibleRef]); - return ( <>
{ onDiceClear(); - setDiceRolls([]); + onDiceRollsChange([]); }} onDiceReroll={onDiceReroll} /> @@ -114,14 +49,13 @@ function DiceControls({ diceRolls={diceRolls} onDiceAdd={(style, type) => { onDiceAdd(style, type); - setDiceRolls((prevRolls) => [ - ...prevRolls, - { type, roll: "unknown" }, - ]); + onDiceRollsChange([...diceRolls, { type, roll: "unknown" }]); }} onDiceLoad={onDiceLoad} onDiceTraySizeChange={onDiceTraySizeChange} diceTraySize={diceTraySize} + shareDice={shareDice} + onShareDiceChange={onShareDiceChage} />
diff --git a/src/components/dice/DiceTrayOverlay.js b/src/components/dice/DiceTrayOverlay.js index 99b6236..1610887 100644 --- a/src/components/dice/DiceTrayOverlay.js +++ b/src/components/dice/DiceTrayOverlay.js @@ -19,7 +19,15 @@ import DiceTray from "../../dice/diceTray/DiceTray"; import DiceLoadingContext from "../../contexts/DiceLoadingContext"; -function DiceTrayOverlay({ isOpen }) { +import { getDiceRoll } from "../../helpers/dice"; + +function DiceTrayOverlay({ + isOpen, + shareDice, + onShareDiceChage, + diceRolls, + onDiceRollsChange, +}) { const sceneRef = useRef(); const shadowGeneratorRef = useRef(); const diceRefs = useRef([]); @@ -251,6 +259,34 @@ function DiceTrayOverlay({ isOpen }) { }; }, [diceTraySize]); + // Update dice rolls + useEffect(() => { + function updateDiceRolls() { + const die = diceRefs.current; + const sceneVisible = sceneVisibleRef.current; + if (!sceneVisible) { + return; + } + const diceAwake = die.map((dice) => dice.asleep).includes(false); + if (!diceAwake) { + return; + } + + let newRolls = []; + for (let i = 0; i < die.length; i++) { + const dice = die[i]; + let roll = getDiceRoll(dice); + newRolls[i] = roll; + } + onDiceRollsChange(newRolls); + } + + const updateInterval = setInterval(updateDiceRolls, 100); + return () => { + clearInterval(updateInterval); + }; + }, [diceRefs, sceneVisibleRef, onDiceRollsChange]); + return ( {isLoading && ( } diff --git a/src/components/map/MapDice.js b/src/components/party/DiceTrayButton.js similarity index 75% rename from src/components/map/MapDice.js rename to src/components/party/DiceTrayButton.js index e40f109..ead662c 100644 --- a/src/components/map/MapDice.js +++ b/src/components/party/DiceTrayButton.js @@ -6,7 +6,12 @@ import DiceTrayOverlay from "../dice/DiceTrayOverlay"; import { DiceLoadingProvider } from "../../contexts/DiceLoadingContext"; -function MapDice() { +function DiceTrayButton({ + shareDice, + onShareDiceChage, + diceRolls, + onDiceRollsChange, +}) { const [isExpanded, setIsExpanded] = useState(false); return ( @@ -37,10 +42,16 @@ function MapDice() { - + ); } -export default MapDice; +export default DiceTrayButton; diff --git a/src/components/party/Party.js b/src/components/party/Party.js index a4bee8c..42324e1 100644 --- a/src/components/party/Party.js +++ b/src/components/party/Party.js @@ -8,6 +8,7 @@ import StartStreamButton from "./StartStreamButton"; import SettingsButton from "../SettingsButton"; import StartTimerButton from "./StartTimerButton"; import Timer from "./Timer"; +import DiceTrayButton from "./DiceTrayButton"; function Party({ nickname, @@ -22,6 +23,10 @@ function Party({ partyTimers, onTimerStart, onTimerStop, + shareDice, + onShareDiceChage, + diceRolls, + onDiceRollsChange, }) { return ( - + accumulator + dice.roll, 0) + }`} + /> {Object.entries(partyNicknames).map(([id, partyNickname]) => ( + + + ); } diff --git a/src/helpers/dice.js b/src/helpers/dice.js new file mode 100644 index 0000000..00f9450 --- /dev/null +++ b/src/helpers/dice.js @@ -0,0 +1,43 @@ +import * as BABYLON from "babylonjs"; + +/** + * Find the number facing up on a mesh instance of a dice + * @param {Object} instance The dice instance + */ +export function getDiceInstanceRoll(instance) { + let highestDot = -1; + let highestLocator; + for (let locator of instance.getChildTransformNodes()) { + let dif = locator + .getAbsolutePosition() + .subtract(instance.getAbsolutePosition()); + let direction = dif.normalize(); + const dot = BABYLON.Vector3.Dot(direction, BABYLON.Vector3.Up()); + if (dot > highestDot) { + highestDot = dot; + highestLocator = locator; + } + } + return parseInt(highestLocator.name.slice(12)); +} + +/** + * Find the number facing up on a dice object + * @param {Object} dice The Dice object + */ +export function getDiceRoll(dice) { + let number = getDiceInstanceRoll(dice.instance); + // If the dice is a d100 add the d10 + if (dice.type === "d100") { + const d10Number = getDiceInstanceRoll(dice.d10Instance); + // Both zero set to 100 + if (d10Number === 0 && number === 0) { + number = 100; + } else { + number += d10Number; + } + } else if (dice.type === "d10" && number === 0) { + number = 10; + } + return { type: dice.type, roll: number }; +} diff --git a/src/icons/ShareDiceOffIcon.js b/src/icons/ShareDiceOffIcon.js new file mode 100644 index 0000000..8834ac4 --- /dev/null +++ b/src/icons/ShareDiceOffIcon.js @@ -0,0 +1,18 @@ +import React from "react"; + +function ShareDiceOffIcon() { + return ( + + + + + ); +} + +export default ShareDiceOffIcon; diff --git a/src/icons/ShareDiceOnIcon.js b/src/icons/ShareDiceOnIcon.js new file mode 100644 index 0000000..0f4401d --- /dev/null +++ b/src/icons/ShareDiceOnIcon.js @@ -0,0 +1,18 @@ +import React from "react"; + +function ShareDiceOnIcon() { + return ( + + + + + ); +} + +export default ShareDiceOnIcon; diff --git a/src/network/NetworkedParty.js b/src/network/NetworkedParty.js index 522abc3..6590453 100644 --- a/src/network/NetworkedParty.js +++ b/src/network/NetworkedParty.js @@ -25,6 +25,9 @@ function NetworkedParty({ gameId, session }) { const [partyStreams, setPartyStreams] = useState({}); const [timer, setTimer] = useState(null); const [partyTimers, setPartyTimers] = useState({}); + const [diceRolls, setDiceRolls] = useState([]); + const [shareDice, setShareDice] = useState(false); + const [partyDiceRolls, setPartyDiceRolls] = useState({}); function handleNicknameChange(newNickname) { setNickname(newNickname); @@ -93,6 +96,14 @@ function NetworkedParty({ gameId, session }) { }; }, [timer, session]); + function handleDiceRollsChange(newDiceRolls) { + setDiceRolls(newDiceRolls); + } + + function handleShareDiceChange(newShareDice) { + setShareDice(newShareDice); + } + useEffect(() => { function handlePeerConnect({ peer, reply }) { reply("nickname", { [session.id]: nickname }); @@ -191,6 +202,10 @@ function NetworkedParty({ gameId, session }) { partyTimers={partyTimers} onTimerStart={handleTimerStart} onTimerStop={handleTimerStop} + shareDice={shareDice} + onShareDiceChage={handleShareDiceChange} + diceRolls={diceRolls} + onDiceRollsChange={handleDiceRollsChange} /> ); }