Conversation
🤖 Generated with GitHub Actions
These are needed because we cannot use `dart test -p chrome` to run tests.
The web_test_runner.dart script sets up the correct proxy + WASM bootstrap.
Run web tests (from thermion_dart/):
dart run tool/web_test_runner.dart \
--assets=../examples/assets test/some_tests.dart
- tool/web_test_runner.dart: single entry point that generates a
per-file HTML test wrapper (loads the multithreaded Filament WASM
module), starts the COI proxy, runs `dart test -p chrome`, and
prints a per-file pass/fail summary.
- tool/coi_proxy.dart: intercepting proxy that injects COOP/COEP/CORP
headers so the browser is cross-origin isolated and exposes
SharedArrayBuffer, which the pthreads Filament build requires.
- dart_test.yaml: configures the chrome platform used by the runner
(headful + --proxy-server routing through coi_proxy on port 8899)
and a 120s per-test timeout. Without it the runner's `dart test
-p chrome` launches headless Chrome with no proxy and the WASM
tests fail for lack of SharedArrayBuffer.
🤖 Generated with GitHub Actions
…yet.
- gizmo_tests.dart, projection_tests.dart,
view_dependent_texture_mapping_tests.dart, and the 'unlit fixed size
material' test in unlit_material_tests.dart reference APIs that were
removed or left as `throw Exception("TODO")` by the refactor
(GizmoAsset decoupled from ThermionAsset with no add/remove API;
TextureProjection.create unimplemented; setImage3D /
getProjectedPixelBuffer / getColorBuffer removed; createUnlitFixedSize
materialInstance removed; setCameraPosition removed). These can't be
made to pass until that work is finished, so their bodies are
preserved as block-commented reference with TODO(c9b41bd) headers
and main() left as a no-op so dart analyze is satisfied.
🤖 Generated with GitHub Actions
dart analyze fails CI on warnings by default (--fatal-warnings is on), but the repo has ~390 long-standing warnings (unused vars/imports, long lines, etc.) under CI's 3.12.2 analyzer — and ~82 under the local 3.13-dev toolchain — so it has never been warning-clean under any SDK, and warning counts differ across versions (a treadmill). The codebase is error-clean, so gate on errors only: - lint.yml: `dart analyze --no-fatal-warnings` (errors still fail). - analysis_options.yaml: exclude the generated FFI/JS-interop bindings (thermion_dart_ffi.g.dart / thermion_dart_js_interop.g.dart) from analysis — linting ffigen output is noise (dozens of unnecessary_cast). This is the right policy for a repo that's never been lint-clean; chasing version-specific warnings isn't worth it. Co-Authored-By: Claude <noreply@anthropic.com>
Note we longer use melos (this was originally chosen because we needed separate packages for each Flutter plugin but this is no longer the case). Also, thermion_dart & thermion_flutter will now be versioned in lock-step.
…evant for local development) and pin to current version.
🤖 Generated with GitHub Actions
Engine_createRenderer existed but had no matching destroy in the C API, even though filament::Engine::destroy(Renderer*) is a documented public API (Engine.h:950). Adds: - Engine_destroyRenderer(TEngine*, TRenderer*) — sync, mirrors the other Engine_destroy* helpers in TEngine.cpp. - Engine_destroyRendererRenderThread(TEngine*, TRenderer*, requestId, VoidCallback) — render-thread variant that proxies completion back to the calling thread, matching the pattern of Engine_destroyView / Engine_destroyScene / Engine_destroySwapChain.
stbi_load_from_memory returns a malloc'd buffer we own. LinearImage above copies/converts from it; release the intermediate before returning so it doesn't leak per decode (significant on repeated PNG decodes). Also delete the LinearImage on a failed decode so it isn't leaked from the error path.
generateMipmaps() requires BLIT_SRC | BLIT_DST per Filament's Texture::generateMipmaps doc. Native backends often relax this, WebGL does not (throws PreconditionPanic). Include the flags whenever the caller asks for >1 level so the mip path works on every backend.
WebGL/ANGLE constrains the format/type combo for readPixels by the bound framebuffer's color format, but swapchain vs. FLOAT render target differ. Add a native Texture_getFormat() so capture() can keep FLOAT reads from a FLOAT color attachment and only downgrade to UBYTE for RGBA8. - native Texture_getFormat() in TTexture.cpp/.h returning InternalFormat - FFITexture.getFormat() now calls native instead of throwing - getFormat exposed through FFIFilamentApp for per-view readback
Ktx2Reader internally calls Texture::Builder().build, which on web must happen on the engine's render thread; routing through the *RenderThread variant avoids the abort. - Ktx2Reader_createTextureRenderThread in ThermionDartRenderThreadApi.cpp/.h - FFIFilamentApp.loadKtx2 awaits the render-thread variant
Adding Texture_getFormat + Ktx2Reader_createTextureRenderThread to the native headers (via the capture/ktx2 fixes) caused ffigen to emit RenderManager_setPaused and NativeLibrary into both ffi.g.dart and js_interop.g.dart. thermion_flutter_plugin_web.dart pulls js_interop directly and ffi.g.dart transitively via thermion_flutter.dart, so those symbols collided (4x ambiguous_import). Hide the two duplicated names from the thermion_flutter.dart re-export; they are provided unambiguously by the js_interop import.
🤖 Generated with GitHub Actions
Move the frame-scheduling machinery (vsync callback dispatch, port-mode debug transport, Flutter-synced Linux loop, diagnostic timing) out of ThermionFlutterPluginImpl's static state and into a dedicated FrameScheduler singleton (lib/src/platform/src/frame_scheduler.dart). Pure refactor: the plugin now delegates to FrameScheduler.instance (stop / start / startFlutterSynced / pause / resume / setOnFrame) and the resize path uses pause()+isRendering instead of private _resizing/ _rendering flags, but runtime behaviour is unchanged. No lifecycle listener, no new tests. Co-Authored-By: Claude <noreply@anthropic.com>
🤖 Generated with GitHub Actions
refactor: extract FrameScheduler into its own class
* feat: pause rendering on app background via WidgetsBindingObserver Register ThermionFlutterPluginImpl as a WidgetsBindingObserver and stop (or, on Linux, pause) the native FrameScheduler when the app is backgrounded, restarting it on resume. Also harden FrameScheduler against two real failure modes uncovered while adding the listener: - start()/startFlutterSynced() are now idempotent, so a rapid pause->resume can't double-register the callback/port or double-start the native scheduler. - resume() re-arms the Flutter frame callback in Flutter-synced (Linux) mode; previously the persistent callback stopped re-arming itself once paused, freezing the Linux render loop after the first background->foreground transition. - _onFrame now counts dropped vsyncs (was logged as drop=N but never incremented). Adds an integration test (examples/flutter/quickstart/integration_test/ lifecycle_test.dart) covering the scheduler state machine and lifecycle recovery, plus a macOS CI step to run it. Builds on the FrameScheduler extraction in the base branch.
Fix the ordering of format/lint/generate bindings. Fold format + analyze into Generate Artifacts, after `make dart-bindings`, so analyze always sees current bindings and only one workflow pushes. Add a workflow_dispatch `force_regenerate` input to recover a branch whose checked-in bindings are already stale (the current develop state).
🤖 Generated with GitHub Actions
Previously would hang indefinitely, test synthesized AppLifecycleState.paused via the binding and then pumped while still in that state. SchedulerBinding flips framesEnabled=false on paused/ hidden/detached, making scheduleFrame() a no-op; the live integration-test binding's pump() waits on a frame that never fires, deadlocking the test until the GHA job ceiling. Drive the full sequence (inactive->hidden->paused->hidden->inactive-> resumed) so states are distinct (Flutter ignores duplicates) and end at resumed, which restores framesEnabled and re-arms the frame loop. Pump only after resumed, while framesEnabled is true.
🤖 Generated with GitHub Actions
…atform compatibility (cherry picked from commit 9487372)
- test/src/test_io{,_native,_web}.dart: conditional-import shim decoupling
the harness from dart:io (native keeps File/Directory/Platform; web stubs
file IO, selects OPENGL backend, calls NativeLibrary.initBindings).
- test/helpers.dart: route all File/Directory/Platform usage through the
shim (outDirPath is now a String); setup() awaits initTestBindings.
- test/engine_tests.html: package:test custom-HTML wrapper.
- tool/web_test_runner.dart: Chrome test driver (--name / -N passthrough).
- tool/coi_proxy.dart: COOP/COEP proxy for cross-origin isolation.
- native (RenderThread, ThermionDartRenderThreadApi, TGltfAssetLoader,
TNameComponentManager, TAnimationManager, CMakeLists): render-thread +
c_api plumbing for the web build.
- test/{view,projection,view_dependent_texture_mapping}_tests.dart,
viewer_lifecycle_test.dart: test updates for the shim + web paths.
- Replace dart:io File.readAsBytesSync() with loadResourceBytes() so the PNG/JPEG/KTX2 reads work under the browser harness (the COI proxy serves the bytes via the thermion.assets sentinel host). - Re-export src/test_io.dart from helpers.dart so tests don't have to import the shim directly. - Switch the generate-mipmaps test to RGBA32F + RGBA + FLOAT + requireAlpha so the texture format is color-renderable on WebGL (RGB32F isn't, even with EXT_color_buffer_float) and generateMipmaps' preconditions are met. - Add getFormat round-trip tests for RGBA32F / RGBA16F / RGBA8 / R16F / DEPTH32F and a RenderTarget.getColorTexture format-readback test, to lock in the new Texture_getFormat binding. - Document web test runner in README so new contributors invoke tool/web_test_runner.dart instead of `dart test -p chrome` directly (the wrapper stamps the per-file HTML host and manages the COI proxy lifecycle).
🤖 Generated with GitHub Actions
The web multi-viewer feature (b48c421) added `late final int _maxBatch` assigned in initState from webOptions.maxViewers, and the later "cap to 1 viewer on web" change (971f369) added a second `final int _maxBatch = kIsWeb ? 1 : 64` without removing the first — a duplicate field declaration that broke `flutter build windows` (error: '_maxBatch' is already declared in this scope). Keep the newer cap-to-1 field; drop the stale late-final declaration and its initState assignment. Co-Authored-By: Claude <noreply@anthropic.com>
…n check Releases can no longer ship without all dart + flutter-build checks green: the publish job now needs both `validate` and a `tests` job that calls run-tests.yml (only on a real tag push, so manual dry-run dispatch stays fast). Also fix a latent bug in the already-published check: the bash `want` local was passed into a single-quoted python -c script that referenced a bare `want` name (undefined -> NameError -> function always returned "not found"). Pass the version via argv instead. Co-Authored-By: Claude <noreply@anthropic.com>
The shared root README (symlinked into both thermion_dart and thermion_flutter) referenced the logo via a relative path (docs/logo.png). That works on GitHub, but on pub.dev relative image paths resolve against the *package* root, and docs/ is not included in either published package — so the logo disappeared from the pub.dev page. Restore an absolute raw.githubusercontent.com URL (SHA-pinned so already-published versions stay stable), matching how the pre-standardization per-package README referenced the logo. Co-Authored-By: Claude <noreply@anthropic.com>
Replace the broken user-attachment video link in the top-level README (also published to pub.dev via the thermion_dart / thermion_flutter README symlinks) with a clickable YouTube thumbnail-link. Add examples/dart/cli_headless/bin/render_demo.dart, the headless renderer that produced the demo: BusterDrone under the the_sky_is_on_fire HDRI with key/fill/rim point lights, ACES tone mapping, 120fps orbit+dolly over the full glTF animation, advanced on the render thread via animationManager. Co-Authored-By: Claude <noreply@anthropic.com>
Switch output resolution and framing with --preset=desktop|iphone. - desktop: 1280x720 (16:9), unchanged. - iphone: 1170x2532 (19.5:9 portrait, iPhone 15 Pro point resolution), with a larger orbit radius + gentler dolly so the wide drone stays framed without clipping the narrow portrait frame. Each preset renders into its own output/frames_<preset>/ folder so they coexist, and all framing (radius/height + their amplitudes) is per-preset. Also adds --no-skybox to render the subject against black (keeping the IBL) for verifying framing/silhouette without a busy background. Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com> EOF && \ echo "=== pushing ===" && git push origin develop 2>&1
* fix(animation): dispatch setGltfAnimationTime on the render thread
* fix: correct procedural geometry winding and sphere poles * fix: preserve WebAssembly native output buffers * fix(web): enable bloom options
Drop the `push: branches: [develop]` trigger from deploy.yml so Cloudflare deploys fire only on a release tag (v*) or manual dispatch — not on every commit to develop. Co-authored-by: Claude <noreply@anthropic.com>
…rkflow - publish-pub-dev: publish now waits on verify-artifacts and verify-swift-bindings gates plus the test suite (needs chain), so a release can never ship stale generated bindings or red tests - generate-artifacts / generate-swift-bindings: gain a reusable workflow_call verify mode (regenerate + fail on stale diff); no longer self-trigger on v* tags, which previously tried to move the tag and landed nowhere - release.yml (new): dispatch-driven release entry point - validates the version against both pubspecs, runs the verify gates + test matrix, then creates and pushes the annotated v<version> tag via the RELEASE_TOKEN PAT (GITHUB_TOKEN tag pushes don't trigger workflows) - docs/RELEASING.md: runbook rewritten for the new flow + RELEASE_TOKEN one-time setup Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.