pixel/index.html
2026-06-02 17:19:36 +09:00

283 lines
15 KiB
HTML
Raw 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>Pixel Island Summoner - Local Prototype</title>
<link rel="stylesheet" href="./styles.css" />
</head>
<body>
<div class="app">
<canvas id="worldCanvas" aria-label="Island map"></canvas>
<div id="islandClickHint" class="islandClickHint">Left-click: select · Right-click: clear</div>
<button id="openEditor" class="drawDockButton" type="button" title="Open Pixel Studio">✎ DRAW</button>
<div id="placementPreviewBar" class="placementPreviewBar" hidden>
<button id="confirmPreviewPlace" class="primary" type="button">Place here</button>
<button id="backToCanvas" class="secondary" type="button">Back to canvas</button>
<span>Check how this work looks on the island. Works are permanent in Collection; island placement is temporary exhibition.</span>
</div>
<header class="hud topHud islandTopBar">
<div class="brandBlock">
<div class="logo">Pixel Island</div>
<div class="subline">A rotating island exhibition for tiny pixel works.</div>
</div>
<div class="authorCard accountCard utilityControl" aria-label="Local account">
<div class="accountFields">
<label class="accountField">ID
<input id="accountId" type="text" readonly placeholder="auto" />
</label>
<label class="accountField">Name
<input id="authorName" type="text" maxlength="24" value="Local Artist" />
</label>
<label class="accountField">Pass
<input id="accountPass" type="text" maxlength="32" placeholder="auto" />
</label>
</div>
<button id="createAccount" class="miniButton" type="button">Generate account</button>
<small id="accountNote">Save + Place creates a local ID, name, and password. Change the password after creation.</small>
</div>
</header>
<div id="analogClock" class="analogClock" aria-label="Island day-night clock" title="10 min = 1 island day">
<div class="analogClockDial">
<span id="analogClockHand" class="analogClockHand"></span>
</div>
<div id="phaseLabel" class="phaseLabel analogClockLabel">Day</div>
<div class="phaseBar analogPhaseBar" aria-hidden="true"><span id="phaseBar"></span></div>
</div>
<section id="studioDrawer" class="studioDrawer" aria-label="Pixel Studio">
<div class="drawerHead">
<div>
<h1>Pixel Studio</h1>
<p>Make static scenery or moving island life.</p>
</div>
<button id="closeEditor" class="ghostButton" title="Close">×</button>
</div>
<nav class="tabs" aria-label="Studio tabs">
<button class="tab active" data-tab="draw">Create</button>
<button class="tab" data-tab="library">Collection</button>
<button class="tab" data-tab="settings">Settings</button>
<button class="tab devOnly" data-tab="data">Data</button>
</nav>
<div class="drawerBody">
<section id="tab-draw" class="tabPanel active">
<div class="card editorCard heroEditor">
<div class="quickSetupBar twoCols">
<label class="field inlineField">Canvas size
<select id="assetSize">
<option value="8" selected>8×8</option>
<option value="16">16×16</option>
<option value="32">32×32</option>
<option value="64">64×64</option>
</select>
</label>
<label class="field inlineField">Role
<select id="assetCategory">
<option value="human">Human</option>
<option value="animal">Animal</option>
<option value="nature" selected>Nature</option>
<option value="building">Building</option>
<option value="ship">Ship</option>
<option value="other">Other</option>
</select>
</label>
</div>
<label class="field compactNameField inlineField">Name
<input id="assetName" type="text" maxlength="32" placeholder="Tiny bakery, round tree, island pup..." />
</label>
<div class="editorTop compactEditorTop">
<div id="sideSwitcher" class="sideSwitcher" hidden aria-label="Sprite direction">
<button id="editLeft" title="Left-facing sprite">◀ Left</button>
<button id="editRight" class="active" title="Right-facing sprite is the main/front direction">▶ Right</button>
</div>
</div>
<div class="paintLayout">
<canvas id="paintCanvas" width="512" height="512" aria-label="Pixel editor"></canvas>
<div class="palettePanel">
<div id="paletteGrid" class="paletteGrid" aria-label="Color palette"></div>
</div>
</div>
<div class="toolRow editorToolRow">
<button id="toolBrush" class="tool toolBrush active" title="B">✎ Draw</button>
<button id="toolErase" class="tool toolErase" title="E">⌫ Erase</button>
<button id="toolFill" class="tool toolFill" title="F">▣ Fill</button>
<button id="toolPick" class="tool toolPick" title="I">◆ Pick</button>
</div>
<div class="toolRow editorHistoryRow">
<button id="undoPaint" class="tool toolUndo" type="button" disabled>↶ Undo</button>
<button id="redoPaint" class="tool toolRedo" type="button" disabled>↷ Redo</button>
</div>
<div id="advancedToolGroup" class="advancedToolGroup" hidden>
<div class="toolRow advancedDrawRow">
<button id="toolLine" class="tool toolLine advancedTool" title="L"> Line</button>
<button id="toolRect" class="tool toolRect advancedTool" title="R">□ Rect</button>
<button id="toolSelect" class="tool toolSelect advancedTool" title="S">▥ Select</button>
<button id="toolDoor" class="tool toolDoor advancedTool buildingOnly">▤ Door</button>
<button id="clearPaint" class="tool danger advancedTool">× Clear</button>
</div>
<div class="toolRow advancedActionRow">
<button id="outlinePaint" class="tool toolOutline advancedTool" type="button">▧ Outline</button>
<button id="flipHorizontal" class="tool toolFlipH advancedTool" type="button">⇄ Flip H</button>
<button id="flipVertical" class="tool toolFlipV advancedTool" type="button">⇅ Flip V</button>
<button id="clearSelection" class="tool toolClearSel advancedTool" type="button" disabled>◇ Clear Sel</button>
</div>
</div>
<div class="advancedRow">
<button id="toggleAdvanced" class="tool toolAdvanced" type="button"> Advanced</button>
<button id="toolLight" class="tool toolLight advancedOnly" hidden>✹ Light</button>
<button id="toolDepth" class="tool toolDepth advancedOnly" hidden>▨ Depth</button>
<button id="toolParticle" class="tool toolParticle advancedOnly" hidden>⁕ Particle</button>
<button id="depthHigh" class="tool advancedOnly" type="button" hidden>▲ High</button>
<button id="depthLow" class="tool advancedOnly" type="button" hidden>▼ Low</button>
<div id="particleDirectionWrap" class="particleControl particleControlGroup advancedOnly" hidden>
<label>Direction
<select id="particleDirection">
<option value="up" selected>↑ Up</option>
<option value="down">↓ Down</option>
<option value="left">← Left</option>
<option value="right">→ Right</option>
</select>
</label>
<small id="particleRangeStatus">Particle: paint cells like Light/Depth. Shift/right-click clears a cell.</small>
</div>
<span id="advancedHint" class="hint" hidden>Advanced tools stay below the basic draw row. Select tool: left-click selects, right-click clears selection. Particle paints emitter cells with palette color and direction. Shift/right-click clears a particle cell.</span>
</div>
<input id="paintColor" type="color" value="#6bd06b" hidden />
<div id="editHint" class="hint">Palette color is used for pixels, lights, particles, and depth marks. Shortcuts: B/E/F/I/L/R/S, Ctrl/Cmd+Z, arrows move a selection.</div>
</div>
<div class="card stack summonCard">
<div class="cardTitle">Finish</div>
<div class="actionRow finishActions">
<button id="saveAndPlace" class="primary bigPrimary">Save + Place on Island</button>
<button id="saveAsset" class="secondary">Save to Collection</button>
</div>
</div>
<div id="lineageNote" class="lineageNote"></div>
</section>
<section id="tab-library" class="tabPanel">
<div class="card stack">
<div class="libraryHead">
<div class="cardTitle">Collection</div>
<button id="showHiddenAssets" class="tool" type="button">Hidden</button>
</div>
<p class="hint">Your works are permanent here. The island is a temporary exhibition: place your own new or past works; remix only copies lineage and pixels to the canvas.</p>
<div id="hiddenAssetPanel" class="hiddenAssetPanel" hidden>
<div class="cardTitle">Hidden</div>
<div id="hiddenAssetList" class="assetList compactAssetList"></div>
</div>
<div id="likedCodex" class="likedCodex"></div>
<div id="assetList" class="assetList"></div>
</div>
</section>
<section id="tab-settings" class="tabPanel">
<div class="card stack">
<div class="cardTitle">Settings</div>
<p class="hint">Turn major visual systems on or off. Server decides the public 250 exhibition slots; this local cap only filters your view.</p>
<div class="toggleList">
<label class="checkRow"><input id="settingLights" type="checkbox" checked /> <span>Lights & glow</span></label>
<label class="checkRow"><input id="settingParticles" type="checkbox" checked /> <span>Particles & ambient FX</span></label>
<label class="checkRow"><input id="settingDayNight" type="checkbox" checked /> <span>Day / night cycle</span></label>
<label class="field displayLimitField">Island display cap
<input id="displayLimit" type="number" min="25" max="500" step="25" value="250" />
</label>
</div>
<div id="rotationStats" class="syncStats"></div>
</div>
</section>
<section id="tab-data" class="tabPanel devOnly">
<div class="card stack">
<div class="cardTitle">Local save</div>
<p class="hint">Works are durable collection works; island placements are temporary exhibition objects. Export JSON if you want to move or test a local world.</p>
<div class="actionRow wrap">
<button id="exportData">Export full JSON</button>
<button id="exportCompact">Export compact</button>
<button id="exportSnapshot">Export snapshot</button>
<button id="exportAssetBundle">Export asset bundle</button>
<button id="importData">Import JSON</button>
<button id="exportPng" type="button">Export PNG</button>
<button id="importPng" type="button">Import PNG</button>
<input id="pngImportInput" type="file" accept="image/png,image/*" hidden />
<button id="resetAll" class="danger">Reset all</button>
</div>
<div id="syncStats" class="syncStats"></div>
<textarea id="dataBox" rows="10" placeholder="Exported JSON appears here."></textarea>
</div>
<div class="card stack">
<div class="cardTitle">Phase 5 guardrails</div>
<p class="hint">Local pre-server checks for object volume, orphaned placements, terrain compatibility, hidden objects, and report logs.</p>
<div id="guardrailStats" class="syncStats"></div>
<div class="actionRow wrap">
<button id="validateWorld" type="button">Validate world</button>
<button id="exportModerationReport" type="button">Export moderation report</button>
<button id="clearReports" class="danger" type="button">Clear reports</button>
</div>
</div>
</section>
</div>
</section>
<div id="selectionBubble" class="selectionBubble" hidden>
<div id="bubbleName" class="bubbleName">Name</div>
<div id="bubbleAuthor" class="bubbleAuthor">by Author</div>
<div id="bubbleRemixFrom" class="bubbleRemixFrom" hidden></div>
<div id="bubbleRemixCount" class="bubbleRemixCount">Remixed: 0</div>
<div class="bubbleVotes">
<button id="voteUp" type="button"></button>
<span id="voteScore">0</span>
<button id="voteDown" type="button"></button>
</div>
<div class="bubbleActions">
<button id="bubbleRemix" class="bubbleRemixPrimary" type="button">Remix</button>
<button id="bubbleTeleport" type="button" hidden>Teleport to source</button>
</div>
<button id="bubbleMenu" class="bubbleMenuButton" type="button">Menu</button>
<div id="bubbleMenuActions" class="bubbleMenuActions" hidden>
<button id="bubbleReport" type="button">Report</button>
<button id="bubbleHide" type="button" hidden>Hide</button>
</div>
</div>
<div id="toast" class="toast" hidden></div>
<div id="reportDialog" class="reportDialog" hidden>
<div class="reportCard" role="dialog" aria-modal="true" aria-labelledby="reportTitle">
<div id="reportTitle" class="cardTitle">Report object</div>
<p class="hint">Select a reason for reporting <strong id="reportObjectName">this object</strong>.</p>
<label class="field">Reason
<select id="reportReason">
<option value="inappropriate">Inappropriate / sexual</option>
<option value="harassment">Harassment / hate</option>
<option value="spam">Spam / flooding</option>
<option value="copyright">Copyright / stolen work</option>
<option value="other">Other</option>
</select>
</label>
<div class="actionRow wrap reportActions">
<button id="reportSubmit" class="danger" type="button">Report + Hide</button>
<button id="reportCancel" type="button">Cancel</button>
</div>
</div>
</div>
</div>
<script src="./js/core-utils.js"></script>
<script src="./js/module-loader.js"></script>
<script src="./js/state-index.js"></script>
<script src="./js/rotation-policy.js"></script>
<script src="./js/lighting.js"></script>
<script src="./js/phase2-sync.js"></script>
<script src="./app.js"></script>
</body>
</html>