mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-25 03:29:51 +01:00
fix: shell and quick equipment frame invalidations
This commit is contained in:
1 parent
3e2bfc453a
commit
5cf8e48747
13 files changed
+77
-51
No files matched your search
@@ -14,7 +14,7 @@ export const PrimaryArmorScene = memo(() => {
|
|||||||
const wrapper = useRef<Group>(null);
|
const wrapper = useRef<Group>(null);
|
||||||
const turretContainer = useRef<Group>(null);
|
const turretContainer = useRef<Group>(null);
|
||||||
const gunContainer = useRef<Group>(null);
|
const gunContainer = useRef<Group>(null);
|
||||||
const protagonist = Duel.use((draft) => draft.protagonist);
|
// const protagonist = Duel.use((draft) => draft.protagonist);
|
||||||
const tank = Duel.use((state) => state.protagonist.tank);
|
const tank = Duel.use((state) => state.protagonist.tank);
|
||||||
const track = Duel.use((state) => state.protagonist.track);
|
const track = Duel.use((state) => state.protagonist.track);
|
||||||
const turret = Duel.use((state) => state.protagonist.turret);
|
const turret = Duel.use((state) => state.protagonist.turret);
|
||||||
@@ -33,7 +33,7 @@ export const PrimaryArmorScene = memo(() => {
|
|||||||
state.protagonist.consumables.includes(73),
|
state.protagonist.consumables.includes(73),
|
||||||
);
|
);
|
||||||
|
|
||||||
useTankTransform(protagonist, turretContainer, gunContainer);
|
useTankTransform(track, turret, turretContainer, gunContainer);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ModelTankWrapper ref={wrapper}>
|
<ModelTankWrapper ref={wrapper}>
|
||||||
|
|||||||
+7
-4
@@ -78,15 +78,18 @@ export function PrimaryArmorSceneComponent({
|
|||||||
|
|
||||||
await handleProtagonistEquipmentChange(duel.protagonist.equipmentMatrix);
|
await handleProtagonistEquipmentChange(duel.protagonist.equipmentMatrix);
|
||||||
await handleAntagonistEquipmentChange(duel.antagonist.equipmentMatrix);
|
await handleAntagonistEquipmentChange(duel.antagonist.equipmentMatrix);
|
||||||
|
|
||||||
|
// console.log('handleShellChange');
|
||||||
|
|
||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
function handleGreenPenetrationChange(greenPenetration: boolean) {
|
function handleGreenPenetrationChange(greenPenetration: boolean) {
|
||||||
material.uniforms.greenPenetration.value = greenPenetration;
|
material.uniforms.greenPenetration.value = greenPenetration;
|
||||||
invalidate();
|
|
||||||
}
|
}
|
||||||
function handleOpaqueChange(opaque: boolean) {
|
function handleOpaqueChange(opaque: boolean) {
|
||||||
material.uniforms.opaque.value = opaque;
|
material.uniforms.opaque.value = opaque;
|
||||||
invalidate();
|
|
||||||
|
// invalidate();
|
||||||
}
|
}
|
||||||
function handleWireframeChange(wireframe: boolean) {
|
function handleWireframeChange(wireframe: boolean) {
|
||||||
material.wireframe = wireframe;
|
material.wireframe = wireframe;
|
||||||
@@ -104,7 +107,7 @@ export function PrimaryArmorSceneComponent({
|
|||||||
? thickness * 1.03
|
? thickness * 1.03
|
||||||
: thickness;
|
: thickness;
|
||||||
|
|
||||||
invalidate();
|
// invalidate();
|
||||||
}
|
}
|
||||||
async function handleAntagonistEquipmentChange(equipment: EquipmentMatrix) {
|
async function handleAntagonistEquipmentChange(equipment: EquipmentMatrix) {
|
||||||
const duel = duelStore.getState();
|
const duel = duelStore.getState();
|
||||||
@@ -173,7 +176,7 @@ export function PrimaryArmorSceneComponent({
|
|||||||
material.uniforms.inverseProjectionMatrix.value =
|
material.uniforms.inverseProjectionMatrix.value =
|
||||||
camera.projectionMatrixInverse;
|
camera.projectionMatrixInverse;
|
||||||
|
|
||||||
invalidate();
|
// invalidate();
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { J_HAT, K_HAT } from '@blitzkit/core';
|
import { J_HAT, K_HAT } from '@blitzkit/core';
|
||||||
import { Box, Flex, Text } from '@radix-ui/themes';
|
import { Box, Flex, Text } from '@radix-ui/themes';
|
||||||
import { Html } from '@react-three/drei';
|
import { Html } from '@react-three/drei';
|
||||||
import { invalidate, useFrame } from '@react-three/fiber';
|
import { useFrame } from '@react-three/fiber';
|
||||||
import { clamp } from 'lodash-es';
|
import { clamp } from 'lodash-es';
|
||||||
import { useEffect, useRef, type ComponentProps } from 'react';
|
import { useEffect, useRef, type ComponentProps } from 'react';
|
||||||
import {
|
import {
|
||||||
@@ -105,7 +105,7 @@ export function ShotDisplay() {
|
|||||||
outTracer.current.position.set(0, tracerT2 * outLength, 0);
|
outTracer.current.position.set(0, tracerT2 * outLength, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
invalidate();
|
// invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@@ -122,7 +122,7 @@ export function ShotDisplay() {
|
|||||||
splashRadiusWrapper.current.scale.set(scale, scale, scale);
|
splashRadiusWrapper.current.scale.set(scale, scale, scale);
|
||||||
splashRadiusMaterial.current.opacity = opacity;
|
splashRadiusMaterial.current.opacity = opacity;
|
||||||
|
|
||||||
invalidate();
|
// invalidate();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ export const SpacedArmorScene = memo<SpacedArmorSceneProps>(({ scene }) => {
|
|||||||
const wrapper = useRef<Group>(null);
|
const wrapper = useRef<Group>(null);
|
||||||
const turretContainer = useRef<Group>(null);
|
const turretContainer = useRef<Group>(null);
|
||||||
const gunContainer = useRef<Group>(null);
|
const gunContainer = useRef<Group>(null);
|
||||||
const protagonist = Duel.use((draft) => draft.protagonist);
|
|
||||||
const tank = Duel.use((state) => state.protagonist.tank);
|
const tank = Duel.use((state) => state.protagonist.tank);
|
||||||
const track = Duel.use((state) => state.protagonist.track);
|
const track = Duel.use((state) => state.protagonist.track);
|
||||||
const turret = Duel.use((state) => state.protagonist.turret);
|
const turret = Duel.use((state) => state.protagonist.turret);
|
||||||
@@ -50,7 +49,7 @@ export const SpacedArmorScene = memo<SpacedArmorSceneProps>(({ scene }) => {
|
|||||||
state.protagonist.consumables.includes(73),
|
state.protagonist.consumables.includes(73),
|
||||||
);
|
);
|
||||||
|
|
||||||
useTankTransform(protagonist, turretContainer, gunContainer);
|
useTankTransform(track, turret, turretContainer, gunContainer);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ModelTankWrapper ref={wrapper}>
|
<ModelTankWrapper ref={wrapper}>
|
||||||
|
|||||||
+3
-4
@@ -1,5 +1,4 @@
|
|||||||
import { resolvePenetrationCoefficient } from '@blitzkit/core';
|
import { resolvePenetrationCoefficient } from '@blitzkit/core';
|
||||||
import { invalidate } from '@react-three/fiber';
|
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import {
|
import {
|
||||||
AdditiveBlending,
|
AdditiveBlending,
|
||||||
@@ -54,7 +53,7 @@ export function SpacedArmorSubExternal({
|
|||||||
const tankopediaEphemeral = tankopediaEphemeralStore.getState();
|
const tankopediaEphemeral = tankopediaEphemeralStore.getState();
|
||||||
const shell = tankopediaEphemeral.customShell ?? duel.antagonist.shell;
|
const shell = tankopediaEphemeral.customShell ?? duel.antagonist.shell;
|
||||||
material.uniforms.penetration.value = shell.penetration.near;
|
material.uniforms.penetration.value = shell.penetration.near;
|
||||||
invalidate();
|
// invalidate();
|
||||||
}
|
}
|
||||||
async function handleProtagonistEquipmentChange(
|
async function handleProtagonistEquipmentChange(
|
||||||
equipment: EquipmentMatrix,
|
equipment: EquipmentMatrix,
|
||||||
@@ -69,7 +68,7 @@ export function SpacedArmorSubExternal({
|
|||||||
? thickness * 1.03
|
? thickness * 1.03
|
||||||
: thickness;
|
: thickness;
|
||||||
|
|
||||||
invalidate();
|
// invalidate();
|
||||||
}
|
}
|
||||||
async function handleAntagonistEquipmentChange(equipment: EquipmentMatrix) {
|
async function handleAntagonistEquipmentChange(equipment: EquipmentMatrix) {
|
||||||
const duel = duelStore.getState();
|
const duel = duelStore.getState();
|
||||||
@@ -86,7 +85,7 @@ export function SpacedArmorSubExternal({
|
|||||||
penetration *
|
penetration *
|
||||||
resolvePenetrationCoefficient(hasCalibratedShells, shell.type);
|
resolvePenetrationCoefficient(hasCalibratedShells, shell.type);
|
||||||
|
|
||||||
invalidate();
|
// invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
handleShellChange();
|
handleShellChange();
|
||||||
|
|||||||
+2
-5
@@ -1,5 +1,4 @@
|
|||||||
import { isExplosive, resolvePenetrationCoefficient } from '@blitzkit/core';
|
import { isExplosive, resolvePenetrationCoefficient } from '@blitzkit/core';
|
||||||
import { invalidate } from '@react-three/fiber';
|
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import {
|
import {
|
||||||
AdditiveBlending,
|
AdditiveBlending,
|
||||||
@@ -65,7 +64,7 @@ export function SpacedArmorSubSpaced({
|
|||||||
shell.normalization ?? 0,
|
shell.normalization ?? 0,
|
||||||
);
|
);
|
||||||
|
|
||||||
invalidate();
|
// invalidate();
|
||||||
}
|
}
|
||||||
async function handleProtagonistEquipmentChange(
|
async function handleProtagonistEquipmentChange(
|
||||||
equipment: EquipmentMatrix,
|
equipment: EquipmentMatrix,
|
||||||
@@ -80,7 +79,7 @@ export function SpacedArmorSubSpaced({
|
|||||||
? thickness * 1.03
|
? thickness * 1.03
|
||||||
: thickness;
|
: thickness;
|
||||||
|
|
||||||
invalidate();
|
// invalidate();
|
||||||
}
|
}
|
||||||
async function handleAntagonistEquipmentChange(equipment: EquipmentMatrix) {
|
async function handleAntagonistEquipmentChange(equipment: EquipmentMatrix) {
|
||||||
const duel = duelStore.getState();
|
const duel = duelStore.getState();
|
||||||
@@ -96,8 +95,6 @@ export function SpacedArmorSubSpaced({
|
|||||||
material.uniforms.penetration.value =
|
material.uniforms.penetration.value =
|
||||||
penetration *
|
penetration *
|
||||||
resolvePenetrationCoefficient(hasCalibratedShells, shell.type);
|
resolvePenetrationCoefficient(hasCalibratedShells, shell.type);
|
||||||
|
|
||||||
invalidate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleShellChange();
|
handleShellChange();
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ export const StaticArmor = memo<ArmorSceneProps>(({ thicknessRange }) => {
|
|||||||
state.protagonist.consumables.includes(73),
|
state.protagonist.consumables.includes(73),
|
||||||
);
|
);
|
||||||
|
|
||||||
useTankTransform(protagonist, turretContainer, gunContainer);
|
useTankTransform(track, turret, turretContainer, gunContainer);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ModelTankWrapper ref={wrapper}>
|
<ModelTankWrapper ref={wrapper}>
|
||||||
|
|||||||
+14
-5
@@ -9,6 +9,7 @@ import {
|
|||||||
Text,
|
Text,
|
||||||
TextField,
|
TextField,
|
||||||
} from '@radix-ui/themes';
|
} from '@radix-ui/themes';
|
||||||
|
import { throttle } from 'lodash-es';
|
||||||
import { type ChangeEvent } from 'react';
|
import { type ChangeEvent } from 'react';
|
||||||
import { Duel } from '../../../../../../stores/duel';
|
import { Duel } from '../../../../../../stores/duel';
|
||||||
import { TankopediaEphemeral } from '../../../../../../stores/tankopediaEphemeral';
|
import { TankopediaEphemeral } from '../../../../../../stores/tankopediaEphemeral';
|
||||||
@@ -154,7 +155,13 @@ export function CustomShellButton() {
|
|||||||
<Flex align="center" justify="between" gap="4" py="1">
|
<Flex align="center" justify="between" gap="4" py="1">
|
||||||
<Text>Normalization</Text>
|
<Text>Normalization</Text>
|
||||||
|
|
||||||
<Flex align="center" gap="2" flexGrow="1" maxWidth="15rem">
|
<Flex
|
||||||
|
align="center"
|
||||||
|
gap="2"
|
||||||
|
flexGrow="1"
|
||||||
|
maxWidth="15rem"
|
||||||
|
minWidth="8rem"
|
||||||
|
>
|
||||||
<Text color="gray">
|
<Text color="gray">
|
||||||
{customShell.normalization ?? 0}°
|
{customShell.normalization ?? 0}°
|
||||||
</Text>
|
</Text>
|
||||||
@@ -162,11 +169,13 @@ export function CustomShellButton() {
|
|||||||
min={0}
|
min={0}
|
||||||
max={90}
|
max={90}
|
||||||
value={[customShell.normalization ?? 0]}
|
value={[customShell.normalization ?? 0]}
|
||||||
onValueChange={([value]) => {
|
onValueChange={throttle(([value]) => {
|
||||||
|
console.log('asd');
|
||||||
|
|
||||||
mutateTankopediaEphemeral((draft) => {
|
mutateTankopediaEphemeral((draft) => {
|
||||||
draft.customShell!.normalization = value;
|
draft.customShell!.normalization = value;
|
||||||
});
|
});
|
||||||
}}
|
}, 1000)}
|
||||||
/>
|
/>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
@@ -180,11 +189,11 @@ export function CustomShellButton() {
|
|||||||
min={0}
|
min={0}
|
||||||
max={90}
|
max={90}
|
||||||
value={[customShell.ricochet ?? 90]}
|
value={[customShell.ricochet ?? 90]}
|
||||||
onValueChange={([value]) => {
|
onValueChange={throttle(([value]) => {
|
||||||
mutateTankopediaEphemeral((draft) => {
|
mutateTankopediaEphemeral((draft) => {
|
||||||
draft.customShell!.ricochet = value;
|
draft.customShell!.ricochet = value;
|
||||||
});
|
});
|
||||||
}}
|
}, 1000)}
|
||||||
/>
|
/>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|||||||
+1
-2
@@ -1,6 +1,5 @@
|
|||||||
import { asset } from '@blitzkit/core';
|
import { asset } from '@blitzkit/core';
|
||||||
import { IconButton } from '@radix-ui/themes';
|
import { IconButton } from '@radix-ui/themes';
|
||||||
import { invalidate } from '@react-three/fiber';
|
|
||||||
import { useArmor } from '../../../../../../hooks/useArmor';
|
import { useArmor } from '../../../../../../hooks/useArmor';
|
||||||
import { Duel } from '../../../../../../stores/duel';
|
import { Duel } from '../../../../../../stores/duel';
|
||||||
import { TankopediaEphemeral } from '../../../../../../stores/tankopediaEphemeral';
|
import { TankopediaEphemeral } from '../../../../../../stores/tankopediaEphemeral';
|
||||||
@@ -22,7 +21,7 @@ export function DynamicArmorSwitcher() {
|
|||||||
variant="soft"
|
variant="soft"
|
||||||
size={{ initial: '2', sm: '3' }}
|
size={{ initial: '2', sm: '3' }}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
invalidate();
|
// invalidate();
|
||||||
mutateDuel((draft) => {
|
mutateDuel((draft) => {
|
||||||
if (draft.protagonist.consumables.includes(73)) {
|
if (draft.protagonist.consumables.includes(73)) {
|
||||||
draft.protagonist.consumables =
|
draft.protagonist.consumables =
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ import {
|
|||||||
Text,
|
Text,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
} from '@radix-ui/themes';
|
} from '@radix-ui/themes';
|
||||||
import { invalidate } from '@react-three/fiber';
|
|
||||||
import { useState, type RefObject } from 'react';
|
import { useState, type RefObject } from 'react';
|
||||||
import { ENVIRONMENTS } from '../../../../../constants/lightingEnvironments';
|
import { ENVIRONMENTS } from '../../../../../constants/lightingEnvironments';
|
||||||
import { Pose, poseEvent } from '../../../../../core/blitzkit/pose';
|
import { Pose, poseEvent } from '../../../../../core/blitzkit/pose';
|
||||||
@@ -202,7 +201,7 @@ export function Options({ thicknessRange, canvas }: OptionsProps) {
|
|||||||
size={{ initial: '2', sm: '3' }}
|
size={{ initial: '2', sm: '3' }}
|
||||||
radius="none"
|
radius="none"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
invalidate();
|
// invalidate();
|
||||||
mutateDuel((draft) => {
|
mutateDuel((draft) => {
|
||||||
draft.antagonist.shell = thisShell;
|
draft.antagonist.shell = thisShell;
|
||||||
});
|
});
|
||||||
@@ -240,7 +239,7 @@ export function Options({ thicknessRange, canvas }: OptionsProps) {
|
|||||||
size={{ initial: '2', sm: '3' }}
|
size={{ initial: '2', sm: '3' }}
|
||||||
radius="none"
|
radius="none"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
invalidate();
|
// invalidate();
|
||||||
mutateDuel((draft) => {
|
mutateDuel((draft) => {
|
||||||
draft.antagonist.equipmentMatrix[0][0] = hasCalibratedShells
|
draft.antagonist.equipmentMatrix[0][0] = hasCalibratedShells
|
||||||
? 0
|
? 0
|
||||||
@@ -266,7 +265,7 @@ export function Options({ thicknessRange, canvas }: OptionsProps) {
|
|||||||
size={{ initial: '2', sm: '3' }}
|
size={{ initial: '2', sm: '3' }}
|
||||||
radius="none"
|
radius="none"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
invalidate();
|
// invalidate();
|
||||||
mutateDuel((draft) => {
|
mutateDuel((draft) => {
|
||||||
draft.protagonist.equipmentMatrix[1][1] = hasEnhancedArmor
|
draft.protagonist.equipmentMatrix[1][1] = hasEnhancedArmor
|
||||||
? 0
|
? 0
|
||||||
|
|||||||
+5
-3
@@ -1,5 +1,5 @@
|
|||||||
import { normalizeAngleRad } from '@blitzkit/core';
|
import { normalizeAngleRad } from '@blitzkit/core';
|
||||||
import { invalidate, useThree, type ThreeEvent } from '@react-three/fiber';
|
import { useThree, type ThreeEvent } from '@react-three/fiber';
|
||||||
import { memo, useRef } from 'react';
|
import { memo, useRef } from 'react';
|
||||||
import { Group, Mesh, MeshStandardMaterial, Vector2 } from 'three';
|
import { Group, Mesh, MeshStandardMaterial, Vector2 } from 'three';
|
||||||
import { applyPitchYawLimits } from '../../../../../../core/blitz/applyPitchYawLimits';
|
import { applyPitchYawLimits } from '../../../../../../core/blitz/applyPitchYawLimits';
|
||||||
@@ -20,6 +20,8 @@ export const TankModel = memo(() => {
|
|||||||
const duelStore = Duel.useStore();
|
const duelStore = Duel.useStore();
|
||||||
const protagonist = Duel.use((draft) => draft.protagonist);
|
const protagonist = Duel.use((draft) => draft.protagonist);
|
||||||
const tankopediaPersistentStore = TankopediaPersistent.useStore();
|
const tankopediaPersistentStore = TankopediaPersistent.useStore();
|
||||||
|
const track = Duel.use((state) => state.protagonist.track);
|
||||||
|
const turret = Duel.use((state) => state.protagonist.turret);
|
||||||
const canvas = useThree((state) => state.gl.domElement);
|
const canvas = useThree((state) => state.gl.domElement);
|
||||||
const hullContainer = useRef<Group>(null);
|
const hullContainer = useRef<Group>(null);
|
||||||
const turretContainer = useRef<Group>(null);
|
const turretContainer = useRef<Group>(null);
|
||||||
@@ -33,7 +35,7 @@ export const TankModel = memo(() => {
|
|||||||
const { gltf } = useModel(protagonist.tank.id);
|
const { gltf } = useModel(protagonist.tank.id);
|
||||||
const nodes = Object.values(gltf.nodes);
|
const nodes = Object.values(gltf.nodes);
|
||||||
|
|
||||||
useTankTransform(protagonist, turretContainer, gunContainer);
|
useTankTransform(track, turret, turretContainer, gunContainer);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ModelTankWrapper ref={hullContainer}>
|
<ModelTankWrapper ref={hullContainer}>
|
||||||
@@ -53,7 +55,7 @@ export const TankModel = memo(() => {
|
|||||||
|
|
||||||
if (!material) return;
|
if (!material) return;
|
||||||
|
|
||||||
invalidate();
|
// invalidate();
|
||||||
|
|
||||||
if (material.map) material.map.offset.y += offset;
|
if (material.map) material.map.offset.y += offset;
|
||||||
if (material.aoMap) material.aoMap.offset.y += offset;
|
if (material.aoMap) material.aoMap.offset.y += offset;
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { EventManager } from '@blitzkit/core';
|
import { EventManager } from '@blitzkit/core';
|
||||||
import { invalidate } from '@react-three/fiber';
|
|
||||||
|
|
||||||
export interface ModelTransformEventData {
|
export interface ModelTransformEventData {
|
||||||
yaw?: number;
|
yaw?: number;
|
||||||
@@ -7,4 +6,6 @@ export interface ModelTransformEventData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const modelTransformEvent = new EventManager<ModelTransformEventData>();
|
export const modelTransformEvent = new EventManager<ModelTransformEventData>();
|
||||||
modelTransformEvent.on(() => invalidate());
|
modelTransformEvent.on(() => {
|
||||||
|
// invalidate();
|
||||||
|
});
|
||||||
@@ -1,26 +1,30 @@
|
|||||||
import { I_HAT, J_HAT, K_HAT } from '@blitzkit/core';
|
import {
|
||||||
|
I_HAT,
|
||||||
|
J_HAT,
|
||||||
|
K_HAT,
|
||||||
|
TrackDefinition,
|
||||||
|
TurretDefinition,
|
||||||
|
} from '@blitzkit/core';
|
||||||
import { type RefObject, useEffect } from 'react';
|
import { type RefObject, useEffect } from 'react';
|
||||||
import { Euler, Group, Vector3 } from 'three';
|
import { Euler, Group, Vector3 } from 'three';
|
||||||
import { degToRad } from 'three/src/math/MathUtils.js';
|
import { degToRad } from 'three/src/math/MathUtils.js';
|
||||||
import { correctZYTuple } from '../core/blitz/correctZYTuple';
|
import { correctZYTuple } from '../core/blitz/correctZYTuple';
|
||||||
import {
|
import { modelTransformEvent } from '../core/blitzkit/modelTransform';
|
||||||
type ModelTransformEventData,
|
import { Duel } from '../stores/duel';
|
||||||
modelTransformEvent,
|
|
||||||
} from '../core/blitzkit/modelTransform';
|
|
||||||
import type { DuelMember } from '../stores/duel';
|
|
||||||
import { useTankModelDefinition } from './useTankModelDefinition';
|
import { useTankModelDefinition } from './useTankModelDefinition';
|
||||||
|
|
||||||
export function useTankTransform(
|
export function useTankTransform(
|
||||||
member: DuelMember,
|
track: TrackDefinition,
|
||||||
|
turret: TurretDefinition,
|
||||||
turretContainer: RefObject<Group>,
|
turretContainer: RefObject<Group>,
|
||||||
gunContainer: RefObject<Group>,
|
gunContainer: RefObject<Group>,
|
||||||
) {
|
) {
|
||||||
const tankModelDefinition = useTankModelDefinition();
|
const tankModelDefinition = useTankModelDefinition();
|
||||||
|
const duelStore = Duel.useStore();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const trackModelDefinition = tankModelDefinition.tracks[member.track.id];
|
const trackModelDefinition = tankModelDefinition.tracks[track.id];
|
||||||
const turretModelDefinition = tankModelDefinition.turrets[member.turret.id];
|
const turretModelDefinition = tankModelDefinition.turrets[turret.id];
|
||||||
|
|
||||||
const hullOrigin = correctZYTuple(trackModelDefinition.origin);
|
const hullOrigin = correctZYTuple(trackModelDefinition.origin);
|
||||||
const turretOrigin = correctZYTuple(tankModelDefinition.turret_origin);
|
const turretOrigin = correctZYTuple(tankModelDefinition.turret_origin);
|
||||||
const gunOrigin = correctZYTuple(turretModelDefinition.gun_origin);
|
const gunOrigin = correctZYTuple(turretModelDefinition.gun_origin);
|
||||||
@@ -29,7 +33,8 @@ export function useTankTransform(
|
|||||||
const gunPosition = new Vector3();
|
const gunPosition = new Vector3();
|
||||||
const gunRotation = new Euler();
|
const gunRotation = new Euler();
|
||||||
|
|
||||||
function handleModelTransform({ yaw, pitch }: ModelTransformEventData) {
|
function handleModelTransform() {
|
||||||
|
const { yaw, pitch } = duelStore.getState().protagonist;
|
||||||
gunPosition
|
gunPosition
|
||||||
.set(0, 0, 0)
|
.set(0, 0, 0)
|
||||||
.sub(hullOrigin)
|
.sub(hullOrigin)
|
||||||
@@ -77,11 +82,24 @@ export function useTankTransform(
|
|||||||
turretContainer.current?.rotation.copy(turretRotation);
|
turretContainer.current?.rotation.copy(turretRotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleModelTransform(member);
|
handleModelTransform();
|
||||||
|
|
||||||
modelTransformEvent.on(handleModelTransform);
|
modelTransformEvent.on(handleModelTransform);
|
||||||
|
|
||||||
|
const unsubscribes = [
|
||||||
|
duelStore.subscribe(
|
||||||
|
(state) => state.protagonist.pitch,
|
||||||
|
handleModelTransform,
|
||||||
|
),
|
||||||
|
duelStore.subscribe(
|
||||||
|
(state) => state.protagonist.yaw,
|
||||||
|
handleModelTransform,
|
||||||
|
),
|
||||||
|
() => modelTransformEvent.off(handleModelTransform),
|
||||||
|
];
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
modelTransformEvent.off(handleModelTransform);
|
unsubscribes.forEach((unsubscribe) => unsubscribe());
|
||||||
};
|
};
|
||||||
}, [member]);
|
}, [track, turret]);
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user