diff --git a/src/commands/create-foliage-layer-command.ts b/src/commands/create-foliage-layer-command.ts new file mode 100644 index 00000000..dfca2ec4 --- /dev/null +++ b/src/commands/create-foliage-layer-command.ts @@ -0,0 +1,48 @@ +import { createOpaqueId } from "../core/ids"; +import { cloneFoliageLayer, type FoliageLayer } from "../foliage/foliage"; + +import type { EditorCommand } from "./command"; + +interface CreateFoliageLayerCommandOptions { + layer: FoliageLayer; + label?: string; +} + +export function createCreateFoliageLayerCommand( + options: CreateFoliageLayerCommandOptions +): EditorCommand { + const nextLayer = cloneFoliageLayer(options.layer); + + return { + id: createOpaqueId("command"), + label: options.label ?? "Create foliage layer", + execute(context) { + const currentDocument = context.getDocument(); + + if (currentDocument.foliageLayers[nextLayer.id] !== undefined) { + throw new Error(`Foliage layer ${nextLayer.id} already exists.`); + } + + context.setDocument({ + ...currentDocument, + foliageLayers: { + ...currentDocument.foliageLayers, + [nextLayer.id]: cloneFoliageLayer(nextLayer) + } + }); + }, + undo(context) { + const currentDocument = context.getDocument(); + const nextFoliageLayers = { + ...currentDocument.foliageLayers + }; + + delete nextFoliageLayers[nextLayer.id]; + + context.setDocument({ + ...currentDocument, + foliageLayers: nextFoliageLayers + }); + } + }; +} diff --git a/src/commands/delete-foliage-layer-command.ts b/src/commands/delete-foliage-layer-command.ts new file mode 100644 index 00000000..e8be3b86 --- /dev/null +++ b/src/commands/delete-foliage-layer-command.ts @@ -0,0 +1,53 @@ +import { createOpaqueId } from "../core/ids"; +import { cloneFoliageLayer, type FoliageLayer } from "../foliage/foliage"; + +import type { EditorCommand } from "./command"; + +export function createDeleteFoliageLayerCommand( + foliageLayerId: string +): EditorCommand { + let deletedLayer: FoliageLayer | null = null; + + return { + id: createOpaqueId("command"), + label: "Delete foliage layer", + execute(context) { + const currentDocument = context.getDocument(); + const currentLayer = currentDocument.foliageLayers[foliageLayerId]; + + if (currentLayer === undefined) { + throw new Error(`Foliage layer ${foliageLayerId} does not exist.`); + } + + if (deletedLayer === null) { + deletedLayer = cloneFoliageLayer(currentLayer); + } + + const nextFoliageLayers = { + ...currentDocument.foliageLayers + }; + + delete nextFoliageLayers[foliageLayerId]; + + context.setDocument({ + ...currentDocument, + foliageLayers: nextFoliageLayers + }); + }, + undo(context) { + if (deletedLayer === null) { + return; + } + + const currentDocument = context.getDocument(); + + context.setDocument({ + ...currentDocument, + foliageLayers: { + ...currentDocument.foliageLayers, + [deletedLayer.id]: cloneFoliageLayer(deletedLayer) + } + }); + } + }; +} diff --git a/src/commands/update-foliage-layer-command.ts b/src/commands/update-foliage-layer-command.ts new file mode 100644 index 00000000..b4d5882e --- /dev/null +++ b/src/commands/update-foliage-layer-command.ts @@ -0,0 +1,56 @@ +import { createOpaqueId } from "../core/ids"; +import { cloneFoliageLayer, type FoliageLayer } from "../foliage/foliage"; + +import type { EditorCommand } from "./command"; + +interface UpdateFoliageLayerCommandOptions { + layer: FoliageLayer; + label?: string; +} + +export function createUpdateFoliageLayerCommand( + options: UpdateFoliageLayerCommandOptions +): EditorCommand { + const nextLayer = cloneFoliageLayer(options.layer); + let previousLayer: FoliageLayer | null = null; + + return { + id: createOpaqueId("command"), + label: options.label ?? "Update foliage layer", + execute(context) { + const currentDocument = context.getDocument(); + const currentLayer = currentDocument.foliageLayers[nextLayer.id]; + + if (currentLayer === undefined) { + throw new Error(`Foliage layer ${nextLayer.id} does not exist.`); + } + + if (previousLayer === null) { + previousLayer = cloneFoliageLayer(currentLayer); + } + + context.setDocument({ + ...currentDocument, + foliageLayers: { + ...currentDocument.foliageLayers, + [nextLayer.id]: cloneFoliageLayer(nextLayer) + } + }); + }, + undo(context) { + if (previousLayer === null) { + return; + } + + const currentDocument = context.getDocument(); + + context.setDocument({ + ...currentDocument, + foliageLayers: { + ...currentDocument.foliageLayers, + [previousLayer.id]: cloneFoliageLayer(previousLayer) + } + }); + } + }; +}