import { layerNamesOf } from '../model/collisionLayers'; import { DEFAULT_GAME_LINK_ZOOM, DEFAULT_WHILE_PLAYING, type GameLinkZoom, type PlayFrom, type WhilePlaying, } from '../model/playSettings'; import type { Project } from '../model/Project'; import { clampSymbolScale } from '../model/symbolScale'; import { clampMasterVolume } from '../model/master'; import type { Command } from './Command'; export class RenameProjectCommand implements Command { readonly label = 'Rename project'; private previous = ''; constructor(private readonly name: string) {} execute(project: Project): void { this.previous = project.name; project.name = this.name; } undo(project: Project): void { project.name = this.previous; } } export type LayerList = 'collisionLayers' | 'renderLayers'; const LAYER_LIST_LABEL: Record = { collisionLayers: 'Collision layers', renderLayers: 'Render layers', }; /** * The named collision layers (#152) or render layers (#302) of the project. Objects name a layer by * number, so removing one shifts what every object below it points at – which is why the dialog only * ever hands over a whole list, and why the list is read through `layerNamesOf` here as well. */ export class SetLayerNamesCommand implements Command { readonly label: string; private previous: string[] = []; constructor( private readonly list: LayerList, private readonly names: readonly string[], ) { this.label = LAYER_LIST_LABEL[list]; } execute(project: Project): void { this.previous = project[this.list]; project[this.list] = layerNamesOf(this.names); } undo(project: Project): void { project[this.list] = this.previous; } } /** Size of the scene view's symbol icons, kept inside its range like a loaded project's. */ export class SetSymbolScaleCommand implements Command { readonly label = 'Symbol scale'; private previous = 1; constructor(private readonly scale: number) {} execute(project: Project): void { this.previous = project.symbolScale; project.symbolScale = clampSymbolScale(this.scale); } undo(project: Project): void { project.symbolScale = this.previous; } } /** Which scene Play starts (#226): saved with the project like the rest of its settings. */ export class SetPlayFromCommand implements Command { readonly label = 'Play starts'; private previous: PlayFrom = 'start'; constructor(private readonly playFrom: PlayFrom) {} execute(project: Project): void { this.previous = project.playFrom; project.playFrom = this.playFrom; } undo(project: Project): void { project.playFrom = this.previous; } } /** How closely the panels follow a running game (#265). */ export class SetWhilePlayingCommand implements Command { readonly label = 'While playing'; private previous: WhilePlaying = DEFAULT_WHILE_PLAYING; constructor(private readonly whilePlaying: WhilePlaying) {} execute(project: Project): void { this.previous = project.whilePlaying; project.whilePlaying = this.whilePlaying; } undo(project: Project): void { project.whilePlaying = this.previous; } } /** How the page of the released game sizes the camera frame (#279). */ export class SetGameLinkZoomCommand implements Command { readonly label = 'Game link zoom'; private previous: GameLinkZoom = DEFAULT_GAME_LINK_ZOOM; constructor(private readonly zoom: GameLinkZoom) {} execute(project: Project): void { this.previous = project.gameLinkZoom; project.gameLinkZoom = this.zoom; } undo(project: Project): void { project.gameLinkZoom = this.previous; } } /** The level of the master bus (#325), kept inside 0–1 like a loaded project's. */ export class SetMasterVolumeCommand implements Command { readonly label = 'Master volume'; private previous = 1; constructor(private readonly volume: number) {} execute(project: Project): void { this.previous = project.masterVolume; project.masterVolume = clampMasterVolume(this.volume); } undo(project: Project): void { project.masterVolume = this.previous; } } /** The sound FX of the master bus (#325), by id; '' for none. */ export class SetMasterFxCommand implements Command { readonly label = 'Master FX'; private previous = ''; constructor(private readonly fx: string) {} execute(project: Project): void { this.previous = project.masterFx; project.masterFx = this.fx; } undo(project: Project): void { project.masterFx = this.previous; } }