Commit Graph

109 Commits

Author SHA1 Message Date
Christian Semmler
9872902e4d
Actor editor (#24)
Some checks are pending
Build / build (push) Waiting to run
* Improve Lighthouse LCP and accessibility scores

Preload the LCP image (install.webp) from the HTML and add
fetchpriority="high" so the browser discovers it before JS executes.
Use a <main> landmark for the primary content container to satisfy
the "document has a main landmark" accessibility audit.

* Add actor editor with animated 3D character preview

Browse and customize all 66 game actors with a Three.js rendered preview
featuring skeletal walk cycle animations. Click interaction matches the
game's character-dependent behavior (Pepper=hat, Nick=color, etc.).

- Parse WDB global parts and global textures for character assembly
- Parse and serialize character data (66 entries x 16 bytes) in save files
- AnimationParser for .ani binary format with hierarchical keyframe evaluation
- Full g_cycles animation table (11 types x 17 animations) driven by move/sound
- Per-mesh texture support for hats, torso, and face textures

* Extract BaseRenderer to deduplicate actor and vehicle renderers

- Extract shared Three.js setup, lighting, texture, geometry, and
  animation loop code into BaseRenderer base class (~170 lines)
- Deduplicate WdbParser.parseGlobalParts via parsePartData delegation
- Consolidate lego brown/lt grey into shared LegoColors constant
- Remove dead code: updatePartColor, SUFFIX_NAMES, CharacterType,
  getCharacterType, partToLODIndex, unused imports and re-exports
- Simplify updateCharacter and resolve methods by removing unnecessary
  defensive checks on frozen data and bounded UI inputs
- Extract actorKey helper in ActorEditor to deduplicate key computation
- Delete unused animations/manifest.json

* Add reset to default button for actor editor

Compare each actor's character state against ActorInfoInit defaults
and show a reset button when any field differs. Resets all 10 fields
(sound, move, mood, hat, colors) in a single save round-trip by
extending updateSaveSlot to accept batch character updates.

* Show full character names in actor editor

Add ActorDisplayNames lookup with names from savegame.ksy doc comments
(e.g. "Pepper Roni", "Mama Brickolini") instead of internal IDs.
Widen nav label min-width to 150px to prevent button shifting.

* Stabilize actor position when hat changes

Override centerAndScaleModel in ActorRenderer to exclude the hat
part from the bounding box calculation, so switching between hats
of different sizes no longer shifts the body/head position.

* Fetch assets from SI files via HTTP Range requests

Replace static animation, texture, and globe bitmap files with a
manifest-driven approach that extracts them directly from the game's
SI files at runtime using HTTP Range requests.

A new generate-manifest script scans SI files by MxCh objectId to
locate each asset's byte offset(s), verifies integrity via MD5, and
writes an asset-ranges.json manifest. The app consumes this manifest
to fetch assets on demand, including support for files split across
MxCh interleave boundaries.

Also removes unused constants (ActorLODIndex, animation keyframe
flag constants).

* Fetch character icons from SI files via HTTP Range requests

Replace static webp character icons with runtime extraction from
INFOMAIN.SI, extending the bitmap manifest to support multiple SI files.

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>

* Fix actor editor animation and interaction bugs

Use mood (not sound+4*move) to select walking animation, matching
FUN_10063b90. Load secondary animation tier (speed 4.0 threshold)
which NPCs typically use in-game, producing the independent head/hat
movement. Fix switchSound wrap to 9 values, add switchColor click
remapping for claws/head/body, fix g_cycles case mismatches, add
morph key visibility support, and preserve root Y-translation for
vertical bounce while stripping horizontal movement.

* Add click animations to actor editor

Play a one-shot gesture animation when clicking an actor, matching the
in-game LegoEntity::ClickAnimation behavior (objectId = m_move + 10).
After the click animation finishes, the walking loop resumes. Adds the
4 click animations from SNDANIM.SI to the asset manifest and extends
ActorRenderer with queue-based click animation playback. Also fixes
treadmill XZ stripping for click animations where actor_01 is nested
under wrapper nodes.

* Add vehicle rendering to actor editor

Actors with personal vehicles (skateboard, motorcycles, bicycles) can
now be toggled between walking and vehicle mode via a button in the
actor navigation bar. Vehicle geometries are loaded from WDB world
models and rendered alongside the character with matching animations.

* Add click sound playback to actor editor

Plays the character's click sound (m_sound + 50) and, for Laura's
SwitchMood, an additional mood sound (m_mood + 66) from SNDANIM.SI,
matching the original game behavior. Sounds are fetched on demand,
decoded as WAV, and cached as AudioBuffers.

* Replace Range request asset loading with packed binary bundle

Extract save editor assets (animations, sounds, textures, bitmaps) into
a single save-editor.bin file at build time instead of fetching byte
ranges from ~550MB SI files at runtime. The bundle packs an embedded
JSON index and all fragment data into one file (~756KB), eliminating
Range request complexity and enabling proper Workbox precaching.

* Clean up actor editor branch: DRY, dead code, CSS

- Extract buildNodeToPartGroupMap() in ActorRenderer to deduplicate
  map-building logic in loadAnimationForActor and playClickAnimation
- Refactor updateMissionScore() to use getMissionScoreOffset() instead
  of duplicating offset calculation
- Remove unused ActorPartLabels export from actorConstants
- Make fetchBitmap module-private (only used by fetchBitmapAsURL)
- Merge duplicate .globe-btn CSS blocks in LightPositionEditor

* Add drag-to-orbit controls to vehicle and actor editors

Use Three.js OrbitControls in BaseRenderer for rotation-only orbiting
with damping. Vehicle editor auto-rotates and resets on part switch.
Actor editor uses orbit without auto-rotate (has skeletal animations).
Drag vs click detection uses pointermove threshold to avoid false
positives from autoRotate damping.

* Rebase WdbModelRenderer on BaseRenderer

Remove duplicated scene/camera/renderer/lighting setup, geometry
unpacking, animation loop, and dispose logic. Score cube gets orbit
controls and drag-vs-click detection for free.

* Add zoom, pan, and camera reset to 3D editors

Enable zoom (scroll/pinch) and pan (right-click/two-finger drag) on
all OrbitControls. Add resetView() to BaseRenderer that restores
initial camera state and auto-rotate via OrbitControls.saveState/reset.
Add reset camera button to EditorTooltip with mobile-friendly touch
targets and hover-only highlight to avoid sticky state on touch.

* Update changelog and fix sticky hover on touch devices

Add actor editor features, 3D orbit/zoom/pan controls, and camera
reset button to the February 2026 changelog. Wrap hover styles in
@media (hover: hover) for vehicle toggle and texture buttons.

* Update README with save editor setup, project structure, and Three.js
2026-02-14 02:29:55 +01:00
Christian Semmler
de9fefb999
Improve Lighthouse LCP and accessibility scores (#23)
Some checks failed
Build / build (push) Has been cancelled
Preload the LCP image (install.webp) from the HTML and add
fetchpriority="high" so the browser discovers it before JS executes.
Use a <main> landmark for the primary content container to satisfy
the "document has a main landmark" accessibility audit.
2026-02-08 00:43:07 +01:00
Christian Semmler
a85e2ab952
Organize public assets (#22)
* Organize public assets into subdirectories

Group 80+ flat files into images/, textures/, pdf/, and audio/ subdirectories
for easier navigation. Update all references across 14 source files.

* Add apple-touch-icon
2026-02-08 00:01:45 +01:00
Christian Semmler
39598aa3b9
Vehicle textures (#21)
* Add vehicle texture editing

Parse and serialize Act1State textures in save files. Add a texture
picker modal with default presets (from .tex files) and custom uploads
persisted to IndexedDB per texture name. Quantize uploaded images
against the WDB palette and render texture changes in the 3D preview.
Support resetting textures to the WDB default.

* Fix vehicle texture not updating when switching save slots

Include slot number in the part key so that switching save slots
triggers a full part reload with the new slot's textures.

* Preload default textures for instant texture picker opening

Fetch and parse .tex files in the background when a textured part
loads, and pass the results to TexturePickerModal as a prop. The
modal no longer fetches on mount, eliminating the loading delay.

* Cleanup: parallel fetching, error recovery, dead code removal

- Fetch .tex files in parallel with Promise.all instead of sequentially
- Clear cached IndexedDB promise on rejection so subsequent calls retry
- Remove unused textureOrder array from Act1State parser
- Unify selectDefault/applyCustom into single applyTexture function
- Remove redundant squareTexture call on already-squared wdbTexture

* Add vehicle texture editor to February 2026 changelog

* Fix mouseenter error on non-Element targets
2026-02-07 23:34:57 +01:00
Christian Semmler
2c12d5ad5e
Fix tooltip flash and misposition on mobile (#20)
Some checks failed
Build / build (push) Has been cancelled
- Temporarily expand tooltip for accurate size measurement before positioning
- Use @media (hover: hover) to prevent CSS :hover triggering on touch tap
- Await position calculation before showing tooltip
2026-02-03 02:28:04 +01:00
Christian Semmler
006ba8472c
Fix double save when changing extension settings (#19)
handleExtensionChange was calling handleFormChange() explicitly, but the
change event also bubbles up to the form's onchange handler which calls
handleFormChange() again - causing two saves per change.

Now handleExtensionChange only calls checkCacheStatus() since the form's
onchange already handles saving.
2026-02-03 02:07:11 +01:00
Christian Semmler
a680bc67ef
Add dynamic tooltip positioning using Floating UI (#18)
- Use @floating-ui/dom for intelligent tooltip placement
- Tooltips now shift/flip to stay within viewport bounds
- Collapse hidden tooltips to prevent horizontal scroll overflow
- Move tooltip setup to App.svelte for global coverage
2026-02-03 02:00:24 +01:00
Christian Semmler
eed65faeac
Use Node.js built-in parseArgs for CLI argument parsing (#17)
Replace manual argument parsing with util.parseArgs() API.
2026-02-03 01:37:08 +01:00
Christian Semmler
9ab402393b
Add February 2026 changelog entries (#16)
Add Sky Color Editor and Vehicle Part Editor features to changelog.
2026-02-03 01:34:38 +01:00
Christian Semmler
0cca67f900
Fix graphics options not hidden when Software renderer is pre-selected (#15)
Call showOrHideGraphicsOptions() after loading config from OPFS to ensure
Anti-aliasing and Anisotropic filtering are properly hidden when the
Software renderer is already configured in the INI file.
2026-02-03 01:24:46 +01:00
Christian Semmler
c85eeef56a
Feature/vehicle part editor (#14)
Some checks are pending
Build / build (push) Waiting to run
* Add vehicle part color editor to save editor

- Add Vehicles tab with 3D preview of customizable vehicle parts
- Support all 43 colorable parts across 4 vehicles (dune buggy, helicopter, jetski, race car)
- Implement shared LOD resolution for proper rendering of all parts
- Extract reusable NavButton and ResetButton components
- Remove debug console.log statements from ScoreCube

* Reserve space for reset button in vehicle editor to prevent layout shift

* Add tooltip to vehicle editor explaining click-to-cycle interaction

* Add scroll-into-view behavior for name slots on mobile

When name slots overflow on narrow screens, focusing a partially visible
slot now smoothly scrolls it into view. Scrollbar is hidden for cleaner UI.

* Extract EditorTooltip component for consistent tooltip positioning

Refactored tooltip markup into reusable EditorTooltip component used by
both ScoreCube and VehicleEditor. Tooltip now consistently appears in
top right corner of the editor section.

* Add transparency support to vehicle part rendering

Apply mesh alpha values from WDB to Three.js materials. In the original
game, alpha=0 means opaque while alpha>0 enables transparency. Disable
depthWrite for transparent meshes to prevent z-fighting.

* Use MeshLambertMaterial for original game-like rendering

Switch from MeshStandardMaterial (PBR) to MeshLambertMaterial for flat,
vibrant colors matching the original game. Simplify lighting setup for
solid colors without visible shadows.

* Fix WDB texture parsing for parts vs models

Parts and models have different texture info formats - models include a
skipTextures field that parts don't have. Add isModel parameter to
parseTextureInfo to handle this difference correctly. Also remove silent
catch blocks and overly defensive checks.
2026-02-02 02:08:12 +01:00
Christian Semmler
36a6e0fde9
Feature/island sky color editor (#13)
* Add Island tab with sky color editor

- Add parseVariables() to SaveGameParser to extract variable names, values, and offsets
- Add updateVariable() to SaveGameSerializer for modifying variable values
- Add colorUtils.js with LEGO Island's custom HSV-to-RGB algorithm
- Add SkyColorEditor component with H/S/V sliders and color preview
- Add Island tab to SaveEditorPage with Sky Color section
- Include reset to default button when values differ from default (56/54/68)

* Remove tooltip

* Add light position editor to Island tab

Allows users to select one of 6 sun positions using visual globe
image selectors. Includes converted globe images (BMP to WebP).
2026-02-01 23:42:40 +01:00
Christian Semmler
64be72194e
Add save game editor (#12)
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
2026-02-01 00:28:16 +01:00
Christian Semmler
8f374561e5
Add prepare:assets script for game asset setup (#11)
Some checks are pending
Build / build (push) Waiting to run
Add a Node.js script that sets up LEGO Island game assets via symlinks:
- Accepts source path interactively or via --path/-p flag
- Case-insensitive file matching for cross-platform compatibility
- Validates all required files before making changes
- Supports optional extra/ and textures/ folders
- Includes --force/-f flag to skip deletion confirmation

Updates README with new setup step and script documentation.
2026-01-31 20:14:44 +01:00
Christian Semmler
15169c3ec5
Fix transition animation in config section
Some checks are pending
Build / build (push) Waiting to run
2026-01-30 16:32:51 -08:00
Christian Semmler
ff379338f9
Fix issue on Safari: audio not playing on first toggle 2026-01-30 15:01:30 -08:00
Christian Semmler
b5389b2685
Fix tooltip CSS issues on Config page
Some checks failed
Build / build (push) Has been cancelled
- Allow tooltips to overflow container when section is open
- Expand touch target for tooltip triggers on mobile devices

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 16:31:45 -08:00
Christian Semmler
5ce1b1ed69
Merge pull request #10 from isledecomp/svelte
Migrate frontend to Svelte 5
2026-01-25 10:08:08 -08:00
Christian Semmler
1703e0ec73
Improve development mode experience
- Show "DEVELOPMENT MODE" in footer instead of timestamp
- Disable offline install/uninstall when service worker unavailable
- Set __BUILD_TIME__ to null in dev mode for conditional rendering
2026-01-11 21:11:32 -07:00
Christian Semmler
adfea5e91b
Skip service worker in dev mode and copy isle.js/isle.wasm on build
- Skip service worker registration when running in dev mode to avoid 404 errors
- Add isle.js and isle.wasm copy step to production build
- Add build:ci script for CI builds without required wasm files
2026-01-11 20:59:55 -07:00
Christian Semmler
894546a468
Test CI 2026-01-11 19:51:08 -07:00
Christian Semmler
abe2b70871
Test CI 2026-01-11 19:50:20 -07:00
Christian Semmler
6a60a829ce
Add GitHub Actions workflow to verify warning-free builds 2026-01-11 19:43:20 -07:00
Christian Semmler
bb1deef26a Add complete animation list and fix select styling in debug panel 2026-01-11 19:28:45 -07:00
Christian Semmler
c4b1b0d226
Merge branch 'svelte' of github.com:isledecomp/isle.pizza into svelte 2026-01-11 19:16:55 -07:00
Christian Semmler
b47748f2ab
Update README.md 2026-01-12 03:16:30 +01:00
Christian Semmler
92d90de61b
Rename serviceWorker.js to service-worker.js 2026-01-11 19:15:18 -07:00
Christian Semmler
32a16b5da1
Rename project to isle.pizza 2026-01-11 19:12:23 -07:00
Christian Semmler
804a87e687
Migrate frontend to Svelte 5
- Replace vanilla JS with Svelte 5 components
- Add Vite build system with Terser optimization
- Reorganize assets into src/ and public/ directories
- Update README with setup instructions
2026-01-11 19:10:16 -07:00
Christian Semmler
4a55a478e2
Fixes 2026-01-04 16:57:57 -07:00
Christian Semmler
479edf1111
Fix tooltips on mobile 2026-01-04 16:43:13 -07:00
Christian Semmler
02ce28d00b
Address Safari issues 2026-01-04 16:18:52 -07:00
Christian Semmler
17eefb0be6
Improvements 2026-01-04 16:05:21 -07:00
Christian Semmler
96097a01bc
Update changelog 2026-01-04 15:40:51 -07:00
Christian Semmler
bd2c31bd79
Updates 2026-01-04 15:36:53 -07:00
Christian Semmler
e96ba299b7
Update config page 2026-01-04 15:31:19 -07:00
Christian Semmler
57a8cb17d9
Add Cancel animation 2026-01-04 14:40:33 -07:00
Christian Semmler
67a6548bba
Update sections 2026-01-04 14:28:36 -07:00
Christian Semmler
75a536692c
Add System tab 2026-01-04 14:12:26 -07:00
Christian Semmler
41e555ae17
Update free stuff page 2026-01-04 10:50:57 -07:00
Christian Semmler
4444ed09dc
Add congrats image to Free Stuff 2026-01-04 10:47:05 -07:00
Christian Semmler
3a7005c09c
Add voices section 2026-01-04 10:43:02 -07:00
Christian Semmler
10d1bf2376
Improve ReadMe page 2026-01-04 09:45:50 -07:00
Christian Semmler
c978263a2d
Update sw.js 2026-01-03 15:40:30 -07:00
Christian Semmler
efba2da6c9
Fix font size 2026-01-03 15:21:56 -07:00
Christian Semmler
054d84439c
Update index.html 2026-01-03 15:11:31 -07:00
Christian Semmler
369359daf3
Add update popup 2026-01-03 15:11:14 -07:00
Christian Semmler
d6588e2a23
Bugfix: invalid cache status in incognito windows 2026-01-03 14:50:54 -07:00
Christian Semmler
572219f703
Add debug menu 2026-01-01 09:34:47 -07:00
Christian Semmler
d3e395a63d
Add changelog section 2025-12-31 14:31:55 -07:00