Compare commits
53 Commits
thermion_f
...
thermion_d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
961b2ae1ee | ||
|
|
a7ac118899 | ||
|
|
d92ad4ef12 | ||
|
|
437e91e7bd | ||
|
|
e169bf6c41 | ||
|
|
23b060c329 | ||
|
|
5fd0a10630 | ||
|
|
ddfb649733 | ||
|
|
ecffc5b62a | ||
|
|
429b8eb93b | ||
|
|
413faec849 | ||
|
|
433b6373a9 | ||
|
|
ad2c5afb7f | ||
|
|
a561c847a7 | ||
|
|
ef7ba24ecc | ||
|
|
ee176d2684 | ||
|
|
fa168df28f | ||
|
|
ba3d016c1a | ||
|
|
e04d8e76c2 | ||
|
|
353b33b7c3 | ||
|
|
3c1b26af2c | ||
|
|
b4ea80a84c | ||
|
|
db44bc6f74 | ||
|
|
c668549fb0 | ||
|
|
a66703b61c | ||
|
|
cb8943ff72 | ||
|
|
9f59577f90 | ||
|
|
b86145d4c6 | ||
|
|
cb8672f120 | ||
|
|
92578426ac | ||
|
|
4a6479c4d8 | ||
|
|
2244d3fcb6 | ||
|
|
003fd59269 | ||
|
|
77e6ef7568 | ||
|
|
6f07d406f8 | ||
|
|
bf5551e278 | ||
|
|
64577af352 | ||
|
|
951894be41 | ||
|
|
c64b2b8659 | ||
|
|
322e77d2b7 | ||
|
|
a8a52bb2f4 | ||
|
|
c7dfd293e2 | ||
|
|
cf2498b45f | ||
|
|
edb7538c36 | ||
|
|
b023e2fb97 | ||
|
|
b51cc4b1d1 | ||
|
|
d995ed8843 | ||
|
|
b0d34bf6a8 | ||
|
|
2e28b0379d | ||
|
|
c899e30a7b | ||
|
|
37f8558794 | ||
|
|
3cfa26d284 | ||
|
|
b22a82e181 |
39
.github/workflows/dart.yml
vendored
39
.github/workflows/dart.yml
vendored
@@ -7,6 +7,20 @@ on:
|
||||
branches: [ "develop" ]
|
||||
|
||||
jobs:
|
||||
compile-web-wasm:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup CMake
|
||||
uses: jwlawson/actions-setup-cmake@v2
|
||||
with:
|
||||
cmake-version: '3.25.0' # or 'latest'
|
||||
- name: Setup Emscripten
|
||||
uses: mymindstorm/setup-emsdk@v14
|
||||
with:
|
||||
version: 'latest'
|
||||
- name: Compile web
|
||||
run: make wasm
|
||||
dart-tests:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
@@ -58,7 +72,6 @@ jobs:
|
||||
path: |
|
||||
${{ github.workspace }}/thermion_dart/.dart_tool/thermion_dart/log/build.log
|
||||
retention-days: 5
|
||||
|
||||
flutter_examples:
|
||||
name: flutter_examples
|
||||
runs-on: macos-latest
|
||||
@@ -104,8 +117,28 @@ jobs:
|
||||
# D:\a\thermion\thermion\thermion_dart\.dart_tool\thermion_dart\log\build.log
|
||||
/Users/runner/work/thermion/thermion/thermion_dart/.dart_tool/thermion_dart/log/build.log
|
||||
retention-days: 5
|
||||
|
||||
|
||||
flutter_examples_windows:
|
||||
name: flutter_examples_windows
|
||||
runs-on: windows-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: examples/flutter
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Flutter
|
||||
uses: subosito/flutter-action@v2
|
||||
with:
|
||||
channel: master
|
||||
- run: cd quickstart && flutter pub get && flutter build windows
|
||||
- run: cd picking && flutter pub get && flutter build windows
|
||||
- name: Upload logs
|
||||
if: failure() || steps.build.outcome == 'failure'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: build-logs
|
||||
path: |
|
||||
D:\a\thermion\thermion\thermion_dart\.dart_tool\thermion_dart\log\build.log
|
||||
retention-days: 5
|
||||
# thermion_dart:
|
||||
# name: thermion_dart
|
||||
# runs-on: macos-latest
|
||||
|
||||
235
CHANGELOG.md
235
CHANGELOG.md
@@ -3,7 +3,7 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## 2025-07-03
|
||||
## 2025-07-24
|
||||
|
||||
### Changes
|
||||
|
||||
@@ -11,95 +11,184 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
|
||||
|
||||
Packages with breaking changes:
|
||||
|
||||
- [`thermion_dart` - `v0.3.0`](#thermion_dart---v030)
|
||||
- [`thermion_flutter` - `v0.3.0`](#thermion_flutter---v030)
|
||||
- [`thermion_flutter_method_channel` - `v0.3.0`](#thermion_flutter_method_channel---v030)
|
||||
- There are no breaking changes in this release.
|
||||
|
||||
Packages with other changes:
|
||||
|
||||
- [`thermion_flutter_web` - `v0.3.0`](#thermion_flutter_web---v030)
|
||||
- [`thermion_flutter_platform_interface` - `v0.3.0`](#thermion_flutter_platform_interface---v030)
|
||||
- [`thermion_dart` - `v0.3.3`](#thermion_dart---v033)
|
||||
- [`thermion_flutter_method_channel` - `v0.3.3`](#thermion_flutter_method_channel---v033)
|
||||
- [`thermion_flutter_platform_interface` - `v0.3.3`](#thermion_flutter_platform_interface---v033)
|
||||
- [`thermion_flutter_web` - `v0.3.3`](#thermion_flutter_web---v033)
|
||||
- [`thermion_flutter` - `v0.3.3`](#thermion_flutter---v033)
|
||||
|
||||
---
|
||||
|
||||
#### `thermion_dart` - `v0.3.0`
|
||||
#### `thermion_dart` - `v0.3.3`
|
||||
|
||||
- **REFACTOR**: gizmo/input handler improvements.
|
||||
- **REFACTOR**: add createGizmoRenderThread.
|
||||
- **REFACTOR**: Gizmo internals.
|
||||
- **REFACTOR**: dont require GizmoInputHandler to wrap an existing InputHandler (you can do this by creating your own InputHandler that wraps two children.
|
||||
- **FIX**: glTF instancing when loaded via buffer.
|
||||
- **FIX**: don't return entity from SceneManager_addLightRenderThread.
|
||||
- **FIX**: return light entity from SceneManager.
|
||||
- **FIX**: store reference to material instances in ThermionViewer so they can be cleaned up on dispose.
|
||||
- **FIX**: remove MaterialInstance from SceneManager storage when destroyed.
|
||||
- **FIX**: add destroyCamera to ThermionViewer interface.
|
||||
- **FIX**: UV calculation for geometry.
|
||||
- **FIX**: use createGizmoRenderThread.
|
||||
- **FIX**: remove MaterialInstance from SceneManager storage when destroyed.
|
||||
- **FIX**: move removeIbl to render thread.
|
||||
- **FIX**: move material/instance creation to render thread.
|
||||
- **FIX**: allow destroying instances independently of owner.
|
||||
- **FIX**: remove MaterialInstance from SceneManager storage when destroyed.
|
||||
- **FIX**: use render thread methods for grid overlay creation and create ubershader instance.
|
||||
- **FIX**: only use Windows-style ndkRoot when building on Windows.
|
||||
- **FIX**: set overlay layer visibility when adding grid.
|
||||
- **FIX**: only use Windows-style ndkRoot when building on Windows.
|
||||
- **FIX**: when creating geometry, normals/uvs are set to false by default. remove wirefame camera container (can now be replaced by bounding box methods.
|
||||
- **FIX**: fix highlights after first.
|
||||
- **FEAT**: remove bounding box from SceneAsset and create renderable wireframe bounding box in ThermionAsset.
|
||||
- **FEAT**: add setTransparencyMode to Dart Material class.
|
||||
- **FEAT**: expose attached entity as Stream on GizmoInputHandler.
|
||||
- **FEAT**: allow custom material for grid overlay, and material creation from Uint8List.
|
||||
- **FEAT**: allow setting material instance directly on ThermionAsset.
|
||||
- **FEAT**: allow passing custom material for grid overlay.
|
||||
- **FEAT**: allow passing custom material for grid overlay.
|
||||
- **FEAT**: allow passing custom material for grid overlay.
|
||||
- **FEAT**: more rotation gizmo improvements.
|
||||
- **FEAT**: rotation gizmo improvements.
|
||||
- **FEAT**: add rotation gizmo.
|
||||
- **FEAT**: add rotation gizmo asset + resource file.
|
||||
- **FEAT**: add rotation gizmo asset + resource file.
|
||||
- **FEAT**: use existing material instances when creating an instance of GeometrySceneAsset and no material instance is passed.
|
||||
- **FEAT**: re-implement grid overlay.
|
||||
- **FEAT**: add gizmo.glb to assets/resources.
|
||||
- **FEAT**: add TRACE macro.
|
||||
- **FEAT**: update Filament to v1.56.4.
|
||||
- **FEAT**: expose setCastShadows/setReceiveShadows.
|
||||
- **FEAT**: re-add uvScale, vertexScale to unlit material.
|
||||
- **FEAT**: re-add uvScale, vertexScale to unlit material.
|
||||
- **BREAKING** **REFACTOR**: move light methods from FilamentViewer to SceneManager/TLightManager and rename clearLights/clearAssets to destroyLights/destroyAssets.
|
||||
- **BREAKING** **REFACTOR**: rename removeAsset to destroyAsset.
|
||||
- **BREAKING** **FIX**: rename removeEntity to removeAsset.
|
||||
- **BREAKING** **FEAT**: change default near/far to 0.1/100.0.
|
||||
- **BREAKING** **FEAT**: use raw pointer scale (>1 meaning zoom in, <1 meaning zoom out) rather than binary -1/1 for DelegateInputHandler.
|
||||
- **BREAKING** **FEAT**: remove Viewer setRenderTarget method (use the View method instead).
|
||||
- Bump "thermion_dart" to `0.3.3`.
|
||||
|
||||
#### `thermion_flutter` - `v0.3.0`
|
||||
#### `thermion_flutter_method_channel` - `v0.3.3`
|
||||
|
||||
- **REFACTOR**: rename ThermionFlutterTexture->PlatformTextureDescriptor.
|
||||
- **FIX**: rename msPerFrame property.
|
||||
- **FEAT**: add FocusNode to ThermionListenerWidget.
|
||||
- **FEAT**: use new createTextureAndBindToView in ThermionTextureWidget.
|
||||
- **BREAKING** **REFACTOR**: move light methods from FilamentViewer to SceneManager/TLightManager and rename clearLights/clearAssets to destroyLights/destroyAssets.
|
||||
- **BREAKING** **FEAT**: remove superseded ThermionWindows widget.
|
||||
- **BREAKING** **FEAT**: rename thermion_flutter_ffi package to thermion_flutter_method_channel.
|
||||
- Bump "thermion_flutter_method_channel" to `0.3.3`.
|
||||
|
||||
#### `thermion_flutter_method_channel` - `v0.3.0`
|
||||
#### `thermion_flutter_platform_interface` - `v0.3.3`
|
||||
|
||||
- **REFACTOR**: rename ThermionFlutterTexture->PlatformTextureDescriptor.
|
||||
- **BREAKING** **FEAT**: rename thermion_flutter_ffi package to thermion_flutter_method_channel.
|
||||
- Bump "thermion_flutter_platform_interface" to `0.3.3`.
|
||||
|
||||
#### `thermion_flutter_web` - `v0.3.0`
|
||||
#### `thermion_flutter_web` - `v0.3.3`
|
||||
|
||||
- **REFACTOR**: rename ThermionFlutterTexture->PlatformTextureDescriptor.
|
||||
- Bump "thermion_flutter_web" to `0.3.3`.
|
||||
|
||||
#### `thermion_flutter_platform_interface` - `v0.3.0`
|
||||
#### `thermion_flutter` - `v0.3.3`
|
||||
|
||||
- **REFACTOR**: rename ThermionFlutterTexture->PlatformTextureDescriptor.
|
||||
- **FEAT**: create separate createTexture and createTextureAndBindToView interface methods.
|
||||
- Bump "thermion_flutter" to `0.3.3`.
|
||||
|
||||
|
||||
## 2025-07-17
|
||||
|
||||
### Changes
|
||||
|
||||
---
|
||||
|
||||
Packages with breaking changes:
|
||||
|
||||
- There are no breaking changes in this release.
|
||||
|
||||
Packages with other changes:
|
||||
|
||||
- [`thermion_dart` - `v0.3.3-pre`](#thermion_dart---v033-pre)
|
||||
- [`thermion_flutter` - `v0.3.3-pre`](#thermion_flutter---v033-pre)
|
||||
- [`thermion_flutter_method_channel` - `v0.3.3-pre`](#thermion_flutter_method_channel---v033-pre)
|
||||
- [`thermion_flutter_platform_interface` - `v0.3.3-pre`](#thermion_flutter_platform_interface---v033-pre)
|
||||
- [`thermion_flutter_web` - `v0.3.3-pre`](#thermion_flutter_web---v033-pre)
|
||||
|
||||
---
|
||||
|
||||
#### `thermion_dart` - `v0.3.3-pre`
|
||||
|
||||
- **FIX**: fix Windows build.dart.
|
||||
- **FIX**: add nan/negative checks inside setLensProjection.
|
||||
|
||||
#### `thermion_flutter` - `v0.3.3-pre`
|
||||
|
||||
- **DOCS**: replace thermion_flutter README with symlink to thermion_dart README.
|
||||
|
||||
#### `thermion_flutter_method_channel` - `v0.3.3-pre`
|
||||
|
||||
- **FEAT**: allow passing renderTargetColorTextureFormat via ThermionFlutterOptions.
|
||||
|
||||
#### `thermion_flutter_platform_interface` - `v0.3.3-pre`
|
||||
|
||||
- **FEAT**: allow passing renderTargetColorTextureFormat via ThermionFlutterOptions.
|
||||
|
||||
#### `thermion_flutter_web` - `v0.3.3-pre`
|
||||
|
||||
- Bump "thermion_flutter_web" to `0.3.3-pre`.
|
||||
|
||||
|
||||
## 2025-07-08
|
||||
|
||||
### Changes
|
||||
|
||||
---
|
||||
|
||||
Packages with breaking changes:
|
||||
|
||||
- There are no breaking changes in this release.
|
||||
|
||||
Packages with other changes:
|
||||
|
||||
- [`thermion_dart` - `v0.3.2`](#thermion_dart---v032)
|
||||
- [`thermion_flutter` - `v0.3.2`](#thermion_flutter---v032)
|
||||
- [`thermion_flutter_method_channel` - `v0.3.2`](#thermion_flutter_method_channel---v032)
|
||||
- [`thermion_flutter_web` - `v0.3.2`](#thermion_flutter_web---v032)
|
||||
- [`thermion_flutter_platform_interface` - `v0.3.2`](#thermion_flutter_platform_interface---v032)
|
||||
|
||||
---
|
||||
|
||||
#### `thermion_dart` - `v0.3.2`
|
||||
|
||||
- Bump "thermion_dart" to `0.3.2`.
|
||||
|
||||
#### `thermion_flutter` - `v0.3.2`
|
||||
|
||||
- Bump "thermion_flutter" to `0.3.2`.
|
||||
|
||||
#### `thermion_flutter_method_channel` - `v0.3.2`
|
||||
|
||||
- Bump "thermion_flutter_method_channel" to `0.3.2`.
|
||||
|
||||
#### `thermion_flutter_web` - `v0.3.2`
|
||||
|
||||
- **FIX**: add missing destroySwapchain argument for web.
|
||||
|
||||
#### `thermion_flutter_platform_interface` - `v0.3.2`
|
||||
|
||||
- Bump "thermion_flutter_platform_interface" to `0.3.2`.
|
||||
|
||||
|
||||
## 2025-07-08
|
||||
|
||||
### Changes
|
||||
|
||||
---
|
||||
|
||||
Packages with breaking changes:
|
||||
|
||||
- There are no breaking changes in this release.
|
||||
|
||||
Packages with other changes:
|
||||
|
||||
- [`thermion_dart` - `v0.3.1`](#thermion_dart---v031)
|
||||
- [`thermion_flutter` - `v0.3.1`](#thermion_flutter---v031)
|
||||
- [`thermion_flutter_method_channel` - `v0.3.1`](#thermion_flutter_method_channel---v031)
|
||||
- [`thermion_flutter_web` - `v0.3.1`](#thermion_flutter_web---v031)
|
||||
- [`thermion_flutter_platform_interface` - `v0.3.1`](#thermion_flutter_platform_interface---v031)
|
||||
|
||||
---
|
||||
|
||||
#### `thermion_dart` - `v0.3.1`
|
||||
|
||||
- **REFACTOR**: remove covariant keyword from createInstance args.
|
||||
- **FIX**: add flush() to skybox/IBL destroy methods to ensure that textre upload callbacks are completed to avoid stalling.
|
||||
- **FIX**: duplicate setting for _grid.
|
||||
|
||||
#### `thermion_flutter` - `v0.3.1`
|
||||
|
||||
- **FIX**: addDestroySwapchain argument to createViewer() (true by default). This is only used on iOS/macOS where a single swapchain is shared between all render targets.
|
||||
- **DOCS**: fix typo in link.
|
||||
- **DOCS**: remove code from thermion_flutter README.md and point to docs/repository example instead.
|
||||
|
||||
#### `thermion_flutter_method_channel` - `v0.3.1`
|
||||
|
||||
- **FIX**: addDestroySwapchain argument to createViewer() (true by default). This is only used on iOS/macOS where a single swapchain is shared between all render targets.
|
||||
|
||||
#### `thermion_flutter_web` - `v0.3.1`
|
||||
|
||||
#### `thermion_flutter_platform_interface` - `v0.3.1`
|
||||
|
||||
- **FIX**: addDestroySwapchain argument to createViewer() (true by default). This is only used on iOS/macOS where a single swapchain is shared between all render targets.
|
||||
|
||||
# Change Log
|
||||
|
||||
#### v0.3.0
|
||||
|
||||
This release involved considerable internal refactoring, allowing us to expose more Filament functionality on the Dart side. Previously, most of this functionality was
|
||||
rigidly implemented in C++ and didn't allow for end-users to take advantage of Filament directly.
|
||||
|
||||
This also means there are a number of breaking changes from `0.2.1`. To summarize:
|
||||
|
||||
- `ViewerWidget` has been introduced. This is a Flutter widget for users who only need basic rendering and don't need/want to deal with camera/materials/etc directly.
|
||||
- Users who want more fine-grained control than a `ViewerWidget` can still work with `ThermionViewer` and `ThermionWidget`.
|
||||
- The singleton `FilamentApp.instance` exposes methods for working almost directly with the underlying Filament engine (e.g. loading custom materials from `Uint8List`, creating textures, etc).
|
||||
- New interfaces have been added for `Material`, `MaterialInstance`, `Texture`, `View`, `Scene` and `Camera`.
|
||||
- `ThermionAsset` replaces `ThermionEntity` as the main interface for scene objects.
|
||||
- Transforms/material instances should be set directly by `asset.setTransform`, `asset.setMaterialInstanceAt`
|
||||
- Material properties can be set directly on the `MaterialInstance`, e.g. `materialInstance.setParameterFloat4("baseColorFactor", 1.0, 0.0, 0.0, 1.0);
|
||||
- Linux binaries have been added to `thermion_dart`. This package can be run on Linux (which we are using for CI and automated testing) but there are not yet any Flutter bindings, so `thermion_flutter` cannot run on Linux yet.
|
||||
- On Windows, `thermion_flutter` now uses the Vulkan backend. This is still experimental and will have limited supported on older hardware (pre-2018).
|
||||
- Web support for `thermion_dart` has now reached parity with other platforms, though should still be considered experimental. Some manual steps are required to run in a Flutter app or a Dart web app.
|
||||
|
||||
## 2025-01-08
|
||||
|
||||
### Changes
|
||||
|
||||
17
Makefile
17
Makefile
@@ -1,8 +1,17 @@
|
||||
wasm:
|
||||
cd thermion_dart/native/web &&\
|
||||
mkdir -p build &&\
|
||||
cd build &&\
|
||||
emcmake cmake .. &&\
|
||||
@if [ ! -f thermion_dart/native/web/lib/release/filament-v1.58.0-web-release.zip ]; then \
|
||||
echo "Downloading filament-v1.58.0-web-release.zip..."; \
|
||||
mkdir -p thermion_dart/native/web/lib/release; \
|
||||
curl -L -o thermion_dart/native/web/lib/release/filament-v1.58.0-web-release.zip \
|
||||
https://pub-c8b6266320924116aaddce03b5313c0a.r2.dev/filament-v1.58.0-web-release.zip; \
|
||||
echo "Extracting filament-v1.58.0-web-release.zip..."; \
|
||||
cd thermion_dart/native/web/lib/release && \
|
||||
unzip filament-v1.58.0-web-release.zip; \
|
||||
fi
|
||||
cd thermion_dart/native/web && \
|
||||
mkdir -p build && \
|
||||
cd build && \
|
||||
emcmake cmake .. && \
|
||||
emmake make
|
||||
wasm-clean:
|
||||
cd thermion_dart/native/web && rm -rf build
|
||||
|
||||
@@ -79,4 +79,4 @@ Thank you to the following people:
|
||||
- @LukasPoque for CI/refactoring work
|
||||
- @alexmercerind for his work on integrating ANGLE textures on Flutter Windows
|
||||
- @BrutalCoding for documentation fixes
|
||||
|
||||
- @chenriji for testing and bug fixes
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"Getting Started",
|
||||
[
|
||||
["Overview", "/"],
|
||||
["Getting Started", "/getting_started"],
|
||||
["Quick Start", "/quickstart"],
|
||||
["Viewer", "/viewer"],
|
||||
["Camera Manipulation", "/camera_manipulation"]
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
## Camera Manipulation (Flutter)
|
||||
|
||||
> You can find the entire project below in the [flutter/quickstart](https://github.com/nmfisher/thermion/examples/flutter/camera_manipulation) folder.
|
||||
|
||||
A `ThermionListenerWidget` is one option for manipulating the camera with an input device (e.g. mouse or touchscreen gestures).
|
||||
|
||||
This will generally wrap a `ThermionWidget`, meaning the entire viewport will act as a receiver for gesture events.
|
||||
|
||||
> You can position this independently (for example, stacked vertically beneath the viewport), but this will not translate picking queries correctly.
|
||||
|
||||
```
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(children: [
|
||||
if (_thermionViewer != null)
|
||||
Positioned.fill(
|
||||
child: ThermionListenerWidget(
|
||||
inputHandler:
|
||||
DelegateInputHandler.fixedOrbit(_thermionViewer!)
|
||||
..setActionForType(InputType.MMB_HOLD_AND_MOVE, InputAction.ROTATE)
|
||||
..setActionForType(InputType.SCALE1, InputAction.ROTATE)
|
||||
..setActionForType(InputType.SCALE2, InputAction.ZOOM)
|
||||
..setActionForType(InputType.SCROLLWHEEL, InputAction.ZOOM),
|
||||
child: ThermionWidget(
|
||||
viewer: _thermionViewer!,
|
||||
))),
|
||||
]);
|
||||
```
|
||||
|
||||
`ThermionListenerWidget` is a very simple widget; it simply forwards pointer, gesture and keyboard events to the provided [InputHandler], which must decide how to interpret those events.
|
||||
|
||||
For example, one [InputHandler] implementation might interpret mouse pointer movement as "rotate the camera", whereas a separate implementation might interpret it as "translate this specific entity".
|
||||
|
||||
Thermion provides two default InputHandler implementations for manipulating the camera: [DelegateInputHandler.fixedOrbit] and [DelegateInputHandler.flight].
|
||||
|
||||
[DelegateInputHandler.fixedOrbit] will rotate the camera in a fixed orbit around a target point (the origin, by default), and also allow zooming in/out (subject to a minimum distance, which is configurable).
|
||||
|
||||
By default, [DelegateInputHandler.fixedOrbit] will:
|
||||
- rotate the camera when the middle mouse button is held and the pointer is moved (on desktop), and when a single swipe left/right/up/down is detected (on mobile)
|
||||
- zoom the camera when the scroll wheel is scrolled up/down (on desktop), and when a pinch gesture is detected (on mobile)
|
||||
|
||||
You can change the action for a specific input type by calling `setActionForType`; for example, if you wanted to rotate the camera by moving the mouse pointer while holding the left mouse button, you would call:
|
||||
|
||||
```
|
||||
setActionForType(InputType.LMB_HOLD_AND_MOVE, InputAction.ROTATE)
|
||||
```
|
||||
|
||||
See the [InputType] and [InputAction] enums for available input types and actions.
|
||||
|
||||
[DelegateInputHandler.flight] will translate keyboard and mouse/touchscreen gestures to free flight camera manipulation.
|
||||
|
||||
By default:
|
||||
- holding the middle mouse button will control the pitch/roll/yaw of the camera
|
||||
- holding the left mouse button will pan the camera left/right/up/down
|
||||
- the middle mouse button will zoom/dolly the camera in/out
|
||||
- the WASD keys will pan the camera left/right/up/down and dolly the camera forward/backward
|
||||
|
||||
If these don't exactly fit your use case, you can create your own [InputHandler] implementation. If you think it would be useful to other users, please feel free to submit a PR for your implementation to be included in the base Thermion package.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
40
docs/getting_started.mdx
Normal file
40
docs/getting_started.mdx
Normal file
@@ -0,0 +1,40 @@
|
||||
## Getting Started
|
||||
|
||||
Thermion currently requires the Flutter `master` channel with the `native-assets` experiment enabled.
|
||||
|
||||
1. Switch to Flutter master channel, upgrade Flutter, create a new project, then add `thermion_flutter` as a dependency
|
||||
|
||||
```bash
|
||||
$ flutter channel master
|
||||
$ flutter upgrade
|
||||
$ flutter config --enable-native-assets
|
||||
$ cd your_flutter_project
|
||||
$ flutter pub add thermion_flutter
|
||||
```
|
||||
|
||||
2. If running on iOS or MacOS, change the minimum deployment target to OSX 13
|
||||
|
||||
<Accordion title="Click to open iOS/MacOS instructions">
|
||||
|
||||
Make sure the `platform` entry refers to `13.0` in your Podfile.
|
||||
|
||||
In `macos/Podfile` (for macOS):
|
||||
```
|
||||
platform :osx, '13.0'
|
||||
```
|
||||
|
||||
In `ios/Podfile`, (for iOS):
|
||||
```
|
||||
platform :ios, '13.0'
|
||||
```
|
||||
|
||||
Then open XCode:
|
||||
```
|
||||
open macos/Runner.xcworkspace
|
||||
```
|
||||
|
||||
and change the minimum deployment target to 13.0:
|
||||
|
||||

|
||||
|
||||
</Accordion>
|
||||
@@ -1,23 +1,20 @@
|
||||
# ViewerWidget Documentation
|
||||
# Quick Start
|
||||
|
||||
`ViewerWidget` is a simplified wrapper around the Thermion 3D viewer that makes it easy to display 3D models in your Flutter application.
|
||||
If all you need is a quick and easy route to rendering a single 3D model in your Flutter application, start with `ViewerWidget`.
|
||||
|
||||
## Overview
|
||||
This is a simplified, Flutter-only wrapper around the underlying 3D rendering API with sane defaults for most people.
|
||||
|
||||
`ViewerWidget` handles the setup and configuration of a Thermion viewer, including:
|
||||
`ViewerWidget` handles all the setup and configuration of the underlying Thermion API, including:
|
||||
- Loading 3D models (glTF assets)
|
||||
- Configuring skyboxes and image-based lighting
|
||||
- Setting up camera positions and manipulators
|
||||
- Managing the rendering lifecycle
|
||||
|
||||
## Installation
|
||||
## Setup
|
||||
|
||||
First, make sure you have the Thermion Flutter plugin added to your dependencies:
|
||||
Follow the steps listed in [Getting Started](./getting_started) to configure your Flutter installation and project.
|
||||
|
||||
```yaml
|
||||
dependencies:
|
||||
thermion_flutter: ^latest_version
|
||||
```
|
||||
If you're running Windows, delete the `examples/flutter/quickstart/assets` symlink and copy the `assets` folder from `examples/assets` to `examples/flutter/quickstart/assets`.
|
||||
|
||||
## Basic Usage
|
||||
|
||||
|
||||
@@ -1,18 +1,25 @@
|
||||
## Showcase
|
||||
|
||||
## KTX Viewer
|
||||
|
||||
https://ktxviewer.com
|
||||
|
||||
A basic HTML + Dart site for viewing KTX textures in browser.
|
||||
|
||||
## DartPad Playground
|
||||
|
||||
A custom DartPad that lets you experiment with Thermion from your browser (currently, only Chrome is supported).
|
||||
|
||||
[](https://dartpad.thermion.dev)
|
||||
|
||||
(Outdated, needs to be upgraded to Thermion `0.3.0`);
|
||||
|
||||
## mixreel (Flutter/Web)
|
||||
|
||||
Create 3D worlds and translate to AI video.
|
||||
|
||||
[](https://mixreel.ai)
|
||||
|
||||
|
||||
## Nick Fisher
|
||||
|
||||
My personal website, where I create an interactive clone of myself with Avaturn & Cartesia (no Flutter, made with Thermion and the [Jaspr Dart UI framework](https://github.com/schultek/jaspr)).
|
||||
@@ -21,3 +28,4 @@ My personal website, where I create an interactive clone of myself with Avaturn
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,43 +1,14 @@
|
||||
## Quickstart (Flutter)
|
||||
## ThermionViewer (Flutter)
|
||||
|
||||
> You can find the entire project below in the [examples/flutter/quickstart](https://github.com/nmfisher/thermion/tree/master/examples/flutter/quickstart) folder of the repository.
|
||||
If you just want to display a 3D object in the viewport with some basic camera controls, use the [ViewerWidget described in the Quickstart section](./quickstart).
|
||||
|
||||
1. Switch to Flutter master channel, upgrade Flutter, create a new project, then add `thermion_flutter` as a dependency
|
||||
If you need want more fine-grained control
|
||||
|
||||
```bash
|
||||
$ flutter channel master
|
||||
$ flutter upgrade
|
||||
$ flutter config --enable-native-assets
|
||||
$ flutter create thermion_sample_project && cd thermion_sample_project
|
||||
$ flutter pub add thermion_flutter
|
||||
```
|
||||
> You can find the entire project below in the [examples/flutter/viewer](https://github.com/nmfisher/thermion/tree/master/examples/flutter/viewer) folder of the repository.
|
||||
|
||||
2. If running on iOS or MacOS, change the minimum deployment target to OSX 13
|
||||
|
||||
<Accordion title="Click to open iOS/MacOS instructions">
|
||||
|
||||
Make sure the `platform` entry refers to `13.0` in your Podfile.
|
||||
|
||||
In `macos/Podfile` (for macOS):
|
||||
```
|
||||
platform :osx, '13.0'
|
||||
```
|
||||
|
||||
In `ios/Podfile`, (for iOS):
|
||||
```
|
||||
platform :ios, '13.0'
|
||||
```
|
||||
|
||||
Then open XCode:
|
||||
```
|
||||
open macos/Runner.xcworkspace
|
||||
```
|
||||
|
||||
and change the minimum deployment target to 13.0:
|
||||
|
||||

|
||||
|
||||
</Accordion>
|
||||
|
||||
2. Add a folder containing your assets (glTF model + skybox ktx) to your `pubspec.yaml` asset list
|
||||
|
||||
@@ -53,11 +24,11 @@ flutter
|
||||
```dart
|
||||
|
||||
class _MyAppState extends State<MyApp> {
|
||||
late ThermionFlutterPlugin _thermionFlutterPlugin;
|
||||
late Future<ThermionViewer> _thermionViewer;
|
||||
void initState() {
|
||||
_thermionFlutterPlugin = ThermionFlutterPlugin();
|
||||
_thermionViewer = _thermionFlutterPlugin.createViewer();
|
||||
ThermionFlutterPlugin.createViewer().then((viewer) {
|
||||
_thermionViewer = viewer;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
35
docs/web.mdx
35
docs/web.mdx
@@ -1,26 +1,41 @@
|
||||
## Web
|
||||
|
||||
First, you must manually compile the wasm+javascript module. This requires:
|
||||
Web support is still experimental and currently requires you to manually compile Thermion to WASM first.
|
||||
|
||||
Requirements:
|
||||
|
||||
1) GNU Make
|
||||
2) CMake
|
||||
3) Emscripten
|
||||
|
||||
From the project root directory
|
||||
|
||||
```
|
||||
make wasm
|
||||
thermion % ls -l
|
||||
total 272
|
||||
drwxr-xr-x 4 nickfisher staff 128 Jul 3 14:06 assets
|
||||
-rw-r--r-- 1 nickfisher staff 84532 Jul 3 14:06 CHANGELOG.md
|
||||
-rw-r--r-- 1 nickfisher staff 2349 Jul 3 14:06 Dockerfile
|
||||
drwxr-xr-x 19 nickfisher staff 608 Jul 3 14:06 docs
|
||||
-rw-r--r-- 1 nickfisher staff 748 Jul 3 14:06 docs.json
|
||||
drwxr-xr-x 7 nickfisher staff 224 Jan 8 17:01 examples
|
||||
-rw-r--r-- 1 nickfisher staff 11341 Oct 23 2024 LICENSE
|
||||
-rw-r--r-- 1 nickfisher staff 2161 Jul 3 14:06 Makefile
|
||||
drwxr-xr-x@ 13 nickfisher staff 416 Jul 3 14:06 materials
|
||||
-rw-r--r--@ 1 nickfisher staff 517 Oct 23 2024 melos_thermion_workspace.iml
|
||||
-rw-r--r-- 1 nickfisher staff 77 Oct 23 2024 melos.yaml
|
||||
-rw-r--r--@ 1 nickfisher staff 9865 Jul 1 13:03 pubspec.lock
|
||||
-rw-r--r-- 1 nickfisher staff 97 Jun 12 11:38 pubspec.yaml
|
||||
-rw-r--r-- 1 nickfisher staff 3355 Jul 3 14:06 README.md
|
||||
drwxr-xr-x@ 22 nickfisher staff 704 Jul 3 14:06 thermion_dart
|
||||
drwxr-xr-x 7 nickfisher staff 224 Jul 3 14:06 thermion_flutter
|
||||
thermion % make wasm
|
||||
```
|
||||
|
||||
### Flutter
|
||||
|
||||
Thermion requires Android SDK version 22, so change your `app/android/build.gradle` to match this version or higher:
|
||||
Copy thermion_dart.js and thermion_dart.wasm to the `/web` folder for your target app.
|
||||
|
||||
```groovy
|
||||
defaultConfig {
|
||||
...
|
||||
minSdk = 22
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
flutter run -d chrome --web-header Cross-Origin-Embedder-Policy=require-corp --web-header Cross-Origin-Opener-Policy=same-origin
|
||||
|
||||
103
examples/flutter/camera_manipulation/lib/main.dart
Normal file
103
examples/flutter/camera_manipulation/lib/main.dart
Normal file
@@ -0,0 +1,103 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:thermion_flutter/thermion_flutter.dart';
|
||||
|
||||
void main() {
|
||||
runApp(const MyApp());
|
||||
Logger.root.onRecord.listen((record) {
|
||||
print(record);
|
||||
});
|
||||
}
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
const MyApp({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
title: 'Thermion Demo',
|
||||
theme: ThemeData(
|
||||
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
|
||||
useMaterial3: true,
|
||||
),
|
||||
home: const MyHomePage(title: 'Thermion Demo Home Page'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class MyHomePage extends StatefulWidget {
|
||||
const MyHomePage({super.key, required this.title});
|
||||
final String title;
|
||||
|
||||
@override
|
||||
State<MyHomePage> createState() => _MyHomePageState();
|
||||
}
|
||||
|
||||
class _MyHomePageState extends State<MyHomePage> {
|
||||
|
||||
late DelegateInputHandler _fixedOrbitInputHandler;
|
||||
late DelegateInputHandler _freeFlightInputHandler;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
_thermionViewer = await ThermionFlutterPlugin.createViewer();
|
||||
var assetData = await rootBundle.load("assets/cube.glb");
|
||||
var asset =
|
||||
await _thermionViewer!.loadGltfFromBuffer(assetData.buffer.asUint8List(assetData.offsetInBytes), keepData: true, loadResourcesAsync: true);
|
||||
await _thermionViewer!.loadSkybox("assets/default_env_skybox.ktx");
|
||||
await _thermionViewer!.loadIbl("assets/default_env_ibl.ktx");
|
||||
await _thermionViewer!.setPostProcessing(true);
|
||||
await _thermionViewer!.setRendering(true);
|
||||
|
||||
_fixedOrbitInputHandler =
|
||||
DelegateInputHandler.fixedOrbit(_thermionViewer!)
|
||||
..setActionForType(InputType.MMB_HOLD_AND_MOVE, InputAction.ROTATE)
|
||||
..setActionForType(InputType.SCALE1, InputAction.ROTATE)
|
||||
..setActionForType(InputType.SCALE2, InputAction.ZOOM)
|
||||
..setActionForType(InputType.SCROLLWHEEL, InputAction.ZOOM);
|
||||
|
||||
_freeFlightInputHandler =
|
||||
DelegateInputHandler.flight(_thermionViewer!)
|
||||
..setActionForType(InputType.MMB_HOLD_AND_MOVE, InputAction.ROTATE)
|
||||
..setActionForType(InputType.SCALE1, InputAction.ROTATE)
|
||||
..setActionForType(InputType.SCALE2, InputAction.ZOOM)
|
||||
..setActionForType(InputType.SCROLLWHEEL, InputAction.ZOOM);
|
||||
|
||||
setState(() {});
|
||||
});
|
||||
}
|
||||
|
||||
ThermionViewer? _thermionViewer;
|
||||
|
||||
bool isOrbit = true;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(children: [
|
||||
if (_thermionViewer != null) ...[
|
||||
Positioned.fill(
|
||||
child: ThermionListenerWidget(
|
||||
inputHandler: isOrbit
|
||||
? _fixedOrbitInputHandler : _freeFlightInputHandler,
|
||||
child:ThermionWidget(
|
||||
viewer: _thermionViewer!,
|
||||
))),
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
isOrbit = !isOrbit;
|
||||
setState(() {});
|
||||
},
|
||||
child: Text("Switch to ${isOrbit ? "Free Flight" : "Orbit"}"))
|
||||
],
|
||||
)
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -80,7 +80,7 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||
await _thermionViewer!.loadSkybox("assets/default_env_skybox.ktx");
|
||||
await _thermionViewer!.loadIbl("assets/default_env_ibl.ktx");
|
||||
|
||||
await _thermionViewer!.setBackgroundColor(0, 0, 1, 1);
|
||||
// await _thermionViewer!.setBackgroundColor(0, 0, 1, 1);
|
||||
|
||||
// The underlying Filament rendering engine exposes a number of
|
||||
// post-processing options (anti-aliasing, bloom, etc).
|
||||
@@ -93,13 +93,6 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||
// false is designed to allow you to pause rendering to conserve battery life
|
||||
await _thermionViewer!.setRendering(true);
|
||||
|
||||
// Timer.periodic(Duration(seconds: 1), (_) async {
|
||||
// final rnd = Random();
|
||||
|
||||
// await camera.setLensProjection();
|
||||
// await _thermionViewer!.setBackgroundColor(rnd.nextDouble(),rnd.nextDouble(), 0, 1.0);
|
||||
// });
|
||||
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
@@ -120,25 +113,16 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||
child: ElevatedButton(onPressed: _load, child: const Text("Load")));
|
||||
}
|
||||
|
||||
Widget _renderButton() {
|
||||
Widget _changeBgColor() {
|
||||
return Center(
|
||||
child: ElevatedButton(
|
||||
onPressed: () async {
|
||||
// final rnd = Random();
|
||||
// await FilamentApp.instance!.setClearColor(
|
||||
// rnd.nextDouble(), rnd.nextDouble(), rnd.nextDouble(), 1.0);
|
||||
// final camera = await _thermionViewer!.getActiveCamera();
|
||||
// await _thermionViewer!.setRendering(false);
|
||||
|
||||
// // await camera.setLensProjection();
|
||||
// await _thermionViewer!.removeSkybox();
|
||||
// // await _thermionViewer!.setBackgroundColor(rnd.nextDouble(), 1.0, 0, 1.0);
|
||||
// await _thermionViewer!.clearBackgroundImage(destroy: true);
|
||||
// // await _thermionViewer!.setBackgroundImage("/Users/nickfisher/Documents/thermion/thermion_dart/test/assets/cube_texture_512x512.png");
|
||||
|
||||
// await FilamentApp.instance!.render();
|
||||
final rnd = Random();
|
||||
await _thermionViewer!.removeSkybox();
|
||||
await _thermionViewer!.setBackgroundColor(
|
||||
rnd.nextDouble(), rnd.nextDouble(), rnd.nextDouble(), 1.0);
|
||||
},
|
||||
child: const Text("Render")));
|
||||
child: const Text("Change background color")));
|
||||
}
|
||||
|
||||
Widget _unloadButton() {
|
||||
@@ -153,9 +137,9 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||
body: Stack(children: [
|
||||
if (_thermionViewer != null)
|
||||
Positioned.fill(
|
||||
child: ThermionWidget(
|
||||
child: ThermionListenerWidget(inputHandler: DelegateInputHandler.fixedOrbit(_thermionViewer!), child:ThermionWidget(
|
||||
viewer: _thermionViewer!,
|
||||
)),
|
||||
))),
|
||||
Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: Padding(
|
||||
@@ -165,7 +149,7 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
if (_thermionViewer == null) _loadButton(),
|
||||
if (_thermionViewer != null) _renderButton(),
|
||||
if (_thermionViewer != null) _changeBgColor(),
|
||||
if (_thermionViewer != null) _unloadButton(),
|
||||
])))
|
||||
]));
|
||||
|
||||
@@ -558,7 +558,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.14;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
@@ -641,7 +641,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.14;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = macosx;
|
||||
@@ -691,7 +691,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.14;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
|
||||
@@ -108,10 +108,13 @@ fragment {
|
||||
1.0
|
||||
);
|
||||
|
||||
color.rgb = (axes.x < 1e-8) ? color.rgb : AXIS_COLOR_X;
|
||||
color.rgb = (axes.z < 1e-8) ? color.rgb : AXIS_COLOR_Z;
|
||||
|
||||
material.baseColor = color * gridAlpha;
|
||||
|
||||
if(axes.x > 1e-8) {
|
||||
material.baseColor = vec4(AXIS_COLOR_X, 1.0);
|
||||
} else if(axes.z > 1e-8) {
|
||||
material.baseColor = vec4(AXIS_COLOR_Z, 1.0);
|
||||
} else {
|
||||
material.baseColor = color * gridAlpha;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,8 @@
|
||||
name: thermion_workspace
|
||||
packages:
|
||||
- thermion_dart
|
||||
- thermion_flutter/**
|
||||
- thermion_flutter/thermion_flutter_platform_interface
|
||||
- thermion_flutter/thermion_flutter_method_channel
|
||||
- thermion_flutter/thermion_flutter_web
|
||||
- thermion_flutter/thermion_flutter
|
||||
|
||||
|
||||
@@ -1,3 +1,26 @@
|
||||
## 0.3.3
|
||||
|
||||
- Bump "thermion_dart" to `0.3.3`.
|
||||
|
||||
## 0.3.3-pre
|
||||
|
||||
- **FIX**: fix Windows build.dart.
|
||||
- **FIX**: add nan/negative checks inside setLensProjection.
|
||||
|
||||
## 0.3.2
|
||||
|
||||
- Bump "thermion_dart" to `0.3.2`.
|
||||
|
||||
## 0.3.1
|
||||
|
||||
- **REFACTOR**: remove covariant keyword from createInstance args.
|
||||
- **FIX**: add flush() to skybox/IBL destroy methods to ensure that textre upload callbacks are completed to avoid stalling.
|
||||
- **FIX**: duplicate setting for _grid.
|
||||
|
||||
## 0.3.0
|
||||
|
||||
- n
|
||||
|
||||
## 0.3.0
|
||||
|
||||
> Note: This release has breaking changes.
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:archive/archive.dart';
|
||||
import 'package:code_assets/code_assets.dart';
|
||||
import 'package:hooks/hooks.dart';
|
||||
import 'package:native_toolchain_c/native_toolchain_c.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
import 'package:native_toolchain_c/native_toolchain_c.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
void main(List<String> args) async {
|
||||
@@ -130,7 +131,7 @@ void main(List<String> args) async {
|
||||
|
||||
var frameworks = [];
|
||||
|
||||
if (platform != "windows") {
|
||||
if (targetOS != OS.windows) {
|
||||
flags.addAll(['-std=c++17']);
|
||||
} else {
|
||||
defines["WIN32"] = "1";
|
||||
@@ -193,7 +194,7 @@ void main(List<String> args) async {
|
||||
name: packageName,
|
||||
language: Language.cpp,
|
||||
assetName: 'thermion_dart.dart',
|
||||
sources: platform == "windows" ? [] : sources,
|
||||
sources: targetOS == OS.windows ? [] : sources,
|
||||
includes: platform == "windows"
|
||||
? []
|
||||
: ['native/include', 'native/include/filament'],
|
||||
@@ -219,12 +220,12 @@ void main(List<String> args) async {
|
||||
"/I${path.join(pkgRootFilePath, "native", "include", "windows", "vulkan")}",
|
||||
"@${srcs.uri.toFilePath(windows: true)}",
|
||||
// ...sources,
|
||||
'/link',
|
||||
"/LIBPATH:$libDir",
|
||||
'/DLL',
|
||||
// '/link',
|
||||
// "/LIBPATH:$libDir",
|
||||
// '/DLL',
|
||||
]
|
||||
],
|
||||
dartBuildFiles: ['hook/build.dart'],
|
||||
libraryDirectories: [libDir],
|
||||
);
|
||||
|
||||
await cbuilder.run(
|
||||
|
||||
@@ -221,8 +221,11 @@ extension DartBigIntExtension on int {
|
||||
}
|
||||
|
||||
extension Float32ListExtension on Float32List {
|
||||
|
||||
Uint8List asUint8List() {
|
||||
return this.buffer.asUint8List(this.offsetInBytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void resizeWebCanvas(int width, int height) {
|
||||
throw UnsupportedError("Not supported on non-web platforms");
|
||||
}
|
||||
|
||||
@@ -157,7 +157,6 @@ extension Uint8ListExtension on Uint8List {
|
||||
|
||||
extension Float32ListExtension on Float32List {
|
||||
Pointer<Float32> get address {
|
||||
|
||||
final ptr = getPointer<Float32>(this, this.toJS);
|
||||
final bar =
|
||||
Float32ArrayWrapper(NativeLibrary.instance.HEAPU8.buffer, ptr, length)
|
||||
@@ -167,7 +166,8 @@ extension Float32ListExtension on Float32List {
|
||||
}
|
||||
|
||||
Uint8List asUint8List() {
|
||||
var ptr = Pointer<Uint8>(_NativeLibrary.instance._emscripten_get_byte_offset(this.toJS));
|
||||
var ptr = Pointer<Uint8>(
|
||||
_NativeLibrary.instance._emscripten_get_byte_offset(this.toJS));
|
||||
return ptr.asTypedList(length * 4);
|
||||
}
|
||||
}
|
||||
@@ -468,3 +468,7 @@ void stackRestore(Pointer ptr) =>
|
||||
void getStackFree() {
|
||||
print(_NativeLibrary.instance._emscripten_stack_get_free());
|
||||
}
|
||||
|
||||
void resizeWebCanvas(int width, int height) {
|
||||
Thermion_resizeCanvas(width, height);
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ class FFIAsset extends ThermionAsset {
|
||||
///
|
||||
@override
|
||||
Future<FFIAsset> createInstance(
|
||||
{covariant List<MaterialInstance>? materialInstances = null}) async {
|
||||
{List<MaterialInstance>? materialInstances = null}) async {
|
||||
if(isInstance) {
|
||||
return instanceOwner!.createInstance(materialInstances: materialInstances);
|
||||
}
|
||||
|
||||
@@ -5,11 +5,10 @@ import '../../../utils/src/matrix.dart';
|
||||
|
||||
class FFICamera extends Camera<Pointer<TCamera>> {
|
||||
final Pointer<TCamera> camera;
|
||||
|
||||
|
||||
@override
|
||||
Pointer<TCamera> getNativeHandle() {
|
||||
return camera;
|
||||
|
||||
}
|
||||
|
||||
final FFIFilamentApp app;
|
||||
@@ -92,6 +91,16 @@ class FFICamera extends Camera<Pointer<TCamera>> {
|
||||
double far = kFar,
|
||||
double aspect = 1.0,
|
||||
double focalLength = kFocalLength}) async {
|
||||
if (near.isNaN ||
|
||||
far.isNaN ||
|
||||
aspect.isNaN ||
|
||||
focalLength.isNaN ||
|
||||
near.isNegative ||
|
||||
far.isNegative ||
|
||||
aspect.isNegative ||
|
||||
focalLength.isNegative) {
|
||||
throw FormatException();
|
||||
}
|
||||
Camera_setLensProjection(camera, near, far, aspect, focalLength);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,16 +12,39 @@ class GridOverlay extends FFIAsset {
|
||||
static Future<GridOverlay> create(
|
||||
FFIFilamentApp app, Pointer<TAnimationManager> animationManager) async {
|
||||
if (_overlay == null) {
|
||||
_gridMaterial ??= FFIMaterial(Material_createGridMaterial(app.engine), app);
|
||||
|
||||
_gridMaterial ??=
|
||||
FFIMaterial(Material_createGridMaterial(app.engine), app);
|
||||
|
||||
final asset = await withPointerCallback<TSceneAsset>((cb) =>
|
||||
SceneAsset_createGridRenderThread(
|
||||
app.engine, _gridMaterial!.getNativeHandle(), cb));
|
||||
|
||||
_overlay = GridOverlay(asset, app, animationManager);
|
||||
var materialInstance = await _overlay!.getMaterialInstanceAt();
|
||||
await materialInstance.setParameterFloat3("gridColor", 0.1, 0.1, 0.1);
|
||||
await materialInstance
|
||||
.setTransparencyMode(TransparencyMode.TWO_PASSES_TWO_SIDES);
|
||||
await materialInstance.setCullingMode(CullingMode.NONE);
|
||||
|
||||
await materialInstance.setParameterFloat3("gridColor", 0.3, 0.35, 0.3);
|
||||
|
||||
final ffiAsset =
|
||||
FFIAsset(asset, FilamentApp.instance as FFIFilamentApp, nullptr);
|
||||
await FilamentApp.instance!.setPriority(ffiAsset.entity, 0);
|
||||
for (final child in await ffiAsset.getChildEntities()) {
|
||||
await FilamentApp.instance!.setPriority(child, 7);
|
||||
}
|
||||
// await materialInstance.setParameterFloat("distance", 10.0);
|
||||
}
|
||||
return _overlay!;
|
||||
}
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
@override
|
||||
Future<FFIAsset> createInstance(
|
||||
{List<MaterialInstance>? materialInstances = null}) async {
|
||||
throw Exception(
|
||||
"Only a single instance of the grid overlay can be created");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ abstract class ThermionAsset {
|
||||
/// call [Scene.add].
|
||||
///
|
||||
Future<ThermionAsset> createInstance(
|
||||
{covariant List<MaterialInstance>? materialInstances = null});
|
||||
{List<MaterialInstance>? materialInstances = null});
|
||||
|
||||
///
|
||||
/// Returns the number of instances associated with this asset.
|
||||
|
||||
@@ -7,7 +7,6 @@ import 'package:thermion_dart/thermion_dart.dart';
|
||||
typedef PointerEventDetails = (Vector2 localPosition, Vector2 delta);
|
||||
|
||||
abstract class InputHandlerDelegate {
|
||||
|
||||
Future handle(List<InputEvent> events) async {
|
||||
// noop, override to implement
|
||||
}
|
||||
@@ -36,34 +35,48 @@ class DelegateInputHandler implements InputHandler {
|
||||
bool _ready = false;
|
||||
bool _processing = false;
|
||||
|
||||
DelegateInputHandler(
|
||||
{required this.viewer, required this.delegates, this.batch = true}) {
|
||||
DelegateInputHandler({
|
||||
required this.viewer,
|
||||
required this.delegates,
|
||||
this.batch = true,
|
||||
}) {
|
||||
FilamentApp.instance!.registerRequestFrameHook(process);
|
||||
viewer.initialized.then((_) {
|
||||
this._ready = true;
|
||||
});
|
||||
}
|
||||
|
||||
factory DelegateInputHandler.fixedOrbit(ThermionViewer viewer,
|
||||
{double minimumDistance = 0.1,
|
||||
Vector3? target,
|
||||
InputSensitivityOptions sensitivity = const InputSensitivityOptions(),
|
||||
ThermionEntity? entity}) {
|
||||
return DelegateInputHandler(viewer: viewer, delegates: [
|
||||
OrbitInputHandlerDelegate(viewer.view,
|
||||
factory DelegateInputHandler.fixedOrbit(
|
||||
ThermionViewer viewer, {
|
||||
double minimumDistance = 0.1,
|
||||
Vector3? target,
|
||||
InputSensitivityOptions sensitivity = const InputSensitivityOptions(),
|
||||
ThermionEntity? entity,
|
||||
}) {
|
||||
return DelegateInputHandler(
|
||||
viewer: viewer,
|
||||
delegates: [
|
||||
OrbitInputHandlerDelegate(
|
||||
viewer.view,
|
||||
sensitivity: sensitivity,
|
||||
minZoomDistance: minimumDistance,
|
||||
maxZoomDistance: 1000.0)
|
||||
]);
|
||||
maxZoomDistance: 1000.0,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
factory DelegateInputHandler.flight(ThermionViewer viewer,
|
||||
{bool freeLook = false,
|
||||
InputSensitivityOptions sensitivity = const InputSensitivityOptions(),
|
||||
ThermionEntity? entity}) =>
|
||||
DelegateInputHandler(viewer: viewer, delegates: [
|
||||
FreeFlightInputHandlerDelegateV2(viewer.view, sensitivity: sensitivity)
|
||||
]);
|
||||
factory DelegateInputHandler.flight(
|
||||
ThermionViewer viewer, {
|
||||
bool freeLook = false,
|
||||
InputSensitivityOptions sensitivity = const InputSensitivityOptions(),
|
||||
ThermionEntity? entity,
|
||||
}) => DelegateInputHandler(
|
||||
viewer: viewer,
|
||||
delegates: [
|
||||
FreeFlightInputHandlerDelegateV2(viewer.view, sensitivity: sensitivity),
|
||||
],
|
||||
);
|
||||
|
||||
Future<void> process() async {
|
||||
_processing = true;
|
||||
|
||||
@@ -1,449 +0,0 @@
|
||||
// ignore_for_file: camel_case_types, non_constant_identifier_names, unused_element, unused_field, return_of_invalid_type, void_checks, annotate_overrides, no_leading_underscores_for_local_identifiers, library_private_types_in_public_apia
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
//
|
||||
// Generated by `package:ffigen`.
|
||||
// ignore_for_file: type=lint
|
||||
import 'dart:ffi' as ffi;
|
||||
import 'package:objective_c/objective_c.dart' as objc;
|
||||
|
||||
@ffi.Native<
|
||||
ffi.Pointer<objc.ObjCObject> Function(
|
||||
ffi.Pointer<objc.ObjCObject>, ffi.Pointer<ffi.Void>)>()
|
||||
external ffi.Pointer<objc.ObjCObject>
|
||||
_ThermionTextureSwift_protocolTrampoline_1mbt9g9(
|
||||
ffi.Pointer<objc.ObjCObject> target,
|
||||
ffi.Pointer<ffi.Void> arg0,
|
||||
);
|
||||
|
||||
late final _class_ThermionTextureSwift =
|
||||
objc.getClass("swift_module.ThermionTextureSwift");
|
||||
late final _sel_isKindOfClass_ = objc.registerName("isKindOfClass:");
|
||||
final _objc_msgSend_19nvye5 = objc.msgSendPointer
|
||||
.cast<
|
||||
ffi.NativeFunction<
|
||||
ffi.Bool Function(
|
||||
ffi.Pointer<objc.ObjCObject>,
|
||||
ffi.Pointer<objc.ObjCSelector>,
|
||||
ffi.Pointer<objc.ObjCObject>)>>()
|
||||
.asFunction<
|
||||
bool Function(ffi.Pointer<objc.ObjCObject>,
|
||||
ffi.Pointer<objc.ObjCSelector>, ffi.Pointer<objc.ObjCObject>)>();
|
||||
late final _sel_cvMetalTextureCache = objc.registerName("cvMetalTextureCache");
|
||||
final _objc_msgSend_13yqbb6 = objc.msgSendPointer
|
||||
.cast<
|
||||
ffi.NativeFunction<
|
||||
ffi.Int Function(ffi.Pointer<objc.ObjCObject>,
|
||||
ffi.Pointer<objc.ObjCSelector>)>>()
|
||||
.asFunction<
|
||||
int Function(
|
||||
ffi.Pointer<objc.ObjCObject>, ffi.Pointer<objc.ObjCSelector>)>();
|
||||
late final _sel_setCvMetalTextureCache_ =
|
||||
objc.registerName("setCvMetalTextureCache:");
|
||||
final _objc_msgSend_9o8504 = objc.msgSendPointer
|
||||
.cast<
|
||||
ffi.NativeFunction<
|
||||
ffi.Void Function(ffi.Pointer<objc.ObjCObject>,
|
||||
ffi.Pointer<objc.ObjCSelector>, ffi.Int)>>()
|
||||
.asFunction<
|
||||
void Function(ffi.Pointer<objc.ObjCObject>,
|
||||
ffi.Pointer<objc.ObjCSelector>, int)>();
|
||||
|
||||
/// WARNING: MTLDevice is a stub. To generate bindings for this class, include
|
||||
/// MTLDevice in your config's objc-protocols list.
|
||||
///
|
||||
/// MTLDevice
|
||||
interface class MTLDevice extends objc.ObjCProtocolBase {
|
||||
MTLDevice._(ffi.Pointer<objc.ObjCObject> pointer,
|
||||
{bool retain = false, bool release = false})
|
||||
: super(pointer, retain: retain, release: release);
|
||||
|
||||
/// Constructs a [MTLDevice] that points to the same underlying object as [other].
|
||||
MTLDevice.castFrom(objc.ObjCObjectBase other)
|
||||
: this._(other.ref.pointer, retain: true, release: true);
|
||||
|
||||
/// Constructs a [MTLDevice] that wraps the given raw object pointer.
|
||||
MTLDevice.castFromPointer(ffi.Pointer<objc.ObjCObject> other,
|
||||
{bool retain = false, bool release = false})
|
||||
: this._(other, retain: retain, release: release);
|
||||
}
|
||||
|
||||
late final _sel_metalDevice = objc.registerName("metalDevice");
|
||||
final _objc_msgSend_151sglz = objc.msgSendPointer
|
||||
.cast<
|
||||
ffi.NativeFunction<
|
||||
ffi.Pointer<objc.ObjCObject> Function(ffi.Pointer<objc.ObjCObject>,
|
||||
ffi.Pointer<objc.ObjCSelector>)>>()
|
||||
.asFunction<
|
||||
ffi.Pointer<objc.ObjCObject> Function(
|
||||
ffi.Pointer<objc.ObjCObject>, ffi.Pointer<objc.ObjCSelector>)>();
|
||||
late final _sel_setMetalDevice_ = objc.registerName("setMetalDevice:");
|
||||
final _objc_msgSend_xtuoz7 = objc.msgSendPointer
|
||||
.cast<
|
||||
ffi.NativeFunction<
|
||||
ffi.Void Function(
|
||||
ffi.Pointer<objc.ObjCObject>,
|
||||
ffi.Pointer<objc.ObjCSelector>,
|
||||
ffi.Pointer<objc.ObjCObject>)>>()
|
||||
.asFunction<
|
||||
void Function(ffi.Pointer<objc.ObjCObject>,
|
||||
ffi.Pointer<objc.ObjCSelector>, ffi.Pointer<objc.ObjCObject>)>();
|
||||
late final _sel_cvMetalTexture = objc.registerName("cvMetalTexture");
|
||||
late final _sel_setCvMetalTexture_ = objc.registerName("setCvMetalTexture:");
|
||||
|
||||
/// WARNING: MTLTexture is a stub. To generate bindings for this class, include
|
||||
/// MTLTexture in your config's objc-protocols list.
|
||||
///
|
||||
/// MTLTexture
|
||||
interface class MTLTexture extends objc.ObjCProtocolBase {
|
||||
MTLTexture._(ffi.Pointer<objc.ObjCObject> pointer,
|
||||
{bool retain = false, bool release = false})
|
||||
: super(pointer, retain: retain, release: release);
|
||||
|
||||
/// Constructs a [MTLTexture] that points to the same underlying object as [other].
|
||||
MTLTexture.castFrom(objc.ObjCObjectBase other)
|
||||
: this._(other.ref.pointer, retain: true, release: true);
|
||||
|
||||
/// Constructs a [MTLTexture] that wraps the given raw object pointer.
|
||||
MTLTexture.castFromPointer(ffi.Pointer<objc.ObjCObject> other,
|
||||
{bool retain = false, bool release = false})
|
||||
: this._(other, retain: retain, release: release);
|
||||
}
|
||||
|
||||
late final _sel_metalTexture = objc.registerName("metalTexture");
|
||||
late final _sel_setMetalTexture_ = objc.registerName("setMetalTexture:");
|
||||
late final _sel_metalTextureAddress = objc.registerName("metalTextureAddress");
|
||||
final _objc_msgSend_1hz7y9r = objc.msgSendPointer
|
||||
.cast<
|
||||
ffi.NativeFunction<
|
||||
ffi.Long Function(ffi.Pointer<objc.ObjCObject>,
|
||||
ffi.Pointer<objc.ObjCSelector>)>>()
|
||||
.asFunction<
|
||||
int Function(
|
||||
ffi.Pointer<objc.ObjCObject>, ffi.Pointer<objc.ObjCSelector>)>();
|
||||
late final _sel_setMetalTextureAddress_ =
|
||||
objc.registerName("setMetalTextureAddress:");
|
||||
final _objc_msgSend_4sp4xj = objc.msgSendPointer
|
||||
.cast<
|
||||
ffi.NativeFunction<
|
||||
ffi.Void Function(ffi.Pointer<objc.ObjCObject>,
|
||||
ffi.Pointer<objc.ObjCSelector>, ffi.Long)>>()
|
||||
.asFunction<
|
||||
void Function(ffi.Pointer<objc.ObjCObject>,
|
||||
ffi.Pointer<objc.ObjCSelector>, int)>();
|
||||
typedef instancetype = ffi.Pointer<objc.ObjCObject>;
|
||||
typedef Dartinstancetype = objc.ObjCObjectBase;
|
||||
late final _sel_init = objc.registerName("init");
|
||||
late final _sel_initWithWidth_height_isDepth_isStencil_ =
|
||||
objc.registerName("initWithWidth:height:isDepth:isStencil:");
|
||||
final _objc_msgSend_1v8gk45 = objc.msgSendPointer
|
||||
.cast<
|
||||
ffi.NativeFunction<
|
||||
ffi.Pointer<objc.ObjCObject> Function(
|
||||
ffi.Pointer<objc.ObjCObject>,
|
||||
ffi.Pointer<objc.ObjCSelector>,
|
||||
ffi.Int64,
|
||||
ffi.Int64,
|
||||
ffi.Bool,
|
||||
ffi.Bool)>>()
|
||||
.asFunction<
|
||||
ffi.Pointer<objc.ObjCObject> Function(ffi.Pointer<objc.ObjCObject>,
|
||||
ffi.Pointer<objc.ObjCSelector>, int, int, bool, bool)>();
|
||||
late final _sel_destroyTexture = objc.registerName("destroyTexture");
|
||||
final _objc_msgSend_1pl9qdv = objc.msgSendPointer
|
||||
.cast<
|
||||
ffi.NativeFunction<
|
||||
ffi.Void Function(ffi.Pointer<objc.ObjCObject>,
|
||||
ffi.Pointer<objc.ObjCSelector>)>>()
|
||||
.asFunction<
|
||||
void Function(
|
||||
ffi.Pointer<objc.ObjCObject>, ffi.Pointer<objc.ObjCSelector>)>();
|
||||
late final _sel_fillWithPNGImageWithImageURL_ =
|
||||
objc.registerName("fillWithPNGImageWithImageURL:");
|
||||
late final _sel_fillColor = objc.registerName("fillColor");
|
||||
late final _sel_getTextureBytes = objc.registerName("getTextureBytes");
|
||||
late final _sel_new = objc.registerName("new");
|
||||
late final _sel_allocWithZone_ = objc.registerName("allocWithZone:");
|
||||
final _objc_msgSend_1cwp428 = objc.msgSendPointer
|
||||
.cast<
|
||||
ffi.NativeFunction<
|
||||
ffi.Pointer<objc.ObjCObject> Function(ffi.Pointer<objc.ObjCObject>,
|
||||
ffi.Pointer<objc.ObjCSelector>, ffi.Pointer<objc.NSZone>)>>()
|
||||
.asFunction<
|
||||
ffi.Pointer<objc.ObjCObject> Function(ffi.Pointer<objc.ObjCObject>,
|
||||
ffi.Pointer<objc.ObjCSelector>, ffi.Pointer<objc.NSZone>)>();
|
||||
late final _sel_alloc = objc.registerName("alloc");
|
||||
late final _sel_self = objc.registerName("self");
|
||||
ffi.Pointer<objc.ObjCObject> _ObjCBlock_objcObjCObject_ffiVoid_fnPtrTrampoline(
|
||||
ffi.Pointer<objc.ObjCBlockImpl> block, ffi.Pointer<ffi.Void> arg0) =>
|
||||
block.ref.target
|
||||
.cast<
|
||||
ffi.NativeFunction<
|
||||
ffi.Pointer<objc.ObjCObject> Function(
|
||||
ffi.Pointer<ffi.Void> arg0)>>()
|
||||
.asFunction<
|
||||
ffi.Pointer<objc.ObjCObject> Function(
|
||||
ffi.Pointer<ffi.Void>)>()(arg0);
|
||||
ffi.Pointer<ffi.Void> _ObjCBlock_objcObjCObject_ffiVoid_fnPtrCallable =
|
||||
ffi.Pointer.fromFunction<
|
||||
ffi.Pointer<objc.ObjCObject> Function(
|
||||
ffi.Pointer<objc.ObjCBlockImpl>, ffi.Pointer<ffi.Void>)>(
|
||||
_ObjCBlock_objcObjCObject_ffiVoid_fnPtrTrampoline)
|
||||
.cast();
|
||||
ffi.Pointer<objc.ObjCObject>
|
||||
_ObjCBlock_objcObjCObject_ffiVoid_closureTrampoline(
|
||||
ffi.Pointer<objc.ObjCBlockImpl> block,
|
||||
ffi.Pointer<ffi.Void> arg0) =>
|
||||
(objc.getBlockClosure(block) as ffi.Pointer<objc.ObjCObject> Function(
|
||||
ffi.Pointer<ffi.Void>))(arg0);
|
||||
ffi.Pointer<ffi.Void> _ObjCBlock_objcObjCObject_ffiVoid_closureCallable =
|
||||
ffi.Pointer.fromFunction<
|
||||
ffi.Pointer<objc.ObjCObject> Function(
|
||||
ffi.Pointer<objc.ObjCBlockImpl>, ffi.Pointer<ffi.Void>)>(
|
||||
_ObjCBlock_objcObjCObject_ffiVoid_closureTrampoline)
|
||||
.cast();
|
||||
|
||||
/// Construction methods for `objc.ObjCBlock<ffi.Pointer<objc.ObjCObject> Function(ffi.Pointer<ffi.Void>)>`.
|
||||
abstract final class ObjCBlock_objcObjCObject_ffiVoid {
|
||||
/// Returns a block that wraps the given raw block pointer.
|
||||
static objc
|
||||
.ObjCBlock<ffi.Pointer<objc.ObjCObject> Function(ffi.Pointer<ffi.Void>)>
|
||||
castFromPointer(ffi.Pointer<objc.ObjCBlockImpl> pointer,
|
||||
{bool retain = false, bool release = false}) =>
|
||||
objc.ObjCBlock<
|
||||
ffi.Pointer<objc.ObjCObject> Function(ffi.Pointer<ffi.Void>)>(
|
||||
pointer,
|
||||
retain: retain,
|
||||
release: release);
|
||||
|
||||
/// Creates a block from a C function pointer.
|
||||
///
|
||||
/// This block must be invoked by native code running on the same thread as
|
||||
/// the isolate that registered it. Invoking the block on the wrong thread
|
||||
/// will result in a crash.
|
||||
static objc.ObjCBlock<ffi.Pointer<objc.ObjCObject> Function(ffi.Pointer<ffi.Void>)>
|
||||
fromFunctionPointer(
|
||||
ffi.Pointer<
|
||||
ffi.NativeFunction<
|
||||
ffi.Pointer<objc.ObjCObject> Function(
|
||||
ffi.Pointer<ffi.Void> arg0)>>
|
||||
ptr) =>
|
||||
objc.ObjCBlock<ffi.Pointer<objc.ObjCObject> Function(ffi.Pointer<ffi.Void>)>(
|
||||
objc.newPointerBlock(_ObjCBlock_objcObjCObject_ffiVoid_fnPtrCallable, ptr.cast()),
|
||||
retain: false,
|
||||
release: true);
|
||||
|
||||
/// Creates a block from a Dart function.
|
||||
///
|
||||
/// This block must be invoked by native code running on the same thread as
|
||||
/// the isolate that registered it. Invoking the block on the wrong thread
|
||||
/// will result in a crash.
|
||||
///
|
||||
/// If `keepIsolateAlive` is true, this block will keep this isolate alive
|
||||
/// until it is garbage collected by both Dart and ObjC.
|
||||
static objc
|
||||
.ObjCBlock<ffi.Pointer<objc.ObjCObject> Function(ffi.Pointer<ffi.Void>)>
|
||||
fromFunction(objc.ObjCObjectBase Function(ffi.Pointer<ffi.Void>) fn,
|
||||
{bool keepIsolateAlive = true}) =>
|
||||
objc.ObjCBlock<
|
||||
ffi.Pointer<objc.ObjCObject> Function(ffi.Pointer<ffi.Void>)>(
|
||||
objc.newClosureBlock(
|
||||
_ObjCBlock_objcObjCObject_ffiVoid_closureCallable,
|
||||
(ffi.Pointer<ffi.Void> arg0) =>
|
||||
fn(arg0).ref.retainAndAutorelease(),
|
||||
keepIsolateAlive),
|
||||
retain: false,
|
||||
release: true);
|
||||
}
|
||||
|
||||
/// Call operator for `objc.ObjCBlock<ffi.Pointer<objc.ObjCObject> Function(ffi.Pointer<ffi.Void>)>`.
|
||||
extension ObjCBlock_objcObjCObject_ffiVoid_CallExtension on objc
|
||||
.ObjCBlock<ffi.Pointer<objc.ObjCObject> Function(ffi.Pointer<ffi.Void>)> {
|
||||
objc.ObjCObjectBase call(ffi.Pointer<ffi.Void> arg0) => objc.ObjCObjectBase(
|
||||
ref.pointer.ref.invoke
|
||||
.cast<
|
||||
ffi.NativeFunction<
|
||||
ffi.Pointer<objc.ObjCObject> Function(
|
||||
ffi.Pointer<objc.ObjCBlockImpl> block,
|
||||
ffi.Pointer<ffi.Void> arg0)>>()
|
||||
.asFunction<
|
||||
ffi.Pointer<objc.ObjCObject> Function(
|
||||
ffi.Pointer<objc.ObjCBlockImpl>,
|
||||
ffi.Pointer<ffi.Void>)>()(ref.pointer, arg0),
|
||||
retain: true,
|
||||
release: true);
|
||||
}
|
||||
|
||||
late final _sel_retain = objc.registerName("retain");
|
||||
late final _sel_autorelease = objc.registerName("autorelease");
|
||||
|
||||
/// ThermionTextureSwift
|
||||
class ThermionTextureSwift extends objc.NSObject {
|
||||
ThermionTextureSwift._(ffi.Pointer<objc.ObjCObject> pointer,
|
||||
{bool retain = false, bool release = false})
|
||||
: super.castFromPointer(pointer, retain: retain, release: release);
|
||||
|
||||
/// Constructs a [ThermionTextureSwift] that points to the same underlying object as [other].
|
||||
ThermionTextureSwift.castFrom(objc.ObjCObjectBase other)
|
||||
: this._(other.ref.pointer, retain: true, release: true);
|
||||
|
||||
/// Constructs a [ThermionTextureSwift] that wraps the given raw object pointer.
|
||||
ThermionTextureSwift.castFromPointer(ffi.Pointer<objc.ObjCObject> other,
|
||||
{bool retain = false, bool release = false})
|
||||
: this._(other, retain: retain, release: release);
|
||||
|
||||
/// Returns whether [obj] is an instance of [ThermionTextureSwift].
|
||||
static bool isInstance(objc.ObjCObjectBase obj) {
|
||||
return _objc_msgSend_19nvye5(
|
||||
obj.ref.pointer, _sel_isKindOfClass_, _class_ThermionTextureSwift);
|
||||
}
|
||||
|
||||
/// cvMetalTextureCache
|
||||
int get cvMetalTextureCache {
|
||||
return _objc_msgSend_13yqbb6(this.ref.pointer, _sel_cvMetalTextureCache);
|
||||
}
|
||||
|
||||
/// setCvMetalTextureCache:
|
||||
set cvMetalTextureCache(int value) {
|
||||
_objc_msgSend_9o8504(this.ref.pointer, _sel_setCvMetalTextureCache_, value);
|
||||
}
|
||||
|
||||
/// metalDevice
|
||||
MTLDevice? get metalDevice {
|
||||
final _ret = _objc_msgSend_151sglz(this.ref.pointer, _sel_metalDevice);
|
||||
return _ret.address == 0
|
||||
? null
|
||||
: MTLDevice.castFromPointer(_ret, retain: true, release: true);
|
||||
}
|
||||
|
||||
/// setMetalDevice:
|
||||
set metalDevice(MTLDevice? value) {
|
||||
_objc_msgSend_xtuoz7(this.ref.pointer, _sel_setMetalDevice_,
|
||||
value?.ref.pointer ?? ffi.nullptr);
|
||||
}
|
||||
|
||||
/// cvMetalTexture
|
||||
int get cvMetalTexture {
|
||||
return _objc_msgSend_13yqbb6(this.ref.pointer, _sel_cvMetalTexture);
|
||||
}
|
||||
|
||||
/// setCvMetalTexture:
|
||||
set cvMetalTexture(int value) {
|
||||
_objc_msgSend_9o8504(this.ref.pointer, _sel_setCvMetalTexture_, value);
|
||||
}
|
||||
|
||||
/// metalTexture
|
||||
MTLTexture? get metalTexture {
|
||||
final _ret = _objc_msgSend_151sglz(this.ref.pointer, _sel_metalTexture);
|
||||
return _ret.address == 0
|
||||
? null
|
||||
: MTLTexture.castFromPointer(_ret, retain: true, release: true);
|
||||
}
|
||||
|
||||
/// setMetalTexture:
|
||||
set metalTexture(MTLTexture? value) {
|
||||
_objc_msgSend_xtuoz7(this.ref.pointer, _sel_setMetalTexture_,
|
||||
value?.ref.pointer ?? ffi.nullptr);
|
||||
}
|
||||
|
||||
/// metalTextureAddress
|
||||
int get metalTextureAddress {
|
||||
return _objc_msgSend_1hz7y9r(this.ref.pointer, _sel_metalTextureAddress);
|
||||
}
|
||||
|
||||
/// setMetalTextureAddress:
|
||||
set metalTextureAddress(int value) {
|
||||
_objc_msgSend_4sp4xj(this.ref.pointer, _sel_setMetalTextureAddress_, value);
|
||||
}
|
||||
|
||||
/// init
|
||||
ThermionTextureSwift init() {
|
||||
final _ret =
|
||||
_objc_msgSend_151sglz(this.ref.retainAndReturnPointer(), _sel_init);
|
||||
return ThermionTextureSwift.castFromPointer(_ret,
|
||||
retain: false, release: true);
|
||||
}
|
||||
|
||||
/// initWithWidth:height:isDepth:isStencil:
|
||||
ThermionTextureSwift initWithWidth_height_isDepth_isStencil_(
|
||||
int width, int height, bool isDepth, bool isStencil) {
|
||||
final _ret = _objc_msgSend_1v8gk45(
|
||||
this.ref.retainAndReturnPointer(),
|
||||
_sel_initWithWidth_height_isDepth_isStencil_,
|
||||
width,
|
||||
height,
|
||||
isDepth,
|
||||
isStencil);
|
||||
return ThermionTextureSwift.castFromPointer(_ret,
|
||||
retain: false, release: true);
|
||||
}
|
||||
|
||||
/// destroyTexture
|
||||
void destroyTexture() {
|
||||
_objc_msgSend_1pl9qdv(this.ref.pointer, _sel_destroyTexture);
|
||||
}
|
||||
|
||||
/// fillWithPNGImageWithImageURL:
|
||||
bool fillWithPNGImageWithImageURL_(objc.NSURL imageURL) {
|
||||
return _objc_msgSend_19nvye5(this.ref.pointer,
|
||||
_sel_fillWithPNGImageWithImageURL_, imageURL.ref.pointer);
|
||||
}
|
||||
|
||||
/// fillColor
|
||||
void fillColor() {
|
||||
_objc_msgSend_1pl9qdv(this.ref.pointer, _sel_fillColor);
|
||||
}
|
||||
|
||||
/// getTextureBytes
|
||||
objc.NSData? getTextureBytes() {
|
||||
final _ret = _objc_msgSend_151sglz(this.ref.pointer, _sel_getTextureBytes);
|
||||
return _ret.address == 0
|
||||
? null
|
||||
: objc.NSData.castFromPointer(_ret, retain: true, release: true);
|
||||
}
|
||||
|
||||
/// new
|
||||
static ThermionTextureSwift new$() {
|
||||
final _ret = _objc_msgSend_151sglz(_class_ThermionTextureSwift, _sel_new);
|
||||
return ThermionTextureSwift.castFromPointer(_ret,
|
||||
retain: false, release: true);
|
||||
}
|
||||
|
||||
/// allocWithZone:
|
||||
static ThermionTextureSwift allocWithZone_(ffi.Pointer<objc.NSZone> zone) {
|
||||
final _ret = _objc_msgSend_1cwp428(
|
||||
_class_ThermionTextureSwift, _sel_allocWithZone_, zone);
|
||||
return ThermionTextureSwift.castFromPointer(_ret,
|
||||
retain: false, release: true);
|
||||
}
|
||||
|
||||
/// alloc
|
||||
static ThermionTextureSwift alloc() {
|
||||
final _ret = _objc_msgSend_151sglz(_class_ThermionTextureSwift, _sel_alloc);
|
||||
return ThermionTextureSwift.castFromPointer(_ret,
|
||||
retain: false, release: true);
|
||||
}
|
||||
|
||||
/// self
|
||||
ThermionTextureSwift self$1() {
|
||||
final _ret = _objc_msgSend_151sglz(this.ref.pointer, _sel_self);
|
||||
return ThermionTextureSwift.castFromPointer(_ret,
|
||||
retain: true, release: true);
|
||||
}
|
||||
|
||||
/// retain
|
||||
ThermionTextureSwift retain() {
|
||||
final _ret = _objc_msgSend_151sglz(this.ref.pointer, _sel_retain);
|
||||
return ThermionTextureSwift.castFromPointer(_ret,
|
||||
retain: true, release: true);
|
||||
}
|
||||
|
||||
/// autorelease
|
||||
ThermionTextureSwift autorelease() {
|
||||
final _ret = _objc_msgSend_151sglz(this.ref.pointer, _sel_autorelease);
|
||||
return ThermionTextureSwift.castFromPointer(_ret,
|
||||
retain: true, release: true);
|
||||
}
|
||||
|
||||
/// Returns a new instance of ThermionTextureSwift constructed with the default `new` method.
|
||||
factory ThermionTextureSwift() => new$();
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
#include <stdint.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <objc/message.h>
|
||||
#import "../../../native/include/generated/ThermionTextureSwiftObjCAPI.h"
|
||||
|
||||
#if !__has_feature(objc_arc)
|
||||
#error "This file must be compiled with ARC enabled"
|
||||
#endif
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wundeclared-selector"
|
||||
|
||||
typedef struct {
|
||||
int64_t version;
|
||||
void* (*newWaiter)(void);
|
||||
void (*awaitWaiter)(void*);
|
||||
void* (*currentIsolate)(void);
|
||||
void (*enterIsolate)(void*);
|
||||
void (*exitIsolate)(void);
|
||||
int64_t (*getMainPortId)(void);
|
||||
bool (*getCurrentThreadOwnsIsolate)(int64_t);
|
||||
} DOBJC_Context;
|
||||
|
||||
id objc_retainBlock(id);
|
||||
|
||||
#define BLOCKING_BLOCK_IMPL(ctx, BLOCK_SIG, INVOKE_DIRECT, INVOKE_LISTENER) \
|
||||
assert(ctx->version >= 1); \
|
||||
void* targetIsolate = ctx->currentIsolate(); \
|
||||
int64_t targetPort = ctx->getMainPortId == NULL ? 0 : ctx->getMainPortId(); \
|
||||
return BLOCK_SIG { \
|
||||
void* currentIsolate = ctx->currentIsolate(); \
|
||||
bool mayEnterIsolate = \
|
||||
currentIsolate == NULL && \
|
||||
ctx->getCurrentThreadOwnsIsolate != NULL && \
|
||||
ctx->getCurrentThreadOwnsIsolate(targetPort); \
|
||||
if (currentIsolate == targetIsolate || mayEnterIsolate) { \
|
||||
if (mayEnterIsolate) { \
|
||||
ctx->enterIsolate(targetIsolate); \
|
||||
} \
|
||||
INVOKE_DIRECT; \
|
||||
if (mayEnterIsolate) { \
|
||||
ctx->exitIsolate(); \
|
||||
} \
|
||||
} else { \
|
||||
void* waiter = ctx->newWaiter(); \
|
||||
INVOKE_LISTENER; \
|
||||
ctx->awaitWaiter(waiter); \
|
||||
} \
|
||||
};
|
||||
|
||||
|
||||
Protocol* _ThermionTextureSwift_MTLDevice(void) { return @protocol(MTLDevice); }
|
||||
|
||||
Protocol* _ThermionTextureSwift_MTLTexture(void) { return @protocol(MTLTexture); }
|
||||
|
||||
typedef id (^ProtocolTrampoline)(void * sel);
|
||||
__attribute__((visibility("default"))) __attribute__((used))
|
||||
id _ThermionTextureSwift_protocolTrampoline_1mbt9g9(id target, void * sel) {
|
||||
return ((ProtocolTrampoline)((id (*)(id, SEL, SEL))objc_msgSend)(target, @selector(getDOBJCDartProtocolMethodForSelector:), sel))(sel);
|
||||
}
|
||||
#undef BLOCKING_BLOCK_IMPL
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
@@ -502,8 +502,171 @@ class GeometryHelper {
|
||||
|
||||
return Geometry(vertices, indices, normals: _normals, uvs: _uvs);
|
||||
}
|
||||
static Geometry camera({
|
||||
double bodyWidth = 0.6, // X-axis (medium width)
|
||||
double bodyHeight = 0.7, // Y-axis (medium height)
|
||||
double bodyDepth = 1.4, // Z-axis (LONG dimension - camera body extends back)
|
||||
double lensRadius = 0.3,
|
||||
double lensLength = 0.4,
|
||||
bool normals = true,
|
||||
bool uvs = true,
|
||||
}) {
|
||||
List<double> verticesList = [];
|
||||
List<double> normalsList = [];
|
||||
List<double> uvsList = [];
|
||||
List<int> indices = [];
|
||||
|
||||
static Geometry wireframeCamera({
|
||||
// Helper function to add a vertex with normal and UV
|
||||
void addVertex(double x, double y, double z, double nx, double ny, double nz, double u, double v) {
|
||||
verticesList.addAll([x, y, z]);
|
||||
if (normals) normalsList.addAll([nx, ny, nz]);
|
||||
if (uvs) uvsList.addAll([u, v]);
|
||||
}
|
||||
|
||||
int currentIndex = 0;
|
||||
|
||||
// === CAMERA BODY (Rectangular box) ===
|
||||
// Now: width=1.0, height=0.6, depth=1.4 (long)
|
||||
// The front face (Z=+halfDepth) is the short face where lens attaches
|
||||
double halfWidth = bodyWidth / 2; // 0.5 (medium)
|
||||
double halfHeight = bodyHeight / 2; // 0.3 (short)
|
||||
double halfDepth = bodyDepth / 2; // 0.7 (long - extends backward)
|
||||
|
||||
// Front face (SHORT face - where lens attaches) - Z = +halfDepth
|
||||
addVertex(-halfWidth, -halfHeight, halfDepth, 0, 0, 1, 0, 0); // 0
|
||||
addVertex(halfWidth, -halfHeight, halfDepth, 0, 0, 1, 1, 0); // 1
|
||||
addVertex(halfWidth, halfHeight, halfDepth, 0, 0, 1, 1, 1); // 2
|
||||
addVertex(-halfWidth, halfHeight, halfDepth, 0, 0, 1, 0, 1); // 3
|
||||
|
||||
// Back face (SHORT face) - Z = -halfDepth
|
||||
addVertex(halfWidth, -halfHeight, -halfDepth, 0, 0, -1, 0, 0); // 4
|
||||
addVertex(-halfWidth, -halfHeight, -halfDepth, 0, 0, -1, 1, 0); // 5
|
||||
addVertex(-halfWidth, halfHeight, -halfDepth, 0, 0, -1, 1, 1); // 6
|
||||
addVertex(halfWidth, halfHeight, -halfDepth, 0, 0, -1, 0, 1); // 7
|
||||
|
||||
// Top face (LONG face) - Y = +halfHeight
|
||||
addVertex(-halfWidth, halfHeight, halfDepth, 0, 1, 0, 0, 0); // 8
|
||||
addVertex(halfWidth, halfHeight, halfDepth, 0, 1, 0, 1, 0); // 9
|
||||
addVertex(halfWidth, halfHeight, -halfDepth, 0, 1, 0, 1, 1); // 10
|
||||
addVertex(-halfWidth, halfHeight, -halfDepth, 0, 1, 0, 0, 1); // 11
|
||||
|
||||
// Bottom face (LONG face) - Y = -halfHeight
|
||||
addVertex(-halfWidth, -halfHeight, -halfDepth, 0, -1, 0, 0, 0); // 12
|
||||
addVertex(halfWidth, -halfHeight, -halfDepth, 0, -1, 0, 1, 0); // 13
|
||||
addVertex(halfWidth, -halfHeight, halfDepth, 0, -1, 0, 1, 1); // 14
|
||||
addVertex(-halfWidth, -halfHeight, halfDepth, 0, -1, 0, 0, 1); // 15
|
||||
|
||||
// Right face (LONG face) - X = +halfWidth
|
||||
addVertex(halfWidth, -halfHeight, halfDepth, 1, 0, 0, 0, 0); // 16
|
||||
addVertex(halfWidth, -halfHeight, -halfDepth, 1, 0, 0, 1, 0); // 17
|
||||
addVertex(halfWidth, halfHeight, -halfDepth, 1, 0, 0, 1, 1); // 18
|
||||
addVertex(halfWidth, halfHeight, halfDepth, 1, 0, 0, 0, 1); // 19
|
||||
|
||||
// Left face (LONG face) - X = -halfWidth
|
||||
addVertex(-halfWidth, -halfHeight, -halfDepth, -1, 0, 0, 0, 0); // 20
|
||||
addVertex(-halfWidth, -halfHeight, halfDepth, -1, 0, 0, 1, 0); // 21
|
||||
addVertex(-halfWidth, halfHeight, halfDepth, -1, 0, 0, 1, 1); // 22
|
||||
addVertex(-halfWidth, halfHeight, -halfDepth, -1, 0, 0, 0, 1); // 23
|
||||
|
||||
// Body indices
|
||||
List<int> bodyIndices = [
|
||||
// Front face
|
||||
0, 1, 2, 0, 2, 3,
|
||||
// Back face
|
||||
4, 5, 6, 4, 6, 7,
|
||||
// Top face
|
||||
8, 9, 10, 8, 10, 11,
|
||||
// Bottom face
|
||||
12, 13, 14, 12, 14, 15,
|
||||
// Right face
|
||||
16, 17, 18, 16, 18, 19,
|
||||
// Left face
|
||||
20, 21, 22, 20, 22, 23
|
||||
];
|
||||
|
||||
indices.addAll(bodyIndices);
|
||||
currentIndex = 24;
|
||||
|
||||
// === CONICAL LENS ===
|
||||
int segments = 16;
|
||||
double lensApexZ = -halfDepth; // Apex touches the front face (short face)
|
||||
double lensBaseZ = -halfDepth - lensLength; // Base extends outward along Z-axis
|
||||
|
||||
// Lens apex (tip of the cone - touching the camera body at center of front face)
|
||||
addVertex(0, 0, lensApexZ, 0, 0, -1, 0.5, 0);
|
||||
int apexIndex = currentIndex;
|
||||
currentIndex++;
|
||||
|
||||
// Lens base circle (the wide part extending outward)
|
||||
List<int> baseIndices = [];
|
||||
for (int i = 0; i < segments; i++) {
|
||||
double theta = i * 2 * pi / segments;
|
||||
double x = lensRadius * cos(theta);
|
||||
double y = lensRadius * sin(theta);
|
||||
|
||||
// Calculate normal for cone side (pointing outward from cone surface)
|
||||
double normalX = x / lensRadius; // Normalized radial component
|
||||
double normalY = y / lensRadius;
|
||||
double normalZ = lensRadius / lensLength; // Axial component based on cone slope
|
||||
|
||||
// Normalize the normal vector
|
||||
double normalLength = sqrt(normalX * normalX + normalY * normalY + normalZ * normalZ);
|
||||
normalX /= normalLength;
|
||||
normalY /= normalLength;
|
||||
normalZ /= normalLength;
|
||||
|
||||
addVertex(x, y, lensBaseZ, normalX, normalY, normalZ, i / segments, 1);
|
||||
baseIndices.add(currentIndex);
|
||||
currentIndex++;
|
||||
}
|
||||
|
||||
// Create cone side triangles
|
||||
for (int i = 0; i < segments; i++) {
|
||||
int current = baseIndices[i];
|
||||
int next = baseIndices[(i + 1) % segments];
|
||||
|
||||
// Triangle from apex to base edge (counter-clockwise when viewed from outside)
|
||||
indices.addAll([apexIndex, next, current]);
|
||||
}
|
||||
|
||||
// === LENS BASE (flat circular face at the wide end) ===
|
||||
// Center of lens base
|
||||
addVertex(0, 0, lensBaseZ, 0, 0, 1, 0.5, 0.5);
|
||||
int baseCenterIndex = currentIndex;
|
||||
currentIndex++;
|
||||
|
||||
// Base circle vertices (separate from cone vertices for proper normals)
|
||||
List<int> baseFaceIndices = [];
|
||||
for (int i = 0; i < segments; i++) {
|
||||
double theta = i * 2 * pi / segments;
|
||||
double x = lensRadius * cos(theta);
|
||||
double y = lensRadius * sin(theta);
|
||||
|
||||
double u = 0.5 + 0.5 * cos(theta);
|
||||
double v = 0.5 + 0.5 * sin(theta);
|
||||
|
||||
addVertex(x, y, lensBaseZ, 0, 0, 1, u, v);
|
||||
baseFaceIndices.add(currentIndex);
|
||||
currentIndex++;
|
||||
}
|
||||
|
||||
// Create base face triangles (facing outward from camera)
|
||||
for (int i = 0; i < segments; i++) {
|
||||
int current = baseFaceIndices[i];
|
||||
int next = baseFaceIndices[(i + 1) % segments];
|
||||
|
||||
// Triangle from center to edge (counter-clockwise when viewed from outside)
|
||||
indices.addAll([baseCenterIndex, current, next]);
|
||||
}
|
||||
|
||||
Float32List vertices = Float32List.fromList(verticesList);
|
||||
Float32List? _normals = normals ? Float32List.fromList(normalsList) : null;
|
||||
Float32List? _uvs = uvs ? Float32List.fromList(uvsList) : null;
|
||||
|
||||
return Geometry(vertices, Uint16List.fromList(indices), normals: _normals, uvs: _uvs);
|
||||
}
|
||||
|
||||
static Geometry wireframeCamera({
|
||||
double sphereRadius = 0.2,
|
||||
double frustumDistance = 1.0,
|
||||
double frustumNear = 0.5,
|
||||
|
||||
@@ -394,6 +394,7 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
}
|
||||
|
||||
if (_skyboxTextureUploadComplete != null) {
|
||||
await FilamentApp.instance!.flush();
|
||||
await _skyboxTextureUploadComplete;
|
||||
_skyboxTextureUploadComplete = null;
|
||||
}
|
||||
@@ -414,6 +415,7 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
await ibl.destroy();
|
||||
}
|
||||
if (_iblTextureUploadComplete != null) {
|
||||
await FilamentApp.instance!.flush();
|
||||
await _iblTextureUploadComplete!;
|
||||
_iblTextureUploadComplete = null;
|
||||
}
|
||||
@@ -691,7 +693,7 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
///
|
||||
///
|
||||
Future setGridOverlayVisibility(bool visible) async {
|
||||
_grid ??= _grid = await GridOverlay.create(app, animationManager);
|
||||
_grid ??= await GridOverlay.create(app, animationManager);
|
||||
|
||||
if (visible) {
|
||||
await scene.add(_grid!);
|
||||
|
||||
@@ -83,7 +83,8 @@ abstract class ThermionViewer {
|
||||
Future clearBackgroundImage({bool destroy = false});
|
||||
|
||||
///
|
||||
/// Sets the color for the background plane (positioned at the maximum depth, i.e. behind all other objects including the skybox).
|
||||
/// Sets the color for the background plane (positioned at the maximum depth,
|
||||
/// i.e. behind all other objects including the skybox).
|
||||
///
|
||||
Future setBackgroundColor(double r, double g, double b, double alpha);
|
||||
|
||||
@@ -343,13 +344,14 @@ abstract class ThermionViewer {
|
||||
int getCameraCount();
|
||||
|
||||
///
|
||||
/// Adds the asset to the scene, meaning the asset will be rendered/visible.
|
||||
/// Adds the asset to the scene. All renderable entities attached to
|
||||
/// the asset will be visible.
|
||||
///
|
||||
Future addToScene(covariant ThermionAsset asset);
|
||||
|
||||
///
|
||||
/// Removes the asset from the scene, meaning the asset will not be rendered/visible.
|
||||
/// The asset itself will remain valid.
|
||||
/// Removes the asset from the scene. None of the renderable entities
|
||||
/// attached to the asset will be visible, but the asset itself remains valid.
|
||||
///
|
||||
Future removeFromScene(covariant ThermionAsset asset);
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#pragma comment(lib, "dracodec.lib")
|
||||
#pragma comment(lib, "ibl.lib")
|
||||
#pragma comment(lib, "ktxreader.lib")
|
||||
#pragma comment(lib, "png.lib")
|
||||
#pragma comment(lib, "z.lib")
|
||||
#pragma comment(lib, "stb.lib")
|
||||
#pragma comment(lib, "uberzlib.lib")
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "ThermionWin32.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace thermion {
|
||||
extern "C"
|
||||
@@ -16,35 +20,35 @@ enum TProjection {
|
||||
typedef enum TProjection TProjection;
|
||||
|
||||
// Camera methods
|
||||
void Camera_setExposure(TCamera *camera, float aperture, float shutterSpeed, float sensitivity);
|
||||
double4x4 Camera_getModelMatrix(TCamera *const camera);
|
||||
double4x4 Camera_getViewMatrix(TCamera *const camera);
|
||||
double4x4 Camera_getProjectionMatrix(TCamera *const camera);
|
||||
double4x4 Camera_getCullingProjectionMatrix(TCamera *const camera);
|
||||
void Camera_getFrustum(TCamera *camera, double* out);
|
||||
void Camera_setProjectionMatrix(TCamera *camera, double *matrix, double near, double far);
|
||||
void Camera_setProjectionFromFov(TCamera *camera, double fovInDegrees, double aspect, double near, double far, bool horizontal);
|
||||
double Camera_getFocalLength(TCamera *const camera);
|
||||
double4x4 Camera_getViewMatrix(TCamera *const camera);
|
||||
double4x4 Camera_getModelMatrix(TCamera* camera);
|
||||
void Camera_lookAt(TCamera* camera, double3 eye, double3 focus, double3 up);
|
||||
EMSCRIPTEN_KEEPALIVE void Camera_setExposure(TCamera *camera, float aperture, float shutterSpeed, float sensitivity);
|
||||
EMSCRIPTEN_KEEPALIVE double4x4 Camera_getModelMatrix(TCamera *const camera);
|
||||
EMSCRIPTEN_KEEPALIVE double4x4 Camera_getViewMatrix(TCamera *const camera);
|
||||
EMSCRIPTEN_KEEPALIVE double4x4 Camera_getProjectionMatrix(TCamera *const camera);
|
||||
EMSCRIPTEN_KEEPALIVE double4x4 Camera_getCullingProjectionMatrix(TCamera *const camera);
|
||||
EMSCRIPTEN_KEEPALIVE void Camera_getFrustum(TCamera *camera, double* out);
|
||||
EMSCRIPTEN_KEEPALIVE void Camera_setProjectionMatrix(TCamera *camera, double *matrix, double near, double far);
|
||||
EMSCRIPTEN_KEEPALIVE void Camera_setProjectionFromFov(TCamera *camera, double fovInDegrees, double aspect, double near, double far, bool horizontal);
|
||||
EMSCRIPTEN_KEEPALIVE double Camera_getFocalLength(TCamera *const camera);
|
||||
EMSCRIPTEN_KEEPALIVE double4x4 Camera_getViewMatrix(TCamera *const camera);
|
||||
EMSCRIPTEN_KEEPALIVE double4x4 Camera_getModelMatrix(TCamera* camera);
|
||||
EMSCRIPTEN_KEEPALIVE void Camera_lookAt(TCamera* camera, double3 eye, double3 focus, double3 up);
|
||||
|
||||
double Camera_getNear(TCamera *camera);
|
||||
double Camera_getCullingFar(TCamera *camera);
|
||||
float Camera_getFov(TCamera *camera, bool horizontal);
|
||||
double Camera_getFocusDistance(TCamera *camera);
|
||||
void Camera_setFocusDistance(TCamera *camera, float focusDistance);
|
||||
EMSCRIPTEN_KEEPALIVE double Camera_getNear(TCamera *camera);
|
||||
EMSCRIPTEN_KEEPALIVE double Camera_getCullingFar(TCamera *camera);
|
||||
EMSCRIPTEN_KEEPALIVE float Camera_getFov(TCamera *camera, bool horizontal);
|
||||
EMSCRIPTEN_KEEPALIVE double Camera_getFocusDistance(TCamera *camera);
|
||||
EMSCRIPTEN_KEEPALIVE void Camera_setFocusDistance(TCamera *camera, float focusDistance);
|
||||
|
||||
void Camera_setCustomProjectionWithCulling(
|
||||
EMSCRIPTEN_KEEPALIVE void Camera_setCustomProjectionWithCulling(
|
||||
TCamera* camera,
|
||||
double4x4 projectionMatrix,
|
||||
double near,
|
||||
double far
|
||||
);
|
||||
void Camera_setModelMatrix(TCamera* camera, double *tModelMatrix);
|
||||
void Camera_setLensProjection(TCamera *camera, double near, double far, double aspect, double focalLength);
|
||||
EntityId Camera_getEntity(TCamera* camera);
|
||||
void Camera_setProjection(TCamera *const tCamera, TProjection projection, double left, double right,
|
||||
EMSCRIPTEN_KEEPALIVE void Camera_setModelMatrix(TCamera* camera, double *tModelMatrix);
|
||||
EMSCRIPTEN_KEEPALIVE void Camera_setLensProjection(TCamera *camera, double near, double far, double aspect, double focalLength);
|
||||
EMSCRIPTEN_KEEPALIVE EntityId Camera_getEntity(TCamera* camera);
|
||||
EMSCRIPTEN_KEEPALIVE void Camera_setProjection(TCamera *const tCamera, TProjection projection, double left, double right,
|
||||
double bottom, double top,
|
||||
double near, double far);
|
||||
|
||||
|
||||
@@ -16,16 +16,16 @@ namespace thermion
|
||||
typedef int32_t EntityId;
|
||||
typedef void (*FilamentRenderCallback)(void *const owner);
|
||||
|
||||
void RenderThread_create();
|
||||
void RenderThread_destroy();
|
||||
void RenderThread_requestFrameAsync();
|
||||
void RenderThread_setRenderTicker(TRenderTicker *tRenderTicker);
|
||||
void RenderThread_addTask(void (*task)());
|
||||
EMSCRIPTEN_KEEPALIVE void RenderThread_create();
|
||||
EMSCRIPTEN_KEEPALIVE void RenderThread_destroy();
|
||||
EMSCRIPTEN_KEEPALIVE void RenderThread_requestFrameAsync();
|
||||
EMSCRIPTEN_KEEPALIVE void RenderThread_setRenderTicker(TRenderTicker *tRenderTicker);
|
||||
EMSCRIPTEN_KEEPALIVE void RenderThread_addTask(void (*task)());
|
||||
|
||||
void RenderTicker_renderRenderThread(TRenderTicker *tRenderTicker, uint64_t frameTimeInNanos, uint32_t requestId, VoidCallback onComplete);
|
||||
void AnimationManager_createRenderThread(TEngine *tEngine, TScene *tScene, void (*onComplete)(TAnimationManager *));
|
||||
EMSCRIPTEN_KEEPALIVE void RenderTicker_renderRenderThread(TRenderTicker *tRenderTicker, uint64_t frameTimeInNanos, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_createRenderThread(TEngine *tEngine, TScene *tScene, void (*onComplete)(TAnimationManager *));
|
||||
|
||||
void Engine_createRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_createRenderThread(
|
||||
TBackend backend,
|
||||
void* platform,
|
||||
void* sharedContext,
|
||||
@@ -33,22 +33,22 @@ namespace thermion
|
||||
bool disableHandleUseAfterFreeCheck,
|
||||
void (*onComplete)(TEngine *)
|
||||
);
|
||||
void Engine_createRendererRenderThread(TEngine *tEngine, void (*onComplete)(TRenderer *));
|
||||
void Engine_createSwapChainRenderThread(TEngine *tEngine, void *window, uint64_t flags, void (*onComplete)(TSwapChain *));
|
||||
void Engine_createHeadlessSwapChainRenderThread(TEngine *tEngine, uint32_t width, uint32_t height, uint64_t flags, void (*onComplete)(TSwapChain *));
|
||||
void Engine_createCameraRenderThread(TEngine* tEngine, void (*onComplete)(TCamera *));
|
||||
void Engine_createViewRenderThread(TEngine *tEngine, void (*onComplete)(TView *));
|
||||
void Engine_buildMaterialRenderThread(TEngine *tEngine, const uint8_t *materialData, size_t length, void (*onComplete)(TMaterial *));
|
||||
void Engine_destroyRenderThread(TEngine *tEngine, uint32_t requestId, VoidCallback onComplete);
|
||||
void Engine_destroySwapChainRenderThread(TEngine *tEngine, TSwapChain *tSwapChain, uint32_t requestId, VoidCallback onComplete);
|
||||
void Engine_destroyViewRenderThread(TEngine *tEngine, TView *tView, uint32_t requestId, VoidCallback onComplete);
|
||||
void Engine_destroySceneRenderThread(TEngine *tEngine, TScene *tScene, uint32_t requestId, VoidCallback onComplete);
|
||||
void Engine_destroyColorGradingRenderThread(TEngine *tEngine, TColorGrading *tColorGrading, uint32_t requestId, VoidCallback onComplete);
|
||||
void Engine_destroyMaterialRenderThread(TEngine *tEngine, TMaterial *tMaterial, uint32_t requestId, VoidCallback onComplete);
|
||||
void Engine_destroyMaterialInstanceRenderThread(TEngine *tEngine, TMaterialInstance *tMaterialInstance, uint32_t requestId, VoidCallback onComplete);
|
||||
void Engine_destroySkyboxRenderThread(TEngine *tEngine, TSkybox *tSkybox, uint32_t requestId, VoidCallback onComplete);
|
||||
void Engine_destroyIndirectLightRenderThread(TEngine *tEngine, TIndirectLight *tIndirectLight, uint32_t requestId, VoidCallback onComplete);
|
||||
void Texture_buildRenderThread(TEngine *engine,
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_createRendererRenderThread(TEngine *tEngine, void (*onComplete)(TRenderer *));
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_createSwapChainRenderThread(TEngine *tEngine, void *window, uint64_t flags, void (*onComplete)(TSwapChain *));
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_createHeadlessSwapChainRenderThread(TEngine *tEngine, uint32_t width, uint32_t height, uint64_t flags, void (*onComplete)(TSwapChain *));
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_createCameraRenderThread(TEngine* tEngine, void (*onComplete)(TCamera *));
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_createViewRenderThread(TEngine *tEngine, void (*onComplete)(TView *));
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_buildMaterialRenderThread(TEngine *tEngine, const uint8_t *materialData, size_t length, void (*onComplete)(TMaterial *));
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_destroyRenderThread(TEngine *tEngine, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_destroySwapChainRenderThread(TEngine *tEngine, TSwapChain *tSwapChain, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_destroyViewRenderThread(TEngine *tEngine, TView *tView, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_destroySceneRenderThread(TEngine *tEngine, TScene *tScene, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_destroyColorGradingRenderThread(TEngine *tEngine, TColorGrading *tColorGrading, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_destroyMaterialRenderThread(TEngine *tEngine, TMaterial *tMaterial, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_destroyMaterialInstanceRenderThread(TEngine *tEngine, TMaterialInstance *tMaterialInstance, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_destroySkyboxRenderThread(TEngine *tEngine, TSkybox *tSkybox, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_destroyIndirectLightRenderThread(TEngine *tEngine, TIndirectLight *tIndirectLight, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Texture_buildRenderThread(TEngine *engine,
|
||||
uint32_t width,
|
||||
uint32_t height,
|
||||
uint32_t depth,
|
||||
@@ -59,25 +59,25 @@ namespace thermion
|
||||
TTextureFormat format,
|
||||
void (*onComplete)(TTexture*)
|
||||
);
|
||||
void Texture_generateMipMapsRenderThread(TTexture *tTexture, TEngine *tEngine, uint32_t requestId, VoidCallback onComplete);
|
||||
void Ktx1Reader_createTextureRenderThread(TEngine *tEngine, TKtx1Bundle *tBundle, uint32_t requestId, VoidCallback onTextureUploadComplete, void (*onComplete)(TTexture *));
|
||||
EMSCRIPTEN_KEEPALIVE void Texture_generateMipMapsRenderThread(TTexture *tTexture, TEngine *tEngine, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Ktx1Reader_createTextureRenderThread(TEngine *tEngine, TKtx1Bundle *tBundle, uint32_t requestId, VoidCallback onTextureUploadComplete, void (*onComplete)(TTexture *));
|
||||
|
||||
void Engine_destroyTextureRenderThread(TEngine *engine, TTexture* tTexture, uint32_t requestId, VoidCallback onComplete);
|
||||
void Engine_createFenceRenderThread(TEngine *tEngine, void (*onComplete)(TFence*));
|
||||
void Fence_waitAndDestroyRenderThread(TFence *tFence, uint32_t requestId, VoidCallback onComplete);
|
||||
void Engine_destroyFenceRenderThread(TEngine *tEngine, TFence *tFence, uint32_t requestId, VoidCallback onComplete);
|
||||
void Engine_flushAndWaitRenderThread(TEngine *tEngine, uint32_t requestId, VoidCallback onComplete);
|
||||
void Engine_executeRenderThread(TEngine *tEngine, uint32_t requestId, VoidCallback onComplete);
|
||||
void Engine_buildSkyboxRenderThread(TEngine *tEngine, TTexture *tTexture, void (*onComplete)(TSkybox *));
|
||||
void Engine_buildIndirectLightFromIrradianceTextureRenderThread(TEngine *tEngine, TTexture *tReflectionsTexture, TTexture* tIrradianceTexture, float intensity, void (*onComplete)(TIndirectLight *));
|
||||
void Engine_buildIndirectLightFromIrradianceHarmonicsRenderThread(TEngine *tEngine, TTexture *tReflectionsTexture, float *harmonics, float intensity, void (*onComplete)(TIndirectLight *));
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_destroyTextureRenderThread(TEngine *engine, TTexture* tTexture, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_createFenceRenderThread(TEngine *tEngine, void (*onComplete)(TFence*));
|
||||
EMSCRIPTEN_KEEPALIVE void Fence_waitAndDestroyRenderThread(TFence *tFence, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_destroyFenceRenderThread(TEngine *tEngine, TFence *tFence, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_flushAndWaitRenderThread(TEngine *tEngine, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_executeRenderThread(TEngine *tEngine, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_buildSkyboxRenderThread(TEngine *tEngine, TTexture *tTexture, void (*onComplete)(TSkybox *));
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_buildIndirectLightFromIrradianceTextureRenderThread(TEngine *tEngine, TTexture *tReflectionsTexture, TTexture* tIrradianceTexture, float intensity, void (*onComplete)(TIndirectLight *));
|
||||
EMSCRIPTEN_KEEPALIVE void Engine_buildIndirectLightFromIrradianceHarmonicsRenderThread(TEngine *tEngine, TTexture *tReflectionsTexture, float *harmonics, float intensity, void (*onComplete)(TIndirectLight *));
|
||||
|
||||
void Renderer_setClearOptionsRenderThread(TRenderer *tRenderer, double clearR, double clearG, double clearB, double clearA, uint8_t clearStencil, bool clear, bool discard, uint32_t requestId, VoidCallback onComplete);
|
||||
void Renderer_beginFrameRenderThread(TRenderer *tRenderer, TSwapChain *tSwapChain, uint64_t frameTimeInNanos, void (*onComplete)(bool));
|
||||
void Renderer_endFrameRenderThread(TRenderer *tRenderer, uint32_t requestId, VoidCallback onComplete);
|
||||
void Renderer_renderRenderThread(TRenderer *tRenderer, TView *tView, uint32_t requestId, VoidCallback onComplete);
|
||||
void Renderer_renderStandaloneViewRenderThread(TRenderer *tRenderer, TView *tView, uint32_t requestId, VoidCallback onComplete);
|
||||
void Renderer_readPixelsRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void Renderer_setClearOptionsRenderThread(TRenderer *tRenderer, double clearR, double clearG, double clearB, double clearA, uint8_t clearStencil, bool clear, bool discard, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Renderer_beginFrameRenderThread(TRenderer *tRenderer, TSwapChain *tSwapChain, uint64_t frameTimeInNanos, void (*onComplete)(bool));
|
||||
EMSCRIPTEN_KEEPALIVE void Renderer_endFrameRenderThread(TRenderer *tRenderer, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Renderer_renderRenderThread(TRenderer *tRenderer, TView *tView, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Renderer_renderStandaloneViewRenderThread(TRenderer *tRenderer, TView *tView, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Renderer_readPixelsRenderThread(
|
||||
TRenderer *tRenderer,
|
||||
uint32_t width, uint32_t height, uint32_t xOffset, uint32_t yOffset,
|
||||
TRenderTarget *tRenderTarget,
|
||||
@@ -87,29 +87,29 @@ namespace thermion
|
||||
size_t outLength,
|
||||
uint32_t requestId, VoidCallback onComplete);
|
||||
|
||||
void Material_createInstanceRenderThread(TMaterial *tMaterial, void (*onComplete)(TMaterialInstance *));
|
||||
void Material_createImageMaterialRenderThread(TEngine *tEngine, void (*onComplete)(TMaterial *));
|
||||
void Material_createGizmoMaterialRenderThread(TEngine *tEngine, void (*onComplete)(TMaterial *));
|
||||
void Material_createOutlineMaterialRenderThread(TEngine *tEngine, void (*onComplete)(TMaterial *));
|
||||
EMSCRIPTEN_KEEPALIVE void Material_createInstanceRenderThread(TMaterial *tMaterial, void (*onComplete)(TMaterialInstance *));
|
||||
EMSCRIPTEN_KEEPALIVE void Material_createImageMaterialRenderThread(TEngine *tEngine, void (*onComplete)(TMaterial *));
|
||||
EMSCRIPTEN_KEEPALIVE void Material_createGizmoMaterialRenderThread(TEngine *tEngine, void (*onComplete)(TMaterial *));
|
||||
EMSCRIPTEN_KEEPALIVE void Material_createOutlineMaterialRenderThread(TEngine *tEngine, void (*onComplete)(TMaterial *));
|
||||
|
||||
void ColorGrading_createRenderThread(TEngine *tEngine, TToneMapping toneMapping, void (*callback)(TColorGrading *));
|
||||
void View_pickRenderThread(TView *tView, uint32_t requestId, uint32_t x, uint32_t y, PickCallback callback);
|
||||
void View_setColorGradingRenderThread(TView *tView, TColorGrading *tColorGrading, uint32_t requestId, VoidCallback onComplete);
|
||||
void View_setBloomRenderThread(TView *tView, bool enabled, double strength, uint32_t requestId, VoidCallback onComplete);
|
||||
void View_setCameraRenderThread(TView *tView, TCamera *tCamera, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void ColorGrading_createRenderThread(TEngine *tEngine, TToneMapping toneMapping, void (*callback)(TColorGrading *));
|
||||
EMSCRIPTEN_KEEPALIVE void View_pickRenderThread(TView *tView, uint32_t requestId, uint32_t x, uint32_t y, PickCallback callback);
|
||||
EMSCRIPTEN_KEEPALIVE void View_setColorGradingRenderThread(TView *tView, TColorGrading *tColorGrading, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void View_setBloomRenderThread(TView *tView, bool enabled, double strength, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void View_setCameraRenderThread(TView *tView, TCamera *tCamera, uint32_t requestId, VoidCallback onComplete);
|
||||
|
||||
void SceneAsset_createGridRenderThread(TEngine *tEngine, TMaterial * tMaterial, void (*callback)(TSceneAsset *));
|
||||
EMSCRIPTEN_KEEPALIVE void SceneAsset_createGridRenderThread(TEngine *tEngine, TMaterial * tMaterial, void (*callback)(TSceneAsset *));
|
||||
|
||||
void SceneAsset_destroyRenderThread(TSceneAsset *tSceneAsset, uint32_t requestId, VoidCallback onComplete);
|
||||
void SceneAsset_createFromFilamentAssetRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void SceneAsset_destroyRenderThread(TSceneAsset *tSceneAsset, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void SceneAsset_createFromFilamentAssetRenderThread(
|
||||
TEngine *tEngine,
|
||||
TGltfAssetLoader *tAssetLoader,
|
||||
TNameComponentManager *tNameComponentManager,
|
||||
TFilamentAsset *tFilamentAsset,
|
||||
void (*onComplete)(TSceneAsset *)
|
||||
);
|
||||
void SceneAsset_createInstanceRenderThread(TSceneAsset *asset, TMaterialInstance **tMaterialInstances, int materialInstanceCount, void (*callback)(TSceneAsset *));
|
||||
void SceneAsset_createGeometryRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void SceneAsset_createInstanceRenderThread(TSceneAsset *asset, TMaterialInstance **tMaterialInstances, int materialInstanceCount, void (*callback)(TSceneAsset *));
|
||||
EMSCRIPTEN_KEEPALIVE void SceneAsset_createGeometryRenderThread(
|
||||
TEngine *tEngine,
|
||||
float *vertices,
|
||||
uint32_t numVertices,
|
||||
@@ -124,7 +124,7 @@ namespace thermion
|
||||
int materialInstanceCount,
|
||||
void (*callback)(TSceneAsset *)
|
||||
);
|
||||
void MaterialProvider_createMaterialInstanceRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void MaterialProvider_createMaterialInstanceRenderThread(
|
||||
TMaterialProvider *tMaterialProvider,
|
||||
bool doubleSided,
|
||||
bool unlit,
|
||||
@@ -166,12 +166,12 @@ namespace thermion
|
||||
bool hasVolume,
|
||||
void (*callback)(TMaterialInstance *));
|
||||
|
||||
void AnimationManager_updateBoneMatricesRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_updateBoneMatricesRenderThread(
|
||||
TAnimationManager *tAnimationManager,
|
||||
TSceneAsset *sceneAsset,
|
||||
void (*callback)(bool));
|
||||
|
||||
void AnimationManager_setMorphTargetWeightsRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_setMorphTargetWeightsRenderThread(
|
||||
TAnimationManager *tAnimationManager,
|
||||
EntityId entityId,
|
||||
const float *const morphData,
|
||||
@@ -179,16 +179,16 @@ namespace thermion
|
||||
void (*callback)(bool));
|
||||
|
||||
// Image methods
|
||||
void Image_createEmptyRenderThread(uint32_t width, uint32_t height, uint32_t channel, void (*onComplete)(TLinearImage *));
|
||||
void Image_decodeRenderThread(uint8_t* data, size_t length, const char* name, bool alpha, void (*onComplete)(TLinearImage *));
|
||||
void Image_getBytesRenderThread(TLinearImage *tLinearImage, void (*onComplete)(float *));
|
||||
void Image_destroyRenderThread(TLinearImage *tLinearImage, uint32_t requestId, VoidCallback onComplete);
|
||||
void Image_getWidthRenderThread(TLinearImage *tLinearImage, void (*onComplete)(uint32_t));
|
||||
void Image_getHeightRenderThread(TLinearImage *tLinearImage, void (*onComplete)(uint32_t));
|
||||
void Image_getChannelsRenderThread(TLinearImage *tLinearImage, void (*onComplete)(uint32_t));
|
||||
EMSCRIPTEN_KEEPALIVE void Image_createEmptyRenderThread(uint32_t width, uint32_t height, uint32_t channel, void (*onComplete)(TLinearImage *));
|
||||
EMSCRIPTEN_KEEPALIVE void Image_decodeRenderThread(uint8_t* data, size_t length, const char* name, bool alpha, void (*onComplete)(TLinearImage *));
|
||||
EMSCRIPTEN_KEEPALIVE void Image_getBytesRenderThread(TLinearImage *tLinearImage, void (*onComplete)(float *));
|
||||
EMSCRIPTEN_KEEPALIVE void Image_destroyRenderThread(TLinearImage *tLinearImage, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Image_getWidthRenderThread(TLinearImage *tLinearImage, void (*onComplete)(uint32_t));
|
||||
EMSCRIPTEN_KEEPALIVE void Image_getHeightRenderThread(TLinearImage *tLinearImage, void (*onComplete)(uint32_t));
|
||||
EMSCRIPTEN_KEEPALIVE void Image_getChannelsRenderThread(TLinearImage *tLinearImage, void (*onComplete)(uint32_t));
|
||||
|
||||
|
||||
void Texture_loadImageRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void Texture_loadImageRenderThread(
|
||||
TEngine *tEngine,
|
||||
TTexture *tTexture,
|
||||
TLinearImage *tImage,
|
||||
@@ -197,7 +197,7 @@ namespace thermion
|
||||
int level,
|
||||
void (*onComplete)(bool)
|
||||
);
|
||||
void Texture_setImageRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void Texture_setImageRenderThread(
|
||||
TEngine *tEngine,
|
||||
TTexture *tTexture,
|
||||
uint32_t level,
|
||||
@@ -213,8 +213,8 @@ namespace thermion
|
||||
uint32_t pixelDataType,
|
||||
void (*onComplete)(bool)
|
||||
);
|
||||
void RenderTarget_getColorTextureRenderThread(TRenderTarget *tRenderTarget, void (*onComplete)(TTexture *));
|
||||
void RenderTarget_createRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void RenderTarget_getColorTextureRenderThread(TRenderTarget *tRenderTarget, void (*onComplete)(TTexture *));
|
||||
EMSCRIPTEN_KEEPALIVE void RenderTarget_createRenderThread(
|
||||
TEngine *tEngine,
|
||||
uint32_t width,
|
||||
uint32_t height,
|
||||
@@ -222,7 +222,7 @@ namespace thermion
|
||||
TTexture *depth,
|
||||
void (*onComplete)(TRenderTarget *)
|
||||
);
|
||||
void RenderTarget_destroyRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void RenderTarget_destroyRenderThread(
|
||||
TEngine *tEngine,
|
||||
TRenderTarget *tRenderTarget,
|
||||
uint32_t requestId, VoidCallback onComplete
|
||||
@@ -230,8 +230,8 @@ namespace thermion
|
||||
|
||||
|
||||
// TextureSampler methods
|
||||
void TextureSampler_createRenderThread(void (*onComplete)(TTextureSampler*));
|
||||
void TextureSampler_createWithFilteringRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void TextureSampler_createRenderThread(void (*onComplete)(TTextureSampler*));
|
||||
EMSCRIPTEN_KEEPALIVE void TextureSampler_createWithFilteringRenderThread(
|
||||
TSamplerMinFilter minFilter,
|
||||
TSamplerMagFilter magFilter,
|
||||
TSamplerWrapMode wrapS,
|
||||
@@ -239,53 +239,53 @@ namespace thermion
|
||||
TSamplerWrapMode wrapR,
|
||||
void (*onComplete)(TTextureSampler*)
|
||||
);
|
||||
void TextureSampler_createWithComparisonRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void TextureSampler_createWithComparisonRenderThread(
|
||||
TSamplerCompareMode compareMode,
|
||||
TSamplerCompareFunc compareFunc,
|
||||
void (*onComplete)(TTextureSampler*)
|
||||
);
|
||||
void TextureSampler_setMinFilterRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void TextureSampler_setMinFilterRenderThread(
|
||||
TTextureSampler* sampler,
|
||||
TSamplerMinFilter filter,
|
||||
uint32_t requestId, VoidCallback onComplete
|
||||
);
|
||||
void TextureSampler_setMagFilterRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void TextureSampler_setMagFilterRenderThread(
|
||||
TTextureSampler* sampler,
|
||||
TSamplerMagFilter filter,
|
||||
uint32_t requestId, VoidCallback onComplete
|
||||
);
|
||||
void TextureSampler_setWrapModeSRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void TextureSampler_setWrapModeSRenderThread(
|
||||
TTextureSampler* sampler,
|
||||
TSamplerWrapMode mode,
|
||||
uint32_t requestId, VoidCallback onComplete
|
||||
);
|
||||
void TextureSampler_setWrapModeTRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void TextureSampler_setWrapModeTRenderThread(
|
||||
TTextureSampler* sampler,
|
||||
TSamplerWrapMode mode,
|
||||
uint32_t requestId, VoidCallback onComplete
|
||||
);
|
||||
void TextureSampler_setWrapModeRRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void TextureSampler_setWrapModeRRenderThread(
|
||||
TTextureSampler* sampler,
|
||||
TSamplerWrapMode mode,
|
||||
uint32_t requestId, VoidCallback onComplete
|
||||
);
|
||||
void TextureSampler_setAnisotropyRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void TextureSampler_setAnisotropyRenderThread(
|
||||
TTextureSampler* sampler,
|
||||
double anisotropy,
|
||||
uint32_t requestId, VoidCallback onComplete
|
||||
);
|
||||
void TextureSampler_setCompareModeRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void TextureSampler_setCompareModeRenderThread(
|
||||
TTextureSampler* sampler,
|
||||
TSamplerCompareMode mode,
|
||||
TTextureSamplerCompareFunc func,
|
||||
uint32_t requestId, VoidCallback onComplete
|
||||
);
|
||||
void TextureSampler_destroyRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void TextureSampler_destroyRenderThread(
|
||||
TTextureSampler* sampler,
|
||||
uint32_t requestId, VoidCallback onComplete
|
||||
);
|
||||
|
||||
void AnimationManager_setBoneTransformRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_setBoneTransformRenderThread(
|
||||
TAnimationManager *tAnimationManager,
|
||||
EntityId asset,
|
||||
int skinIndex,
|
||||
@@ -293,18 +293,18 @@ namespace thermion
|
||||
const float *const transform,
|
||||
void (*callback)(bool));
|
||||
|
||||
void AnimationManager_resetToRestPoseRenderThread(TAnimationManager *tAnimationManager, TSceneAsset *tSceneAsset, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void AnimationManager_resetToRestPoseRenderThread(TAnimationManager *tAnimationManager, TSceneAsset *tSceneAsset, uint32_t requestId, VoidCallback onComplete);
|
||||
|
||||
void GltfAssetLoader_createRenderThread(TEngine *tEngine, TMaterialProvider *tMaterialProvider, TNameComponentManager *tNameComponentManager, void (*callback)(TGltfAssetLoader *));
|
||||
void GltfResourceLoader_createRenderThread(TEngine *tEngine, void (*callback)(TGltfResourceLoader *));
|
||||
void GltfResourceLoader_destroyRenderThread(TEngine *tEngine, TGltfResourceLoader *tResourceLoader, uint32_t requestId, VoidCallback onComplete);
|
||||
void GltfResourceLoader_loadResourcesRenderThread(TGltfResourceLoader *tGltfResourceLoader, TFilamentAsset *tFilamentAsset, void (*callback)(bool));
|
||||
void GltfResourceLoader_addResourceDataRenderThread(TGltfResourceLoader *tGltfResourceLoader, const char *uri, uint8_t *data, size_t length, uint32_t requestId, VoidCallback onComplete);
|
||||
void GltfResourceLoader_asyncBeginLoadRenderThread(TGltfResourceLoader *tGltfResourceLoader, TFilamentAsset *tFilamentAsset, void (*callback)(bool));
|
||||
void GltfResourceLoader_asyncUpdateLoadRenderThread(TGltfResourceLoader *tGltfResourceLoader);
|
||||
void GltfResourceLoader_asyncGetLoadProgressRenderThread(TGltfResourceLoader *tGltfResourceLoader, void (*callback)(float));
|
||||
EMSCRIPTEN_KEEPALIVE void GltfAssetLoader_createRenderThread(TEngine *tEngine, TMaterialProvider *tMaterialProvider, TNameComponentManager *tNameComponentManager, void (*callback)(TGltfAssetLoader *));
|
||||
EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_createRenderThread(TEngine *tEngine, void (*callback)(TGltfResourceLoader *));
|
||||
EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_destroyRenderThread(TEngine *tEngine, TGltfResourceLoader *tResourceLoader, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_loadResourcesRenderThread(TGltfResourceLoader *tGltfResourceLoader, TFilamentAsset *tFilamentAsset, void (*callback)(bool));
|
||||
EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_addResourceDataRenderThread(TGltfResourceLoader *tGltfResourceLoader, const char *uri, uint8_t *data, size_t length, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_asyncBeginLoadRenderThread(TGltfResourceLoader *tGltfResourceLoader, TFilamentAsset *tFilamentAsset, void (*callback)(bool));
|
||||
EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_asyncUpdateLoadRenderThread(TGltfResourceLoader *tGltfResourceLoader);
|
||||
EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_asyncGetLoadProgressRenderThread(TGltfResourceLoader *tGltfResourceLoader, void (*callback)(float));
|
||||
|
||||
void GltfAssetLoader_loadRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void GltfAssetLoader_loadRenderThread(
|
||||
TEngine *tEngine,
|
||||
TGltfAssetLoader *tAssetLoader,
|
||||
uint8_t *data,
|
||||
@@ -312,8 +312,8 @@ namespace thermion
|
||||
uint8_t numInstances,
|
||||
void (*callback)(TFilamentAsset *)
|
||||
);
|
||||
void Scene_addFilamentAssetRenderThread(TScene* tScene, TFilamentAsset *tAsset, uint32_t requestId, VoidCallback onComplete);
|
||||
void Gizmo_createRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void Scene_addFilamentAssetRenderThread(TScene* tScene, TFilamentAsset *tAsset, uint32_t requestId, VoidCallback onComplete);
|
||||
EMSCRIPTEN_KEEPALIVE void Gizmo_createRenderThread(
|
||||
TEngine *tEngine,
|
||||
TGltfAssetLoader *tAssetLoader,
|
||||
TGltfResourceLoader *tGltfResourceLoader,
|
||||
@@ -330,4 +330,3 @@ namespace thermion
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -8,5 +8,5 @@ GRID_PACKAGE:
|
||||
GRID_GRID_OFFSET:
|
||||
.int 0
|
||||
GRID_GRID_SIZE:
|
||||
.int 50913
|
||||
.int 49793
|
||||
|
||||
|
||||
@@ -8,5 +8,5 @@ _GRID_PACKAGE:
|
||||
_GRID_GRID_OFFSET:
|
||||
.int 0
|
||||
_GRID_GRID_SIZE:
|
||||
.int 50913
|
||||
.int 49793
|
||||
|
||||
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -3,11 +3,15 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
extern const uint8_t GRID_PACKAGE[];
|
||||
extern int GRID_GRID_OFFSET;
|
||||
extern int GRID_GRID_SIZE;
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#define GRID_GRID_DATA (GRID_PACKAGE + GRID_GRID_OFFSET)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3,11 +3,16 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
extern const uint8_t OUTLINE_PACKAGE[];
|
||||
extern int OUTLINE_OUTLINE_OFFSET;
|
||||
extern int OUTLINE_OUTLINE_SIZE;
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define OUTLINE_OUTLINE_DATA (OUTLINE_PACKAGE + OUTLINE_OUTLINE_OFFSET)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -37,6 +37,10 @@ public:
|
||||
MaterialInstance** getMaterialInstances() override { return &_materialInstance; }
|
||||
size_t getMaterialInstanceCount() override { return 1; }
|
||||
|
||||
utils::Entity getEntity() override {
|
||||
return _gridEntity;
|
||||
}
|
||||
|
||||
void addAllEntities(Scene* scene) override;
|
||||
void removeAllEntities(Scene* scene) override;
|
||||
|
||||
|
||||
@@ -209,10 +209,7 @@ namespace thermion
|
||||
|
||||
SceneAsset *GridOverlay::createInstance(MaterialInstance **materialInstances, size_t materialInstanceCount)
|
||||
{
|
||||
auto instance = std::make_unique<GridOverlay>(_engine, _material);
|
||||
auto *raw = instance.get();
|
||||
_instances.push_back(std::move(instance));
|
||||
return reinterpret_cast<SceneAsset *>(raw);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void GridOverlay::addAllEntities(Scene *scene)
|
||||
@@ -250,7 +247,7 @@ namespace thermion
|
||||
}
|
||||
|
||||
size_t GridOverlay::getChildEntityCount() {
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Entity GridOverlay::findEntityByName(const char *name)
|
||||
|
||||
@@ -85,10 +85,10 @@ EMSCRIPTEN_KEEPALIVE TFilamentAsset *GltfAssetLoader_load(
|
||||
const char *const *const resourceUris = asset->getResourceUris();
|
||||
const size_t resourceUriCount = asset->getResourceUriCount();
|
||||
|
||||
Log("glTF asset : %d resource URIs, %d instances", resourceUriCount, numInstances);
|
||||
TRACE("Loading glTF asset with %d resource URIs (allocating %d reserved instances", resourceUriCount, numInstances);
|
||||
|
||||
for(int i = 0; i < resourceUriCount; i++) {
|
||||
Log("%s", resourceUris[i]);
|
||||
TRACE("%s", resourceUris[i]);
|
||||
}
|
||||
|
||||
return reinterpret_cast<TFilamentAsset *>(asset);
|
||||
|
||||
@@ -54,7 +54,7 @@ set(EMCC_CFLAGS ${EMCC_CFLAGS} -sSTACK_SIZE=10485760)
|
||||
# set(EMCC_CFLAGS ${EMCC_CFLAGS} -sLINKABLE=1)
|
||||
# set(EMCC_CFLAGS ${EMCC_CFLAGS} -sSIDE_MODULE)
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -std=c++17 -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=1")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -std=c++17 -Wno-invalid-specialization -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=1")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
name: thermion_dart
|
||||
description: 3D rendering toolkit for Dart.
|
||||
version: 0.3.0
|
||||
version: 0.3.3
|
||||
homepage: https://thermion.dev
|
||||
repository: https://github.com/nmfisher/thermion
|
||||
|
||||
environment:
|
||||
sdk: ">=3.5.4 <4.0.0"
|
||||
sdk: ">=3.6.0-0 <4.0.0"
|
||||
|
||||
dependencies:
|
||||
vector_math: ^2.1.2
|
||||
|
||||
@@ -82,10 +82,6 @@ class TestHelper {
|
||||
testDir = Directory("${packageUri}test").path;
|
||||
outDir = Directory("$testDir/output/${dir}");
|
||||
outDir.createSync(recursive: true);
|
||||
if (Platform.isMacOS) {
|
||||
DynamicLibrary.open('${testDir}/generated/objective_c.dylib');
|
||||
DynamicLibrary.open('${testDir}/generated/libThermionTextureSwift.dylib');
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
@@ -226,6 +222,10 @@ class TestHelper {
|
||||
|
||||
FFIRenderTarget? renderTarget;
|
||||
if (createRenderTarget) {
|
||||
// if (Platform.isMacOS) {
|
||||
// DynamicLibrary.open('${testDir}/generated/objective_c.dylib');
|
||||
// DynamicLibrary.open('${testDir}/generated/libThermionTextureSwift.dylib');
|
||||
// }
|
||||
// var metalColorTexture = await createTexture(
|
||||
// viewportDimensions.width, viewportDimensions.height);
|
||||
// var metalDepthTexture = await createTexture(
|
||||
|
||||
@@ -1,3 +1,25 @@
|
||||
## 0.3.3
|
||||
|
||||
- Bump "thermion_flutter" to `0.3.3`.
|
||||
|
||||
## 0.3.3-pre
|
||||
|
||||
- **DOCS**: replace thermion_flutter README with symlink to thermion_dart README.
|
||||
|
||||
## 0.3.2
|
||||
|
||||
- Bump "thermion_flutter" to `0.3.2`.
|
||||
|
||||
## 0.3.1
|
||||
|
||||
- **FIX**: addDestroySwapchain argument to createViewer() (true by default). This is only used on iOS/macOS where a single swapchain is shared between all render targets.
|
||||
- **DOCS**: fix typo in link.
|
||||
- **DOCS**: remove code from thermion_flutter README.md and point to docs/repository example instead.
|
||||
|
||||
## 0.3.0
|
||||
|
||||
- Bump "thermion_flutter" to `0.3.0`.
|
||||
|
||||
## 0.3.0
|
||||
|
||||
> Note: This release has breaking changes.
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||

|
||||
|
||||
<p align="center">
|
||||
<a href="https://thermion.dev/quickstart">Quickstart (Flutter)</a> •
|
||||
<a href="https://thermion.dev/quickstart">Documentation</a> •
|
||||
<a href="https://thermion.dev/showcase">Showcase</a> •
|
||||
<a href="https://dartpad.thermion.dev/">Playground</a> •
|
||||
<a href="https://discord.gg/h2VdDK3EAQ">Discord</a>
|
||||
</p>
|
||||
|
||||
## Cross-platform 3D engine for Dart and Flutter.
|
||||
|
||||
<a href="https://pub.dev/packages/thermion_dart"><img src="https://img.shields.io/pub/v/thermion_dart?label=pub.dev&labelColor=333940&logo=dart&color=00589B" alt="pub"></a>
|
||||
<a href="https://github.com/nmfisher/thermion"><img src="https://img.shields.io/github/stars/nmfisher/flutter_filament?style=flat&label=stars&labelColor=333940&color=8957e5&logo=github" alt="github"></a>
|
||||
<a href="https://discord.gg/h2VdDK3EAQ"><img src="https://img.shields.io/discord/993167615587520602?logo=discord&logoColor=fff&labelColor=333940" alt="discord"></a>
|
||||
<a href="https://github.com/nmfisher/thermion"><img src="https://img.shields.io/github/contributors/nmfisher/flutter_filament?logo=github&labelColor=333940" alt="contributors"></a>
|
||||
|
||||
### Quickstart (Flutter)
|
||||
|
||||
```
|
||||
_thermionViewer = await ThermionFlutterPlugin.createViewer();
|
||||
|
||||
// Geometry and models are represented as "entities". Here, we load a glTF
|
||||
// file containing a plain cube.
|
||||
// By default, all paths are treated as asset paths. To load from a file
|
||||
// instead, use file:// URIs.
|
||||
var entity =
|
||||
await _thermionViewer!.loadGlb("assets/cube.glb", keepData: true);
|
||||
|
||||
// Thermion uses a right-handed coordinate system where +Y is up and -Z is
|
||||
// "into" the screen.
|
||||
// By default, the camera is located at (0,0,0) looking at (0,0,-1); this
|
||||
// would place it directly inside the cube we just loaded.
|
||||
//
|
||||
// Let's move the camera to (0,0,10) to ensure the cube is visible in the
|
||||
// viewport.
|
||||
await _thermionViewer!.setCameraPosition(0, 0, 10);
|
||||
|
||||
// Without a light source, your scene will be totally black. Let's load a skybox
|
||||
// (a cubemap image that is rendered behind everything else in the scene)
|
||||
// and an image-based indirect light that has been precomputed from the same
|
||||
// skybox.
|
||||
await _thermionViewer!.loadSkybox("assets/default_env_skybox.ktx");
|
||||
await _thermionViewer!.loadIbl("assets/default_env_ibl.ktx");
|
||||
|
||||
// Finally, you need to explicitly enable rendering. Setting rendering to
|
||||
// false is designed to allow you to pause rendering to conserve battery life
|
||||
await _thermionViewer!.setRendering(true);
|
||||
```
|
||||
|
||||
and then in your Flutter application:
|
||||
```
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(children: [
|
||||
if (_thermionViewer != null)
|
||||
Positioned.fill(
|
||||
child: ThermionWidget(
|
||||
viewer: _thermionViewer!,
|
||||
)),
|
||||
]);
|
||||
}
|
||||
```
|
||||
1
thermion_flutter/thermion_flutter/README.md
Symbolic link
1
thermion_flutter/thermion_flutter/README.md
Symbolic link
@@ -0,0 +1 @@
|
||||
../../thermion_dart/README.md
|
||||
@@ -1,96 +1,10 @@
|
||||
For a more thorough example with both Flutter and pure Dart, see the [examples folder in the repository](https://github.com/nmfisher/thermion/tree/develop/examples).
|
||||
# Examples
|
||||
|
||||
[flutter/quickstart/lib/main.dart](https://github.com/nmfisher/thermion/tree/develop/examples)
|
||||
See the [Getting Started](https://thermion.dev/getting_started) and [Quickstart](https://thermion.dev/quickstart) sections of the documentation for step-by-step instructions in creating a Flutter app.
|
||||
|
||||
You can also jump straight to the [Quickstart example in the repository](https://github.com/nmfisher/thermion/tree/develop/examples/flutter/quickstart/lib/main.dart) for an example of a Flutter app that uses a simple 3D viewer widget.
|
||||
|
||||
```dart
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:thermion_flutter/thermion_flutter.dart';
|
||||
For a more advanced example, see the [Viewer example in the repository](https://github.com/nmfisher/thermion/tree/develop/examples/flutter/viewer/lib/main.dart).
|
||||
|
||||
import 'package:vector_math/vector_math_64.dart' as v;
|
||||
import 'dart:math';
|
||||
|
||||
void main() {
|
||||
runApp(const MyApp());
|
||||
}
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
const MyApp({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
title: 'Flutter Demo',
|
||||
theme: ThemeData(
|
||||
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
|
||||
useMaterial3: true,
|
||||
),
|
||||
home: const MyHomePage(title: 'Flutter Demo Home Page'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class MyHomePage extends StatefulWidget {
|
||||
const MyHomePage({super.key, required this.title});
|
||||
final String title;
|
||||
|
||||
@override
|
||||
State<MyHomePage> createState() => _MyHomePageState();
|
||||
}
|
||||
|
||||
class _MyHomePageState extends State<MyHomePage> {
|
||||
bool _loaded = false;
|
||||
ThermionViewer? _thermionViewer;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
Future _load() async {
|
||||
var viewer = await ThermionFlutterPlugin.createViewer();
|
||||
_thermionViewer = viewer;
|
||||
_thermionViewer!.loadSkybox("assets/default_env_skybox.ktx");
|
||||
_thermionViewer!.loadGlb("assets/cube.glb");
|
||||
|
||||
_thermionViewer!.setCameraPosition(0, 1, 10);
|
||||
_thermionViewer!.setCameraRotation(
|
||||
v.Quaternion.axisAngle(v.Vector3(1, 0, 0), -30 / 180 * pi) *
|
||||
v.Quaternion.axisAngle(v.Vector3(0, 1, 0), 15 / 180 * pi));
|
||||
_thermionViewer!.addLight(LightType.SUN, 7500, 50000, 0, 0, 0, 1, -1, -1);
|
||||
_thermionViewer!.setRendering(true);
|
||||
_loaded = true;
|
||||
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
Future _unload() async {
|
||||
var viewer = _thermionViewer!;
|
||||
_thermionViewer = null;
|
||||
setState(() {});
|
||||
await viewer.dispose();
|
||||
_loaded = false;
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
Widget _loadButton() {
|
||||
return Center(
|
||||
child: ElevatedButton(child: const Text("Load"), onPressed: _load));
|
||||
}
|
||||
|
||||
Widget _unloadButton() {
|
||||
return Center(
|
||||
child: ElevatedButton(child: const Text("Unload"), onPressed: _unload));
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(children: [
|
||||
if (_thermionViewer != null)
|
||||
Positioned.fill(child: ThermionWidget(viewer: _thermionViewer!)),
|
||||
if (!_loaded) _loadButton(),
|
||||
if (_loaded) _unloadButton(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ import 'package:thermion_flutter_platform_interface/thermion_flutter_platform_in
|
||||
class ThermionFlutterPlugin {
|
||||
ThermionFlutterPlugin._();
|
||||
|
||||
static Future<ThermionViewer> createViewer() {
|
||||
return ThermionFlutterPlatform.instance.createViewer();
|
||||
static Future<ThermionViewer> createViewer({bool destroySwapchain = true}) {
|
||||
return ThermionFlutterPlatform.instance.createViewer(destroySwapchain: destroySwapchain);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@ import 'package:thermion_dart/thermion_dart.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../../utils/camera_orientation.dart';
|
||||
|
||||
import 'dart:math';
|
||||
|
||||
class CameraOptionsWidget extends StatefulWidget {
|
||||
final Camera camera;
|
||||
final CameraOrientation cameraOrientation;
|
||||
@@ -51,7 +49,7 @@ class _CameraOptionsWidgetState extends State<CameraOptionsWidget> {
|
||||
}
|
||||
|
||||
Future _set() async {
|
||||
await widget.camera.setCameraExposure(
|
||||
await widget.camera.setExposure(
|
||||
double.parse(_apertureController.text),
|
||||
double.parse(_speedController.text),
|
||||
double.parse(_sensitivityController.text));
|
||||
@@ -59,9 +57,6 @@ class _CameraOptionsWidgetState extends State<CameraOptionsWidget> {
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
double _bloom = 0.0;
|
||||
|
||||
double _focalLength = 26.0;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Theme(
|
||||
|
||||
@@ -112,6 +112,7 @@ class _ViewerWidgetState extends State<ViewerWidget> {
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(ViewerWidget oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
if (oldWidget.manipulatorType != widget.manipulatorType) {
|
||||
@@ -140,13 +141,13 @@ class _ViewerWidgetState extends State<ViewerWidget> {
|
||||
viewport = thermionWidget;
|
||||
case ManipulatorType.ORBIT:
|
||||
viewport = ThermionListenerWidget(
|
||||
key: ObjectKey(ManipulatorType.ORBIT),
|
||||
key: const ObjectKey(ManipulatorType.ORBIT),
|
||||
inputHandler: DelegateInputHandler.fixedOrbit(viewer!,
|
||||
minimumDistance: widget.initialCameraPosition.length),
|
||||
child: thermionWidget);
|
||||
case ManipulatorType.FREE_FLIGHT:
|
||||
viewport = ThermionListenerWidget(
|
||||
key: ObjectKey(ManipulatorType.FREE_FLIGHT),
|
||||
key: const ObjectKey(ManipulatorType.FREE_FLIGHT),
|
||||
inputHandler: DelegateInputHandler.flight(viewer!),
|
||||
child: thermionWidget);
|
||||
}
|
||||
@@ -178,13 +179,13 @@ class _ViewerWidgetState extends State<ViewerWidget> {
|
||||
|
||||
await camera.lookAt(widget.initialCameraPosition);
|
||||
|
||||
await viewer!.setRendering(true);
|
||||
|
||||
if (widget.background != null) {
|
||||
await viewer!.setBackgroundColor(widget.background!.r,
|
||||
widget.background!.g, widget.background!.b, widget.background!.a);
|
||||
}
|
||||
|
||||
await viewer!.setRendering(true);
|
||||
|
||||
thermionWidget = ThermionWidget(
|
||||
key: ObjectKey(DateTime.now()),
|
||||
viewer: viewer!,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: thermion_flutter
|
||||
description: Flutter plugin for 3D rendering with the Thermion toolkit.
|
||||
version: 0.3.0
|
||||
version: 0.3.3
|
||||
homepage: https://thermion.dev
|
||||
repository: https://github.com/nmfisher/thermion
|
||||
|
||||
@@ -17,11 +17,10 @@ dependencies:
|
||||
plugin_platform_interface: ^2.0.0
|
||||
ffi: ^2.1.2
|
||||
animation_tools_dart: ^0.1.0
|
||||
thermion_dart: ^0.3.0
|
||||
thermion_flutter_platform_interface: ^0.3.0
|
||||
thermion_flutter_method_channel:
|
||||
path: ../thermion_flutter_method_channel
|
||||
thermion_flutter_web: ^0.3.0
|
||||
thermion_dart: ^0.3.3
|
||||
thermion_flutter_platform_interface: ^0.3.3
|
||||
thermion_flutter_method_channel: ^0.3.3
|
||||
thermion_flutter_web: ^0.3.3
|
||||
logging: ^1.2.0
|
||||
web: ^1.0.0
|
||||
|
||||
|
||||
@@ -1,3 +1,23 @@
|
||||
## 0.3.3
|
||||
|
||||
- Bump "thermion_flutter_method_channel" to `0.3.3`.
|
||||
|
||||
## 0.3.3-pre
|
||||
|
||||
- **FEAT**: allow passing renderTargetColorTextureFormat via ThermionFlutterOptions.
|
||||
|
||||
## 0.3.2
|
||||
|
||||
- Bump "thermion_flutter_method_channel" to `0.3.2`.
|
||||
|
||||
## 0.3.1
|
||||
|
||||
- **FIX**: addDestroySwapchain argument to createViewer() (true by default). This is only used on iOS/macOS where a single swapchain is shared between all render targets.
|
||||
|
||||
## 0.3.0
|
||||
|
||||
- Bump "thermion_flutter_method_channel" to `0.3.0`.
|
||||
|
||||
## 0.3.0
|
||||
|
||||
> Note: This release has breaking changes.
|
||||
|
||||
@@ -46,7 +46,7 @@ class ThermionFlutterMethodChannelPlatform extends ThermionFlutterPlatform {
|
||||
return asset.buffer.asUint8List(asset.offsetInBytes);
|
||||
}
|
||||
|
||||
Future<ThermionViewer> createViewer() async {
|
||||
Future<ThermionViewer> createViewer({bool destroySwapchain = true}) async {
|
||||
var driverPlatform = await channel.invokeMethod("getDriverPlatform");
|
||||
|
||||
var platformPtr = driverPlatform == null
|
||||
@@ -118,7 +118,13 @@ class ThermionFlutterMethodChannelPlatform extends ThermionFlutterPlatform {
|
||||
// TODO - see if we can use `renderStandaloneView` in FilamentViewer to
|
||||
// avoid this
|
||||
if (Platform.isMacOS || Platform.isIOS) {
|
||||
_swapChain = await FilamentApp.instance!.createHeadlessSwapChain(1, 1, hasStencilBuffer: true);
|
||||
if(destroySwapchain && _swapChain != null) {
|
||||
await FilamentApp.instance!.destroySwapChain(_swapChain!);
|
||||
_swapChain = null;
|
||||
}
|
||||
|
||||
_swapChain ??= await FilamentApp.instance!
|
||||
.createHeadlessSwapChain(1, 1, hasStencilBuffer: true);
|
||||
await FilamentApp.instance!.register(_swapChain!, viewer.view);
|
||||
await viewer.view.setRenderable(true);
|
||||
}
|
||||
@@ -179,10 +185,8 @@ class ThermionFlutterMethodChannelPlatform extends ThermionFlutterPlatform {
|
||||
}
|
||||
|
||||
_swapChain = await FilamentApp.instance!.createHeadlessSwapChain(
|
||||
descriptor.width,
|
||||
descriptor.height,
|
||||
hasStencilBuffer: true
|
||||
);
|
||||
descriptor.width, descriptor.height,
|
||||
hasStencilBuffer: true);
|
||||
|
||||
_logger.info(
|
||||
"Created headless swapchain ${descriptor.width}x${descriptor.height}",
|
||||
@@ -208,7 +212,7 @@ class ThermionFlutterMethodChannelPlatform extends ThermionFlutterPlatform {
|
||||
TextureUsage.TEXTURE_USAGE_COLOR_ATTACHMENT,
|
||||
TextureUsage.TEXTURE_USAGE_SAMPLEABLE,
|
||||
},
|
||||
textureFormat: TextureFormat.RGBA32F,
|
||||
textureFormat: options.renderTargetColorTextureFormat,
|
||||
textureSamplerType: TextureSamplerType.SAMPLER_2D,
|
||||
);
|
||||
final depth = await FilamentApp.instance!.createTexture(
|
||||
@@ -221,7 +225,7 @@ class ThermionFlutterMethodChannelPlatform extends ThermionFlutterPlatform {
|
||||
TextureUsage.TEXTURE_USAGE_STENCIL_ATTACHMENT
|
||||
},
|
||||
textureFormat:
|
||||
TextureFormat.DEPTH24_STENCIL8, // TextureFormat.DEPTH32F,
|
||||
options.renderTargetDepthTextureFormat,
|
||||
textureSamplerType: TextureSamplerType.SAMPLER_2D,
|
||||
);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
name: thermion_flutter_method_channel
|
||||
description: Desktop + mobile implementation for texture creation + registration with Flutter.
|
||||
repository: https://github.com/nmfisher/thermion_flutter/thermion_flutter
|
||||
version: 0.3.0
|
||||
version: 0.3.3
|
||||
|
||||
environment:
|
||||
sdk: ">=3.3.0 <4.0.0"
|
||||
@@ -23,8 +23,8 @@ dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
plugin_platform_interface: ^2.1.0
|
||||
thermion_flutter_platform_interface: ^0.3.0
|
||||
thermion_dart: ^0.3.0
|
||||
thermion_flutter_platform_interface: ^0.3.3
|
||||
thermion_dart: ^0.3.3
|
||||
logging: ^1.2.0
|
||||
dependency_overrides:
|
||||
thermion_dart:
|
||||
|
||||
@@ -1,3 +1,23 @@
|
||||
## 0.3.3
|
||||
|
||||
- Bump "thermion_flutter_platform_interface" to `0.3.3`.
|
||||
|
||||
## 0.3.3-pre
|
||||
|
||||
- **FEAT**: allow passing renderTargetColorTextureFormat via ThermionFlutterOptions.
|
||||
|
||||
## 0.3.2
|
||||
|
||||
- Bump "thermion_flutter_platform_interface" to `0.3.2`.
|
||||
|
||||
## 0.3.1
|
||||
|
||||
- **FIX**: addDestroySwapchain argument to createViewer() (true by default). This is only used on iOS/macOS where a single swapchain is shared between all render targets.
|
||||
|
||||
## 0.3.0
|
||||
|
||||
- Bump "thermion_flutter_platform_interface" to `0.3.0`.
|
||||
|
||||
## 0.3.0
|
||||
|
||||
- **REFACTOR**: rename ThermionFlutterTexture->PlatformTextureDescriptor.
|
||||
|
||||
@@ -7,13 +7,25 @@ import 'thermion_flutter_texture.dart';
|
||||
class ThermionFlutterOptions {
|
||||
final String? uberarchivePath;
|
||||
final Backend? backend;
|
||||
|
||||
/// The format to use for the default render target color attachment.
|
||||
/// Currently only applicable on iOS/macOS.
|
||||
///
|
||||
final TextureFormat renderTargetColorTextureFormat;
|
||||
|
||||
/// The format to use for the default render target depth attachment.
|
||||
/// Currently only applicable on iOS/macOS.
|
||||
///
|
||||
final TextureFormat renderTargetDepthTextureFormat;
|
||||
|
||||
const ThermionFlutterOptions(
|
||||
{this.uberarchivePath = null, this.backend = null});
|
||||
{this.uberarchivePath = null,
|
||||
this.backend = null,
|
||||
this.renderTargetColorTextureFormat = TextureFormat.RGBA32F,
|
||||
this.renderTargetDepthTextureFormat = TextureFormat.DEPTH24_STENCIL8});
|
||||
}
|
||||
|
||||
class ThermionFlutterWebOptions extends ThermionFlutterOptions {
|
||||
|
||||
final bool createCanvas;
|
||||
final bool importCanvasAsWidget;
|
||||
|
||||
@@ -22,8 +34,6 @@ class ThermionFlutterWebOptions extends ThermionFlutterOptions {
|
||||
this.createCanvas = true,
|
||||
String? uberarchivePath})
|
||||
: super(uberarchivePath: uberarchivePath);
|
||||
|
||||
|
||||
}
|
||||
|
||||
abstract class ThermionFlutterPlatform extends PlatformInterface {
|
||||
@@ -42,15 +52,11 @@ abstract class ThermionFlutterPlatform extends PlatformInterface {
|
||||
_options ??= const ThermionFlutterOptions();
|
||||
return _options!;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
void setOptions(covariant ThermionFlutterOptions options) {
|
||||
if (_options != null) {
|
||||
throw Exception(
|
||||
"Options can only be set once for the entire app lifecycle.");
|
||||
}
|
||||
_options = options;
|
||||
}
|
||||
|
||||
@@ -65,7 +71,7 @@ abstract class ThermionFlutterPlatform extends PlatformInterface {
|
||||
///
|
||||
///
|
||||
///
|
||||
Future<ThermionViewer> createViewer() {
|
||||
Future<ThermionViewer> createViewer({bool destroySwapchain = true}) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
name: thermion_flutter_platform_interface
|
||||
description: A common platform interface for the thermion_flutter plugin.
|
||||
repository: https://github.com/nmfisher/thermion_flutter/thermion_flutter
|
||||
version: 0.3.0
|
||||
version: 0.3.3
|
||||
|
||||
environment:
|
||||
sdk: ">=3.3.0 <4.0.0"
|
||||
@@ -11,7 +11,7 @@ dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
plugin_platform_interface: ^2.1.0
|
||||
thermion_dart: ^0.3.0
|
||||
thermion_dart: ^0.3.3
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
||||
@@ -1,3 +1,17 @@
|
||||
## 0.3.3
|
||||
|
||||
- Bump "thermion_flutter_web" to `0.3.3`.
|
||||
|
||||
## 0.3.3-pre
|
||||
|
||||
- Bump "thermion_flutter_web" to `0.3.3-pre`.
|
||||
|
||||
## 0.3.2
|
||||
|
||||
- **FIX**: add missing destroySwapchain argument for web.
|
||||
|
||||
## 0.3.1
|
||||
|
||||
## 0.3.0
|
||||
|
||||
- **REFACTOR**: rename ThermionFlutterTexture->PlatformTextureDescriptor.
|
||||
|
||||
@@ -40,7 +40,7 @@ class ThermionFlutterWebPlugin extends ThermionFlutterPlatform {
|
||||
return asset.buffer.asUint8List(asset.offsetInBytes);
|
||||
}
|
||||
|
||||
Future<ThermionViewer> createViewer() async {
|
||||
Future<ThermionViewer> createViewer({bool destroySwapchain = true}) async {
|
||||
HTMLCanvasElement? canvas;
|
||||
if (FilamentApp.instance == null) {
|
||||
// first, try and initialize bindings to see if the user has included thermion_dart.js manually in index.html
|
||||
@@ -117,7 +117,7 @@ class ThermionFlutterWebPlugin extends ThermionFlutterPlatform {
|
||||
///
|
||||
void resizeCanvas(double width, double height) async {
|
||||
_logger.info("Resizing canvas to ${width}x${height}");
|
||||
Thermion_resizeCanvas((window.devicePixelRatio * width).ceil(),
|
||||
resizeWebCanvas((window.devicePixelRatio * width).ceil(),
|
||||
(window.devicePixelRatio * height).ceil());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
name: thermion_flutter_web
|
||||
description: A web platform interface for the thermion_flutter plugin.
|
||||
repository: https://github.com/nmfisher/thermion_flutter/thermion_flutter
|
||||
version: 0.3.0
|
||||
version: 0.3.3
|
||||
|
||||
environment:
|
||||
sdk: ">=3.3.0 <4.0.0"
|
||||
@@ -20,10 +20,11 @@ dependencies:
|
||||
sdk: flutter
|
||||
plugin_platform_interface: ^2.1.0
|
||||
web: ^1.0.0
|
||||
thermion_dart: ^0.3.0
|
||||
thermion_flutter_platform_interface: ^0.3.0
|
||||
thermion_dart: ^0.3.3
|
||||
thermion_flutter_platform_interface: ^0.3.3
|
||||
flutter_web_plugins:
|
||||
sdk: flutter
|
||||
logging: ^1.3.0
|
||||
dependency_overrides:
|
||||
thermion_flutter_platform_interface:
|
||||
path: ../thermion_flutter_platform_interface
|
||||
|
||||
Reference in New Issue
Block a user