From 4e28d05e51ce0b53ea92aacaa820d1c896647346 Mon Sep 17 00:00:00 2001 From: BFlat Date: Fri, 8 Aug 2025 20:52:03 +0700 Subject: [PATCH] copy paste bug fixes (#756) copy paste character works, tested cmd + c/v works on mac too. --- .../PageEnigma/Editor/keybinds_controls.ts | 23 ++++++--- .../PageEnigma/Editor/scene_manager_api.ts | 49 ++++++++++++++++--- 2 files changed, 57 insertions(+), 15 deletions(-) diff --git a/frontend/apps/editor3d/app/src/pages/PageEnigma/Editor/keybinds_controls.ts b/frontend/apps/editor3d/app/src/pages/PageEnigma/Editor/keybinds_controls.ts index 1e05d70b99..db6c14bd99 100644 --- a/frontend/apps/editor3d/app/src/pages/PageEnigma/Editor/keybinds_controls.ts +++ b/frontend/apps/editor3d/app/src/pages/PageEnigma/Editor/keybinds_controls.ts @@ -329,18 +329,23 @@ export class MouseControls { } if ((event.ctrlKey || event.metaKey) && !this.isProcessing) { - if (event.key === "Z" || event.key === "z") { + const keyLower = event.key.toLowerCase(); + if (keyLower === "z") { // redo this.isProcessing = true; await this.sceneManager?.redo(); this.isProcessing = false; - } else if (event.key === "c") { - // redo + } else if (keyLower === "c") { + // Copy + event.preventDefault(); + event.stopPropagation(); this.isProcessing = true; await this.sceneManager?.copy(); this.isProcessing = false; - } else if (event.key === "v") { - // redo + } else if (keyLower === "v") { + // Paste + event.preventDefault(); + event.stopPropagation(); this.isProcessing = true; await this.sceneManager?.paste(); this.isProcessing = false; @@ -406,7 +411,7 @@ export class MouseControls { // If the mouse is clicked but controls also locked, move the camera with the mouse const camera = this.lockControls.getObject(); - const _euler = new Euler(0, 0, 0, 'YXZ'); + const _euler = new Euler(0, 0, 0, "YXZ"); const _MOUSE_SENSITIVITY = 0.002; const pointerSpeed = 1.0; const _PI_2 = Math.PI / 2; @@ -418,7 +423,10 @@ export class MouseControls { _euler.y -= event.movementX * _MOUSE_SENSITIVITY * pointerSpeed; _euler.x -= event.movementY * _MOUSE_SENSITIVITY * pointerSpeed; - _euler.x = Math.max(_PI_2 - maxPolarAngle, Math.min(_PI_2 - minPolarAngle, _euler.x)); + _euler.x = Math.max( + _PI_2 - maxPolarAngle, + Math.min(_PI_2 - minPolarAngle, _euler.x), + ); camera.quaternion.setFromEuler(_euler); } else if (this.lockControls) { @@ -452,7 +460,6 @@ export class MouseControls { } else { this.handleMousePointerLock(); } - } // When the mouse clicks the screen. diff --git a/frontend/apps/editor3d/app/src/pages/PageEnigma/Editor/scene_manager_api.ts b/frontend/apps/editor3d/app/src/pages/PageEnigma/Editor/scene_manager_api.ts index b76d53826f..1ba68fc66c 100644 --- a/frontend/apps/editor3d/app/src/pages/PageEnigma/Editor/scene_manager_api.ts +++ b/frontend/apps/editor3d/app/src/pages/PageEnigma/Editor/scene_manager_api.ts @@ -8,6 +8,11 @@ import { import Scene from "./scene"; import { MouseControls } from "./keybinds_controls"; import { ClipGroup } from "~/enums"; +import Queue from "~/pages/PageEnigma/Queue/Queue"; +import { QueueNames } from "~/pages/PageEnigma/Queue/QueueNames"; +import { fromEngineActions } from "~/pages/PageEnigma/Queue/fromEngineActions"; +import { MediaItem } from "~/pages/PageEnigma/models"; +import { AssetType } from "~/enums"; import { CommandInputTypes, CreationSceneItem, @@ -146,8 +151,7 @@ export class SceneManager implements SceneManagerAPI { if (media_token.includes("SKY::")) { const token = media_token.replace("SKY::", ""); this.scene.updateSkybox(token); - } - else if (media_token !== "Parim") { + } else if (media_token !== "Parim") { return await this.scene.loadObject( media_token, name, @@ -265,11 +269,9 @@ export class SceneManager implements SceneManagerAPI { } public async copy() { - // TODO MAKE BETTER FIX: Temp disables copy and paste of characters. - const object = this.mouse_controls.selected?.at(0) - if (object !== undefined) { - if (this.is_character(object.uuid) === false) - this.copiedObject = object; + const object = this.mouse_controls.selected?.at(0); + if (object !== undefined && object.name !== "::CAM::") { + this.copiedObject = object; } } @@ -283,6 +285,7 @@ export class SceneManager implements SceneManagerAPI { const media_id = userdata["media_id"]; const color = userdata["color"]; const name = this.copiedObject.name; + const wasCharacter: boolean = !!this.copiedObject.userData.isCharacter; const obj = await this.create(media_id, name, position); this.scene.setColor(obj.uuid, color); @@ -290,8 +293,40 @@ export class SceneManager implements SceneManagerAPI { obj.rotation.copy(rotation); obj.scale.copy(scale); + // Preserve character stuff on pasted object + if (wasCharacter) { + obj.userData.isCharacter = true; + } + this.mouse_controls.selectObject(obj); this.updateOutliner(); + + if (wasCharacter) { + Queue.publish({ + queueName: QueueNames.FROM_ENGINE, + action: fromEngineActions.UPDATE_CHARACTER_ID, + data: { + version: 1, + type: AssetType.CHARACTER, + media_id: media_id, + object_uuid: obj.uuid, + name: name, + } as MediaItem, + }); + } else { + Queue.publish({ + queueName: QueueNames.FROM_ENGINE, + action: fromEngineActions.ADD_OBJECT, + data: { + version: 1, + type: AssetType.OBJECT, + media_id: media_id, + object_uuid: obj.uuid, + name: name, + } as MediaItem, + }); + } + await this.copy(); await this.add_creation_undostack(obj); }