Spaces:
Sleeping
Sleeping
| import * as SPLAT from "gsplat"; | |
| import { InputMode } from "./InputMode"; | |
| import { Engine } from "./Engine"; | |
| import { ModeManager } from "./ModeManager"; | |
| import { SelectionManager } from "./SelectionManager"; | |
| import { UndoManager } from "./UndoManager"; | |
| import { ScaleAction } from "./ScaleAction"; | |
| class ScaleMode implements InputMode { | |
| exit: () => void; | |
| constructor(engine: Engine) { | |
| const splat = SelectionManager.selectedSplat as SPLAT.Splat; | |
| const initialMousePosition = engine.mouseManager.currentMousePosition.clone(); | |
| const initialScale = splat.scale.clone(); | |
| let axis: "x" | "y" | "z" | null = null; | |
| const handleClick = () => { | |
| const action = new ScaleAction(splat, initialScale, splat.scale); | |
| UndoManager.do(action); | |
| ModeManager.enterMode("default"); | |
| }; | |
| const handleCancel = () => { | |
| splat.scale = initialScale; | |
| ModeManager.enterMode("default"); | |
| }; | |
| const handleMouseMove = () => { | |
| const plane = new SPLAT.Plane(engine.camera.forward, splat.position); | |
| const initialDirection = engine.camera.screenPointToRay(initialMousePosition.x, initialMousePosition.y); | |
| const newDirection = engine.camera.screenPointToRay( | |
| engine.mouseManager.currentMousePosition.x, | |
| engine.mouseManager.currentMousePosition.y, | |
| ); | |
| const initialIntersection = plane.intersect(engine.camera.position, initialDirection); | |
| const newIntersection = plane.intersect(engine.camera.position, newDirection); | |
| if (initialIntersection && newIntersection) { | |
| const initialDistance = initialIntersection.subtract(splat.position).magnitude(); | |
| const distance = newIntersection.subtract(splat.position).magnitude(); | |
| const scaleRatio = distance / initialDistance; | |
| let scaleAxis = SPLAT.Vector3.One(); | |
| switch (axis) { | |
| case "x": | |
| scaleAxis = new SPLAT.Vector3(1, 0, 0); | |
| break; | |
| case "y": | |
| scaleAxis = new SPLAT.Vector3(0, 1, 0); | |
| break; | |
| case "z": | |
| scaleAxis = new SPLAT.Vector3(0, 0, 1); | |
| break; | |
| } | |
| scaleAxis = splat.rotation.apply(scaleAxis); | |
| scaleAxis = new SPLAT.Vector3(Math.abs(scaleAxis.x), Math.abs(scaleAxis.y), Math.abs(scaleAxis.z)); | |
| const scaling = scaleAxis.multiply(scaleRatio).add(SPLAT.Vector3.One().subtract(scaleAxis)); | |
| splat.scale = initialScale.multiply(scaling); | |
| } | |
| }; | |
| const handleAxisX = () => { | |
| if (axis === "x") { | |
| axis = null; | |
| } else { | |
| axis = "x"; | |
| } | |
| handleMouseMove(); | |
| }; | |
| const handleAxisY = () => { | |
| if (axis === "y") { | |
| axis = null; | |
| } else { | |
| axis = "y"; | |
| } | |
| handleMouseMove(); | |
| }; | |
| const handleAxisZ = () => { | |
| if (axis === "z") { | |
| axis = null; | |
| } else { | |
| axis = "z"; | |
| } | |
| handleMouseMove(); | |
| }; | |
| engine.mouseManager.registerMouse("click", handleClick); | |
| engine.mouseManager.registerMouse("contextmenu", handleCancel); | |
| engine.mouseManager.registerMouse("mousemove", handleMouseMove); | |
| engine.keyboardManager.registerKey("Escape", handleCancel); | |
| engine.keyboardManager.registerKey("s", handleCancel); | |
| engine.keyboardManager.registerKey("x", handleAxisX); | |
| engine.keyboardManager.registerKey("y", handleAxisY); | |
| engine.keyboardManager.registerKey("z", handleAxisZ); | |
| this.exit = () => { | |
| engine.mouseManager.unregisterMouse("click"); | |
| engine.mouseManager.unregisterMouse("contextmenu"); | |
| engine.mouseManager.unregisterMouse("mousemove"); | |
| engine.keyboardManager.unregisterKey("Escape"); | |
| engine.keyboardManager.unregisterKey("s"); | |
| engine.keyboardManager.unregisterKey("x"); | |
| engine.keyboardManager.unregisterKey("y"); | |
| engine.keyboardManager.unregisterKey("z"); | |
| }; | |
| } | |
| } | |
| export { ScaleMode }; | |