player camera gizmo in editor
This commit is contained in:
@@ -6,21 +6,22 @@ import { SceneEditorObjectSelectionLayer } from "./SceneEditor/SceneEditorObject
|
|||||||
import { LightsLayer } from "./LighsLayer";
|
import { LightsLayer } from "./LighsLayer";
|
||||||
import { StatsLayer } from './StatsLayer';
|
import { StatsLayer } from './StatsLayer';
|
||||||
import { SceneEditorObjectGizmosLayer } from "./SceneEditor/SceneEditorObjectGizmosLayer";
|
import { SceneEditorObjectGizmosLayer } from "./SceneEditor/SceneEditorObjectGizmosLayer";
|
||||||
import { PlayButtonsLayer } from "./PlayButtonsLayer";
|
import { PlayButtons } from "./PlayButtons";
|
||||||
|
import { SceneEditorPlayerGizmosLayer } from "./SceneEditor/SceneEditorPlayerGizmosLayer";
|
||||||
|
|
||||||
export const LayeredThreeView = observer(function () {
|
export const LayeredThreeView = observer(function () {
|
||||||
|
|
||||||
return <>
|
return <>
|
||||||
<Canvas>
|
<Canvas>
|
||||||
<LightsLayer />
|
<LightsLayer />
|
||||||
{/* <Perf position="bottom-right" /> */}
|
|
||||||
<SceneEditorCameraLayer />
|
<SceneEditorCameraLayer />
|
||||||
<ObjectGeometriesLayer>
|
<ObjectGeometriesLayer>
|
||||||
<SceneEditorObjectSelectionLayer />
|
<SceneEditorObjectSelectionLayer />
|
||||||
<SceneEditorObjectGizmosLayer />
|
<SceneEditorObjectGizmosLayer />
|
||||||
</ObjectGeometriesLayer>
|
</ObjectGeometriesLayer>
|
||||||
|
<SceneEditorPlayerGizmosLayer />
|
||||||
<StatsLayer />
|
<StatsLayer />
|
||||||
</Canvas>
|
</Canvas>
|
||||||
<PlayButtonsLayer />
|
<PlayButtons />
|
||||||
</>;
|
</>;
|
||||||
});
|
});
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@ import { observer } from "mobx-react-lite";
|
|||||||
import { state } from "../../state";
|
import { state } from "../../state";
|
||||||
import { IconPlayerPlayFilled, IconPlayerPauseFilled, IconPlayerStopFilled, IconPlayerSkipForwardFilled } from '@tabler/icons-react';
|
import { IconPlayerPlayFilled, IconPlayerPauseFilled, IconPlayerStopFilled, IconPlayerSkipForwardFilled } from '@tabler/icons-react';
|
||||||
|
|
||||||
export const PlayButtonsLayer = observer(function () {
|
export const PlayButtons = observer(function () {
|
||||||
return <div style={{ position: 'absolute', top: 8, right: 8, display: 'flex', gap: 4, fontSize: 14 }}>
|
return <div style={{ position: 'absolute', top: 8, right: 8, display: 'flex', gap: 4, fontSize: 14 }}>
|
||||||
{
|
{
|
||||||
state.game
|
state.game
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
import { useEffect, useMemo, useRef } from "react";
|
||||||
|
import * as THREE from "three";
|
||||||
|
import { useThree, useFrame } from "@react-three/fiber";
|
||||||
|
import { observer } from "mobx-react-lite";
|
||||||
|
import { state } from "../../../state";
|
||||||
|
import { computeBoundingBox } from "../../../utils/runtime";
|
||||||
|
|
||||||
|
const _offset = new THREE.Vector3();
|
||||||
|
const _lookAt = new THREE.Vector3();
|
||||||
|
const _euler = new THREE.Euler(0, 0, 0, 'YXZ');
|
||||||
|
|
||||||
|
export const SceneEditorPlayerGizmosLayer = observer(function () {
|
||||||
|
const scene = useThree(s => s.scene);
|
||||||
|
const helperRef = useRef<THREE.CameraHelper | null>(null);
|
||||||
|
|
||||||
|
const playerCam = useMemo(() => new THREE.PerspectiveCamera(75, 16 / 9, 0.1, 1000), []);
|
||||||
|
|
||||||
|
const playerObjectId = state.world.data.initialScene.playerObjectId;
|
||||||
|
const playerObject = playerObjectId
|
||||||
|
? state.world.data.initialScene.objects[playerObjectId]
|
||||||
|
: undefined;
|
||||||
|
const playerType = playerObject
|
||||||
|
? state.world.data.objectTypes[playerObject.typeId]
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!playerObject || !playerType)
|
||||||
|
return;
|
||||||
|
const helper = new THREE.CameraHelper(playerCam);
|
||||||
|
scene.add(helper);
|
||||||
|
helperRef.current = helper;
|
||||||
|
return () => {
|
||||||
|
scene.remove(helper);
|
||||||
|
helper.dispose();
|
||||||
|
helperRef.current = null;
|
||||||
|
};
|
||||||
|
}, [playerObject, playerType, playerCam, scene]);
|
||||||
|
|
||||||
|
useFrame(() => {
|
||||||
|
if (!playerObject || !playerType || !helperRef.current)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const bb = computeBoundingBox(playerType);
|
||||||
|
const W = bb.max[0] - bb.min[0];
|
||||||
|
const H = bb.max[1] - bb.min[1];
|
||||||
|
const D = bb.max[2] - bb.min[2];
|
||||||
|
const radius = Math.sqrt(W * W + H * H + D * D);
|
||||||
|
const centerY = (bb.min[1] + bb.max[1]) / 2;
|
||||||
|
|
||||||
|
const yaw = playerObject.rotation[1];
|
||||||
|
|
||||||
|
_offset.set(W * 0.1, centerY + H * 0.3, bb.max[2] + radius);
|
||||||
|
_offset.applyEuler(_euler.set(0, yaw, 0, 'YXZ'));
|
||||||
|
|
||||||
|
playerCam.position.set(
|
||||||
|
playerObject.position[0] + _offset.x,
|
||||||
|
playerObject.position[1] + _offset.y,
|
||||||
|
playerObject.position[2] + _offset.z,
|
||||||
|
);
|
||||||
|
_lookAt.set(
|
||||||
|
playerObject.position[0],
|
||||||
|
playerObject.position[1] + centerY,
|
||||||
|
playerObject.position[2],
|
||||||
|
);
|
||||||
|
playerCam.lookAt(_lookAt);
|
||||||
|
playerCam.updateMatrixWorld(true);
|
||||||
|
|
||||||
|
helperRef.current.update();
|
||||||
|
});
|
||||||
|
|
||||||
|
return null;
|
||||||
|
});
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import { ViewItem } from "./base";
|
||||||
|
|
||||||
|
export class PlayerViewItem extends ViewItem {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user