Skip to content

v0.12.2

Particle Rendering Fix

The particle system failed to render in v0.12.1 — vertex data never reached the GPU. This release rewrites the particle render path:

  • ParticlePlugin now builds rotated quads directly into TransientBufferPool during collect(), using the standard DrawCommand path
  • Eliminates per-emitter intermediate heap allocations
  • New CMD_STATE_CUSTOM_DRAW flag on DrawCommand makes custom draw extensible instead of hardcoding RenderType checks

Extensible Asset Handlers

New registerAssetHandler() API lets plugins register custom asset type handlers:

  • Scene loading no longer hardcodes asset field handling logic
  • Builtin handlers (texture, Spine, material, font, etc.) lazy-initialize via builtinAssetHandlers.ts
  • Plugins can call registerAssetHandler() in build() to register custom asset types

Cross-Platform devicePixelRatio

PlatformAdapter interface now includes a devicePixelRatio() method:

  • Web and WeChat Mini Game platforms provide native implementations
  • Replaces platform-specific branching previously in base.ts

Memory Leak Fixes

Fixed multiple WASM memory leaks when entities are despawned:

  • Timeline/Tween: C++ timeline objects and tween entities were not freed on entity despawn — now automatically calls _tl_destroy and Tween.cancelAll() via onDespawn
  • Spine: SpineManager was not cleaned up on entity despawn — now automatically calls SpineManager.removeEntity()
  • Audio: audio handles were not stopped or released on entity despawn — now automatically stops and cleans up
  • Font resources: font resources were not released on scene unload — now cleaned up via releaseFont()

ECS Stability Improvements

Commands Exception Isolation

Commands.flush() now wraps each pending command in try-catch — a single command throwing no longer silently skips remaining commands in the queue.

Query Mut Entity Validation

Query Mut write-back paths (both iterator and forEach) now validate entity existence before writing back mutations, preventing crashes when entities are despawned mid-iteration via deferred Commands.

ScriptStorage Validation

ScriptStorage.set() now validates component data against schema (warn level), catching invalid data in hot iteration paths.

Scene and Plugin Error Recovery

  • Scene loading now cleans up already-created entities when component deserialization fails, preventing half-initialized entities from lingering
  • Plugin build() failures now trigger automatic rollback — the plugin is removed from installedPluginSet_, installed_plugins_, and installedPluginNames_

Internal Improvements

  • Eliminated module-level singletons: CollectionViewPlugin, TimelinePlugin, and PostProcessStack global state moved into plugin/class instances
  • Unified asset discovery via discoverSceneAssets() — scene loading, preloading, and runtime loading share a single discovery function
  • PostProcessStack dirty flag skips WASM sync when no mutations occurred
  • MaterialCache extracted from static globals into EngineContext with proper lifecycle cleanup
  • 11 UI plugins now declare explicit plugin dependencies, leveraging topological sort for initialization order

Bug Fixes

  • Fixed async startup systems potentially executing twice under concurrent tick() calls — added reentrant guard
  • Fixed web fileExists false positive under Tauri custom protocol — Tauri returns 200 for all HEAD requests, switched to GET + body cancel
  • Fixed Windows build failure when invoking emcmake.bat.bat files require cmd.exe /C shell execution
  • Fixed Windows build failure when emcmake.bat path contains spaces — path is now quoted
  • Fixed uniform buffer overflow writing out of bounds — overflow guard moved before writes