@fonsecabarreto/genesis-gl-core 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -2
- package/dist/{Camera-DY_8gx3C.d.ts → Camera-CJVYy9fH.d.ts} +13 -2
- package/dist/Core/classes/Material.d.ts +1 -1
- package/dist/Core/classes/Material.js +1 -1
- package/dist/Core/classes/Model.d.ts +3 -3
- package/dist/Core/classes/Model.js +1 -1
- package/dist/Core/classes/Renderer.d.ts +11 -5
- package/dist/Core/classes/Renderer.js +4 -4
- package/dist/Core/classes/Scene.d.ts +2 -2
- package/dist/Core/classes/Viewport.d.ts +1 -1
- package/dist/Core/classes/Viewport.js +1 -1
- package/dist/Core/index.d.ts +4 -4
- package/dist/Core/index.js +4 -4
- package/dist/Core/utils/load-glb.d.ts +3 -3
- package/dist/Core/utils/load-glb.js +4 -4
- package/dist/Core/utils/parse-obj.d.ts +2 -2
- package/dist/Core/utils/parse-obj.js +4 -4
- package/dist/Editor/index.d.ts +126 -15
- package/dist/Editor/index.js +471 -74
- package/dist/Editor/index.js.map +1 -1
- package/dist/Game/controls/KeyboardInput.d.ts +4 -4
- package/dist/Game/index.d.ts +308 -7
- package/dist/Game/index.js +470 -24
- package/dist/Game/index.js.map +1 -1
- package/dist/{KeyboardInput-DTsfj3tE.d.ts → KeyboardInput-1xOAabI0.d.ts} +95 -14
- package/dist/{Material-BGLkldxv.d.ts → Material-DhwSRbP2.d.ts} +8 -0
- package/dist/{Model-CQvDXd-b.d.ts → Model-BBZHnUp1.d.ts} +24 -8
- package/dist/{chunk-6LS6AO5H.js → chunk-L66K4AZU.js} +36 -30
- package/dist/chunk-L66K4AZU.js.map +1 -0
- package/dist/{chunk-JK2HEZAT.js → chunk-QOAQVTAB.js} +26 -22
- package/dist/chunk-QOAQVTAB.js.map +1 -0
- package/dist/{chunk-5TAAXI6S.js → chunk-XMW2MS66.js} +39 -16
- package/dist/chunk-XMW2MS66.js.map +1 -0
- package/dist/{chunk-QCQVJCSR.js → chunk-ZCJ3MJZD.js} +103 -67
- package/dist/chunk-ZCJ3MJZD.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-5TAAXI6S.js.map +0 -1
- package/dist/chunk-6LS6AO5H.js.map +0 -1
- package/dist/chunk-JK2HEZAT.js.map +0 -1
- package/dist/chunk-QCQVJCSR.js.map +0 -1
package/dist/Editor/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/Editor/sections/materials/MaterialSpec.ts","../../src/Editor/sections/materials/MaterialStore.ts","../../src/Editor/sections/scene/SceneSpec.ts","../../src/Editor/sections/scene/SceneStore.ts","../../src/Editor/sections/scene/SceneSection.ts","../../src/Editor/EditorSidebar.ts","../../src/Editor/TopBar.ts","../../src/Editor/sections/models/ModelsSection.ts"],"sourcesContent":["/** Plain, JSON-serialisable description of a material preset. */\nexport interface MaterialSpec {\n /** Unique identifier (crypto.randomUUID). */\n id: string;\n /** Human-readable name shown in the UI. */\n name: string;\n\n /** RGBA albedo / base colour [0–1]. */\n albedoColor: [number, number, number, number];\n /** RGB diffuse colour [0–1]. */\n diffuse: [number, number, number];\n /** RGB ambient colour [0–1]. */\n ambientColor: [number, number, number];\n /** RGB specular colour [0–1]. */\n specular: [number, number, number];\n\n /** Phong shininess exponent. */\n shininess: number;\n /** Opacity (d / Tr). */\n dissolve: number;\n\n /** Skip lighting calculations and render with raw albedo. */\n unlit: boolean;\n /** Render both front and back faces. */\n doubleSided: boolean;\n\n /** Optional public path to a texture image (relative to /public). */\n texturePath?: string;\n /** When true the texture wraps with GL_REPEAT instead of CLAMP_TO_EDGE. */\n textureRepeat?: boolean;\n /** Physics friction coefficient [0–1]. Defaults to 0.75 when omitted. */\n friction?: number;\n}\n\n/** Create a spec with sensible defaults. */\nexport function createDefaultSpec(name = 'New Material'): MaterialSpec {\n return {\n id: crypto.randomUUID(),\n name,\n albedoColor: [1, 1, 1, 1],\n diffuse: [1, 1, 1],\n ambientColor: [0.1, 0.1, 0.1],\n specular: [0.3, 0.3, 0.3],\n shininess: 64,\n dissolve: 1,\n unlit: false,\n doubleSided: false,\n friction: 0.3,\n };\n}\n","import { createDefaultSpec, MaterialSpec } from './MaterialSpec';\n\nconst STORAGE_KEY = 'genesisgl__material_presets';\n\ntype StoreListener = (specs: MaterialSpec[]) => void;\n\nexport interface MaterialStoreOptions {\n /**\n * URL / public-folder path to a JSON file that seeds the store on {@link MaterialStore.init}.\n * Example: `'data/materials.json'`\n *\n * The file is fetched once with `fetch()` during init. If the fetch succeeds its\n * contents supersede anything already in `localStorage`.\n */\n filePath?: string;\n}\n\n/**\n * Manages a collection of {@link MaterialSpec} presets.\n *\n * - Automatically persists to `localStorage` on every change (synchronous).\n * - Call {@link init} once at startup to seed from a configurable JSON file.\n * - Supports exporting / importing the whole collection as a `.json` file.\n */\nexport class MaterialStore {\n private specs = new Map<string, MaterialSpec>();\n private listeners: StoreListener[] = [];\n private readonly filePath: string | null;\n\n constructor(options: MaterialStoreOptions = {}) {\n this.filePath = options.filePath ?? null;\n // Seed from localStorage immediately so the store is usable before init().\n this.loadFromStorage();\n }\n\n /**\n * Asynchronously loads materials from the configured {@link MaterialStoreOptions.filePath}.\n * Call this once during app / resource initialisation (e.g. inside `loadResources`).\n *\n * The file data is merged on top of any localStorage data; conflicting IDs are\n * overwritten by the file version.\n */\n async init(): Promise<void> {\n if (!this.filePath) return;\n try {\n const res = await fetch(this.filePath);\n if (!res.ok) {\n console.warn(\n `[MaterialStore] Could not load \"${this.filePath}\" (${res.status})`,\n );\n return;\n }\n const items = (await res.json()) as MaterialSpec[];\n for (const spec of items) this.specs.set(spec.id, spec);\n // Sync localStorage so subsequent reloads don't need the fetch.\n this.persist();\n this.emit();\n } catch {\n console.warn(`[MaterialStore] Failed to fetch \"${this.filePath}\"`);\n }\n }\n\n // ── CRUD ────────────────────────────────────────────────────\n\n getAll(): MaterialSpec[] {\n return [...this.specs.values()];\n }\n\n get(id: string): MaterialSpec | undefined {\n return this.specs.get(id);\n }\n\n /** Add a brand-new spec and return it. */\n create(name?: string): MaterialSpec {\n const spec = createDefaultSpec(name);\n this.specs.set(spec.id, spec);\n this.persist();\n this.emit();\n void this.syncToServer();\n return spec;\n }\n\n /** Replace an existing spec (matched by id). */\n update(spec: MaterialSpec): void {\n if (!this.specs.has(spec.id)) return;\n this.specs.set(spec.id, { ...spec });\n this.persist();\n this.emit();\n void this.syncToServer();\n }\n\n /** Deep-clone a spec under a new id. */\n duplicate(id: string): MaterialSpec | undefined {\n const src = this.specs.get(id);\n if (!src) return undefined;\n const copy: MaterialSpec = {\n ...src,\n id: crypto.randomUUID(),\n name: `${src.name} (copy)`,\n albedoColor: [...src.albedoColor],\n diffuse: [...src.diffuse],\n ambientColor: [...src.ambientColor],\n specular: [...src.specular],\n };\n this.specs.set(copy.id, copy);\n this.persist();\n this.emit();\n void this.syncToServer();\n return copy;\n }\n\n delete(id: string): void {\n this.specs.delete(id);\n this.persist();\n this.emit();\n void this.syncToServer();\n }\n\n // ── Server sync ──────────────────────────────────────────────\n\n /**\n * Write the full collection to the server's `materials.json` via the\n * `PUT /api/materials` endpoint provided by the Vite dev plugin.\n * Silently no-ops if no `filePath` was configured.\n */\n async syncToServer(): Promise<boolean> {\n if (!this.filePath) return false;\n try {\n const res = await fetch('/api/materials', {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(this.getAll(), null, 2),\n });\n if (!res.ok) {\n console.warn(`[MaterialStore] Server sync failed (${res.status})`);\n }\n return res.ok;\n } catch {\n console.warn('[MaterialStore] syncToServer: network error');\n return false;\n }\n }\n\n // ── Persistence ──────────────────────────────────────────────\n\n private persist(): void {\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(this.getAll()));\n } catch {\n console.warn('[MaterialStore] Failed to write to localStorage');\n }\n }\n\n private loadFromStorage(): void {\n try {\n const raw = localStorage.getItem(STORAGE_KEY);\n if (!raw) return;\n const items = JSON.parse(raw) as unknown as MaterialSpec[];\n for (const spec of items) this.specs.set(spec.id, spec);\n } catch {\n console.warn('[MaterialStore] Failed to read from localStorage');\n }\n }\n\n // ── File I/O ─────────────────────────────────────────────────\n\n /** Download the full collection as a `.json` file (defaults to the configured filePath name). */\n async exportToFile(filename?: string): Promise<void> {\n const defaultName = this.filePath\n ? this.filePath.split('/').pop() ?? 'materials.json'\n : 'materials.json';\n const name = filename ?? defaultName;\n const json = JSON.stringify(this.getAll(), null, 2);\n const blob = new Blob([json], { type: 'application/json' });\n\n // Use File System Access API when available, fallback to <a download>\n if ('showSaveFilePicker' in window) {\n try {\n const handle = await (\n window as typeof window & {\n showSaveFilePicker: (\n opts: unknown,\n ) => Promise<FileSystemFileHandle>;\n }\n ).showSaveFilePicker({\n suggestedName: name,\n types: [\n { description: 'JSON', accept: { 'application/json': ['.json'] } },\n ],\n });\n const writable = await handle.createWritable();\n await writable.write(blob);\n await writable.close();\n return;\n } catch {\n // user cancelled or API unavailable — fall through\n }\n }\n\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = name;\n a.click();\n URL.revokeObjectURL(url);\n }\n\n /**\n * Open a file-picker, parse the JSON, and merge imported specs.\n * Existing specs with the same id are overwritten.\n */\n importFromFile(): Promise<void> {\n return new Promise((resolve) => {\n const input = document.createElement('input');\n input.type = 'file';\n input.accept = '.json,application/json';\n\n input.onchange = async () => {\n const file = input.files?.[0];\n if (!file) {\n resolve();\n return;\n }\n\n try {\n const text = await file.text();\n const items = JSON.parse(text) as unknown as MaterialSpec[];\n for (const spec of items) this.specs.set(spec.id, spec);\n this.persist();\n this.emit();\n } catch {\n console.error('[MaterialStore] Failed to parse imported file');\n }\n resolve();\n };\n\n input.click();\n });\n }\n\n // ── Subscriptions ────────────────────────────────────────────\n\n subscribe(fn: StoreListener): () => void {\n this.listeners.push(fn);\n return () => {\n this.listeners = this.listeners.filter((l) => l !== fn);\n };\n }\n\n private emit(): void {\n const all = this.getAll();\n for (const fn of this.listeners) fn(all);\n }\n}\n","import { Vector3 } from '../../../Core/domain/interfaces/Vectors';\n\n/** JSON-serialisable description of a single item placed in the scene. */\nexport interface SceneItemSpec {\n /** Unique identifier (crypto.randomUUID). */\n id: string;\n /** Human-readable label shown in the editor. */\n name: string;\n /**\n * Key used to look up the base model in the DI / resource container.\n * The model must have been loaded during resource initialisation.\n */\n resourceKey: string;\n\n translation: Vector3;\n rotation: Vector3;\n scale: Vector3;\n\n /**\n * Custom AABB override relative to translation:\n * `[offsetX, offsetY, offsetZ, width, height, depth]`.\n * When `null` or omitted the model's auto-computed bbox is used.\n */\n bounds?: [number, number, number, number, number, number] | null;\n\n /** Whether this item participates in collision detection. Defaults to `true`. */\n collider?: boolean;\n\n /**\n * Optional material name (from `materials.json`) to override the model's\n * default material. Applied to all meshes in the model at placement time.\n */\n materialKey?: string | null;\n}\n\n/** Top-level scene definition stored in `scene.json`. */\nexport interface SceneSpec {\n /** World position where the player spawns. */\n playerSpawn: Vector3;\n /** All placed models in the scene. */\n items: SceneItemSpec[];\n}\n\n/** Create a new scene item with sensible defaults. */\nexport function createDefaultSceneItem(\n name = 'New Item',\n resourceKey = '',\n): SceneItemSpec {\n return {\n id: crypto.randomUUID(),\n name,\n resourceKey,\n translation: [0, 0, 0],\n rotation: [0, 0, 0],\n scale: [1, 1, 1],\n bounds: null,\n collider: true,\n materialKey: null,\n };\n}\n\n/** Create an empty scene. */\nexport function createDefaultScene(): SceneSpec {\n return {\n playerSpawn: [0, 0, 0],\n items: [],\n };\n}\n","import { createDefaultScene, SceneItemSpec, SceneSpec } from './SceneSpec';\n\nconst STORAGE_KEY = 'genesisgl__scene';\n\ntype StoreListener = (spec: SceneSpec) => void;\n\nexport interface SceneStoreOptions {\n /**\n * URL / public-folder path to a JSON file that seeds the store on {@link SceneStore.init}.\n * Example: `'data/scene.json'`\n */\n filePath?: string;\n}\n\n/**\n * Manages the current scene definition ({@link SceneSpec}).\n *\n * Follows the same patterns as `MaterialStore`:\n * - Persists to `localStorage` on every change.\n * - Call {@link init} once at startup to load from a JSON file.\n * - Syncs back to the server via a PUT endpoint (Vite dev plugin).\n */\nexport class SceneStore {\n private scene: SceneSpec = createDefaultScene();\n private listeners: StoreListener[] = [];\n private readonly filePath: string | null;\n\n constructor(options: SceneStoreOptions = {}) {\n this.filePath = options.filePath ?? null;\n this.loadFromStorage();\n }\n\n // ── Initialisation ──────────────────────────────────────────\n\n async init(): Promise<void> {\n if (!this.filePath) return;\n try {\n const res = await fetch(this.filePath);\n if (!res.ok) {\n console.warn(\n `[SceneStore] Could not load \"${this.filePath}\" (${res.status})`,\n );\n return;\n }\n const data = (await res.json()) as SceneSpec;\n this.scene = data;\n this.persist();\n this.emit();\n } catch {\n console.warn(`[SceneStore] Failed to fetch \"${this.filePath}\"`);\n }\n }\n\n // ── Read ─────────────────────────────────────────────────────\n\n get(): SceneSpec {\n return this.scene;\n }\n\n getItems(): SceneItemSpec[] {\n return this.scene.items;\n }\n\n getItem(id: string): SceneItemSpec | undefined {\n return this.scene.items.find((i) => i.id === id);\n }\n\n getPlayerSpawn(): [number, number, number] {\n return [...this.scene.playerSpawn] as [number, number, number];\n }\n\n // ── Mutations ────────────────────────────────────────────────\n\n setPlayerSpawn(x: number, y: number, z: number): void {\n this.scene.playerSpawn = [x, y, z];\n this.persist();\n this.emit();\n void this.syncToServer();\n }\n\n addItem(item: SceneItemSpec): void {\n this.scene.items.push(item);\n this.persist();\n this.emit();\n void this.syncToServer();\n }\n\n updateItem(item: SceneItemSpec): void {\n const idx = this.scene.items.findIndex((i) => i.id === item.id);\n if (idx === -1) return;\n this.scene.items[idx] = { ...item };\n this.persist();\n this.emit();\n void this.syncToServer();\n }\n\n deleteItem(id: string): void {\n this.scene.items = this.scene.items.filter((i) => i.id !== id);\n this.persist();\n this.emit();\n void this.syncToServer();\n }\n\n /** Replace the entire scene definition. */\n setScene(spec: SceneSpec): void {\n this.scene = spec;\n this.persist();\n this.emit();\n void this.syncToServer();\n }\n\n // ── Server sync ──────────────────────────────────────────────\n\n async syncToServer(): Promise<boolean> {\n if (!this.filePath) return false;\n try {\n const res = await fetch('/api/scene', {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(this.scene, null, 2),\n });\n if (!res.ok) {\n console.warn(`[SceneStore] Server sync failed (${res.status})`);\n }\n return res.ok;\n } catch {\n console.warn('[SceneStore] syncToServer: network error');\n return false;\n }\n }\n\n // ── Persistence ──────────────────────────────────────────────\n\n private persist(): void {\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(this.scene));\n } catch {\n console.warn('[SceneStore] Failed to write to localStorage');\n }\n }\n\n private loadFromStorage(): void {\n try {\n const raw = localStorage.getItem(STORAGE_KEY);\n if (!raw) return;\n const data = JSON.parse(raw) as unknown as SceneSpec;\n if (data && Array.isArray(data.items)) {\n this.scene = data;\n }\n } catch {\n console.warn('[SceneStore] Failed to read from localStorage');\n }\n }\n\n // ── File I/O ─────────────────────────────────────────────────\n\n async exportToFile(filename = 'scene.json'): Promise<void> {\n const json = JSON.stringify(this.scene, null, 2);\n const blob = new Blob([json], { type: 'application/json' });\n\n if ('showSaveFilePicker' in window) {\n try {\n const handle = await (\n window as typeof window & {\n showSaveFilePicker: (\n opts: unknown,\n ) => Promise<FileSystemFileHandle>;\n }\n ).showSaveFilePicker({\n suggestedName: filename,\n types: [\n { description: 'JSON', accept: { 'application/json': ['.json'] } },\n ],\n });\n const writable = await handle.createWritable();\n await writable.write(blob);\n await writable.close();\n return;\n } catch {\n // user cancelled — fall through\n }\n }\n\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = filename;\n a.click();\n URL.revokeObjectURL(url);\n }\n\n importFromFile(): Promise<void> {\n return new Promise((resolve) => {\n const input = document.createElement('input');\n input.type = 'file';\n input.accept = '.json,application/json';\n\n input.onchange = async () => {\n const file = input.files?.[0];\n if (!file) {\n resolve();\n return;\n }\n try {\n const text = await file.text();\n const data = JSON.parse(text) as unknown as SceneSpec;\n if (data && Array.isArray(data.items)) {\n this.scene = data;\n this.persist();\n this.emit();\n }\n } catch {\n console.error('[SceneStore] Failed to parse imported file');\n }\n resolve();\n };\n\n input.click();\n });\n }\n\n // ── Subscriptions ────────────────────────────────────────────\n\n subscribe(fn: StoreListener): () => void {\n this.listeners.push(fn);\n return () => {\n this.listeners = this.listeners.filter((l) => l !== fn);\n };\n }\n\n private emit(): void {\n const spec = this.scene;\n for (const fn of this.listeners) fn(spec);\n }\n}\n","import { EditorTab } from '../../EditorSidebar';\nimport { createDefaultSceneItem, SceneItemSpec } from './SceneSpec';\nimport { SceneStore } from './SceneStore';\n\n/** Entry from models.json */\nexport interface ModelRegistryEntry {\n key: string;\n name: string;\n type: string;\n path?: string;\n description?: string;\n}\n\nexport interface SceneSectionOptions {\n /** URL to the models registry JSON file. */\n modelsFile?: string;\n /** Returns the list of material names currently available. */\n getMaterialNames?: () => string[];\n /** Renderer reference — used to toggle hitbox debug visualisation. */\n renderer?: { debug: boolean };\n}\n\n/**\n * Scene Editor — rendered as a tab inside the {@link EditorSidebar}.\n *\n * Lets the user:\n * – View / edit player spawn position.\n * – View / edit every scene item (translation, rotation, scale, bounds, collider).\n * – Add, duplicate, and delete items.\n * – Reload the game to apply changes.\n */\nexport class SceneSection {\n private root: HTMLElement | null = null;\n private listEl: HTMLElement | null = null;\n private selectedId: string | null = null;\n private formEl: HTMLElement | null = null;\n private unsub?: () => void;\n private modelRegistry: ModelRegistryEntry[] = [];\n private readonly getMaterialNames: () => string[];\n private readonly modelsFile: string | null;\n private readonly renderer: { debug: boolean } | null;\n private hitboxCheck: HTMLInputElement | null = null;\n\n private constructor(\n private readonly store: SceneStore,\n options: SceneSectionOptions = {},\n ) {\n this.modelsFile = options.modelsFile ?? null;\n this.getMaterialNames = options.getMaterialNames ?? (() => []);\n this.renderer = options.renderer ?? null;\n }\n\n // ── Factory ──────────────────────────────────────────────────\n\n static create(\n store: SceneStore,\n options?: SceneSectionOptions,\n ): SceneSection {\n return new SceneSection(store, options);\n }\n\n // ── Tab descriptor ───────────────────────────────────────────\n\n asTab(): EditorTab {\n return {\n id: 'scene',\n label: '🌍 Scene',\n buildContent: (c) => this.buildContent(c),\n onActivate: () => this.onActivate(),\n onDeactivate: () => this.onDeactivate(),\n destroy: () => this.unsub?.(),\n };\n }\n\n // ── Lifecycle ────────────────────────────────────────────────\n\n private onActivate(): void {\n // Load model registry if not loaded yet\n if (this.modelRegistry.length === 0 && this.modelsFile) {\n void fetch(this.modelsFile)\n .then((r) => r.json())\n .then((data: ModelRegistryEntry[]) => {\n this.modelRegistry = data;\n this.refreshForm(); // re-render form with dropdown populated\n })\n .catch(() =>\n console.warn('[SceneSection] Could not load models registry'),\n );\n }\n this.refreshList();\n this.refreshForm();\n }\n\n private onDeactivate(): void {\n /* nothing for now */\n }\n\n // ── Build ────────────────────────────────────────────────────\n\n private buildContent(container: HTMLElement): void {\n this.root = container;\n\n // ── Toolbar\n const toolbar = mk('div', TOOLBAR_STYLE);\n toolbar.appendChild(\n this.mkBtn('+ Item', () => this.onAdd(), 'Add scene item'),\n );\n toolbar.appendChild(\n this.mkBtn('❑', () => this.onDuplicate(), 'Duplicate selected'),\n );\n toolbar.appendChild(\n this.mkBtn('🗑', () => this.onDelete(), 'Delete selected'),\n );\n const reloadBtn = mk(\n 'button',\n BTN_STYLE + ';margin-left:auto;color:#6cf;border-color:#446;',\n );\n reloadBtn.textContent = '🔄 Reload Game';\n reloadBtn.title = 'Sync JSON then reload game to apply changes';\n reloadBtn.onclick = () => location.reload();\n toolbar.appendChild(reloadBtn);\n\n // ── Hitbox toggle\n if (this.renderer) {\n const hitboxLabel = document.createElement('label');\n hitboxLabel.style.cssText =\n 'display:flex;align-items:center;gap:4px;cursor:pointer;color:#ccc;font-size:10px;margin-left:6px;';\n this.hitboxCheck = document.createElement('input');\n this.hitboxCheck.type = 'checkbox';\n this.hitboxCheck.checked = this.renderer.debug;\n this.hitboxCheck.onchange = () => {\n if (this.renderer) {\n this.renderer.debug = this.hitboxCheck!.checked;\n }\n };\n hitboxLabel.appendChild(this.hitboxCheck);\n const hitboxText = document.createElement('span');\n hitboxText.textContent = 'Hitboxes';\n hitboxLabel.appendChild(hitboxText);\n toolbar.appendChild(hitboxLabel);\n }\n\n // ── Body (list + form)\n const body = mk('div', 'display:flex;flex:1;overflow:hidden;');\n this.listEl = mk('div', LIST_STYLE);\n this.formEl = mk('div', FORM_STYLE);\n body.appendChild(this.listEl);\n body.appendChild(this.formEl);\n\n container.appendChild(toolbar);\n container.appendChild(body);\n\n this.unsub = this.store.subscribe(() => {\n this.refreshList();\n this.refreshForm();\n });\n\n this.refreshList();\n }\n\n // ── List ─────────────────────────────────────────────────────\n\n private refreshList(): void {\n if (!this.listEl) return;\n this.listEl.innerHTML = '';\n\n // ── Player Spawn card (always on top)\n const spawn = this.store.getPlayerSpawn();\n const spawnCard = mk('div', CARD_STYLE);\n spawnCard.style.borderLeft = '3px solid #e8a';\n const spawnLabel = mk(\n 'div',\n 'font-weight:bold;color:#e8a;margin-bottom:2px;font-size:11px;',\n );\n spawnLabel.textContent = '🧑 Player Spawn';\n spawnCard.appendChild(spawnLabel);\n spawnCard.appendChild(\n dataRow('pos', `${f(spawn[0])} ${f(spawn[1])} ${f(spawn[2])}`),\n );\n spawnCard.style.cursor = 'pointer';\n spawnCard.onclick = () => {\n this.selectedId = '__player_spawn__';\n this.refreshList();\n this.refreshForm();\n };\n if (this.selectedId === '__player_spawn__') {\n spawnCard.style.background = '#2a2d3a';\n }\n this.listEl.appendChild(spawnCard);\n\n // ── Separator\n const sep = mk('div', 'height:1px;background:#333;margin:6px 0;');\n this.listEl.appendChild(sep);\n\n // ── Scene Items\n const heading = mk(\n 'div',\n 'color:#666;font-size:10px;letter-spacing:1px;padding:0 0 4px;',\n );\n const items = this.store.getItems();\n heading.textContent = `SCENE ITEMS (${items.length})`;\n this.listEl.appendChild(heading);\n\n for (const item of items) {\n const active = item.id === this.selectedId;\n const card = mk('div', CARD_STYLE);\n if (active) card.style.background = '#2a2d3a';\n card.style.cursor = 'pointer';\n card.onclick = () => {\n this.selectedId = item.id;\n // Auto-show hitboxes when selecting a model\n if (this.renderer) {\n this.renderer.debug = true;\n if (this.hitboxCheck) this.hitboxCheck.checked = true;\n }\n this.refreshList();\n this.refreshForm();\n };\n\n const nameEl = mk(\n 'div',\n 'font-weight:bold;color:#9cdcfe;margin-bottom:2px;font-size:11px;',\n );\n nameEl.textContent = `${item.name} [${item.resourceKey}]`;\n card.appendChild(nameEl);\n\n card.appendChild(\n dataRow(\n 'pos',\n `${f(item.translation[0])} ${f(item.translation[1])} ${f(item.translation[2])}`,\n ),\n );\n card.appendChild(\n dataRow(\n 'scl',\n `${f(item.scale[0])} ${f(item.scale[1])} ${f(item.scale[2])}`,\n ),\n );\n\n this.listEl.appendChild(card);\n }\n }\n\n // ── Form ─────────────────────────────────────────────────────\n\n private refreshForm(): void {\n if (!this.formEl) return;\n this.formEl.innerHTML = '';\n\n if (this.selectedId === '__player_spawn__') {\n this.buildSpawnForm(this.formEl);\n return;\n }\n\n const item = this.selectedId\n ? this.store.getItem(this.selectedId)\n : undefined;\n if (!item) {\n const hint = mk('div', 'color:#666;padding:8px;font-size:11px;');\n hint.textContent = 'Select an item to edit';\n this.formEl.appendChild(hint);\n return;\n }\n\n this.buildItemForm(this.formEl, item);\n }\n\n private buildSpawnForm(container: HTMLElement): void {\n const spawn = this.store.getPlayerSpawn();\n const title = mk(\n 'div',\n 'font-weight:bold;color:#e8a;padding:0 0 6px;font-size:12px;',\n );\n title.textContent = '🧑 Player Spawn';\n container.appendChild(title);\n\n container.appendChild(\n this.vec3Row('Position', spawn, (v) => {\n this.store.setPlayerSpawn(v[0], v[1], v[2]);\n }),\n );\n }\n\n private buildItemForm(container: HTMLElement, item: SceneItemSpec): void {\n const title = mk(\n 'div',\n 'font-weight:bold;color:#9cdcfe;padding:0 0 6px;font-size:12px;',\n );\n title.textContent = item.name;\n container.appendChild(title);\n\n // Name\n container.appendChild(\n this.textRow('Name', item.name, (v) => {\n this.store.updateItem({ ...item, name: v });\n }),\n );\n\n // Resource Key (model picker dropdown)\n const modelOptions = this.modelRegistry.map((m) => ({\n value: m.key,\n label: `${m.name} (${m.type})`,\n }));\n container.appendChild(\n this.selectRow('Resource', item.resourceKey, modelOptions, (v) => {\n this.store.updateItem({ ...item, resourceKey: v });\n }),\n );\n\n // Material override\n const matNames = this.getMaterialNames();\n const matOptions = [\n { value: '', label: '(default)' },\n ...matNames.map((n) => ({ value: n, label: n })),\n ];\n container.appendChild(\n this.selectRow('Material', item.materialKey ?? '', matOptions, (v) => {\n this.store.updateItem({ ...item, materialKey: v || null });\n }),\n );\n\n // Translation\n container.appendChild(\n this.vec3Row(\n 'Position',\n [...item.translation] as [number, number, number],\n (v) => {\n this.store.updateItem({ ...item, translation: v });\n },\n ),\n );\n\n // Rotation\n container.appendChild(\n this.vec3Row(\n 'Rotation',\n [...item.rotation] as [number, number, number],\n (v) => {\n this.store.updateItem({ ...item, rotation: v });\n },\n ),\n );\n\n // Scale\n container.appendChild(\n this.vec3Row(\n 'Scale',\n [...item.scale] as [number, number, number],\n (v) => {\n this.store.updateItem({ ...item, scale: v });\n },\n ),\n );\n\n // Bounds\n const hasBounds = item.bounds != null;\n container.appendChild(\n this.checkRow('Custom Bounds', hasBounds, (on) => {\n if (on) {\n this.store.updateItem({\n ...item,\n bounds: [0, 0, 0, 1, 1, 1],\n });\n } else {\n this.store.updateItem({ ...item, bounds: null });\n }\n }),\n );\n\n if (item.bounds) {\n const b = item.bounds;\n container.appendChild(\n this.vec3Row('Offset', [b[0], b[1], b[2]], (v) => {\n this.store.updateItem({\n ...item,\n bounds: [v[0], v[1], v[2], b[3], b[4], b[5]],\n });\n }),\n );\n container.appendChild(\n this.vec3Row('Size', [b[3], b[4], b[5]], (v) => {\n this.store.updateItem({\n ...item,\n bounds: [b[0], b[1], b[2], v[0], v[1], v[2]],\n });\n }),\n );\n }\n\n // Collider\n container.appendChild(\n this.checkRow('Collider', item.collider !== false, (on) => {\n this.store.updateItem({ ...item, collider: on });\n }),\n );\n }\n\n // ── CRUD actions ─────────────────────────────────────────────\n\n private onAdd(): void {\n const item = createDefaultSceneItem();\n this.store.addItem(item);\n this.selectedId = item.id;\n }\n\n private onDuplicate(): void {\n if (!this.selectedId || this.selectedId === '__player_spawn__') return;\n const src = this.store.getItem(this.selectedId);\n if (!src) return;\n const copy: SceneItemSpec = {\n ...src,\n id: crypto.randomUUID(),\n name: `${src.name} (copy)`,\n translation: [...src.translation] as [number, number, number],\n rotation: [...src.rotation] as [number, number, number],\n scale: [...src.scale] as [number, number, number],\n bounds: src.bounds\n ? ([...src.bounds] as [number, number, number, number, number, number])\n : null,\n };\n this.store.addItem(copy);\n this.selectedId = copy.id;\n }\n\n private onDelete(): void {\n if (!this.selectedId || this.selectedId === '__player_spawn__') return;\n this.store.deleteItem(this.selectedId);\n this.selectedId = null;\n }\n\n // ── Input helpers ────────────────────────────────────────────\n\n private vec3Row(\n label: string,\n values: [number, number, number],\n onChange: (v: [number, number, number]) => void,\n ): HTMLElement {\n const row = mk('div', ROW_STYLE);\n const lbl = mk('div', LABEL_STYLE);\n lbl.textContent = label;\n row.appendChild(lbl);\n\n const group = mk('div', 'display:flex;gap:4px;');\n const labels = ['X', 'Y', 'Z'];\n\n for (let i = 0; i < 3; i++) {\n const wrap = mk('div', 'display:flex;flex-direction:column;flex:1;');\n const axisLbl = mk('div', 'color:#666;font-size:9px;text-align:center;');\n axisLbl.textContent = labels[i];\n const input = document.createElement('input');\n input.type = 'number';\n input.step = '0.1';\n input.value = String(values[i]);\n input.style.cssText = INPUT_STYLE;\n input.onchange = () => {\n const v = [...values] as [number, number, number];\n v[i] = parseFloat(input.value) || 0;\n onChange(v);\n };\n wrap.appendChild(axisLbl);\n wrap.appendChild(input);\n group.appendChild(wrap);\n }\n\n row.appendChild(group);\n return row;\n }\n\n private textRow(\n label: string,\n value: string,\n onChange: (v: string) => void,\n ): HTMLElement {\n const row = mk('div', ROW_STYLE);\n const lbl = mk('div', LABEL_STYLE);\n lbl.textContent = label;\n row.appendChild(lbl);\n\n const input = document.createElement('input');\n input.type = 'text';\n input.value = value;\n input.style.cssText = INPUT_STYLE + ';flex:1;';\n input.onchange = () => onChange(input.value);\n row.appendChild(input);\n return row;\n }\n\n private selectRow(\n label: string,\n value: string,\n options: { value: string; label: string }[],\n onChange: (v: string) => void,\n ): HTMLElement {\n const row = mk('div', ROW_STYLE);\n const lbl = mk('div', LABEL_STYLE);\n lbl.textContent = label;\n row.appendChild(lbl);\n\n const select = document.createElement('select');\n select.style.cssText = INPUT_STYLE + ';flex:1;';\n for (const opt of options) {\n const o = document.createElement('option');\n o.value = opt.value;\n o.textContent = opt.label;\n if (opt.value === value) o.selected = true;\n select.appendChild(o);\n }\n select.onchange = () => onChange(select.value);\n row.appendChild(select);\n return row;\n }\n\n private checkRow(\n label: string,\n checked: boolean,\n onChange: (v: boolean) => void,\n ): HTMLElement {\n const row = mk('div', ROW_STYLE + ';align-items:center;');\n const lbl = mk('div', LABEL_STYLE);\n lbl.textContent = label;\n row.appendChild(lbl);\n\n const input = document.createElement('input');\n input.type = 'checkbox';\n input.checked = checked;\n input.onchange = () => onChange(input.checked);\n row.appendChild(input);\n return row;\n }\n\n private mkBtn(\n text: string,\n onClick: () => void,\n title: string,\n ): HTMLButtonElement {\n const btn = document.createElement('button');\n btn.textContent = text;\n btn.title = title;\n btn.style.cssText = BTN_STYLE;\n btn.onclick = onClick;\n return btn;\n }\n}\n\n// ── Helpers ───────────────────────────────────────────────────────\n\nfunction mk(\n tag: string,\n style = '',\n): HTMLElement & HTMLButtonElement & HTMLDivElement {\n const el = document.createElement(tag) as HTMLElement &\n HTMLButtonElement &\n HTMLDivElement;\n if (style) el.style.cssText = style;\n return el;\n}\n\nfunction f(n: number): string {\n return n.toFixed(2);\n}\n\nfunction dataRow(label: string, value: string): HTMLElement {\n const row = document.createElement('div');\n row.style.cssText = 'display:flex;gap:4px;line-height:1.6;';\n\n const lbl = document.createElement('span');\n lbl.style.cssText = 'color:#666;width:28px;flex-shrink:0;font-size:10px;';\n lbl.textContent = label;\n\n const val = document.createElement('span');\n val.style.cssText = 'color:#ccc;font-size:10px;';\n val.textContent = value;\n\n row.appendChild(lbl);\n row.appendChild(val);\n return row;\n}\n\n// ── Styles ────────────────────────────────────────────────────────\n\nconst TOOLBAR_STYLE = [\n 'display:flex',\n 'gap:6px',\n 'padding:6px 10px',\n 'background:#222',\n 'border-bottom:1px solid #333',\n 'flex-shrink:0',\n].join(';');\n\nconst BTN_STYLE = [\n 'background:#2a2a2a',\n 'color:#ccc',\n 'border:1px solid #555',\n 'border-radius:4px',\n 'padding:3px 10px',\n 'cursor:pointer',\n 'font-size:11px',\n 'font-family:monospace',\n].join(';');\n\nconst LIST_STYLE = [\n 'width:220px',\n 'overflow-y:auto',\n 'padding:8px',\n 'border-right:1px solid #333',\n 'flex-shrink:0',\n].join(';');\n\nconst FORM_STYLE = ['flex:1', 'overflow-y:auto', 'padding:10px'].join(';');\n\nconst CARD_STYLE = [\n 'background:#1e1e1e',\n 'border:1px solid #333',\n 'border-radius:4px',\n 'padding:6px 8px',\n 'margin-bottom:4px',\n 'font-family:monospace',\n 'font-size:10px',\n].join(';');\n\nconst ROW_STYLE = ['display:flex', 'gap:6px', 'margin-bottom:8px'].join(';');\n\nconst LABEL_STYLE = [\n 'color:#888',\n 'font-size:11px',\n 'width:70px',\n 'flex-shrink:0',\n 'padding-top:2px',\n].join(';');\n\nconst INPUT_STYLE = [\n 'background:#1a1a1a',\n 'color:#ccc',\n 'border:1px solid #444',\n 'border-radius:3px',\n 'padding:3px 5px',\n 'font-size:11px',\n 'font-family:monospace',\n 'width:60px',\n 'outline:none',\n].join(';');\n","import { MaterialSpec } from './sections/materials/MaterialSpec';\nimport { MaterialStore } from './sections/materials/MaterialStore';\n\ntype Vec3Field = 'diffuse' | 'ambientColor' | 'specular';\n\nexport interface EditorTab {\n id: string;\n /** Label shown on the tab button. */\n label: string;\n /** Called once to populate the tab's content container. */\n buildContent: (container: HTMLElement) => void;\n /** Called each time the tab becomes the active, visible tab. */\n onActivate?: () => void;\n /** Called each time the tab is hidden (tab switch or sidebar hide). */\n onDeactivate?: () => void;\n /** Optional cleanup called when the sidebar is unmounted. */\n destroy?: () => void;\n}\n\n/**\n * Fixed right-side editor sidebar.\n *\n * - Hosts a tab strip so new features can be added via {@link addTab}.\n * - First tab is the Material Editor (colour preview swatches + full form).\n * - Every store mutation auto-syncs to `materials.json` via the Vite dev plugin.\n * - \"🔄 Reload Game\" triggers `location.reload()` to pick up JSON changes.\n */\nexport class EditorSidebar {\n private root!: HTMLElement;\n private tabBar!: HTMLElement;\n private contentArea!: HTMLElement;\n private tabs: EditorTab[] = [];\n private activeTabId: string | null = null;\n\n // material panel state\n private listEl!: HTMLElement;\n private formEl!: HTMLElement;\n private selectedId: string | null = null;\n private unsubMaterials?: () => void;\n\n // drag-resize state\n private _sidebarWidth = 520;\n private _dragging = false;\n\n // layout mode: 'absolute' overlays, 'shared' shrinks viewport\n private _layoutMode: 'absolute' | 'shared' = 'absolute';\n private _layoutBtn: HTMLButtonElement | null = null;\n\n private constructor(private readonly store: MaterialStore) {}\n\n // ── Public API ──────────────────────────────────────────────\n\n static mount(store: MaterialStore): EditorSidebar {\n const s = new EditorSidebar(store);\n s.build();\n return s;\n }\n\n show(): void {\n this.root.style.display = 'flex';\n this.applyLayout();\n if (this.activeTabId) {\n this.tabs.find((t) => t.id === this.activeTabId)?.onActivate?.();\n }\n }\n\n hide(): void {\n if (this.activeTabId) {\n this.tabs.find((t) => t.id === this.activeTabId)?.onDeactivate?.();\n }\n this.root.style.display = 'none';\n this.applyLayout();\n }\n\n toggle(): void {\n if (this.root.style.display === 'none') this.show();\n else this.hide();\n }\n\n get isVisible(): boolean {\n return this.root.style.display !== 'none';\n }\n\n /** Register an extra tab. */\n addTab(tab: EditorTab): void {\n this.tabs.push(tab);\n if (this.tabBar) this.renderTabBar();\n }\n\n unmount(): void {\n this.unsubMaterials?.();\n for (const t of this.tabs) t.destroy?.();\n this.root?.remove();\n }\n\n // ── Build ────────────────────────────────────────────────────\n\n private build(): void {\n this.root = el('div', { id: 'gl-editor-sidebar' }, SIDEBAR_STYLE);\n this.root.style.display = 'none';\n this.root.style.width = `${this._sidebarWidth}px`;\n\n // ── Drag handle (left edge) ────────────────────────────────\n const handle = el('div', {}, DRAG_HANDLE_STYLE);\n handle.addEventListener('mousedown', (e) => {\n e.preventDefault();\n this._dragging = true;\n document.body.style.cursor = 'col-resize';\n document.body.style.userSelect = 'none';\n });\n document.addEventListener('mousemove', (e) => {\n if (!this._dragging) return;\n const newWidth = window.innerWidth - e.clientX;\n this._sidebarWidth = Math.max(280, Math.min(newWidth, 900));\n this.root.style.width = `${this._sidebarWidth}px`;\n this.applyLayout();\n });\n document.addEventListener('mouseup', () => {\n if (!this._dragging) return;\n this._dragging = false;\n document.body.style.cursor = '';\n document.body.style.userSelect = '';\n });\n this.root.appendChild(handle);\n\n const header = el('div', {}, HEADER_STYLE);\n const title = el(\n 'span',\n {},\n 'font-weight:bold;color:#9cdcfe;letter-spacing:1px;',\n );\n title.textContent = '🛠 Editor';\n header.appendChild(title);\n // Layout toggle (absolute ↔ shared)\n this._layoutBtn = el(\n 'button',\n {},\n ICON_BTN_STYLE + ';margin-left:auto;font-size:14px;',\n );\n this._layoutBtn.title = 'Toggle: overlay / share viewport';\n this._layoutBtn.textContent = '⇔';\n this._layoutBtn.onclick = () => this.toggleLayout();\n header.appendChild(this._layoutBtn);\n\n const closeBtn = el('button', {}, ICON_BTN_STYLE);\n closeBtn.textContent = '✕';\n closeBtn.title = 'Close sidebar';\n closeBtn.onclick = () => this.hide();\n header.appendChild(closeBtn);\n\n this.tabBar = el('div', {}, TAB_BAR_STYLE);\n this.contentArea = el(\n 'div',\n {},\n 'flex:1;overflow:hidden;display:flex;flex-direction:column;',\n );\n\n this.root.appendChild(header);\n this.root.appendChild(this.tabBar);\n this.root.appendChild(this.contentArea);\n document.body.appendChild(this.root);\n\n this.addTab({\n id: 'materials',\n label: '🎨 Materials',\n buildContent: (c) => this.buildMaterialsContent(c),\n destroy: () => this.unsubMaterials?.(),\n });\n this.activateTab('materials');\n }\n\n // ── Layout mode ──────────────────────────────────────────────\n\n private toggleLayout(): void {\n this._layoutMode = this._layoutMode === 'absolute' ? 'shared' : 'absolute';\n this.applyLayout();\n }\n\n private applyLayout(): void {\n const visible = this.root.style.display !== 'none';\n if (this._layoutMode === 'shared' && visible) {\n document.body.style.marginRight = `${this._sidebarWidth}px`;\n } else {\n document.body.style.marginRight = '0';\n }\n // Update button label hint\n if (this._layoutBtn) {\n this._layoutBtn.textContent = this._layoutMode === 'absolute' ? '⇔' : '⇤';\n this._layoutBtn.title =\n this._layoutMode === 'absolute'\n ? 'Switch to shared layout (shrink viewport)'\n : 'Switch to overlay layout';\n }\n }\n\n // ── Tab system ───────────────────────────────────────────────\n\n private renderTabBar(): void {\n this.tabBar.innerHTML = '';\n for (const tab of this.tabs) {\n const btn = el(\n 'button',\n {},\n TAB_BTN_STYLE + (tab.id === this.activeTabId ? TAB_BTN_ACTIVE : ''),\n );\n btn.textContent = tab.label;\n btn.onclick = () => this.activateTab(tab.id);\n this.tabBar.appendChild(btn);\n }\n }\n\n /** Activate a tab by id. Safe to call from outside (e.g. TopBar button). */\n activateTab(id: string): void {\n // Deactivate the current tab before switching\n if (this.activeTabId && this.activeTabId !== id) {\n this.tabs.find((t) => t.id === this.activeTabId)?.onDeactivate?.();\n }\n this.activeTabId = id;\n this.renderTabBar();\n this.contentArea.innerHTML = '';\n const tab = this.tabs.find((t) => t.id === id);\n if (!tab) return;\n const c = el(\n 'div',\n {},\n 'flex:1;overflow:hidden;display:flex;flex-direction:column;',\n );\n tab.buildContent(c);\n this.contentArea.appendChild(c);\n tab.onActivate?.();\n }\n\n // ── Materials tab content ────────────────────────────────────\n\n private buildMaterialsContent(container: HTMLElement): void {\n const toolbar = el('div', {}, TOOLBAR_STYLE);\n toolbar.appendChild(this.mkBtn('+', () => this.onNew(), 'New material'));\n toolbar.appendChild(this.mkBtn('❑', () => this.onDuplicate(), 'Duplicate'));\n toolbar.appendChild(this.mkBtn('🗑', () => this.onDelete(), 'Delete'));\n const reloadBtn = el(\n 'button',\n {},\n BTN_STYLE + ';margin-left:auto;color:#6cf;border-color:#446;',\n );\n reloadBtn.textContent = '🔄 Reload Game';\n reloadBtn.title = 'Sync JSON then reload game to apply changes';\n reloadBtn.onclick = () => location.reload();\n toolbar.appendChild(reloadBtn);\n\n const body = el('div', {}, 'display:flex;flex:1;overflow:hidden;');\n this.listEl = el('div', {}, LIST_STYLE);\n this.formEl = el('div', {}, FORM_STYLE);\n body.appendChild(this.listEl);\n body.appendChild(this.formEl);\n\n container.appendChild(toolbar);\n container.appendChild(body);\n\n this.unsubMaterials = this.store.subscribe(() => this.refreshList());\n this.refreshList();\n }\n\n // ── List ─────────────────────────────────────────────────────\n\n private refreshList(): void {\n this.listEl.innerHTML = '';\n for (const spec of this.store.getAll()) {\n const active = spec.id === this.selectedId;\n const item = el(\n 'div',\n {},\n LIST_ITEM_STYLE + (active ? LIST_ITEM_ACTIVE : ''),\n );\n // Colour preview swatch\n const swatch = el('div', {}, swatchStyle(spec));\n item.appendChild(swatch);\n const nameEl = el(\n 'span',\n {},\n 'flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;',\n );\n nameEl.textContent = spec.name;\n item.appendChild(nameEl);\n item.onclick = () => this.select(spec.id);\n this.listEl.appendChild(item);\n }\n\n if (this.selectedId && !this.store.get(this.selectedId)) {\n this.selectedId = null;\n this.formEl.innerHTML = EMPTY_FORM_HTML;\n }\n }\n\n private select(id: string): void {\n this.selectedId = id;\n this.refreshList();\n this.buildForm();\n }\n\n // ── Form ─────────────────────────────────────────────────────\n\n private buildForm(): void {\n const spec = this.selectedId ? this.store.get(this.selectedId) : undefined;\n this.formEl.innerHTML = '';\n if (!spec) return;\n\n const draft: MaterialSpec = {\n ...spec,\n albedoColor: [...spec.albedoColor],\n diffuse: [...spec.diffuse],\n ambientColor: [...spec.ambientColor],\n specular: [...spec.specular],\n };\n\n const save = () => {\n this.store.update(draft);\n this.select(draft.id);\n };\n\n // Name\n formRow(this.formEl, 'Name', () => {\n const inp = el('input', { type: 'text', value: draft.name }, INPUT_STYLE);\n inp.oninput = () => {\n draft.name = inp.value;\n };\n inp.onblur = save;\n return inp;\n });\n\n // Albedo RGBA\n formRow(this.formEl, 'Albedo (RGBA)', () => {\n const wrap = el('div', {}, 'display:flex;gap:4px;align-items:center;');\n const hex = rgbToHex(\n draft.albedoColor[0],\n draft.albedoColor[1],\n draft.albedoColor[2],\n );\n const picker = el(\n 'input',\n { type: 'color', value: hex },\n 'cursor:pointer;',\n );\n const alphaIn = el(\n 'input',\n {\n type: 'range',\n min: '0',\n max: '1',\n step: '0.01',\n value: String(draft.albedoColor[3]),\n },\n 'flex:1;',\n );\n const alphaLbl = el(\n 'span',\n {},\n 'min-width:30px;color:#ccc;font-size:11px;',\n );\n alphaLbl.textContent = draft.albedoColor[3].toFixed(2);\n const update = () => {\n const [r, g, b] = hexToRgb(picker.value);\n draft.albedoColor = [r, g, b, parseFloat(alphaIn.value)];\n alphaLbl.textContent = parseFloat(alphaIn.value).toFixed(2);\n save();\n };\n picker.oninput = update;\n alphaIn.oninput = update;\n wrap.appendChild(picker);\n wrap.appendChild(alphaIn);\n wrap.appendChild(alphaLbl);\n return wrap;\n });\n\n // Vec3 colour pickers\n for (const key of ['diffuse', 'ambientColor', 'specular'] as Vec3Field[]) {\n const label = {\n diffuse: 'Diffuse',\n ambientColor: 'Ambient',\n specular: 'Specular',\n }[key];\n formRow(this.formEl, label, () => {\n const hex = rgbToHex(draft[key][0], draft[key][1], draft[key][2]);\n const picker = el(\n 'input',\n { type: 'color', value: hex },\n 'cursor:pointer;',\n );\n picker.oninput = () => {\n [draft[key][0], draft[key][1], draft[key][2]] = hexToRgb(\n picker.value,\n );\n save();\n };\n return picker;\n });\n }\n\n // Sliders\n numericRow(this.formEl, 'Shininess', draft.shininess, 2, 256, 1, (v) => {\n draft.shininess = v;\n save();\n });\n numericRow(this.formEl, 'Dissolve', draft.dissolve, 0, 1, 0.01, (v) => {\n draft.dissolve = v;\n save();\n });\n numericRow(\n this.formEl,\n 'Friction',\n draft.friction ?? 0.75,\n 0,\n 1,\n 0.01,\n (v) => {\n draft.friction = v;\n save();\n },\n );\n\n // Toggles\n checkRow(this.formEl, 'Unlit', draft.unlit, (v) => {\n draft.unlit = v;\n save();\n });\n checkRow(this.formEl, 'Double Sided', draft.doubleSided, (v) => {\n draft.doubleSided = v;\n save();\n });\n\n // Texture path\n formRow(this.formEl, 'Texture Path', () => {\n const inp = el(\n 'input',\n {\n type: 'text',\n value: draft.texturePath ?? '',\n placeholder: 'textures/my-tex.png',\n },\n INPUT_STYLE,\n );\n inp.oninput = () => {\n draft.texturePath = inp.value || undefined;\n };\n inp.onblur = save;\n return inp;\n });\n }\n\n // ── Actions ──────────────────────────────────────────────────\n\n private onNew(): void {\n const spec = this.store.create();\n this.select(spec.id);\n }\n\n private onDuplicate(): void {\n if (!this.selectedId) return;\n const copy = this.store.duplicate(this.selectedId);\n if (copy) this.select(copy.id);\n }\n\n private onDelete(): void {\n if (!this.selectedId) return;\n if (!confirm('Delete this material?')) return;\n this.store.delete(this.selectedId);\n this.selectedId = null;\n this.formEl.innerHTML = EMPTY_FORM_HTML;\n }\n\n private mkBtn(\n label: string,\n onClick: () => void,\n title = '',\n ): HTMLButtonElement {\n const b = el('button', {}, BTN_STYLE);\n b.textContent = label;\n b.title = title;\n b.onclick = onClick;\n return b;\n }\n}\n\n// ── DOM helpers ───────────────────────────────────────────────────\n\nfunction el<K extends keyof HTMLElementTagNameMap>(\n tag: K,\n attrs: Record<string, string> = {},\n style = '',\n): HTMLElementTagNameMap[K] {\n const e = document.createElement(tag);\n for (const [k, v] of Object.entries(attrs))\n (e as unknown as Record<string, string>)[k] = v;\n if (style) e.style.cssText = style;\n return e;\n}\n\nfunction formRow(\n parent: HTMLElement,\n label: string,\n buildInput: () => HTMLElement,\n): void {\n const row = el(\n 'div',\n {},\n 'display:flex;justify-content:space-between;align-items:center;margin-bottom:6px;gap:8px;',\n );\n const lbl = el(\n 'label',\n {},\n 'color:#bbb;font-size:12px;white-space:nowrap;min-width:90px;',\n );\n lbl.textContent = label;\n row.appendChild(lbl);\n const wrap = el('div', {}, 'flex:1;');\n wrap.appendChild(buildInput());\n row.appendChild(wrap);\n parent.appendChild(row);\n}\n\nfunction numericRow(\n parent: HTMLElement,\n label: string,\n value: number,\n min: number,\n max: number,\n step: number,\n onChange: (v: number) => void,\n): void {\n formRow(parent, label, () => {\n const wrap = el('div', {}, 'display:flex;gap:4px;align-items:center;');\n const slider = el(\n 'input',\n {\n type: 'range',\n min: String(min),\n max: String(max),\n step: String(step),\n value: String(value),\n },\n 'flex:1;',\n );\n const lbl = el(\n 'span',\n {},\n 'min-width:36px;color:#ccc;font-size:11px;text-align:right;',\n );\n lbl.textContent = value.toString();\n slider.oninput = () => {\n lbl.textContent = slider.value;\n onChange(parseFloat(slider.value));\n };\n wrap.appendChild(slider);\n wrap.appendChild(lbl);\n return wrap;\n });\n}\n\nfunction checkRow(\n parent: HTMLElement,\n label: string,\n value: boolean,\n onChange: (v: boolean) => void,\n): void {\n formRow(parent, label, () => {\n const cb = el('input', { type: 'checkbox' }, '');\n cb.checked = value;\n cb.onchange = () => onChange(cb.checked);\n return cb;\n });\n}\n\nfunction rgbToHex(r: number, g: number, b: number): string {\n const byte = (v: number) =>\n Math.round(Math.min(1, Math.max(0, v)) * 255)\n .toString(16)\n .padStart(2, '0');\n return `#${byte(r)}${byte(g)}${byte(b)}`;\n}\n\nfunction hexToRgb(hex: string): [number, number, number] {\n const n = parseInt(hex.slice(1), 16);\n return [((n >> 16) & 255) / 255, ((n >> 8) & 255) / 255, (n & 255) / 255];\n}\n\nfunction swatchStyle(spec: MaterialSpec): string {\n const [r, g, b, a] = spec.albedoColor;\n return [\n `background:rgba(${Math.round(r * 255)},${Math.round(g * 255)},${Math.round(b * 255)},${a})`,\n 'width:18px',\n 'min-width:18px',\n 'height:18px',\n 'border-radius:3px',\n 'border:1px solid #666',\n 'flex-shrink:0',\n ].join(';');\n}\n\n// ── Constants ─────────────────────────────────────────────────────\n\nconst EMPTY_FORM_HTML =\n '<p style=\"color:#888;padding:16px 10px;font-size:12px;\">Select or create a material.</p>';\n\n// ── Styles ────────────────────────────────────────────────────────\n\nconst SIDEBAR_STYLE = [\n 'position:fixed',\n 'top:32px',\n 'right:0',\n 'height:calc(100vh - 32px)',\n 'background:#1e1e1e',\n 'border-left:1px solid #444',\n 'display:flex',\n 'flex-direction:column',\n 'color:#ddd',\n 'font-family:monospace',\n 'font-size:12px',\n 'z-index:9998',\n 'box-shadow:-4px 0 20px rgba(0,0,0,.6)',\n 'overflow:hidden',\n].join(';');\n\nconst DRAG_HANDLE_STYLE = [\n 'position:absolute',\n 'top:0',\n 'left:0',\n 'width:5px',\n 'height:100%',\n 'cursor:col-resize',\n 'z-index:1',\n 'background:transparent',\n].join(';');\n\nconst HEADER_STYLE = [\n 'display:flex',\n 'align-items:center',\n 'gap:8px',\n 'padding:0 12px',\n 'height:36px',\n 'background:#252525',\n 'border-bottom:1px solid #444',\n 'flex-shrink:0',\n].join(';');\n\nconst ICON_BTN_STYLE = [\n 'padding:2px 7px',\n 'background:transparent',\n 'color:#888',\n 'border:1px solid #444',\n 'border-radius:4px',\n 'cursor:pointer',\n 'font-size:12px',\n].join(';');\n\nconst TAB_BAR_STYLE = [\n 'display:flex',\n 'background:#1a1a1a',\n 'border-bottom:1px solid #444',\n 'flex-shrink:0',\n].join(';');\n\nconst TAB_BTN_STYLE = [\n 'padding:5px 12px',\n 'background:transparent',\n 'color:#aaa',\n 'border:none',\n 'border-right:1px solid #333',\n 'cursor:pointer',\n 'font-family:monospace',\n 'font-size:11px',\n 'white-space:nowrap',\n].join(';');\n\nconst TAB_BTN_ACTIVE =\n ';background:#1e1e1e;color:#fff;border-bottom:2px solid #007acc;';\n\nconst TOOLBAR_STYLE = [\n 'display:flex',\n 'align-items:center',\n 'gap:4px',\n 'padding:5px 8px',\n 'background:#252525',\n 'border-bottom:1px solid #444',\n 'flex-shrink:0',\n].join(';');\n\nconst BTN_STYLE = [\n 'padding:3px 8px',\n 'background:#3a3a3a',\n 'color:#ddd',\n 'border:1px solid #555',\n 'border-radius:4px',\n 'cursor:pointer',\n 'font-family:monospace',\n 'font-size:11px',\n].join(';');\n\nconst LIST_STYLE = [\n 'width:140px',\n 'min-width:140px',\n 'overflow-y:auto',\n 'border-right:1px solid #333',\n 'padding:4px',\n 'display:flex',\n 'flex-direction:column',\n 'gap:2px',\n].join(';');\n\nconst LIST_ITEM_STYLE = [\n 'display:flex',\n 'align-items:center',\n 'gap:6px',\n 'padding:5px 6px',\n 'border-radius:4px',\n 'cursor:pointer',\n 'overflow:hidden',\n 'color:#ccc',\n].join(';');\n\nconst LIST_ITEM_ACTIVE =\n ';background:#007acc22;outline:1px solid #007acc;color:#fff;';\n\nconst FORM_STYLE = ['flex:1', 'overflow-y:auto', 'padding:10px 10px 16px'].join(\n ';',\n);\n\nconst INPUT_STYLE = [\n 'width:100%',\n 'background:#2a2a2a',\n 'border:1px solid #555',\n 'border-radius:3px',\n 'color:#ddd',\n 'padding:3px 5px',\n 'font-family:monospace',\n 'font-size:11px',\n 'box-sizing:border-box',\n].join(';');\n","/** Minimal sidebar interface used by TopBar for tab-aware buttons. */\ninterface ISidebar {\n show(): void;\n toggle(): void;\n activateTab(id: string): void;\n readonly isVisible: boolean;\n}\n\n/**\n * Slim top bar pinned at the top of the viewport.\n * Houses engine tool buttons (e.g. Material Editor toggle).\n */\nexport class TopBar {\n private root!: HTMLElement;\n\n private constructor() {}\n\n static mount(materialPanel: ISidebar): TopBar {\n const bar = new TopBar();\n bar.build(materialPanel);\n return bar;\n }\n\n unmount(): void {\n this.root?.remove();\n }\n\n private build(materialPanel: ISidebar): void {\n this.root = document.createElement('div');\n this.root.id = 'gl-top-bar';\n this.root.style.cssText = TOP_BAR_STYLE;\n\n // Left group – branding\n const brand = document.createElement('span');\n brand.textContent = 'GenesisGL';\n brand.style.cssText =\n 'font-weight:bold;color:#9cdcfe;letter-spacing:1px;margin-right:16px;';\n this.root.appendChild(brand);\n\n // Tool buttons\n this.root.appendChild(this.mkToggleBtn('🎨 Materials', materialPanel));\n\n document.body.prepend(this.root);\n\n // Push page content down so the bar doesn't overlay anything\n document.body.style.paddingTop = `${this.root.offsetHeight || 34}px`;\n }\n\n /** Add the Models tab button after the game has started. */\n addModelsButton(sidebar: ISidebar): void {\n const btn = document.createElement('button');\n btn.textContent = '🧠 Models';\n btn.style.cssText = BTN_STYLE;\n btn.onclick = () => {\n sidebar.show();\n sidebar.activateTab('models');\n btn.style.cssText = sidebar.isVisible ? BTN_ACTIVE_STYLE : BTN_STYLE;\n };\n this.root.appendChild(btn);\n }\n\n /** Add the Scene tab button after the game has started. */\n addSceneButton(sidebar: ISidebar): void {\n const btn = document.createElement('button');\n btn.textContent = '🌍 Scene';\n btn.style.cssText = BTN_STYLE;\n btn.onclick = () => {\n sidebar.show();\n sidebar.activateTab('scene');\n btn.style.cssText = sidebar.isVisible ? BTN_ACTIVE_STYLE : BTN_STYLE;\n };\n this.root.appendChild(btn);\n }\n\n private mkToggleBtn(label: string, panel: ISidebar): HTMLButtonElement {\n return this.mkPanelToggleBtn(label, panel);\n }\n\n private mkPanelToggleBtn(\n label: string,\n panel: { toggle(): void; isVisible: boolean },\n ): HTMLButtonElement {\n const btn = document.createElement('button');\n btn.textContent = label;\n btn.style.cssText = BTN_STYLE;\n btn.onclick = () => {\n panel.toggle();\n btn.style.cssText = panel.isVisible ? BTN_ACTIVE_STYLE : BTN_STYLE;\n };\n return btn;\n }\n}\n\n// ── Styles ────────────────────────────────────────────────────────\n\nconst TOP_BAR_STYLE = [\n 'position:fixed',\n 'top:0',\n 'left:0',\n 'right:0',\n 'height:32px',\n 'z-index:9999',\n 'display:flex',\n 'align-items:center',\n 'padding:0 12px',\n 'gap:6px',\n 'background:#1a1a1a',\n 'border-bottom:1px solid #444',\n 'font-family:monospace',\n 'font-size:12px',\n 'color:#ddd',\n 'box-shadow:0 2px 8px rgba(0,0,0,.5)',\n].join(';');\n\nconst BTN_STYLE = [\n 'padding:3px 10px',\n 'background:#2d2d2d',\n 'color:#ddd',\n 'border:1px solid #555',\n 'border-radius:4px',\n 'cursor:pointer',\n 'font-size:11px',\n 'font-family:monospace',\n].join(';');\n\nconst BTN_ACTIVE_STYLE = [\n 'padding:3px 10px',\n 'background:#007acc',\n 'color:#fff',\n 'border:1px solid #007acc',\n 'border-radius:4px',\n 'cursor:pointer',\n 'font-size:11px',\n 'font-family:monospace',\n].join(';');\n","import { EditorTab } from '../../EditorSidebar';\n\n/** Minimal interface: only the debug flag we need. */\ninterface IRenderer {\n debug: boolean;\n}\n\n/** Bounding box as stored on Model. */\ninterface AABB {\n min: [number, number, number];\n max: [number, number, number];\n}\n\n/** Minimal model shape required by the inspector. */\ninterface IModel {\n translation: [number, number, number];\n rotation: [number, number, number];\n scale: [number, number, number];\n boundingBox: AABB;\n}\n\n/** Minimal scene interface: just the keyed entry list. */\ninterface IScene {\n getEntries(): [string, IModel][];\n}\n\n/**\n * Model Inspector — rendered as a tab inside the {@link EditorSidebar}.\n *\n * Lifecycle:\n * – `buildContent(container)` builds the DOM once when the tab is activated.\n * – `onActivate()` enables `renderer.debug` and starts a 200 ms refresh loop.\n * – `onDeactivate()` disables `renderer.debug` and stops the refresh loop.\n * – `asTab()` returns an {@link EditorTab} descriptor ready for `sidebar.addTab()`.\n */\nexport class ModelsSection {\n private listEl: HTMLElement | null = null;\n private hitboxCheck: HTMLInputElement | null = null;\n private intervalId: ReturnType<typeof setInterval> | null = null;\n\n private constructor(\n private readonly renderer: IRenderer,\n private readonly scene: IScene,\n ) {}\n\n // ── Factory ──────────────────────────────────────────────────\n\n static create(renderer: IRenderer, scene: IScene): ModelsSection {\n return new ModelsSection(renderer, scene);\n }\n\n // ── Tab descriptor ───────────────────────────────────────────\n\n asTab(): EditorTab {\n return {\n id: 'models',\n label: '🧠 Models',\n buildContent: (c) => this.buildContent(c),\n onActivate: () => this.start(),\n onDeactivate: () => this.stop(),\n destroy: () => this.stop(),\n };\n }\n\n // ── Lifecycle ────────────────────────────────────────────────\n\n private start(): void {\n this.renderer.debug = true;\n if (this.hitboxCheck) this.hitboxCheck.checked = true;\n this.refresh();\n if (this.intervalId === null) {\n this.intervalId = setInterval(() => this.refresh(), 200);\n }\n }\n\n private stop(): void {\n this.renderer.debug = false;\n if (this.hitboxCheck) this.hitboxCheck.checked = false;\n if (this.intervalId !== null) {\n clearInterval(this.intervalId);\n this.intervalId = null;\n }\n }\n\n // ── Build ────────────────────────────────────────────────────\n\n private buildContent(container: HTMLElement): void {\n // ── Controls row\n const controls = mk('div', CONTROLS_STYLE);\n const hitboxRow = document.createElement('label');\n hitboxRow.style.cssText =\n 'display:flex;align-items:center;gap:6px;cursor:pointer;color:#ccc;font-size:11px;';\n this.hitboxCheck = document.createElement('input');\n this.hitboxCheck.type = 'checkbox';\n this.hitboxCheck.checked = this.renderer.debug;\n this.hitboxCheck.onchange = () => {\n this.renderer.debug = this.hitboxCheck!.checked;\n };\n hitboxRow.appendChild(this.hitboxCheck);\n const hitboxLbl = document.createElement('span');\n hitboxLbl.textContent = 'Show Hitboxes';\n hitboxRow.appendChild(hitboxLbl);\n controls.appendChild(hitboxRow);\n\n // ── Model list\n this.listEl = mk('div', LIST_STYLE);\n\n container.appendChild(controls);\n container.appendChild(this.listEl);\n }\n\n // ── Live refresh ─────────────────────────────────────────────\n\n private refresh(): void {\n if (!this.listEl) return;\n const entries = this.scene.getEntries();\n this.listEl.innerHTML = '';\n\n const heading = mk(\n 'div',\n 'color:#666;font-size:10px;letter-spacing:1px;padding:0 0 4px;',\n );\n heading.textContent = `MODELS (${entries.length})`;\n this.listEl.appendChild(heading);\n\n for (const [key, model] of entries) {\n const card = mk('div', CARD_STYLE);\n\n const nameEl = mk(\n 'div',\n 'font-weight:bold;color:#9cdcfe;margin-bottom:4px;',\n );\n nameEl.textContent = key;\n card.appendChild(nameEl);\n\n const t = model.translation;\n const r = model.rotation;\n const s = model.scale;\n const bb = model.boundingBox;\n const w = bb.max[0] - bb.min[0];\n const h = bb.max[1] - bb.min[1];\n const d = bb.max[2] - bb.min[2];\n\n card.appendChild(dataRow('pos', `${f(t[0])} ${f(t[1])} ${f(t[2])}`));\n card.appendChild(dataRow('rot', `${f(r[0])} ${f(r[1])} ${f(r[2])}`));\n card.appendChild(dataRow('scl', `${f(s[0])} ${f(s[1])} ${f(s[2])}`));\n card.appendChild(dataRow('bbox', `${f(w)}w ${f(h)}h ${f(d)}d`));\n\n this.listEl.appendChild(card);\n }\n }\n}\n\n// ── Helpers ───────────────────────────────────────────────────────\n\nfunction mk(\n tag: string,\n style = '',\n): HTMLElement & HTMLButtonElement & HTMLDivElement {\n const el = document.createElement(tag) as HTMLElement &\n HTMLButtonElement &\n HTMLDivElement;\n if (style) el.style.cssText = style;\n return el;\n}\n\nfunction f(n: number): string {\n return n.toFixed(2);\n}\n\nfunction dataRow(label: string, value: string): HTMLElement {\n const row = document.createElement('div');\n row.style.cssText = 'display:flex;gap:4px;line-height:1.6;';\n\n const lbl = document.createElement('span');\n lbl.style.cssText = 'color:#666;width:28px;flex-shrink:0;font-size:10px;';\n lbl.textContent = label;\n\n const val = document.createElement('span');\n val.style.cssText = 'color:#ccc;font-size:10px;';\n val.textContent = value;\n\n row.appendChild(lbl);\n row.appendChild(val);\n return row;\n}\n\n// ── Styles ────────────────────────────────────────────────────────\n\nconst CONTROLS_STYLE = [\n 'padding:6px 10px',\n 'background:#222',\n 'border-bottom:1px solid #333',\n 'flex-shrink:0',\n].join(';');\n\nconst LIST_STYLE = [\n 'overflow-y:auto',\n 'padding:8px',\n 'display:flex',\n 'flex-direction:column',\n 'gap:6px',\n].join(';');\n\nconst CARD_STYLE = [\n 'background:#252525',\n 'border:1px solid #333',\n 'border-radius:4px',\n 'padding:6px 8px',\n].join(';');\n"],"mappings":"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","names":["STORAGE_KEY","el","TOOLBAR_STYLE","BTN_STYLE","LIST_STYLE","FORM_STYLE","INPUT_STYLE","BTN_STYLE","mk","LIST_STYLE","CARD_STYLE","dataRow","f","el"]}
|
|
1
|
+
{"version":3,"sources":["../../src/Editor/sections/materials/MaterialSpec.ts","../../src/Editor/sections/materials/MaterialStore.ts","../../src/Editor/sections/scene/SceneSpec.ts","../../src/Editor/sections/scene/SceneStore.ts","../../src/Editor/sections/scene/SceneSection.ts","../../src/Editor/EditorSidebar.ts","../../src/Editor/TopBar.ts","../../src/Editor/sections/models/ModelsSection.ts"],"sourcesContent":["/** Plain, JSON-serialisable description of a material preset. */\nexport interface MaterialSpec {\n /** Unique identifier (crypto.randomUUID). */\n id: string;\n /** Human-readable name shown in the UI. */\n name: string;\n\n /** RGBA albedo / base colour [0–1]. */\n albedoColor: [number, number, number, number];\n /** RGB diffuse colour [0–1]. */\n diffuse: [number, number, number];\n /** RGB ambient colour [0–1]. */\n ambientColor: [number, number, number];\n /** RGB specular colour [0–1]. */\n specular: [number, number, number];\n\n /** Phong shininess exponent. */\n shininess: number;\n /** Opacity (d / Tr). */\n dissolve: number;\n\n /** Skip lighting calculations and render with raw albedo. */\n unlit: boolean;\n /** Render both front and back faces. */\n doubleSided: boolean;\n\n /** Optional public path to a texture image (relative to /public). */\n texturePath?: string;\n /** When true the texture wraps with GL_REPEAT instead of CLAMP_TO_EDGE. */\n textureRepeat?: boolean;\n /** Physics friction coefficient [0–1]. Defaults to 0.75 when omitted. */\n friction?: number;\n}\n\n/** Create a spec with sensible defaults. */\nexport function createDefaultSpec(name = 'New Material'): MaterialSpec {\n return {\n id: crypto.randomUUID(),\n name,\n albedoColor: [1, 1, 1, 1],\n diffuse: [1, 1, 1],\n ambientColor: [0.1, 0.1, 0.1],\n specular: [0.3, 0.3, 0.3],\n shininess: 64,\n dissolve: 1,\n unlit: false,\n doubleSided: false,\n friction: 0.3,\n };\n}\n","import { createDefaultSpec, MaterialSpec } from './MaterialSpec';\n\nconst STORAGE_KEY = 'genesisgl__material_presets';\n\ntype StoreListener = (specs: MaterialSpec[]) => void;\n\nexport interface MaterialStoreOptions {\n /**\n * URL / public-folder path to a JSON file that seeds the store on {@link MaterialStore.init}.\n * Example: `'data/materials.json'`\n *\n * The file is fetched once with `fetch()` during init. If the fetch succeeds its\n * contents supersede anything already in `localStorage`.\n */\n filePath?: string;\n}\n\n/**\n * Manages a collection of {@link MaterialSpec} presets.\n *\n * - Automatically persists to `localStorage` on every change (synchronous).\n * - Call {@link init} once at startup to seed from a configurable JSON file.\n * - Supports exporting / importing the whole collection as a `.json` file.\n */\nexport class MaterialStore {\n private specs = new Map<string, MaterialSpec>();\n private listeners: StoreListener[] = [];\n private readonly filePath: string | null;\n\n constructor(options: MaterialStoreOptions = {}) {\n this.filePath = options.filePath ?? null;\n // Seed from localStorage immediately so the store is usable before init().\n this.loadFromStorage();\n }\n\n /**\n * Asynchronously loads materials from the configured {@link MaterialStoreOptions.filePath}.\n * Call this once during app / resource initialisation (e.g. inside `loadResources`).\n *\n * The file data is merged on top of any localStorage data; conflicting IDs are\n * overwritten by the file version.\n */\n async init(): Promise<void> {\n if (!this.filePath) return;\n try {\n const res = await fetch(this.filePath);\n if (!res.ok) {\n console.warn(\n `[MaterialStore] Could not load \"${this.filePath}\" (${res.status})`,\n );\n return;\n }\n const items = (await res.json()) as MaterialSpec[];\n for (const spec of items) this.specs.set(spec.id, spec);\n // Sync localStorage so subsequent reloads don't need the fetch.\n this.persist();\n this.emit();\n } catch {\n console.warn(`[MaterialStore] Failed to fetch \"${this.filePath}\"`);\n }\n }\n\n // ── CRUD ────────────────────────────────────────────────────\n\n getAll(): MaterialSpec[] {\n return [...this.specs.values()];\n }\n\n get(id: string): MaterialSpec | undefined {\n return this.specs.get(id);\n }\n\n /** Add a brand-new spec and return it. */\n create(name?: string): MaterialSpec {\n const spec = createDefaultSpec(name);\n this.specs.set(spec.id, spec);\n this.persist();\n this.emit();\n void this.syncToServer();\n return spec;\n }\n\n /** Replace an existing spec (matched by id). */\n update(spec: MaterialSpec): void {\n if (!this.specs.has(spec.id)) return;\n this.specs.set(spec.id, { ...spec });\n this.persist();\n this.emit();\n void this.syncToServer();\n }\n\n /** Deep-clone a spec under a new id. */\n duplicate(id: string): MaterialSpec | undefined {\n const src = this.specs.get(id);\n if (!src) return undefined;\n const copy: MaterialSpec = {\n ...src,\n id: crypto.randomUUID(),\n name: `${src.name} (copy)`,\n albedoColor: [...src.albedoColor],\n diffuse: [...src.diffuse],\n ambientColor: [...src.ambientColor],\n specular: [...src.specular],\n };\n this.specs.set(copy.id, copy);\n this.persist();\n this.emit();\n void this.syncToServer();\n return copy;\n }\n\n delete(id: string): void {\n this.specs.delete(id);\n this.persist();\n this.emit();\n void this.syncToServer();\n }\n\n // ── Server sync ──────────────────────────────────────────────\n\n /**\n * Write the full collection to the server's `materials.json` via the\n * `PUT /api/materials` endpoint provided by the Vite dev plugin.\n * Silently no-ops if no `filePath` was configured.\n */\n async syncToServer(): Promise<boolean> {\n if (!this.filePath) return false;\n try {\n const res = await fetch('/api/materials', {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(this.getAll(), null, 2),\n });\n if (!res.ok) {\n console.warn(`[MaterialStore] Server sync failed (${res.status})`);\n }\n return res.ok;\n } catch {\n console.warn('[MaterialStore] syncToServer: network error');\n return false;\n }\n }\n\n // ── Persistence ──────────────────────────────────────────────\n\n private persist(): void {\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(this.getAll()));\n } catch {\n console.warn('[MaterialStore] Failed to write to localStorage');\n }\n }\n\n private loadFromStorage(): void {\n try {\n const raw = localStorage.getItem(STORAGE_KEY);\n if (!raw) return;\n const items = JSON.parse(raw) as unknown as MaterialSpec[];\n for (const spec of items) this.specs.set(spec.id, spec);\n } catch {\n console.warn('[MaterialStore] Failed to read from localStorage');\n }\n }\n\n // ── File I/O ─────────────────────────────────────────────────\n\n /** Download the full collection as a `.json` file (defaults to the configured filePath name). */\n async exportToFile(filename?: string): Promise<void> {\n const defaultName = this.filePath\n ? this.filePath.split('/').pop() ?? 'materials.json'\n : 'materials.json';\n const name = filename ?? defaultName;\n const json = JSON.stringify(this.getAll(), null, 2);\n const blob = new Blob([json], { type: 'application/json' });\n\n // Use File System Access API when available, fallback to <a download>\n if ('showSaveFilePicker' in window) {\n try {\n const handle = await (\n window as typeof window & {\n showSaveFilePicker: (\n opts: unknown,\n ) => Promise<FileSystemFileHandle>;\n }\n ).showSaveFilePicker({\n suggestedName: name,\n types: [\n { description: 'JSON', accept: { 'application/json': ['.json'] } },\n ],\n });\n const writable = await handle.createWritable();\n await writable.write(blob);\n await writable.close();\n return;\n } catch {\n // user cancelled or API unavailable — fall through\n }\n }\n\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = name;\n a.click();\n URL.revokeObjectURL(url);\n }\n\n /**\n * Open a file-picker, parse the JSON, and merge imported specs.\n * Existing specs with the same id are overwritten.\n */\n importFromFile(): Promise<void> {\n return new Promise((resolve) => {\n const input = document.createElement('input');\n input.type = 'file';\n input.accept = '.json,application/json';\n\n input.onchange = async () => {\n const file = input.files?.[0];\n if (!file) {\n resolve();\n return;\n }\n\n try {\n const text = await file.text();\n const items = JSON.parse(text) as unknown as MaterialSpec[];\n for (const spec of items) this.specs.set(spec.id, spec);\n this.persist();\n this.emit();\n } catch {\n console.error('[MaterialStore] Failed to parse imported file');\n }\n resolve();\n };\n\n input.click();\n });\n }\n\n // ── Subscriptions ────────────────────────────────────────────\n\n subscribe(fn: StoreListener): () => void {\n this.listeners.push(fn);\n return () => {\n this.listeners = this.listeners.filter((l) => l !== fn);\n };\n }\n\n private emit(): void {\n const all = this.getAll();\n for (const fn of this.listeners) fn(all);\n }\n}\n","import { Vector3 } from '../../../Core/domain/interfaces/Vectors';\n\n/** JSON-serialisable description of a single item placed in the scene. */\nexport interface SceneItemSpec {\n /** Unique identifier (crypto.randomUUID). */\n id: string;\n /** Human-readable label shown in the editor. */\n name: string;\n /**\n * Key used to look up the base model in the DI / resource container.\n * The model must have been loaded during resource initialisation.\n * Leave empty for procedurally generated interactive actors (e.g. spheres).\n */\n resourceKey: string;\n\n translation: Vector3;\n rotation: Vector3;\n scale: Vector3;\n\n /**\n * Custom AABB override relative to translation:\n * `[offsetX, offsetY, offsetZ, width, height, depth]`.\n * When `null` or omitted the model's auto-computed bbox is used.\n */\n bounds?: [number, number, number, number, number, number] | null;\n\n /** Whether this item participates in collision detection. Defaults to `true`. */\n collider?: boolean;\n\n /**\n * Optional material name (from `materials.json`) to override the model's\n * default material. Applied to all meshes in the model at placement time.\n */\n materialKey?: string | null;\n\n // ── Interactive physics fields ─────────────────────────────────────────\n\n /**\n * When `true` this item is a physics-simulated {@link InteractiveActor}.\n * Leave `resourceKey` empty to use a procedurally generated sphere shape.\n */\n interactive?: boolean;\n\n /** Sphere radius (world units). Only used when `interactive: true` and no `resourceKey`. Default `0.5`. */\n radius?: number;\n\n /** Mass in kg — affects impulse distribution in body-pair collisions. Default `1.0`. */\n mass?: number;\n\n /** Bounce coefficient 0–1. Higher = bouncier. Default `0.6` for sphere actors. */\n restitution?: number;\n}\n\n/** Top-level scene definition stored in `scenes.json`. */\nexport interface SceneSpec {\n /** World position where the player spawns. */\n playerSpawn: Vector3;\n /** All items in the scene — static actors and interactive physics bodies. */\n items: SceneItemSpec[];\n}\n\n/** Create a new scene item with sensible defaults. */\nexport function createDefaultSceneItem(\n name = 'New Item',\n resourceKey = '',\n): SceneItemSpec {\n return {\n id: crypto.randomUUID(),\n name,\n resourceKey,\n translation: [0, 0, 0],\n rotation: [0, 0, 0],\n scale: [1, 1, 1],\n bounds: null,\n collider: true,\n materialKey: null,\n };\n}\n\n/** Create an empty scene. */\nexport function createDefaultScene(): SceneSpec {\n return {\n playerSpawn: [0, 0, 0],\n items: [],\n };\n}\n\n// ── Multi-scene types ─────────────────────────────────────────\n\n/**\n * A named, addressable scene that can live inside a multi-scene project file.\n * Extends {@link SceneSpec} with a stable `id` and a human-readable `name`.\n */\nexport interface NamedScene extends SceneSpec {\n /** Stable unique identifier (crypto.randomUUID). */\n id: string;\n /** Human-readable label shown in the scene picker. */\n name: string;\n /**\n * When `true`, this is the scene the game loads at startup.\n * Exactly one scene in a {@link MultiSceneFile} should be active at a time.\n */\n isActive?: boolean;\n}\n\n/**\n * Top-level structure stored in a multi-scene JSON file (e.g. `scenes.json`).\n * Each entry in `scenes` is a fully self-contained {@link NamedScene}.\n */\nexport interface MultiSceneFile {\n scenes: NamedScene[];\n}\n\n/** Create a new named scene with sensible defaults. */\nexport function createDefaultNamedScene(\n name = 'Scene 1',\n isActive = false,\n): NamedScene {\n return { id: crypto.randomUUID(), name, isActive, ...createDefaultScene() };\n}\n\n/** Create an empty multi-scene file containing a single default scene (marked active). */\nexport function createDefaultMultiSceneFile(): MultiSceneFile {\n return { scenes: [createDefaultNamedScene('Scene 1', true)] };\n}\n","import {\n createDefaultMultiSceneFile,\n createDefaultNamedScene,\n MultiSceneFile,\n NamedScene,\n SceneItemSpec,\n SceneSpec,\n} from './SceneSpec';\n\nconst STORAGE_KEY = 'genesisgl__scenes';\n\n/** Called whenever the *active* scene's data changes. */\ntype StoreListener = (spec: SceneSpec) => void;\n/** Called whenever the scene list or the active-scene selection changes. */\ntype ScenesListener = (scenes: NamedScene[], activeId: string) => void;\n/** Called when the game-startup scene is toggled via {@link SceneStore.setActiveGameScene}. */\ntype GameSceneListener = (spec: SceneSpec) => void;\n\nexport interface SceneStoreOptions {\n /**\n * URL / public-folder path to a multi-scene JSON (`MultiSceneFile`)\n * that seeds the store on {@link SceneStore.init}.\n * @example `'data/scenes.json'`\n */\n scenesFilePath: string;\n}\n\n/**\n * Manages a collection of named scenes ({@link MultiSceneFile}).\n *\n * Back-compat: all single-scene mutators & readers still work — they\n * transparently delegate to whichever scene is currently active.\n *\n * Multi-scene extras:\n * - {@link getScenes} – list all scenes\n * - {@link getActiveSceneId} – which scene the editor is editing\n * - {@link setActiveScene} – switch which scene the editor is editing\n * - {@link getActiveGameSceneId} – which scene the game will load\n * - {@link setActiveGameScene} – toggle which scene the game will load\n * - {@link addScene} – create & activate a new scene\n * - {@link removeScene} – delete a scene (min 1 kept)\n * - {@link renameScene}\n * - {@link subscribeScenes} – react to scene-list / selection changes\n */\nexport class SceneStore {\n private multiScene: MultiSceneFile = createDefaultMultiSceneFile();\n private activeSceneId: string;\n private listeners: StoreListener[] = [];\n private scenesListeners: ScenesListener[] = [];\n private gameSceneListeners: GameSceneListener[] = [];\n private readonly scenesFilePath: string;\n\n constructor(options: SceneStoreOptions) {\n this.scenesFilePath = options.scenesFilePath;\n this.activeSceneId = this.multiScene.scenes[0].id;\n this.loadFromStorage();\n }\n\n // ── Initialisation ──────────────────────────────────────────\n\n async init(): Promise<void> {\n try {\n const res = await fetch(this.scenesFilePath);\n if (!res.ok) {\n console.warn(`[SceneStore] Could not load \"${this.scenesFilePath}\" (${res.status})`);\n return;\n }\n const data = (await res.json()) as unknown;\n this.loadData(data);\n this.persist();\n this.emit();\n this.emitScenes();\n } catch {\n console.warn(`[SceneStore] Failed to fetch \"${this.scenesFilePath}\"`);\n }\n }\n\n // ── Multi-scene management ───────────────────────────────────\n\n /** All scenes in the project. */\n getScenes(): NamedScene[] {\n return this.multiScene.scenes;\n }\n\n /** Id of the currently active scene. */\n getActiveSceneId(): string {\n return this.activeSceneId;\n }\n\n /** Switch which scene is being edited. */\n setActiveScene(id: string): void {\n if (!this.multiScene.scenes.find((s) => s.id === id)) return;\n this.activeSceneId = id;\n this.emit();\n this.emitScenes();\n }\n\n /** Create a new scene and make it active. Returns the new scene. */\n addScene(name = 'New Scene'): NamedScene {\n const scene = createDefaultNamedScene(name);\n this.multiScene.scenes.push(scene);\n this.activeSceneId = scene.id;\n this.persist();\n this.emit();\n this.emitScenes();\n void this.syncToServer();\n return scene;\n }\n\n /**\n * Delete a scene by id.\n * The last remaining scene is never deleted.\n */\n removeScene(id: string): void {\n if (this.multiScene.scenes.length <= 1) return;\n this.multiScene.scenes = this.multiScene.scenes.filter((s) => s.id !== id);\n if (this.activeSceneId === id) {\n this.activeSceneId = this.multiScene.scenes[0].id;\n }\n this.persist();\n this.emit();\n this.emitScenes();\n void this.syncToServer();\n }\n\n /** Rename a scene. */\n renameScene(id: string, name: string): void {\n const scene = this.multiScene.scenes.find((s) => s.id === id);\n if (!scene) return;\n scene.name = name;\n this.persist();\n this.emitScenes();\n void this.syncToServer();\n }\n\n /**\n * Returns the id of the scene flagged as the **game's** active scene\n * (the one that loads at runtime), or the first scene if none is flagged.\n */\n getActiveGameSceneId(): string {\n return (\n this.multiScene.scenes.find((s) => s.isActive)?.id ??\n this.multiScene.scenes[0].id\n );\n }\n\n /**\n * Set exactly one scene as the game's active scene.\n * All other scenes have their `isActive` flag removed.\n */\n setActiveGameScene(id: string): void {\n const target = this.multiScene.scenes.find((s) => s.id === id);\n if (!target) return;\n for (const s of this.multiScene.scenes) {\n s.isActive = s.id === id;\n }\n this.persist();\n this.emitScenes();\n this.emitGameScene();\n void this.syncToServer();\n }\n\n // ── Read (delegated to active scene) ────────────────────────\n\n get(): SceneSpec {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { id: _id, name: _name, isActive: _ia, ...spec } = this.activeScene;\n return spec as SceneSpec;\n }\n\n getItems(): SceneItemSpec[] {\n return this.activeScene.items;\n }\n\n getItem(id: string): SceneItemSpec | undefined {\n return this.activeScene.items.find((i) => i.id === id);\n }\n\n getPlayerSpawn(): [number, number, number] {\n return [...this.activeScene.playerSpawn] as [number, number, number];\n }\n\n // ── Mutations (delegated to active scene) ───────────────────\n\n setPlayerSpawn(x: number, y: number, z: number): void {\n this.activeScene.playerSpawn = [x, y, z];\n this.persist();\n this.emit();\n void this.syncToServer();\n }\n\n addItem(item: SceneItemSpec): void {\n this.activeScene.items.push(item);\n this.persist();\n this.emit();\n void this.syncToServer();\n }\n\n updateItem(item: SceneItemSpec): void {\n const idx = this.activeScene.items.findIndex((i) => i.id === item.id);\n if (idx === -1) return;\n this.activeScene.items[idx] = { ...item };\n this.persist();\n this.emit();\n void this.syncToServer();\n }\n\n deleteItem(id: string): void {\n this.activeScene.items = this.activeScene.items.filter((i) => i.id !== id);\n this.persist();\n this.emit();\n void this.syncToServer();\n }\n\n /** Replace the entire active scene definition. */\n setScene(spec: SceneSpec): void {\n Object.assign(this.activeScene, spec);\n this.persist();\n this.emit();\n void this.syncToServer();\n }\n\n // ── Server sync ──────────────────────────────────────────────\n\n async syncToServer(): Promise<boolean> {\n try {\n const res = await fetch('/api/scenes', {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(this.multiScene, null, 2),\n });\n if (!res.ok) {\n console.warn(`[SceneStore] Server sync failed (${res.status})`);\n }\n return res.ok;\n } catch {\n console.warn('[SceneStore] syncToServer: network error');\n return false;\n }\n }\n\n // ── Persistence ──────────────────────────────────────────────\n\n private persist(): void {\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(this.multiScene));\n } catch {\n console.warn('[SceneStore] Failed to write to localStorage');\n }\n }\n\n private loadFromStorage(): void {\n try {\n const raw = localStorage.getItem(STORAGE_KEY);\n if (!raw) return;\n this.loadData(JSON.parse(raw) as unknown);\n } catch {\n console.warn('[SceneStore] Failed to read from localStorage');\n }\n }\n\n private loadData(data: unknown): void {\n if (\n data !== null &&\n typeof data === 'object' &&\n Array.isArray((data as MultiSceneFile).scenes) &&\n (data as MultiSceneFile).scenes.length > 0\n ) {\n this.multiScene = data as MultiSceneFile;\n if (!this.multiScene.scenes.find((s) => s.id === this.activeSceneId)) {\n this.activeSceneId = this.multiScene.scenes[0].id;\n }\n }\n }\n\n // ── File I/O ─────────────────────────────────────────────────\n\n /** Export the full multi-scene file. */\n async exportToFile(filename = 'scenes.json'): Promise<void> {\n const json = JSON.stringify(this.multiScene, null, 2);\n const blob = new Blob([json], { type: 'application/json' });\n\n if ('showSaveFilePicker' in window) {\n try {\n const handle = await (\n window as typeof window & {\n showSaveFilePicker: (\n opts: unknown,\n ) => Promise<FileSystemFileHandle>;\n }\n ).showSaveFilePicker({\n suggestedName: filename,\n types: [\n { description: 'JSON', accept: { 'application/json': ['.json'] } },\n ],\n });\n const writable = await handle.createWritable();\n await writable.write(blob);\n await writable.close();\n return;\n } catch {\n // user cancelled — fall through\n }\n }\n\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = filename;\n a.click();\n URL.revokeObjectURL(url);\n }\n\n /** Import a multi-scene JSON file, replacing current data. */\n importFromFile(): Promise<void> {\n return new Promise((resolve) => {\n const input = document.createElement('input');\n input.type = 'file';\n input.accept = '.json,application/json';\n\n input.onchange = async () => {\n const file = input.files?.[0];\n if (!file) {\n resolve();\n return;\n }\n try {\n const text = await file.text();\n const data = JSON.parse(text) as unknown;\n this.loadData(data);\n this.persist();\n this.emit();\n this.emitScenes();\n } catch {\n console.error('[SceneStore] Failed to parse imported file');\n }\n resolve();\n };\n\n input.click();\n });\n }\n\n // ── Subscriptions ────────────────────────────────────────────\n\n /** Subscribe to active-scene data changes. */\n subscribe(fn: StoreListener): () => void {\n this.listeners.push(fn);\n return () => {\n this.listeners = this.listeners.filter((l) => l !== fn);\n };\n }\n\n /**\n * Subscribe to scene-list or active-scene-selection changes.\n * Fired when scenes are added/removed/renamed or the active scene switches.\n */\n subscribeScenes(fn: ScenesListener): () => void {\n this.scenesListeners.push(fn);\n return () => {\n this.scenesListeners = this.scenesListeners.filter((l) => l !== fn);\n };\n }\n\n /**\n * Subscribe to game-scene changes.\n * Fired only when {@link setActiveGameScene} is called — use this to reload\n * the running game world with the newly flagged scene's data.\n */\n subscribeGameScene(fn: GameSceneListener): () => void {\n this.gameSceneListeners.push(fn);\n return () => {\n this.gameSceneListeners = this.gameSceneListeners.filter((l) => l !== fn);\n };\n }\n\n // ── Private helpers ──────────────────────────────────────────\n\n private get activeScene(): NamedScene {\n return (\n this.multiScene.scenes.find((s) => s.id === this.activeSceneId) ??\n this.multiScene.scenes[0]\n );\n }\n\n private emit(): void {\n const spec = this.get();\n for (const fn of this.listeners) fn(spec);\n }\n\n private emitScenes(): void {\n const scenes = this.getScenes();\n const activeId = this.activeSceneId;\n for (const fn of this.scenesListeners) fn(scenes, activeId);\n }\n\n private emitGameScene(): void {\n const activeId = this.getActiveGameSceneId();\n const scene = this.multiScene.scenes.find((s) => s.id === activeId);\n if (!scene) return;\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { id: _id, name: _name, isActive: _ia, ...spec } = scene;\n for (const fn of this.gameSceneListeners) fn(spec as SceneSpec);\n }\n}\n","import { EditorTab } from '../../EditorSidebar';\nimport { createDefaultSceneItem, SceneItemSpec } from './SceneSpec';\nimport { SceneStore } from './SceneStore';\n\n/** Entry from models.json */\nexport interface ModelRegistryEntry {\n key: string;\n name: string;\n type: string;\n path?: string;\n description?: string;\n}\n\nexport interface SceneSectionOptions {\n /** URL to the models registry JSON file. */\n modelsFile?: string;\n /** Returns the list of material names currently available. */\n getMaterialNames?: () => string[];\n /** Renderer reference — used to toggle hitbox debug visualisation. */\n renderer?: { debug: boolean };\n}\n\n/**\n * Scene Editor — rendered as a tab inside the {@link EditorSidebar}.\n *\n * Lets the user:\n * – View / edit player spawn position.\n * – View / edit every scene item (translation, rotation, scale, bounds, collider).\n * – Add, duplicate, and delete items.\n * – Reload the game to apply changes.\n */\nexport class SceneSection {\n private root: HTMLElement | null = null;\n private listEl: HTMLElement | null = null;\n private selectedId: string | null = null;\n private formEl: HTMLElement | null = null;\n private unsub?: () => void;\n private unsubScenes?: () => void;\n private scenesBar: HTMLElement | null = null;\n private modelRegistry: ModelRegistryEntry[] = [];\n private readonly getMaterialNames: () => string[];\n private readonly modelsFile: string | null;\n private readonly renderer: { debug: boolean } | null;\n private hitboxCheck: HTMLInputElement | null = null;\n\n private constructor(\n private readonly store: SceneStore,\n options: SceneSectionOptions = {},\n ) {\n this.modelsFile = options.modelsFile ?? null;\n this.getMaterialNames = options.getMaterialNames ?? (() => []);\n this.renderer = options.renderer ?? null;\n }\n\n // ── Factory ──────────────────────────────────────────────────\n\n static create(\n store: SceneStore,\n options?: SceneSectionOptions,\n ): SceneSection {\n return new SceneSection(store, options);\n }\n\n // ── Tab descriptor ───────────────────────────────────────────\n\n asTab(): EditorTab {\n return {\n id: 'scene',\n label: '🌍 Scene',\n buildContent: (c) => this.buildContent(c),\n onActivate: () => this.onActivate(),\n onDeactivate: () => this.onDeactivate(),\n destroy: () => {\n this.unsub?.();\n this.unsubScenes?.();\n },\n };\n }\n\n // ── Lifecycle ────────────────────────────────────────────────\n\n private onActivate(): void {\n // Load model registry if not loaded yet\n if (this.modelRegistry.length === 0 && this.modelsFile) {\n void fetch(this.modelsFile)\n .then((r) => r.json())\n .then((data: ModelRegistryEntry[]) => {\n this.modelRegistry = data;\n this.refreshForm(); // re-render form with dropdown populated\n })\n .catch(() =>\n console.warn('[SceneSection] Could not load models registry'),\n );\n }\n this.refreshList();\n this.refreshForm();\n }\n\n private onDeactivate(): void {\n /* nothing for now */\n }\n\n // ── Build ────────────────────────────────────────────────────\n\n private buildContent(container: HTMLElement): void {\n this.root = container;\n\n // ── Scenes picker bar (tabs for each named scene)\n this.scenesBar = mk('div', SCENES_BAR_STYLE);\n this.refreshScenesBar();\n container.appendChild(this.scenesBar);\n\n this.unsubScenes = this.store.subscribeScenes(() => this.refreshScenesBar());\n\n // ── Toolbar\n const toolbar = mk('div', TOOLBAR_STYLE);\n toolbar.appendChild(\n this.mkBtn('+ Item', () => this.onAdd(), 'Add scene item'),\n );\n toolbar.appendChild(\n this.mkBtn('❑', () => this.onDuplicate(), 'Duplicate selected'),\n );\n toolbar.appendChild(\n this.mkBtn('🗑', () => this.onDelete(), 'Delete selected'),\n );\n const reloadBtn = mk(\n 'button',\n BTN_STYLE + ';margin-left:auto;color:#6cf;border-color:#446;',\n );\n reloadBtn.textContent = '🔄 Reload Game';\n reloadBtn.title = 'Sync JSON then reload game to apply changes';\n reloadBtn.onclick = () => location.reload();\n toolbar.appendChild(reloadBtn);\n\n // ── Hitbox toggle\n if (this.renderer) {\n const hitboxLabel = document.createElement('label');\n hitboxLabel.style.cssText =\n 'display:flex;align-items:center;gap:4px;cursor:pointer;color:#ccc;font-size:10px;margin-left:6px;';\n this.hitboxCheck = document.createElement('input');\n this.hitboxCheck.type = 'checkbox';\n this.hitboxCheck.checked = this.renderer.debug;\n this.hitboxCheck.onchange = () => {\n if (this.renderer) {\n this.renderer.debug = this.hitboxCheck!.checked;\n }\n };\n hitboxLabel.appendChild(this.hitboxCheck);\n const hitboxText = document.createElement('span');\n hitboxText.textContent = 'Hitboxes';\n hitboxLabel.appendChild(hitboxText);\n toolbar.appendChild(hitboxLabel);\n }\n\n // ── Body (list + form)\n const body = mk('div', 'display:flex;flex:1;overflow:hidden;');\n this.listEl = mk('div', LIST_STYLE);\n this.formEl = mk('div', FORM_STYLE);\n body.appendChild(this.listEl);\n body.appendChild(this.formEl);\n\n container.appendChild(toolbar);\n container.appendChild(body);\n\n this.unsub = this.store.subscribe(() => {\n this.refreshList();\n this.refreshForm();\n });\n\n this.refreshList();\n }\n\n // ── Scenes bar ──────────────────────────────────────────────\n\n private refreshScenesBar(): void {\n if (!this.scenesBar) return;\n this.scenesBar.innerHTML = '';\n\n const scenes = this.store.getScenes();\n const activeId = this.store.getActiveSceneId();\n\n // Tab buttons — one per scene\n for (const scene of scenes) {\n const isEditorActive = scene.id === activeId;\n const isGameActive = !!scene.isActive;\n\n const tabWrap = mk('div', 'display:flex;align-items:stretch;gap:2px;');\n\n const tab = mk(\n 'button',\n SCENE_TAB_STYLE + (isEditorActive ? SCENE_TAB_ACTIVE : ''),\n );\n tab.textContent = scene.name;\n tab.title = `Switch to \"${scene.name}\"`;\n tab.onclick = () => {\n this.selectedId = null;\n this.store.setActiveScene(scene.id);\n this.refreshList();\n this.refreshForm();\n };\n\n // Double-click to rename inline\n tab.ondblclick = (e) => {\n e.preventDefault();\n const newName = prompt('Rename scene:', scene.name);\n if (newName && newName.trim()) {\n this.store.renameScene(scene.id, newName.trim());\n }\n };\n\n tabWrap.appendChild(tab);\n\n // ▶ Game-active toggle\n const playBtn = mk(\n 'button',\n SCENE_PLAY_BTN_STYLE + (isGameActive ? SCENE_PLAY_BTN_ACTIVE : ''),\n );\n playBtn.textContent = '▶';\n playBtn.title = isGameActive\n ? 'This scene is loaded by the game (click another to change)'\n : `Set \"${scene.name}\" as the game’s startup scene`;\n playBtn.onclick = (e) => {\n e.stopPropagation();\n this.store.setActiveGameScene(scene.id);\n };\n tabWrap.appendChild(playBtn);\n\n this.scenesBar.appendChild(tabWrap);\n }\n\n // Spacer\n const spacer = mk('div', 'flex:1;');\n this.scenesBar.appendChild(spacer);\n\n // + Add scene\n const addBtn = mk('button', SCENE_BAR_BTN_STYLE);\n addBtn.textContent = '+';\n addBtn.title = 'Add new scene';\n addBtn.onclick = () => {\n const name = prompt('New scene name:', `Scene ${scenes.length + 1}`);\n if (name && name.trim()) {\n this.selectedId = null;\n this.store.addScene(name.trim());\n this.refreshList();\n this.refreshForm();\n }\n };\n this.scenesBar.appendChild(addBtn);\n\n // ✏️ Rename active scene\n const renameBtn = mk('button', SCENE_BAR_BTN_STYLE);\n renameBtn.textContent = '✏️';\n renameBtn.title = 'Rename active scene';\n renameBtn.onclick = () => {\n const current = scenes.find((s) => s.id === activeId);\n if (!current) return;\n const newName = prompt('Rename scene:', current.name);\n if (newName && newName.trim()) {\n this.store.renameScene(activeId, newName.trim());\n }\n };\n this.scenesBar.appendChild(renameBtn);\n\n // 🗑 Delete active scene (disabled when only 1 scene)\n const delBtn = mk('button', SCENE_BAR_BTN_STYLE);\n delBtn.textContent = '🗑';\n delBtn.title = scenes.length <= 1 ? 'Cannot delete the last scene' : 'Delete active scene';\n delBtn.disabled = scenes.length <= 1;\n delBtn.style.opacity = scenes.length <= 1 ? '0.35' : '1';\n delBtn.onclick = () => {\n const current = scenes.find((s) => s.id === activeId);\n if (!current) return;\n if (!confirm(`Delete scene \"${current.name}\"?`)) return;\n this.selectedId = null;\n this.store.removeScene(activeId);\n this.refreshList();\n this.refreshForm();\n };\n this.scenesBar.appendChild(delBtn);\n }\n\n // ── List ─────────────────────────────────────────────────────\n\n private refreshList(): void {\n if (!this.listEl) return;\n this.listEl.innerHTML = '';\n\n // ── Player Spawn card (always on top)\n const spawn = this.store.getPlayerSpawn();\n const spawnCard = mk('div', CARD_STYLE);\n spawnCard.style.borderLeft = '3px solid #e8a';\n const spawnLabel = mk(\n 'div',\n 'font-weight:bold;color:#e8a;margin-bottom:2px;font-size:11px;',\n );\n spawnLabel.textContent = '🧑 Player Spawn';\n spawnCard.appendChild(spawnLabel);\n spawnCard.appendChild(\n dataRow('pos', `${f(spawn[0])} ${f(spawn[1])} ${f(spawn[2])}`),\n );\n spawnCard.style.cursor = 'pointer';\n spawnCard.onclick = () => {\n this.selectedId = '__player_spawn__';\n this.refreshList();\n this.refreshForm();\n };\n if (this.selectedId === '__player_spawn__') {\n spawnCard.style.background = '#2a2d3a';\n }\n this.listEl.appendChild(spawnCard);\n\n // ── Separator\n const sep = mk('div', 'height:1px;background:#333;margin:6px 0;');\n this.listEl.appendChild(sep);\n\n // ── Scene Items\n const heading = mk(\n 'div',\n 'color:#666;font-size:10px;letter-spacing:1px;padding:0 0 4px;',\n );\n const items = this.store.getItems();\n heading.textContent = `SCENE ITEMS (${items.length})`;\n this.listEl.appendChild(heading);\n\n for (const item of items) {\n const active = item.id === this.selectedId;\n const card = mk('div', CARD_STYLE);\n if (active) card.style.background = '#2a2d3a';\n card.style.cursor = 'pointer';\n card.onclick = () => {\n this.selectedId = item.id;\n // Auto-show hitboxes when selecting a model\n if (this.renderer) {\n this.renderer.debug = true;\n if (this.hitboxCheck) this.hitboxCheck.checked = true;\n }\n this.refreshList();\n this.refreshForm();\n };\n\n const cardHeader = mk('div', 'display:flex;align-items:center;gap:4px;margin-bottom:2px;');\n const typeIcon = mk('span', 'font-size:10px;');\n typeIcon.textContent = item.interactive ? '⚡' : '📦';\n const nameEl = mk('div', 'font-weight:bold;color:#9cdcfe;font-size:11px;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;');\n nameEl.textContent = item.name || '(unnamed)';\n cardHeader.appendChild(typeIcon);\n cardHeader.appendChild(nameEl);\n if (item.interactive) {\n const badge = mk('span', 'font-size:8px;padding:1px 4px;border-radius:2px;background:#2a3a1a;color:#8c8;border:1px solid #4a7040;flex-shrink:0;');\n badge.textContent = 'PHY';\n cardHeader.appendChild(badge);\n }\n card.appendChild(cardHeader);\n\n if (item.resourceKey) {\n card.appendChild(dataRow('res', item.resourceKey));\n }\n card.appendChild(\n dataRow(\n 'pos',\n `${f(item.translation[0])} ${f(item.translation[1])} ${f(item.translation[2])}`,\n ),\n );\n card.appendChild(\n dataRow(\n 'scl',\n `${f(item.scale[0])} ${f(item.scale[1])} ${f(item.scale[2])}`,\n ),\n );\n\n this.listEl.appendChild(card);\n }\n }\n\n // ── Form ─────────────────────────────────────────────────────\n\n private refreshForm(): void {\n if (!this.formEl) return;\n this.formEl.innerHTML = '';\n\n if (this.selectedId === '__player_spawn__') {\n this.buildSpawnForm(this.formEl);\n return;\n }\n\n const item = this.selectedId\n ? this.store.getItem(this.selectedId)\n : undefined;\n if (!item) {\n const hint = mk('div', 'color:#666;padding:8px;font-size:11px;');\n hint.textContent = 'Select an item to edit';\n this.formEl.appendChild(hint);\n return;\n }\n\n this.buildItemForm(this.formEl, item);\n }\n\n private buildSpawnForm(container: HTMLElement): void {\n const spawn = this.store.getPlayerSpawn();\n const title = mk(\n 'div',\n 'font-weight:bold;color:#e8a;padding:0 0 6px;font-size:12px;',\n );\n title.textContent = '🧑 Player Spawn';\n container.appendChild(title);\n\n container.appendChild(\n this.vec3Row('Position', spawn, (v) => {\n this.store.setPlayerSpawn(v[0], v[1], v[2]);\n }),\n );\n }\n\n private buildItemForm(container: HTMLElement, item: SceneItemSpec): void {\n // ── Title bar ─────────────────────────────────────────────\n const titleBar = mk(\n 'div',\n 'display:flex;align-items:center;gap:8px;padding:0 0 10px;border-bottom:1px solid #333;margin-bottom:4px;',\n );\n const typeIcon = mk('span', 'font-size:16px;');\n typeIcon.textContent = item.interactive ? '⚡' : '📦';\n const titleText = mk(\n 'div',\n 'font-weight:bold;color:#9cdcfe;font-size:13px;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;',\n );\n titleText.textContent = item.name || '(unnamed)';\n const typeBadge = mk(\n 'span',\n 'font-size:9px;padding:2px 6px;border-radius:3px;font-family:monospace;flex-shrink:0;' +\n (item.interactive\n ? 'background:#2a3a1a;color:#8c8;border:1px solid #4a7040;'\n : 'background:#1a1a2a;color:#88a;border:1px solid #445;'),\n );\n typeBadge.textContent = item.interactive ? 'PHYSICS' : 'STATIC';\n titleBar.appendChild(typeIcon);\n titleBar.appendChild(titleText);\n titleBar.appendChild(typeBadge);\n container.appendChild(titleBar);\n\n // ── IDENTITY ──────────────────────────────────────────────\n container.appendChild(this.sectionHeader('Identity', '🏷'));\n\n container.appendChild(\n this.textRow('Name', item.name, (v) => {\n this.store.updateItem({ ...item, name: v });\n }),\n );\n\n const modelOptions = this.modelRegistry.map((m) => ({\n value: m.key,\n label: `${m.name} (${m.type})`,\n }));\n container.appendChild(\n this.selectRow('Resource', item.resourceKey, modelOptions, (v) => {\n this.store.updateItem({ ...item, resourceKey: v });\n }),\n );\n\n // ── TRANSFORM ─────────────────────────────────────────────\n container.appendChild(this.sectionHeader('Transform', '📐'));\n\n container.appendChild(\n this.vec3Row(\n 'Position',\n [...item.translation] as [number, number, number],\n (v) => {\n this.store.updateItem({ ...item, translation: v });\n },\n ),\n );\n container.appendChild(\n this.vec3Row(\n 'Rotation',\n [...item.rotation] as [number, number, number],\n (v) => {\n this.store.updateItem({ ...item, rotation: v });\n },\n ),\n );\n container.appendChild(\n this.vec3Row(\n 'Scale',\n [...item.scale] as [number, number, number],\n (v) => {\n this.store.updateItem({ ...item, scale: v });\n },\n ),\n );\n\n // ── RENDERING ─────────────────────────────────────────────\n container.appendChild(this.sectionHeader('Rendering', '🎨'));\n\n const matNames = this.getMaterialNames();\n const matOptions = [\n { value: '', label: '(default)' },\n ...matNames.map((n) => ({ value: n, label: n })),\n ];\n container.appendChild(\n this.selectRow('Material', item.materialKey ?? '', matOptions, (v) => {\n this.store.updateItem({ ...item, materialKey: v || null });\n }),\n );\n container.appendChild(\n this.checkRow('Collider', item.collider !== false, (on) => {\n this.store.updateItem({ ...item, collider: on });\n }),\n );\n\n // ── BOUNDS OVERRIDE ────────────────────────────────────────\n container.appendChild(this.sectionHeader('Bounds Override', '📏'));\n\n container.appendChild(\n this.checkRow('Custom', item.bounds != null, (on) => {\n this.store.updateItem({\n ...item,\n bounds: on ? [0, 0, 0, 1, 1, 1] : null,\n });\n }),\n );\n if (item.bounds) {\n const b = item.bounds;\n const hint = mk(\n 'div',\n 'color:#555;font-size:9px;margin:-4px 0 6px 76px;font-family:monospace;',\n );\n hint.textContent = 'offset (x y z) + size (w h d)';\n container.appendChild(hint);\n container.appendChild(\n this.vec3Row('Offset', [b[0], b[1], b[2]], (v) => {\n this.store.updateItem({\n ...item,\n bounds: [v[0], v[1], v[2], b[3], b[4], b[5]],\n });\n }),\n );\n container.appendChild(\n this.vec3Row('Size', [b[3], b[4], b[5]], (v) => {\n this.store.updateItem({\n ...item,\n bounds: [b[0], b[1], b[2], v[0], v[1], v[2]],\n });\n }),\n );\n }\n\n // ── PHYSICS ───────────────────────────────────────────────\n container.appendChild(this.sectionHeader('Physics', '⚡'));\n\n container.appendChild(\n this.checkRow('Interactive', !!item.interactive, (on) => {\n this.store.updateItem({\n ...item,\n interactive: on,\n radius: on ? (item.radius ?? 0.5) : item.radius,\n mass: on ? (item.mass ?? 1.0) : item.mass,\n restitution: on ? (item.restitution ?? 0.6) : item.restitution,\n });\n }),\n );\n\n if (item.interactive) {\n const physHint = mk(\n 'div',\n 'color:#555;font-size:9px;margin:-4px 0 6px 76px;font-family:monospace;',\n );\n physHint.textContent =\n 'leave resource empty to auto-generate a sphere mesh';\n container.appendChild(physHint);\n\n container.appendChild(\n this.numberRow(\n 'Radius',\n item.radius ?? 0.5,\n { step: 0.05, min: 0.01 },\n (v) => {\n this.store.updateItem({ ...item, radius: v });\n },\n ),\n );\n container.appendChild(\n this.numberRow(\n 'Mass',\n item.mass ?? 1.0,\n { step: 0.1, min: 0.01 },\n (v) => {\n this.store.updateItem({ ...item, mass: v });\n },\n ),\n );\n container.appendChild(\n this.numberRow(\n 'Restitution',\n item.restitution ?? 0.6,\n { step: 0.05, min: 0, max: 1 },\n (v) => {\n this.store.updateItem({ ...item, restitution: v });\n },\n ),\n );\n }\n }\n\n // ── CRUD actions ─────────────────────────────────────────────\n\n private onAdd(): void {\n const item = createDefaultSceneItem();\n this.store.addItem(item);\n this.selectedId = item.id;\n }\n\n private onDuplicate(): void {\n if (!this.selectedId || this.selectedId === '__player_spawn__') return;\n const src = this.store.getItem(this.selectedId);\n if (!src) return;\n const copy: SceneItemSpec = {\n ...src,\n id: crypto.randomUUID(),\n name: `${src.name} (copy)`,\n translation: [...src.translation] as [number, number, number],\n rotation: [...src.rotation] as [number, number, number],\n scale: [...src.scale] as [number, number, number],\n bounds: src.bounds\n ? ([...src.bounds] as [number, number, number, number, number, number])\n : null,\n };\n this.store.addItem(copy);\n this.selectedId = copy.id;\n }\n\n private onDelete(): void {\n if (!this.selectedId || this.selectedId === '__player_spawn__') return;\n this.store.deleteItem(this.selectedId);\n this.selectedId = null;\n }\n\n // ── Input helpers ────────────────────────────────────────────\n\n private sectionHeader(label: string, icon = ''): HTMLElement {\n const wrap = mk('div', SECTION_HEADER_STYLE);\n if (icon) {\n const ico = mk('span', 'font-size:11px;');\n ico.textContent = icon;\n wrap.appendChild(ico);\n }\n const lbl = mk(\n 'span',\n 'color:#666;font-size:9px;letter-spacing:1.5px;font-family:monospace;text-transform:uppercase;',\n );\n lbl.textContent = label;\n wrap.appendChild(lbl);\n return wrap;\n }\n\n private numberRow(\n label: string,\n value: number,\n opts: { step?: number; min?: number; max?: number } = {},\n onChange: (v: number) => void,\n ): HTMLElement {\n const row = mk('div', ROW_STYLE);\n const lbl = mk('div', LABEL_STYLE);\n lbl.textContent = label;\n row.appendChild(lbl);\n\n const input = document.createElement('input');\n input.type = 'number';\n input.step = String(opts.step ?? 0.1);\n if (opts.min !== undefined) input.min = String(opts.min);\n if (opts.max !== undefined) input.max = String(opts.max);\n input.value = String(value);\n input.style.cssText = INPUT_STYLE + ';width:80px;';\n input.onchange = () => onChange(parseFloat(input.value) || 0);\n row.appendChild(input);\n return row;\n }\n\n private vec3Row(\n label: string,\n values: [number, number, number],\n onChange: (v: [number, number, number]) => void,\n ): HTMLElement {\n const row = mk('div', ROW_STYLE);\n const lbl = mk('div', LABEL_STYLE);\n lbl.textContent = label;\n row.appendChild(lbl);\n\n const group = mk('div', 'display:flex;gap:4px;');\n const labels = ['X', 'Y', 'Z'];\n\n for (let i = 0; i < 3; i++) {\n const wrap = mk('div', 'display:flex;flex-direction:column;flex:1;');\n const axisLbl = mk('div', 'color:#666;font-size:9px;text-align:center;');\n axisLbl.textContent = labels[i];\n const input = document.createElement('input');\n input.type = 'number';\n input.step = '0.1';\n input.value = String(values[i]);\n input.style.cssText = INPUT_STYLE;\n input.onchange = () => {\n const v = [...values] as [number, number, number];\n v[i] = parseFloat(input.value) || 0;\n onChange(v);\n };\n wrap.appendChild(axisLbl);\n wrap.appendChild(input);\n group.appendChild(wrap);\n }\n\n row.appendChild(group);\n return row;\n }\n\n private textRow(\n label: string,\n value: string,\n onChange: (v: string) => void,\n ): HTMLElement {\n const row = mk('div', ROW_STYLE);\n const lbl = mk('div', LABEL_STYLE);\n lbl.textContent = label;\n row.appendChild(lbl);\n\n const input = document.createElement('input');\n input.type = 'text';\n input.value = value;\n input.style.cssText = INPUT_STYLE + ';flex:1;';\n input.onchange = () => onChange(input.value);\n row.appendChild(input);\n return row;\n }\n\n private selectRow(\n label: string,\n value: string,\n options: { value: string; label: string }[],\n onChange: (v: string) => void,\n ): HTMLElement {\n const row = mk('div', ROW_STYLE);\n const lbl = mk('div', LABEL_STYLE);\n lbl.textContent = label;\n row.appendChild(lbl);\n\n const select = document.createElement('select');\n select.style.cssText = INPUT_STYLE + ';flex:1;';\n for (const opt of options) {\n const o = document.createElement('option');\n o.value = opt.value;\n o.textContent = opt.label;\n if (opt.value === value) o.selected = true;\n select.appendChild(o);\n }\n select.onchange = () => onChange(select.value);\n row.appendChild(select);\n return row;\n }\n\n private checkRow(\n label: string,\n checked: boolean,\n onChange: (v: boolean) => void,\n ): HTMLElement {\n const row = mk('div', ROW_STYLE + ';align-items:center;');\n const lbl = mk('div', LABEL_STYLE);\n lbl.textContent = label;\n row.appendChild(lbl);\n\n const input = document.createElement('input');\n input.type = 'checkbox';\n input.checked = checked;\n input.onchange = () => onChange(input.checked);\n row.appendChild(input);\n return row;\n }\n\n private mkBtn(\n text: string,\n onClick: () => void,\n title: string,\n ): HTMLButtonElement {\n const btn = document.createElement('button');\n btn.textContent = text;\n btn.title = title;\n btn.style.cssText = BTN_STYLE;\n btn.onclick = onClick;\n return btn;\n }\n}\n\n// ── Helpers ───────────────────────────────────────────────────────\n\nfunction mk(\n tag: string,\n style = '',\n): HTMLElement & HTMLButtonElement & HTMLDivElement {\n const el = document.createElement(tag) as HTMLElement &\n HTMLButtonElement &\n HTMLDivElement;\n if (style) el.style.cssText = style;\n return el;\n}\n\nfunction f(n: number): string {\n return n.toFixed(2);\n}\n\nfunction dataRow(label: string, value: string): HTMLElement {\n const row = document.createElement('div');\n row.style.cssText = 'display:flex;gap:4px;line-height:1.6;';\n\n const lbl = document.createElement('span');\n lbl.style.cssText = 'color:#666;width:28px;flex-shrink:0;font-size:10px;';\n lbl.textContent = label;\n\n const val = document.createElement('span');\n val.style.cssText = 'color:#ccc;font-size:10px;';\n val.textContent = value;\n\n row.appendChild(lbl);\n row.appendChild(val);\n return row;\n}\n\n// ── Styles ────────────────────────────────────────────────────────\n\nconst TOOLBAR_STYLE = [\n 'display:flex',\n 'gap:6px',\n 'padding:6px 10px',\n 'background:#222',\n 'border-bottom:1px solid #333',\n 'flex-shrink:0',\n].join(';');\n\nconst SCENES_BAR_STYLE = [\n 'display:flex',\n 'align-items:center',\n 'gap:4px',\n 'padding:4px 8px',\n 'background:#181818',\n 'border-bottom:1px solid #333',\n 'flex-shrink:0',\n 'overflow-x:auto',\n].join(';');\n\nconst SCENE_TAB_STYLE = [\n 'background:#252525',\n 'color:#aaa',\n 'border:1px solid #444',\n 'border-radius:4px 4px 0 0',\n 'padding:3px 10px',\n 'cursor:pointer',\n 'font-size:10px',\n 'font-family:monospace',\n 'white-space:nowrap',\n].join(';');\n\nconst SCENE_TAB_ACTIVE =\n ';background:#2a2d3a;color:#9cdcfe;border-color:#5577aa;border-bottom-color:#2a2d3a;';\n\nconst SCENE_PLAY_BTN_STYLE = [\n 'background:#252525',\n 'color:#555',\n 'border:1px solid #444',\n 'border-radius:0 4px 0 0',\n 'padding:3px 6px',\n 'cursor:pointer',\n 'font-size:9px',\n 'font-family:monospace',\n 'white-space:nowrap',\n 'line-height:1',\n].join(';');\n\nconst SCENE_PLAY_BTN_ACTIVE =\n ';background:#1a3a1a;color:#4ec94e;border-color:#3a7a3a;';\n\nconst SCENE_BAR_BTN_STYLE = [\n 'background:transparent',\n 'color:#888',\n 'border:1px solid #444',\n 'border-radius:3px',\n 'padding:2px 6px',\n 'cursor:pointer',\n 'font-size:11px',\n 'font-family:monospace',\n 'flex-shrink:0',\n].join(';');\n\nconst BTN_STYLE = [\n 'background:#2a2a2a',\n 'color:#ccc',\n 'border:1px solid #555',\n 'border-radius:4px',\n 'padding:3px 10px',\n 'cursor:pointer',\n 'font-size:11px',\n 'font-family:monospace',\n].join(';');\n\nconst LIST_STYLE = [\n 'width:220px',\n 'overflow-y:auto',\n 'padding:8px',\n 'border-right:1px solid #333',\n 'flex-shrink:0',\n].join(';');\n\nconst FORM_STYLE = ['flex:1', 'overflow-y:auto', 'padding:10px'].join(';');\n\nconst CARD_STYLE = [\n 'background:#1e1e1e',\n 'border:1px solid #333',\n 'border-radius:4px',\n 'padding:6px 8px',\n 'margin-bottom:4px',\n 'font-family:monospace',\n 'font-size:10px',\n].join(';');\n\nconst SECTION_HEADER_STYLE = [\n 'display:flex',\n 'align-items:center',\n 'gap:6px',\n 'margin:14px 0 6px',\n 'padding-bottom:4px',\n 'border-bottom:1px solid #2a2a2a',\n].join(';');\n\nconst ROW_STYLE = ['display:flex', 'gap:6px', 'margin-bottom:8px'].join(';');\n\nconst LABEL_STYLE = [\n 'color:#888',\n 'font-size:11px',\n 'width:70px',\n 'flex-shrink:0',\n 'padding-top:2px',\n].join(';');\n\nconst INPUT_STYLE = [\n 'background:#1a1a1a',\n 'color:#ccc',\n 'border:1px solid #444',\n 'border-radius:3px',\n 'padding:3px 5px',\n 'font-size:11px',\n 'font-family:monospace',\n 'width:60px',\n 'outline:none',\n].join(';');\n","import { MaterialSpec } from './sections/materials/MaterialSpec';\nimport { MaterialStore } from './sections/materials/MaterialStore';\n\ntype Vec3Field = 'diffuse' | 'ambientColor' | 'specular';\n\nexport interface EditorTab {\n id: string;\n /** Label shown on the tab button. */\n label: string;\n /** Called once to populate the tab's content container. */\n buildContent: (container: HTMLElement) => void;\n /** Called each time the tab becomes the active, visible tab. */\n onActivate?: () => void;\n /** Called each time the tab is hidden (tab switch or sidebar hide). */\n onDeactivate?: () => void;\n /** Optional cleanup called when the sidebar is unmounted. */\n destroy?: () => void;\n}\n\n/**\n * Fixed right-side editor sidebar.\n *\n * - Hosts a tab strip so new features can be added via {@link addTab}.\n * - First tab is the Material Editor (colour preview swatches + full form).\n * - Every store mutation auto-syncs to `materials.json` via the Vite dev plugin.\n * - \"🔄 Reload Game\" triggers `location.reload()` to pick up JSON changes.\n */\nexport class EditorSidebar {\n private root!: HTMLElement;\n private tabBar!: HTMLElement;\n private contentArea!: HTMLElement;\n private tabs: EditorTab[] = [];\n private activeTabId: string | null = null;\n\n // material panel state\n private listEl!: HTMLElement;\n private formEl!: HTMLElement;\n private selectedId: string | null = null;\n private unsubMaterials?: () => void;\n\n // drag-resize state\n private _sidebarWidth = 520;\n private _dragging = false;\n\n // layout mode: 'absolute' overlays, 'shared' shrinks viewport\n private _layoutMode: 'absolute' | 'shared' = 'absolute';\n private _layoutBtn: HTMLButtonElement | null = null;\n\n private constructor(private readonly store: MaterialStore) {}\n\n // ── Public API ──────────────────────────────────────────────\n\n static mount(store: MaterialStore): EditorSidebar {\n const s = new EditorSidebar(store);\n s.build();\n return s;\n }\n\n show(): void {\n this.root.style.display = 'flex';\n this.applyLayout();\n if (this.activeTabId) {\n this.tabs.find((t) => t.id === this.activeTabId)?.onActivate?.();\n }\n }\n\n hide(): void {\n if (this.activeTabId) {\n this.tabs.find((t) => t.id === this.activeTabId)?.onDeactivate?.();\n }\n this.root.style.display = 'none';\n this.applyLayout();\n }\n\n toggle(): void {\n if (this.root.style.display === 'none') this.show();\n else this.hide();\n }\n\n get isVisible(): boolean {\n return this.root.style.display !== 'none';\n }\n\n /** Register an extra tab. */\n addTab(tab: EditorTab): void {\n this.tabs.push(tab);\n if (this.tabBar) this.renderTabBar();\n }\n\n unmount(): void {\n this.unsubMaterials?.();\n for (const t of this.tabs) t.destroy?.();\n this.root?.remove();\n }\n\n // ── Build ────────────────────────────────────────────────────\n\n private build(): void {\n this.root = el('div', { id: 'gl-editor-sidebar' }, SIDEBAR_STYLE);\n this.root.style.display = 'none';\n this.root.style.width = `${this._sidebarWidth}px`;\n\n // ── Drag handle (left edge) ────────────────────────────────\n const handle = el('div', {}, DRAG_HANDLE_STYLE);\n handle.addEventListener('mousedown', (e) => {\n e.preventDefault();\n this._dragging = true;\n document.body.style.cursor = 'col-resize';\n document.body.style.userSelect = 'none';\n });\n document.addEventListener('mousemove', (e) => {\n if (!this._dragging) return;\n const newWidth = window.innerWidth - e.clientX;\n this._sidebarWidth = Math.max(280, Math.min(newWidth, 900));\n this.root.style.width = `${this._sidebarWidth}px`;\n this.applyLayout();\n });\n document.addEventListener('mouseup', () => {\n if (!this._dragging) return;\n this._dragging = false;\n document.body.style.cursor = '';\n document.body.style.userSelect = '';\n });\n this.root.appendChild(handle);\n\n const header = el('div', {}, HEADER_STYLE);\n const title = el(\n 'span',\n {},\n 'font-weight:bold;color:#9cdcfe;letter-spacing:1px;',\n );\n title.textContent = '🛠 Editor';\n header.appendChild(title);\n // Layout toggle (absolute ↔ shared)\n this._layoutBtn = el(\n 'button',\n {},\n ICON_BTN_STYLE + ';margin-left:auto;font-size:14px;',\n );\n this._layoutBtn.title = 'Toggle: overlay / share viewport';\n this._layoutBtn.textContent = '⇔';\n this._layoutBtn.onclick = () => this.toggleLayout();\n header.appendChild(this._layoutBtn);\n\n const closeBtn = el('button', {}, ICON_BTN_STYLE);\n closeBtn.textContent = '✕';\n closeBtn.title = 'Close sidebar';\n closeBtn.onclick = () => this.hide();\n header.appendChild(closeBtn);\n\n this.tabBar = el('div', {}, TAB_BAR_STYLE);\n this.contentArea = el(\n 'div',\n {},\n 'flex:1;overflow:hidden;display:flex;flex-direction:column;',\n );\n\n this.root.appendChild(header);\n this.root.appendChild(this.tabBar);\n this.root.appendChild(this.contentArea);\n document.body.appendChild(this.root);\n\n this.addTab({\n id: 'materials',\n label: '🎨 Materials',\n buildContent: (c) => this.buildMaterialsContent(c),\n destroy: () => this.unsubMaterials?.(),\n });\n this.activateTab('materials');\n }\n\n // ── Layout mode ──────────────────────────────────────────────\n\n private toggleLayout(): void {\n this._layoutMode = this._layoutMode === 'absolute' ? 'shared' : 'absolute';\n this.applyLayout();\n }\n\n private applyLayout(): void {\n const visible = this.root.style.display !== 'none';\n if (this._layoutMode === 'shared' && visible) {\n document.body.style.marginRight = `${this._sidebarWidth}px`;\n } else {\n document.body.style.marginRight = '0';\n }\n // Update button label hint\n if (this._layoutBtn) {\n this._layoutBtn.textContent = this._layoutMode === 'absolute' ? '⇔' : '⇤';\n this._layoutBtn.title =\n this._layoutMode === 'absolute'\n ? 'Switch to shared layout (shrink viewport)'\n : 'Switch to overlay layout';\n }\n }\n\n // ── Tab system ───────────────────────────────────────────────\n\n private renderTabBar(): void {\n this.tabBar.innerHTML = '';\n for (const tab of this.tabs) {\n const btn = el(\n 'button',\n {},\n TAB_BTN_STYLE + (tab.id === this.activeTabId ? TAB_BTN_ACTIVE : ''),\n );\n btn.textContent = tab.label;\n btn.onclick = () => this.activateTab(tab.id);\n this.tabBar.appendChild(btn);\n }\n }\n\n /** Activate a tab by id. Safe to call from outside (e.g. TopBar button). */\n activateTab(id: string): void {\n // Deactivate the current tab before switching\n if (this.activeTabId && this.activeTabId !== id) {\n this.tabs.find((t) => t.id === this.activeTabId)?.onDeactivate?.();\n }\n this.activeTabId = id;\n this.renderTabBar();\n this.contentArea.innerHTML = '';\n const tab = this.tabs.find((t) => t.id === id);\n if (!tab) return;\n const c = el(\n 'div',\n {},\n 'flex:1;overflow:hidden;display:flex;flex-direction:column;',\n );\n tab.buildContent(c);\n this.contentArea.appendChild(c);\n tab.onActivate?.();\n }\n\n // ── Materials tab content ────────────────────────────────────\n\n private buildMaterialsContent(container: HTMLElement): void {\n const toolbar = el('div', {}, TOOLBAR_STYLE);\n toolbar.appendChild(this.mkBtn('+', () => this.onNew(), 'New material'));\n toolbar.appendChild(this.mkBtn('❑', () => this.onDuplicate(), 'Duplicate'));\n toolbar.appendChild(this.mkBtn('🗑', () => this.onDelete(), 'Delete'));\n const reloadBtn = el(\n 'button',\n {},\n BTN_STYLE + ';margin-left:auto;color:#6cf;border-color:#446;',\n );\n reloadBtn.textContent = '🔄 Reload Game';\n reloadBtn.title = 'Sync JSON then reload game to apply changes';\n reloadBtn.onclick = () => location.reload();\n toolbar.appendChild(reloadBtn);\n\n const body = el('div', {}, 'display:flex;flex:1;overflow:hidden;');\n this.listEl = el('div', {}, LIST_STYLE);\n this.formEl = el('div', {}, FORM_STYLE);\n body.appendChild(this.listEl);\n body.appendChild(this.formEl);\n\n container.appendChild(toolbar);\n container.appendChild(body);\n\n this.unsubMaterials = this.store.subscribe(() => this.refreshList());\n this.refreshList();\n }\n\n // ── List ─────────────────────────────────────────────────────\n\n private refreshList(): void {\n this.listEl.innerHTML = '';\n for (const spec of this.store.getAll()) {\n const active = spec.id === this.selectedId;\n const item = el(\n 'div',\n {},\n LIST_ITEM_STYLE + (active ? LIST_ITEM_ACTIVE : ''),\n );\n // Colour preview swatch\n const swatch = el('div', {}, swatchStyle(spec));\n item.appendChild(swatch);\n const nameEl = el(\n 'span',\n {},\n 'flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;',\n );\n nameEl.textContent = spec.name;\n item.appendChild(nameEl);\n item.onclick = () => this.select(spec.id);\n this.listEl.appendChild(item);\n }\n\n if (this.selectedId && !this.store.get(this.selectedId)) {\n this.selectedId = null;\n this.formEl.innerHTML = EMPTY_FORM_HTML;\n }\n }\n\n private select(id: string): void {\n this.selectedId = id;\n this.refreshList();\n this.buildForm();\n }\n\n // ── Form ─────────────────────────────────────────────────────\n\n private buildForm(): void {\n const spec = this.selectedId ? this.store.get(this.selectedId) : undefined;\n this.formEl.innerHTML = '';\n if (!spec) return;\n\n const draft: MaterialSpec = {\n ...spec,\n albedoColor: [...spec.albedoColor],\n diffuse: [...spec.diffuse],\n ambientColor: [...spec.ambientColor],\n specular: [...spec.specular],\n };\n\n const save = () => {\n this.store.update(draft);\n this.select(draft.id);\n };\n\n // Name\n formRow(this.formEl, 'Name', () => {\n const inp = el('input', { type: 'text', value: draft.name }, INPUT_STYLE);\n inp.oninput = () => {\n draft.name = inp.value;\n };\n inp.onblur = save;\n return inp;\n });\n\n // Albedo RGBA\n formRow(this.formEl, 'Albedo (RGBA)', () => {\n const wrap = el('div', {}, 'display:flex;gap:4px;align-items:center;');\n const hex = rgbToHex(\n draft.albedoColor[0],\n draft.albedoColor[1],\n draft.albedoColor[2],\n );\n const picker = el(\n 'input',\n { type: 'color', value: hex },\n 'cursor:pointer;',\n );\n const alphaIn = el(\n 'input',\n {\n type: 'range',\n min: '0',\n max: '1',\n step: '0.01',\n value: String(draft.albedoColor[3]),\n },\n 'flex:1;',\n );\n const alphaLbl = el(\n 'span',\n {},\n 'min-width:30px;color:#ccc;font-size:11px;',\n );\n alphaLbl.textContent = draft.albedoColor[3].toFixed(2);\n const update = () => {\n const [r, g, b] = hexToRgb(picker.value);\n draft.albedoColor = [r, g, b, parseFloat(alphaIn.value)];\n alphaLbl.textContent = parseFloat(alphaIn.value).toFixed(2);\n save();\n };\n picker.oninput = update;\n alphaIn.oninput = update;\n wrap.appendChild(picker);\n wrap.appendChild(alphaIn);\n wrap.appendChild(alphaLbl);\n return wrap;\n });\n\n // Vec3 colour pickers\n for (const key of ['diffuse', 'ambientColor', 'specular'] as Vec3Field[]) {\n const label = {\n diffuse: 'Diffuse',\n ambientColor: 'Ambient',\n specular: 'Specular',\n }[key];\n formRow(this.formEl, label, () => {\n const hex = rgbToHex(draft[key][0], draft[key][1], draft[key][2]);\n const picker = el(\n 'input',\n { type: 'color', value: hex },\n 'cursor:pointer;',\n );\n picker.oninput = () => {\n [draft[key][0], draft[key][1], draft[key][2]] = hexToRgb(\n picker.value,\n );\n save();\n };\n return picker;\n });\n }\n\n // Sliders\n numericRow(this.formEl, 'Shininess', draft.shininess, 2, 256, 1, (v) => {\n draft.shininess = v;\n save();\n });\n numericRow(this.formEl, 'Dissolve', draft.dissolve, 0, 1, 0.01, (v) => {\n draft.dissolve = v;\n save();\n });\n numericRow(\n this.formEl,\n 'Friction',\n draft.friction ?? 0.75,\n 0,\n 1,\n 0.01,\n (v) => {\n draft.friction = v;\n save();\n },\n );\n\n // Toggles\n checkRow(this.formEl, 'Unlit', draft.unlit, (v) => {\n draft.unlit = v;\n save();\n });\n checkRow(this.formEl, 'Double Sided', draft.doubleSided, (v) => {\n draft.doubleSided = v;\n save();\n });\n\n // Texture path\n formRow(this.formEl, 'Texture Path', () => {\n const inp = el(\n 'input',\n {\n type: 'text',\n value: draft.texturePath ?? '',\n placeholder: 'textures/my-tex.png',\n },\n INPUT_STYLE,\n );\n inp.oninput = () => {\n draft.texturePath = inp.value || undefined;\n };\n inp.onblur = save;\n return inp;\n });\n }\n\n // ── Actions ──────────────────────────────────────────────────\n\n private onNew(): void {\n const spec = this.store.create();\n this.select(spec.id);\n }\n\n private onDuplicate(): void {\n if (!this.selectedId) return;\n const copy = this.store.duplicate(this.selectedId);\n if (copy) this.select(copy.id);\n }\n\n private onDelete(): void {\n if (!this.selectedId) return;\n if (!confirm('Delete this material?')) return;\n this.store.delete(this.selectedId);\n this.selectedId = null;\n this.formEl.innerHTML = EMPTY_FORM_HTML;\n }\n\n private mkBtn(\n label: string,\n onClick: () => void,\n title = '',\n ): HTMLButtonElement {\n const b = el('button', {}, BTN_STYLE);\n b.textContent = label;\n b.title = title;\n b.onclick = onClick;\n return b;\n }\n}\n\n// ── DOM helpers ───────────────────────────────────────────────────\n\nfunction el<K extends keyof HTMLElementTagNameMap>(\n tag: K,\n attrs: Record<string, string> = {},\n style = '',\n): HTMLElementTagNameMap[K] {\n const e = document.createElement(tag);\n for (const [k, v] of Object.entries(attrs))\n (e as unknown as Record<string, string>)[k] = v;\n if (style) e.style.cssText = style;\n return e;\n}\n\nfunction formRow(\n parent: HTMLElement,\n label: string,\n buildInput: () => HTMLElement,\n): void {\n const row = el(\n 'div',\n {},\n 'display:flex;justify-content:space-between;align-items:center;margin-bottom:6px;gap:8px;',\n );\n const lbl = el(\n 'label',\n {},\n 'color:#bbb;font-size:12px;white-space:nowrap;min-width:90px;',\n );\n lbl.textContent = label;\n row.appendChild(lbl);\n const wrap = el('div', {}, 'flex:1;');\n wrap.appendChild(buildInput());\n row.appendChild(wrap);\n parent.appendChild(row);\n}\n\nfunction numericRow(\n parent: HTMLElement,\n label: string,\n value: number,\n min: number,\n max: number,\n step: number,\n onChange: (v: number) => void,\n): void {\n formRow(parent, label, () => {\n const wrap = el('div', {}, 'display:flex;gap:4px;align-items:center;');\n const slider = el(\n 'input',\n {\n type: 'range',\n min: String(min),\n max: String(max),\n step: String(step),\n value: String(value),\n },\n 'flex:1;',\n );\n const lbl = el(\n 'span',\n {},\n 'min-width:36px;color:#ccc;font-size:11px;text-align:right;',\n );\n lbl.textContent = value.toString();\n slider.oninput = () => {\n lbl.textContent = slider.value;\n onChange(parseFloat(slider.value));\n };\n wrap.appendChild(slider);\n wrap.appendChild(lbl);\n return wrap;\n });\n}\n\nfunction checkRow(\n parent: HTMLElement,\n label: string,\n value: boolean,\n onChange: (v: boolean) => void,\n): void {\n formRow(parent, label, () => {\n const cb = el('input', { type: 'checkbox' }, '');\n cb.checked = value;\n cb.onchange = () => onChange(cb.checked);\n return cb;\n });\n}\n\nfunction rgbToHex(r: number, g: number, b: number): string {\n const byte = (v: number) =>\n Math.round(Math.min(1, Math.max(0, v)) * 255)\n .toString(16)\n .padStart(2, '0');\n return `#${byte(r)}${byte(g)}${byte(b)}`;\n}\n\nfunction hexToRgb(hex: string): [number, number, number] {\n const n = parseInt(hex.slice(1), 16);\n return [((n >> 16) & 255) / 255, ((n >> 8) & 255) / 255, (n & 255) / 255];\n}\n\nfunction swatchStyle(spec: MaterialSpec): string {\n const [r, g, b, a] = spec.albedoColor;\n return [\n `background:rgba(${Math.round(r * 255)},${Math.round(g * 255)},${Math.round(b * 255)},${a})`,\n 'width:18px',\n 'min-width:18px',\n 'height:18px',\n 'border-radius:3px',\n 'border:1px solid #666',\n 'flex-shrink:0',\n ].join(';');\n}\n\n// ── Constants ─────────────────────────────────────────────────────\n\nconst EMPTY_FORM_HTML =\n '<p style=\"color:#888;padding:16px 10px;font-size:12px;\">Select or create a material.</p>';\n\n// ── Styles ────────────────────────────────────────────────────────\n\nconst SIDEBAR_STYLE = [\n 'position:fixed',\n 'top:32px',\n 'right:0',\n 'height:calc(100vh - 32px)',\n 'background:#1e1e1e',\n 'border-left:1px solid #444',\n 'display:flex',\n 'flex-direction:column',\n 'color:#ddd',\n 'font-family:monospace',\n 'font-size:12px',\n 'z-index:9998',\n 'box-shadow:-4px 0 20px rgba(0,0,0,.6)',\n 'overflow:hidden',\n].join(';');\n\nconst DRAG_HANDLE_STYLE = [\n 'position:absolute',\n 'top:0',\n 'left:0',\n 'width:5px',\n 'height:100%',\n 'cursor:col-resize',\n 'z-index:1',\n 'background:transparent',\n].join(';');\n\nconst HEADER_STYLE = [\n 'display:flex',\n 'align-items:center',\n 'gap:8px',\n 'padding:0 12px',\n 'height:36px',\n 'background:#252525',\n 'border-bottom:1px solid #444',\n 'flex-shrink:0',\n].join(';');\n\nconst ICON_BTN_STYLE = [\n 'padding:2px 7px',\n 'background:transparent',\n 'color:#888',\n 'border:1px solid #444',\n 'border-radius:4px',\n 'cursor:pointer',\n 'font-size:12px',\n].join(';');\n\nconst TAB_BAR_STYLE = [\n 'display:flex',\n 'background:#1a1a1a',\n 'border-bottom:1px solid #444',\n 'flex-shrink:0',\n].join(';');\n\nconst TAB_BTN_STYLE = [\n 'padding:5px 12px',\n 'background:transparent',\n 'color:#aaa',\n 'border:none',\n 'border-right:1px solid #333',\n 'cursor:pointer',\n 'font-family:monospace',\n 'font-size:11px',\n 'white-space:nowrap',\n].join(';');\n\nconst TAB_BTN_ACTIVE =\n ';background:#1e1e1e;color:#fff;border-bottom:2px solid #007acc;';\n\nconst TOOLBAR_STYLE = [\n 'display:flex',\n 'align-items:center',\n 'gap:4px',\n 'padding:5px 8px',\n 'background:#252525',\n 'border-bottom:1px solid #444',\n 'flex-shrink:0',\n].join(';');\n\nconst BTN_STYLE = [\n 'padding:3px 8px',\n 'background:#3a3a3a',\n 'color:#ddd',\n 'border:1px solid #555',\n 'border-radius:4px',\n 'cursor:pointer',\n 'font-family:monospace',\n 'font-size:11px',\n].join(';');\n\nconst LIST_STYLE = [\n 'width:140px',\n 'min-width:140px',\n 'overflow-y:auto',\n 'border-right:1px solid #333',\n 'padding:4px',\n 'display:flex',\n 'flex-direction:column',\n 'gap:2px',\n].join(';');\n\nconst LIST_ITEM_STYLE = [\n 'display:flex',\n 'align-items:center',\n 'gap:6px',\n 'padding:5px 6px',\n 'border-radius:4px',\n 'cursor:pointer',\n 'overflow:hidden',\n 'color:#ccc',\n].join(';');\n\nconst LIST_ITEM_ACTIVE =\n ';background:#007acc22;outline:1px solid #007acc;color:#fff;';\n\nconst FORM_STYLE = ['flex:1', 'overflow-y:auto', 'padding:10px 10px 16px'].join(\n ';',\n);\n\nconst INPUT_STYLE = [\n 'width:100%',\n 'background:#2a2a2a',\n 'border:1px solid #555',\n 'border-radius:3px',\n 'color:#ddd',\n 'padding:3px 5px',\n 'font-family:monospace',\n 'font-size:11px',\n 'box-sizing:border-box',\n].join(';');\n","/** Minimal sidebar interface used by TopBar for tab-aware buttons. */\ninterface ISidebar {\n show(): void;\n toggle(): void;\n activateTab(id: string): void;\n readonly isVisible: boolean;\n}\n\n/** Minimal room panel interface used by TopBar. */\ninterface IRoomPanel {\n toggle(): void;\n readonly isVisible: boolean;\n}\n\n/**\n * Slim top bar pinned at the top of the viewport.\n * Houses engine tool buttons (e.g. Material Editor toggle).\n */\nexport class TopBar {\n private root!: HTMLElement;\n\n private constructor() {}\n\n static mount(materialPanel: ISidebar): TopBar {\n const bar = new TopBar();\n bar.build(materialPanel);\n return bar;\n }\n\n unmount(): void {\n this.root?.remove();\n }\n\n private build(materialPanel: ISidebar): void {\n this.root = document.createElement('div');\n this.root.id = 'gl-top-bar';\n this.root.style.cssText = TOP_BAR_STYLE;\n\n // Left group – branding\n const brand = document.createElement('span');\n brand.textContent = 'GenesisGL';\n brand.style.cssText =\n 'font-weight:bold;color:#9cdcfe;letter-spacing:1px;margin-right:16px;';\n this.root.appendChild(brand);\n\n // Tool buttons\n this.root.appendChild(this.mkToggleBtn('🎨 Materials', materialPanel));\n\n document.body.prepend(this.root);\n\n // Push page content down so the bar doesn't overlay anything\n document.body.style.paddingTop = `${this.root.offsetHeight || 34}px`;\n }\n\n /** Add the Models tab button after the game has started. */\n addModelsButton(sidebar: ISidebar): void {\n const btn = document.createElement('button');\n btn.textContent = '🧠 Models';\n btn.style.cssText = BTN_STYLE;\n btn.onclick = () => {\n sidebar.show();\n sidebar.activateTab('models');\n btn.style.cssText = sidebar.isVisible ? BTN_ACTIVE_STYLE : BTN_STYLE;\n };\n this.root.appendChild(btn);\n }\n\n /** Add the Scene tab button after the game has started. */\n addSceneButton(sidebar: ISidebar): void {\n const btn = document.createElement('button');\n btn.textContent = '🌍 Scene';\n btn.style.cssText = BTN_STYLE;\n btn.onclick = () => {\n sidebar.show();\n sidebar.activateTab('scene');\n btn.style.cssText = sidebar.isVisible ? BTN_ACTIVE_STYLE : BTN_STYLE;\n };\n this.root.appendChild(btn);\n }\n\n /** Add the Room manager button. */\n addRoomButton(panel: IRoomPanel): void {\n const btn = document.createElement('button');\n btn.textContent = '🚪 Rooms';\n btn.style.cssText = BTN_STYLE;\n btn.onclick = () => {\n panel.toggle();\n btn.style.cssText = panel.isVisible ? BTN_ACTIVE_STYLE : BTN_STYLE;\n };\n this.root.appendChild(btn);\n }\n\n private mkToggleBtn(label: string, panel: ISidebar): HTMLButtonElement {\n return this.mkPanelToggleBtn(label, panel);\n }\n\n private mkPanelToggleBtn(\n label: string,\n panel: { toggle(): void; isVisible: boolean },\n ): HTMLButtonElement {\n const btn = document.createElement('button');\n btn.textContent = label;\n btn.style.cssText = BTN_STYLE;\n btn.onclick = () => {\n panel.toggle();\n btn.style.cssText = panel.isVisible ? BTN_ACTIVE_STYLE : BTN_STYLE;\n };\n return btn;\n }\n}\n\n// ── Styles ────────────────────────────────────────────────────────\n\nconst TOP_BAR_STYLE = [\n 'position:fixed',\n 'top:0',\n 'left:0',\n 'right:0',\n 'height:32px',\n 'z-index:9999',\n 'display:flex',\n 'align-items:center',\n 'padding:0 12px',\n 'gap:6px',\n 'background:#1a1a1a',\n 'border-bottom:1px solid #444',\n 'font-family:monospace',\n 'font-size:12px',\n 'color:#ddd',\n 'box-shadow:0 2px 8px rgba(0,0,0,.5)',\n].join(';');\n\nconst BTN_STYLE = [\n 'padding:3px 10px',\n 'background:#2d2d2d',\n 'color:#ddd',\n 'border:1px solid #555',\n 'border-radius:4px',\n 'cursor:pointer',\n 'font-size:11px',\n 'font-family:monospace',\n].join(';');\n\nconst BTN_ACTIVE_STYLE = [\n 'padding:3px 10px',\n 'background:#007acc',\n 'color:#fff',\n 'border:1px solid #007acc',\n 'border-radius:4px',\n 'cursor:pointer',\n 'font-size:11px',\n 'font-family:monospace',\n].join(';');\n","import { EditorTab } from '../../EditorSidebar';\n\n/** Minimal interface: only the debug flag we need. */\ninterface IRenderer {\n debug: boolean;\n}\n\n/** Bounding box as stored on Model. */\ninterface AABB {\n min: [number, number, number];\n max: [number, number, number];\n}\n\n/** Minimal model shape required by the inspector. */\ninterface IModel {\n translation: [number, number, number];\n rotation: [number, number, number];\n scale: [number, number, number];\n boundingBox: AABB;\n}\n\n/** Minimal scene interface: just the keyed entry list. */\ninterface IScene {\n getEntries(): [string, IModel][];\n}\n\n/**\n * Model Inspector — rendered as a tab inside the {@link EditorSidebar}.\n *\n * Lifecycle:\n * – `buildContent(container)` builds the DOM once when the tab is activated.\n * – `onActivate()` enables `renderer.debug` and starts a 200 ms refresh loop.\n * – `onDeactivate()` disables `renderer.debug` and stops the refresh loop.\n * – `asTab()` returns an {@link EditorTab} descriptor ready for `sidebar.addTab()`.\n */\nexport class ModelsSection {\n private listEl: HTMLElement | null = null;\n private hitboxCheck: HTMLInputElement | null = null;\n private intervalId: ReturnType<typeof setInterval> | null = null;\n\n private constructor(\n private readonly renderer: IRenderer,\n private readonly scene: IScene,\n ) {}\n\n // ── Factory ──────────────────────────────────────────────────\n\n static create(renderer: IRenderer, scene: IScene): ModelsSection {\n return new ModelsSection(renderer, scene);\n }\n\n // ── Tab descriptor ───────────────────────────────────────────\n\n asTab(): EditorTab {\n return {\n id: 'models',\n label: '🧠 Models',\n buildContent: (c) => this.buildContent(c),\n onActivate: () => this.start(),\n onDeactivate: () => this.stop(),\n destroy: () => this.stop(),\n };\n }\n\n // ── Lifecycle ────────────────────────────────────────────────\n\n private start(): void {\n this.renderer.debug = true;\n if (this.hitboxCheck) this.hitboxCheck.checked = true;\n this.refresh();\n if (this.intervalId === null) {\n this.intervalId = setInterval(() => this.refresh(), 200);\n }\n }\n\n private stop(): void {\n this.renderer.debug = false;\n if (this.hitboxCheck) this.hitboxCheck.checked = false;\n if (this.intervalId !== null) {\n clearInterval(this.intervalId);\n this.intervalId = null;\n }\n }\n\n // ── Build ────────────────────────────────────────────────────\n\n private buildContent(container: HTMLElement): void {\n // ── Controls row\n const controls = mk('div', CONTROLS_STYLE);\n const hitboxRow = document.createElement('label');\n hitboxRow.style.cssText =\n 'display:flex;align-items:center;gap:6px;cursor:pointer;color:#ccc;font-size:11px;';\n this.hitboxCheck = document.createElement('input');\n this.hitboxCheck.type = 'checkbox';\n this.hitboxCheck.checked = this.renderer.debug;\n this.hitboxCheck.onchange = () => {\n this.renderer.debug = this.hitboxCheck!.checked;\n };\n hitboxRow.appendChild(this.hitboxCheck);\n const hitboxLbl = document.createElement('span');\n hitboxLbl.textContent = 'Show Hitboxes';\n hitboxRow.appendChild(hitboxLbl);\n controls.appendChild(hitboxRow);\n\n // ── Model list\n this.listEl = mk('div', LIST_STYLE);\n\n container.appendChild(controls);\n container.appendChild(this.listEl);\n }\n\n // ── Live refresh ─────────────────────────────────────────────\n\n private refresh(): void {\n if (!this.listEl) return;\n const entries = this.scene.getEntries();\n this.listEl.innerHTML = '';\n\n const heading = mk(\n 'div',\n 'color:#666;font-size:10px;letter-spacing:1px;padding:0 0 4px;',\n );\n heading.textContent = `MODELS (${entries.length})`;\n this.listEl.appendChild(heading);\n\n for (const [key, model] of entries) {\n const card = mk('div', CARD_STYLE);\n\n const nameEl = mk(\n 'div',\n 'font-weight:bold;color:#9cdcfe;margin-bottom:4px;',\n );\n nameEl.textContent = key;\n card.appendChild(nameEl);\n\n const t = model.translation;\n const r = model.rotation;\n const s = model.scale;\n const bb = model.boundingBox;\n const w = bb.max[0] - bb.min[0];\n const h = bb.max[1] - bb.min[1];\n const d = bb.max[2] - bb.min[2];\n\n card.appendChild(dataRow('pos', `${f(t[0])} ${f(t[1])} ${f(t[2])}`));\n card.appendChild(dataRow('rot', `${f(r[0])} ${f(r[1])} ${f(r[2])}`));\n card.appendChild(dataRow('scl', `${f(s[0])} ${f(s[1])} ${f(s[2])}`));\n card.appendChild(dataRow('bbox', `${f(w)}w ${f(h)}h ${f(d)}d`));\n\n this.listEl.appendChild(card);\n }\n }\n}\n\n// ── Helpers ───────────────────────────────────────────────────────\n\nfunction mk(\n tag: string,\n style = '',\n): HTMLElement & HTMLButtonElement & HTMLDivElement {\n const el = document.createElement(tag) as HTMLElement &\n HTMLButtonElement &\n HTMLDivElement;\n if (style) el.style.cssText = style;\n return el;\n}\n\nfunction f(n: number): string {\n return n.toFixed(2);\n}\n\nfunction dataRow(label: string, value: string): HTMLElement {\n const row = document.createElement('div');\n row.style.cssText = 'display:flex;gap:4px;line-height:1.6;';\n\n const lbl = document.createElement('span');\n lbl.style.cssText = 'color:#666;width:28px;flex-shrink:0;font-size:10px;';\n lbl.textContent = label;\n\n const val = document.createElement('span');\n val.style.cssText = 'color:#ccc;font-size:10px;';\n val.textContent = value;\n\n row.appendChild(lbl);\n row.appendChild(val);\n return row;\n}\n\n// ── Styles ────────────────────────────────────────────────────────\n\nconst CONTROLS_STYLE = [\n 'padding:6px 10px',\n 'background:#222',\n 'border-bottom:1px solid #333',\n 'flex-shrink:0',\n].join(';');\n\nconst LIST_STYLE = [\n 'overflow-y:auto',\n 'padding:8px',\n 'display:flex',\n 'flex-direction:column',\n 'gap:6px',\n].join(';');\n\nconst CARD_STYLE = [\n 'background:#252525',\n 'border:1px solid #333',\n 'border-radius:4px',\n 'padding:6px 8px',\n].join(';');\n"],"mappings":"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","names":["STORAGE_KEY","el","TOOLBAR_STYLE","BTN_STYLE","LIST_STYLE","FORM_STYLE","INPUT_STYLE","BTN_STYLE","mk","LIST_STYLE","CARD_STYLE","dataRow","f","el"]}
|