mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 10:47:04 +02:00
feat: dissect event
This commit is contained in:
1 parent
4b24cf313b
commit
43021c4945
6 files changed
+89
-9
No files matched your search
@@ -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> */}
|
||||
</>
|
||||
);
|
||||
},
|
||||
|
||||
+6
-5
@@ -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,
|
||||
})),
|
||||
);
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user