diff --git a/src/core/transform-session.ts b/src/core/transform-session.ts index 3d56ae67..9e1301bb 100644 --- a/src/core/transform-session.ts +++ b/src/core/transform-session.ts @@ -25,6 +25,7 @@ import type { ViewportPanelId } from "../viewport-three/viewport-layout"; export type TransformOperation = "translate" | "rotate" | "scale"; export type TransformAxis = "x" | "y" | "z"; +export type TransformAxisSpace = "world" | "local"; export type TransformSessionSource = "keyboard" | "gizmo" | "toolbar"; export interface YawEntityRotationState { @@ -145,6 +146,7 @@ export interface ActiveTransformSession { sourcePanelId: ViewportPanelId; operation: TransformOperation; axisConstraint: TransformAxis | null; + axisConstraintSpace: TransformAxisSpace; target: TransformTarget; preview: TransformPreview; } @@ -307,6 +309,7 @@ export function cloneTransformSession(session: TransformSessionState): Transform sourcePanelId: session.sourcePanelId, operation: session.operation, axisConstraint: session.axisConstraint, + axisConstraintSpace: session.axisConstraintSpace, target: cloneTransformTarget(session.target), preview: cloneTransformPreview(session.preview) }; @@ -327,6 +330,7 @@ export function areTransformSessionsEqual(left: TransformSessionState, right: Tr left.sourcePanelId === right.sourcePanelId && left.operation === right.operation && left.axisConstraint === right.axisConstraint && + left.axisConstraintSpace === right.axisConstraintSpace && areTransformTargetsEqual(left.target, right.target) && areTransformPreviewsEqual(left.preview, right.preview) ); @@ -428,6 +432,7 @@ export function createTransformSession(options: { sourcePanelId: ViewportPanelId; operation: TransformOperation; axisConstraint?: TransformAxis | null; + axisConstraintSpace?: TransformAxisSpace; target: TransformTarget; }): ActiveTransformSession { return { @@ -437,6 +442,7 @@ export function createTransformSession(options: { sourcePanelId: options.sourcePanelId, operation: options.operation, axisConstraint: options.axisConstraint ?? null, + axisConstraintSpace: options.axisConstraintSpace ?? "world", target: cloneTransformTarget(options.target), preview: createTransformPreviewFromTarget(options.target) }; @@ -515,6 +521,15 @@ export function getTransformAxisLabel(axis: TransformAxis): string { return axis.toUpperCase(); } +export function getTransformAxisSpaceLabel(axisSpace: TransformAxisSpace): string { + switch (axisSpace) { + case "world": + return "World"; + case "local": + return "Local"; + } +} + export function getTransformTargetLabel(target: TransformTarget): string { switch (target.kind) { case "brush": @@ -608,6 +623,28 @@ export function supportsTransformAxisConstraint(session: ActiveTransformSession, } } +export function supportsLocalTransformAxisConstraint(session: ActiveTransformSession, axis: TransformAxis): boolean { + if (!supportsTransformAxisConstraint(session, axis)) { + return false; + } + + if (session.operation === "scale") { + return false; + } + + switch (session.target.kind) { + case "brush": + case "modelInstance": + return true; + case "entity": + return session.target.initialRotation.kind !== "none"; + case "brushFace": + case "brushEdge": + case "brushVertex": + return false; + } +} + function resolveEntityRotation(entity: EntityInstance): EntityTransformRotationState { switch (entity.kind) { case "playerStart":