refactor states
This commit is contained in:
parent
bdf4a01e7f
commit
2a172f687c
@ -1,15 +1,12 @@
|
|||||||
import { Board, ComponentRepo } from "./Board";
|
import { Board, ComponentRepo } from "./Board";
|
||||||
import { Renderer } from "./Renderer";
|
import { Renderer } from "./Renderer";
|
||||||
import type { State } from "./State";
|
import * as states from "./states";
|
||||||
import { Normal } from "./states/Normal";
|
|
||||||
import { Panning } from "./states/Panning";
|
|
||||||
import { Placing } from "./states/Placing";
|
|
||||||
import { v2, V2 } from "./V2";
|
import { v2, V2 } from "./V2";
|
||||||
|
|
||||||
export class Cx {
|
export class Cx {
|
||||||
public offset = v2(0, 0);
|
public offset = v2(0, 0);
|
||||||
private renderNeeded = false;
|
private renderNeeded = false;
|
||||||
private state = new Normal(this) as State;
|
private state = new states.Normal(this) as states.State;
|
||||||
private updateActions: (() => void)[] = [];
|
private updateActions: (() => void)[] = [];
|
||||||
|
|
||||||
private selectionBox: SelectionBox | null = null;
|
private selectionBox: SelectionBox | null = null;
|
||||||
@ -57,17 +54,17 @@ export class Cx {
|
|||||||
selectTool(tool: Tool) {
|
selectTool(tool: Tool) {
|
||||||
switch (tool) {
|
switch (tool) {
|
||||||
case "pan":
|
case "pan":
|
||||||
this.transitionTo(new Panning(this));
|
this.transitionTo(new states.Panning(this));
|
||||||
break;
|
break;
|
||||||
case "input":
|
case "input":
|
||||||
case "output":
|
case "output":
|
||||||
case "and":
|
case "and":
|
||||||
case "or":
|
case "or":
|
||||||
case "not":
|
case "not":
|
||||||
this.transitionTo(new Placing(this, tool));
|
this.transitionTo(new states.Placing(this, tool));
|
||||||
break;
|
break;
|
||||||
default:
|
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.leaveState?.();
|
||||||
this.state = newState;
|
this.state = newState;
|
||||||
this.state.enterState?.();
|
this.state.enterState?.();
|
||||||
|
|||||||
@ -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;
|
|
||||||
}
|
|
||||||
151
editor/src/editor/states.ts
Normal file
151
editor/src/editor/states.ts
Normal file
@ -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";
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
import type { Cx } from "../Cx";
|
|
||||||
import type { State } from "../State";
|
|
||||||
|
|
||||||
export class Selecting implements State {
|
|
||||||
constructor(private cx: Cx) {}
|
|
||||||
}
|
|
||||||
@ -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";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user