mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-11-15 05:36:11 +01:00
feat: code split containers
This commit is contained in:
1 parent
39e4bce254
commit
56d8392f12
8 files changed
+395
-308
No files matched your search
@@ -0,0 +1,135 @@
|
||||
import { ThreeEvent, useThree } from '@react-three/fiber';
|
||||
import { clamp } from 'lodash';
|
||||
import { RefObject, useRef } from 'react';
|
||||
import { Group, Mesh, Object3D, Vector3 } from 'three';
|
||||
import {
|
||||
PitchLimits,
|
||||
YawLimits,
|
||||
} from '../../../../../core/blitzkrieg/modelDefinitions';
|
||||
import { resolveJsxTree } from '../../../../../core/blitzkrieg/resolveJsxTree';
|
||||
import { normalizeAnglePI } from '../../../../../core/math/normalizeAngle180';
|
||||
|
||||
interface GunContainerProps {
|
||||
turretOrigin: Vector3;
|
||||
gunOrigin: Vector3;
|
||||
gunPitch: number;
|
||||
turretYaw: number;
|
||||
objects: Object3D[];
|
||||
model: number;
|
||||
yawLimits?: YawLimits;
|
||||
pitchLimits: PitchLimits;
|
||||
onPitchStart: () => void;
|
||||
onPitchEnd: (pitch: number, yaw: number) => void;
|
||||
turretContainer: RefObject<Group>;
|
||||
}
|
||||
|
||||
export function GunContainer({
|
||||
gunOrigin,
|
||||
turretOrigin,
|
||||
gunPitch,
|
||||
turretYaw,
|
||||
objects,
|
||||
yawLimits,
|
||||
onPitchStart,
|
||||
turretContainer,
|
||||
pitchLimits,
|
||||
model,
|
||||
onPitchEnd,
|
||||
}: GunContainerProps) {
|
||||
const canvas = useThree((state) => state.gl.domElement);
|
||||
const gunContainer = useRef<Group>(null);
|
||||
|
||||
return (
|
||||
<group
|
||||
position={new Vector3()
|
||||
.sub(turretOrigin)
|
||||
.sub(gunOrigin)
|
||||
.applyAxisAngle(new Vector3(1, 0, 0), gunPitch)
|
||||
.add(turretOrigin)
|
||||
.add(gunOrigin)}
|
||||
rotation={[gunPitch, 0, 0]}
|
||||
ref={gunContainer}
|
||||
>
|
||||
{objects.map((object) => {
|
||||
const isCurrentMantlet =
|
||||
object.name === `gun_${model.toString().padStart(2, '0')}_mask`;
|
||||
const isCurrentGun =
|
||||
object.name === `gun_${model.toString().padStart(2, '0')}`;
|
||||
const isVisible = isCurrentGun || isCurrentMantlet;
|
||||
let draftMantletPitch = 0;
|
||||
let draftTurretYaw = 0;
|
||||
|
||||
function handlePointerDown(event: ThreeEvent<PointerEvent>) {
|
||||
event.stopPropagation();
|
||||
|
||||
onPitchStart();
|
||||
draftMantletPitch = gunPitch;
|
||||
draftTurretYaw = turretYaw;
|
||||
window.addEventListener('pointermove', handlePointerMove);
|
||||
window.addEventListener('pointerup', handlePointerUp);
|
||||
}
|
||||
function handlePointerMove(event: PointerEvent) {
|
||||
if (yawLimits) {
|
||||
draftTurretYaw = clamp(
|
||||
draftTurretYaw + event.movementX * (Math.PI / canvas.width),
|
||||
-yawLimits.max * (Math.PI / 180),
|
||||
-yawLimits.min * (Math.PI / 180),
|
||||
);
|
||||
} else {
|
||||
draftTurretYaw += event.movementX * ((2 * Math.PI) / canvas.width);
|
||||
}
|
||||
draftMantletPitch = clamp(
|
||||
draftMantletPitch - event.movementY * (Math.PI / canvas.height),
|
||||
-pitchLimits.max * (Math.PI / 180),
|
||||
-pitchLimits.min * (Math.PI / 180),
|
||||
);
|
||||
|
||||
if (gunContainer.current) {
|
||||
gunContainer.current.position
|
||||
.set(0, 0, 0)
|
||||
.sub(turretOrigin)
|
||||
.sub(gunOrigin)
|
||||
.applyAxisAngle(new Vector3(1, 0, 0), draftMantletPitch)
|
||||
.add(turretOrigin)
|
||||
.add(gunOrigin);
|
||||
gunContainer.current.rotation.x = draftMantletPitch;
|
||||
}
|
||||
|
||||
if (turretContainer.current) {
|
||||
turretContainer.current.position
|
||||
.set(0, 0, 0)
|
||||
.sub(turretOrigin)
|
||||
.applyAxisAngle(new Vector3(0, 0, 1), draftTurretYaw)
|
||||
.add(turretOrigin);
|
||||
turretContainer.current.rotation.z = draftTurretYaw;
|
||||
}
|
||||
}
|
||||
function handlePointerUp() {
|
||||
onPitchEnd(
|
||||
normalizeAnglePI(draftMantletPitch),
|
||||
normalizeAnglePI(draftTurretYaw),
|
||||
);
|
||||
window.removeEventListener('pointermove', handlePointerMove);
|
||||
window.removeEventListener('pointerup', handlePointerUp);
|
||||
}
|
||||
|
||||
if (!isVisible) return null;
|
||||
return (
|
||||
<mesh
|
||||
visible={isVisible}
|
||||
onPointerDown={handlePointerDown}
|
||||
children={resolveJsxTree(object)}
|
||||
key={object.uuid}
|
||||
castShadow
|
||||
receiveShadow
|
||||
geometry={(object as Mesh).geometry}
|
||||
material={(object as Mesh).material}
|
||||
position={object.position}
|
||||
rotation={object.rotation}
|
||||
scale={object.scale}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</group>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
import { ThreeEvent, useThree } from '@react-three/fiber';
|
||||
import { ReactNode, forwardRef, useImperativeHandle, useRef } from 'react';
|
||||
import { Group, Mesh, Object3D } from 'three';
|
||||
import { resolveJsxTree } from '../../../../../core/blitzkrieg/resolveJsxTree';
|
||||
import { normalizeAnglePI } from '../../../../../core/math/normalizeAngle180';
|
||||
|
||||
interface HullContainerProps {
|
||||
children: ReactNode;
|
||||
yaw: number;
|
||||
objects: Object3D[];
|
||||
onYawStart: () => void;
|
||||
onYawEnd: (yaw: number) => void;
|
||||
}
|
||||
|
||||
export const HullContainer = forwardRef<Group, HullContainerProps>(
|
||||
({ children, yaw, objects, onYawStart, onYawEnd }, ref) => {
|
||||
const canvas = useThree((state) => state.gl.domElement);
|
||||
const hullContainer = useRef<Group>(null);
|
||||
|
||||
useImperativeHandle(ref, () => hullContainer.current!);
|
||||
|
||||
return (
|
||||
<group ref={hullContainer} rotation={[-Math.PI / 2, 0, yaw]}>
|
||||
{objects.map((object) => {
|
||||
const isHull = object.name === 'hull';
|
||||
const isWheel = object.name.startsWith('chassis_wheel_');
|
||||
const isTrack = object.name.startsWith('chassis_track_');
|
||||
const isVisible = isHull || isWheel || isTrack;
|
||||
let draftHullYaw = 0;
|
||||
|
||||
function handlePointerDown(event: ThreeEvent<PointerEvent>) {
|
||||
event.stopPropagation();
|
||||
|
||||
draftHullYaw = yaw;
|
||||
|
||||
onYawStart();
|
||||
window.addEventListener('pointermove', handlePointerMove);
|
||||
window.addEventListener('pointerup', handlePointerUp);
|
||||
}
|
||||
function handlePointerMove(event: PointerEvent) {
|
||||
draftHullYaw += event.movementX * ((2 * Math.PI) / canvas.width);
|
||||
|
||||
if (hullContainer.current) {
|
||||
hullContainer.current.rotation.z = draftHullYaw;
|
||||
}
|
||||
}
|
||||
function handlePointerUp() {
|
||||
onYawEnd(normalizeAnglePI(draftHullYaw));
|
||||
window.removeEventListener('pointermove', handlePointerMove);
|
||||
window.removeEventListener('pointerup', handlePointerUp);
|
||||
}
|
||||
|
||||
if (!isVisible) return null;
|
||||
return (
|
||||
<mesh
|
||||
children={resolveJsxTree(object)}
|
||||
key={object.uuid}
|
||||
castShadow
|
||||
receiveShadow
|
||||
geometry={(object as Mesh).geometry}
|
||||
material={(object as Mesh).material}
|
||||
position={object.position}
|
||||
rotation={object.rotation}
|
||||
scale={object.scale}
|
||||
onPointerDown={handlePointerDown}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
||||
{children}
|
||||
</group>
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -0,0 +1,26 @@
|
||||
import { Color } from 'three';
|
||||
import InfiniteGridHelper from '../../../../../components/InfiniteGridHelper';
|
||||
|
||||
export function SceneProps() {
|
||||
return (
|
||||
<>
|
||||
<InfiniteGridHelper
|
||||
size1={1 / 5}
|
||||
size2={1}
|
||||
distance={20}
|
||||
color={new Color('#ffffff')}
|
||||
/>
|
||||
<InfiniteGridHelper
|
||||
position={[0, 1e-4, 0]}
|
||||
size1={0}
|
||||
size2={100}
|
||||
distance={25}
|
||||
color={new Color('red')}
|
||||
/>
|
||||
|
||||
<directionalLight position={[1, 1, -1]} intensity={1} castShadow />
|
||||
<directionalLight position={[-1, 1, 1]} intensity={2} castShadow />
|
||||
<ambientLight intensity={0.25} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
import { ThreeEvent, useThree } from '@react-three/fiber';
|
||||
import { ReactNode, forwardRef, useImperativeHandle, useRef } from 'react';
|
||||
import { Group, Mesh, Object3D, Vector3 } from 'three';
|
||||
import { resolveJsxTree } from '../../../../../core/blitzkrieg/resolveJsxTree';
|
||||
import { normalizeAnglePI } from '../../../../../core/math/normalizeAngle180';
|
||||
|
||||
interface TurretContainerProps {
|
||||
origin: Vector3;
|
||||
objects: Object3D[];
|
||||
children: ReactNode;
|
||||
yaw: number;
|
||||
model: number;
|
||||
onYawStart: () => void;
|
||||
onYawEnd: (yaw: number) => void;
|
||||
}
|
||||
|
||||
export const TurretContainer = forwardRef(
|
||||
(
|
||||
{
|
||||
origin,
|
||||
yaw,
|
||||
children,
|
||||
objects,
|
||||
model,
|
||||
onYawEnd,
|
||||
onYawStart,
|
||||
}: TurretContainerProps,
|
||||
ref,
|
||||
) => {
|
||||
const canvas = useThree((state) => state.gl.domElement);
|
||||
const turretContainer = useRef<Group>(null);
|
||||
|
||||
useImperativeHandle(ref, () => turretContainer.current!);
|
||||
|
||||
return (
|
||||
<group
|
||||
position={new Vector3()
|
||||
.sub(origin)
|
||||
.applyAxisAngle(new Vector3(0, 0, 1), yaw)
|
||||
.add(origin)}
|
||||
rotation={[0, 0, yaw]}
|
||||
ref={turretContainer}
|
||||
>
|
||||
{objects.map((object) => {
|
||||
const isTurret = object.name.startsWith('turret_');
|
||||
const isCurrentTurret =
|
||||
object.name === `turret_${model.toString().padStart(2, '0')}`;
|
||||
const isVisible = isCurrentTurret;
|
||||
let draftYaw = 0;
|
||||
|
||||
function handlePointerDown(event: ThreeEvent<PointerEvent>) {
|
||||
event.stopPropagation();
|
||||
|
||||
if (isTurret) {
|
||||
draftYaw = yaw;
|
||||
|
||||
onYawStart();
|
||||
window.addEventListener('pointermove', handlePointerMove);
|
||||
window.addEventListener('pointerup', handlePointerUp);
|
||||
}
|
||||
}
|
||||
function handlePointerMove(event: PointerEvent) {
|
||||
draftYaw += event.movementX * ((2 * Math.PI) / canvas.width);
|
||||
|
||||
if (turretContainer.current) {
|
||||
turretContainer.current.position
|
||||
.set(0, 0, 0)
|
||||
.sub(origin)
|
||||
.applyAxisAngle(new Vector3(0, 0, 1), draftYaw)
|
||||
.add(origin);
|
||||
turretContainer.current.rotation.z = draftYaw;
|
||||
}
|
||||
}
|
||||
function handlePointerUp() {
|
||||
onYawEnd(normalizeAnglePI(draftYaw));
|
||||
window.removeEventListener('pointermove', handlePointerMove);
|
||||
window.removeEventListener('pointerup', handlePointerUp);
|
||||
}
|
||||
|
||||
if (!isVisible) return null;
|
||||
return (
|
||||
<mesh
|
||||
visible={isVisible}
|
||||
onPointerDown={handlePointerDown}
|
||||
children={resolveJsxTree(object)}
|
||||
key={object.uuid}
|
||||
castShadow
|
||||
receiveShadow
|
||||
geometry={(object as Mesh).geometry}
|
||||
material={(object as Mesh).material}
|
||||
position={object.position}
|
||||
rotation={object.rotation}
|
||||
scale={object.scale}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
||||
{children}
|
||||
</group>
|
||||
);
|
||||
},
|
||||
);
|
||||
Reference in new issue
Block a user