1
0
Fork 0
Code Issues Pull requests Projects Releases Packages Wiki Activity Actions Pages

Refactor launcher and studio modules

This commit is contained in:
Andraxion 2026-06-27 04:36:26 -04:00
parent a20d298be2
commit ec3e0f5138
34 changed files with 10300 additions and 8600 deletions

View file

@ -0,0 +1,475 @@
export const WORLDSHAPER_STUDIO_MARKUP_SHELL = `
<body>
<div class="shell">
<div class="menu-bar" id="menuBar">
<button class="menu-btn" id="undoBtn" type="button">Undo</button>
<button class="menu-btn" id="redoBtn" type="button">Redo</button>
<button class="menu-btn" id="saveBtn" type="button">Save</button>
<button class="menu-btn" id="testHeightBtn" type="button">Test Height</button>
<div class="menu-bar-center">
<label class="menu-layer-label" for="menuLayerSelect">Change Layer:</label>
<select class="menu-layer-select" id="menuLayerSelect"></select>
</div>
<div class="menu-bar-right">
<div class="theme-preset-bar" role="group" aria-label="Editor theme presets">
__THEME_PRESET_BUTTONS__
</div>
<span id="saveStatus" class="save-status" title="Ready" aria-label="Ready">Ready</span>
</div>
</div>
<div class="body" id="editorBody">
`;
export const WORLDSHAPER_STUDIO_MARKUP_SIDEBAR = `
<aside class="sidebar" id="sidebar">
<div class="sidebar-tabs" id="sidebarTabs">
<div class="sidebar-tab-row">
<button class="sidebar-tab-btn" id="informationTabBtn" type="button">Settings</button>
<button class="sidebar-tab-btn" id="historyTabBtn" type="button">History</button>
<button class="sidebar-tab-btn" id="newsTabBtn" type="button">News</button>
</div>
<div class="sidebar-tab-row">
<button class="sidebar-tab-btn" id="instancesTabBtn" type="button">Entities</button>
<button class="sidebar-tab-btn" id="tilesTabBtn" type="button">Graphics</button>
<button class="sidebar-tab-btn active" id="layersTabBtn" type="button">Layers</button>
</div>
<div class="sidebar-tab-row">
<button class="sidebar-tab-btn" id="triggersTabBtn" type="button">Triggers</button>
<button class="sidebar-tab-btn" id="pathsTabBtn" type="button">Paths</button>
<button class="sidebar-tab-btn" id="transitionsTabBtn" type="button">Transitions</button>
</div>
<div class="sidebar-tab-row">
<span></span>
</div>
</div>
<div class="sidebar-panels-host" id="sidebarPanelsHost">
<div class="sidebar-panel hidden" id="informationPanel">
<h3>Settings</h3>
<div class="information-panel-layout">
<div class="selector-section">
<div class="selector-section-header">
<button class="selector-section-toggle" id="toggleInformationSettingsSectionBtn" type="button" aria-expanded="true">
<span class="selector-section-chevron">&#9662;</span>
<span>World Info</span>
</button>
</div>
<div class="selector-section-body" id="informationSettingsSectionBody">
<div class="map-manager">
<div class="field-row">
<label for="mapIdLocked">World Id</label>
<input id="mapIdLocked" class="info-readonly" type="text" readonly />
</div>
<div class="field-row">
<label for="mapNameInput">World Name</label>
<input id="mapNameInput" type="text" />
</div>
<div class="field-row">
<label for="mapWidthInput">Loaded Width</label>
<div class="info-cell-value info-dim-value" id="mapWidthValue">
<input id="mapWidthInput" class="info-dim-input info-readonly" type="number" min="1" max="512" readonly />
<div class="info-dim-controls" id="mapWidthControls">
<button class="icon-action-btn" id="confirmWidthBtn" type="button" title="Apply width change">âÃâœÃ¢â¬Å</button>
<button class="icon-action-btn danger" id="cancelWidthBtn" type="button" title="Discard width change">̢̮â¬â</button>
</div>
</div>
</div>
<div class="field-row">
<label for="mapHeightInput">Loaded Height</label>
<div class="info-cell-value info-dim-value" id="mapHeightValue">
<input id="mapHeightInput" class="info-dim-input info-readonly" type="number" min="1" max="512" readonly />
<div class="info-dim-controls" id="mapHeightControls">
<button class="icon-action-btn" id="confirmHeightBtn" type="button" title="Apply height change">âÃâœÃ¢â¬Å</button>
<button class="icon-action-btn danger" id="cancelHeightBtn" type="button" title="Discard height change">̢̮â¬â</button>
</div>
</div>
</div>
<div class="field-row">
<label for="mapBackgroundColorInput">Background Color</label>
<input id="mapBackgroundColorInput" type="color" />
</div>
</div>
</div>
<div class="selector-section">
<div class="selector-section-header">
<button class="selector-section-toggle" id="toggleInformationConfigurationSectionBtn" type="button" aria-expanded="true">
<span class="selector-section-chevron">&#9662;</span>
<span>Configuration</span>
</button>
</div>
<div class="selector-section-body" id="informationConfigurationSectionBody">
<div class="map-manager">
<div class="field-row">
<label for="engineOverridesBtn">Engine Overrides</label>
<div>
<button id="engineOverridesBtn" class="mini-btn engine-overrides-launch-btn" type="button">Open Override Manager</button>
<div class="engine-overrides-summary" id="engineOverridesSummary">No engine overrides active.</div>
</div>
</div>
<div class="field-row">
<label for="backgroundModeBtn">Background Brush</label>
<button id="backgroundModeBtn" class="background-mode-btn" type="button">
<span class="background-mode-preview" id="backgroundModePreview"></span>
<span class="background-mode-copy">
<span class="background-mode-title" id="backgroundModeTitle">Inherit</span>
<span class="background-mode-meta" id="backgroundModeMeta">Click to cycle tile, hole, inherit.</span>
</span>
</button>
</div>
</div>
<div class="information-utility-actions">
<button class="mini-btn" id="restoreToolWindowsBtn" type="button">Restore all windows</button>
<button class="mini-btn" id="resetWorkspaceLayoutBtn" type="button">Reset workspace layout</button>
</div>
<div class="experimental-import-panel">
<button id="experimentalImportToggleBtn" class="experimental-import-toggle" type="button" aria-expanded="false">
<span class="experimental-import-check" id="experimentalImportCheck">[ ]</span>
<span class="experimental-import-copy">
<span class="experimental-import-title">Experimental Imports</span>
<span class="experimental-import-meta">Import compatible sprite or tile JSON from other editor builds.</span>
</span>
<span class="experimental-import-chevron">&#9662;</span>
</button>
<div class="experimental-import-body hidden" id="experimentalImportBody">
<div class="experimental-import-warning">Warning: supports a single entry or a full <code>sprites.json</code> / <code>tiles.json</code> gallery. Matching art is deduped and only new images are kept.</div>
<div class="experimental-import-actions">
<button class="mini-btn" id="importSpritesBtn" type="button">Import Sprites</button>
<button class="mini-btn" id="importTilesBtn" type="button">Import Tiles</button>
<button class="mini-btn experimental-import-icon-btn" id="importJsonBtn" type="button" title="Paste JSON import" aria-label="Paste JSON import">&#128221;</button>
</div>
<input id="importSpritesInput" class="hidden" type="file" accept=".json,application/json" />
<input id="importTilesInput" class="hidden" type="file" accept=".json,application/json" />
</div>
</div>
</div>
</div>
<div class="experimental-import-modal hidden" id="importJsonModal">
<div class="experimental-import-modal-card" role="dialog" aria-modal="true" aria-labelledby="importJsonModalTitle">
<div class="experimental-import-modal-head">
<h4 class="experimental-import-modal-title" id="importJsonModalTitle">Paste Import JSON</h4>
<select id="importJsonTypeSelect">
<option value="sprites">Sprites</option>
<option value="tiles">Tiles</option>
</select>
</div>
<div class="experimental-import-modal-copy">Paste a single entry or a full compatible gallery payload, then confirm to import only new art.</div>
<div class="experimental-import-modal-body">
<textarea id="importJsonTextarea" rows="12" spellcheck="false" placeholder="{ &quot;tiles&quot;: [ ... ] }"></textarea>
</div>
<div class="experimental-import-modal-actions">
<button class="mini-btn" id="importJsonConfirmBtn" type="button" title="Import JSON">&#10003;</button>
<button class="mini-btn danger" id="importJsonCancelBtn" type="button" title="Cancel import">&#10005;</button>
</div>
</div>
</div>
<div class="information-bottom-stack">
<div class="selector-section">
<div class="selector-section-header">
<button class="selector-section-toggle" id="toggleInformationHotkeysSectionBtn" type="button" aria-expanded="false">
<span class="selector-section-chevron">&#9662;</span>
<span>Hotkeys</span>
</button>
</div>
<div class="selector-section-body hidden" id="informationHotkeysSectionBody">
<div class="info-help-panel" aria-label="Worldshaper Studio keyboard help">
<div class="info-help-title">Editor Controls</div>
<div class="info-help-list">
<div class="shortcut-row">
<div class="shortcut-keys">
<span class="shortcut-keycap">Ctrl</span>
<span class="shortcut-plus">+</span>
<span class="shortcut-mouse-shell">
<span class="shortcut-mouse-dot"></span>
<span class="shortcut-mouse-label">Wheel</span>
</span>
</div>
<div class="shortcut-action">Zoom canvas</div>
</div>
<div class="shortcut-row">
<div class="shortcut-keys">
<span class="shortcut-keycap">MMB</span>
<span class="shortcut-plus">+</span>
<span class="shortcut-mouse-shell">
<span class="shortcut-mouse-dot"></span>
<span class="shortcut-mouse-label">Drag</span>
</span>
</div>
<div class="shortcut-action">Pan the room view</div>
</div>
<div class="shortcut-row">
<div class="shortcut-keys">
<span class="shortcut-keycap">L Shift</span>
<span class="shortcut-plus">+</span>
<span class="shortcut-mouse-shell">
<span class="shortcut-mouse-dot"></span>
<span class="shortcut-mouse-label">Drag</span>
</span>
</div>
<div class="shortcut-action">Straight line draw</div>
</div>
<div class="shortcut-row">
<div class="shortcut-keys">
<span class="shortcut-keycap">Alt</span>
<span class="shortcut-plus">+</span>
<span class="shortcut-mouse-shell">
<span class="shortcut-mouse-dot"></span>
<span class="shortcut-mouse-label">Drag</span>
</span>
</div>
<div class="shortcut-action">Erase on active layer</div>
</div>
<div class="shortcut-row">
<div class="shortcut-keys">
<span class="shortcut-keycap">L Ctrl</span>
<span class="shortcut-plus">+</span>
<span class="shortcut-mouse-shell">
<span class="shortcut-mouse-dot"></span>
<span class="shortcut-mouse-label">Drag</span>
</span>
</div>
<div class="shortcut-action"><span class="shortcut-shape-icon square" aria-hidden="true"></span><span>Rectangle outline</span></div>
</div>
<div class="shortcut-row">
<div class="shortcut-keys">
<span class="shortcut-keycap">R Ctrl</span>
<span class="shortcut-plus">+</span>
<span class="shortcut-mouse-shell">
<span class="shortcut-mouse-dot"></span>
<span class="shortcut-mouse-label">Drag</span>
</span>
</div>
<div class="shortcut-action"><span class="shortcut-shape-icon circle" aria-hidden="true"></span><span>Circle outline</span></div>
</div>
<div class="shortcut-row">
<div class="shortcut-keys">
<span class="shortcut-keycap">R Shift</span>
</div>
<div class="shortcut-action">Hold to hide the grid</div>
</div>
<div class="shortcut-row">
<div class="shortcut-keys">
<span class="shortcut-keycap">M</span>
</div>
<div class="shortcut-action">Open world overview</div>
</div>
<div class="shortcut-row">
<div class="shortcut-keys">
<span class="shortcut-keycap">O</span>
</div>
<div class="shortcut-action">Toggle chunk bounds</div>
</div>
<div class="shortcut-row">
<div class="shortcut-keys">
<span class="shortcut-keycap">Ctrl</span>
<span class="shortcut-plus">+</span>
<span class="shortcut-keycap">Z</span>
</div>
<div class="shortcut-action">Undo</div>
</div>
<div class="shortcut-row">
<div class="shortcut-keys">
<span class="shortcut-keycap">Ctrl</span>
<span class="shortcut-plus">+</span>
<span class="shortcut-keycap">Y</span>
</div>
<div class="shortcut-action">Redo</div>
</div>
<div class="shortcut-row">
<div class="shortcut-keys">
<span class="shortcut-keycap">Escape</span>
</div>
<div class="shortcut-action">Clear canvas selection / collapse cells</div>
</div>
<div class="shortcut-row">
<div class="shortcut-keys">
<span class="shortcut-keycap">Delete</span>
</div>
<div class="shortcut-action">Delete focused tile or entity</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="sidebar-panel" id="layersPanel">
<h3>Layers</h3>
<div class="selector-section">
<div class="selector-section-header">
<button class="selector-section-toggle" id="toggleDrawLayerSectionBtn" type="button" aria-expanded="true">
<span class="selector-section-chevron">&#9662;</span>
<span>Draw Layers</span>
</button>
<button class="mini-btn" id="addLayerBtn" type="button">Add Layer</button>
</div>
<div class="selector-section-body" id="drawLayerSectionBody">
<div class="layer-list" id="layerList"></div>
</div>
</div>
<div class="selector-section">
<div class="selector-section-header">
<button class="selector-section-toggle" id="toggleHeightLayerSectionBtn" type="button" aria-expanded="true">
<span class="selector-section-chevron">&#9662;</span>
<span>Height Layers</span>
</button>
<button class="mini-btn" id="addHeightLayerBtn" type="button">Add Height Layer</button>
</div>
<div class="selector-section-body" id="heightLayerSectionBody">
<div class="layer-list" id="heightLayerList"></div>
<p class="muted selector-hint">Select a height layer, then paint tiles to grow its sparse patch footprint. The list order is the height stack: top entry is Z1, next is Z2, and so on.</p>
</div>
</div>
</div>
<div class="sidebar-panel hidden" id="tilesPanel">
<h3>Graphics</h3>
<div class="entity-filter-tabs" role="tablist" aria-label="Graphics categories">
<button class="entity-filter-tab active" id="graphicsTilesBtn" type="button" aria-pressed="true">Tiles</button>
<button class="entity-filter-tab" id="graphicsSpritesBtn" type="button" aria-pressed="false">Sprites</button>
<button class="entity-filter-tab" id="graphicsOtherBtn" type="button" aria-pressed="false">Other</button>
</div>
<div class="selector-toolbar">
<button class="panel-square-btn" id="newTileFolderBtn" type="button" title="Create graphics folder">&#128193;</button>
<button class="panel-square-btn" id="newTileBtn" type="button" title="Create new graphic" aria-label="Create new graphic">
<span class="panel-icon-image-plus" aria-hidden="true">
<span class="panel-icon-image-frame"></span>
<span class="panel-icon-image-plus-mark">+</span>
</span>
</button>
<button class="panel-square-btn" id="tileSearchModeBtn" type="button" title="Search graphics" aria-label="Search graphics" aria-pressed="false">
<span class="panel-icon-search" aria-hidden="true">&#128269;</span>
</button>
</div>
<div class="npc-list" id="paintPalette"></div>
<p class="muted selector-hint">Tiles paint the world. Sprites power entities. Other graphics stay stored without entering the entity picker.</p>
</div>
<div class="sidebar-panel hidden" id="instancesPanel">
<h3>Entities</h3>
<div class="entity-filter-tabs" role="tablist" aria-label="Entity categories">
<button class="entity-filter-tab active" id="entityTypeFriendlyBtn" type="button" aria-pressed="true">Friendly</button>
<button class="entity-filter-tab" id="entityTypeHostileBtn" type="button" aria-pressed="false">Hostile</button>
<button class="entity-filter-tab" id="entityTypePropBtn" type="button" aria-pressed="false">Props</button>
</div>
<div class="hidden" id="entitySearchModeHost"></div>
<div class="selector-section" id="entityCatalogSection">
<div class="selector-section-header">
<button class="selector-section-toggle" id="toggleTemplateSectionBtn" type="button" aria-expanded="true">
<span class="selector-section-chevron">&#9662;</span>
<span>Catalog</span>
</button>
<div class="selector-section-actions">
<button class="panel-square-btn" id="newTemplateFolderBtn" type="button" title="Create entity catalog folder">&#128193;</button>
<button class="panel-square-btn" id="entitySearchModeBtn" type="button" title="Search entities" aria-label="Search entities" aria-pressed="false">
<span class="panel-icon-search" aria-hidden="true">&#128269;</span>
</button>
</div>
</div>
<div class="selector-section-body" id="instanceTemplateSectionBody">
<div class="npc-list" id="instancePalette"></div>
<p class="muted selector-hint">Select a catalog entity, then click the canvas to place it. The selection stays active for multi-click placement.</p>
</div>
</div>
<div class="selector-section" id="placedEntitiesSection">
<div class="selector-section-header">
<button class="selector-section-toggle" id="togglePlacedSectionBtn" type="button" aria-expanded="true">
<span class="selector-section-chevron">&#9662;</span>
<span>Placed Entities</span>
</button>
<div class="selector-section-actions">
<button class="mini-btn" id="newNpcBtn" type="button">New Entity</button>
<button class="panel-square-btn" id="newPlacedFolderBtn" type="button" title="Create placed entity folder">&#128193;</button>
</div>
</div>
<div class="selector-section-body" id="placedInstanceSectionBody">
<div class="npc-list" id="npcList"></div>
</div>
</div>
</div>
<div class="sidebar-panel hidden" id="triggersPanel">
<h3>Triggers</h3>
<div class="selector-toolbar">
<button class="panel-square-btn" id="newTriggerFolderBtn" type="button" title="Create trigger folder">&#128193;</button>
</div>
<div class="npc-list" id="triggerList"></div>
<p class="muted selector-hint">Trigger placement UI will land here next.</p>
</div>
<div class="sidebar-panel hidden" id="pathsPanel">
<h3>Paths</h3>
<div class="selector-toolbar">
<button class="panel-square-btn" id="newPathFolderBtn" type="button" title="Create path folder">&#128193;</button>
</div>
<div class="npc-list" id="pathList"></div>
<p class="muted selector-hint">Path placement UI will land here next.</p>
</div>
<div class="sidebar-panel hidden" id="transitionsPanel">
<h3>Transitions</h3>
<div class="selector-toolbar">
<button class="panel-square-btn" id="newTransitionFolderBtn" type="button" title="Create transition folder">&#128193;</button>
</div>
<div class="npc-list" id="transitionList"></div>
<p class="muted selector-hint">Transition placement UI will land here next.</p>
</div>
<div class="sidebar-panel hidden history-panel-layout" id="historyPanel">
<h3>History</h3>
<div class="history-stack">
<div class="history-list-scroll">
<div class="history-list" id="historyList"></div>
</div>
<div class="history-current" id="historyCurrent">
<div class="history-current-label">Current State</div>
<div class="history-current-empty">No history yet.</div>
</div>
<div class="history-preview" id="historyPreview">
<h4>Change Preview</h4>
<div class="history-preview-empty">Select a history entry to inspect it.</div>
</div>
</div>
</div>
</div>
<div class="sidebar-static-footer" aria-label="Tool pane links">
<div class="sidebar-footer-links">
<div class="sidebar-footer-linkbar">
<a class="sidebar-footer-link" href="http://www.andraxion.net" target="_blank" rel="noreferrer">Andraxion Studios</a>
</div>
</div>
</div>
</aside>
`;
export const WORLDSHAPER_STUDIO_MARKUP_STAGE = `
<section class="stage" id="stage">
<div class="meta" id="meta">
<div class="meta-main" id="metaMain"></div>
<div class="meta-stats" id="metaStats"></div>
</div>
<button
class="canvas-tool-btn"
id="canvasSelectToolBtn"
type="button"
title="Tile selector: off"
aria-label="Toggle tile selector"
aria-pressed="false"
>
<span class="canvas-tool-btn-icon" aria-hidden="true"></span>
</button>
<div class="viewport" id="viewport">
<div class="viewport-layer"><div class="pixi-host" id="pixiHost" aria-hidden="true"></div><canvas id="roomCanvas"></canvas></div>
<div class="viewport-spacer" id="viewportSpacer" aria-hidden="true"></div>
</div>
</section>
<div class="tool-window-layer" id="toolWindowLayer" aria-hidden="true"></div>
</div>
</div>
`;