mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-04 01:18:34 +00:00
PageScene: move switchCameraView into CameraController via DI
CameraController now owns switchCameraView. The body lifted from SceneUtils.switchCameraView gets cross-subsystem capabilities (scene access, transform-controls removal, selection write, editor-state and object-panel store actions) through a new CameraControllerDeps object that Editor wires up in initialize(). This keeps subsystems from importing each other directly: the controller sees a narrow callback surface, not SelectionBridge or SceneUtils. Same precedent as the existing ViewportController setters. Deletes: - SceneUtils.switchCameraView (helper.ts) - Editor.switchCameraView facade The space-bar handler in MouseControls now points directly at cameraController.switchCameraView via the callback Editor passes in.
This commit is contained in:
1 parent
554a76d35f
commit
89ac302392
3 files changed
+98
-70
No files matched your search
@@ -137,7 +137,19 @@ class Editor {
|
||||
// load paths invoke updateSurfaceIdAttributeToMesh as a callback.
|
||||
this.postProcessing = new PostProcessingPipeline();
|
||||
this.gizmo = new GizmoController();
|
||||
this.cameraController = new CameraController();
|
||||
this.cameraController = new CameraController({
|
||||
getThreeScene: () => this.activeScene.scene,
|
||||
getHotItems: () => this.activeScene.hot_items ?? null,
|
||||
removeTransformControls: () => this.utils.removeTransformControls(),
|
||||
setSelected: (obj) => {
|
||||
this.selection.selected = obj ?? undefined;
|
||||
this.selection.publishSelect();
|
||||
this.selection.updateSelectedUI();
|
||||
},
|
||||
setEditorState: (state) =>
|
||||
usePageSceneStore.getState().setEditorState(state),
|
||||
hideObjectPanel: () => usePageSceneStore.getState().hideObjectPanel(),
|
||||
});
|
||||
this.selection = new SelectionBridge({
|
||||
getSceneManager: () => this.sceneManager,
|
||||
cameraName: this.cameraController.camera_name,
|
||||
@@ -353,7 +365,7 @@ class Editor {
|
||||
this.cameraController.freeCamState,
|
||||
this.cameraController.lockControls,
|
||||
this.cameraController.camera_last_pos,
|
||||
this.switchCameraView.bind(this),
|
||||
this.cameraController.switchCameraView.bind(this.cameraController),
|
||||
this.deleteObject.bind(this),
|
||||
this.viewport.canvReference,
|
||||
this.mouse,
|
||||
@@ -671,10 +683,6 @@ class Editor {
|
||||
});
|
||||
}
|
||||
|
||||
switchCameraView() {
|
||||
this.utils.switchCameraView();
|
||||
}
|
||||
|
||||
deleteObject(uuid: string) {
|
||||
this.mouse_controls?.clearFKVisuals();
|
||||
this.mouse_controls?.removeTransformControls(true);
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
lookAtFromCamera,
|
||||
type FreeCamControlState,
|
||||
} from "../cameraMath";
|
||||
import { CameraAspectRatio } from "~/pages/PageScene/enums";
|
||||
import { CameraAspectRatio, EditorStates } from "~/pages/PageScene/enums";
|
||||
import { usePageSceneStore } from "~/pages/PageScene/PageSceneStore";
|
||||
|
||||
export type RenderDimensions = {
|
||||
@@ -14,6 +14,18 @@ export type RenderDimensions = {
|
||||
aspectRatio: number;
|
||||
};
|
||||
|
||||
// Capabilities CameraController needs from outside its own state.
|
||||
// Editor wires these in initialize() so CameraController never imports
|
||||
// sibling subsystems directly.
|
||||
export type CameraControllerDeps = {
|
||||
getThreeScene: () => THREE.Scene;
|
||||
getHotItems: () => THREE.Object3D[] | null;
|
||||
removeTransformControls: () => void;
|
||||
setSelected: (obj: THREE.Object3D | null) => void;
|
||||
setEditorState: (state: EditorStates) => void;
|
||||
hideObjectPanel: () => void;
|
||||
};
|
||||
|
||||
// Owns the editor's camera-related state: the live PerspectiveCameras,
|
||||
// the cam_obj proxy in the scene, FreeCam control state, lockControls,
|
||||
// and the per-frame camera tick that ran inline in renderSingleFrame.
|
||||
@@ -42,12 +54,82 @@ export class CameraController {
|
||||
render_width: number;
|
||||
render_height: number;
|
||||
|
||||
constructor() {
|
||||
private deps: CameraControllerDeps;
|
||||
|
||||
constructor(deps: CameraControllerDeps) {
|
||||
this.deps = deps;
|
||||
const dims = this.getRenderDimensions();
|
||||
this.render_width = dims.width;
|
||||
this.render_height = dims.height;
|
||||
}
|
||||
|
||||
// Toggles between free-camera (edit) mode and the active render
|
||||
// camera's perspective. Lifted from SceneUtils.switchCameraView so
|
||||
// the camera state stays in one place.
|
||||
switchCameraView() {
|
||||
this.camera_person_mode = !this.camera_person_mode;
|
||||
if (this.freeCamState) {
|
||||
this.freeCamState.velocity.set(0, 0, 0);
|
||||
}
|
||||
if (!this.cam_obj) return;
|
||||
|
||||
if (this.camera_person_mode && this.camera) {
|
||||
this.last_cam_pos.copy(this.camera.position);
|
||||
this.last_cam_rot.copy(this.camera.rotation);
|
||||
|
||||
this.camera.position.copy(this.cam_obj.position);
|
||||
this.camera.rotation.copy(this.cam_obj.rotation);
|
||||
|
||||
if (this.lockControls) {
|
||||
this.deps.getThreeScene().add(this.lockControls.getObject());
|
||||
}
|
||||
// useFreeCam reads editorState from the store and enables
|
||||
// itself when CAMERA_VIEW; nothing to do here.
|
||||
this.cam_obj.scale.set(0, 0, 0);
|
||||
|
||||
this.deps.removeTransformControls();
|
||||
this.deps.setSelected(this.cam_obj);
|
||||
this.deps.setEditorState(EditorStates.CAMERA_VIEW);
|
||||
|
||||
const hot = this.deps.getHotItems();
|
||||
if (hot) {
|
||||
hot.forEach((element) => {
|
||||
element.visible = false;
|
||||
});
|
||||
}
|
||||
|
||||
// Workaround: in camera mode, a right-click should pan rather
|
||||
// than open the browser context menu. Defer the listener attach
|
||||
// until after the letterbox swap settles.
|
||||
setTimeout(
|
||||
() =>
|
||||
document
|
||||
.getElementById("letterbox")
|
||||
?.addEventListener("contextmenu", function (event) {
|
||||
event.preventDefault();
|
||||
}),
|
||||
250,
|
||||
);
|
||||
} else if (this.camera) {
|
||||
this.camera.position.copy(this.last_cam_pos);
|
||||
this.camera.rotation.copy(this.last_cam_rot);
|
||||
if (this.lockControls) {
|
||||
this.deps.getThreeScene().remove(this.lockControls.getObject());
|
||||
}
|
||||
this.cam_obj.scale.set(1, 1, 1);
|
||||
|
||||
const hot = this.deps.getHotItems();
|
||||
if (hot) {
|
||||
hot.forEach((element) => {
|
||||
element.visible = true;
|
||||
});
|
||||
}
|
||||
|
||||
this.deps.hideObjectPanel();
|
||||
this.deps.setEditorState(EditorStates.EDIT);
|
||||
}
|
||||
}
|
||||
|
||||
setFreeCamState(state: FreeCamControlState | null) {
|
||||
this.freeCamState = state;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ import Scene from "./scene";
|
||||
import Editor from "./editor";
|
||||
import * as THREE from "three";
|
||||
import { XYZ } from "../datastructures/common";
|
||||
import { EditorStates } from "../enums";
|
||||
import { usePageSceneStore } from "../PageSceneStore";
|
||||
|
||||
export class SceneUtils {
|
||||
@@ -112,67 +111,6 @@ export class SceneUtils {
|
||||
}
|
||||
}
|
||||
|
||||
switchCameraView() {
|
||||
const cam = this.editor.cameraController;
|
||||
cam.camera_person_mode = !cam.camera_person_mode;
|
||||
if (cam.freeCamState) {
|
||||
cam.freeCamState.velocity.set(0, 0, 0);
|
||||
}
|
||||
if (cam.cam_obj) {
|
||||
if (cam.camera_person_mode && cam.camera) {
|
||||
cam.last_cam_pos.copy(cam.camera.position);
|
||||
cam.last_cam_rot.copy(cam.camera.rotation);
|
||||
|
||||
cam.camera.position.copy(cam.cam_obj.position);
|
||||
cam.camera.rotation.copy(cam.cam_obj.rotation);
|
||||
|
||||
if (cam.lockControls) {
|
||||
this.editor.activeScene.scene.add(cam.lockControls.getObject());
|
||||
}
|
||||
// useFreeCam reads editorState from the store and enables
|
||||
// itself when CAMERA_VIEW; nothing to do here.
|
||||
cam.cam_obj.scale.set(0, 0, 0);
|
||||
|
||||
this.removeTransformControls();
|
||||
this.editor.selection.selected = cam.cam_obj;
|
||||
this.editor.publishSelect();
|
||||
this.editor.updateSelectedUI();
|
||||
usePageSceneStore.getState().setEditorState(EditorStates.CAMERA_VIEW);
|
||||
if (this.editor.activeScene.hot_items) {
|
||||
this.editor.activeScene.hot_items.forEach((element) => {
|
||||
element.visible = false;
|
||||
});
|
||||
}
|
||||
|
||||
// Make a better solution later but for now this is so that in camera mode when you right click it does not bring up the context menu and allows you to pan.
|
||||
setTimeout(
|
||||
() =>
|
||||
document
|
||||
.getElementById("letterbox")
|
||||
?.addEventListener("contextmenu", function (event) {
|
||||
event.preventDefault();
|
||||
}),
|
||||
250,
|
||||
);
|
||||
} else if (cam.camera) {
|
||||
cam.camera.position.copy(cam.last_cam_pos);
|
||||
cam.camera.rotation.copy(cam.last_cam_rot);
|
||||
if (cam.lockControls) {
|
||||
this.editor.activeScene.scene.remove(cam.lockControls.getObject());
|
||||
}
|
||||
cam.cam_obj.scale.set(1, 1, 1);
|
||||
if (this.editor.activeScene.hot_items) {
|
||||
this.editor.activeScene.hot_items.forEach((element) => {
|
||||
element.visible = true;
|
||||
});
|
||||
}
|
||||
|
||||
usePageSceneStore.getState().hideObjectPanel();
|
||||
usePageSceneStore.getState().setEditorState(EditorStates.EDIT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the "check sum" of the editors selected object.
|
||||
getSelectedSum(): number {
|
||||
if (this.editor.sceneManager?.selected_objects === undefined) {
|
||||
|
||||
Reference in new issue
Block a user