use useRef instead of useState

This commit is contained in:
tresabhi committed 2026-10-02 16:34:12 -05:00
1 parent 0477887d68
commit f7db1280cf
1 file changed
+65 -64
@@ -5,7 +5,7 @@ import {
} from "@blitzkit/core";
import { invalidate, useFrame } from "@react-three/fiber";
import type { QuicklimeEvent } from "quicklime";
import { useEffect, useState } from "react";
import { useEffect, useRef } from "react";
import {
MeshBasicMaterial,
NormalBlending,
@@ -43,44 +43,43 @@ export function PrimaryArmorSceneComponent({
node,
thickness,
}: PrimaryArmorSceneComponentProps) {
const [material] = useState(
() =>
new ShaderMaterial({
fragmentShader,
vertexShader,
const material = useRef(
new ShaderMaterial({
fragmentShader,
vertexShader,
fog: true,
transparent: true,
fog: true,
transparent: true,
blending: isHalloween ? SubtractiveBlending : NormalBlending,
blending: isHalloween ? SubtractiveBlending : NormalBlending,
uniforms: UniformsUtils.merge([
UniformsLib.common,
UniformsLib.fog,
uniforms: UniformsUtils.merge([
UniformsLib.common,
UniformsLib.fog,
{
thickness: { value: null },
penetration: { value: null },
caliber: { value: null },
ricochet: { value: null },
normalization: { value: null },
isExplosive: { value: null },
canSplash: { value: null },
damage: { value: null },
explosionRadius: { value: null },
greenPenetration: { value: null },
advancedHighlighting: { value: null },
opaque: { value: null },
{
thickness: { value: null },
penetration: { value: null },
caliber: { value: null },
ricochet: { value: null },
normalization: { value: null },
isExplosive: { value: null },
canSplash: { value: null },
damage: { value: null },
explosionRadius: { value: null },
greenPenetration: { value: null },
advancedHighlighting: { value: null },
opaque: { value: null },
inverseProjectionMatrix: { value: null },
resolution: { value: new Vector2() },
spacedArmorBuffer: { value: null },
spacedArmorDepth: { value: null },
inverseProjectionMatrix: { value: null },
resolution: { value: new Vector2() },
spacedArmorBuffer: { value: null },
spacedArmorDepth: { value: null },
opacity: { value: 0 },
},
]),
})
opacity: { value: 0 },
},
]),
}),
);
useEffect(() => {
@@ -89,17 +88,17 @@ export function PrimaryArmorSceneComponent({
const shell =
tankopediaEphemeral.customShell ?? Duel.state.antagonist.shell;
material.uniforms.caliber.value = shell.caliber;
material.uniforms.ricochet.value = degToRad(
isExplosive(shell.type) ? 90 : shell.ricochet!
material.current.uniforms.caliber.value = shell.caliber;
material.current.uniforms.ricochet.value = degToRad(
isExplosive(shell.type) ? 90 : shell.ricochet!,
);
material.uniforms.normalization.value = degToRad(
shell.normalization ?? 0
material.current.uniforms.normalization.value = degToRad(
shell.normalization ?? 0,
);
material.uniforms.isExplosive.value = isExplosive(shell.type);
material.uniforms.canSplash.value = canSplash(shell.type);
material.uniforms.damage.value = shell.armor_damage;
material.uniforms.explosionRadius.value = shell.explosion_radius;
material.current.uniforms.isExplosive.value = isExplosive(shell.type);
material.current.uniforms.canSplash.value = canSplash(shell.type);
material.current.uniforms.damage.value = shell.armor_damage;
material.current.uniforms.explosionRadius.value = shell.explosion_radius;
handleProtagonistEquipmentChange(true);
handleAntagonistEquipmentChange(true);
@@ -107,31 +106,32 @@ export function PrimaryArmorSceneComponent({
invalidate();
}
function handleGreenPenetrationChange(greenPenetration: boolean) {
material.uniforms.greenPenetration.value = greenPenetration;
material.current.uniforms.greenPenetration.value = greenPenetration;
}
function handleAdvancedHighlightingChange(advancedHighlighting: boolean) {
material.uniforms.advancedHighlighting.value = advancedHighlighting;
material.current.uniforms.advancedHighlighting.value =
advancedHighlighting;
invalidate();
}
function handleOpaqueChange(opaque: boolean) {
material.uniforms.opaque.value = opaque;
material.current.uniforms.opaque.value = opaque;
}
function handleWireframeChange(wireframe: boolean) {
material.wireframe = wireframe;
material.current.wireframe = wireframe;
}
function handleProtagonistEquipmentChange(noInvalidate = false) {
const equipment = Duel.state.protagonist.equipmentMatrix;
const hasEnhancedArmor = hasEquipment(
110,
Duel.state.protagonist.tank.equipment_preset,
equipment
equipment,
);
const equalizer =
(Duel.state.equalize
? Duel.state.protagonist.tank.equalizer?.armor
: undefined) ?? 1;
material.uniforms.thickness.value =
material.current.uniforms.thickness.value =
thickness * (hasEnhancedArmor ? 1.04 : 1) * equalizer;
if (!noInvalidate) invalidate();
@@ -145,29 +145,29 @@ export function PrimaryArmorSceneComponent({
const hasCalibratedShells = hasEquipment(
103,
Duel.state.antagonist.tank.equipment_preset,
equipment
equipment,
);
material.uniforms.penetration.value =
material.current.uniforms.penetration.value =
penetration *
resolvePenetrationCoefficient(
hasCalibratedShells,
Duel.state.equalize,
shell.type,
Duel.state.antagonist.tank.equalizer
Duel.state.antagonist.tank.equalizer,
);
if (!noInvalidate) invalidate();
}
function handleTransitionEvent(event: QuicklimeEvent<number>) {
material.uniforms.opacity.value = event.data;
material.current.uniforms.opacity.value = event.data;
}
handleShellChange();
handleGreenPenetrationChange(TankopediaPersistent.state.greenPenetration);
handleAdvancedHighlightingChange(
TankopediaPersistent.state.advancedHighlighting
TankopediaPersistent.state.advancedHighlighting,
);
handleOpaqueChange(TankopediaPersistent.state.opaque);
handleWireframeChange(TankopediaPersistent.state.wireframe);
@@ -181,27 +181,27 @@ export function PrimaryArmorSceneComponent({
Tankopedia.on((state) => state.customShell, handleShellChange),
TankopediaPersistent.on(
(state) => state.greenPenetration,
handleGreenPenetrationChange
handleGreenPenetrationChange,
),
TankopediaPersistent.on(
(state) => state.advancedHighlighting,
handleAdvancedHighlightingChange
handleAdvancedHighlightingChange,
),
TankopediaPersistent.on((state) => state.opaque, handleOpaqueChange),
Duel.on(
(state) => state.protagonist.equipmentMatrix,
() => handleProtagonistEquipmentChange()
() => handleProtagonistEquipmentChange(),
),
Duel.on(
(state) => state.antagonist.equipmentMatrix,
() => handleAntagonistEquipmentChange()
() => handleAntagonistEquipmentChange(),
),
Duel.on(
(state) => state.equalize,
() => {
handleProtagonistEquipmentChange();
handleAntagonistEquipmentChange();
}
},
),
() => transitionEvent.off(handleTransitionEvent),
];
@@ -212,13 +212,14 @@ export function PrimaryArmorSceneComponent({
}, []);
useFrame(({ gl, camera }) => {
gl.getSize(material.uniforms.resolution.value).multiplyScalar(
gl.getPixelRatio()
gl.getSize(material.current.uniforms.resolution.value).multiplyScalar(
gl.getPixelRatio(),
);
material.uniforms.spacedArmorBuffer.value = spacedArmorRenderTarget.texture;
material.uniforms.spacedArmorDepth.value =
material.current.uniforms.spacedArmorBuffer.value =
spacedArmorRenderTarget.texture;
material.current.uniforms.spacedArmorDepth.value =
spacedArmorRenderTarget.depthTexture;
material.uniforms.inverseProjectionMatrix.value =
material.current.uniforms.inverseProjectionMatrix.value =
camera.projectionMatrixInverse;
});
@@ -243,7 +244,7 @@ export function PrimaryArmorSceneComponent({
{...props}
key={`${key}-include`}
renderOrder={1}
material={material}
material={material.current}
/>
);
},