mirror of
https://github.com/isledecomp/isle.pizza.git
synced 2026-02-28 05:47:39 +00:00
Some checks are pending
Build / build (push) Waiting to run
* WIP * stuff * WIP: Interactive 3D score cube for save editor * Conditionally render ScoreCube to properly clean up WebGL canvas Only mount the ScoreCube component when on the save-editor page. This ensures onDestroy is called when navigating away, properly disposing of the WebGL renderer and removing the canvas from DOM. * Refactor: Consolidate formats and genericize WDB rendering - Move parsing/serialization code to src/core/formats/: - BinaryReader.js, BinaryWriter.js (shared utilities) - SaveGameParser.js, SaveGameSerializer.js - PlayersParser.js, PlayersSerializer.js - Create formats/index.js as barrel export - Extract generic WdbModelRenderer from ScoreCubeRenderer: - WdbModelRenderer handles D3DRM geometry and paletted textures - ScoreCubeRenderer extends it with score-specific logic - Prepares for rendering other WDB models in the future - Keep savegame/constants.js for domain-specific constants - savegame/index.js remains as high-level API facade * Save editor UI improvements - Make save slot cards fixed width (85px) to prevent resizing with name length - Make save slot cards more compact (smaller icons, padding, font) - Remove Act selection from Character section - Remove box-shadow from selected character to fix collapsed section bleed * Improve score cube lighting to match in-game appearance - Use flat, even lighting (high ambient + soft front light) - Remove harsh directional shadows from edges - Adjust camera position slightly for better framing * Add spacing below score cube canvas * Add spinning loader while loading score cube * Update three.js to 0.182.0 and fix npm audit issues - Update three.js from 0.170.0 to 0.182.0 - Fix npm audit vulnerabilities (devalue, lodash, svelte) - Remaining vulns are in dev dependencies (vite, workbox-cli) * Fix score cube overflow on mobile Add max-width constraints to prevent the score cube from expanding its container on narrow viewports while preserving its natural 200x200 size on desktop. * Add save slot carousel and improve empty states - Add reusable Carousel component with arrow navigation, drag-to-scroll, and click-to-scroll-into-view functionality - Replace static save slot list with horizontal carousel - Add empty state with image when no save files exist - Add prompt state when saves exist but none is selected - Reset selected slot when entering Save Editor page * Add February 2026 changelog entry for Save Editor * Add missing January 2026 changelog entries for Safari and mobile fixes * Remove unused mission images * Refactor opfs.js to reduce code duplication - Consolidate getFileHandle to use getOpfsRoot internally - Add writeTextFile helper that uses writeBinaryFile - Extract showToast helper for toast notifications - Simplify saveConfig to use writeTextFile instead of duplicate worker - Simplify fileExists and readBinaryFile to use getFileHandle * Remove unused ScoreColorButton component * Remove unused UI components
103 lines
3.4 KiB
Svelte
103 lines
3.4 KiB
Svelte
<script>
|
|
import { onMount } from 'svelte';
|
|
import { currentPage, debugEnabled } from './stores.js';
|
|
import { registerServiceWorker, checkCacheStatus } from './core/service-worker.js';
|
|
import { setupCanvasEvents } from './core/emscripten.js';
|
|
import TopContent from './lib/TopContent.svelte';
|
|
import Controls from './lib/Controls.svelte';
|
|
import ReadMePage from './lib/ReadMePage.svelte';
|
|
import ConfigurePage from './lib/ConfigurePage.svelte';
|
|
import FreeStuffPage from './lib/FreeStuffPage.svelte';
|
|
import SaveEditorPage from './lib/SaveEditorPage.svelte';
|
|
import UpdatePopup from './lib/UpdatePopup.svelte';
|
|
import GoodbyePopup from './lib/GoodbyePopup.svelte';
|
|
import ConfigToast from './lib/ConfigToast.svelte';
|
|
import DebugPanel from './lib/DebugPanel.svelte';
|
|
import CanvasWrapper from './lib/CanvasWrapper.svelte';
|
|
|
|
onMount(async () => {
|
|
// Disable browser's automatic scroll restoration
|
|
if ('scrollRestoration' in history) {
|
|
history.scrollRestoration = 'manual';
|
|
}
|
|
|
|
// Register service worker and initialize
|
|
const registration = await registerServiceWorker();
|
|
if (registration) {
|
|
checkCacheStatus();
|
|
}
|
|
|
|
// Setup canvas events
|
|
setupCanvasEvents();
|
|
|
|
// Initialize history state based on current page
|
|
const initialHash = window.location.hash;
|
|
if (initialHash) {
|
|
// Set up proper history state for the current hash
|
|
history.replaceState({ page: 'main' }, '', window.location.pathname);
|
|
history.pushState({ page: $currentPage }, '', initialHash);
|
|
} else {
|
|
history.replaceState({ page: 'main' }, '', window.location.pathname);
|
|
}
|
|
|
|
// Handle browser back/forward
|
|
window.addEventListener('popstate', (e) => {
|
|
if (e.state && e.state.page && e.state.page !== 'main') {
|
|
currentPage.set(e.state.page);
|
|
} else {
|
|
currentPage.set('main');
|
|
}
|
|
});
|
|
});
|
|
|
|
// Scroll to top whenever page changes
|
|
$: $currentPage, window.scrollTo(0, 0);
|
|
</script>
|
|
|
|
<!-- Audio element outside page routing so it persists across navigation -->
|
|
<audio id="install-audio" loop preload="none">
|
|
<source src="install.mp3" type="audio/mpeg">
|
|
</audio>
|
|
|
|
<GoodbyePopup />
|
|
<UpdatePopup />
|
|
<ConfigToast />
|
|
|
|
<div id="main-container">
|
|
<div class="page-wrapper" class:active={$currentPage === 'main'}>
|
|
<TopContent />
|
|
<Controls />
|
|
</div>
|
|
<div class="page-wrapper" class:active={$currentPage === 'read-me'}>
|
|
<ReadMePage />
|
|
</div>
|
|
<div class="page-wrapper" class:active={$currentPage === 'configure'}>
|
|
<ConfigurePage />
|
|
</div>
|
|
<div class="page-wrapper" class:active={$currentPage === 'free-stuff'}>
|
|
<FreeStuffPage />
|
|
</div>
|
|
<div class="page-wrapper" class:active={$currentPage === 'save-editor'}>
|
|
<SaveEditorPage />
|
|
</div>
|
|
|
|
<div class="footer-disclaimer">
|
|
<p>LEGO® and LEGO Island™ are trademarks of The LEGO Group.</p>
|
|
<p>This is an unofficial fan project and is not affiliated with or endorsed by The LEGO Group.</p>
|
|
</div>
|
|
|
|
<div class="app-footer">
|
|
{#if __BUILD_TIME__}
|
|
<p>Last updated: {__BUILD_TIME__}</p>
|
|
{:else}
|
|
<p><strong>DEVELOPMENT MODE</strong></p>
|
|
{/if}
|
|
</div>
|
|
</div>
|
|
|
|
<CanvasWrapper />
|
|
|
|
{#if $debugEnabled}
|
|
<DebugPanel />
|
|
{/if}
|