Separated dice loading and dice instance creation and added loading spinner for dice
This commit is contained in:
parent
da84f923d1
commit
7f0b4e32af
@ -4,6 +4,8 @@ import { Flex, IconButton } from "theme-ui";
|
|||||||
import ExpandMoreDiceIcon from "../../icons/ExpandMoreDiceIcon";
|
import ExpandMoreDiceIcon from "../../icons/ExpandMoreDiceIcon";
|
||||||
import DiceTrayOverlay from "./dice/DiceTrayOverlay";
|
import DiceTrayOverlay from "./dice/DiceTrayOverlay";
|
||||||
|
|
||||||
|
import { DiceLoadingProvider } from "../../contexts/DiceLoadingContext";
|
||||||
|
|
||||||
function MapDice() {
|
function MapDice() {
|
||||||
const [isExpanded, setIsExpanded] = useState(false);
|
const [isExpanded, setIsExpanded] = useState(false);
|
||||||
|
|
||||||
@ -32,7 +34,9 @@ function MapDice() {
|
|||||||
>
|
>
|
||||||
<ExpandMoreDiceIcon isExpanded={isExpanded} />
|
<ExpandMoreDiceIcon isExpanded={isExpanded} />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
|
<DiceLoadingProvider>
|
||||||
<DiceTrayOverlay isOpen={isExpanded} />
|
<DiceTrayOverlay isOpen={isExpanded} />
|
||||||
|
</DiceLoadingProvider>
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { Flex, IconButton } from "theme-ui";
|
import { Flex, IconButton } from "theme-ui";
|
||||||
|
|
||||||
import D20Icon from "../../../icons/D20Icon";
|
import D20Icon from "../../../icons/D20Icon";
|
||||||
@ -20,10 +20,18 @@ import { dice } from "../../../dice";
|
|||||||
function DiceButtons({
|
function DiceButtons({
|
||||||
diceRolls,
|
diceRolls,
|
||||||
onDiceAdd,
|
onDiceAdd,
|
||||||
|
onDiceLoad,
|
||||||
diceTraySize,
|
diceTraySize,
|
||||||
onDiceTraySizeChange,
|
onDiceTraySizeChange,
|
||||||
}) {
|
}) {
|
||||||
const [currentDice, setCurrentDice] = useState(dice[0]);
|
const [currentDice, setCurrentDice] = useState();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const initialDice = dice[0];
|
||||||
|
onDiceLoad(initialDice);
|
||||||
|
setCurrentDice(initialDice);
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
|
||||||
const diceCounts = {};
|
const diceCounts = {};
|
||||||
for (let dice of diceRolls) {
|
for (let dice of diceRolls) {
|
||||||
@ -34,6 +42,11 @@ function DiceButtons({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function handleDiceChange(dice) {
|
||||||
|
await onDiceLoad(dice);
|
||||||
|
setCurrentDice(dice);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
sx={{
|
sx={{
|
||||||
@ -44,7 +57,7 @@ function DiceButtons({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<SelectDiceButton
|
<SelectDiceButton
|
||||||
onDiceChange={setCurrentDice}
|
onDiceChange={handleDiceChange}
|
||||||
currentDice={currentDice}
|
currentDice={currentDice}
|
||||||
/>
|
/>
|
||||||
<Divider vertical color="hsl(210, 50%, 96%)" />
|
<Divider vertical color="hsl(210, 50%, 96%)" />
|
||||||
|
@ -10,6 +10,7 @@ function DiceControls({
|
|||||||
onDiceAdd,
|
onDiceAdd,
|
||||||
onDiceClear,
|
onDiceClear,
|
||||||
onDiceReroll,
|
onDiceReroll,
|
||||||
|
onDiceLoad,
|
||||||
diceTraySize,
|
diceTraySize,
|
||||||
onDiceTraySizeChange,
|
onDiceTraySizeChange,
|
||||||
}) {
|
}) {
|
||||||
@ -116,6 +117,7 @@ function DiceControls({
|
|||||||
{ type, roll: "unknown" },
|
{ type, roll: "unknown" },
|
||||||
]);
|
]);
|
||||||
}}
|
}}
|
||||||
|
onDiceLoad={onDiceLoad}
|
||||||
onDiceTraySizeChange={onDiceTraySizeChange}
|
onDiceTraySizeChange={onDiceTraySizeChange}
|
||||||
diceTraySize={diceTraySize}
|
diceTraySize={diceTraySize}
|
||||||
/>
|
/>
|
||||||
|
@ -13,10 +13,12 @@ import environment from "../../../dice/environment.dds";
|
|||||||
import Scene from "./DiceScene";
|
import Scene from "./DiceScene";
|
||||||
import DiceControls from "./DiceControls";
|
import DiceControls from "./DiceControls";
|
||||||
import Dice from "../../../dice/Dice";
|
import Dice from "../../../dice/Dice";
|
||||||
|
import LoadingOverlay from "../../LoadingOverlay";
|
||||||
|
|
||||||
import DiceTray from "../../../dice/diceTray/DiceTray";
|
import DiceTray from "../../../dice/diceTray/DiceTray";
|
||||||
|
|
||||||
import MapInteractionContext from "../../../contexts/MapInteractionContext";
|
import MapInteractionContext from "../../../contexts/MapInteractionContext";
|
||||||
|
import DiceLoadingContext from "../../../contexts/DiceLoadingContext";
|
||||||
|
|
||||||
function DiceTrayOverlay({ isOpen }) {
|
function DiceTrayOverlay({ isOpen }) {
|
||||||
const sceneRef = useRef();
|
const sceneRef = useRef();
|
||||||
@ -29,6 +31,10 @@ function DiceTrayOverlay({ isOpen }) {
|
|||||||
const diceTrayRef = useRef();
|
const diceTrayRef = useRef();
|
||||||
|
|
||||||
const [diceTraySize, setDiceTraySize] = useState("single");
|
const [diceTraySize, setDiceTraySize] = useState("single");
|
||||||
|
const { assetLoadStart, assetLoadFinish, isLoading } = useContext(
|
||||||
|
DiceLoadingContext
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const diceTray = diceTrayRef.current;
|
const diceTray = diceTrayRef.current;
|
||||||
let resizeTimout;
|
let resizeTimout;
|
||||||
@ -70,9 +76,11 @@ function DiceTrayOverlay({ isOpen }) {
|
|||||||
sceneRef.current = scene;
|
sceneRef.current = scene;
|
||||||
initializeScene(scene);
|
initializeScene(scene);
|
||||||
engine.runRenderLoop(() => update(scene));
|
engine.runRenderLoop(() => update(scene));
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
async function initializeScene(scene) {
|
async function initializeScene(scene) {
|
||||||
|
assetLoadStart();
|
||||||
let light = new BABYLON.DirectionalLight(
|
let light = new BABYLON.DirectionalLight(
|
||||||
"DirectionalLight",
|
"DirectionalLight",
|
||||||
new BABYLON.Vector3(-0.5, -1, -0.5),
|
new BABYLON.Vector3(-0.5, -1, -0.5),
|
||||||
@ -95,6 +103,7 @@ function DiceTrayOverlay({ isOpen }) {
|
|||||||
let diceTray = new DiceTray("single", scene, shadowGenerator);
|
let diceTray = new DiceTray("single", scene, shadowGenerator);
|
||||||
await diceTray.load();
|
await diceTray.load();
|
||||||
diceTrayRef.current = diceTray;
|
diceTrayRef.current = diceTray;
|
||||||
|
assetLoadFinish();
|
||||||
}
|
}
|
||||||
|
|
||||||
function update(scene) {
|
function update(scene) {
|
||||||
@ -194,6 +203,15 @@ function DiceTrayOverlay({ isOpen }) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function handleDiceLoad(dice) {
|
||||||
|
assetLoadStart();
|
||||||
|
const scene = sceneRef.current;
|
||||||
|
if (scene) {
|
||||||
|
await dice.class.load(scene);
|
||||||
|
}
|
||||||
|
assetLoadFinish();
|
||||||
|
}
|
||||||
|
|
||||||
const { setPreventMapInteraction } = useContext(MapInteractionContext);
|
const { setPreventMapInteraction } = useContext(MapInteractionContext);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -229,9 +247,11 @@ function DiceTrayOverlay({ isOpen }) {
|
|||||||
onDiceAdd={handleDiceAdd}
|
onDiceAdd={handleDiceAdd}
|
||||||
onDiceClear={handleDiceClear}
|
onDiceClear={handleDiceClear}
|
||||||
onDiceReroll={handleDiceReroll}
|
onDiceReroll={handleDiceReroll}
|
||||||
|
onDiceLoad={handleDiceLoad}
|
||||||
diceTraySize={diceTraySize}
|
diceTraySize={diceTraySize}
|
||||||
onDiceTraySizeChange={setDiceTraySize}
|
onDiceTraySizeChange={setDiceTraySize}
|
||||||
/>
|
/>
|
||||||
|
{isLoading && <LoadingOverlay />}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
31
src/contexts/DiceLoadingContext.js
Normal file
31
src/contexts/DiceLoadingContext.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
|
||||||
|
const DiceLoadingContext = React.createContext();
|
||||||
|
|
||||||
|
export function DiceLoadingProvider({ children }) {
|
||||||
|
const [loadingAssetCount, setLoadingAssetCount] = useState(0);
|
||||||
|
|
||||||
|
function assetLoadStart() {
|
||||||
|
setLoadingAssetCount((prevLoadingAssets) => prevLoadingAssets + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function assetLoadFinish() {
|
||||||
|
setLoadingAssetCount((prevLoadingAssets) => prevLoadingAssets - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const isLoading = loadingAssetCount > 0;
|
||||||
|
|
||||||
|
const value = {
|
||||||
|
assetLoadStart,
|
||||||
|
assetLoadFinish,
|
||||||
|
isLoading,
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DiceLoadingContext.Provider value={value}>
|
||||||
|
{children}
|
||||||
|
</DiceLoadingContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DiceLoadingContext;
|
@ -8,7 +8,7 @@ class GalaxyDice extends Dice {
|
|||||||
static meshes;
|
static meshes;
|
||||||
static material;
|
static material;
|
||||||
|
|
||||||
static async createInstance(diceType, scene) {
|
static async load(scene) {
|
||||||
if (!this.material) {
|
if (!this.material) {
|
||||||
this.material = this.loadMaterial(
|
this.material = this.loadMaterial(
|
||||||
"galaxy_pbr",
|
"galaxy_pbr",
|
||||||
@ -19,6 +19,12 @@ class GalaxyDice extends Dice {
|
|||||||
if (!this.meshes) {
|
if (!this.meshes) {
|
||||||
this.meshes = await this.loadMeshes(this.material, scene);
|
this.meshes = await this.loadMeshes(this.material, scene);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async createInstance(diceType, scene) {
|
||||||
|
if (!this.material || !this.meshes) {
|
||||||
|
throw Error("Dice not loaded, call load before creating an instance");
|
||||||
|
}
|
||||||
|
|
||||||
return Dice.createInstance(
|
return Dice.createInstance(
|
||||||
this.meshes[diceType],
|
this.meshes[diceType],
|
||||||
|
@ -13,7 +13,7 @@ class IronDice extends Dice {
|
|||||||
return { mass: properties.mass * 2, friction: properties.friction };
|
return { mass: properties.mass * 2, friction: properties.friction };
|
||||||
}
|
}
|
||||||
|
|
||||||
static async createInstance(diceType, scene) {
|
static async load(scene) {
|
||||||
if (!this.material) {
|
if (!this.material) {
|
||||||
this.material = this.loadMaterial(
|
this.material = this.loadMaterial(
|
||||||
"iron_pbr",
|
"iron_pbr",
|
||||||
@ -24,6 +24,12 @@ class IronDice extends Dice {
|
|||||||
if (!this.meshes) {
|
if (!this.meshes) {
|
||||||
this.meshes = await this.loadMeshes(this.material, scene);
|
this.meshes = await this.loadMeshes(this.material, scene);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async createInstance(diceType, scene) {
|
||||||
|
if (!this.material || !this.meshes) {
|
||||||
|
throw Error("Dice not loaded, call load before creating an instance");
|
||||||
|
}
|
||||||
|
|
||||||
return Dice.createInstance(
|
return Dice.createInstance(
|
||||||
this.meshes[diceType],
|
this.meshes[diceType],
|
||||||
|
@ -8,10 +8,10 @@ class NebulaDice extends Dice {
|
|||||||
static meshes;
|
static meshes;
|
||||||
static material;
|
static material;
|
||||||
|
|
||||||
static async createInstance(diceType, scene) {
|
static async load(scene) {
|
||||||
if (!this.material) {
|
if (!this.material) {
|
||||||
this.material = this.loadMaterial(
|
this.material = this.loadMaterial(
|
||||||
"nebula_pbr",
|
"neubula_pbr",
|
||||||
{ albedo, metalRoughness, normal },
|
{ albedo, metalRoughness, normal },
|
||||||
scene
|
scene
|
||||||
);
|
);
|
||||||
@ -19,6 +19,12 @@ class NebulaDice extends Dice {
|
|||||||
if (!this.meshes) {
|
if (!this.meshes) {
|
||||||
this.meshes = await this.loadMeshes(this.material, scene);
|
this.meshes = await this.loadMeshes(this.material, scene);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async createInstance(diceType, scene) {
|
||||||
|
if (!this.material || !this.meshes) {
|
||||||
|
throw Error("Dice not loaded, call load before creating an instance");
|
||||||
|
}
|
||||||
|
|
||||||
return Dice.createInstance(
|
return Dice.createInstance(
|
||||||
this.meshes[diceType],
|
this.meshes[diceType],
|
||||||
|
@ -8,7 +8,7 @@ class SunriseDice extends Dice {
|
|||||||
static meshes;
|
static meshes;
|
||||||
static material;
|
static material;
|
||||||
|
|
||||||
static async createInstance(diceType, scene) {
|
static async load(scene) {
|
||||||
if (!this.material) {
|
if (!this.material) {
|
||||||
this.material = this.loadMaterial(
|
this.material = this.loadMaterial(
|
||||||
"sunrise_pbr",
|
"sunrise_pbr",
|
||||||
@ -19,6 +19,12 @@ class SunriseDice extends Dice {
|
|||||||
if (!this.meshes) {
|
if (!this.meshes) {
|
||||||
this.meshes = await this.loadMeshes(this.material, scene);
|
this.meshes = await this.loadMeshes(this.material, scene);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async createInstance(diceType, scene) {
|
||||||
|
if (!this.material || !this.meshes) {
|
||||||
|
throw Error("Dice not loaded, call load before creating an instance");
|
||||||
|
}
|
||||||
|
|
||||||
return Dice.createInstance(
|
return Dice.createInstance(
|
||||||
this.meshes[diceType],
|
this.meshes[diceType],
|
||||||
|
@ -8,7 +8,7 @@ class SunsetDice extends Dice {
|
|||||||
static meshes;
|
static meshes;
|
||||||
static material;
|
static material;
|
||||||
|
|
||||||
static async createInstance(diceType, scene) {
|
static async load(scene) {
|
||||||
if (!this.material) {
|
if (!this.material) {
|
||||||
this.material = this.loadMaterial(
|
this.material = this.loadMaterial(
|
||||||
"sunset_pbr",
|
"sunset_pbr",
|
||||||
@ -19,6 +19,12 @@ class SunsetDice extends Dice {
|
|||||||
if (!this.meshes) {
|
if (!this.meshes) {
|
||||||
this.meshes = await this.loadMeshes(this.material, scene);
|
this.meshes = await this.loadMeshes(this.material, scene);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async createInstance(diceType, scene) {
|
||||||
|
if (!this.material || !this.meshes) {
|
||||||
|
throw Error("Dice not loaded, call load before creating an instance");
|
||||||
|
}
|
||||||
|
|
||||||
return Dice.createInstance(
|
return Dice.createInstance(
|
||||||
this.meshes[diceType],
|
this.meshes[diceType],
|
||||||
|
@ -8,7 +8,7 @@ class WalnutDice extends Dice {
|
|||||||
static meshes;
|
static meshes;
|
||||||
static material;
|
static material;
|
||||||
|
|
||||||
static async createInstance(diceType, scene) {
|
static async load(scene) {
|
||||||
if (!this.material) {
|
if (!this.material) {
|
||||||
this.material = this.loadMaterial(
|
this.material = this.loadMaterial(
|
||||||
"walnut_pbr",
|
"walnut_pbr",
|
||||||
@ -19,6 +19,12 @@ class WalnutDice extends Dice {
|
|||||||
if (!this.meshes) {
|
if (!this.meshes) {
|
||||||
this.meshes = await this.loadMeshes(this.material, scene);
|
this.meshes = await this.loadMeshes(this.material, scene);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async createInstance(diceType, scene) {
|
||||||
|
if (!this.material || !this.meshes) {
|
||||||
|
throw Error("Dice not loaded, call load before creating an instance");
|
||||||
|
}
|
||||||
|
|
||||||
return Dice.createInstance(
|
return Dice.createInstance(
|
||||||
this.meshes[diceType],
|
this.meshes[diceType],
|
||||||
|
Loading…
Reference in New Issue
Block a user