mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-28 21:19:52 +01:00
feat: start of rotation
This commit is contained in:
1 parent
d60551d30a
commit
10942879a6
7 files changed
+121
-18
No files matched your search
@@ -119,6 +119,7 @@
|
|||||||
"@react-three/fiber": "^9.3.0",
|
"@react-three/fiber": "^9.3.0",
|
||||||
"@types/react": "^19.1.14",
|
"@types/react": "^19.1.14",
|
||||||
"@types/react-dom": "^19.1.9",
|
"@types/react-dom": "^19.1.9",
|
||||||
|
"@types/three": "^0.180.0",
|
||||||
"@vite-pwa/astro": "^1.1.0",
|
"@vite-pwa/astro": "^1.1.0",
|
||||||
"astro": "^5.14.1",
|
"astro": "^5.14.1",
|
||||||
"astro-favicons": "^3.1.5",
|
"astro-favicons": "^3.1.5",
|
||||||
@@ -130,6 +131,8 @@
|
|||||||
"react": "^19.1.1",
|
"react": "^19.1.1",
|
||||||
"react-dom": "^19.1.1",
|
"react-dom": "^19.1.1",
|
||||||
"react-promise-suspense": "^0.3.4",
|
"react-promise-suspense": "^0.3.4",
|
||||||
|
"three": "^0.180.0",
|
||||||
|
"three-stdlib": "^2.36.0",
|
||||||
"typescript": "^5.9.2",
|
"typescript": "^5.9.2",
|
||||||
"urlon": "^3.1.0",
|
"urlon": "^3.1.0",
|
||||||
},
|
},
|
||||||
@@ -1540,7 +1543,7 @@
|
|||||||
|
|
||||||
"fetch-blob": ["[email protected]", "", { "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" } }, "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ=="],
|
"fetch-blob": ["[email protected]", "", { "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" } }, "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ=="],
|
||||||
|
|
||||||
"fflate": ["fflate@0.7.4", "", {}, "sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw=="],
|
"fflate": ["fflate@0.8.2", "", {}, "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="],
|
||||||
|
|
||||||
"file-type": ["[email protected]", "", {}, "sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ=="],
|
"file-type": ["[email protected]", "", {}, "sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ=="],
|
||||||
|
|
||||||
@@ -2414,7 +2417,7 @@
|
|||||||
|
|
||||||
"text-decoder": ["[email protected]", "", { "dependencies": { "b4a": "^1.6.4" } }, "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA=="],
|
"text-decoder": ["[email protected]", "", { "dependencies": { "b4a": "^1.6.4" } }, "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA=="],
|
||||||
|
|
||||||
"three": ["[email protected]70.0", "", {}, "sha512-FQK+LEpYc0fBD+J8g6oSEyyNzjp+Q7Ks1C568WWaoMRLW+TkNNWmenWeGgJjV105Gd+p/2ql1ZcjYvNiPZBhuQ=="],
|
"three": ["[email protected]80.0", "", {}, "sha512-o+qycAMZrh+TsE01GqWUxUIKR1AL0S8pq7zDkYOQw8GqfX8b8VoCKYUoHbhiX5j+7hr8XsuHDVU6+gkQJQKg9w=="],
|
||||||
|
|
||||||
"three-mesh-bvh": ["[email protected]", "", { "peerDependencies": { "three": ">= 0.159.0" } }, "sha512-4G5lBaF+g2auKX3P0yqx+MJC6oVt6sB5k+CchS6Ob0qvH0YIhuUk1eYr7ktsIpY+albCqE80/FVQGV190PmiAg=="],
|
"three-mesh-bvh": ["[email protected]", "", { "peerDependencies": { "three": ">= 0.159.0" } }, "sha512-4G5lBaF+g2auKX3P0yqx+MJC6oVt6sB5k+CchS6Ob0qvH0YIhuUk1eYr7ktsIpY+albCqE80/FVQGV190PmiAg=="],
|
||||||
|
|
||||||
@@ -2758,9 +2761,9 @@
|
|||||||
|
|
||||||
"@rollup/pluginutils/estree-walker": ["[email protected]", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
|
"@rollup/pluginutils/estree-walker": ["[email protected]", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
|
||||||
|
|
||||||
"@surma/rollup-plugin-off-main-thread/magic-string": ["[email protected]", "", { "dependencies": { "sourcemap-codec": "^1.4.8" } }, "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ=="],
|
"@shuding/opentype.js/fflate": ["[email protected]", "", {}, "sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw=="],
|
||||||
|
|
||||||
"@types/three/fflate": ["[email protected]", "", {}, "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="],
|
"@surma/rollup-plugin-off-main-thread/magic-string": ["[email protected]", "", { "dependencies": { "sourcemap-codec": "^1.4.8" } }, "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ=="],
|
||||||
|
|
||||||
"anymatch/picomatch": ["[email protected]", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
"anymatch/picomatch": ["[email protected]", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||||
|
|
||||||
@@ -2832,6 +2835,8 @@
|
|||||||
|
|
||||||
"simple-swizzle/is-arrayish": ["[email protected]", "", {}, "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA=="],
|
"simple-swizzle/is-arrayish": ["[email protected]", "", {}, "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA=="],
|
||||||
|
|
||||||
|
"stats-gl/three": ["[email protected]", "", {}, "sha512-FQK+LEpYc0fBD+J8g6oSEyyNzjp+Q7Ks1C568WWaoMRLW+TkNNWmenWeGgJjV105Gd+p/2ql1ZcjYvNiPZBhuQ=="],
|
||||||
|
|
||||||
"string_decoder/safe-buffer": ["[email protected]", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
|
"string_decoder/safe-buffer": ["[email protected]", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
|
||||||
|
|
||||||
"tar-fs/tar-stream": ["[email protected]", "", { "dependencies": { "b4a": "^1.6.4", "fast-fifo": "^1.2.0", "streamx": "^2.15.0" } }, "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ=="],
|
"tar-fs/tar-stream": ["[email protected]", "", { "dependencies": { "b4a": "^1.6.4", "fast-fifo": "^1.2.0", "streamx": "^2.15.0" } }, "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ=="],
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
"name": "@blitzkit/website",
|
"name": "@blitzkit/website",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "astro dev",
|
"dev": "PUBLIC_TARGET=web astro dev",
|
||||||
"build": "PUBLIC_TARGET=app astro build",
|
"build": "PUBLIC_TARGET=web astro build",
|
||||||
"preview": "PUBLIC_TARGET=app astro preview",
|
"preview": "PUBLIC_TARGET=web astro preview",
|
||||||
"lint": "astro check",
|
"lint": "astro check",
|
||||||
"astro": "astro"
|
"astro": "astro"
|
||||||
},
|
},
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
"@react-three/fiber": "^9.3.0",
|
"@react-three/fiber": "^9.3.0",
|
||||||
"@types/react": "^19.1.14",
|
"@types/react": "^19.1.14",
|
||||||
"@types/react-dom": "^19.1.9",
|
"@types/react-dom": "^19.1.9",
|
||||||
|
"@types/three": "^0.180.0",
|
||||||
"@vite-pwa/astro": "^1.1.0",
|
"@vite-pwa/astro": "^1.1.0",
|
||||||
"astro": "^5.14.1",
|
"astro": "^5.14.1",
|
||||||
"astro-favicons": "^3.1.5",
|
"astro-favicons": "^3.1.5",
|
||||||
@@ -32,6 +33,8 @@
|
|||||||
"react": "^19.1.1",
|
"react": "^19.1.1",
|
||||||
"react-dom": "^19.1.1",
|
"react-dom": "^19.1.1",
|
||||||
"react-promise-suspense": "^0.3.4",
|
"react-promise-suspense": "^0.3.4",
|
||||||
|
"three": "^0.180.0",
|
||||||
|
"three-stdlib": "^2.36.0",
|
||||||
"typescript": "^5.9.2",
|
"typescript": "^5.9.2",
|
||||||
"urlon": "^3.1.0"
|
"urlon": "^3.1.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,25 @@
|
|||||||
|
import { useThree, type ThreeEvent } from "@react-three/fiber";
|
||||||
|
import type { QuicklimeEvent } from "quicklime";
|
||||||
|
import { useCallback, useEffect, useRef } from "react";
|
||||||
|
import { Group, Vector2 } from "three";
|
||||||
import { awaitableModelDefinitions } from "../../../core/awaitables/modelDefinitions";
|
import { awaitableModelDefinitions } from "../../../core/awaitables/modelDefinitions";
|
||||||
import { jsxTree } from "../../../core/blitzkit/jsxTree";
|
import { jsxTree } from "../../../core/blitzkit/jsxTree";
|
||||||
|
import {
|
||||||
|
modelTransformEvent,
|
||||||
|
type ModelTransformEventData,
|
||||||
|
} from "../../../core/blitzkit/modelTransform";
|
||||||
|
import { controlsEnabledEvent } from "../../../core/controlsEnabled";
|
||||||
import { useModel } from "../../../hooks/useModel";
|
import { useModel } from "../../../hooks/useModel";
|
||||||
import { Mixer } from "../../../stores/mixer";
|
import { Mixer } from "../../../stores/mixer";
|
||||||
|
|
||||||
const modelDefinitions = await awaitableModelDefinitions;
|
const modelDefinitions = await awaitableModelDefinitions;
|
||||||
|
|
||||||
export function Model() {
|
export function Model() {
|
||||||
|
const canvas = useThree((state) => state.gl.domElement);
|
||||||
|
|
||||||
|
const turretGroup = useRef<Group>(null!);
|
||||||
|
const gunGroup = useRef<Group>(null!);
|
||||||
|
|
||||||
const hull = Mixer.use((state) => state.hull);
|
const hull = Mixer.use((state) => state.hull);
|
||||||
const turret = Mixer.use((state) => state.turret);
|
const turret = Mixer.use((state) => state.turret);
|
||||||
const gun = Mixer.use((state) => state.gun);
|
const gun = Mixer.use((state) => state.gun);
|
||||||
@@ -31,6 +45,54 @@ export function Model() {
|
|||||||
const gunTurretModel = gunTankModel.turrets[gun.turret.id];
|
const gunTurretModel = gunTankModel.turrets[gun.turret.id];
|
||||||
const gunModel = gunTurretModel.guns[gun.gun.id];
|
const gunModel = gunTurretModel.guns[gun.gun.id];
|
||||||
|
|
||||||
|
const pointer = useRef(new Vector2());
|
||||||
|
const delta = useRef(new Vector2());
|
||||||
|
|
||||||
|
const handlePointerDown = useCallback((event: ThreeEvent<PointerEvent>) => {
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
|
controlsEnabledEvent.dispatch(false);
|
||||||
|
pointer.current.set(event.clientX, event.clientY);
|
||||||
|
|
||||||
|
window.addEventListener("pointermove", handlePointerMove);
|
||||||
|
window.addEventListener("pointerup", handlePointerUp);
|
||||||
|
}, []);
|
||||||
|
const handlePointerMove = useCallback((event: PointerEvent) => {
|
||||||
|
const bounds = canvas.getBoundingClientRect();
|
||||||
|
|
||||||
|
delta.current.set(event.clientX, event.clientY).sub(pointer.current);
|
||||||
|
pointer.current.set(event.clientX, event.clientY);
|
||||||
|
|
||||||
|
modelTransformEvent.dispatch({
|
||||||
|
pitch:
|
||||||
|
modelTransformEvent.last!.pitch +
|
||||||
|
delta.current.y * (Math.PI / bounds.height),
|
||||||
|
yaw:
|
||||||
|
modelTransformEvent.last!.yaw +
|
||||||
|
delta.current.x * (Math.PI / bounds.width),
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
const handlePointerUp = useCallback(() => {
|
||||||
|
controlsEnabledEvent.dispatch(true);
|
||||||
|
|
||||||
|
window.removeEventListener("pointermove", handlePointerMove);
|
||||||
|
window.removeEventListener("pointerup", handlePointerUp);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
function handleModelTransform(
|
||||||
|
event: QuicklimeEvent<ModelTransformEventData>
|
||||||
|
) {
|
||||||
|
turretGroup.current.rotation.z = event.data.yaw;
|
||||||
|
}
|
||||||
|
|
||||||
|
modelTransformEvent.on(handleModelTransform);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
modelTransformEvent.off(handleModelTransform);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<group rotation={[-Math.PI / 2, 0, 0]}>
|
<group rotation={[-Math.PI / 2, 0, 0]}>
|
||||||
{hullNodes.map((node) => {
|
{hullNodes.map((node) => {
|
||||||
@@ -49,6 +111,8 @@ export function Model() {
|
|||||||
})}
|
})}
|
||||||
|
|
||||||
<group
|
<group
|
||||||
|
ref={turretGroup}
|
||||||
|
rotation={[0, 0, modelTransformEvent.last!.yaw]}
|
||||||
position={[
|
position={[
|
||||||
tankModel.turret_origin.x +
|
tankModel.turret_origin.x +
|
||||||
trackModel.origin.x -
|
trackModel.origin.x -
|
||||||
@@ -74,7 +138,15 @@ export function Model() {
|
|||||||
|
|
||||||
return jsxTree(node, {
|
return jsxTree(node, {
|
||||||
mesh(_, props, key) {
|
mesh(_, props, key) {
|
||||||
return <mesh {...props} key={key} castShadow receiveShadow />;
|
return (
|
||||||
|
<mesh
|
||||||
|
{...props}
|
||||||
|
key={key}
|
||||||
|
castShadow
|
||||||
|
receiveShadow
|
||||||
|
onPointerDown={handlePointerDown}
|
||||||
|
/>
|
||||||
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -1,12 +1,30 @@
|
|||||||
import { OrbitControls } from "@react-three/drei";
|
import { OrbitControls } from "@react-three/drei";
|
||||||
import { Canvas } from "@react-three/fiber";
|
import { Canvas } from "@react-three/fiber";
|
||||||
import { forwardRef, Suspense } from "react";
|
import type { QuicklimeEvent } from "quicklime";
|
||||||
|
import { forwardRef, Suspense, useEffect, useRef } from "react";
|
||||||
|
import type { OrbitControls as OrbitControlsClass } from "three-stdlib";
|
||||||
|
import { controlsEnabledEvent } from "../../core/controlsEnabled";
|
||||||
import { Lighting } from "../Tankopedia/HeroSection/components/TankSandbox/components/Lighting";
|
import { Lighting } from "../Tankopedia/HeroSection/components/TankSandbox/components/Lighting";
|
||||||
import { SceneProps } from "../Tankopedia/HeroSection/components/TankSandbox/components/SceneProps";
|
import { SceneProps } from "../Tankopedia/HeroSection/components/TankSandbox/components/SceneProps";
|
||||||
import { MixerFallback } from "./components/MixerFallback";
|
import { MixerFallback } from "./components/MixerFallback";
|
||||||
import { Model } from "./components/Model";
|
import { Model } from "./components/Model";
|
||||||
|
|
||||||
export const MixerScene = forwardRef<HTMLCanvasElement>((_, ref) => {
|
export const MixerScene = forwardRef<HTMLCanvasElement>((_, ref) => {
|
||||||
|
const controls = useRef<OrbitControlsClass>(null!);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
function handleControlsEnabled(event: QuicklimeEvent<boolean>) {
|
||||||
|
if (!controls.current) return;
|
||||||
|
controls.current.enabled = event.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
controlsEnabledEvent.on(handleControlsEnabled);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
controlsEnabledEvent.off(handleControlsEnabled);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Canvas
|
<Canvas
|
||||||
ref={ref}
|
ref={ref}
|
||||||
@@ -18,6 +36,7 @@ export const MixerScene = forwardRef<HTMLCanvasElement>((_, ref) => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<OrbitControls
|
<OrbitControls
|
||||||
|
ref={controls}
|
||||||
maxDistance={20}
|
maxDistance={20}
|
||||||
minDistance={5}
|
minDistance={5}
|
||||||
enableDamping={false}
|
enableDamping={false}
|
||||||
|
|||||||
+10
-8
@@ -1,6 +1,7 @@
|
|||||||
import { I_HAT, J_HAT } from "@blitzkit/core";
|
import { I_HAT, J_HAT } from "@blitzkit/core";
|
||||||
import { OrbitControls } from "@react-three/drei";
|
import { OrbitControls } from "@react-three/drei";
|
||||||
import { invalidate, useFrame, useThree } from "@react-three/fiber";
|
import { invalidate, useFrame, useThree } from "@react-three/fiber";
|
||||||
|
import type { QuicklimeEvent } from "quicklime";
|
||||||
import { useEffect, useRef } from "react";
|
import { useEffect, useRef } from "react";
|
||||||
import { PerspectiveCamera, Vector3 } from "three";
|
import { PerspectiveCamera, Vector3 } from "three";
|
||||||
import { OrbitControls as OrbitControlsClass } from "three-stdlib";
|
import { OrbitControls as OrbitControlsClass } from "three-stdlib";
|
||||||
@@ -8,6 +9,7 @@ import { awaitableModelDefinitions } from "../../../../../../core/awaitables/mod
|
|||||||
import { applyPitchYawLimits } from "../../../../../../core/blitz/applyPitchYawLimits";
|
import { applyPitchYawLimits } from "../../../../../../core/blitz/applyPitchYawLimits";
|
||||||
import { hasEquipment } from "../../../../../../core/blitzkit/hasEquipment";
|
import { hasEquipment } from "../../../../../../core/blitzkit/hasEquipment";
|
||||||
import { Pose, poseEvent } from "../../../../../../core/blitzkit/pose";
|
import { Pose, poseEvent } from "../../../../../../core/blitzkit/pose";
|
||||||
|
import { controlsEnabledEvent } from "../../../../../../core/controlsEnabled";
|
||||||
import { Duel } from "../../../../../../stores/duel";
|
import { Duel } from "../../../../../../stores/duel";
|
||||||
import { Tankopedia } from "../../../../../../stores/tankopedia";
|
import { Tankopedia } from "../../../../../../stores/tankopedia";
|
||||||
|
|
||||||
@@ -99,12 +101,12 @@ export function Controls({
|
|||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const unsubscribeTankopediaEphemeral = Tankopedia.on(
|
function handleControlsEnabled(event: QuicklimeEvent<boolean>) {
|
||||||
(state) => state.controlsEnabled,
|
if (!orbitControls.current) return;
|
||||||
(enabled) => {
|
orbitControls.current.enabled = event.data;
|
||||||
if (orbitControls.current) orbitControls.current.enabled = enabled;
|
}
|
||||||
}
|
|
||||||
);
|
controlsEnabledEvent.on(handleControlsEnabled);
|
||||||
|
|
||||||
function handlePoseEvent(event: Pose) {
|
function handlePoseEvent(event: Pose) {
|
||||||
const hasImprovedVerticalStabilizer = hasEquipment(
|
const hasImprovedVerticalStabilizer = hasEquipment(
|
||||||
@@ -203,7 +205,7 @@ export function Controls({
|
|||||||
poseEvent.on(handlePoseEvent);
|
poseEvent.on(handlePoseEvent);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
unsubscribeTankopediaEphemeral();
|
controlsEnabledEvent.off(handleControlsEnabled);
|
||||||
poseEvent.off(handlePoseEvent);
|
poseEvent.off(handlePoseEvent);
|
||||||
};
|
};
|
||||||
}, [camera, protagonistTank.id, antagonistTank.id]);
|
}, [camera, protagonistTank.id, antagonistTank.id]);
|
||||||
@@ -264,7 +266,7 @@ export function Controls({
|
|||||||
enableZoom={zoomable}
|
enableZoom={zoomable}
|
||||||
zoomSpeed={zoomable ? undefined : 0}
|
zoomSpeed={zoomable ? undefined : 0}
|
||||||
ref={orbitControls}
|
ref={orbitControls}
|
||||||
enabled={Tankopedia.state.controlsEnabled}
|
enabled={controlsEnabledEvent.last!}
|
||||||
enableDamping={false}
|
enableDamping={false}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
import { Quicklime } from "quicklime";
|
||||||
|
|
||||||
|
export const controlsEnabledEvent = new Quicklime(true);
|
||||||
@@ -82,7 +82,6 @@ interface Tankopedia {
|
|||||||
shot?: Shot;
|
shot?: Shot;
|
||||||
skills: Record<string, number>;
|
skills: Record<string, number>;
|
||||||
relativeAgainst: TankopediaRelativeAgainst;
|
relativeAgainst: TankopediaRelativeAgainst;
|
||||||
controlsEnabled: boolean;
|
|
||||||
model: ModelDefinition;
|
model: ModelDefinition;
|
||||||
editStatic: boolean;
|
editStatic: boolean;
|
||||||
highlightArmor?: {
|
highlightArmor?: {
|
||||||
|
|||||||
Reference in new issue
Block a user