Spaces:
Running
Running
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 }; | |