pixel/index.html
2026-06-04 18:20:50 +09:00

272 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</title>
<link rel="stylesheet" href="./styles.css" />
</head>
<body>
<div class="app">
<canvas id="worldCanvas" aria-label="Island map"></canvas>
<a class="homeLink" href="https://host.nishi.boats/~333/" aria-label="Open 333 home" title="Open 333 home">
<span class="homeLinkIcon" aria-hidden="true"></span>
<span class="homeLinkText">333</span>
</a>
<button id="openEditor" class="drawDockButton" type="button" title="Open Pixel Studio"><span>✎ DRAW</span><span id="drawQuotaBadge" class="quotaBadge drawQuotaBadge" aria-live="polite"></span></button>
<button id="placeHereButton" class="placeHereButton" type="button" hidden>PLACE HERE</button>
<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>
</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>
</nav>
<div class="drawerBody">
<section id="tab-draw" class="tabPanel active">
<div class="card editorCard heroEditor">
<div class="creationMetaRow" aria-label="Work setup">
<input id="assetName" class="metaInput metaName" type="text" maxlength="32" placeholder="Name" aria-label="Name" />
<input id="assetHeight" class="metaInput metaDimension" type="number" min="1" max="64" step="1" value="8" placeholder="H" aria-label="Height" />
<span class="dimensionSeparator" aria-hidden="true">×</span>
<input id="assetWidth" class="metaInput metaDimension" type="number" min="1" max="64" step="1" value="8" placeholder="W" aria-label="Width" />
<select id="assetCategory" class="metaInput metaRole" aria-label="Role" required>
<option value="" disabled>Role</option>
<option value="human" selected>Human</option>
<option value="animal">Animal</option>
<option value="bird">Bird</option>
<option value="fish">Fish</option>
<option value="nature">Nature</option>
<option value="building">Building</option>
<option value="ship">Ship</option>
<option value="other">Other</option>
</select>
</div>
<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 id="frontSideSwitcher" class="sideSwitcher frontSideSwitcher" hidden aria-label="Front-facing side">
<span class="sideSwitcherLabel">Front</span>
<button id="frontLeft" title="Show left side first">◀ Left</button>
<button id="frontRight" class="active" title="Show right side first">▶ Right</button>
</div>
</div>
<div class="paintLayout">
<div class="paintMainColumn">
<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="drawControlPanel">
<div class="toolRow editorToolRow basicEditorTools" aria-label="Basic draw tools">
<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>
<button id="clearPaint" class="tool toolClear danger" type="button">Clear</button>
</div>
<div class="toolRow editorUtilityRow">
<button id="toggleAdvanced" class="tool toolAdvanced" type="button"> Advanced</button>
<button id="undoPaint" class="tool toolUndo" type="button" disabled>↶ Undo</button>
<button id="redoPaint" class="tool toolRedo" type="button" disabled>↷ Redo</button>
</div>
<div class="advancedPanel">
<div class="advancedPanelHeader">Advanced draw</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>
</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 extraAdvancedRow">
<button id="toolLight" class="tool toolLight advancedOnly" hidden>Light</button>
<button id="toolParticle" class="tool toolParticle advancedOnly" hidden>Particle</button>
<button id="toolDepth" class="tool toolDepth advancedOnly" hidden>Depth</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>
</div>
<span id="advancedHint" class="hint" hidden></span>
<input id="paintColor" type="color" value="#6bd06b" hidden />
<div id="editHint" class="hint" hidden></div>
</div>
</div>
</div>
</div>
<div class="card stack summonCard">
<div class="cardTitle">Finish</div>
<div class="actionRow finishActions">
<button id="saveAndPlace" class="primary bigPrimary"><span>Publish</span><span id="finishQuotaBadge" class="quotaBadge finishQuotaBadge" aria-live="polite"></span></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.</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 accountSettingsCard">
<div class="cardTitle">Account</div>
<p class="hint">Local publishing identity for saving and placing your works.</p>
<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">Publish creates a local account for island publishing.</small>
</div>
</div>
<div class="card stack">
<div class="cardTitle">Display</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>
</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="confirmDialog" class="reportDialog" hidden>
<div class="reportCard" role="dialog" aria-modal="true" aria-labelledby="confirmTitle">
<div id="confirmTitle" class="cardTitle">Delete work</div>
<p id="confirmMessage" class="hint"></p>
<div class="actionRow wrap reportActions">
<button id="confirmOk" class="danger" type="button">Delete</button>
<button id="confirmCancel" type="button">Cancel</button>
</div>
</div>
</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/palette.js"></script>
<script src="./js/pixel-codec.js"></script>
<script src="./js/worker-client.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>