diff --git a/editor/src/editor/Cx.ts b/editor/src/editor/Cx.ts index b48a7ce..0e9bada 100644 --- a/editor/src/editor/Cx.ts +++ b/editor/src/editor/Cx.ts @@ -1,15 +1,12 @@ import { Board, ComponentRepo } from "./Board"; import { Renderer } from "./Renderer"; -import type { State } from "./State"; -import { Normal } from "./states/Normal"; -import { Panning } from "./states/Panning"; -import { Placing } from "./states/Placing"; +import * as states from "./states"; import { v2, V2 } from "./V2"; export class Cx { public offset = v2(0, 0); private renderNeeded = false; - private state = new Normal(this) as State; + private state = new states.Normal(this) as states.State; private updateActions: (() => void)[] = []; private selectionBox: SelectionBox | null = null; @@ -57,17 +54,17 @@ export class Cx { selectTool(tool: Tool) { switch (tool) { case "pan": - this.transitionTo(new Panning(this)); + this.transitionTo(new states.Panning(this)); break; case "input": case "output": case "and": case "or": case "not": - this.transitionTo(new Placing(this, tool)); + this.transitionTo(new states.Placing(this, tool)); break; default: - this.transitionTo(new Normal(this)); + this.transitionTo(new states.Normal(this)); } } @@ -82,7 +79,7 @@ export class Cx { ); } - transitionTo(newState: State) { + transitionTo(newState: states.State) { this.state.leaveState?.(); this.state = newState; this.state.enterState?.(); diff --git a/editor/src/editor/State.ts b/editor/src/editor/State.ts deleted file mode 100644 index 724bf59..0000000 --- a/editor/src/editor/State.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { Tool } from "./Cx"; -import type { V2 } from "./V2"; - -export interface State { - enterState?(): void; - leaveState?(): void; - onMouseDown?(pos: V2): void; - onMouseUp?(pos: V2): void; - onMouseMove?(deltaPos: V2, pos: V2): void; - onKeyDown?(key: string): void; - onKeyUp?(key: string): void; - selectedTool?(): Tool | null; -} diff --git a/editor/src/editor/states.ts b/editor/src/editor/states.ts new file mode 100644 index 0000000..121803f --- /dev/null +++ b/editor/src/editor/states.ts @@ -0,0 +1,151 @@ +import type { ComponentDef } from "./Board"; +import type { Cx, Tool } from "./Cx"; +import { v2, type V2 } from "./V2"; + +export interface State { + enterState?(): void; + leaveState?(): void; + onMouseDown?(pos: V2): void; + onMouseUp?(pos: V2): void; + onMouseMove?(deltaPos: V2, pos: V2): void; + onKeyDown?(key: string): void; + onKeyUp?(key: string): void; + selectedTool?(): Tool | null; +} + +export class Normal implements State { + constructor(private cx: Cx) {} + + onMouseDown(pos: V2): void { + if ( + this.cx.board.handleMouseClick( + pos.sub(this.cx.offset), + (comp, i) => {}, + (comp, i) => {}, + (comp) => {}, + ) === "handled" + ) { + return; + } else { + this.cx.addSelectionRect(pos); + this.cx.transitionTo(new SelectingBox(this.cx)); + } + } + + onMouseMove(_deltaPos: V2, pos: V2): void { + this.cx.board.updateMouseHover(pos.sub(this.cx.offset)); + this.cx.setRenderNeeded(); + } + + onKeyDown(key: string): void { + if (key === "Shift") { + this.cx.transitionTo(new Panning(this.cx)); + return; + } + } + + selectedTool(): Tool | null { + return "select"; + } +} + +export class Panning implements State { + private dragging = false; + + constructor(private cx: Cx) {} + + onMouseDown(_pos: V2): void { + this.dragging = true; + } + + onMouseUp(_pos: V2): void { + this.dragging = false; + } + + onMouseMove(deltaPos: V2): void { + if (this.dragging) { + this.cx.moveOffset(deltaPos); + } + } + + onKeyDown(key: string): void { + if (key === "Escape") { + this.cx.transitionTo(new Normal(this.cx)); + return; + } + } + + onKeyUp(key: string): void { + if (key === "Shift") { + this.cx.transitionTo(new Normal(this.cx)); + return; + } + } + + selectedTool(): Tool | null { + return "pan"; + } +} + +export class Placing implements State { + private compDef: ComponentDef; + + constructor( + private cx: Cx, + private tool: Tool, + ) { + this.compDef = this.cx.componentRepo.get(this.tool); + } + + enterState(): void { + this.cx.addComponentPlacer(v2(0, 0), this.compDef.size); + } + + leaveState(): void { + this.cx.removeComponentPlacer(); + } + + onMouseDown(pos: V2): void { + const boardPos = this.cx.canvasPosToBoard(pos); + if (this.cx.board.canPlaceComponent(this.compDef, boardPos)) { + this.cx.board.placeComponent(this.compDef, boardPos); + this.cx.transitionTo(new Normal(this.cx)); + } + } + + onMouseMove(_deltaPos: V2, pos: V2): void { + this.cx.setComponentPlacerPos(pos); + } + + onKeyDown(key: string): void { + if (key === "Escape") { + this.cx.transitionTo(new Normal(this.cx)); + return; + } + } + + selectedTool(): Tool | null { + return this.tool; + } +} + +export class Selecting implements State { + constructor(private cx: Cx) {} +} + +export class SelectingBox implements State { + constructor(private cx: Cx) {} + + onMouseUp(_pos: V2): void { + this.cx.removeSelectionRect(); + this.cx.transitionTo(new Normal(this.cx)); + } + + onMouseMove(deltaPos: V2): void { + this.cx.moveSelectionRect(deltaPos); + } + + selectedTool(): Tool | null { + return "select"; + } +} diff --git a/editor/src/editor/states/Normal.ts b/editor/src/editor/states/Normal.ts deleted file mode 100644 index cac5888..0000000 --- a/editor/src/editor/states/Normal.ts +++ /dev/null @@ -1,41 +0,0 @@ -import type { Cx, Tool } from "../Cx"; -import type { V2 } from "../V2"; -import type { State } from "../State"; -import { Panning } from "./Panning"; -import { SelectingBox } from "./SelectingBox"; - -export class Normal implements State { - constructor(private cx: Cx) {} - - onMouseDown(pos: V2): void { - if ( - this.cx.board.handleMouseClick( - pos.sub(this.cx.offset), - (comp, i) => {}, - (comp, i) => {}, - (comp) => {}, - ) === "handled" - ) { - return; - } else { - this.cx.addSelectionRect(pos); - this.cx.transitionTo(new SelectingBox(this.cx)); - } - } - - onMouseMove(_deltaPos: V2, pos: V2): void { - this.cx.board.updateMouseHover(pos.sub(this.cx.offset)); - this.cx.setRenderNeeded(); - } - - onKeyDown(key: string): void { - if (key === "Shift") { - this.cx.transitionTo(new Panning(this.cx)); - return; - } - } - - selectedTool(): Tool | null { - return "select"; - } -} diff --git a/editor/src/editor/states/Panning.ts b/editor/src/editor/states/Panning.ts deleted file mode 100644 index 8f03163..0000000 --- a/editor/src/editor/states/Panning.ts +++ /dev/null @@ -1,42 +0,0 @@ -import type { Cx, Tool } from "../Cx"; -import type { V2_ } from "../V2"; -import type { State } from "../State"; -import { Normal } from "./Normal"; - -export class Panning implements State { - private dragging = false; - - constructor(private cx: Cx) {} - - onMouseDown(_pos: V2_): void { - this.dragging = true; - } - - onMouseUp(_pos: V2_): void { - this.dragging = false; - } - - onMouseMove(deltaPos: V2_): void { - if (this.dragging) { - this.cx.moveOffset(deltaPos); - } - } - - onKeyDown(key: string): void { - if (key === "Escape") { - this.cx.transitionTo(new Normal(this.cx)); - return; - } - } - - onKeyUp(key: string): void { - if (key === "Shift") { - this.cx.transitionTo(new Normal(this.cx)); - return; - } - } - - selectedTool(): Tool | null { - return "pan"; - } -} diff --git a/editor/src/editor/states/Placing.ts b/editor/src/editor/states/Placing.ts deleted file mode 100644 index b43a441..0000000 --- a/editor/src/editor/states/Placing.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { type Cx, type Tool } from "../Cx"; -import { V2, v2 } from "../V2"; -import type { State } from "../State"; -import { Normal } from "./Normal"; -import type { ComponentDef } from "../Board"; - -export class Placing implements State { - private compDef: ComponentDef; - - constructor( - private cx: Cx, - private tool: Tool, - ) { - this.compDef = this.cx.componentRepo.get(this.tool); - } - - enterState(): void { - this.cx.addComponentPlacer(v2(0, 0), this.compDef.size); - } - - leaveState(): void { - this.cx.removeComponentPlacer(); - } - - onMouseDown(pos: V2): void { - const boardPos = this.cx.canvasPosToBoard(pos); - if (this.cx.board.canPlaceComponent(this.compDef, boardPos)) { - this.cx.board.placeComponent(this.compDef, boardPos); - this.cx.transitionTo(new Normal(this.cx)); - } - } - - onMouseMove(_deltaPos: V2, pos: V2): void { - this.cx.setComponentPlacerPos(pos); - } - - onKeyDown(key: string): void { - if (key === "Escape") { - this.cx.transitionTo(new Normal(this.cx)); - return; - } - } - - selectedTool(): Tool | null { - return this.tool; - } -} diff --git a/editor/src/editor/states/Selecting.ts b/editor/src/editor/states/Selecting.ts deleted file mode 100644 index 7940ee0..0000000 --- a/editor/src/editor/states/Selecting.ts +++ /dev/null @@ -1,6 +0,0 @@ -import type { Cx } from "../Cx"; -import type { State } from "../State"; - -export class Selecting implements State { - constructor(private cx: Cx) {} -} diff --git a/editor/src/editor/states/SelectingBox.ts b/editor/src/editor/states/SelectingBox.ts deleted file mode 100644 index 5375539..0000000 --- a/editor/src/editor/states/SelectingBox.ts +++ /dev/null @@ -1,21 +0,0 @@ -import type { Cx, Tool } from "../Cx"; -import type { V2 } from "../V2"; -import type { State } from "../State"; -import { Normal } from "./Normal"; - -export class SelectingBox implements State { - constructor(private cx: Cx) {} - - onMouseUp(_pos: V2): void { - this.cx.removeSelectionRect(); - this.cx.transitionTo(new Normal(this.cx)); - } - - onMouseMove(deltaPos: V2): void { - this.cx.moveSelectionRect(deltaPos); - } - - selectedTool(): Tool | null { - return "select"; - } -}