gsplat-editor / editor /src /ScaleMode.ts
dylanebert's picture
dylanebert HF staff
initial commit
e6b949c
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 };