Files
OpenClaw-bot-review/lib/pixel-office/editor/editorState.ts
T
xmanrui eebe431560 feat: implement Pixel Office Phase 2 - layout editor, persistence, sound, sub-agent visualization
- Add layout editor with floor/wall paint, erase, furniture place/move/rotate/delete tools
- Add editor state management (undo/redo, selection, drag, ghost preview)
- Add EditorToolbar and EditActionBar UI components
- Add layout persistence API (GET/POST to ~/.openclaw/pixel-office/layout.json)
- Add notification sound system (Web Audio API ascending chime on agent completion)
- Add sub-agent visualization via session JSONL parsing
- Fix agent activity API to read from agents.list config and correct session paths
- Add agent name labels above character sprites in canvas renderer
- Add i18n translations for editor features (zh/en)
2026-02-25 01:39:44 +08:00

110 lines
2.5 KiB
TypeScript

import { EditTool, TileType } from '../types'
import type { TileType as TileTypeVal, OfficeLayout, FloorColor } from '../types'
import { UNDO_STACK_MAX_SIZE, DEFAULT_FLOOR_COLOR, DEFAULT_WALL_COLOR } from '../constants'
export class EditorState {
isEditMode = false
activeTool: EditTool = EditTool.SELECT
selectedTileType: TileTypeVal = TileType.FLOOR_1
selectedFurnitureType: string = 'desk'
floorColor: FloorColor = { ...DEFAULT_FLOOR_COLOR }
wallColor: FloorColor = { ...DEFAULT_WALL_COLOR }
// Tracks toggle direction during wall drag
wallDragAdding: boolean | null = null
// Picked furniture color (copied by pick tool)
pickedFurnitureColor: FloorColor | null = null
// Ghost preview position
ghostCol = -1
ghostRow = -1
ghostValid = false
// Selection
selectedFurnitureUid: string | null = null
// Mouse drag state
isDragging = false
// Undo / Redo stacks
undoStack: OfficeLayout[] = []
redoStack: OfficeLayout[] = []
isDirty = false
// Drag-to-move state
dragUid: string | null = null
dragStartCol = 0
dragStartRow = 0
dragOffsetCol = 0
dragOffsetRow = 0
isDragMoving = false
pushUndo(layout: OfficeLayout): void {
this.undoStack.push(layout)
if (this.undoStack.length > UNDO_STACK_MAX_SIZE) {
this.undoStack.shift()
}
}
popUndo(): OfficeLayout | null {
return this.undoStack.pop() || null
}
pushRedo(layout: OfficeLayout): void {
this.redoStack.push(layout)
if (this.redoStack.length > UNDO_STACK_MAX_SIZE) {
this.redoStack.shift()
}
}
popRedo(): OfficeLayout | null {
return this.redoStack.pop() || null
}
clearRedo(): void {
this.redoStack = []
}
clearSelection(): void {
this.selectedFurnitureUid = null
}
clearGhost(): void {
this.ghostCol = -1
this.ghostRow = -1
this.ghostValid = false
}
startDrag(uid: string, startCol: number, startRow: number, offsetCol: number, offsetRow: number): void {
this.dragUid = uid
this.dragStartCol = startCol
this.dragStartRow = startRow
this.dragOffsetCol = offsetCol
this.dragOffsetRow = offsetRow
this.isDragMoving = false
}
clearDrag(): void {
this.dragUid = null
this.isDragMoving = false
}
reset(): void {
this.activeTool = EditTool.SELECT
this.selectedFurnitureUid = null
this.ghostCol = -1
this.ghostRow = -1
this.ghostValid = false
this.isDragging = false
this.wallDragAdding = null
this.undoStack = []
this.redoStack = []
this.isDirty = false
this.dragUid = null
this.isDragMoving = false
}
}