its functionning
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
import { Suspense, useCallback, useEffect } from "react";
|
||||
import { Canvas, useThree } from "@react-three/fiber";
|
||||
import { Physics } from "@react-three/rapier";
|
||||
import * as THREE from "three";
|
||||
import { DebugPerf } from "@/components/debug/DebugPerf";
|
||||
import { RepairGame } from "@/components/three/gameplay/RepairGame";
|
||||
import { logger } from "@/utils/core/Logger";
|
||||
import type { RepairMissionId } from "@/types/gameplay/repairMission";
|
||||
import type { Vector3Tuple } from "@/types/three/three";
|
||||
|
||||
// Isolated scene — no world offset, no terrain. The repair game runs
|
||||
// fully centred in its own context so the heavy map never loads here.
|
||||
const REPAIR_SCENE_POSITION: Vector3Tuple = [0, 0, 0];
|
||||
|
||||
// Background: very dark blue-grey to match Altera's night-time mood
|
||||
const REPAIR_SCENE_BG = "#0b0d14";
|
||||
|
||||
// Lighting tuned to match the main world defaults from lightingConfig.ts
|
||||
const AMBIENT_COLOR = "#dfe7d8";
|
||||
const AMBIENT_INTENSITY = 0.9;
|
||||
const SUN_COLOR = "#ffe2bf";
|
||||
const SUN_INTENSITY = 2.2;
|
||||
const SUN_POSITION: Vector3Tuple = [5, 8, 4];
|
||||
|
||||
// Mimic the first-person view from the main world:
|
||||
// - PLAYER_EYE_HEIGHT = 1.75 → camera Y
|
||||
// - Case floats at [0, 0.4, 1.8] (inspected) → [0, 1.05, 2.05] (repairing)
|
||||
// - Look-at target averaged between those two states
|
||||
const CAMERA_POSITION: Vector3Tuple = [5, 2, 2];
|
||||
const CAMERA_LOOK_AT: Vector3Tuple = [0, 0.7, 1.9];
|
||||
|
||||
function RepairSceneCamera(): null {
|
||||
const { camera } = useThree();
|
||||
|
||||
useEffect(() => {
|
||||
camera.lookAt(...CAMERA_LOOK_AT);
|
||||
}, [camera]);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
interface RepairGameSceneProps {
|
||||
mission: RepairMissionId;
|
||||
}
|
||||
|
||||
export function RepairGameScene({
|
||||
mission,
|
||||
}: RepairGameSceneProps): React.JSX.Element {
|
||||
const handleCreated = useCallback(({ gl }: { gl: THREE.WebGLRenderer }) => {
|
||||
const canvas = gl.domElement;
|
||||
const loseContextExt = gl.getContext().getExtension("WEBGL_lose_context");
|
||||
|
||||
const handleContextLost = (event: Event) => {
|
||||
event.preventDefault();
|
||||
logger.error("WebGL", "Repair scene context lost — attempting restore");
|
||||
window.setTimeout(() => loseContextExt?.restoreContext(), 500);
|
||||
};
|
||||
|
||||
const handleContextRestored = () => {
|
||||
logger.info("WebGL", "Repair scene context restored");
|
||||
};
|
||||
|
||||
canvas.addEventListener("webglcontextlost", handleContextLost);
|
||||
canvas.addEventListener("webglcontextrestored", handleContextRestored);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Canvas
|
||||
camera={{ position: CAMERA_POSITION, fov: 42 }}
|
||||
shadows={{ type: THREE.PCFShadowMap }}
|
||||
gl={{
|
||||
powerPreference: "high-performance",
|
||||
antialias: true,
|
||||
stencil: false,
|
||||
}}
|
||||
onCreated={handleCreated}
|
||||
>
|
||||
<color attach="background" args={[REPAIR_SCENE_BG]} />
|
||||
|
||||
<RepairSceneCamera />
|
||||
|
||||
{/* Lighting — mirrors the game world defaults */}
|
||||
<ambientLight intensity={AMBIENT_INTENSITY} color={AMBIENT_COLOR} />
|
||||
<directionalLight
|
||||
position={SUN_POSITION}
|
||||
intensity={SUN_INTENSITY}
|
||||
color={SUN_COLOR}
|
||||
castShadow
|
||||
shadow-mapSize-width={1024}
|
||||
shadow-mapSize-height={1024}
|
||||
/>
|
||||
|
||||
<Suspense fallback={null}>
|
||||
{/* Physics is required: TriggerObject and GrabbableObject both use
|
||||
RigidBody. The world is minimal — no octree, no character bodies. */}
|
||||
<Physics>
|
||||
<RepairGame
|
||||
mission={mission}
|
||||
position={REPAIR_SCENE_POSITION}
|
||||
snapToTerrain={false}
|
||||
/>
|
||||
</Physics>
|
||||
</Suspense>
|
||||
|
||||
<DebugPerf />
|
||||
</Canvas>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user