diff --git a/src/app/editor-store.ts b/src/app/editor-store.ts index e928533f..f4d7d1d5 100644 --- a/src/app/editor-store.ts +++ b/src/app/editor-store.ts @@ -2,6 +2,7 @@ import { CommandHistory } from "../commands/command-history"; import type { CommandContext, EditorCommand } from "../commands/command"; import { areEditorSelectionsEqual, + getSelectionDefaultActiveId, normalizeSelectionForWhiteboxSelectionMode, type EditorSelection } from "../core/selection"; @@ -71,6 +72,7 @@ export interface EditorStoreState { activeSceneId: string; document: SceneDocument; selection: EditorSelection; + activeSelectionId: string | null; whiteboxSelectionMode: WhiteboxSelectionMode; whiteboxSnapEnabled: boolean; whiteboxSnapStep: number; @@ -211,6 +213,7 @@ export class EditorStore { private document: SceneDocument; private commandTargetSceneId: string | null = null; private selection: EditorSelection = { kind: "none" }; + private activeSelectionId: string | null = null; private whiteboxSelectionMode: WhiteboxSelectionMode = "object"; private whiteboxSnapEnabled = true; private whiteboxSnapStep = 1; @@ -251,6 +254,7 @@ export class EditorStore { getSelection: () => this.selection, setSelection: (selection) => { this.selection = selection; + this.activeSelectionId = getSelectionDefaultActiveId(selection); }, getToolMode: () => this.toolMode, setToolMode: (toolMode) => { @@ -624,6 +628,7 @@ export class EditorStore { } this.selection = selection; + this.activeSelectionId = getSelectionDefaultActiveId(selection); this.emit(); } @@ -644,6 +649,7 @@ export class EditorStore { this.selection, mode ); + this.activeSelectionId = getSelectionDefaultActiveId(this.selection); this.updateActiveSceneEditorPreferences((preferences) => ({ ...preferences, whiteboxSelectionMode: mode @@ -726,6 +732,7 @@ export class EditorStore { this.syncActiveSceneDocument(); this.commandTargetSceneId = null; this.selection = { kind: "none" }; + this.activeSelectionId = null; this.toolMode = "select"; this.previousEditingToolMode = "select"; this.viewportTransientState = createDefaultViewportTransientState(); @@ -821,6 +828,7 @@ export class EditorStore { activeSceneId: this.projectDocument.activeSceneId, document: this.document, selection: this.selection, + activeSelectionId: this.activeSelectionId, whiteboxSelectionMode: this.whiteboxSelectionMode, whiteboxSnapEnabled: this.whiteboxSnapEnabled, whiteboxSnapStep: this.whiteboxSnapStep, diff --git a/src/core/transform-session.ts b/src/core/transform-session.ts index 51d65e62..49a0603a 100644 --- a/src/core/transform-session.ts +++ b/src/core/transform-session.ts @@ -1,5 +1,8 @@ import { createOpaqueId } from "./ids"; -import type { EditorSelection } from "./selection"; +import { + resolveSelectionActiveId, + type EditorSelection +} from "./selection"; import type { WhiteboxSelectionMode } from "./whitebox-selection-mode"; import type { Vec3 } from "./vector"; import { @@ -149,14 +152,38 @@ export interface EntityTransformTarget { initialRotation: EntityTransformRotationState; } +export interface BrushesTransformTarget { + kind: "brushes"; + activeBrushId: string; + initialPivot: Vec3; + items: BrushTransformTarget[]; +} + +export interface ModelInstancesTransformTarget { + kind: "modelInstances"; + activeModelInstanceId: string; + initialPivot: Vec3; + items: ModelInstanceTransformTarget[]; +} + +export interface EntitiesTransformTarget { + kind: "entities"; + activeEntityId: string; + initialPivot: Vec3; + items: EntityTransformTarget[]; +} + export type TransformTarget = | BrushTransformTarget + | BrushesTransformTarget | BrushFaceTransformTarget | BrushEdgeTransformTarget | BrushVertexTransformTarget | ModelInstanceTransformTarget + | ModelInstancesTransformTarget | PathPointTransformTarget - | EntityTransformTarget; + | EntityTransformTarget + | EntitiesTransformTarget; export interface BrushTransformPreview { kind: "brush"; @@ -202,11 +229,53 @@ export interface EntityTransformPreview { rotation: EntityTransformRotationState; } +export interface BrushTransformPreviewItem { + brushId: string; + center: Vec3; + rotationDegrees: Vec3; + size: Vec3; + geometry: BrushGeometry; +} + +export interface BrushesTransformPreview { + kind: "brushes"; + pivot: Vec3; + items: BrushTransformPreviewItem[]; +} + +export interface ModelInstanceTransformPreviewItem { + modelInstanceId: string; + position: Vec3; + rotationDegrees: Vec3; + scale: Vec3; +} + +export interface ModelInstancesTransformPreview { + kind: "modelInstances"; + pivot: Vec3; + items: ModelInstanceTransformPreviewItem[]; +} + +export interface EntityTransformPreviewItem { + entityId: string; + position: Vec3; + rotation: EntityTransformRotationState; +} + +export interface EntitiesTransformPreview { + kind: "entities"; + pivot: Vec3; + items: EntityTransformPreviewItem[]; +} + export type TransformPreview = | BrushTransformPreview + | BrushesTransformPreview | ModelInstanceTransformPreview + | ModelInstancesTransformPreview | PathPointTransformPreview - | EntityTransformPreview; + | EntityTransformPreview + | EntitiesTransformPreview; export interface ActiveTransformSession { kind: "active";