feat: dissect event

This commit is contained in:
tresabhi committed 2025-03-22 20:10:05 -05:00
1 parent 4b24cf313b
commit 43021c4945
6 files changed
+89 -9

No files matched your search

BIN
View File
Binary file not shown.
+1
View File
@@ -20,6 +20,7 @@
"@radix-ui/colors": "^3.0.0",
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/themes": "^3.1.4",
"@react-three/csg": "^4.0.0",
"@react-three/drei": "^9.115.0",
"@react-three/fiber": "^8.17.10",
"compare-versions": "^6.1.1",
@@ -1,12 +1,27 @@
import { asset } from '@blitzkit/core';
import {
Base,
Geometry,
Subtraction,
type CSGGeometryRef,
} from '@react-three/csg';
import { useGLTF } from '@react-three/drei';
import { useEffect, useRef } from 'react';
import type { Mesh } from 'three';
import {
Color,
DoubleSide,
Group,
LineBasicMaterial,
Material,
MeshStandardMaterial,
Vector3,
} from 'three';
import {
dissectEvent,
lastDissection,
type DissectEventData,
} from '../../../core/blitzkit/dissect';
import { jsxTree } from '../../../core/blitzkit/jsxTree';
import { Duel } from '../../../stores/duel';
import { TankopediaEphemeral } from '../../../stores/tankopediaEphemeral';
@@ -16,6 +31,8 @@ interface DissectorSceneComponentProps {
group: string;
}
const NEGATIVE_SIZE = 20;
const armorColor = new Color().multiplyScalar(2 ** -8);
const armorOutlineColor = armorColor.clone().multiplyScalar(2 ** 4.5);
@@ -60,6 +77,10 @@ export function DissectorSceneComponent({
return jsxTree(gltf.scene, {
mesh(mesh, props) {
const csg = useRef<CSGGeometryRef>(null);
const subtractionWrapper = useRef<Group>(null);
const baseWrapper = useRef<Mesh>(null);
if (!(mesh.material instanceof Material)) {
return null;
}
@@ -67,6 +88,10 @@ export function DissectorSceneComponent({
const armorName = mesh.material.name;
const armorPlate = groupArmor.armors[armorName];
if (armorPlate.type === 'Armor' || armorPlate.type === 'ArmorScreen') {
return null;
}
if (!(armorPlate.type in moduleColor)) {
throw new TypeError(`Unhandled armor type: ${armorPlate.type}`);
}
@@ -79,14 +104,55 @@ export function DissectorSceneComponent({
side: DoubleSide,
color: moduleOutlineColor[armorPlate.type],
});
const worldPosition = new Vector3();
useEffect(() => {
function handleDissectEvent(event: DissectEventData) {
if (
!subtractionWrapper.current ||
!csg.current ||
!baseWrapper.current
)
return;
baseWrapper.current.getWorldPosition(worldPosition);
subtractionWrapper.current.position
.copy(worldPosition)
.multiplyScalar(-1);
subtractionWrapper.current.rotation.y = event.rotation;
csg.current.update();
}
dissectEvent.on(handleDissectEvent);
handleDissectEvent(lastDissection);
return () => {
dissectEvent.off(handleDissectEvent);
};
}, []);
return (
<>
<mesh {...props} material={material} />
{/* <mesh {...props} material={material} /> */}
<lineSegments material={outlineMaterial}>
<mesh material={material} ref={baseWrapper}>
<Geometry ref={csg}>
<Base geometry={props.geometry}></Base>
<group rotation={[0, 0, 0]} ref={subtractionWrapper}>
<Subtraction position={[NEGATIVE_SIZE / 2, 0, 0]}>
<boxGeometry
args={[NEGATIVE_SIZE, NEGATIVE_SIZE, NEGATIVE_SIZE]}
/>
</Subtraction>
</group>
</Geometry>
</mesh>
{/* <lineSegments material={outlineMaterial}>
<edgesGeometry args={[props.geometry, 45]} />
</lineSegments>
</lineSegments> */}
</>
);
},
@@ -152,11 +152,12 @@ export const TankSandbox = forwardRef<HTMLCanvasElement, TankSandboxProps>(
return (
<Canvas
frameloop={
onScreen
? display === TankopediaDisplay.ShootingRange
? 'always'
: 'demand'
: 'never'
// onScreen
// ? display === TankopediaDisplay.ShootingRange
// ? 'always'
// : 'demand'
// : 'never'
'always'
}
gl={{
// clippingPlanes: [new Plane(new Vector3(0, 0, 1))],
@@ -0,0 +1,12 @@
import { EventManager } from '@blitzkit/core';
export interface DissectEventData {
rotation: number;
offset: number;
}
export const dissectEvent = new EventManager<DissectEventData>();
export const lastDissection: DissectEventData = { rotation: 0, offset: 0 };
dissectEvent.on((data) => Object.assign(lastDissection, data));
@@ -137,7 +137,7 @@ export const TankopediaEphemeral = createContextualStore(
armor,
controlsEnabled: true,
xpMultiplier: 1,
display: TankopediaDisplay.StaticArmor,
display: TankopediaDisplay.Dissector,
})),
);
},