Files
WolfensteinVB/web-editor/index.html
2026-02-19 23:28:57 +01:00

199 lines
8.0 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Wolfenstein VB Level Editor</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<header>
<h1>Wolfenstein VB Level Editor</h1>
<div class="toolbar">
<label>Map size:</label>
<select id="mapSize">
<option value="32,32">32×32</option>
<option value="48,32">48×32</option>
<option value="64,32">64×32</option>
<option value="48,48">48×48</option>
<option value="64,64">64×64</option>
</select>
<label>Level ID (e.g. e1m4):</label>
<input type="text" id="levelId" value="e1m4" maxlength="8" />
<input type="file" id="loadJsonInput" accept=".json" style="display: none" />
<input type="file" id="loadHInput" accept=".h" style="display: none" />
<button type="button" id="btnSaveJson">Save JSON</button>
<button type="button" id="btnLoadJson">Load JSON</button>
<button type="button" id="btnLoadH" title="Import a map from a C header (.h) file">
Load H
</button>
<button type="button" id="btnExport">Export C</button>
<button type="button" id="btnExportHeader">Export header only</button>
<button type="button" id="btnLinkMode" title="Click a switch then a door to link">
Link switch to door
</button>
<button type="button" id="btnHelp">Help</button>
</div>
</header>
<div id="toast" class="toast hidden" aria-live="polite"></div>
<div class="main">
<div class="left">
<div class="panel">
<h3>Brush (walls)</h3>
<div class="brush-grid" id="brushGrid"></div>
</div>
<div class="panel">
<h3>
Entities
<span id="entityListCap" class="cap-label" title="Game limits (enemy.h, pickup.h)"
>0/21 · 0/16</span
>
</h3>
<button type="button" id="brushSpawn1" class="entity-btn">Spawn 1</button>
<button type="button" id="brushSpawn2" class="entity-btn">Spawn 2</button>
<select id="brushEnemy">
<option value="">Enemy (place on grid)</option>
<option value="0">Zombie</option>
<option value="1">Sergeant</option>
<option value="2">Imp</option>
<option value="3">Demon</option>
<option value="4">Commando</option>
</select>
<select id="brushPickup">
<option value="">Pickup (place on grid)</option>
<option value="0">Ammo clip</option>
<option value="1">Health small</option>
<option value="2">Health large</option>
<option value="3">Shotgun</option>
<option value="4">Helmet</option>
<option value="5">Armor</option>
<option value="6">Shells</option>
<option value="7">Rocket launcher</option>
<option value="8">Key Red</option>
<option value="9">Key Yellow</option>
<option value="10">Key Blue</option>
<option value="11">Chaingun</option>
</select>
</div>
</div>
<div class="center">
<div class="grid-wrap">
<canvas id="grid" tabindex="0"></canvas>
<canvas id="gridOverlay" class="grid-overlay" aria-hidden="true"></canvas>
</div>
<div class="status" id="status">Click grid to paint. Select brush above. 32×32</div>
<div id="gridTooltip" class="grid-tooltip hidden" aria-hidden="true"></div>
<div class="preview-section">
<h3 class="preview-heading">
Preview <span class="preview-hint">(focus canvas to drive: WASD or arrows)</span>
</h3>
<canvas id="previewCanvas" tabindex="0"></canvas>
<button type="button" id="btnResetPreview">Reset view</button>
</div>
</div>
<div class="right">
<div class="panel entity-list-panel">
<h3>Entities</h3>
<p class="hint">
Spawn points, enemies, and pickups on the map. Hover to highlight on grid.
</p>
<ul id="entityList"></ul>
</div>
<div class="panel">
<h3>
Doors <span id="doorListCap" class="cap-label" title="MAX_DOORS in door.h">0/24</span>
</h3>
<p class="hint">
Place door tiles (4 or 6/7/8). Stand in front of a door and press Use to open it.
</p>
<ul id="doorList"></ul>
</div>
<div class="panel">
<h3>
Switches
<span id="switchListCap" class="cap-label" title="MAX_SWITCHES in door.h">0/4</span>
</h3>
<p class="hint">
Place switch (5) on map. In export you link each switch to a door index or exit.
</p>
<div id="linkModeExit" class="link-mode-exit hidden">
Switch <span id="pendingSwitchNum">0</span> selected.
<button type="button" id="btnSetExit">Set EXIT</button>
</div>
<ul id="switchList"></ul>
</div>
</div>
</div>
<div id="exportModal" class="modal hidden">
<div class="modal-content modal-content-export">
<h3>Export</h3>
<div id="exportSections" class="export-sections"></div>
<div class="modal-buttons">
<button type="button" id="btnSaveAsHeader">
Save as <span id="exportFileName">e1m4.h</span>
</button>
<button type="button" id="btnCloseExport">Close</button>
</div>
</div>
</div>
<div id="helpModal" class="modal hidden">
<div class="modal-content modal-content-wide">
<h3>How to use export</h3>
<div class="help-content">
<p>
<strong>Quick start:</strong> Export C → save as <code>e1m4.h</code> in
<code>src/vbdoom/assets/doom/</code> → include in RayCasterData.h → add level case in
gameLoop.c <code>loadLevel()</code>.
</p>
<p><strong>Where to put exported files:</strong></p>
<ul>
<li>Map + defines: save as e.g. <code>src/vbdoom/assets/doom/e1m4.h</code></li>
<li>RayCasterData.h: add <code>#include "../assets/doom/e1m4.h"</code></li>
<li>Paste <code>initEnemiesE1M4()</code> into enemy.c; declare in enemy.h</li>
<li>Paste <code>initPickupsE1M4()</code> into pickup.c; declare in pickup.h</li>
</ul>
<p><strong>In gameLoop.c loadLevel():</strong></p>
<ul>
<li>Add <code>else if (levelNum == 4) { ... }</code> for your level</li>
<li>
<code>copymem((u8*)g_map, (u8*)e1m4_map, cells);</code> — if map is smaller than
MAP_CELLS, zero-fill the rest
</li>
<li>
Set fPlayerX, fPlayerY, fPlayerAng from E1M4_SPAWN_X, E1M4_SPAWN_Y and spawn angle
</li>
<li>Call initDoors(), then all registerDoor/registerSwitch from the export comment</li>
<li>Call initEnemiesE1M4(); initPickupsE1M4();</li>
</ul>
<p>
<strong>Also:</strong> Ensure door.h has MAX_DOORS and MAX_SWITCHES large enough. Extend
level transition checks (e.g. currentLevel &lt; 6) for your max level.
</p>
</div>
<button type="button" id="btnCloseHelp">Close</button>
</div>
</div>
<div id="loadJsonModal" class="modal hidden">
<div class="modal-content">
<h3>Load JSON</h3>
<p>Paste level JSON below or choose a file.</p>
<textarea id="loadJsonText" placeholder='{"version":1,"mapW":32,...}'></textarea>
<div class="modal-buttons">
<button type="button" id="btnLoadJsonChooseFile">Choose file</button>
<button type="button" id="btnLoadJsonApply">Load</button>
<button type="button" id="btnCloseLoadJson">Cancel</button>
</div>
</div>
</div>
<script src="editor.js"></script>
</body>
</html>