Compare commits

..

44 Commits

Author SHA1 Message Date
Nick Fisher
bbba889080 chore(release): publish packages
- thermion_dart@0.2.1-dev.0.0.15
 - thermion_flutter@0.2.1-dev.15
 - thermion_flutter_web@0.2.0+6
 - thermion_flutter_platform_interface@0.2.1-dev.15
 - thermion_flutter_ffi@0.2.1-dev.15
2024-10-31 15:32:22 +08:00
Nick Fisher
2f1c2fdd9f chore: add logging to ThermionTextureWidget 2024-10-31 15:31:41 +08:00
Nick Fisher
cee5631064 fix: multiply coordinates by pixelRatio for scale events 2024-10-31 15:31:18 +08:00
Nick Fisher
e22a0aec4d fix: remove superfluous ceil() calls for picking coordinates 2024-10-31 15:30:49 +08:00
Nick Fisher
c40faeb888 feat: expose zoomSensitivity argument for flight input handler 2024-10-31 15:27:49 +08:00
Nick Fisher
f666b36e43 fix: replace assets symlink for quickstart project 2024-10-30 12:12:09 +08:00
Nick Fisher
965be02891 fix: replace symlinks for camera_manipulation project 2024-10-30 12:12:09 +08:00
Nick Fisher
a760e0e594 chore(release): publish packages
- thermion_dart@0.2.1-dev.0.0.14
 - thermion_flutter@0.2.1-dev.14
 - thermion_flutter_platform_interface@0.2.1-dev.14
 - thermion_flutter_ffi@0.2.1-dev.14
 - thermion_flutter_web@0.2.0+5
2024-10-30 11:43:21 +08:00
Nick Fisher
82bbb572a5 feat: sanitize file paths in build.dart for Windows compatibility 2024-10-30 11:43:15 +08:00
Nick Fisher
2a9158d0e0 chore: use dependency_overrides for camera_manipulation project 2024-10-30 11:43:14 +08:00
Nick Fisher
3e29749eb4 fix: reduce size of pick functor for compatibility with armeabi-v7a 2024-10-30 11:43:14 +08:00
Nick Fisher
1ac72b7c7b chore(release): publish packages
- thermion_dart@0.2.1-dev.0.0.13
 - thermion_flutter_web@0.2.0+4
 - thermion_flutter@0.2.1-dev.13
 - thermion_flutter_ffi@0.2.1-dev.13
 - thermion_flutter_platform_interface@0.2.1-dev.13
2024-10-30 11:43:14 +08:00
Nick Fisher
fb1ed9f34b chore: test cleanup 2024-10-30 11:43:14 +08:00
Nick Fisher
07bdc028df feat: pass through fragment coordinates for picking 2024-10-30 11:43:14 +08:00
Nick Fisher
4ed0e69321 chore: remove sandbox from macos quickstart project 2024-10-30 11:43:14 +08:00
Nick Fisher
61f8be2d62 test: add perspective projection test 2024-10-30 11:43:14 +08:00
Nick Fisher
25505c7648 Update dart.yml 2024-10-30 11:43:14 +08:00
Nick Fisher
7282e713ef Update dart.yml 2024-10-30 11:43:14 +08:00
Nick Fisher
d76882f194 Update dart.yml 2024-10-30 11:43:14 +08:00
Nick Fisher
d24c55033b Update dart.yml 2024-10-30 11:43:14 +08:00
Nick Fisher
64a163a6d6 chore: dummy tests 2024-10-30 11:43:14 +08:00
Nick Fisher
f4e2a4bdc6 chore: dummy tests 2024-10-30 11:43:14 +08:00
Nick Fisher
420193a7e2 chore: dummy tests 2024-10-30 11:43:14 +08:00
Nick Fisher
99b79b4f16 chore: dummy test for GitHub actions 2024-10-30 11:43:14 +08:00
Nick Fisher
d6b2e8f8d3 chore: rename test 2024-10-30 11:43:14 +08:00
Nick Fisher
014e1bfbcd Update dart.yml 2024-10-30 11:43:13 +08:00
Nick Fisher
343f3cfd61 chore: update dart.yml 2024-10-30 11:43:13 +08:00
Nick Fisher
db3ec6b194 chore: update dart.yml 2024-10-30 11:43:13 +08:00
Nick Fisher
063a0b7ca7 chore: cleanup tests 2024-10-30 11:43:13 +08:00
Nick Fisher
5fe91f95db Update dart.yml 2024-10-30 11:43:13 +08:00
Nick Fisher
46cfc6e72f Update dart.yml 2024-10-30 11:43:13 +08:00
Nick Fisher
f71874cbf7 chore: remove combined integration_test 2024-10-30 11:43:13 +08:00
Nick Fisher
c793de7aba Update dart.yml 2024-10-30 11:43:13 +08:00
Nick Fisher
ac3550a27c Update dart.yml 2024-10-30 11:43:13 +08:00
Nick Fisher
b61e7df4ec Update dart.yml 2024-10-30 11:43:13 +08:00
Nick Fisher
1665a9698f chore: clean up thermion_dart test directory for GitHub actions 2024-10-30 11:43:13 +08:00
Nick Fisher
53bfd894b1 chore(release): publish packages
- thermion_dart@0.2.1-dev.0.0.12
 - thermion_flutter@0.2.1-dev.12
 - thermion_flutter_web@0.2.0+3
 - thermion_flutter_platform_interface@0.2.1-dev.12
 - thermion_flutter_ffi@0.2.1-dev.12
2024-10-30 11:43:13 +08:00
Nick Fisher
f2cd165ee0 Update dart.yml 2024-10-30 11:43:13 +08:00
Nick Fisher
8947f7c819 Update dart.yml 2024-10-30 11:43:13 +08:00
Nick Fisher
8402619b97 Update dart.yml 2024-10-30 11:43:13 +08:00
Nick Fisher
5c955d15db Update dart.yml 2024-10-30 11:43:13 +08:00
Nick Fisher
e01072ff00 Update dart.yml 2024-10-30 11:43:13 +08:00
Nick Fisher
e3fe7aaa88 chore: (flutter) (example) use dependency overrides for local thermion packages. We want to build this application for CI before releasing, so we need to be testing the packages that will be built 2024-10-30 11:43:13 +08:00
Nick Fisher
ff5ac01a1d chore: (windows) remove unused libs 2024-10-30 11:43:12 +08:00
1558 changed files with 82634 additions and 283731 deletions

View File

@@ -1,29 +0,0 @@
name: 'Setup Build Environment'
description: 'Set up LLVM, MESA, and Flutter for builds'
runs:
using: 'composite'
steps:
- uses: actions/checkout@v4
- name: Setup LLVM
uses: KyleMayes/install-llvm-action@v1
with:
version: "16"
- name: Add LLVM to PATH
shell: bash
run: |
echo "${{ github.workspace }}/llvm/bin" >> $GITHUB_PATH
echo "LD_LIBRARY_PATH=${{ github.workspace }}/llvm/lib/x86_64-unknown-linux-gnu/" >> $GITHUB_ENV
- name: Verify installation
shell: bash
run: clang --version
- name: Install MESA
shell: bash
run: |
sudo apt-get update
sudo apt-get install -y xvfb
sudo apt-get install -y libosmesa6-dev
- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
channel: master
architecture: X64

View File

@@ -1,3 +1,7 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
name: Dart
on:
@@ -7,130 +11,54 @@ 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:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-build-env
- run: |
cd thermion_dart
dart pub get
xvfb-run dart --enable-experiment=native-assets test \
test/asset_tests.dart \
test/instancing_tests.dart \
test/light_tests.dart \
test/entity_tests.dart \
test/geometry_tests.dart \
test/view_tests.dart \
test/postprocessing_tests.dart \
test/scene_tests.dart \
test/picking_tests.dart \
--concurrency=1
#test/overlay_tests.dart \
- name: Zip output
run: zip -r output.zip ./thermion_dart/test/output
- name: Upload test output
uses: actions/upload-artifact@v4
with:
name: golden-images-${{ github.sha }}
path: output.zip
- name: Download golden images from previous run
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh run download 15990504915 \
--name golden-images-4b9870244a529bf086280331d38c55e294425b4f \
--dir ./thermion_dart/test/golden-downloads
- name: Unzip golden images
run: |
cd thermion_dart/test/golden-downloads && unzip output.zip
- name: Install Python dependencies
run: |
python -m pip install --upgrade pip
pip install Pillow numpy
- name: Compare golden images
run: cd thermion_dart/test && python compare_goldens.py
- name: Upload logs
if: failure() || steps.build.outcome == 'failure'
uses: actions/upload-artifact@v4
with:
name: build-logs
path: |
${{ github.workspace }}/thermion_dart/.dart_tool/thermion_dart/log/build.log
retention-days: 5
flutter_examples:
name: flutter_examples
runs-on: macos-latest
thermion_dart:
name: thermion_dart
runs-on: windows-2019
defaults:
run:
working-directory: examples/flutter
working-directory: thermion_dart # Adjust this path
shell: bash # This helps ensure consistent behavior across platforms
steps:
- uses: actions/checkout@v4
- name: Set up Flutter
uses: subosito/flutter-action@v2
# Enable debug logging for Actions
- name: Enable debug logging
run: echo "ACTIONS_STEP_DEBUG=true" >> $GITHUB_ENV
# Setup Visual Studio environment
- name: Setup MSVC
uses: ilammy/msvc-dev-cmd@v1
with:
channel: master
architecture: ARM64
- name: Set up JDK 17
uses: actions/setup-java@v4
arch: x64
- uses: subosito/flutter-action@v2
with:
java-version: '17'
distribution: 'temurin'
- name: Install Android SDK
uses: android-actions/setup-android@v3
with:
api-level: 34
build-tools: 34.0.0
cmake-version: 3.22.1
ndk-version: 25.1.893739
- name: Accept Android SDK licenses
flutter-version: '3.26.0-0.1.pre' # Specify Flutter version
channel: 'master' # or 'beta', 'dev', 'master'
cache: true # Caches dependencies between runs
architecture: x64 # Explicitly specify x64 architecture
- name: Install dependencies
run: flutter pub get # even though this is a Dart package, it has as dev_dependency on objective_c for testing which for some reason has a Flutter dependency
# Ensure Visual C++ runtime is available
- name: Install Visual C++ redistributable
run: |
yes | $ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager --licenses
- run: cd quickstart && flutter pub get && flutter build macos
# - run: cd quickstart && flutter pub get && flutter build ios
- run: cd quickstart && flutter pub get && flutter build appbundle
- run: cd quickstart && flutter build web
- run: cd picking && flutter pub get && flutter build macos
# - run: cd picking && flutter pub get && flutter build ios
- run: cd picking && flutter pub get && flutter build appbundle
- run: cd picking && flutter build web
- 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
/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
choco install visualstudio2019-workload-vctools -y
choco install vcredist140 -y
# Uncomment this step to verify the use of 'dart format' on each commit.
# - name: Verify formatting
# run: dart format --output=none --set-exit-if-changed .
#- name: Analyze project source
# run: dart analyze
- name: Build and Test
shell: cmd
run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
dart --enable-experiment=native-assets test test/dummy_tests.dart
# Upload logs on failure
- name: Upload logs
if: failure() || steps.build.outcome == 'failure'
uses: actions/upload-artifact@v4
@@ -138,66 +66,41 @@ jobs:
name: build-logs
path: |
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
# thermion_dart:
# name: thermion_dart
# runs-on: macos-latest
# defaults:
# run:
# working-directory: thermion_dart
# steps:
# - uses: actions/checkout@v4
# - name: Set up Flutter
# uses: subosito/flutter-action@v2
# with:
# channel: master
# - run: flutter pub get
# - run: dart --enable-experiment=native-assets test -j1 test/light_tests.dart
# Capture crash dumps if they exist
- name: Collect crash dumps
if: failure()
uses: actions/upload-artifact@v3
with:
name: crash-dumps
path: |
${{ runner.temp }}/*.dmp
${{ env.LOCALAPPDATA }}/Temp/*.dmp
${{ env.LOCALAPPDATA }}/CrashDumps/*.dmp
# thermion_flutter:
# name: thermion_flutter
# runs-on: macos-13
# defaults:
# run:
# working-directory: thermion_flutter/thermion_flutter # Adjust this path
# steps:
# - uses: actions/checkout@v4
# - uses: dart-lang/setup-dart@9a04e6d73cca37bd455e0608d7e5092f881fd603
# - name: Install dependencies
# run: dart pub get
#
#
##- uses: actions/checkout@v4
#- name: Setup LLVM
# uses: KyleMayes/install-llvm-action@v1
# with:
# version: "16"
#- name: Add LLVM to PATH
# run: |
# echo "${{ github.workspace }}/llvm/bin" >> $GITHUB_PATH
# echo "LD_LIBRARY_PATH=${{ github.workspace }}/llvm/lib/x86_64-unknown-linux-gnu/" >> $GITHUB_ENV
#- name: Verify installation
# run: clang --version
#- name: Install MESA
# run: |
# sudo apt-get update
# sudo apt-get install -y xvfb
# sudo apt-get install -y libosmesa6-dev
# #sudo apt-get -y build-dep mesa
# #git clone https://gitlab.freedesktop.org/mesa/mesa.git
# #cd mesa
# #git checkout mesa-23.2.1
# #mkdir -p out
# #meson setup builddir/ -Dprefix="$(pwd)/out" -Dosmesa=true -Dglx=xlib -Dgallium-drivers=swrast -Dvulkan-drivers=swrast
# #meson install -C builddir/
#- name: Install Vulkan SDK and dependencies
# run: |
# wget -qO - https://packages.lunarg.com/lunarg-signing-key-pub.asc | sudo apt-key add -
# sudo wget -qO /etc/apt/sources.list.d/lunarg-vulkan-jammy.list https://packages.lunarg.com/vulkan/lunarg-vulkan-jammy.list
# sudo apt-get update
# sudo apt-get install -y vulkan-sdk
#- name: Set up Flutter
# uses: subosito/flutter-action@v2
# with:
# channel: master
# architecture: X64
# # Uncomment this step to verify the use of 'dart format' on each commit.
# # - name: Verify formatting
# # run: dart format --output=none --set-exit-if-changed .
# - name: Analyze project source
# run: dart analyze
# - name: Run tests
# run: dart --enable-experiment=native-assets test

2
.gitignore vendored
View File

@@ -1,4 +1,5 @@
**/*/.cxx
**/.github
**/.idea
.dart_tool
**/.dart_tool
@@ -9,4 +10,3 @@
pubspec_overrides.yaml
/pubspec.lock
*.iml
**/*/*.filamat

View File

@@ -3,391 +3,6 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## 2025-07-24
### Changes
---
Packages with breaking changes:
- There are no breaking changes in this release.
Packages with other changes:
- [`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.3`
- Bump "thermion_dart" to `0.3.3`.
#### `thermion_flutter_method_channel` - `v0.3.3`
- Bump "thermion_flutter_method_channel" to `0.3.3`.
#### `thermion_flutter_platform_interface` - `v0.3.3`
- Bump "thermion_flutter_platform_interface" to `0.3.3`.
#### `thermion_flutter_web` - `v0.3.3`
- Bump "thermion_flutter_web" to `0.3.3`.
#### `thermion_flutter` - `v0.3.3`
- 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
---
Packages with breaking changes:
- There are no breaking changes in this release.
Packages with other changes:
- [`thermion_dart` - `v0.2.1-dev.20.0`](#thermion_dart---v021-dev200)
- [`thermion_flutter` - `v0.2.1-dev.20.0`](#thermion_flutter---v021-dev200)
- [`thermion_flutter_platform_interface` - `v0.2.1-dev.20.0`](#thermion_flutter_platform_interface---v021-dev200)
- [`thermion_flutter_ffi` - `v0.2.1-dev.20.0`](#thermion_flutter_ffi---v021-dev200)
- [`thermion_flutter_web` - `v0.2.0+11`](#thermion_flutter_web---v02011)
Packages with dependency updates only:
> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project.
- `thermion_flutter_web` - `v0.2.0+11`
---
#### `thermion_dart` - `v0.2.1-dev.20.0`
- **FIX**: only use Windows-style ndkRoot when building on Windows.
#### `thermion_flutter` - `v0.2.1-dev.20.0`
- Bump "thermion_flutter" to `0.2.1-dev.20.0`.
#### `thermion_flutter_platform_interface` - `v0.2.1-dev.20.0`
- Bump "thermion_flutter_platform_interface" to `0.2.1-dev.20.0`.
#### `thermion_flutter_ffi` - `v0.2.1-dev.20.0`
- Bump "thermion_flutter_ffi" to `0.2.1-dev.20.0`.
## 2024-11-21
### Changes
---
Packages with breaking changes:
- [`thermion_dart` - `v0.2.1-dev.19.0`](#thermion_dart---v021-dev190)
Packages with other changes:
- [`thermion_flutter` - `v0.2.1-dev.19.0`](#thermion_flutter---v021-dev190)
- [`thermion_flutter_web` - `v0.2.0+10`](#thermion_flutter_web---v02010)
- [`thermion_flutter_platform_interface` - `v0.2.1-dev.19.0`](#thermion_flutter_platform_interface---v021-dev190)
- [`thermion_flutter_ffi` - `v0.2.1-dev.19.0`](#thermion_flutter_ffi---v021-dev190)
Packages with dependency updates only:
> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project.
- `thermion_flutter` - `v0.2.1-dev.19.0`
- `thermion_flutter_web` - `v0.2.0+10`
- `thermion_flutter_platform_interface` - `v0.2.1-dev.19.0`
- `thermion_flutter_ffi` - `v0.2.1-dev.19.0`
---
#### `thermion_dart` - `v0.2.1-dev.19.0`
- **FEAT**: use InputAction.ZOOM for scroll wheel in free flight handler.
- **FEAT**: free flight camera improvements.
- **BREAKING** **FIX**: update Makefile & rebuild materials for Vulkan.
## 2024-11-18
### Changes
---
Packages with breaking changes:
- There are no breaking changes in this release.
Packages with other changes:
- [`thermion_dart` - `v0.2.1-dev.18.0`](#thermion_dart---v021-dev180)
- [`thermion_flutter` - `v0.2.1-dev.18.0`](#thermion_flutter---v021-dev180)
- [`thermion_flutter_web` - `v0.2.0+9`](#thermion_flutter_web---v0209)
- [`thermion_flutter_platform_interface` - `v0.2.1-dev.18.0`](#thermion_flutter_platform_interface---v021-dev180)
- [`thermion_flutter_ffi` - `v0.2.1-dev.18.0`](#thermion_flutter_ffi---v021-dev180)
Packages with dependency updates only:
> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project.
- `thermion_flutter_web` - `v0.2.0+9`
- `thermion_flutter_platform_interface` - `v0.2.1-dev.18.0`
- `thermion_flutter_ffi` - `v0.2.1-dev.18.0`
---
#### `thermion_dart` - `v0.2.1-dev.18.0`
- **FEAT**: add MaterialInstance.setDepthFunc.
#### `thermion_flutter` - `v0.2.1-dev.18.0`
- **FIX**: fix windows import header.
## 2024-11-15
### Changes
---
Packages with breaking changes:
- There are no breaking changes in this release.
Packages with other changes:
- [`thermion_dart` - `v0.2.1-dev.0.0.17`](#thermion_dart---v021-dev0017)
- [`thermion_flutter` - `v0.2.1-dev.17`](#thermion_flutter---v021-dev17)
- [`thermion_flutter_web` - `v0.2.0+8`](#thermion_flutter_web---v0208)
- [`thermion_flutter_platform_interface` - `v0.2.1-dev.17`](#thermion_flutter_platform_interface---v021-dev17)
- [`thermion_flutter_ffi` - `v0.2.1-dev.17`](#thermion_flutter_ffi---v021-dev17)
Packages with dependency updates only:
> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project.
- `thermion_flutter_web` - `v0.2.0+8`
- `thermion_flutter_platform_interface` - `v0.2.1-dev.17`
- `thermion_flutter_ffi` - `v0.2.1-dev.17`
---
#### `thermion_dart` - `v0.2.1-dev.0.0.17`
- **FIX**: remove superfluous ceil() calls for picking coordinates.
- **FIX**: remove superfluous ceil() calls for picking coordinates.
- **FIX**: reduce size of pick functor for compatibility with armeabi-v7a.
- **FIX**: reduce size of pick functor for compatibility with armeabi-v7a.
- **FEAT**: add Dart methods for getRenderableBoundingBox, setParameterInt and setParameterFloat4.
- **FEAT**: Rename Gizmo material to UnlitFixedSize, and expose methods for using this material on other entities. Also exposes new methods for setting single float parameters.
- **FEAT**: expose zoomSensitivity argument for flight input handler.
- **FEAT**: Rename Gizmo material to UnlitFixedSize, and expose methods for using this material on other entities. Also exposes new methods for setting single float parameters.
- **FEAT**: expose zoomSensitivity argument for flight input handler.
- **FEAT**: sanitize file paths in build.dart for Windows compatibility.
- **FEAT**: pass through fragment coordinates for picking.
- **FEAT**: sanitize file paths in build.dart for Windows compatibility.
- **FEAT**: pass through fragment coordinates for picking.
#### `thermion_flutter` - `v0.2.1-dev.17`
- **FIX**: multiply coordinates by pixelRatio for scale events.
- **FIX**: multiply coordinates by pixelRatio for scale events.
## 2024-10-31
### Changes
---
Packages with breaking changes:
- There are no breaking changes in this release.
Packages with other changes:
- [`thermion_dart` - `v0.2.1-dev.0.0.16`](#thermion_dart---v021-dev0016)
- [`thermion_flutter` - `v0.2.1-dev.16`](#thermion_flutter---v021-dev16)
- [`thermion_flutter_web` - `v0.2.0+7`](#thermion_flutter_web---v0207)
- [`thermion_flutter_platform_interface` - `v0.2.1-dev.16`](#thermion_flutter_platform_interface---v021-dev16)
- [`thermion_flutter_ffi` - `v0.2.1-dev.16`](#thermion_flutter_ffi---v021-dev16)
Packages with dependency updates only:
> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project.
- `thermion_flutter` - `v0.2.1-dev.16`
- `thermion_flutter_web` - `v0.2.0+7`
- `thermion_flutter_platform_interface` - `v0.2.1-dev.16`
- `thermion_flutter_ffi` - `v0.2.1-dev.16`
---
#### `thermion_dart` - `v0.2.1-dev.0.0.16`
- **FEAT**: Rename Gizmo material to UnlitFixedSize, and expose methods for using this material on other entities. Also exposes new methods for setting single float parameters.
## 2024-10-31
### Changes

View File

@@ -1,76 +0,0 @@
FROM ubuntu:22.04
# Set non-interactive mode for apt
ENV DEBIAN_FRONTEND=noninteractive
# Install dependencies and add LLVM repository
RUN apt-get update && apt-get install -y \
git \
build-essential \
cmake \
ninja-build \
libgl1-mesa-dev \
libc++-dev \
libc++abi-dev \
libsdl2-dev \
libxi-dev \
libtbb-dev \
libassimp-dev \
python3 \
python3-pip \
curl \
wget \
software-properties-common \
lsb-release \
&& rm -rf /var/lib/apt/lists/*
# Add LLVM repository and install Clang 16
RUN wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - \
&& add-apt-repository "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-16 main" \
&& apt-get update \
&& apt-get install -y \
clang-16 \
clang++-16 \
libc++-16-dev \
libc++abi-16-dev \
&& rm -rf /var/lib/apt/lists/*
# Set Clang 16 as default
RUN update-alternatives --install /usr/bin/clang clang /usr/bin/clang-16 100 \
&& update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-16 100
# Set environment variables for Clang
ENV CC=clang-16
ENV CXX=clang++-16
# Set working directory
WORKDIR /opt
# Clone the filament repository
RUN git clone https://github.com/google/filament.git
# Change to filament directory
WORKDIR /opt/filament
# Checkout the specific version
RUN git checkout v1.58.0
# Add CMAKE_POSITION_INDEPENDENT_CODE setting after project() line
RUN sed -i '/^project(/a set(CMAKE_POSITION_INDEPENDENT_CODE ON)\nadd_compile_definitions(GLTFIO_USE_FILESYSTEM=0)' CMakeLists.txt
RUN sed -i -e '/^#define GLTFIO_USE_FILESYSTEM 1$/i\
#ifndef GLTFIO_USE_FILESYSTEM' -e '/^#define GLTFIO_USE_FILESYSTEM 1$/a\
#endif' libs/gltfio/src/FFilamentAsset.h
# Make build script executable
RUN chmod +x build.sh
# Run the build commands
RUN ./build.sh -l -i -f -p desktop release
RUN ./build.sh -l -i -f -p desktop release zstd
RUN ./build.sh -l -i -f -p desktop release tinyexr
RUN ./build.sh -l -i -f -p desktop release imageio
RUN zip -r filament-v1.58.0-linux-release.zip /opt/filament/out/release/filament/lib/x86_64/*.a /opt/filament/out/cmake-release/third_party/tinyexr/tnt/libtinyexr.a /opt/filament/out/cmake-release/libs/imageio/libimageio.a
# Set the working directory to the build output
WORKDIR /opt/filament/out/release
CMD ["/bin/bash"]

View File

@@ -1,59 +1,36 @@
wasm:
@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:
dart-web:
cd thermion_dart/native/web; mkdir -p build && cd build && emcmake cmake .. && emmake make
dart-web-clean:
cd thermion_dart/native/web && rm -rf build
wasm-example-web:
cd examples/dart/js_wasm
mkdir -p build
dart compile js web/example.dart -o build/example.dart.js
dart-wasm-cli-example: dart-web-clean dart-web
cd thermion_dart/examples/cli_wasm/bin && dart compile wasm example_cli.dart && node main.js
dart-web-example: dart-web
cp thermion_dart/native/web/build/build/out/thermion_dart* examples/web_wasm/bin
cd thermion_dart/examples/web_wasm/bin && dart compile wasm example_web.dart
flutter-example-web: dart-web-clean dart-web
cd thermion_flutter_federated/thermion_flutter/example/web && dart compile wasm main.dart && cd .. && flutter build web --wasm --profile
flutter-example-macos:
cd thermion_flutter_federated/thermion_flutter/example/web && flutter run -d macos
swift-bindings:
swiftc -c thermion_dart/native/macos/ThermionTexture.swift -module-name swift_module -emit-objc-header-path thermion_dart/native/include/generated/ThermionTextureSwiftObjCAPI.h -emit-library -o thermion_dart/test/generated/libThermionTextureSwift.dylib
swiftc -c thermion_flutter/thermion_flutter/macos/Classes/ThermionTexture.swift -module-name swift_module -emit-objc-header-path thermion_dart/native/include/generated/ThermionTextureSwiftObjCAPI.h -emit-library -o thermion_dart/test/libThermionTextureSwift.dylib
cd thermion_dart/ && dart --enable-experiment=native-assets run ffigen --config ffigen/swift.yaml
bindings:
cd thermion_dart/ && dart --enable-experiment=native-assets run ffigen --config ffigen/native.yaml
shared:
cd thermion_dart/native && make
# We compile a small set of custom materials for various helpers (background image, gizmo, etc)
# You must specify the `FILAMENT_PATH` environment variable, either the path /out/release
# eg: FILAMENT_PATH=/path/to/filament/out/release/bin make materials
#
materials: FORCE
ifndef FILAMENT_PATH
@echo "FILAMENT_PATH is not set"
else
@echo "Using Filament build from ${FILAMENT_PATH}"
./materials/build.sh
endif
resources: FORCE
ifndef FILAMENT_PATH
@echo "FILAMENT_PATH is not set"
else
@echo "Using Filament build from ${FILAMENT_PATH}"
@for gizmo in translation rotation; do \
$(FILAMENT_PATH)/resgen -c -p $${gizmo}_gizmo_glb -x thermion_dart/native/include/resources assets/$${gizmo}_gizmo.glb || exit 1; \
echo '#include "'$${gizmo}_gizmo_glb.h'"' | cat - thermion_dart/native/include/resources/$${gizmo}_gizmo_glb.c > thermion_dart/native/include/resources/$${gizmo}_gizmo_glb.c.new; \
mv thermion_dart/native/include/resources/$${gizmo}_gizmo_glb.c.new thermion_dart/native/include/resources/$${gizmo}_gizmo_glb.c; \
@for material in unlit image gizmo grid; do \
${FILAMENT_PATH}/matc -a opengl -a metal -o materials/$$material.filamat materials/$$material.mat; \
$(FILAMENT_PATH)/resgen -c -p $$material -x thermion_dart/native/include/material/ materials/$$material.filamat; \
echo '#include "'$$material'.h"' | cat - thermion_dart/native/include/material/$$material.c > thermion_dart/native/include/material/$$material.c.new; \
mv thermion_dart/native/include/material/$$material.c.new thermion_dart/native/include/material/$$material.c; \
done
endif
#rm materials/*.filamat
FORCE: ;

View File

@@ -3,7 +3,7 @@
<p align="center">
<a href="https://thermion.dev/quickstart">Quickstart (Flutter)</a> •
<a href="https://thermion.dev/">Documentation</a> •
<a href="https://thermion.dev/showcase">Showcase</a> •
<a href="https://thermion.dev/examples">Showcase</a> •
<a href="https://dartpad.thermion.dev/">Playground</a> •
<a href="https://discord.gg/h2VdDK3EAQ">Discord</a>
</p>
@@ -15,8 +15,6 @@
<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>
https://github.com/user-attachments/assets/b0c07b5a-6156-4e42-a09b-5f9bd85fbf32
### Features
- Supports iOS (arm64), MacOS (arm64/x64), Android (arm64), Windows (x64) (>= 10), Web/WASM
@@ -24,46 +22,58 @@ https://github.com/user-attachments/assets/b0c07b5a-6156-4e42-a09b-5f9bd85fbf32
- camera/entity manipulation with mouse (desktop) and gestures (mobile)
- skinning + morph animations
Uses the Filament PBR engine (currently v1.56.4).
### Quickstart (Flutter)
From the command line:
```bash
```
flutter channel master
flutter upgrade
flutter config --enable-native-assets
```
In your Flutter app:
```
_thermionViewer = await ThermionFlutterPlugin.createViewer();
```dart
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(children: [
Positioned.fill(
child: ViewerWidget(
assetPath: "assets/cube.glb",
skyboxPath: "assets/default_env_skybox.ktx",
iblPath: "assets/default_env_ibl.ktx",
transformToUnitCube: true,
initialCameraPosition: Vector3(0, 0, 6),
background: Colors.blue,
manipulatorType: ManipulatorType.ORBIT,
onViewerAvailable: (viewer) async {
await Future.delayed(const Duration(seconds: 5));
await viewer.removeSkybox();
},
initial: Container(
color: Colors.red,
),
))]));
}
// 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);
```
> the first time you build an app that consumes this package, the Dart native-assets build system will download static binaries from Cloudflare. This may take a few minutes (depending on which platform you are compiling for). These will be cached, so subsequent builds will be much faster.
and then in your Flutter application:
```
@override
Widget build(BuildContext context) {
return Stack(children: [
if (_thermionViewer != null)
Positioned.fill(
child: ThermionWidget(
viewer: _thermionViewer!,
)),
]);
}
```
### Sponsors, Contributors & Acknowledgments
@@ -78,5 +88,4 @@ Thank you to the following people:
- @daverin for MacOS library contributions
- @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

Binary file not shown.

Binary file not shown.

View File

@@ -7,21 +7,15 @@
"Getting Started",
[
["Overview", "/"],
["Getting Started", "/getting_started"],
["Quick Start", "/quickstart"],
["Viewer", "/viewer"],
["Camera Manipulation", "/camera_manipulation"]
]
],
["Misc.", [
["Debugging", "/debugging"],
["Playground", "https://dartpad.thermion.dev"],
["Showcase", "/showcase"],
["Windows", "/windows"],
["Android", "/android"],
["iOS", "/ios"],
["Web", "/web"],
["Linux", "/linux"],
["Contributing", "/contributing"],
["Discord", "https://discord.gg/h2VdDK3EAQ"]
]]

View File

@@ -12,3 +12,15 @@ Thermion requires Android SDK version 22, so change your `app/android/build.grad
}
```
### Shrink/Minify Resources
In release mode, you must add the following to your `app/build.gradle`:
```
buildTypes {
release {
shrinkResources false
minifyEnabled false
}
}
```

View File

@@ -0,0 +1,63 @@
## 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.

View File

@@ -1,27 +0,0 @@
# Debugging
If something is crashing or not working as expected, you can enable verbose logging and/or debug builds (particularly useful for debugging with lldb or getting legible stack traces):
Add a `hooks` section to your app's `pubspec.yaml`, e.g.
```
name: example_cli
description: A sample command-line application.
version: 1.0.0
environment:
sdk: ^3.3.0
# Add the below
hooks:
user_defines:
thermion_dart:
mode: debug
tracing: enabled
```
After changing the `hooks` section, make sure you run `flutter clean` to propagate the changes correctly.
> [!CAUTION]
> Debug builds won't work for Android. This is a known upstream issue with Filament.
Unless `mode: debug` is specified in your `pubspec.yaml`, Thermion will use release builds under the hood, even if your app is compiled/runing in debug mode.

View File

@@ -1,40 +0,0 @@
## 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:
![XCode screenshot](images/macos_min_deployment.png)
</Accordion>

View File

@@ -16,7 +16,7 @@ Thermion is divided into two packages:
With this structure, the Flutter-specific components are not coupled to the Dart components, meaning Thermion can be used for rendering in both Flutter and non-Flutter applications.
For example, Thermion ships with examples for rendering with Dart only (no Flutter) with a CLI/headless application on MacOS, and with a Javascript/WASM/HTML application in browsers.
For example, Thermion ships with examples for rendering with Dart only (no Flutter) with a CLI/headless application on MacOS, and with a Javascript/WASM/HTML applicaiton in browsers.
`thermion_flutter` exports `thermion_dart`, so if you are working with a Flutter application, you will only need to import `thermion_fluttter`.

View File

@@ -1,55 +0,0 @@
## iOS
### Min iOS version
Thermion requires a minimum iOS version of 13.0. When building a Flutter application, ensure your application's `ios/Podfile` contains the following:
```ruby
platform :ios, '13.0'
```
and in ios/Info.plist:
```xml
<key>LSMinimumSystemVersion</key>
<string>13.0</string>
```
When submitting to the App Store, you may encounter an error saying `thermion_dart.framework does not supported the minimum deployment target in Info.plist`.
This is because Flutter hardcodes a deployment target of iOS 12.0 when invoking the native assets build, which conflicts with actual requirement.
After running `flutter build ios` (but before archiving the build and submitting to the App Store), run the following script to replace the `MinimumOSVersion`:
```
#!/bin/zsh
# Array of directories containing Info.plist files
directories=(
"./build/ios/iphoneos/Runner.app/Frameworks/thermion_dart.framework"
"./build/ios/Release-iphoneos/Runner.app/Frameworks/thermion_dart.framework"
"./build/native_assets/ios/thermion_dart.framework"
)
# Loop through each directory
for dir in "${directories[@]}"; do
plist_path="$dir/Info.plist"
# Check if Info.plist exists in the directory
if [[ -f "$plist_path" ]]; then
echo "Processing: $plist_path"
# Use PlistBuddy to change the MinimumOSVersion
/usr/libexec/PlistBuddy -c "Set :MinimumOSVersion 13.0" "$plist_path" 2>/dev/null
if [[ $? -eq 0 ]]; then
echo "✓ Successfully updated version to 13.0"
else
echo "✗ Failed to update version in $plist_path"
fi
else
echo "✗ Info.plist not found in $dir"
fi
done
```

View File

@@ -1,10 +0,0 @@
## Linux support
Currently, only the Dart package (`thermion_dart`) will work on Linux (primarily for the automated build/testing pipeline).
Filament has been built for Ubuntu 22.04; other distributions may work, but YMMV.
The Flutter package (`thermion_flutter`) won't work; it's missing the platform glue code necessary to set up the render target. Support will eventually be added, but there is currently no estimated timeline.
Contributions are welcome and it's actually not a lot of work. Join the Discord if you want to help out.

View File

@@ -1,199 +1,216 @@
# Quick Start
## Quickstart (Flutter)
If all you need is a quick and easy route to rendering a single 3D model in your Flutter application, start with `ViewerWidget`.
> You can find the entire project below in the [flutter/quickstart](https://github.com/nmfisher/thermion_examples/tree/master/flutter/quickstart) folder of the `thermion_examples` repository.
This is a simplified, Flutter-only wrapper around the underlying 3D rendering API with sane defaults for most people.
1. Switch to Flutter master channel, upgrade Flutter, create a new project, then add `thermion_flutter` as a dependency
`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
```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
```
## Setup
2. If running on iOS or MacOS, change the minimum deployment target to OSX 13
Follow the steps listed in [Getting Started](./getting_started) to configure your Flutter installation and project.
<Accordion title="Click to open iOS/MacOS instructions">
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`.
Make sure the `platform` entry refers to `13.0` in your Podfile.
## Basic Usage
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:
![XCode screenshot](images/macos_min_deployment.png)
</Accordion>
2. Add a folder containing your assets (glTF model + skybox ktx) to your `pubspec.yaml` asset list
```yaml
...
flutter
uses-material-design: true
assets:
- assets/
```
3. Create an instance of `ThermionFlutterPlugin` in your app.
```dart
import 'package:flutter/material.dart';
import 'package:thermion_flutter/thermion_flutter.dart';
import 'path_to_your_viewer_widget.dart';
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: ViewerWidget(
assetPath: 'assets/my_model.glb',
initialCameraPosition: Vector3(0, 0, 5),
manipulatorType: ManipulatorType.ORBIT,
),
),
);
class _MyAppState extends State<MyApp> {
  late ThermionFlutterPlugin _thermionFlutterPlugin; 
late Future<ThermionViewer> _thermionViewer;
  void initState() {   
_thermionFlutterPlugin = ThermionFlutterPlugin();   
_thermionViewer = _thermionFlutterPlugin.createViewer(); 
}
}
```
## Properties
| Property | Type | Default | Description |
|----------|------|---------|-------------|
| `initial` | `Widget` | Red decorated box | Widget to display while the viewer is loading |
| `initialCameraPosition` | `Vector3` | `Vector3(0, 0, 5)` | The starting position for the camera (looking towards origin) |
| `showFpsCounter` | `bool` | `false` | Whether to show an FPS counter overlay |
| `assetPath` | `String?` | `null` | Path to the glTF asset to load |
| `skyboxPath` | `String?` | `null` | Path to a KTX skybox image |
| `iblPath` | `String?` | `null` | Path to a KTX image for image-based lighting |
| `directLightType` | `LightType?` | `null` | Type of direct light to add to the scene |
| `transformToUnitCube` | `bool` | `true` | If true, rescales the model to fit within a 1x1x1 cube |
| `postProcessing` | `bool` | `true` | Enables ACES tone mapping and basic anti-aliasing |
| `background` | `Color?` | `null` | Background color (not visible when skybox is provided) |
| `destroyEngineOnUnload` | `bool` | `false` | If true, disposes the engine when widget is disposed |
| `manipulatorType` | `ManipulatorType` | `ORBIT` | Type of camera control to use |
| `onViewerAvailable` | `Future Function(ThermionViewer)?` | `null` | Callback when viewer is ready |
## Camera Manipulators
`ViewerWidget` supports three different camera manipulation modes:
- `ManipulatorType.NONE`: No camera controls, static view
- `ManipulatorType.ORBIT`: Orbit controls (pinch to zoom, swipe to rotate)
- `ManipulatorType.FREE_FLIGHT`: Free flight controls for unrestricted movement
Example:
4. Add a `ThermionWidget` to your widget hierarchy
```dart
ViewerWidget(
assetPath: 'assets/model.glb',
manipulatorType: ManipulatorType.FREE_FLIGHT,
)
```
## Lighting
class _MyAppState extends State<MyApp> {
You can set up lighting in multiple ways:
### Image-Based Lighting
```dart
ViewerWidget(
assetPath: 'assets/model.glb',
iblPath: 'assets/environment.ktx',
)
```
### Direct Light
```dart
ViewerWidget(
assetPath: 'assets/model.glb',
directLightType: LightType.SUN,
)
```
## Advanced Usage
### Accessing the Viewer
You can get access to the underlying `ThermionViewer` object for more advanced control:
```dart
ViewerWidget(
assetPath: 'assets/model.glb',
onViewerAvailable: (viewer) async {
// Now you can use the viewer directly
final camera = await viewer.getActiveCamera();
await camera.lookAt(Vector3(0, 1, 5));
// Add custom lights, manipulate materials, etc.
},
)
```
### Changing Manipulator at Runtime
The `manipulatorType` is the only property that can be changed after the widget is created:
```dart
class _MyWidgetState extends State<MyWidget> {
ManipulatorType _manipulatorType = ManipulatorType.ORBIT;
@override
Widget build(BuildContext context) {
return Column(
children: [
Expanded(
child: ViewerWidget(
assetPath: 'assets/model.glb',
manipulatorType: _manipulatorType,
),
),
Row(
children: [
ElevatedButton(
onPressed: () {
ThermionViewer? _thermionViewer;
void initState() {   
_thermionFlutterPlugin.createViewer().then((viewer) {
setState(() {
_manipulatorType = ManipulatorType.ORBIT;
_thermionViewer = viewer;
});
},
child: Text('Orbit'),
),
ElevatedButton(
onPressed: () {
setState(() {
_manipulatorType = ManipulatorType.FREE_FLIGHT;
});
},
child: Text('Free Flight'),
),
],
),
],
);
}   
Widget build(BuildContext context) {
return Stack(children:[
if(_thermionViewer != null)
    Positioned.fill(
child:ThermionWidget(
plugin:_thermionViewer!
        ) 
    )
    ]); 
}
}
```
## Limitations
- Only the `manipulatorType` property can be changed at runtime. For any other property changes, create a new widget.
- The widget requires that you have the correct environment setup for Thermion (Flutter master channel with native assets enabled).
## Example
Here's a complete example showing how to use `ViewerWidget` with multiple configuration options:
4. Add a button to load the model when pressed
```dart
import 'package:flutter/material.dart';
import 'package:thermion_flutter/thermion_flutter.dart';
import 'package:vector_math/vector_math_64.dart';
class ModelViewer extends StatelessWidget {
@override
...
class _MyAppState extends State<MyApp> {
...
bool _loaded = false;
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('3D Model Viewer')),
body: ViewerWidget(
assetPath: 'assets/robot.glb',
skyboxPath: 'assets/studio_skybox.ktx',
iblPath: 'assets/studio_ibl.ktx',
initialCameraPosition: Vector3(0, 1.5, 3),
manipulatorType: ManipulatorType.ORBIT,
showFpsCounter: true,
background: Colors.grey,
postProcessing: true,
transformToUnitCube: true,
onViewerAvailable: (viewer) async {
// You can perform additional setup here
print('Viewer is ready!');
},
),
);
return Stack(children:[
    if(_thermionViewer != null)
    Positioned.fill(
child:ThermionWidget(
plugin:_thermionViewer!
        ) 
    ),
if (!_loaded)
Center(
child: ElevatedButton(
child: const Text("Load"),
onPressed: () async {
// TODO
_loaded = true;
setState(() {});
}))
    ]); 
}}
```
5. When the button is pressed, load a skybox, lighting and the glb asset
You will need to import the `dart:math` and `package:vector_math` libraries.
```dart
import 'package:vector_math/vector_math_64.dart' as v;
import 'dart:math';
...
class _MyAppState extends State<MyApp> {
...
Widget build(BuildContext context) {
return Stack(children:[
...
if(!_loaded)
Center(
child: ElevatedButton(
child: const Text("Load"),
onPressed: () async {
var viewer = await _thermionViewer;
await viewer.loadIbl("assets/default_env_ibl.ktx");
await viewer.loadSkybox("assets/default_env_skybox.ktx");
await viewer.loadGlb("assets/cube.glb");
await viewer.setCameraPosition(0, 1, 10);
await viewer.setCameraRotation(v.Quaternion.axisAngle(
v.Vector3(1, 0, 0), -30 / 180 * pi) *
v.Quaternion.axisAngle(v.Vector3(0, 1, 0), 15 / 180 * pi));
await viewer.addLight(
LightType.SUN, 7500, 50000, 0, 0, 0, 1, -1, -1);
await viewer.setRendering(true);
_loaded = true;
setState(() {});
}
)
)
]);
}
}
```
Here, we've added a skybox (the background (cube) image rendered behind all other elements in the scene), image-based lighting (where an image is used to determine the direction and intensity of a light source) and a directional light (Sun).
Anything added to the scene is referred to as an "entity" (including lights and cameras).
Entities are always added to the scene at position (0,0,0).
The default scene camera is located at (0,0,0) (and is looking at -Z, or "into" the screen), so by adding a cube at (0,0,0), the camera will now be inside the cube.
We need to move the camera outside the cube so it's visible.
6. Change the camera orientation
```dart
var viewer = await _thermionViewer;
await viewer.loadSkybox("assets/default_env_skybox.ktx");
await viewer.loadGlb("assets/cube.glb");
await viewer.setCameraPosition(0, 1, 10);
await viewer.setCameraRotation(v.Quaternion.axisAngle(
v.Vector3(1, 0, 0), -30 / 180 * pi) *
v.Quaternion.axisAngle(v.Vector3(0, 1, 0), 15 / 180 * pi));
```
The cube still won't be visible until we add a light to the scene and tell Thermion to start rendering.
7. Add a light and turn rendering on
```dart
...
await viewer.addLight(
LightType.SUN, 7500, 50000, 0, 0, 0, 1, -1, -1);
await viewer.setRendering(true);
...
````
8. Run the project
```
$ flutter run -d macos
```
> You may experience a noticeable delay the very first time you run the project. Don't panic, it's not frozen! This is due to the build system downloading the prebuilt Filament binaries from Cloudflare, which can take some time (particularly on Windows). These binaries will be cached after first download, so subsequent runs will be much faster (though every time you run flutter clean, the binaries will be re-downloaded).
![Screenshot of Thermion Quickstart project](images/thermion_sample_project.png)
Your first Thermion project is complete!

View File

@@ -1,25 +1,18 @@
## 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).
[![Screenshot of Thermion Dartpad](images/dartpad.thermion.dev_.png)](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.
[![Screenshot of the mixreeel app](images/ixlabs.app_app.png)](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)).
@@ -28,4 +21,3 @@ My personal website, where I create an interactive clone of myself with Avaturn

View File

@@ -1,186 +0,0 @@
## ThermionViewer (Flutter)
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).
If you need want more fine-grained control
> 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. Add a folder containing your assets (glTF model + skybox ktx) to your `pubspec.yaml` asset list
```yaml
...
flutter
assets:
- assets/
```
3. Create an instance of `ThermionFlutterPlugin` in your app.
```dart
class _MyAppState extends State<MyApp> {
late Future<ThermionViewer> _thermionViewer;
  void initState() {   
ThermionFlutterPlugin.createViewer().then((viewer) {
_thermionViewer = viewer;
});
}
}
```
4. Add a `ThermionWidget` to your widget hierarchy
```dart
class _MyAppState extends State<MyApp> {
ThermionViewer? _thermionViewer;
void initState() {   
_thermionFlutterPlugin.createViewer().then((viewer) {
setState(() {
_thermionViewer = viewer;
});
});
}   
Widget build(BuildContext context) {
return Stack(children:[
if(_thermionViewer != null)
    Positioned.fill(
child:ThermionWidget(
plugin:_thermionViewer!
        ) 
    )
    ]); 
}
}
```
4. Add a button to load the model when pressed
```dart
...
class _MyAppState extends State<MyApp> {
...
bool _loaded = false;
Widget build(BuildContext context) {
return Stack(children:[
    if(_thermionViewer != null)
    Positioned.fill(
child:ThermionWidget(
plugin:_thermionViewer!
        ) 
    ),
if (!_loaded)
Center(
child: ElevatedButton(
child: const Text("Load"),
onPressed: () async {
// TODO
_loaded = true;
setState(() {});
}))
    ]); 
}}
```
5. When the button is pressed, load a skybox, lighting and the glb asset
You will need to import the `dart:math` and `package:vector_math` libraries.
```dart
import 'package:vector_math/vector_math_64.dart' as v;
import 'dart:math';
...
class _MyAppState extends State<MyApp> {
...
Widget build(BuildContext context) {
return Stack(children:[
...
if(!_loaded)
Center(
child: ElevatedButton(
child: const Text("Load"),
onPressed: () async {
var viewer = await _thermionViewer;
await viewer.loadIbl("assets/default_env_ibl.ktx");
await viewer.loadSkybox("assets/default_env_skybox.ktx");
await viewer.loadGlb("assets/cube.glb");
await viewer.setCameraPosition(0, 1, 10);
await viewer.setCameraRotation(v.Quaternion.axisAngle(
v.Vector3(1, 0, 0), -30 / 180 * pi) *
v.Quaternion.axisAngle(v.Vector3(0, 1, 0), 15 / 180 * pi));
await viewer.addLight(
LightType.SUN, 7500, 50000, 0, 0, 0, 1, -1, -1);
await viewer.setRendering(true);
_loaded = true;
setState(() {});
}
)
)
]);
}
}
```
Here, we've added a skybox (the background (cube) image rendered behind all other elements in the scene), image-based lighting (where an image is used to determine the direction and intensity of a light source) and a directional light (Sun).
Anything added to the scene is referred to as an "entity" (including lights and cameras).
Entities are always added to the scene at position (0,0,0).
The default scene camera is located at (0,0,0) (and is looking at -Z, or "into" the screen), so by adding a cube at (0,0,0), the camera will now be inside the cube.
We need to move the camera outside the cube so it's visible.
6. Change the camera orientation
```dart
var viewer = await _thermionViewer;
await viewer.loadSkybox("assets/default_env_skybox.ktx");
await viewer.loadGlb("assets/cube.glb");
await viewer.setCameraPosition(0, 1, 10);
await viewer.setCameraRotation(v.Quaternion.axisAngle(
v.Vector3(1, 0, 0), -30 / 180 * pi) *
v.Quaternion.axisAngle(v.Vector3(0, 1, 0), 15 / 180 * pi));
```
The cube still won't be visible until we add a light to the scene and tell Thermion to start rendering.
7. Add a light and turn rendering on
```dart
...
await viewer.addLight(
LightType.SUN, 7500, 50000, 0, 0, 0, 1, -1, -1);
await viewer.setRendering(true);
...
````
8. Run the project
```
$ flutter run -d macos
```
> You may experience a noticeable delay the very first time you run the project. Don't panic, it's not frozen! This is due to the build system downloading the prebuilt Filament binaries from Cloudflare, which can take some time (particularly on Windows). These binaries will be cached after first download, so subsequent runs will be much faster (though every time you run flutter clean, the binaries will be re-downloaded).
![Screenshot of Thermion Quickstart project](images/thermion_sample_project.png)
Your first Thermion project is complete!

View File

@@ -1,42 +0,0 @@
## Web
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
```
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
Copy thermion_dart.js and thermion_dart.wasm to the `/web` folder for your target app.
```
flutter run -d chrome --web-header Cross-Origin-Embedder-Policy=require-corp --web-header Cross-Origin-Opener-Policy=same-origin
```

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,121 +0,0 @@
{
"asset":{
"generator":"Khronos glTF Blender I/O v4.2.60",
"version":"2.0"
},
"scene":0,
"scenes":[
{
"name":"Scene",
"nodes":[
0
]
}
],
"nodes":[
{
"mesh":0,
"name":"Cube"
}
],
"materials":[
{
"doubleSided":true,
"name":"Material",
"pbrMetallicRoughness":{
"baseColorFactor":[
0.800000011920929,
0.800000011920929,
0.800000011920929,
1
],
"metallicFactor":0,
"roughnessFactor":0.5
}
}
],
"meshes":[
{
"name":"Cube",
"primitives":[
{
"attributes":{
"POSITION":0,
"NORMAL":1,
"TEXCOORD_0":2
},
"indices":3,
"material":0
}
]
}
],
"accessors":[
{
"bufferView":0,
"componentType":5126,
"count":24,
"max":[
1,
1,
1
],
"min":[
-1,
-1,
-1
],
"type":"VEC3"
},
{
"bufferView":1,
"componentType":5126,
"count":24,
"type":"VEC3"
},
{
"bufferView":2,
"componentType":5126,
"count":24,
"type":"VEC2"
},
{
"bufferView":3,
"componentType":5123,
"count":36,
"type":"SCALAR"
}
],
"bufferViews":[
{
"buffer":0,
"byteLength":288,
"byteOffset":0,
"target":34962
},
{
"buffer":0,
"byteLength":288,
"byteOffset":288,
"target":34962
},
{
"buffer":0,
"byteLength":192,
"byteOffset":576,
"target":34962
},
{
"buffer":0,
"byteLength":72,
"byteOffset":768,
"target":34963
}
],
"buffers":[
{
"byteLength":840,
"uri":"cube.bin"
}
]
}

View File

@@ -1,183 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="200"
height="200"
viewBox="0 0 1 1"
version="1.1"
id="svg10"
sodipodi:docname="cube_texture2.svg"
inkscape:export-filename="cube_texture_512x512.png"
inkscape:export-xdpi="245.75999"
inkscape:export-ydpi="245.75999"
inkscape:version="1.4 (e7c3feb1, 2024-10-09)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs10" />
<sodipodi:namedview
id="namedview10"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="1.5185118"
inkscape:cx="255.18405"
inkscape:cy="172.86662"
inkscape:window-width="1920"
inkscape:window-height="964"
inkscape:window-x="0"
inkscape:window-y="25"
inkscape:window-maximized="1"
inkscape:current-layer="svg10"
showgrid="false" />
<!-- Background Grid (optional, for visual aid) -->
<rect
x="0"
y="0"
width="1"
height="1"
fill="#f0f0f0"
id="rect1" />
<line
x1="0.333"
y1="0"
x2="0.333"
y2="1"
stroke="#ccc"
stroke-width="0.005"
id="line1" />
<line
x1="0.666"
y1="0"
x2="0.666"
y2="1"
stroke="#ccc"
stroke-width="0.005"
id="line2" />
<line
y1="0.25"
x1="0"
y2="0.25"
x2="1"
stroke="#ccc"
stroke-width="0.005"
id="line3" />
<line
y1="0.5"
x1="0"
y2="0.5"
x2="1"
stroke="#ccc"
stroke-width="0.005"
id="line4" />
<line
y1="0.75"
x1="0"
y2="0.75"
x2="1"
stroke="#ccc"
stroke-width="0.005"
id="line5" />
<!-- Front Face -->
<rect
x="0.333"
y="0"
width="0.333"
height="0.25"
fill="#ff0000"
id="rect5" />
<text
x="0.5"
y="0.125"
text-anchor="middle"
dominant-baseline="middle"
font-size="0.1"
fill="white"
id="text5">Front</text>
<!-- Back Face -->
<rect
x="0.333"
y="0.5"
width="0.333"
height="0.25"
fill="#00ff00"
id="rect6" />
<text
x="0.5"
y="0.625"
text-anchor="middle"
dominant-baseline="middle"
font-size="0.1"
fill="white"
id="text6">Back</text>
<!-- Top Face -->
<rect
x="0.666"
y="0.25"
width="0.333"
height="0.25"
fill="#0000ff"
id="rect7" />
<text
x="0.833"
y="0.375"
text-anchor="middle"
dominant-baseline="middle"
font-size="0.1"
fill="white"
id="text7">Top</text>
<!-- Bottom Face -->
<rect
x="0"
y="0.25"
width="0.333"
height="0.25"
fill="#ffff00"
id="rect8" />
<text
x="0.15610458"
y="0.37936932"
text-anchor="middle"
dominant-baseline="middle"
font-size="0.0733811px"
fill="#000000"
id="text8"
style="stroke-width:0.733811">Bottom</text>
<!-- Right Face -->
<rect
x="0.333"
y="0.25"
width="0.333"
height="0.25"
fill="#ff00ff"
id="rect9" />
<text
x="0.5"
y="0.375"
text-anchor="middle"
dominant-baseline="middle"
font-size="0.1"
fill="white"
id="text9">Right</text>
<!-- Left Face -->
<rect
x="0.333"
y="0.75"
width="0.333"
height="0.25"
fill="#00ffff"
id="rect10" />
<text
x="0.5"
y="0.875"
text-anchor="middle"
dominant-baseline="middle"
font-size="0.1"
fill="black"
id="text10">Left</text>
</svg>

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 960 KiB

View File

@@ -1 +0,0 @@
{"asset":{"version":"2.0","generator":"babylon.js glTF exporter for 3dsmax 2021 v20210607.3"},"scene":0,"scenes":[{"nodes":[0]}],"nodes":[{"mesh":0,"translation":[0.0,-1.14751673,-5.015955E-08],"name":"Cylinder001"}],"meshes":[{"primitives":[{"attributes":{"POSITION":1,"NORMAL":2,"TEXCOORD_0":3},"indices":0,"material":0},{"attributes":{"POSITION":5,"NORMAL":6,"TEXCOORD_0":7},"indices":4,"material":1},{"attributes":{"POSITION":9,"NORMAL":10,"TEXCOORD_0":11},"indices":8,"material":2},{"attributes":{"POSITION":13,"NORMAL":14,"TEXCOORD_0":15},"indices":12,"material":3},{"attributes":{"POSITION":17,"NORMAL":18,"TEXCOORD_0":19},"indices":16,"material":4}],"name":"Cylinder001"}],"accessors":[{"bufferView":0,"componentType":5123,"count":858,"type":"SCALAR","name":"accessorIndices"},{"bufferView":1,"componentType":5126,"count":858,"max":[0.9673312,-0.0665806457,0.9673312],"min":[-0.9673312,-0.09678768,-0.9673312],"type":"VEC3","name":"accessorPositions"},{"bufferView":1,"byteOffset":10296,"componentType":5126,"count":858,"type":"VEC3","name":"accessorNormals"},{"bufferView":2,"componentType":5126,"count":858,"type":"VEC2","name":"accessorUVs"},{"bufferView":0,"byteOffset":1716,"componentType":5123,"count":14592,"type":"SCALAR","name":"accessorIndices"},{"bufferView":1,"byteOffset":20592,"componentType":5126,"count":14592,"max":[1.01214123,2.33892131,1.02725148],"min":[-1.01214123,-0.09678768,-1.01214123],"type":"VEC3","name":"accessorPositions"},{"bufferView":1,"byteOffset":195696,"componentType":5126,"count":14592,"type":"VEC3","name":"accessorNormals"},{"bufferView":2,"byteOffset":6864,"componentType":5126,"count":14592,"type":"VEC2","name":"accessorUVs"},{"bufferView":0,"byteOffset":30900,"componentType":5123,"count":1620,"type":"SCALAR","name":"accessorIndices"},{"bufferView":1,"byteOffset":370800,"componentType":5126,"count":1620,"max":[1.006612,2.3633275,1.006612],"min":[-1.006612,2.338921,-1.006612],"type":"VEC3","name":"accessorPositions"},{"bufferView":1,"byteOffset":390240,"componentType":5126,"count":1620,"type":"VEC3","name":"accessorNormals"},{"bufferView":2,"byteOffset":123600,"componentType":5126,"count":1620,"type":"VEC2","name":"accessorUVs"},{"bufferView":0,"byteOffset":34140,"componentType":5123,"count":318,"type":"SCALAR","name":"accessorIndices"},{"bufferView":1,"byteOffset":409680,"componentType":5126,"count":318,"max":[0.9454922,2.3548696,0.9454922],"min":[-0.9454921,0.0617354736,-0.945492268],"type":"VEC3","name":"accessorPositions"},{"bufferView":1,"byteOffset":413496,"componentType":5126,"count":318,"type":"VEC3","name":"accessorNormals"},{"bufferView":2,"byteOffset":136560,"componentType":5126,"count":318,"type":"VEC2","name":"accessorUVs"},{"bufferView":0,"byteOffset":34776,"componentType":5123,"count":11520,"type":"SCALAR","name":"accessorIndices"},{"bufferView":1,"byteOffset":417312,"componentType":5126,"count":11520,"max":[0.196413681,2.12139344,1.90955186],"min":[-0.196414649,0.165008187,1.00927675],"type":"VEC3","name":"accessorPositions"},{"bufferView":1,"byteOffset":555552,"componentType":5126,"count":11520,"type":"VEC3","name":"accessorNormals"},{"bufferView":2,"byteOffset":139104,"componentType":5126,"count":11520,"type":"VEC2","name":"accessorUVs"}],"bufferViews":[{"buffer":0,"byteLength":57816,"name":"bufferViewScalar"},{"buffer":0,"byteOffset":57816,"byteLength":693792,"byteStride":12,"name":"bufferViewFloatVec3"},{"buffer":0,"byteOffset":751608,"byteLength":231264,"byteStride":8,"name":"bufferViewFloatVec2"}],"buffers":[{"uri":"model.bin","byteLength":982872}],"materials":[{"pbrMetallicRoughness":{"metallicFactor":0.0,"roughnessFactor":0.9},"doubleSided":true,"name":"01 - Default"},{"pbrMetallicRoughness":{"baseColorTexture":{"index":0},"metallicFactor":0.0,"roughnessFactor":0.9},"doubleSided":true,"name":"02 - Default"},{"pbrMetallicRoughness":{"baseColorFactor":[0.0,1.0,0.117647067,1.0],"metallicFactor":0.0,"roughnessFactor":0.9},"doubleSided":true,"name":"03 - Default"},{"pbrMetallicRoughness":{"baseColorFactor":[0.2784314,0.0,0.9921569,1.0],"metallicFactor":0.0,"roughnessFactor":0.9},"doubleSided":true,"name":"04 - Default"},{"pbrMetallicRoughness":{"baseColorFactor":[0.9725491,0.776470661,0.0,1.0],"metallicFactor":0.0,"roughnessFactor":0.9},"doubleSided":true,"name":"05 - Default"}],"textures":[{"sampler":0,"source":0,"name":"texture.jpg"}],"images":[{"uri":"./texture.jpg"}],"samplers":[{"magFilter":9729,"minFilter":9987}]}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 720 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 312 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 MiB

View File

@@ -1,270 +0,0 @@
7767517
268 473
Input input.1 0 1 data
Convolution Conv_0 1 1 data 193 0=64 1=3 4=1 5=1 6=1728
Split splitncnn_0 1 8 193 193_splitncnn_0 193_splitncnn_1 193_splitncnn_2 193_splitncnn_3 193_splitncnn_4 193_splitncnn_5 193_splitncnn_6 193_splitncnn_7
Convolution Conv_1 1 1 193_splitncnn_7 195 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
Split splitncnn_1 1 4 195 195_splitncnn_0 195_splitncnn_1 195_splitncnn_2 195_splitncnn_3
Concat Concat_3 2 1 193_splitncnn_6 195_splitncnn_3 196
Convolution Conv_4 1 1 196 198 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
Split splitncnn_2 1 3 198 198_splitncnn_0 198_splitncnn_1 198_splitncnn_2
Concat Concat_6 3 1 193_splitncnn_5 195_splitncnn_2 198_splitncnn_2 199
Convolution Conv_7 1 1 199 201 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
Split splitncnn_3 1 2 201 201_splitncnn_0 201_splitncnn_1
Concat Concat_9 4 1 193_splitncnn_4 195_splitncnn_1 198_splitncnn_1 201_splitncnn_1 202
Convolution Conv_10 1 1 202 204 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
Concat Concat_12 5 1 193_splitncnn_3 195_splitncnn_0 198_splitncnn_0 201_splitncnn_0 204 205
Convolution Conv_13 1 1 205 206 0=64 1=3 4=1 5=1 6=110592
Eltwise Add_16 2 1 206 193_splitncnn_2 209 0=1 -23301=2,2.000000e-01,1.000000e+00
Split splitncnn_4 1 6 209 209_splitncnn_0 209_splitncnn_1 209_splitncnn_2 209_splitncnn_3 209_splitncnn_4 209_splitncnn_5
Convolution Conv_17 1 1 209_splitncnn_5 211 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
Split splitncnn_5 1 4 211 211_splitncnn_0 211_splitncnn_1 211_splitncnn_2 211_splitncnn_3
Concat Concat_19 2 1 209_splitncnn_4 211_splitncnn_3 212
Convolution Conv_20 1 1 212 214 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
Split splitncnn_6 1 3 214 214_splitncnn_0 214_splitncnn_1 214_splitncnn_2
Concat Concat_22 3 1 209_splitncnn_3 211_splitncnn_2 214_splitncnn_2 215
Convolution Conv_23 1 1 215 217 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
Split splitncnn_7 1 2 217 217_splitncnn_0 217_splitncnn_1
Concat Concat_25 4 1 209_splitncnn_2 211_splitncnn_1 214_splitncnn_1 217_splitncnn_1 218
Convolution Conv_26 1 1 218 220 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
Concat Concat_28 5 1 209_splitncnn_1 211_splitncnn_0 214_splitncnn_0 217_splitncnn_0 220 221
Convolution Conv_29 1 1 221 222 0=64 1=3 4=1 5=1 6=110592
Eltwise Add_32 2 1 222 209_splitncnn_0 225 0=1 -23301=2,2.000000e-01,1.000000e+00
Split splitncnn_8 1 6 225 225_splitncnn_0 225_splitncnn_1 225_splitncnn_2 225_splitncnn_3 225_splitncnn_4 225_splitncnn_5
Convolution Conv_33 1 1 225_splitncnn_5 227 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
Split splitncnn_9 1 4 227 227_splitncnn_0 227_splitncnn_1 227_splitncnn_2 227_splitncnn_3
Concat Concat_35 2 1 225_splitncnn_4 227_splitncnn_3 228
Convolution Conv_36 1 1 228 230 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
Split splitncnn_10 1 3 230 230_splitncnn_0 230_splitncnn_1 230_splitncnn_2
Concat Concat_38 3 1 225_splitncnn_3 227_splitncnn_2 230_splitncnn_2 231
Convolution Conv_39 1 1 231 233 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
Split splitncnn_11 1 2 233 233_splitncnn_0 233_splitncnn_1
Concat Concat_41 4 1 225_splitncnn_2 227_splitncnn_1 230_splitncnn_1 233_splitncnn_1 234
Convolution Conv_42 1 1 234 236 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
Concat Concat_44 5 1 225_splitncnn_1 227_splitncnn_0 230_splitncnn_0 233_splitncnn_0 236 237
Convolution Conv_45 1 1 237 238 0=64 1=3 4=1 5=1 6=110592
Eltwise Add_48 2 1 238 225_splitncnn_0 241 0=1 -23301=2,2.000000e-01,1.000000e+00
Eltwise Add_51 2 1 241 193_splitncnn_1 244 0=1 -23301=2,2.000000e-01,1.000000e+00
Split splitncnn_12 1 7 244 244_splitncnn_0 244_splitncnn_1 244_splitncnn_2 244_splitncnn_3 244_splitncnn_4 244_splitncnn_5 244_splitncnn_6
Convolution Conv_52 1 1 244_splitncnn_6 246 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
Split splitncnn_13 1 4 246 246_splitncnn_0 246_splitncnn_1 246_splitncnn_2 246_splitncnn_3
Concat Concat_54 2 1 244_splitncnn_5 246_splitncnn_3 247
Convolution Conv_55 1 1 247 249 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
Split splitncnn_14 1 3 249 249_splitncnn_0 249_splitncnn_1 249_splitncnn_2
Concat Concat_57 3 1 244_splitncnn_4 246_splitncnn_2 249_splitncnn_2 250
Convolution Conv_58 1 1 250 252 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
Split splitncnn_15 1 2 252 252_splitncnn_0 252_splitncnn_1
Concat Concat_60 4 1 244_splitncnn_3 246_splitncnn_1 249_splitncnn_1 252_splitncnn_1 253
Convolution Conv_61 1 1 253 255 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
Concat Concat_63 5 1 244_splitncnn_2 246_splitncnn_0 249_splitncnn_0 252_splitncnn_0 255 256
Convolution Conv_64 1 1 256 257 0=64 1=3 4=1 5=1 6=110592
Eltwise Add_67 2 1 257 244_splitncnn_1 260 0=1 -23301=2,2.000000e-01,1.000000e+00
Split splitncnn_16 1 6 260 260_splitncnn_0 260_splitncnn_1 260_splitncnn_2 260_splitncnn_3 260_splitncnn_4 260_splitncnn_5
Convolution Conv_68 1 1 260_splitncnn_5 262 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
Split splitncnn_17 1 4 262 262_splitncnn_0 262_splitncnn_1 262_splitncnn_2 262_splitncnn_3
Concat Concat_70 2 1 260_splitncnn_4 262_splitncnn_3 263
Convolution Conv_71 1 1 263 265 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
Split splitncnn_18 1 3 265 265_splitncnn_0 265_splitncnn_1 265_splitncnn_2
Concat Concat_73 3 1 260_splitncnn_3 262_splitncnn_2 265_splitncnn_2 266
Convolution Conv_74 1 1 266 268 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
Split splitncnn_19 1 2 268 268_splitncnn_0 268_splitncnn_1
Concat Concat_76 4 1 260_splitncnn_2 262_splitncnn_1 265_splitncnn_1 268_splitncnn_1 269
Convolution Conv_77 1 1 269 271 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
Concat Concat_79 5 1 260_splitncnn_1 262_splitncnn_0 265_splitncnn_0 268_splitncnn_0 271 272
Convolution Conv_80 1 1 272 273 0=64 1=3 4=1 5=1 6=110592
Eltwise Add_83 2 1 273 260_splitncnn_0 276 0=1 -23301=2,2.000000e-01,1.000000e+00
Split splitncnn_20 1 6 276 276_splitncnn_0 276_splitncnn_1 276_splitncnn_2 276_splitncnn_3 276_splitncnn_4 276_splitncnn_5
Convolution Conv_84 1 1 276_splitncnn_5 278 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
Split splitncnn_21 1 4 278 278_splitncnn_0 278_splitncnn_1 278_splitncnn_2 278_splitncnn_3
Concat Concat_86 2 1 276_splitncnn_4 278_splitncnn_3 279
Convolution Conv_87 1 1 279 281 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
Split splitncnn_22 1 3 281 281_splitncnn_0 281_splitncnn_1 281_splitncnn_2
Concat Concat_89 3 1 276_splitncnn_3 278_splitncnn_2 281_splitncnn_2 282
Convolution Conv_90 1 1 282 284 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
Split splitncnn_23 1 2 284 284_splitncnn_0 284_splitncnn_1
Concat Concat_92 4 1 276_splitncnn_2 278_splitncnn_1 281_splitncnn_1 284_splitncnn_1 285
Convolution Conv_93 1 1 285 287 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
Concat Concat_95 5 1 276_splitncnn_1 278_splitncnn_0 281_splitncnn_0 284_splitncnn_0 287 288
Convolution Conv_96 1 1 288 289 0=64 1=3 4=1 5=1 6=110592
Eltwise Add_99 2 1 289 276_splitncnn_0 292 0=1 -23301=2,2.000000e-01,1.000000e+00
Eltwise Add_102 2 1 292 244_splitncnn_0 295 0=1 -23301=2,2.000000e-01,1.000000e+00
Split splitncnn_24 1 7 295 295_splitncnn_0 295_splitncnn_1 295_splitncnn_2 295_splitncnn_3 295_splitncnn_4 295_splitncnn_5 295_splitncnn_6
Convolution Conv_103 1 1 295_splitncnn_6 297 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
Split splitncnn_25 1 4 297 297_splitncnn_0 297_splitncnn_1 297_splitncnn_2 297_splitncnn_3
Concat Concat_105 2 1 295_splitncnn_5 297_splitncnn_3 298
Convolution Conv_106 1 1 298 300 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
Split splitncnn_26 1 3 300 300_splitncnn_0 300_splitncnn_1 300_splitncnn_2
Concat Concat_108 3 1 295_splitncnn_4 297_splitncnn_2 300_splitncnn_2 301
Convolution Conv_109 1 1 301 303 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
Split splitncnn_27 1 2 303 303_splitncnn_0 303_splitncnn_1
Concat Concat_111 4 1 295_splitncnn_3 297_splitncnn_1 300_splitncnn_1 303_splitncnn_1 304
Convolution Conv_112 1 1 304 306 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
Concat Concat_114 5 1 295_splitncnn_2 297_splitncnn_0 300_splitncnn_0 303_splitncnn_0 306 307
Convolution Conv_115 1 1 307 308 0=64 1=3 4=1 5=1 6=110592
Eltwise Add_118 2 1 308 295_splitncnn_1 311 0=1 -23301=2,2.000000e-01,1.000000e+00
Split splitncnn_28 1 6 311 311_splitncnn_0 311_splitncnn_1 311_splitncnn_2 311_splitncnn_3 311_splitncnn_4 311_splitncnn_5
Convolution Conv_119 1 1 311_splitncnn_5 313 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
Split splitncnn_29 1 4 313 313_splitncnn_0 313_splitncnn_1 313_splitncnn_2 313_splitncnn_3
Concat Concat_121 2 1 311_splitncnn_4 313_splitncnn_3 314
Convolution Conv_122 1 1 314 316 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
Split splitncnn_30 1 3 316 316_splitncnn_0 316_splitncnn_1 316_splitncnn_2
Concat Concat_124 3 1 311_splitncnn_3 313_splitncnn_2 316_splitncnn_2 317
Convolution Conv_125 1 1 317 319 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
Split splitncnn_31 1 2 319 319_splitncnn_0 319_splitncnn_1
Concat Concat_127 4 1 311_splitncnn_2 313_splitncnn_1 316_splitncnn_1 319_splitncnn_1 320
Convolution Conv_128 1 1 320 322 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
Concat Concat_130 5 1 311_splitncnn_1 313_splitncnn_0 316_splitncnn_0 319_splitncnn_0 322 323
Convolution Conv_131 1 1 323 324 0=64 1=3 4=1 5=1 6=110592
Eltwise Add_134 2 1 324 311_splitncnn_0 327 0=1 -23301=2,2.000000e-01,1.000000e+00
Split splitncnn_32 1 6 327 327_splitncnn_0 327_splitncnn_1 327_splitncnn_2 327_splitncnn_3 327_splitncnn_4 327_splitncnn_5
Convolution Conv_135 1 1 327_splitncnn_5 329 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
Split splitncnn_33 1 4 329 329_splitncnn_0 329_splitncnn_1 329_splitncnn_2 329_splitncnn_3
Concat Concat_137 2 1 327_splitncnn_4 329_splitncnn_3 330
Convolution Conv_138 1 1 330 332 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
Split splitncnn_34 1 3 332 332_splitncnn_0 332_splitncnn_1 332_splitncnn_2
Concat Concat_140 3 1 327_splitncnn_3 329_splitncnn_2 332_splitncnn_2 333
Convolution Conv_141 1 1 333 335 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
Split splitncnn_35 1 2 335 335_splitncnn_0 335_splitncnn_1
Concat Concat_143 4 1 327_splitncnn_2 329_splitncnn_1 332_splitncnn_1 335_splitncnn_1 336
Convolution Conv_144 1 1 336 338 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
Concat Concat_146 5 1 327_splitncnn_1 329_splitncnn_0 332_splitncnn_0 335_splitncnn_0 338 339
Convolution Conv_147 1 1 339 340 0=64 1=3 4=1 5=1 6=110592
Eltwise Add_150 2 1 340 327_splitncnn_0 343 0=1 -23301=2,2.000000e-01,1.000000e+00
Eltwise Add_153 2 1 343 295_splitncnn_0 346 0=1 -23301=2,2.000000e-01,1.000000e+00
Split splitncnn_36 1 7 346 346_splitncnn_0 346_splitncnn_1 346_splitncnn_2 346_splitncnn_3 346_splitncnn_4 346_splitncnn_5 346_splitncnn_6
Convolution Conv_154 1 1 346_splitncnn_6 348 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
Split splitncnn_37 1 4 348 348_splitncnn_0 348_splitncnn_1 348_splitncnn_2 348_splitncnn_3
Concat Concat_156 2 1 346_splitncnn_5 348_splitncnn_3 349
Convolution Conv_157 1 1 349 351 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
Split splitncnn_38 1 3 351 351_splitncnn_0 351_splitncnn_1 351_splitncnn_2
Concat Concat_159 3 1 346_splitncnn_4 348_splitncnn_2 351_splitncnn_2 352
Convolution Conv_160 1 1 352 354 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
Split splitncnn_39 1 2 354 354_splitncnn_0 354_splitncnn_1
Concat Concat_162 4 1 346_splitncnn_3 348_splitncnn_1 351_splitncnn_1 354_splitncnn_1 355
Convolution Conv_163 1 1 355 357 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
Concat Concat_165 5 1 346_splitncnn_2 348_splitncnn_0 351_splitncnn_0 354_splitncnn_0 357 358
Convolution Conv_166 1 1 358 359 0=64 1=3 4=1 5=1 6=110592
Eltwise Add_169 2 1 359 346_splitncnn_1 362 0=1 -23301=2,2.000000e-01,1.000000e+00
Split splitncnn_40 1 6 362 362_splitncnn_0 362_splitncnn_1 362_splitncnn_2 362_splitncnn_3 362_splitncnn_4 362_splitncnn_5
Convolution Conv_170 1 1 362_splitncnn_5 364 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
Split splitncnn_41 1 4 364 364_splitncnn_0 364_splitncnn_1 364_splitncnn_2 364_splitncnn_3
Concat Concat_172 2 1 362_splitncnn_4 364_splitncnn_3 365
Convolution Conv_173 1 1 365 367 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
Split splitncnn_42 1 3 367 367_splitncnn_0 367_splitncnn_1 367_splitncnn_2
Concat Concat_175 3 1 362_splitncnn_3 364_splitncnn_2 367_splitncnn_2 368
Convolution Conv_176 1 1 368 370 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
Split splitncnn_43 1 2 370 370_splitncnn_0 370_splitncnn_1
Concat Concat_178 4 1 362_splitncnn_2 364_splitncnn_1 367_splitncnn_1 370_splitncnn_1 371
Convolution Conv_179 1 1 371 373 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
Concat Concat_181 5 1 362_splitncnn_1 364_splitncnn_0 367_splitncnn_0 370_splitncnn_0 373 374
Convolution Conv_182 1 1 374 375 0=64 1=3 4=1 5=1 6=110592
Eltwise Add_185 2 1 375 362_splitncnn_0 378 0=1 -23301=2,2.000000e-01,1.000000e+00
Split splitncnn_44 1 6 378 378_splitncnn_0 378_splitncnn_1 378_splitncnn_2 378_splitncnn_3 378_splitncnn_4 378_splitncnn_5
Convolution Conv_186 1 1 378_splitncnn_5 380 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
Split splitncnn_45 1 4 380 380_splitncnn_0 380_splitncnn_1 380_splitncnn_2 380_splitncnn_3
Concat Concat_188 2 1 378_splitncnn_4 380_splitncnn_3 381
Convolution Conv_189 1 1 381 383 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
Split splitncnn_46 1 3 383 383_splitncnn_0 383_splitncnn_1 383_splitncnn_2
Concat Concat_191 3 1 378_splitncnn_3 380_splitncnn_2 383_splitncnn_2 384
Convolution Conv_192 1 1 384 386 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
Split splitncnn_47 1 2 386 386_splitncnn_0 386_splitncnn_1
Concat Concat_194 4 1 378_splitncnn_2 380_splitncnn_1 383_splitncnn_1 386_splitncnn_1 387
Convolution Conv_195 1 1 387 389 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
Concat Concat_197 5 1 378_splitncnn_1 380_splitncnn_0 383_splitncnn_0 386_splitncnn_0 389 390
Convolution Conv_198 1 1 390 391 0=64 1=3 4=1 5=1 6=110592
Eltwise Add_201 2 1 391 378_splitncnn_0 394 0=1 -23301=2,2.000000e-01,1.000000e+00
Eltwise Add_204 2 1 394 346_splitncnn_0 397 0=1 -23301=2,2.000000e-01,1.000000e+00
Split splitncnn_48 1 7 397 397_splitncnn_0 397_splitncnn_1 397_splitncnn_2 397_splitncnn_3 397_splitncnn_4 397_splitncnn_5 397_splitncnn_6
Convolution Conv_205 1 1 397_splitncnn_6 399 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
Split splitncnn_49 1 4 399 399_splitncnn_0 399_splitncnn_1 399_splitncnn_2 399_splitncnn_3
Concat Concat_207 2 1 397_splitncnn_5 399_splitncnn_3 400
Convolution Conv_208 1 1 400 402 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
Split splitncnn_50 1 3 402 402_splitncnn_0 402_splitncnn_1 402_splitncnn_2
Concat Concat_210 3 1 397_splitncnn_4 399_splitncnn_2 402_splitncnn_2 403
Convolution Conv_211 1 1 403 405 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
Split splitncnn_51 1 2 405 405_splitncnn_0 405_splitncnn_1
Concat Concat_213 4 1 397_splitncnn_3 399_splitncnn_1 402_splitncnn_1 405_splitncnn_1 406
Convolution Conv_214 1 1 406 408 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
Concat Concat_216 5 1 397_splitncnn_2 399_splitncnn_0 402_splitncnn_0 405_splitncnn_0 408 409
Convolution Conv_217 1 1 409 410 0=64 1=3 4=1 5=1 6=110592
Eltwise Add_220 2 1 410 397_splitncnn_1 413 0=1 -23301=2,2.000000e-01,1.000000e+00
Split splitncnn_52 1 6 413 413_splitncnn_0 413_splitncnn_1 413_splitncnn_2 413_splitncnn_3 413_splitncnn_4 413_splitncnn_5
Convolution Conv_221 1 1 413_splitncnn_5 415 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
Split splitncnn_53 1 4 415 415_splitncnn_0 415_splitncnn_1 415_splitncnn_2 415_splitncnn_3
Concat Concat_223 2 1 413_splitncnn_4 415_splitncnn_3 416
Convolution Conv_224 1 1 416 418 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
Split splitncnn_54 1 3 418 418_splitncnn_0 418_splitncnn_1 418_splitncnn_2
Concat Concat_226 3 1 413_splitncnn_3 415_splitncnn_2 418_splitncnn_2 419
Convolution Conv_227 1 1 419 421 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
Split splitncnn_55 1 2 421 421_splitncnn_0 421_splitncnn_1
Concat Concat_229 4 1 413_splitncnn_2 415_splitncnn_1 418_splitncnn_1 421_splitncnn_1 422
Convolution Conv_230 1 1 422 424 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
Concat Concat_232 5 1 413_splitncnn_1 415_splitncnn_0 418_splitncnn_0 421_splitncnn_0 424 425
Convolution Conv_233 1 1 425 426 0=64 1=3 4=1 5=1 6=110592
Eltwise Add_236 2 1 426 413_splitncnn_0 429 0=1 -23301=2,2.000000e-01,1.000000e+00
Split splitncnn_56 1 6 429 429_splitncnn_0 429_splitncnn_1 429_splitncnn_2 429_splitncnn_3 429_splitncnn_4 429_splitncnn_5
Convolution Conv_237 1 1 429_splitncnn_5 431 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
Split splitncnn_57 1 4 431 431_splitncnn_0 431_splitncnn_1 431_splitncnn_2 431_splitncnn_3
Concat Concat_239 2 1 429_splitncnn_4 431_splitncnn_3 432
Convolution Conv_240 1 1 432 434 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
Split splitncnn_58 1 3 434 434_splitncnn_0 434_splitncnn_1 434_splitncnn_2
Concat Concat_242 3 1 429_splitncnn_3 431_splitncnn_2 434_splitncnn_2 435
Convolution Conv_243 1 1 435 437 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
Split splitncnn_59 1 2 437 437_splitncnn_0 437_splitncnn_1
Concat Concat_245 4 1 429_splitncnn_2 431_splitncnn_1 434_splitncnn_1 437_splitncnn_1 438
Convolution Conv_246 1 1 438 440 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
Concat Concat_248 5 1 429_splitncnn_1 431_splitncnn_0 434_splitncnn_0 437_splitncnn_0 440 441
Convolution Conv_249 1 1 441 442 0=64 1=3 4=1 5=1 6=110592
Eltwise Add_252 2 1 442 429_splitncnn_0 445 0=1 -23301=2,2.000000e-01,1.000000e+00
Eltwise Add_255 2 1 445 397_splitncnn_0 448 0=1 -23301=2,2.000000e-01,1.000000e+00
Split splitncnn_60 1 7 448 448_splitncnn_0 448_splitncnn_1 448_splitncnn_2 448_splitncnn_3 448_splitncnn_4 448_splitncnn_5 448_splitncnn_6
Convolution Conv_256 1 1 448_splitncnn_6 450 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
Split splitncnn_61 1 4 450 450_splitncnn_0 450_splitncnn_1 450_splitncnn_2 450_splitncnn_3
Concat Concat_258 2 1 448_splitncnn_5 450_splitncnn_3 451
Convolution Conv_259 1 1 451 453 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
Split splitncnn_62 1 3 453 453_splitncnn_0 453_splitncnn_1 453_splitncnn_2
Concat Concat_261 3 1 448_splitncnn_4 450_splitncnn_2 453_splitncnn_2 454
Convolution Conv_262 1 1 454 456 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
Split splitncnn_63 1 2 456 456_splitncnn_0 456_splitncnn_1
Concat Concat_264 4 1 448_splitncnn_3 450_splitncnn_1 453_splitncnn_1 456_splitncnn_1 457
Convolution Conv_265 1 1 457 459 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
Concat Concat_267 5 1 448_splitncnn_2 450_splitncnn_0 453_splitncnn_0 456_splitncnn_0 459 460
Convolution Conv_268 1 1 460 461 0=64 1=3 4=1 5=1 6=110592
Eltwise Add_271 2 1 461 448_splitncnn_1 464 0=1 -23301=2,2.000000e-01,1.000000e+00
Split splitncnn_64 1 6 464 464_splitncnn_0 464_splitncnn_1 464_splitncnn_2 464_splitncnn_3 464_splitncnn_4 464_splitncnn_5
Convolution Conv_272 1 1 464_splitncnn_5 466 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
Split splitncnn_65 1 4 466 466_splitncnn_0 466_splitncnn_1 466_splitncnn_2 466_splitncnn_3
Concat Concat_274 2 1 464_splitncnn_4 466_splitncnn_3 467
Convolution Conv_275 1 1 467 469 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
Split splitncnn_66 1 3 469 469_splitncnn_0 469_splitncnn_1 469_splitncnn_2
Concat Concat_277 3 1 464_splitncnn_3 466_splitncnn_2 469_splitncnn_2 470
Convolution Conv_278 1 1 470 472 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
Split splitncnn_67 1 2 472 472_splitncnn_0 472_splitncnn_1
Concat Concat_280 4 1 464_splitncnn_2 466_splitncnn_1 469_splitncnn_1 472_splitncnn_1 473
Convolution Conv_281 1 1 473 475 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
Concat Concat_283 5 1 464_splitncnn_1 466_splitncnn_0 469_splitncnn_0 472_splitncnn_0 475 476
Convolution Conv_284 1 1 476 477 0=64 1=3 4=1 5=1 6=110592
Eltwise Add_287 2 1 477 464_splitncnn_0 480 0=1 -23301=2,2.000000e-01,1.000000e+00
Split splitncnn_68 1 6 480 480_splitncnn_0 480_splitncnn_1 480_splitncnn_2 480_splitncnn_3 480_splitncnn_4 480_splitncnn_5
Convolution Conv_288 1 1 480_splitncnn_5 482 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
Split splitncnn_69 1 4 482 482_splitncnn_0 482_splitncnn_1 482_splitncnn_2 482_splitncnn_3
Concat Concat_290 2 1 480_splitncnn_4 482_splitncnn_3 483
Convolution Conv_291 1 1 483 485 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
Split splitncnn_70 1 3 485 485_splitncnn_0 485_splitncnn_1 485_splitncnn_2
Concat Concat_293 3 1 480_splitncnn_3 482_splitncnn_2 485_splitncnn_2 486
Convolution Conv_294 1 1 486 488 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
Split splitncnn_71 1 2 488 488_splitncnn_0 488_splitncnn_1
Concat Concat_296 4 1 480_splitncnn_2 482_splitncnn_1 485_splitncnn_1 488_splitncnn_1 489
Convolution Conv_297 1 1 489 491 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
Concat Concat_299 5 1 480_splitncnn_1 482_splitncnn_0 485_splitncnn_0 488_splitncnn_0 491 492
Convolution Conv_300 1 1 492 493 0=64 1=3 4=1 5=1 6=110592
Eltwise Add_303 2 1 493 480_splitncnn_0 496 0=1 -23301=2,2.000000e-01,1.000000e+00
Eltwise Add_306 2 1 496 448_splitncnn_0 499 0=1 -23301=2,2.000000e-01,1.000000e+00
Convolution Conv_307 1 1 499 500 0=64 1=3 4=1 5=1 6=36864
BinaryOp Add_308 2 1 193_splitncnn_0 500 501
Interp Resize_310 1 1 501 506 0=1 1=2.000000e+00 2=2.000000e+00
Convolution Conv_311 1 1 506 508 0=64 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
Interp Resize_314 1 1 508 513 0=1 1=2.000000e+00 2=2.000000e+00
Convolution Conv_315 1 1 513 515 0=64 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
Convolution Conv_317 1 1 515 517 0=64 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
Convolution Conv_319 1 1 517 output 0=3 1=3 4=1 5=1 6=1728

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 960 KiB

View File

@@ -1 +0,0 @@
{"asset":{"version":"2.0","generator":"babylon.js glTF exporter for 3dsmax 2021 v20210607.3"},"scene":0,"scenes":[{"nodes":[0]}],"nodes":[{"mesh":0,"translation":[0.0,-1.14751673,-5.015955E-08],"name":"Cylinder001"}],"meshes":[{"primitives":[{"attributes":{"POSITION":1,"NORMAL":2,"TEXCOORD_0":3},"indices":0,"material":0},{"attributes":{"POSITION":5,"NORMAL":6,"TEXCOORD_0":7},"indices":4,"material":1},{"attributes":{"POSITION":9,"NORMAL":10,"TEXCOORD_0":11},"indices":8,"material":2},{"attributes":{"POSITION":13,"NORMAL":14,"TEXCOORD_0":15},"indices":12,"material":3},{"attributes":{"POSITION":17,"NORMAL":18,"TEXCOORD_0":19},"indices":16,"material":4}],"name":"Cylinder001"}],"accessors":[{"bufferView":0,"componentType":5123,"count":858,"type":"SCALAR","name":"accessorIndices"},{"bufferView":1,"componentType":5126,"count":858,"max":[0.9673312,-0.0665806457,0.9673312],"min":[-0.9673312,-0.09678768,-0.9673312],"type":"VEC3","name":"accessorPositions"},{"bufferView":1,"byteOffset":10296,"componentType":5126,"count":858,"type":"VEC3","name":"accessorNormals"},{"bufferView":2,"componentType":5126,"count":858,"type":"VEC2","name":"accessorUVs"},{"bufferView":0,"byteOffset":1716,"componentType":5123,"count":14592,"type":"SCALAR","name":"accessorIndices"},{"bufferView":1,"byteOffset":20592,"componentType":5126,"count":14592,"max":[1.01214123,2.33892131,1.02725148],"min":[-1.01214123,-0.09678768,-1.01214123],"type":"VEC3","name":"accessorPositions"},{"bufferView":1,"byteOffset":195696,"componentType":5126,"count":14592,"type":"VEC3","name":"accessorNormals"},{"bufferView":2,"byteOffset":6864,"componentType":5126,"count":14592,"type":"VEC2","name":"accessorUVs"},{"bufferView":0,"byteOffset":30900,"componentType":5123,"count":1620,"type":"SCALAR","name":"accessorIndices"},{"bufferView":1,"byteOffset":370800,"componentType":5126,"count":1620,"max":[1.006612,2.3633275,1.006612],"min":[-1.006612,2.338921,-1.006612],"type":"VEC3","name":"accessorPositions"},{"bufferView":1,"byteOffset":390240,"componentType":5126,"count":1620,"type":"VEC3","name":"accessorNormals"},{"bufferView":2,"byteOffset":123600,"componentType":5126,"count":1620,"type":"VEC2","name":"accessorUVs"},{"bufferView":0,"byteOffset":34140,"componentType":5123,"count":318,"type":"SCALAR","name":"accessorIndices"},{"bufferView":1,"byteOffset":409680,"componentType":5126,"count":318,"max":[0.9454922,2.3548696,0.9454922],"min":[-0.9454921,0.0617354736,-0.945492268],"type":"VEC3","name":"accessorPositions"},{"bufferView":1,"byteOffset":413496,"componentType":5126,"count":318,"type":"VEC3","name":"accessorNormals"},{"bufferView":2,"byteOffset":136560,"componentType":5126,"count":318,"type":"VEC2","name":"accessorUVs"},{"bufferView":0,"byteOffset":34776,"componentType":5123,"count":11520,"type":"SCALAR","name":"accessorIndices"},{"bufferView":1,"byteOffset":417312,"componentType":5126,"count":11520,"max":[0.196413681,2.12139344,1.90955186],"min":[-0.196414649,0.165008187,1.00927675],"type":"VEC3","name":"accessorPositions"},{"bufferView":1,"byteOffset":555552,"componentType":5126,"count":11520,"type":"VEC3","name":"accessorNormals"},{"bufferView":2,"byteOffset":139104,"componentType":5126,"count":11520,"type":"VEC2","name":"accessorUVs"}],"bufferViews":[{"buffer":0,"byteLength":57816,"name":"bufferViewScalar"},{"buffer":0,"byteOffset":57816,"byteLength":693792,"byteStride":12,"name":"bufferViewFloatVec3"},{"buffer":0,"byteOffset":751608,"byteLength":231264,"byteStride":8,"name":"bufferViewFloatVec2"}],"buffers":[{"uri":"model.bin","byteLength":982872}],"materials":[{"pbrMetallicRoughness":{"metallicFactor":0.0,"roughnessFactor":0.9},"doubleSided":true,"name":"01 - Default"},{"pbrMetallicRoughness":{"baseColorTexture":{"index":0},"metallicFactor":0.0,"roughnessFactor":0.9},"doubleSided":true,"name":"02 - Default"},{"pbrMetallicRoughness":{"baseColorFactor":[0.0,1.0,0.117647067,1.0],"metallicFactor":0.0,"roughnessFactor":0.9},"doubleSided":true,"name":"03 - Default"},{"pbrMetallicRoughness":{"baseColorFactor":[0.2784314,0.0,0.9921569,1.0],"metallicFactor":0.0,"roughnessFactor":0.9},"doubleSided":true,"name":"04 - Default"},{"pbrMetallicRoughness":{"baseColorFactor":[0.9725491,0.776470661,0.0,1.0],"metallicFactor":0.0,"roughnessFactor":0.9},"doubleSided":true,"name":"05 - Default"}],"textures":[{"sampler":0,"source":0,"name":"texture.jpg"}],"images":[{"uri":"./texture.jpg"}],"samplers":[{"magFilter":9729,"minFilter":9987}]}

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 MiB

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,74 +0,0 @@
7767517
72 73
Input input.1 0 1 data
Split splitncnn_input0 1 2 data input_splitncnn_0 input_splitncnn_1
Convolution Conv_0 1 1 input_splitncnn_1 102 0=64 1=3 4=1 5=1 6=1728
PReLU PRelu_1 1 1 102 105 0=64
Convolution Conv_2 1 1 105 106 0=64 1=3 4=1 5=1 6=36864
PReLU PRelu_3 1 1 106 109 0=64
Convolution Conv_4 1 1 109 110 0=64 1=3 4=1 5=1 6=36864
PReLU PRelu_5 1 1 110 113 0=64
Convolution Conv_6 1 1 113 114 0=64 1=3 4=1 5=1 6=36864
PReLU PRelu_7 1 1 114 117 0=64
Convolution Conv_8 1 1 117 118 0=64 1=3 4=1 5=1 6=36864
PReLU PRelu_9 1 1 118 121 0=64
Convolution Conv_10 1 1 121 122 0=64 1=3 4=1 5=1 6=36864
PReLU PRelu_11 1 1 122 125 0=64
Convolution Conv_12 1 1 125 126 0=64 1=3 4=1 5=1 6=36864
PReLU PRelu_13 1 1 126 129 0=64
Convolution Conv_14 1 1 129 130 0=64 1=3 4=1 5=1 6=36864
PReLU PRelu_15 1 1 130 133 0=64
Convolution Conv_16 1 1 133 134 0=64 1=3 4=1 5=1 6=36864
PReLU PRelu_17 1 1 134 137 0=64
Convolution Conv_18 1 1 137 138 0=64 1=3 4=1 5=1 6=36864
PReLU PRelu_19 1 1 138 141 0=64
Convolution Conv_20 1 1 141 142 0=64 1=3 4=1 5=1 6=36864
PReLU PRelu_21 1 1 142 145 0=64
Convolution Conv_22 1 1 145 146 0=64 1=3 4=1 5=1 6=36864
PReLU PRelu_23 1 1 146 149 0=64
Convolution Conv_24 1 1 149 150 0=64 1=3 4=1 5=1 6=36864
PReLU PRelu_25 1 1 150 153 0=64
Convolution Conv_26 1 1 153 154 0=64 1=3 4=1 5=1 6=36864
PReLU PRelu_27 1 1 154 157 0=64
Convolution Conv_28 1 1 157 158 0=64 1=3 4=1 5=1 6=36864
PReLU PRelu_29 1 1 158 161 0=64
Convolution Conv_30 1 1 161 162 0=64 1=3 4=1 5=1 6=36864
PReLU PRelu_31 1 1 162 165 0=64
Convolution Conv_32 1 1 165 166 0=64 1=3 4=1 5=1 6=36864
PReLU PRelu_33 1 1 166 169 0=64
Convolution Conv_34 1 1 169 170 0=64 1=3 4=1 5=1 6=36864
PReLU PRelu_35 1 1 170 173 0=64
Convolution Conv_36 1 1 173 174 0=64 1=3 4=1 5=1 6=36864
PReLU PRelu_37 1 1 174 177 0=64
Convolution Conv_38 1 1 177 178 0=64 1=3 4=1 5=1 6=36864
PReLU PRelu_39 1 1 178 181 0=64
Convolution Conv_40 1 1 181 182 0=64 1=3 4=1 5=1 6=36864
PReLU PRelu_41 1 1 182 185 0=64
Convolution Conv_42 1 1 185 186 0=64 1=3 4=1 5=1 6=36864
PReLU PRelu_43 1 1 186 189 0=64
Convolution Conv_44 1 1 189 190 0=64 1=3 4=1 5=1 6=36864
PReLU PRelu_45 1 1 190 193 0=64
Convolution Conv_46 1 1 193 194 0=64 1=3 4=1 5=1 6=36864
PReLU PRelu_47 1 1 194 197 0=64
Convolution Conv_48 1 1 197 198 0=64 1=3 4=1 5=1 6=36864
PReLU PRelu_49 1 1 198 201 0=64
Convolution Conv_50 1 1 201 202 0=64 1=3 4=1 5=1 6=36864
PReLU PRelu_51 1 1 202 205 0=64
Convolution Conv_52 1 1 205 206 0=64 1=3 4=1 5=1 6=36864
PReLU PRelu_53 1 1 206 209 0=64
Convolution Conv_54 1 1 209 210 0=64 1=3 4=1 5=1 6=36864
PReLU PRelu_55 1 1 210 213 0=64
Convolution Conv_56 1 1 213 214 0=64 1=3 4=1 5=1 6=36864
PReLU PRelu_57 1 1 214 217 0=64
Convolution Conv_58 1 1 217 218 0=64 1=3 4=1 5=1 6=36864
PReLU PRelu_59 1 1 218 221 0=64
Convolution Conv_60 1 1 221 222 0=64 1=3 4=1 5=1 6=36864
PReLU PRelu_61 1 1 222 225 0=64
Convolution Conv_62 1 1 225 226 0=64 1=3 4=1 5=1 6=36864
PReLU PRelu_63 1 1 226 229 0=64
Convolution Conv_64 1 1 229 230 0=64 1=3 4=1 5=1 6=36864
PReLU PRelu_65 1 1 230 233 0=64
Convolution Conv_66 1 1 233 234 0=48 1=3 4=1 5=1 6=27648
PixelShuffle DepthToSpace_67 1 1 234 235 0=4
Interp Resize_68 1 1 input_splitncnn_0 240 0=1 1=4.000000e+00 2=4.000000e+00
BinaryOp Add_69 2 1 235 240 output

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 313 B

View File

@@ -1,30 +0,0 @@
#!/bin/zsh
setopt null_glob
INPUT="./images"
OUTPUT="./images_output"
MODELPATH="./models"
MODELNAME="ultramix-balanced-4x"
TARGET_WIDTH="4320"
FORMAT="jpg" # 或 webp
SCALE=3
MAX_SIZE=$((20 * 1024 * 1024)) # 20MB
./bin/mac/upscayl-bin -i "$INPUT" -o "$OUTPUT" -f $FORMAT -m $MODELPATH -n $MODELNAME -w $TARGET_WIDTH -j 4:8:4 -v
echo "\n===== 输入目录: $INPUT ====="
for img in "$INPUT"/*.{png,jpg,jpeg}; do
[ -e "$img" ] || continue
size=$(stat -f%z "$img")
res=$(sips -g pixelWidth -g pixelHeight "$img" 2>/dev/null | awk '/pixelWidth|pixelHeight/ {print $2}' | xargs | sed 's/ /x/')
echo "$(basename "$img"): ${size} bytes, ${res}"
done
echo "\n===== 输出目录: $OUTPUT ====="
for img in "$OUTPUT"/*.{png,jpg,jpeg}; do
[ -e "$img" ] || continue
size=$(stat -f%z "$img")
res=$(sips -g pixelWidth -g pixelHeight "$img" 2>/dev/null | awk '/pixelWidth|pixelHeight/ {print $2}' | xargs | sed 's/ /x/')
echo "$(basename "$img"): ${size} bytes, ${res}"
done

View File

@@ -1,114 +0,0 @@
#!/bin/zsh
setopt null_glob
# 设置默认值或从环境变量获取
INPUT="${INPUT_DIR:-./images}"
OUTPUT="${OUTPUT_DIR:-./images_output}"
MODELPATH="${MODELPATH:-./models}"
MODELNAME="${MODELNAME:-ultramix-balanced-4x}"
BIN_PATH="${BIN_PATH:-./bin/mac/upscayl-bin}"
TARGET_WIDTH=4320
TARGET_HEIGHT=7680
FORMAT="jpg"
THREADS="4:8:4"
TARGET_SIZE=$((10 * 1024 * 1024)) # 10MB
MAX_SIZE=$((20 * 1024 * 1024)) # 20MB
echo "===== 开始批量处理图片 ====="
echo "输入目录: $INPUT"
echo "输出目录: $OUTPUT"
echo "模型路径: $MODELPATH"
echo "模型名称: $MODELNAME"
echo "二进制文件: $BIN_PATH"
# 确保输出目录存在
mkdir -p "$OUTPUT"
# 循环对每个图片单独执行 upscayl-bin输出路径为文件路径
for img in "$INPUT"/*.{png,jpg,jpeg}; do
[ -e "$img" ] || continue
base=$(basename "$img")
out_img="$OUTPUT/${base%.*}.$FORMAT"
compress=10 # 0为无压缩100为最大压缩
try=1
echo "\n==== 开始处理: $base ===="
echo "输入文件: $img"
echo "输出文件: $out_img"
echo "模型: $MODELNAME, 模型路径: $MODELPATH"
echo "格式: $FORMAT"
# 获取原图宽高
read orig_w orig_h <<< $(sips -g pixelWidth -g pixelHeight "$img" 2>/dev/null | awk '/pixelWidth/ {w=$2} /pixelHeight/ {h=$2} END{print w,h}')
if [ "$orig_w" -lt "$orig_h" ]; then
short=$orig_w
long=$orig_h
else
short=$orig_h
long=$orig_w
fi
echo "DEBUG: orig_w=$orig_w, orig_h=$orig_h, short=$short, long=$long"
scale1=$(echo "scale=8; 4320/$short" | bc)
scale2=$(echo "scale=8; 7680/$long" | bc)
echo "DEBUG: scale1=$scale1, scale2=$scale2"
# 取scale1和scale2的最大值
scale=$(echo "$scale1 > $scale2" | bc -l)
if [ "$scale" -eq 1 ]; then
use_scale=$scale1
else
use_scale=$scale2
fi
use_scale=$(printf "%f" "$use_scale")
echo "DEBUG: use_scale=$use_scale"
# 保证不缩小
scale_cmp=$(echo "$use_scale > 1" | bc -l)
echo "DEBUG: scale_cmp=$scale_cmp"
if [ "$scale_cmp" -eq 1 ]; then
target_w=$(awk -v w="$orig_w" -v s="$use_scale" 'BEGIN{printf "%d", w*s+0.5}')
target_h=$(awk -v h="$orig_h" -v s="$use_scale" 'BEGIN{printf "%d", h*s+0.5}')
echo "原图分辨率: ${orig_w}x${orig_h}, 目标分辨率: ${target_w}x${target_h} (短边≥4320, 长边≥7680)"
else
target_w=$orig_w
target_h=$orig_h
echo "原图分辨率: ${orig_w}x${orig_h}, 已满足短边≥4320且长边≥7680无需放大"
fi
while true; do
echo "尝试第 $try 次: compress=$compress"
upscale_cmd="\"$BIN_PATH\" -i \"$img\" -o \"$out_img\" -f $FORMAT -m \"$MODELPATH\" -n $MODELNAME -r \"${target_w}x${target_h}\" -c $compress -j $THREADS -v"
echo "执行命令: $upscale_cmd"
eval $upscale_cmd
if [ ! -f "$out_img" ]; then
echo "$base: 未生成图片compress=$compress"
break
fi
size=$(stat -f%z "$out_img")
res=$(sips -g pixelWidth -g pixelHeight "$out_img" 2>/dev/null | awk '/pixelWidth|pixelHeight/ {print $2}' | xargs | sed 's/ /x/')
echo "$base: compress=$compress, size=${size} bytes, 分辨率=${res}"
if [ $size -le $MAX_SIZE ] || [ $compress -ge 100 ]; then
echo "$base: 满足大小要求,最终 compress=$compress"
break
fi
# compress 每次递增10最大不超过100
compress=$((compress + 10))
[ $compress -gt 100 ] && compress=100
try=$((try+1))
[ $try -gt 10 ] && echo "$base: 达到最大尝试次数,停止调整" && break
done
done
echo "\n===== 输入目录: $INPUT ====="
for img in "$INPUT"/*.{png,jpg,jpeg}; do
[ -e "$img" ] || continue
size=$(stat -f%z "$img")
res=$(sips -g pixelWidth -g pixelHeight "$img" 2>/dev/null | awk '/pixelWidth|pixelHeight/ {print $2}' | xargs | sed 's/ /x/')
echo "$(basename "$img"): ${size} bytes, ${res}"
done
echo "\n===== 输出目录: $OUTPUT ====="
for img in "$OUTPUT"/*.{png,jpg,jpeg}; do
[ -e "$img" ] || continue
size=$(stat -f%z "$img")
res=$(sips -g pixelWidth -g pixelHeight "$img" 2>/dev/null | awk '/pixelWidth|pixelHeight/ {print $2}' | xargs | sed 's/ /x/')
echo "$(basename "$img"): ${size} bytes, ${res}"
done

View File

@@ -1,131 +0,0 @@
#!/bin/zsh
setopt null_glob
# 从环境变量或参数获取配置
INPUT_FILE="${INPUT_FILE:-$1}"
OUTPUT_FILE="${OUTPUT_FILE:-$2}"
MODELPATH="${MODELPATH:-./models}"
MODELNAME="${MODELNAME:-ultramix-balanced-4x}"
BIN_PATH="${BIN_PATH:-./bin/mac/upscayl-bin}"
TARGET_WIDTH=4320
TARGET_HEIGHT=7680
FORMAT="jpg"
THREADS="4:8:4"
TARGET_SIZE=$((10 * 1024 * 1024)) # 10MB
MAX_SIZE=$((20 * 1024 * 1024)) # 20MB
# 检查输入参数
if [ -z "$INPUT_FILE" ] || [ -z "$OUTPUT_FILE" ]; then
echo "错误: 需要指定输入和输出文件路径"
echo "用法: $0 <输入文件> <输出文件>"
echo "或者设置环境变量 INPUT_FILE 和 OUTPUT_FILE"
exit 1
fi
if [ ! -f "$INPUT_FILE" ]; then
echo "错误: 输入文件不存在: $INPUT_FILE"
exit 1
fi
echo "===== 开始处理单张图片 ====="
echo "输入文件: $INPUT_FILE"
echo "输出文件: $OUTPUT_FILE"
echo "模型路径: $MODELPATH"
echo "模型名称: $MODELNAME"
echo "二进制文件: $BIN_PATH"
# 确保输出目录存在
output_dir=$(dirname "$OUTPUT_FILE")
mkdir -p "$output_dir"
base=$(basename "$INPUT_FILE")
compress=10 # 0为无压缩100为最大压缩
try=1
echo "\n==== 开始处理: $base ===="
echo "输入文件: $INPUT_FILE"
echo "输出文件: $OUTPUT_FILE"
echo "模型: $MODELNAME, 模型路径: $MODELPATH"
echo "格式: $FORMAT"
# 获取原图宽高
read orig_w orig_h <<< $(sips -g pixelWidth -g pixelHeight "$INPUT_FILE" 2>/dev/null | awk '/pixelWidth/ {w=$2} /pixelHeight/ {h=$2} END{print w,h}')
if [ "$orig_w" -lt "$orig_h" ]; then
short=$orig_w
long=$orig_h
else
short=$orig_h
long=$orig_w
fi
echo "DEBUG: orig_w=$orig_w, orig_h=$orig_h, short=$short, long=$long"
scale1=$(echo "scale=8; 4320/$short" | bc)
scale2=$(echo "scale=8; 7680/$long" | bc)
echo "DEBUG: scale1=$scale1, scale2=$scale2"
# 取scale1和scale2的最大值
scale=$(echo "$scale1 > $scale2" | bc -l)
if [ "$scale" -eq 1 ]; then
use_scale=$scale1
else
use_scale=$scale2
fi
use_scale=$(printf "%f" "$use_scale")
echo "DEBUG: use_scale=$use_scale"
# 保证不缩小
scale_cmp=$(echo "$use_scale > 1" | bc -l)
echo "DEBUG: scale_cmp=$scale_cmp"
if [ "$scale_cmp" -eq 1 ]; then
target_w=$(awk -v w="$orig_w" -v s="$use_scale" 'BEGIN{printf "%d", w*s+0.5}')
target_h=$(awk -v h="$orig_h" -v s="$use_scale" 'BEGIN{printf "%d", h*s+0.5}')
echo "原图分辨率: ${orig_w}x${orig_h}, 目标分辨率: ${target_w}x${target_h} (短边≥4320, 长边≥7680)"
else
target_w=$orig_w
target_h=$orig_h
echo "原图分辨率: ${orig_w}x${orig_h}, 已满足短边≥4320且长边≥7680无需放大"
fi
# 处理图片,循环调整压缩率直到满足大小要求
while true; do
echo "尝试第 $try 次: compress=$compress"
upscale_cmd="\"$BIN_PATH\" -i \"$INPUT_FILE\" -o \"$OUTPUT_FILE\" -f $FORMAT -m \"$MODELPATH\" -n $MODELNAME -r \"${target_w}x${target_h}\" -c $compress -j $THREADS -v"
echo "执行命令: $upscale_cmd"
eval $upscale_cmd
if [ ! -f "$OUTPUT_FILE" ]; then
echo "$base: 未生成图片compress=$compress"
echo "处理失败"
exit 1
fi
size=$(stat -f%z "$OUTPUT_FILE")
res=$(sips -g pixelWidth -g pixelHeight "$OUTPUT_FILE" 2>/dev/null | awk '/pixelWidth|pixelHeight/ {print $2}' | xargs | sed 's/ /x/')
echo "$base: compress=$compress, size=${size} bytes, 分辨率=${res}"
if [ $size -le $MAX_SIZE ] || [ $compress -ge 100 ]; then
echo "$base: 满足大小要求,最终 compress=$compress"
break
fi
# compress 每次递增10最大不超过100
compress=$((compress + 10))
[ $compress -gt 100 ] && compress=100
try=$((try+1))
[ $try -gt 10 ] && echo "$base: 达到最大尝试次数,停止调整" && break
done
echo "\n===== 处理完成 ====="
if [ -f "$OUTPUT_FILE" ]; then
input_size=$(stat -f%z "$INPUT_FILE")
output_size=$(stat -f%z "$OUTPUT_FILE")
input_res=$(sips -g pixelWidth -g pixelHeight "$INPUT_FILE" 2>/dev/null | awk '/pixelWidth|pixelHeight/ {print $2}' | xargs | sed 's/ /x/')
output_res=$(sips -g pixelWidth -g pixelHeight "$OUTPUT_FILE" 2>/dev/null | awk '/pixelWidth|pixelHeight/ {print $2}' | xargs | sed 's/ /x/')
echo "输入: $(basename "$INPUT_FILE") - ${input_size} bytes, ${input_res}"
echo "输出: $(basename "$OUTPUT_FILE") - ${output_size} bytes, ${output_res}"
echo "处理成功完成!"
else
echo "处理失败:未生成输出文件"
exit 1
fi

View File

@@ -1,4 +0,0 @@
# https://dart.dev/guides/libraries/private-files
# Created by `dart pub`
.dart_tool/
output/**

View File

@@ -1,3 +0,0 @@
## 1.0.0
- Initial version.

View File

@@ -1,9 +0,0 @@
# cli_headless
A simple headless Dart CLI app using Thermion to render to a bitmap.
To run:
`dart --enable-experiment=native-assets run bin/example.dart`
Currently, this will probably only work on a non-virtualized macOS host.

View File

@@ -1,30 +0,0 @@
# This file configures the static analysis results for your project (errors,
# warnings, and lints).
#
# This enables the 'recommended' set of lints from `package:lints`.
# This set helps identify many issues that may lead to problems when running
# or consuming Dart code, and enforces writing Dart using a single, idiomatic
# style and format.
#
# If you want a smaller set of lints you can change this to specify
# 'package:lints/core.yaml'. These are just the most critical lints
# (the recommended set includes the core lints).
# The core lints are also what is used by pub.dev for scoring packages.
include: package:lints/recommended.yaml
# Uncomment the following section to specify additional rules.
# linter:
# rules:
# - camel_case_types
# analyzer:
# exclude:
# - path/to/excluded/files/**
# For more information about the core and recommended set of lints, see
# https://dart.dev/go/core-lints
# For additional information about configuring this file, see
# https://dart.dev/guides/language/analysis-options

View File

@@ -1,32 +0,0 @@
import 'dart:io';
import 'dart:isolate';
import 'package:thermion_dart/thermion_dart.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_filament_app.dart';
void main() async {
await FFIFilamentApp.create();
final (width, height) = (500, 500);
final sc = await FilamentApp.instance!.createHeadlessSwapChain(width, height);
var viewer = ThermionViewerFFI();
await viewer.initialized;
await FilamentApp.instance!.register(sc, viewer.view);
await viewer.view.setFrustumCullingEnabled(false);
await viewer.setBackgroundColor(1, 0, 1, 1);
await viewer.setViewport(width, height);
final result = await FilamentApp.instance!.capture(
sc,
view: viewer.view,
);
final bitmap = await pixelBufferToBmp(result.first.$2, width, height,
hasAlpha: true, isFloat: true);
var outfile = File("output/render.bmp");
outfile.parent.create();
outfile.writeAsBytesSync(bitmap);
await FilamentApp.instance!.destroy();
Isolate.current.kill();
}

View File

@@ -1,21 +0,0 @@
name: example_cli
description: A sample command-line application.
version: 1.0.0
environment:
sdk: ^3.3.0
hooks:
user_defines:
thermion_dart:
mode: debug
tracing: enabled
dependencies:
thermion_dart:
path: ../../../thermion_dart
dev_dependencies:
ffigen: ^11.0.0
lints: ^3.0.0
test: ^1.24.0

View File

@@ -1,3 +0,0 @@
# https://dart.dev/guides/libraries/private-files
# Created by `dart pub`
.dart_tool/

View File

@@ -1,3 +0,0 @@
## 1.0.0
- Initial version.

View File

@@ -1,7 +0,0 @@
# Thermion Example - Dart/Windows-only (no Flutter)
A (Windows-only) command-line application that renders into a window without Flutter.
```
dart --enable-experiment=native-assets bin\cli_windows.dart
```

View File

@@ -1,30 +0,0 @@
# This file configures the static analysis results for your project (errors,
# warnings, and lints).
#
# This enables the 'recommended' set of lints from `package:lints`.
# This set helps identify many issues that may lead to problems when running
# or consuming Dart code, and enforces writing Dart using a single, idiomatic
# style and format.
#
# If you want a smaller set of lints you can change this to specify
# 'package:lints/core.yaml'. These are just the most critical lints
# (the recommended set includes the core lints).
# The core lints are also what is used by pub.dev for scoring packages.
include: package:lints/recommended.yaml
# Uncomment the following section to specify additional rules.
# linter:
# rules:
# - camel_case_types
# analyzer:
# exclude:
# - path/to/excluded/files/**
# For more information about the core and recommended set of lints, see
# https://dart.dev/go/core-lints
# For additional information about configuring this file, see
# https://dart.dev/guides/language/analysis-options

View File

@@ -1,54 +0,0 @@
import 'dart:ffi';
import 'dart:io';
import 'dart:math';
import 'package:ffi/ffi.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_filament_app.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_viewer_ffi.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_dart.g.dart';
import 'package:thermion_dart/thermion_dart.dart';
import 'package:vector_math/vector_math_64.dart';
import 'package:cli_windows/thermion_window.g.dart';
void main(List<String> arguments) async {
var hwnd = create_thermion_window(500, 500, 0, 0);
update();
await FFIFilamentApp.create();
var viewer = ThermionViewerFFI(
loadAssetFromUri: (path) async => File(path.replaceAll("file://", "")).readAsBytesSync());
await viewer.initialized;
var swapChain = await FilamentApp.instance!.createSwapChain(Pointer<Void>.fromAddress(hwnd));
var view = viewer.view;
await view.setViewport(500, 500);
var camera = await viewer.getActiveCamera();
await camera.setLensProjection();
await FilamentApp.instance!.register(swapChain, view);
await viewer.setBackgroundColor(1.0, 0.0, 0.0, 1.0);
var skyboxPath = File("..\\..\\assets\\default_env_skybox.ktx").absolute;
await viewer.loadSkybox("file://${skyboxPath.uri.toFilePath(windows: true)}");
final cube = await viewer.createGeometry(GeometryHelper.cube());
var stopwatch = Stopwatch();
stopwatch.start();
var last = 0;
await camera.lookAt(Vector3(0, 0, 10));
while(true) {
var angle = (stopwatch.elapsedMilliseconds / 1000) * 2 * pi;
var rotation = Quaternion.axisAngle(Vector3(0,1,0), angle);
var position = Vector3(10 * sin(angle), 0, 10 * cos(angle));
var modelMatrix = Matrix4.compose(position, rotation, Vector3.all(1));
await camera.setModelMatrix(modelMatrix);
await FilamentApp.instance!.requestFrame();
update();
await Future.delayed(Duration(milliseconds: 17));
}
}

View File

@@ -1,32 +0,0 @@
import 'package:logging/logging.dart';
import 'package:native_assets_cli/native_assets_cli.dart';
import 'package:native_toolchain_c/native_toolchain_c.dart';
import 'package:path/path.dart' as path;
void main(List<String> args) async {
final logger = Logger("")
..level = Level.ALL
..onRecord.listen((record) => print(
record.message + "\n"));
await build(args, (input, output) async {
final cbuilder = CBuilder.library(
name: input.packageName,
language: Language.cpp,
assetName: 'cli_windows.dart',
sources: ['native/thermion_window.cpp'],
includes: ['native', '../../../thermion_dart/native/include'],
defines: {"UNICODE":"1"},
flags:[],
dartBuildFiles: ['hook/build.dart'],
);
await cbuilder.run(
input: input,
output: output,
logger: logger,
);
});
}

View File

@@ -1,19 +0,0 @@
// AUTO GENERATED FILE, DO NOT EDIT.
//
// Generated by `package:ffigen`.
// ignore_for_file: type=lint
@ffi.DefaultAsset('package:cli_windows/cli_windows.dart')
library;
import 'dart:ffi' as ffi;
@ffi.Native<ffi.Int Function(ffi.Int, ffi.Int, ffi.Int, ffi.Int)>(isLeaf: true)
external int create_thermion_window(
int width,
int height,
int left,
int top,
);
@ffi.Native<ffi.Void Function()>(isLeaf: true)
external void update();

View File

@@ -1,390 +0,0 @@
#pragma comment(lib, "dwmapi.lib")
#pragma comment(lib, "comctl32.lib")
#pragma comment(lib, "Shlwapi.lib")
#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "Gdi32.lib")
#pragma comment(lib, "User32.lib")
#pragma comment(lib, "dxgi.lib")
#include <dxgi.h>
#include <cstdint>
#include <chrono>
#include <thread>
#include <algorithm>
#include <Windows.h>
#include <dwmapi.h>
#include <ShObjIdl.h>
#include <iostream>
#include <Windows.h>
#include "thermion_window.h"
namespace thermion {
void PrintDefaultGPU() {
IDXGIFactory* factory = nullptr;
CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&factory);
IDXGIAdapter* adapter = nullptr;
factory->EnumAdapters(0, &adapter); // 0 is the default adapter
DXGI_ADAPTER_DESC desc;
adapter->GetDesc(&desc);
std::wcout << L"GPU: " << desc.Description << std::endl;
adapter->Release();
factory->Release();
}
///
/// Instantiating a ThermionWindow creates a HWND that can be passed
/// to Filament to create a swapchain.
///
///
class ThermionWindow {
public:
ThermionWindow(
int width,
int height,
int left,
int top);
HWND GetHandle();
void Resize(int width, int height, int left, int top);
uint32_t _width = 0;
uint32_t _height = 0;
uint32_t _left = 0;
uint32_t _top = 0;
private:
HWND _windowHandle;
};
static ThermionWindow* _window;
static bool _running = false;
static std::thread _renderThread;
// Add these for timing and stats
static int _frameCount = 0;
static std::chrono::time_point<std::chrono::steady_clock> _lastFpsLog;
static void RenderLoop() {
_lastFpsLog = std::chrono::steady_clock::now();
auto lastFrame = std::chrono::steady_clock::now();
while (_running) {
auto now = std::chrono::steady_clock::now();
auto frameDuration = std::chrono::duration_cast<std::chrono::microseconds>(now - lastFrame).count();
// Force a redraw
InvalidateRect(_window->GetHandle(), NULL, FALSE);
// Process any pending messages
MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
if (msg.message == WM_QUIT) {
_running = false;
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// Wait for vsync
DwmFlush();
// Update timing stats
lastFrame = now;
_frameCount++;
// Log FPS every second
auto timeSinceLastLog = std::chrono::duration_cast<std::chrono::milliseconds>(now - _lastFpsLog).count();
if (timeSinceLastLog >= 1000) { // Every second
float fps = (_frameCount * 1000.0f) / timeSinceLastLog;
float avgFrameTime = timeSinceLastLog / (float)_frameCount;
std::cout << "FPS: " << fps << " Frame Time: " << avgFrameTime << "ms"
<< " Last Frame: " << frameDuration / 1000.0f << "ms" << std::endl;
_frameCount = 0;
_lastFpsLog = now;
}
}
}
extern "C" {
EMSCRIPTEN_KEEPALIVE intptr_t create_thermion_window(int width, int height, int left, int top) {
_window = new ThermionWindow(width, height, left, top);
// Start the render thread
_running = true;
_renderThread = std::thread(RenderLoop);
return (intptr_t)_window->GetHandle();
}
// Update function can now be simplified or removed since rendering happens in the thread
EMSCRIPTEN_KEEPALIVE void update() {
}
// Add a cleanup function
EMSCRIPTEN_KEEPALIVE void cleanup() {
_running = false;
if (_renderThread.joinable()) {
_renderThread.join();
}
if (_window) {
delete _window;
_window = nullptr;
}
}
}
static constexpr auto kClassName = L"THERMION_WINDOW";
static constexpr auto kWindowName = L"thermion_window";
static bool was_window_hidden_due_to_minimize_ = false;
static WPARAM last_wm_size_wparam_ = SIZE_RESTORED;
uint64_t last_thread_time_ = 0;
static constexpr auto kNativeViewPositionAndShowDelay = 300;
typedef enum _WINDOWCOMPOSITIONATTRIB {
WCA_UNDEFINED = 0,
WCA_NCRENDERING_ENABLED = 1,
WCA_NCRENDERING_POLICY = 2,
WCA_TRANSITIONS_FORCEDISABLED = 3,
WCA_ALLOW_NCPAINT = 4,
WCA_CAPTION_BUTTON_BOUNDS = 5,
WCA_NONCLIENT_RTL_LAYOUT = 6,
WCA_FORCE_ICONIC_REPRESENTATION = 7,
WCA_EXTENDED_FRAME_BOUNDS = 8,
WCA_HAS_ICONIC_BITMAP = 9,
WCA_THEME_ATTRIBUTES = 10,
WCA_NCRENDERING_EXILED = 11,
WCA_NCADORNMENTINFO = 12,
WCA_EXCLUDED_FROM_LIVEPREVIEW = 13,
WCA_VIDEO_OVERLAY_ACTIVE = 14,
WCA_FORCE_ACTIVEWINDOW_APPEARANCE = 15,
WCA_DISALLOW_PEEK = 16,
WCA_CLOAK = 17,
WCA_CLOAKED = 18,
WCA_ACCENT_POLICY = 19,
WCA_FREEZE_REPRESENTATION = 20,
WCA_EVER_UNCLOAKED = 21,
WCA_VISUAL_OWNER = 22,
WCA_HOLOGRAPHIC = 23,
WCA_EXCLUDED_FROM_DDA = 24,
WCA_PASSIVEUPDATEMODE = 25,
WCA_USEDARKMODECOLORS = 26,
WCA_LAST = 27
} WINDOWCOMPOSITIONATTRIB;
typedef struct _WINDOWCOMPOSITIONATTRIBDATA {
WINDOWCOMPOSITIONATTRIB Attrib;
PVOID pvData;
SIZE_T cbData;
} WINDOWCOMPOSITIONATTRIBDATA;
typedef enum _ACCENT_STATE {
ACCENT_DISABLED = 0,
ACCENT_ENABLE_GRADIENT = 1,
ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
ACCENT_ENABLE_BLURBEHIND = 3,
ACCENT_ENABLE_ACRYLICBLURBEHIND = 4,
ACCENT_ENABLE_HOSTBACKDROP = 5,
ACCENT_INVALID_STATE = 6
} ACCENT_STATE;
typedef struct _ACCENT_POLICY {
ACCENT_STATE AccentState;
DWORD AccentFlags;
DWORD GradientColor;
DWORD AnimationId;
} ACCENT_POLICY;
typedef BOOL(WINAPI* _GetWindowCompositionAttribute)(
HWND, WINDOWCOMPOSITIONATTRIBDATA*);
typedef BOOL(WINAPI* _SetWindowCompositionAttribute)(
HWND, WINDOWCOMPOSITIONATTRIBDATA*);
static _SetWindowCompositionAttribute g_set_window_composition_attribute = NULL;
static bool g_set_window_composition_attribute_initialized = false;
typedef LONG NTSTATUS, *PNTSTATUS;
#define STATUS_SUCCESS (0x00000000)
typedef NTSTATUS(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
RTL_OSVERSIONINFOW GetWindowsVersion() {
HMODULE hmodule = ::GetModuleHandleW(L"ntdll.dll");
if (hmodule) {
RtlGetVersionPtr rtl_get_version_ptr =
(RtlGetVersionPtr)::GetProcAddress(hmodule, "RtlGetVersion");
if (rtl_get_version_ptr != nullptr) {
RTL_OSVERSIONINFOW rovi = {0};
rovi.dwOSVersionInfoSize = sizeof(rovi);
if (STATUS_SUCCESS == rtl_get_version_ptr(&rovi)) {
return rovi;
}
}
}
RTL_OSVERSIONINFOW rovi = {0};
return rovi;
}
void SetWindowComposition(HWND window, int32_t accent_state,
int32_t gradient_color) {
// TODO: Look for a better available API.
if (GetWindowsVersion().dwBuildNumber >= 18362) {
if (!g_set_window_composition_attribute_initialized) {
auto user32 = ::GetModuleHandleA("user32.dll");
if (user32) {
g_set_window_composition_attribute =
reinterpret_cast<_SetWindowCompositionAttribute>(
::GetProcAddress(user32, "SetWindowCompositionAttribute"));
if (g_set_window_composition_attribute) {
g_set_window_composition_attribute_initialized = true;
}
}
}
ACCENT_POLICY accent = {static_cast<ACCENT_STATE>(accent_state), 2,
static_cast<DWORD>(gradient_color), 0};
WINDOWCOMPOSITIONATTRIBDATA data;
data.Attrib = WCA_ACCENT_POLICY;
data.pvData = &accent;
data.cbData = sizeof(accent);
g_set_window_composition_attribute(window, &data);
}
}
// Add tracking for drag state
static bool isDragging = false;
static POINT dragStart = {0, 0};
static POINT windowStart = {0, 0};
LRESULT CALLBACK FilamentWindowProc(HWND const window, UINT const message,
WPARAM const wparam,
LPARAM const lparam) noexcept {
switch (message) {
case WM_DESTROY: {
PostQuitMessage(0);
return 0;
}
case WM_NCHITTEST: {
POINT pt = { LOWORD(lparam), HIWORD(lparam) };
ScreenToClient(window, &pt);
return HTCAPTION;
}
case WM_MOUSEMOVE: {
TRACKMOUSEEVENT event;
event.cbSize = sizeof(event);
event.hwndTrack = window;
event.dwFlags = TME_HOVER;
event.dwHoverTime = 200;
auto user_data = ::GetWindowLongPtr(window, GWLP_USERDATA);
if (user_data) {
HWND flutterRootWindow = reinterpret_cast<HWND>(user_data);
LONG ex_style = ::GetWindowLong(flutterRootWindow, GWL_EXSTYLE);
ex_style &= ~(WS_EX_TRANSPARENT | WS_EX_LAYERED);
::SetWindowLong(flutterRootWindow, GWL_EXSTYLE, ex_style);
}
break;
}
case WM_ERASEBKGND: {
HDC hdc = (HDC)wparam;
RECT rect;
GetClientRect(window, &rect);
ThermionWindow* thermionWindow = reinterpret_cast<ThermionWindow*>(
GetWindowLongPtr(window, GWLP_USERDATA));
if (thermionWindow) {
HBRUSH brush = CreateSolidBrush(RGB(0, 0, 255));
FillRect(hdc, &rect, brush);
DeleteObject(brush);
}
return TRUE;
}
case WM_SIZE:
case WM_MOVE:
case WM_MOVING:
case WM_WINDOWPOSCHANGED: {
auto user_data = ::GetWindowLongPtr(window, GWLP_USERDATA);
if (user_data) {
HWND flutterRootWindow = reinterpret_cast<HWND>(user_data);
LONG ex_style = ::GetWindowLong(flutterRootWindow, GWL_EXSTYLE);
ex_style &= ~(WS_EX_TRANSPARENT | WS_EX_LAYERED);
::SetWindowLong(flutterRootWindow, GWL_EXSTYLE, ex_style);
}
break;
}
default:
return ::DefWindowProc(window, message, wparam, lparam);
}
return 0;
}
ThermionWindow::ThermionWindow(int width,
int height,
int left,
int top) : _width(width), _height(height), _left(left), _top(top) {
PrintDefaultGPU();
auto window_class = WNDCLASSEX{};
::SecureZeroMemory(&window_class, sizeof(window_class));
window_class.cbSize = sizeof(window_class);
window_class.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
window_class.lpfnWndProc = FilamentWindowProc;
window_class.hInstance = GetModuleHandle(nullptr);
window_class.lpszClassName = L"THERMION_WINDOW";
window_class.hCursor = ::LoadCursorW(nullptr, IDC_ARROW);
window_class.hbrBackground = ::CreateSolidBrush(RGB(0,255,0));
::RegisterClassExW(&window_class);
// Create a normal popup window without forcing it to be topmost
_windowHandle = ::CreateWindowW(
L"THERMION_WINDOW",
L"thermion_window",
WS_OVERLAPPEDWINDOW,
left, top, width, height,
nullptr, nullptr,
GetModuleHandle(nullptr),
nullptr
);
// Store the this pointer for use in window procedure
::SetWindowLongPtr(_windowHandle, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
// Disable DWM animations
auto disable_window_transitions = TRUE;
DwmSetWindowAttribute(_windowHandle, DWMWA_TRANSITIONS_FORCEDISABLED,
&disable_window_transitions,
sizeof(disable_window_transitions));
::ShowWindow(_windowHandle, SW_SHOW);
UpdateWindow(_windowHandle);
}
void ThermionWindow::Resize(int width, int height, int left, int top) {
_width = width;
_height = height;
_left = left;
_top = top;
::SetWindowPos(_windowHandle, nullptr, left, top, width, height,
SWP_NOZORDER | SWP_NOACTIVATE);
}
HWND ThermionWindow::GetHandle() { return _windowHandle; }
} // namespace thermion

View File

@@ -1,14 +0,0 @@
#pragma once
#ifdef IS_DLL
#define EMSCRIPTEN_KEEPALIVE __declspec(dllimport)
#else
#define EMSCRIPTEN_KEEPALIVE __declspec(dllexport)
#endif
extern "C" {
intptr_t create_thermion_window(int width, int height, int left, int top);
void update();
}

View File

@@ -1,21 +0,0 @@
name: cli_windows
description: A sample command-line application with basic argument parsing.
version: 0.0.1
environment:
sdk: ^3.6.0-326.0.dev
dependencies:
args: ^2.5.0
thermion_dart:
path: ../../../thermion_dart
ffi: ^2.1.3
vector_math: ^2.1.4
native_toolchain_c: ^0.9.0
native_assets_cli: ^0.12.0
dev_dependencies:
lints: ^5.0.0
test: ^1.24.0

View File

@@ -1,19 +0,0 @@
name: example_web
description: A sample command-line application.
version: 1.0.0
# repository: https://github.com/my_org/my_repo
environment:
sdk: ^3.3.0
dependencies:
thermion_dart:
path: ../../../thermion_dart
logging: ^1.3.0
dev_dependencies:
lints: ^3.0.0
test: ^1.24.0
build_runner: ^2.4.13
build_test: ^2.2.2
build_web_compilers: ^4.1.5

View File

@@ -1 +0,0 @@
../../../assets/

View File

@@ -1,101 +0,0 @@
import 'dart:async';
import 'dart:js_interop';
import 'dart:math';
import 'package:web/web.dart';
import 'package:logging/logging.dart';
import 'package:thermion_dart/thermion_dart.dart'
hide NativeLibrary, Image_decode;
import 'package:thermion_dart/src/filament/src/implementation/ffi_filament_app.dart';
import 'web_input_handler.dart';
import 'package:thermion_dart/src/bindings/src/thermion_dart_js_interop.g.dart';
void main(List<String> arguments) async {
Logger.root.onRecord.listen((record) {
print(record);
});
NativeLibrary.initBindings("thermion_dart");
final canvas =
document.getElementById("thermion_canvas") as HTMLCanvasElement;
try {
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
} catch (err) {
print(err.toString());
}
final config = FFIFilamentConfig(backend: Backend.OPENGL);
await FFIFilamentApp.create(config: config);
var swapChain = await FilamentApp.instance!
.createHeadlessSwapChain(canvas.width, canvas.height);
final viewer = ThermionViewerFFI();
await viewer.initialized;
await FilamentApp.instance!.setClearOptions(1.0, 0.0, 0.0, 1.0);
await FilamentApp.instance!.register(swapChain, viewer.view);
await viewer.setViewport(canvas.width, canvas.height);
await viewer.setRendering(true);
final rnd = Random();
// ignore: prefer_function_declarations_over_variables
bool resizing = false;
// ignore: prefer_function_declarations_over_variables
final resizer = () async {
if (resizing) {
return;
}
try {
resizing = true;
await viewer.setViewport(canvas.clientWidth, canvas.clientHeight);
Thermion_resizeCanvas(canvas.clientWidth, canvas.clientHeight);
} catch (err) {
print(err);
} finally {
resizing = false;
}
};
// ignore: unused_local_variable, prefer_function_declarations_over_variables
final jsWrapper = () {
var promise = resizer().toJS;
return promise;
};
window.addEventListener('resize', jsWrapper.toJS);
// // await FilamentApp.instance!.render();
// // await Future.delayed(Duration(seconds: 1));
// // await FilamentApp.instance!.setClearOptions(1.0, 1.0, 0.0, 1.0);
// // await FilamentApp.instance!.render();
// // await Future.delayed(Duration(seconds: 1));
await viewer.loadSkybox("assets/default_env_skybox.ktx");
await viewer.loadGltf("assets/cube.glb");
final camera = await viewer.getActiveCamera();
var zOffset = 10.0;
final inputHandler = DelegateInputHandler.flight(viewer);
final webInputHandler =
WebInputHandler(inputHandler: inputHandler, canvas: canvas);
await camera.lookAt(Vector3(0, 0, zOffset));
DateTime lastRender = DateTime.now();
while (true) {
var stackPtr = stackSave();
var now = DateTime.now();
await FilamentApp.instance!.requestFrame();
now = DateTime.now();
var timeSinceLast =
now.microsecondsSinceEpoch - lastRender.microsecondsSinceEpoch;
lastRender = now;
if (timeSinceLast < 1667) {
var waitFor = 1667 - timeSinceLast;
await Future.delayed(Duration(microseconds: waitFor));
}
stackRestore(stackPtr);
// inputHandler.keyDown(PhysicalKey.S);
// await camera.lookAt(Vector3(0,0,zOffset));
// zOffset +=0.1;
}
}

View File

@@ -1,35 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="./thermion_dart.js"></script>
<script type="module">
try {
window.thermion_dart = await thermion_dart();
} catch(err) {
console.error(err);
}
const script = document.createElement('script')
script.src = 'example.dart.js'
document.head.append(script);
</script>
<style>
html, body {
margin:0;
padding:0;
}
canvas {
position:absolute;
left:0;
right:0;
top:0;
bottom:0;
width:100%;
height:100%;
}
</style>
</head>
<body>
<canvas id="thermion_canvas"></canvas>
</body>
</html>

View File

@@ -1,35 +0,0 @@
<html>
<head>
<script src="thermion_dart.js"></script>
<style>
html, body {
margin:0;
padding:0;
}
canvas {
position:absolute;
left:0;
right:0;
top:0;
bottom:0;
width:100%;
height:100%;
}
</style>
</head>
<script type="module">
try {
window.thermion_dart = await thermion_dart();
} catch(err) {
console.error(err);
}
const dartModulePromise = WebAssembly.compileStreaming(fetch('./example.wasm'));
const imports = {};
const dart2wasm_runtime = await import('./example.mjs');
const moduleInstance = await dart2wasm_runtime.instantiate(dartModulePromise, imports);
await dart2wasm_runtime.invoke(moduleInstance);
</script>
<body>
<canvas id="canvas"></canvas>
</body>
</html>

View File

@@ -1,22 +0,0 @@
import { readFile } from 'fs/promises';
import { compile } from './example.mjs';
import thermion_dart from './thermion_dart.js';
async function runDartWasm() {
globalThis['thermion_dart'] = await thermion_dart();
const wasmBytes = await readFile('example.wasm');
const compiledApp = await compile(wasmBytes);
const instantiatedApp = await compiledApp.instantiate({});
try {
instantiatedApp.invokeMain();
} catch(err) {
console.error("Failed");
console.error(err);
}
}
runDartWasm().catch(console.error);

View File

@@ -1 +0,0 @@
../../../../thermion_dart/native/web/build/build/out/thermion_dart.js

View File

@@ -1 +0,0 @@
../../../../thermion_dart/native/web/build/build/out/thermion_dart.wasm

View File

@@ -1,299 +0,0 @@
import 'dart:js_interop';
import 'package:web/web.dart' as web;
import 'package:thermion_dart/thermion_dart.dart';
class WebInputHandler {
final InputHandler inputHandler;
final web.HTMLCanvasElement canvas;
late double pixelRatio;
final Map<int, Vector2> _touchPositions = {};
WebInputHandler({
required this.inputHandler,
required this.canvas,
}) {
pixelRatio = web.window.devicePixelRatio;
_initializeEventListeners();
}
void _initializeEventListeners() {
canvas.addEventListener('mousedown', _onMouseDown.toJS);
canvas.addEventListener('mousemove', _onMouseMove.toJS);
canvas.addEventListener('mouseup', _onMouseUp.toJS);
canvas.addEventListener('wheel', _onMouseWheel.toJS);
web.window.addEventListener('keydown', _onKeyDown.toJS);
web.window.addEventListener('keyup', _onKeyUp.toJS);
canvas.addEventListener('touchstart', _onTouchStart.toJS);
canvas.addEventListener('touchmove', _onTouchMove.toJS);
canvas.addEventListener('touchend', _onTouchEnd.toJS);
canvas.addEventListener('touchcancel', _onTouchCancel.toJS);
}
void _onMouseDown(web.MouseEvent event) {
final localPos = _getLocalPositionFromEvent(event);
final button = _getMouseButtonFromEvent(event);
inputHandler.handle(MouseEvent(
MouseEventType.buttonDown,
button,
localPos,
Vector2.zero(),
));
event.preventDefault();
}
void _onMouseMove(web.MouseEvent event) {
final localPos = _getLocalPositionFromEvent(event);
final delta = Vector2(event.movementX ?? 0, event.movementY ?? 0);
final button = _getMouseButtonFromEvent(event);
inputHandler.handle(MouseEvent(
MouseEventType.move,
button,
localPos,
delta,
));
event.preventDefault();
}
void _onMouseUp(web.MouseEvent event) {
final localPos = _getLocalPositionFromEvent(event);
final button = _getMouseButtonFromEvent(event);
inputHandler.handle(MouseEvent(
MouseEventType.buttonUp,
button,
localPos,
Vector2.zero(),
));
event.preventDefault();
}
void _onMouseWheel(web.WheelEvent event) {
final localPos = _getLocalPositionFromEvent(event);
final delta = event.deltaY;
inputHandler.handle(ScrollEvent(
localPosition: localPos,
delta: delta,
));
event.preventDefault();
}
void _onKeyDown(web.KeyboardEvent event) {
PhysicalKey? physicalKey = _getPhysicalKeyFromEvent(event);
LogicalKey? logicalKey = _getLogicalKeyFromEvent(event);
if (physicalKey != null && logicalKey != null) {
inputHandler.handle(KeyEvent(KeyEventType.down, logicalKey, physicalKey));
}
event.preventDefault();
}
void _onKeyUp(web.KeyboardEvent event) {
LogicalKey? logicalKey = _getLogicalKeyFromEvent(event);
PhysicalKey? physicalKey = _getPhysicalKeyFromEvent(event);
if (physicalKey != null && logicalKey != null) {
inputHandler.handle(KeyEvent(KeyEventType.up, logicalKey, physicalKey));
}
event.preventDefault();
}
void _onTouchStart(web.TouchEvent event) {
for (var touch in event.changedTouches.toList()) {
final pos = _getLocalPositionFromTouch(touch);
_touchPositions[touch.identifier] = pos;
}
final touchCount = event.touches.toList().length;
if (touchCount == 1) {
final touch = event.touches.toList().first;
final pos = _getLocalPositionFromTouch(touch);
inputHandler.handle(TouchEvent(
TouchEventType.tap,
pos,
null,
));
}
if (touchCount >= 2) {
final focalPoint = _calculateFocalPoint(event.touches.toList());
inputHandler.handle(ScaleStartEvent(
numPointers: touchCount,
localFocalPoint: (focalPoint.x, focalPoint.y),
));
}
event.preventDefault();
}
void _onTouchMove(web.TouchEvent event) {
for (var touch in event.changedTouches.toList()) {
final id = touch.identifier;
final currPos = _getLocalPositionFromTouch(touch);
final prevPos = _touchPositions[id];
if (prevPos != null) {
_touchPositions[id] = currPos;
}
}
final touchCount = event.touches.toList().length;
if (touchCount >= 2) {
final touches = event.touches.toList();
final focalPoint = _calculateFocalPoint(touches);
// Calculate scale
final currPositions = touches.map((t) => _getLocalPositionFromTouch(t)).toList();
final prevPositions = touches.map((t) => _touchPositions[t.identifier] ?? _getLocalPositionFromTouch(t)).toList();
final currDist = (currPositions[0] - currPositions[1]).length;
final prevDist = (prevPositions[0] - prevPositions[1]).length;
final scale = prevDist > 0 ? currDist / prevDist : 1.0;
// Calculate focal point delta
final prevFocalPoint = _calculateFocalPoint(touches, prevPositions);
final focalPointDelta = focalPoint - prevFocalPoint;
inputHandler.handle(ScaleUpdateEvent(
numPointers: touchCount,
localFocalPoint: (focalPoint.x, focalPoint.y),
localFocalPointDelta: (focalPointDelta.x, focalPointDelta.y),
rotation: 0.0, // We don't track rotation in the web implementation
scale: scale,
horizontalScale: scale,
verticalScale: scale,
));
}
event.preventDefault();
}
void _onTouchEnd(web.TouchEvent event) {
for (var touch in event.changedTouches.toList()) {
_touchPositions.remove(touch.identifier);
}
final touchCount = event.touches.toList().length;
inputHandler.handle(ScaleEndEvent(
numPointers: touchCount,
));
event.preventDefault();
}
void _onTouchCancel(web.TouchEvent event) {
for (var touch in event.changedTouches.toList()) {
_touchPositions.remove(touch.identifier);
}
final touchCount = event.touches.toList().length;
inputHandler.handle(ScaleEndEvent(
numPointers: touchCount,
));
event.preventDefault();
}
MouseButton? _getMouseButtonFromEvent(web.MouseEvent event) {
if (event.button == 1 || (event.buttons & 4 != 0)) {
return MouseButton.middle;
} else if (event.button == 0 || (event.buttons & 1 != 0)) {
return MouseButton.left;
} else if (event.button == 2 || (event.buttons & 2 != 0)) {
return MouseButton.right;
}
return null;
}
PhysicalKey? _getPhysicalKeyFromEvent(web.KeyboardEvent event) {
switch (event.code) {
case 'KeyW':
return PhysicalKey.w;
case 'KeyA':
return PhysicalKey.a;
case 'KeyS':
return PhysicalKey.s;
case 'KeyD':
return PhysicalKey.d;
default:
return null;
}
}
LogicalKey? _getLogicalKeyFromEvent(web.KeyboardEvent event) {
switch (event.key) {
case 'KeyW':
return LogicalKey.w;
case 'KeyA':
return LogicalKey.a;
case 'KeyS':
return LogicalKey.s;
case 'KeyD':
return LogicalKey.d;
default:
return null;
}
}
Vector2 _getLocalPositionFromEvent(web.Event event) {
final rect = canvas.getBoundingClientRect();
double clientX = 0, clientY = 0;
if (event is web.MouseEvent) {
clientX = event.clientX.toDouble();
clientY = event.clientY.toDouble();
} else if (event is web.TouchEvent) {
final touch = event.touches.toList().firstOrNull;
if (touch != null) {
clientX = touch.clientX;
clientY = touch.clientY;
}
}
return Vector2(
(clientX - rect.left) * pixelRatio,
(clientY - rect.top) * pixelRatio,
);
}
Vector2 _getLocalPositionFromTouch(web.Touch touch) {
final rect = canvas.getBoundingClientRect();
return Vector2(
(touch.clientX - rect.left) * pixelRatio,
(touch.clientY - rect.top) * pixelRatio,
);
}
Vector2 _calculateFocalPoint(List<web.Touch> touches, [List<Vector2>? positions]) {
if (touches.isEmpty) return Vector2.zero();
final points = positions ?? touches.map((t) => _getLocalPositionFromTouch(t)).toList();
Vector2 sum = Vector2.zero();
for (var point in points) {
sum += point;
}
return sum.scaled(1.0 / points.length);
}
void dispose() {
canvas.removeEventListener('mousedown', _onMouseDown.toJS);
canvas.removeEventListener('mousemove', _onMouseMove.toJS);
canvas.removeEventListener('mouseup', _onMouseUp.toJS);
canvas.removeEventListener('wheel', _onMouseWheel.toJS);
web.window.removeEventListener('keydown', _onKeyDown.toJS);
web.window.removeEventListener('keyup', _onKeyUp.toJS);
canvas.removeEventListener('touchstart', _onTouchStart.toJS);
canvas.removeEventListener('touchmove', _onTouchMove.toJS);
canvas.removeEventListener('touchend', _onTouchEnd.toJS);
canvas.removeEventListener('touchcancel', _onTouchCancel.toJS);
}
}

View File

@@ -1,46 +0,0 @@
plugins {
id "com.android.application"
id "kotlin-android"
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
id "dev.flutter.flutter-gradle-plugin"
}
android {
namespace = "com.example.quickstart"
compileSdk = flutter.compileSdkVersion
ndkVersion = flutter.ndkVersion
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId = "com.example.quickstart"
// You can update the following values to match your application needs.
// For more information, see: https://flutter.dev/to/review-gradle-config.
minSdk = 22
targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
versionName = flutter.versionName
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig = signingConfigs.debug
shrinkResources false
minifyEnabled false
}
}
}
flutter {
source = "../.."
}

View File

@@ -1,48 +0,0 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:label="camera_manipulation"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:taskAffinity=""
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<meta-data
android:name="io.flutter.embedding.android.EnableImpeller"
android:value="false" />
</application>
<!-- Required to query activities that can process text, see:
https://developer.android.com/training/package-visibility and
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
<queries>
<intent>
<action android:name="android.intent.action.PROCESS_TEXT"/>
<data android:mimeType="text/plain"/>
</intent>
</queries>
</manifest>

View File

@@ -1,26 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>App</string>
<key>CFBundleIdentifier</key>
<string>io.flutter.flutter.app</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>App</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>13.0</string>
</dict>
</plist>

View File

@@ -1,88 +0,0 @@
PODS:
- DKImagePickerController/Core (4.3.9):
- DKImagePickerController/ImageDataManager
- DKImagePickerController/Resource
- DKImagePickerController/ImageDataManager (4.3.9)
- DKImagePickerController/PhotoGallery (4.3.9):
- DKImagePickerController/Core
- DKPhotoGallery
- DKImagePickerController/Resource (4.3.9)
- DKPhotoGallery (0.0.19):
- DKPhotoGallery/Core (= 0.0.19)
- DKPhotoGallery/Model (= 0.0.19)
- DKPhotoGallery/Preview (= 0.0.19)
- DKPhotoGallery/Resource (= 0.0.19)
- SDWebImage
- SwiftyGif
- DKPhotoGallery/Core (0.0.19):
- DKPhotoGallery/Model
- DKPhotoGallery/Preview
- SDWebImage
- SwiftyGif
- DKPhotoGallery/Model (0.0.19):
- SDWebImage
- SwiftyGif
- DKPhotoGallery/Preview (0.0.19):
- DKPhotoGallery/Model
- DKPhotoGallery/Resource
- SDWebImage
- SwiftyGif
- DKPhotoGallery/Resource (0.0.19):
- SDWebImage
- SwiftyGif
- file_picker (0.0.1):
- DKImagePickerController/PhotoGallery
- Flutter
- Flutter (1.0.0)
- package_info_plus (0.4.5):
- Flutter
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
- SDWebImage (5.21.1):
- SDWebImage/Core (= 5.21.1)
- SDWebImage/Core (5.21.1)
- SwiftyGif (5.4.5)
- thermion_flutter (0.0.1):
- Flutter
DEPENDENCIES:
- file_picker (from `.symlinks/plugins/file_picker/ios`)
- Flutter (from `Flutter`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
- thermion_flutter (from `.symlinks/plugins/thermion_flutter/ios`)
SPEC REPOS:
trunk:
- DKImagePickerController
- DKPhotoGallery
- SDWebImage
- SwiftyGif
EXTERNAL SOURCES:
file_picker:
:path: ".symlinks/plugins/file_picker/ios"
Flutter:
:path: Flutter
package_info_plus:
:path: ".symlinks/plugins/package_info_plus/ios"
path_provider_foundation:
:path: ".symlinks/plugins/path_provider_foundation/darwin"
thermion_flutter:
:path: ".symlinks/plugins/thermion_flutter/ios"
SPEC CHECKSUMS:
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
package_info_plus: 580e9a5f1b6ca5594e7c9ed5f92d1dfb2a66b5e1
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
SDWebImage: f29024626962457f3470184232766516dee8dfea
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
thermion_flutter: d0c4adbb1de69e5ecc244d70bbde81d8497246b2
PODFILE CHECKSUM: a57f30d18f102dd3ce366b1d62a55ecbef2158e5
COCOAPODS: 1.16.2

View File

@@ -1,733 +0,0 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
F657CCCFB062AF56C7F1E15C /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D988E66CA93AB1163F3B4F2 /* Pods_RunnerTests.framework */; };
F8DC37C0013EE3DC8802435E /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B0831D015898C7047513698C /* Pods_Runner.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 97C146E61CF9000F007C117D /* Project object */;
proxyType = 1;
remoteGlobalIDString = 97C146ED1CF9000F007C117D;
remoteInfo = Runner;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
31D54E0731320192F7631461 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
3680A9DFE5EC3E59C051B544 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
3D988E66CA93AB1163F3B4F2 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
704E1C99CAABFB056933D88F /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
8C0FE5C77038897D844C5D42 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
9CD72080C199DAE3518D4C3D /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
B0831D015898C7047513698C /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
BA68F2C1572D8BC92CC4C4FF /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
97C146EB1CF9000F007C117D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
F8DC37C0013EE3DC8802435E /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
FA72758808529BDB8770545F /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
F657CCCFB062AF56C7F1E15C /* Pods_RunnerTests.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
0DB20859A61D425430A5D097 /* Frameworks */ = {
isa = PBXGroup;
children = (
B0831D015898C7047513698C /* Pods_Runner.framework */,
3D988E66CA93AB1163F3B4F2 /* Pods_RunnerTests.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
331C8082294A63A400263BE5 /* RunnerTests */ = {
isa = PBXGroup;
children = (
331C807B294A618700263BE5 /* RunnerTests.swift */,
);
path = RunnerTests;
sourceTree = "<group>";
};
4A129A4D3EB41F9DE0778AAC /* Pods */ = {
isa = PBXGroup;
children = (
704E1C99CAABFB056933D88F /* Pods-Runner.debug.xcconfig */,
3680A9DFE5EC3E59C051B544 /* Pods-Runner.release.xcconfig */,
8C0FE5C77038897D844C5D42 /* Pods-Runner.profile.xcconfig */,
31D54E0731320192F7631461 /* Pods-RunnerTests.debug.xcconfig */,
BA68F2C1572D8BC92CC4C4FF /* Pods-RunnerTests.release.xcconfig */,
9CD72080C199DAE3518D4C3D /* Pods-RunnerTests.profile.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
};
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
9740EEB31CF90195004384FC /* Generated.xcconfig */,
);
name = Flutter;
sourceTree = "<group>";
};
97C146E51CF9000F007C117D = {
isa = PBXGroup;
children = (
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
331C8082294A63A400263BE5 /* RunnerTests */,
4A129A4D3EB41F9DE0778AAC /* Pods */,
0DB20859A61D425430A5D097 /* Frameworks */,
);
sourceTree = "<group>";
};
97C146EF1CF9000F007C117D /* Products */ = {
isa = PBXGroup;
children = (
97C146EE1CF9000F007C117D /* Runner.app */,
331C8081294A63A400263BE5 /* RunnerTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
97C146FA1CF9000F007C117D /* Main.storyboard */,
97C146FD1CF9000F007C117D /* Assets.xcassets */,
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
97C147021CF9000F007C117D /* Info.plist */,
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
);
path = Runner;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
331C8080294A63A400263BE5 /* RunnerTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
buildPhases = (
78F05AF37D9E628BE6E89ABD /* [CP] Check Pods Manifest.lock */,
331C807D294A63A400263BE5 /* Sources */,
331C807F294A63A400263BE5 /* Resources */,
FA72758808529BDB8770545F /* Frameworks */,
);
buildRules = (
);
dependencies = (
331C8086294A63A400263BE5 /* PBXTargetDependency */,
);
name = RunnerTests;
productName = RunnerTests;
productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
97C146ED1CF9000F007C117D /* Runner */ = {
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
C7C2718364AC4E2451407065 /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
6DA127E3193C7EF5F7B6B4C0 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = Runner;
productName = Runner;
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = YES;
LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
331C8080294A63A400263BE5 = {
CreatedOnToolsVersion = 14.0;
TestTargetID = 97C146ED1CF9000F007C117D;
};
97C146ED1CF9000F007C117D = {
CreatedOnToolsVersion = 7.3.1;
LastSwiftMigration = 1100;
};
};
};
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 97C146E51CF9000F007C117D;
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
97C146ED1CF9000F007C117D /* Runner */,
331C8080294A63A400263BE5 /* RunnerTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
331C807F294A63A400263BE5 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
97C146EC1CF9000F007C117D /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
);
name = "Thin Binary";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
};
6DA127E3193C7EF5F7B6B4C0 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
78F05AF37D9E628BE6E89ABD /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Run Script";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
C7C2718364AC4E2451407065 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
331C807D294A63A400263BE5 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
97C146EA1CF9000F007C117D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
331C8086294A63A400263BE5 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 97C146ED1CF9000F007C117D /* Runner */;
targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C146FB1CF9000F007C117D /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C147001CF9000F007C117D /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
249021D3217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Profile;
};
249021D4217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = 979UK3QQJ3;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.quickstart;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Profile;
};
331C8088294A63A400263BE5 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 31D54E0731320192F7631461 /* Pods-RunnerTests.debug.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.example.quickstart.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
};
name = Debug;
};
331C8089294A63A400263BE5 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = BA68F2C1572D8BC92CC4C4FF /* Pods-RunnerTests.release.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.example.quickstart.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
};
name = Release;
};
331C808A294A63A400263BE5 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9CD72080C199DAE3518D4C3D /* Pods-RunnerTests.profile.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.example.quickstart.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
};
name = Profile;
};
97C147031CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
97C147041CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
97C147061CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = 979UK3QQJ3;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.quickstart;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Debug;
};
97C147071CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = 979UK3QQJ3;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.quickstart;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
331C8088294A63A400263BE5 /* Debug */,
331C8089294A63A400263BE5 /* Release */,
331C808A294A63A400263BE5 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147031CF9000F007C117D /* Debug */,
97C147041CF9000F007C117D /* Release */,
249021D3217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147061CF9000F007C117D /* Debug */,
97C147071CF9000F007C117D /* Release */,
249021D4217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 97C146E61CF9000F007C117D /* Project object */;
}

View File

@@ -1,101 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1510"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
<TestableReference
skipped = "NO"
parallelizable = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "331C8080294A63A400263BE5"
BuildableName = "RunnerTests.xctest"
BlueprintName = "RunnerTests"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Profile"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@@ -1,114 +0,0 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';
import 'package:thermion_flutter/thermion_flutter.dart';
class Cup extends StatefulWidget {
const Cup({super.key});
@override
State<Cup> createState() => _CupState();
}
class _CupState extends State<Cup> {
bool _isLoading = true;
String? _modelPath, _modelUri;
String _statusMessage = "正在加载本地模型...";
@override
void initState() {
super.initState();
_loadLocalModel();
}
// 从应用支持目录加载模型
Future<void> _loadLocalModel() async {
try {
setState(() {
_statusMessage = "获取本地模型路径...";
});
final supportDir = await getApplicationSupportDirectory();
final modelFile = File(p.join(supportDir.path, 'cup', 'model.gltf'));
String modelPath =
File(p.join(supportDir.path, 'cup', 'model.gltf')).absolute.path;
final cupDir = Directory('${supportDir.path}/cup');
final modelUri = File('${cupDir.path}/model.gltf').uri.toString();
print('加载本地模modelPath: $modelPath');
print('加载本地模modelUri: $modelUri');
if (await modelFile.exists()) {
setState(() {
_modelPath = modelPath;
_modelUri = modelUri;
_isLoading = false;
_statusMessage = "本地模型加载完成";
});
} else {
setState(() {
_isLoading = false;
_statusMessage = "本地模型文件不存在";
});
}
} catch (e) {
print('加载本地模型失败: $e');
setState(() {
_isLoading = false;
_statusMessage = "加载失败: $e";
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('本地模型查看'),
),
body: _isLoading
? Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const CircularProgressIndicator(),
const SizedBox(height: 16),
Text(_statusMessage),
],
),
)
: _modelPath == null
? Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.error, size: 48, color: Colors.red),
const SizedBox(height: 16),
Text(_statusMessage),
const SizedBox(height: 16),
ElevatedButton(
onPressed: _loadLocalModel,
child: const Text('重试'),
),
],
),
)
: ViewerWidget(
// assetPath: "file://$_modelPath",
assetPath: _modelUri,
skyboxPath: "assets/default_env_skybox.ktx",
iblPath: "assets/default_env_ibl.ktx",
transformToUnitCube: true,
initialCameraPosition: Vector3(0, 0, 6),
background: Colors.grey[200],
manipulatorType: ManipulatorType.ORBIT,
initial: const Center(
child: CircularProgressIndicator(),
),
),
);
}
}

View File

@@ -1,142 +0,0 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';
import 'package:thermion_flutter/thermion_flutter.dart';
// import 'package:thermion_dart/src/viewer/src/thermion_viewer_base.dart';
class CupPage1 extends StatelessWidget {
const CupPage1({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(children: [
Positioned.fill(
child: ViewerWidget(
assetPath: "assets/cup/model.gltf",
skyboxPath: "assets/default_env_skybox.ktx",
iblPath: "assets/default_env_ibl.ktx",
transformToUnitCube: true,
initialCameraPosition: Vector3(0, 0, 6),
background: Colors.blue,
manipulatorType: ManipulatorType.ORBIT,
onViewerAvailable: (viewer) async {
await Future.delayed(const Duration(seconds: 5));
await viewer.removeSkybox();
},
initial: Container(
color: Colors.grey,
),
))
]));
}
}
class CupPage extends StatefulWidget {
const CupPage({super.key});
@override
State<CupPage> createState() => _CupPageState();
}
class _CupPageState extends State<CupPage> {
bool _isLoading = true;
String? _modelPath, modelUri;
String _statusMessage = "正在加载本地模型...";
@override
void initState() {
super.initState();
_loadLocalModel();
}
// 从应用支持目录加载模型
Future<void> _loadLocalModel() async {
try {
setState(() {
_statusMessage = "获取本地模型路径...";
});
final supportDir = await getApplicationSupportDirectory();
final modelFile = File(p.join(supportDir.path, 'cup', 'model.gltf'));
String modelPath =
File(p.join(supportDir.path, 'cup', 'model.gltf')).absolute.path;
final cupDir = Directory('${supportDir.path}/cup');
final modelUri = File('${cupDir.path}/model.gltf').uri;
print('加载本地模modelPath: $modelPath');
print('加载本地模modelUri: $modelUri');
if (await modelFile.exists()) {
setState(() {
_modelPath = modelPath;
_isLoading = false;
_statusMessage = "本地模型加载完成";
});
} else {
setState(() {
_isLoading = false;
_statusMessage = "本地模型文件不存在";
});
}
} catch (e) {
print('加载本地模型失败: $e');
setState(() {
_isLoading = false;
_statusMessage = "加载失败: $e";
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('本地模型查看'),
),
body: _isLoading
? Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const CircularProgressIndicator(),
const SizedBox(height: 16),
Text(_statusMessage),
],
),
)
: _modelPath == null
? Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.error, size: 48, color: Colors.red),
const SizedBox(height: 16),
Text(_statusMessage),
const SizedBox(height: 16),
ElevatedButton(
onPressed: _loadLocalModel,
child: const Text('重试'),
),
],
),
)
: ViewerWidget(
assetPath: "file://$_modelPath",
// assetPath: modelUri,
skyboxPath: "assets/default_env_skybox.ktx",
iblPath: "assets/default_env_ibl.ktx",
transformToUnitCube: true,
initialCameraPosition: Vector3(0, 0, 6),
background: Colors.grey[200],
manipulatorType: ManipulatorType.ORBIT,
initial: const Center(
child: CircularProgressIndicator(),
),
),
);
}
}

View File

@@ -1,570 +0,0 @@
import 'dart:convert';
import 'dart:io';
import 'package:animations/utils/binary_manager.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';
import 'cup.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
// 初始化3D模型资源
try {
await BinaryManager.initializeAppResources();
print('3D模型资源初始化成功');
} catch (e) {
print('无法初始化3D模型资源: $e');
}
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: '3D模型纹理替换',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: ModelViewerWithTextureReplace(),
);
}
}
class ModelViewerWithTextureReplace extends StatefulWidget {
const ModelViewerWithTextureReplace({super.key});
@override
State<ModelViewerWithTextureReplace> createState() =>
_ModelViewerWithTextureReplaceState();
}
class _ModelViewerWithTextureReplaceState
extends State<ModelViewerWithTextureReplace> {
bool _isLoading = true;
String? _modelPath;
String? _texturePath;
int _keyValue = 0;
String _statusMessage = "正在加载模型...";
bool _isReplacingTexture = false;
File? _selectedImage;
@override
void initState() {
super.initState();
_load3DModels();
// _loadModel();
}
// 加载3D模型文件
Future<void> _load3DModels() async {
try {
setState(() {
_statusMessage = "获取模型路径...";
});
// 使用BinaryManager获取3D模型文件路径
// final supportDir = await getApplicationSupportDirectory();
// final cupDir = Directory('${supportDir.path}/cup');
// final modelFile = File('${cupDir.path}/model.gltf');
final modelPath = await BinaryManager.get3DModelPath("model.gltf");
final texturePath = await BinaryManager.get3DModelPath("texture.jpg");
// print("路径: $modelPath");
// print("文件是否存在: ${await File(modelPath).exists()}");
// print("文件路径: ${await File(modelPath).uri}");
//
// setState(() {
// _modelPath = File(modelPath).uri.toString(); // 确保是本地路径
// });
// if (!await File(modelPath).exists()) {
// print("❌ 模型文件不存在: $modelPath");
// }
// if (!await File(texturePath).exists()) {
// print("❌ 纹理文件不存在: $texturePath");
// }
print('modelPath=${modelPath}\ntexturePath=${texturePath}');
setState(() {
_modelPath = modelPath;
_texturePath = texturePath;
_isLoading = false;
_statusMessage = "加载完成";
});
} catch (e) {
print('加载3D模型失败: $e');
setState(() {
_isLoading = false;
_statusMessage = "加载失败: $e";
});
}
}
// 使用FilePicker选择新纹理
Future<void> _pickNewTexture() async {
if (_isReplacingTexture || _texturePath == null) return;
setState(() {
_isReplacingTexture = true;
_statusMessage = "正在选择纹理文件...";
});
try {
// 选择图片文件
FilePickerResult? result = await FilePicker.platform.pickFiles(
type: FileType.image,
allowMultiple: false,
);
if (result == null ||
result.files.isEmpty ||
result.files.single.path == null) {
setState(() {
_statusMessage = "取消选择";
});
return;
}
_selectedImage = File(result.files.single.path!);
final selectedFile = result.files.single;
final fileExtension = p.extension(selectedFile.path!).toLowerCase();
// 可选:仅允许特定图片格式
if (!['.jpg', '.jpeg', '.png'].contains(fileExtension)) {
setState(() {
_statusMessage = "仅支持 JPG / PNG 格式纹理";
});
return;
}
final newTexture = File(selectedFile.path!);
final supportDir = await getApplicationSupportDirectory();
final modelDir = p.join(supportDir.path, 'cup');
final modelPath = p.join(modelDir, 'model.gltf');
final modelFile = File(modelPath);
if (!await newTexture.exists()) {
setState(() {
_statusMessage = "所选纹理文件不存在";
});
return;
}
// 复制新纹理为固定名 new.jpg 到模型目录
final newTexturePath = p.join(modelDir, 'new.jpg');
await newTexture.copy(newTexturePath);
_texturePath = newTexturePath;
// 修改 GLTF 文件
if (await modelFile.exists()) {
String gltfContent = await modelFile.readAsString();
// ✅ 修复 GLTF 中非法负号格式(例如 "- 0.123" => "-0.123"
gltfContent = gltfContent.replaceAllMapped(
RegExp(r'-\s+(\d+(\.\d+)?)'),
(match) => '-${match.group(1)}',
);
final gltfJson = jsonDecode(gltfContent);
// 安全修改 images[0].uri
if (gltfJson['images'] != null && gltfJson['images'].isNotEmpty) {
gltfJson['images'][0]['uri'] = './new.jpg';
}
// 可选:修改 textures[0].name
if (gltfJson['textures'] != null && gltfJson['textures'].isNotEmpty) {
gltfJson['textures'][0]['name'] = 'new.jpg';
}
// 写回更新后的内容
final updatedContent =
const JsonEncoder.withIndent(' ').convert(gltfJson);
await modelFile.writeAsString(updatedContent);
print('GLTF文件已成功更新');
// 重建模型视图
setState(() {
_keyValue++;
_statusMessage = "纹理已更新为 new.jpg";
});
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('纹理已成功更新为 new.jpg')),
);
} else {
print('GLTF文件不存在: $modelPath');
setState(() {
_statusMessage = "GLTF文件不存在";
});
}
} catch (e) {
print('更换纹理失败: $e');
setState(() {
_statusMessage = "更换纹理失败: $e";
});
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('更换纹理失败: $e')),
);
} finally {
setState(() {
_isReplacingTexture = false;
});
}
}
// 重置纹理到原始状态
Future<void> _resetTexture() async {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Cup(),
// builder: (context) => CupPage(),
),
);
return;
if (_isReplacingTexture || _texturePath == null) return;
setState(() {
_isReplacingTexture = true;
_statusMessage = "正在重置纹理...";
});
try {
// 检查备份文件是否存在
final backupTexturePath = '${_texturePath!}.backup';
final backupFile = File(backupTexturePath);
if (await backupFile.exists()) {
// 恢复备份文件
await backupFile.copy(_texturePath!);
// 给渲染器一点时间来处理文件变化
await Future.delayed(const Duration(milliseconds: 500));
// 强制重建ViewerWidget以应用恢复的纹理
setState(() {
_keyValue++;
_statusMessage = "纹理已重置";
});
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('纹理已重置到原始状态')),
);
} else {
setState(() {
_statusMessage = "没有备份文件可恢复";
});
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('没有备份文件可恢复')),
);
}
} catch (e) {
print('重置纹理失败: $e');
setState(() {
_statusMessage = "重置纹理失败: $e";
});
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('重置纹理失败: $e')),
);
} finally {
setState(() {
_isReplacingTexture = false;
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('3D模型纹理替换'),
actions: [
IconButton(
icon: const Icon(Icons.texture),
onPressed: _isReplacingTexture ? null : _pickNewTexture,
tooltip: '更换纹理',
),
],
),
body: _isLoading
? Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const CircularProgressIndicator(),
const SizedBox(height: 16),
Text(_statusMessage),
],
),
)
: _modelPath == null
? Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.error, size: 48, color: Colors.red),
const SizedBox(height: 16),
const Text('加载模型失败'),
const SizedBox(height: 16),
ElevatedButton(
onPressed: _load3DModels,
child: const Text('重试'),
),
],
),
)
: Column(
children: [
if (_selectedImage != null)
Container(
width: 300,
height: 300,
decoration: BoxDecoration(
border: Border.all(color: Colors.blue, width: 2),
borderRadius: BorderRadius.circular(12),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Image.file(
_selectedImage!,
fit: BoxFit.cover,
),
),
),
// Expanded(
// child: ViewerWidget(
// key: ValueKey(_keyValue),
// assetPath: "file://$_modelPath",
// skyboxPath: "assets/default_env_skybox.ktx",
// iblPath: "assets/default_env_ibl.ktx",
// transformToUnitCube: true,
// initialCameraPosition: Vector3(0, 0, 6),
// background: Colors.grey[200],
// manipulatorType: ManipulatorType.ORBIT,
// initial: const Center(
// child: CircularProgressIndicator(),
// ),
// ),
// ),
Container(
padding: const EdgeInsets.all(16),
color: Colors.grey[100],
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton.icon(
icon: const Icon(Icons.texture),
label: const Text('选择纹理图片'),
onPressed: _isReplacingTexture
? null
: _pickNewTexture,
),
ElevatedButton.icon(
icon: const Icon(Icons.refresh),
label: const Text('3d查看'),
onPressed:
_isReplacingTexture ? null : _resetTexture,
),
],
),
const SizedBox(height: 8),
Text(
_statusMessage,
style: TextStyle(
color: Colors.grey[600],
fontStyle: FontStyle.italic,
),
),
],
),
),
],
),
);
}
}
/*
import 'dart:async';
import 'package:animations/cup_page.dart';
import 'package:logging/logging.dart';
import 'package:flutter/material.dart' hide View;
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 Animation Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const CupPage(),
);
}
}
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 _inputHandler;
ThermionViewer? _thermionViewer;
ThermionAsset? _asset;
final _droneUri = "assets/cup/model.gltf";
final _cubeUri = "assets/cube_with_morph_targets.glb";
String? _loaded;
final gltfAnimations = <String>[];
int selectedGltfAnimation = -1;
Future _load(String? uri) async {
if (_asset != null) {
await _thermionViewer!.destroyAsset(_asset!);
_asset = null;
}
_loaded = uri;
if (uri != null) {
_asset = await _thermionViewer!.loadGltf(uri);
await _asset!.transformToUnitCube();
final animations = await _asset!.getGltfAnimationNames();
final durations = await Future.wait(List.generate(
animations.length, (i) => _asset!.getGltfAnimationDuration(i)));
final labels = animations
.asMap()
.map((index, animation) =>
MapEntry(index, "$animation (${durations[index]}s"))
.values;
gltfAnimations.clear();
gltfAnimations.addAll(labels);
selectedGltfAnimation = 0;
}
setState(() {});
}
Future _playGltfAnimation() async {
if (selectedGltfAnimation == -1) {
throw Exception();
}
await _asset!.playGltfAnimation(selectedGltfAnimation);
}
Future _stopGltfAnimation() async {
if (selectedGltfAnimation == -1) {
throw Exception();
}
await _asset!.stopGltfAnimation(selectedGltfAnimation);
}
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) async {
_thermionViewer = await ThermionFlutterPlugin.createViewer();
final camera = await _thermionViewer!.getActiveCamera();
await camera.lookAt(Vector3(0, 0, 10));
await _thermionViewer!.loadSkybox("assets/default_env_skybox.ktx");
await _thermionViewer!.loadIbl("assets/default_env_ibl.ktx");
await _thermionViewer!.setPostProcessing(true);
await _thermionViewer!.setRendering(true);
_inputHandler = DelegateInputHandler.fixedOrbit(_thermionViewer!);
await _load(_droneUri);
setState(() {});
});
}
@override
Widget build(BuildContext context) {
if (_thermionViewer == null) {
return Container();
}
return Stack(children: [
Positioned.fill(
child: ThermionListenerWidget(
inputHandler: _inputHandler,
child: ThermionWidget(
viewer: _thermionViewer!,
))),
Card(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
child: Row(children: [
const Text("Asset: "),
DropdownButton<String?>(
value: _loaded,
items: [_droneUri, _cubeUri, null]
.map((uri) => DropdownMenuItem<String?>(
value: uri,
child: Text(
uri ?? "None",
style: const TextStyle(fontSize: 12),
)))
.toList(),
onChanged: _load),
const Text("Animation: "),
DropdownButton<String>(
value: selectedGltfAnimation == -1
? null
: gltfAnimations[selectedGltfAnimation],
items: gltfAnimations
.map((animation) => DropdownMenuItem<String>(
value: animation,
child: Text(
animation,
style: const TextStyle(fontSize: 12),
)))
.toList(),
onChanged: (value) {
if (value == null) {
selectedGltfAnimation = -1;
} else {
selectedGltfAnimation = gltfAnimations.indexOf(value);
}
}),
IconButton(
onPressed: _playGltfAnimation,
icon: const Icon(Icons.play_arrow)),
IconButton(
onPressed: _stopGltfAnimation, icon: const Icon(Icons.stop))
]))),
]);
}
}
*/

View File

@@ -1,284 +0,0 @@
import 'dart:io';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'package:thermion_flutter/thermion_flutter.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: '3D模型纹理替换',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: const ModelViewerScreen(),
);
}
}
class ModelViewerScreen extends StatefulWidget {
const ModelViewerScreen({super.key});
@override
State<ModelViewerScreen> createState() => _ModelViewerScreenState();
}
class _ModelViewerScreenState extends State<ModelViewerScreen> {
bool _isLoading = true;
String? _modelPath;
String? _texturePath;
int _keyValue = 0;
String _statusMessage = "正在加载模型...";
@override
void initState() {
super.initState();
_loadModel();
}
// 加载模型文件到临时目录
Future<void> _loadModel() async {
try {
setState(() {
_statusMessage = "准备模型目录...";
});
final directory = await getApplicationDocumentsDirectory();
final modelDir = Directory('${directory.path}/model');
// 确保目录存在
if (!await modelDir.exists()) {
await modelDir.create(recursive: true);
}
setState(() {
_statusMessage = "加载GLTF文件...";
});
// 加载 .gltf 文件并写入本地
final gltfData =
await DefaultAssetBundle.of(context).load('assets/cup/model.gltf');
final gltfFile = File('${modelDir.path}/model.gltf');
await gltfFile.writeAsBytes(gltfData.buffer.asUint8List());
/// ✅ 打印本地路径(关键)
print('✅ GLTF 本地路径: ${gltfFile.path}');
print('✅ 是否存在: ${await gltfFile.exists()}');
setState(() {
_statusMessage = "加载模型数据...";
});
// 加载 .bin 文件并写入本地
final binData =
await DefaultAssetBundle.of(context).load('assets/cup/model.bin');
final binFile = File('${modelDir.path}/model.bin');
await binFile.writeAsBytes(binData.buffer.asUint8List());
setState(() {
_statusMessage = "加载纹理...";
});
// 加载纹理文件并写入本地
final textureData =
await DefaultAssetBundle.of(context).load('assets/cup/texture.jpg');
final textureFile = File('${modelDir.path}/texture.jpg');
await textureFile.writeAsBytes(textureData.buffer.asUint8List());
/// ✅ 打印纹理路径
print('✅ 纹理本地路径: ${textureFile.path}');
print('✅ 是否存在: ${await textureFile.exists()}');
setState(() {
_modelPath = gltfFile.path;
_texturePath = textureFile.path;
_isLoading = false;
_statusMessage = "加载完成";
});
} catch (e) {
print('❌ 加载模型失败: $e');
setState(() {
_isLoading = false;
_statusMessage = "加载失败: $e";
});
}
}
// 使用FilePicker选择新纹理 - 修复配置错误
Future<void> _pickNewTexture() async {
try {
setState(() {
_statusMessage = "正在选择纹理文件...";
});
// 使用FilePicker选择文件 - 修复配置
// 选项1: 使用FileType.image不能指定allowedExtensions
FilePickerResult? result = await FilePicker.platform.pickFiles(
type: FileType.image,
allowMultiple: false,
);
// 选项2: 如果需要特定扩展名使用FileType.custom
/*
FilePickerResult? result = await FilePicker.platform.pickFiles(
type: FileType.custom,
allowMultiple: false,
allowedExtensions: ['jpg', 'jpeg', 'png', 'bmp', 'tga'],
);
*/
if (result != null &&
result.files.isNotEmpty &&
result.files.single.path != null &&
_texturePath != null) {
setState(() {
_statusMessage = "正在应用新纹理...";
});
// 获取选中的文件
PlatformFile file = result.files.first;
File newTexture = File(file.path!);
// 检查文件是否存在
if (await newTexture.exists()) {
// 复制选中的图片到纹理路径
await newTexture.copy(_texturePath!);
// 强制重建ViewerWidget以应用新纹理
setState(() {
_keyValue++;
_statusMessage = "纹理已更新";
});
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('纹理已成功更新')),
);
} else {
setState(() {
_statusMessage = "文件不存在";
});
}
} else {
setState(() {
_statusMessage = "取消选择";
});
}
} catch (e) {
print('更换纹理失败: $e');
setState(() {
_statusMessage = "更换纹理失败";
});
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('更换纹理失败: $e')),
);
}
return;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('3D模型纹理替换'),
actions: [
IconButton(
icon: const Icon(Icons.texture),
onPressed: _pickNewTexture,
tooltip: '更换纹理',
),
],
),
body: _isLoading
? Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const CircularProgressIndicator(),
const SizedBox(height: 16),
Text(_statusMessage),
],
),
)
: _modelPath == null
? Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.error, size: 48, color: Colors.red),
const SizedBox(height: 16),
const Text('加载模型失败'),
const SizedBox(height: 16),
ElevatedButton(
onPressed: _loadModel,
child: const Text('重试'),
),
],
),
)
: Column(
children: [
Expanded(
child: ViewerWidget(
key: ValueKey(_keyValue),
assetPath: _modelPath!,
skyboxPath: "assets/default_env_skybox.ktx",
iblPath: "assets/default_env_ibl.ktx",
transformToUnitCube: true,
initialCameraPosition: Vector3(0, 0, 6),
background: Colors.grey[200],
manipulatorType: ManipulatorType.ORBIT,
initial: const Center(
child: CircularProgressIndicator(),
),
),
),
Container(
padding: const EdgeInsets.all(16),
color: Colors.grey[100],
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton.icon(
icon: const Icon(Icons.texture),
label: const Text('选择纹理图片'),
onPressed: _pickNewTexture,
),
ElevatedButton.icon(
icon: const Icon(Icons.refresh),
label: const Text('重置视图'),
onPressed: () {
setState(() {
_keyValue++;
});
},
),
],
),
const SizedBox(height: 8),
Text(
_statusMessage,
style: TextStyle(
color: Colors.grey[600],
fontStyle: FontStyle.italic,
),
),
],
),
),
],
),
);
}
}

View File

@@ -1,190 +0,0 @@
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';
import 'package:thermion_flutter/thermion_flutter.dart';
class LocalModelViewer extends StatefulWidget {
@override
_LocalModelViewerState createState() => _LocalModelViewerState();
}
class _LocalModelViewerState extends State<LocalModelViewer> {
ThermionViewer? _viewer;
ThermionAsset? _asset;
bool _isLoading = true;
bool _hasError = false;
String _statusMessage = "初始化中...";
@override
void initState() {
super.initState();
ThermionFlutterPlugin.createViewer().then((viewer) async {
_viewer = viewer;
_loadLocalModel(); // 在 viewer 初始化之后再加载模型
});
}
Future<void> _loadLocalModel() async {
try {
setState(() {
_isLoading = true;
_statusMessage = "获取本地模型路径...";
});
final supportDir = await getApplicationSupportDirectory();
final modelDir = p.join(supportDir.path, 'cup');
final modelPath = p.join(modelDir, 'model.gltf');
final modelFile = File(modelPath);
if (await modelFile.exists()) {
// 检查二进制文件
final binPath = p.join(modelDir, 'model.bin');
final binFile = File(binPath);
if (!await binFile.exists()) {
throw Exception("二进制文件不存在: $binPath");
}
// 检查文件大小
final binSize = await binFile.length();
if (binSize == 0) {
throw Exception("二进制文件为空");
}
// 检查纹理文件
final texturePath = p.join(modelDir, 'texture.jpg');
final textureFile = File(texturePath);
if (!await textureFile.exists()) {
throw Exception("纹理文件不存在: $texturePath");
}
setState(() {
_statusMessage = "读取和修改模型数据...";
});
// 读取GLTF文件内容
String gltfContent = await modelFile.readAsString();
// 修改纹理路径(去掉"./"前缀)
gltfContent = gltfContent.replaceAll('"./texture.jpg"', '"new.jpg"');
// 转换为字节数组
Uint8List gltfBytes = Uint8List.fromList(utf8.encode(gltfContent));
// 使用绝对路径作为资源URI
final resourceUri = "file://${Directory(modelDir).absolute.path}";
setState(() {
_statusMessage = "加载模型中...";
});
final asset = await _viewer?.loadGltfFromBuffer(
gltfBytes,
resourceUri: resourceUri,
addToScene: true,
);
setState(() {
_asset = asset;
_isLoading = false;
_statusMessage = "模型加载完成";
});
} else {
setState(() {
_isLoading = false;
_statusMessage = "本地模型文件不存在";
});
}
} catch (e) {
print('加载本地模型失败: $e');
setState(() {
_isLoading = false;
_hasError = true;
_statusMessage = "加载失败: $e";
});
}
}
@override
Widget build(BuildContext context) {
if (_isLoading) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircularProgressIndicator(),
SizedBox(height: 16),
Text(_statusMessage),
],
),
);
}
if (_hasError || _viewer == null) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.error_outline, color: Colors.red, size: 48),
SizedBox(height: 16),
Text("加载3D模型失败"),
Text(_statusMessage, style: TextStyle(color: Colors.red)),
SizedBox(height: 16),
ElevatedButton(
onPressed: _loadLocalModel,
child: Text("重试"),
),
],
),
);
}
return Scaffold(
appBar: AppBar(
title: const Text('本地模型查看'),
),
body: ThermionListenerWidget(
inputHandler: DelegateInputHandler.fixedOrbit(_viewer!),
child: ThermionWidget(
viewer: _viewer!,
showFpsCounter: true, // 可选显示FPS计数器
),
),
);
// 使用ThermionWidget显示3D内容
return ThermionListenerWidget(
inputHandler: DelegateInputHandler.fixedOrbit(_viewer!),
child: ThermionWidget(
viewer: _viewer!,
showFpsCounter: true, // 可选显示FPS计数器
),
);
}
Future<void> deleteModelFile() async {
// 获取应用支持目录
final supportDir = await getApplicationSupportDirectory();
// 构建 model.gltf 的完整路径
final modelFile = File(p.join(supportDir.path, 'cup', 'model.gltf'));
// 检查文件是否存在,然后删除
if (await modelFile.exists()) {
await modelFile.delete();
print('model.gltf 已删除');
} else {
print('model.gltf 文件不存在');
}
}
@override
void dispose() {
// deleteModelFile();
// 清理资源
_viewer?.dispose();
super.dispose();
}
}

View File

@@ -1,405 +0,0 @@
import 'dart:convert';
import 'dart:io';
import 'package:flutter/services.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';
class BinaryManager {
/// 当前应用版本(用于初始化检查)
static String? _currentVersion;
/// 获取当前应用版本
static Future<String> _getCurrentVersion() async {
if (_currentVersion == null) {
final packageInfo = await PackageInfo.fromPlatform();
_currentVersion = '${packageInfo.version}+${packageInfo.buildNumber}';
}
return _currentVersion!;
}
/// 检查是否已完成初始化(基于版本号)
static Future<bool> isInitialized() async {
final supportDir = await getApplicationSupportDirectory();
final currentVersion = await _getCurrentVersion();
final initMarker = File(
p.join(supportDir.path, '.initialized_$currentVersion'),
);
return await initMarker.exists();
}
/// 标记初始化完成(文件名包含版本号)
static Future<void> markInitialized() async {
final supportDir = await getApplicationSupportDirectory();
final currentVersion = await _getCurrentVersion();
final initMarker = File(
p.join(supportDir.path, '.initialized_$currentVersion'),
);
await initMarker.writeAsString('${DateTime.now().toIso8601String()}\n');
}
/// 从assets目录提取文件到指定路径
static Future<void> _extractAsset(String assetPath, String localPath) async {
final localFile = File(localPath);
try {
// 从assets中读取数据
final ByteData data = await rootBundle.load(assetPath);
final List<int> bytes = data.buffer.asUint8List();
// 确保目录存在
final dir = Directory(p.dirname(localPath));
if (!await dir.exists()) {
await dir.create(recursive: true);
}
// 写入本地文件
await localFile.writeAsBytes(bytes);
print('成功提取文件: $assetPath -> $localPath');
} catch (e) {
print('提取资源文件失败 $assetPath: $e');
rethrow;
}
}
/// 初始化应用程序资源 - 将所有必要的assets迁移到系统文件夹
static Future<void> initializeAppResources() async {
final currentVersion = await _getCurrentVersion();
if (await isInitialized()) {
print('应用程序资源已初始化,当前版本: $currentVersion');
return;
}
try {
// 迁移shell脚本
await _migrateShellScript();
// 迁移二进制文件
await _migrateBinaries();
// 迁移模型文件
await _migrateModels();
// 迁移3D模型文件
await migrate3DModels();
// 标记初始化完成
await markInitialized();
print('应用程序资源初始化完成');
} catch (e) {
print('应用程序资源初始化失败: $e');
rethrow;
}
}
/// 迁移3D模型文件
static Future<void> migrate3DModels() async {
print('开始迁移3D模型文件...');
final supportDir = await getApplicationSupportDirectory();
final models3dDir = Directory(p.join(supportDir.path, 'cup'));
// 创建3D模型目录
if (!await models3dDir.exists()) {
await models3dDir.create(recursive: true);
}
// 3D模型文件列表
final model3dFiles = ['model.gltf', 'model.bin', 'texture.jpg'];
// 迁移所有3D模型文件
for (final modelFile in model3dFiles) {
try {
// if (modelFile == 'model.gltf') {
// // 对于GLTF文件我们需要修改内容
// await _extractAndModifyGltfAsset(
// 'assets/cup/$modelFile',
// p.join(models3dDir.path, modelFile),
// );
// } else {
// 对于其他文件,直接复制
await _extractAsset(
'assets/cup/$modelFile',
p.join(models3dDir.path, modelFile),
);
// }
} catch (e) {
print('迁移3D模型文件失败 $modelFile: $e');
// 继续迁移其他模型文件
}
}
print('3D模型文件迁移完成');
}
static Future<void> _extractAndModifyGltfAsset(
String assetPath, String targetPath) async {
try {
// 读取资源文件内容
final byteData = await rootBundle.load(assetPath);
final buffer = byteData.buffer;
final gltfContent = utf8.decode(
buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
// 修改纹理路径(去掉"./"前缀)
final modifiedGltfContent =
gltfContent.replaceAll('"./texture.jpg"', '"texture.jpg"');
// 写入修改后的内容到目标文件
final file = File(targetPath);
await file.writeAsBytes(utf8.encode(modifiedGltfContent));
print('已修改并迁移: $assetPath -> $targetPath');
} catch (e) {
print('提取并修改GLTF资源失败: $e');
rethrow;
}
}
static Future<void> _migrateShellScript() async {
print('开始迁移脚本文件...');
final supportDir = await getApplicationSupportDirectory();
// 迁移 Shell 脚本 (macOS/Linux)
final shellScriptPath = p.join(supportDir.path, 'upscale_to_8k_single.sh');
await _extractAsset('assets/upscale_to_8k_single.sh', shellScriptPath);
// 设置脚本执行权限(仅限 macOS/Linux
if (Platform.isMacOS || Platform.isLinux) {
try {
final result = await Process.run('chmod', ['+x', shellScriptPath]);
if (result.exitCode == 0) {
print('成功设置Shell脚本执行权限: $shellScriptPath');
} else {
print('设置Shell脚本执行权限失败: ${result.stderr}');
}
} catch (e) {
print('设置Shell脚本权限异常: $e');
}
}
print('脚本文件迁移完成');
}
/// 迁移二进制文件
static Future<void> _migrateBinaries() async {
print('开始迁移二进制文件...');
final supportDir = await getApplicationSupportDirectory();
final binDir = Directory(p.join(supportDir.path, 'bin'));
// 创建bin目录
if (!await binDir.exists()) {
await binDir.create(recursive: true);
}
// macOS 二进制文件
final macBinDir = Directory(p.join(binDir.path, 'macos'));
if (!await macBinDir.exists()) {
await macBinDir.create(recursive: true);
}
await _extractAsset(
'assets/bin/mac/upscayl-bin',
p.join(macBinDir.path, 'upscayl-bin'),
);
// Windows 二进制文件
final winBinDir = Directory(p.join(binDir.path, 'windows'));
if (!await winBinDir.exists()) {
await winBinDir.create(recursive: true);
}
await _extractAsset(
'assets/bin/windows/upscayl-bin.exe',
p.join(winBinDir.path, 'upscayl-bin.exe'),
);
await _extractAsset(
'assets/bin/windows/vcomp140.dll',
p.join(winBinDir.path, 'vcomp140.dll'),
);
await _extractAsset(
'assets/bin/windows/vcomp140d.dll',
p.join(winBinDir.path, 'vcomp140d.dll'),
);
// 设置 macOS/Linux 二进制文件执行权限
if (Platform.isMacOS || Platform.isLinux) {
final binPath = p.join(macBinDir.path, 'upscayl-bin');
try {
final result = await Process.run('chmod', ['+x', binPath]);
if (result.exitCode == 0) {
print('成功设置执行权限: $binPath');
} else {
print('设置执行权限失败: ${result.stderr}');
}
} catch (e) {
print('设置权限异常: $e');
}
}
print('二进制文件迁移完成');
}
/// 迁移模型文件
static Future<void> _migrateModels() async {
print('开始迁移模型文件...');
final supportDir = await getApplicationSupportDirectory();
final modelsDir = Directory(p.join(supportDir.path, 'models'));
// 创建models目录
if (!await modelsDir.exists()) {
await modelsDir.create(recursive: true);
}
// 模型文件列表
final modelFiles = [
'high-fidelity-4x.bin',
'high-fidelity-4x.param',
'digital-art-4x.bin',
'digital-art-4x.param',
'remacri-4x.bin',
'remacri-4x.param',
'ultrasharp-4x.bin',
'ultrasharp-4x.param',
'upscayl-standard-4x.bin',
'upscayl-standard-4x.param',
'ultramix-balanced-4x.bin',
'ultramix-balanced-4x.param',
'upscayl-lite-4x.bin',
'upscayl-lite-4x.param',
];
// 迁移所有模型文件
for (final modelFile in modelFiles) {
try {
await _extractAsset(
'assets/models/$modelFile',
p.join(modelsDir.path, modelFile),
);
} catch (e) {
print('迁移模型文件失败 $modelFile: $e');
// 继续迁移其他模型文件
}
}
print('模型文件迁移完成');
}
/// 获取模型文件目录路径
static Future<String> getModelsPath() async {
final supportDir = await getApplicationSupportDirectory();
return p.join(supportDir.path, 'cup', "model.gltf");
}
/// 获取3D模型文件目录路径
static Future<String> get3DModelsPath() async {
final supportDir = await getApplicationSupportDirectory();
return p.join(supportDir.path, 'cup');
}
static Future<Map<String, dynamic>> readLocalJson() async {
// 获取应用支持目录(默认在 ~/Library/Application Support/
final appSupportDir = await getApplicationSupportDirectory();
final targetDir = Directory('${appSupportDir.path}/cup');
// 检查目录是否存在,若不存在则创建
if (!await targetDir.exists()) {
await targetDir.create(recursive: true);
}
print('file=${targetDir.path}/model.gltf');
// 构建 JSON 文件路径
final file = File('${targetDir.path}/model.gltf');
if (await file.exists()) {
final content = await file.readAsString();
return jsonDecode(content);
} else {
throw Exception('JSON 文件不存在');
}
}
/// 获取特定的3D模型文件路径
static Future<String> get3DModelPath(String filename) async {
final models3dPath = await get3DModelsPath();
return p.join(models3dPath, filename);
}
/// 获取脚本文件路径 (仅适用于macOS/Linux)
static Future<String> getScriptPath() async {
if (Platform.isWindows) {
throw UnsupportedError('Windows平台已使用专门的UpscaleWindowsService不再需要脚本文件');
}
final supportDir = await getApplicationSupportDirectory();
final scriptName = 'upscale_to_8k_single.sh';
final scriptPath = p.join(supportDir.path, scriptName);
final scriptFile = File(scriptPath);
if (!await scriptFile.exists()) {
throw FileSystemException(
'脚本文件不存在: $scriptPath\n请确保应用程序已正确初始化资源',
scriptPath,
);
}
return scriptPath;
}
/// 获取二进制文件路径
static Future<String> getBinaryPath() async {
final supportDir = await getApplicationSupportDirectory();
String platformDir;
String binaryName;
if (Platform.isMacOS) {
platformDir = 'macos';
binaryName = 'upscayl-bin';
} else if (Platform.isWindows) {
platformDir = 'windows';
binaryName = 'upscayl-bin.exe';
} else if (Platform.isLinux) {
platformDir = 'macos'; // Linux 使用 macOS 的二进制文件
binaryName = 'upscayl-bin';
} else {
throw UnsupportedError('不支持的操作系统: ${Platform.operatingSystem}');
}
final binPath = p.join(supportDir.path, 'bin', platformDir, binaryName);
// 检查文件是否存在
final binFile = File(binPath);
if (!await binFile.exists()) {
throw FileSystemException('二进制文件不存在: $binPath\n请确保应用程序已正确初始化资源', binPath);
}
return binPath;
}
/// 设置脚本执行权限
static Future<void> setScriptExecutable(String scriptPath) async {
// 设置脚本执行权限(仅限 macOS/Linux
if (Platform.isMacOS || Platform.isLinux) {
try {
final result = await Process.run('chmod', ['+x', scriptPath]);
if (result.exitCode == 0) {
print('成功设置脚本执行权限: $scriptPath');
} else {
print('设置脚本执行权限失败: ${result.stderr}');
}
} catch (e) {
print('设置脚本权限异常: $e');
}
}
// Windows 不需要设置执行权限
}
}

View File

@@ -1,204 +0,0 @@
import 'dart:io';
import 'package:flutter/services.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';
class ModelManager {
/// 当前应用版本(用于初始化检查)
static String? _currentVersion;
/// 获取当前应用版本
static Future<String> _getCurrentVersion() async {
if (_currentVersion == null) {
final packageInfo = await PackageInfo.fromPlatform();
_currentVersion = '${packageInfo.version}+${packageInfo.buildNumber}';
}
return _currentVersion!;
}
/// 检查3D模型资源是否已完成初始化基于版本号
static Future<bool> isInitialized() async {
final supportDir = await getApplicationSupportDirectory();
final currentVersion = await _getCurrentVersion();
final initMarker = File(
p.join(supportDir.path, '3d_models', '.initialized_$currentVersion'),
);
return await initMarker.exists();
}
/// 标记3D模型资源初始化完成
static Future<void> markInitialized() async {
final supportDir = await getApplicationSupportDirectory();
final currentVersion = await _getCurrentVersion();
final modelsDir = Directory(p.join(supportDir.path, '3d_models'));
if (!await modelsDir.exists()) {
await modelsDir.create(recursive: true);
}
final initMarker = File(
p.join(modelsDir.path, '.initialized_$currentVersion'),
);
await initMarker.writeAsString('${DateTime.now().toIso8601String()}\n');
}
/// 从assets目录提取文件到指定路径
static Future<void> _extractAsset(String assetPath, String localPath) async {
final localFile = File(localPath);
final localDir = Directory(p.dirname(localPath));
// 确保目录存在
if (!await localDir.exists()) {
await localDir.create(recursive: true);
}
try {
// 从assets中读取数据
final ByteData data = await rootBundle.load(assetPath);
final List<int> bytes = data.buffer.asUint8List();
// 写入本地文件
await localFile.writeAsBytes(bytes);
print('成功提取3D模型文件: $assetPath -> $localPath');
} catch (e) {
print('提取3D模型资源文件失败 $assetPath: $e');
rethrow;
}
}
/// 初始化3D模型资源
static Future<void> initializeAppResources() async {
final currentVersion = await _getCurrentVersion();
if (await isInitialized()) {
print('3D模型资源已初始化当前版本: $currentVersion');
return;
}
try {
// 迁移模型文件
await _migrateModels();
// 标记初始化完成
await markInitialized();
print('3D模型资源初始化完成');
} catch (e) {
print('3D模型资源初始化失败: $e');
rethrow;
}
}
/// 迁移3D模型文件
/// 迁移3D模型文件
static Future<void> _migrateModels() async {
print('开始迁移3D模型文件...');
final supportDir = await getApplicationSupportDirectory();
final modelsDir = Directory(p.join(supportDir.path, 'models'));
// 创建3D模型目录
if (!await modelsDir.exists()) {
await modelsDir.create(recursive: true);
}
// 创建cup子目录
final cupDir = Directory(p.join(modelsDir.path, 'cup'));
if (!await cupDir.exists()) {
await cupDir.create(recursive: true);
}
// 3D模型文件列表 - 修正路径
final modelFiles = [
'cup/model.gltf',
'cup/model.bin',
'cup/texture.jpg',
];
// 迁移所有3D模型文件
for (final modelFile in modelFiles) {
try {
// 确保源文件路径正确
final assetPath = 'assets/$modelFile';
// 检查资源是否存在
try {
await rootBundle.load(assetPath);
} catch (e) {
print('资源文件不存在: $assetPath');
continue;
}
await _extractAsset(
assetPath,
p.join(modelsDir.path, modelFile),
);
} catch (e) {
print('迁移3D模型文件失败 $modelFile: $e');
// 继续迁移其他模型文件
}
}
print('3D模型文件迁移完成');
}
/// 获取3D模型文件目录路径
static Future<String> getModelsPath() async {
final supportDir = await getApplicationSupportDirectory();
return p.join(supportDir.path, 'models/cup/');
}
/// 获取特定3D模型文件的路径
static Future<String> getModelFilePath(String relativePath) async {
final modelsPath = await getModelsPath();
final filePath = p.join(modelsPath, relativePath);
final file = File(filePath);
if (!await file.exists()) {
throw FileSystemException(
'3D模型文件不存在: $filePath\n请确保应用程序已正确初始化3D模型资源',
filePath,
);
}
return filePath;
}
/// 获取GLTF模型文件路径
static Future<String> getGltfModelPath() async {
return getModelFilePath('cup/model.gltf');
}
/// 获取BIN模型文件路径
static Future<String> getBinModelPath() async {
return getModelFilePath('cup/model.bin');
}
/// 获取纹理文件路径
static Future<String> getTexturePath() async {
return getModelFilePath('cup/texture.jpg');
}
/// 更新纹理文件
static Future<void> updateTexture(File newTextureFile) async {
try {
final texturePath = await getTexturePath();
final textureFile = File(texturePath);
// 删除旧纹理文件
if (await textureFile.exists()) {
await textureFile.delete();
}
// 复制新纹理文件
await newTextureFile.copy(texturePath);
print('纹理文件更新成功: $texturePath');
} catch (e) {
print('更新纹理文件失败: $e');
rethrow;
}
}
}

View File

@@ -1,18 +0,0 @@
//
// Generated file. Do not edit.
//
import FlutterMacOS
import Foundation
import file_picker
import package_info_plus
import path_provider_foundation
import thermion_flutter
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FilePickerPlugin.register(with: registry.registrar(forPlugin: "FilePickerPlugin"))
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
SwiftThermionFlutterPlugin.register(with: registry.registrar(forPlugin: "SwiftThermionFlutterPlugin"))
}

View File

@@ -1,41 +0,0 @@
PODS:
- file_picker (0.0.1):
- FlutterMacOS
- FlutterMacOS (1.0.0)
- package_info_plus (0.0.1):
- FlutterMacOS
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
- thermion_flutter (0.0.1):
- FlutterMacOS
DEPENDENCIES:
- file_picker (from `Flutter/ephemeral/.symlinks/plugins/file_picker/macos`)
- FlutterMacOS (from `Flutter/ephemeral`)
- package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`)
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
- thermion_flutter (from `Flutter/ephemeral/.symlinks/plugins/thermion_flutter/macos`)
EXTERNAL SOURCES:
file_picker:
:path: Flutter/ephemeral/.symlinks/plugins/file_picker/macos
FlutterMacOS:
:path: Flutter/ephemeral
package_info_plus:
:path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos
path_provider_foundation:
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin
thermion_flutter:
:path: Flutter/ephemeral/.symlinks/plugins/thermion_flutter/macos
SPEC CHECKSUMS:
file_picker: 7584aae6fa07a041af2b36a2655122d42f578c1a
FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1
package_info_plus: a8a591e70e87ce97ce5d21b2594f69cea9e0312f
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
thermion_flutter: d5d52ef933321eedbee6c4ddda4259c8cbcc84ed
PODFILE CHECKSUM: 1888651be91a8ad58692c1add9ce24279fd4e950
COCOAPODS: 1.16.2

View File

@@ -1,803 +0,0 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objects = {
/* Begin PBXAggregateTarget section */
33CC111A2044C6BA0003C045 /* Flutter Assemble */ = {
isa = PBXAggregateTarget;
buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */;
buildPhases = (
33CC111E2044C6BF0003C045 /* ShellScript */,
);
dependencies = (
);
name = "Flutter Assemble";
productName = FLX;
};
/* End PBXAggregateTarget section */
/* Begin PBXBuildFile section */
331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; };
335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; };
33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; };
33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
56F02897B820ADA2DE043C9B /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 93162ABED09E78126BD3CDE5 /* Pods_Runner.framework */; };
62AA8D6F0977DC04C5F3E47D /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9491FF37DFB0425E4EA0B397 /* Pods_RunnerTests.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 33CC10E52044A3C60003C045 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 33CC10EC2044A3C60003C045;
remoteInfo = Runner;
};
33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 33CC10E52044A3C60003C045 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 33CC111A2044C6BA0003C045;
remoteInfo = FLX;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
33CC110E2044A8840003C045 /* Bundle Framework */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
);
name = "Bundle Framework";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = "<group>"; };
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = "<group>"; };
33CC10ED2044A3C60003C045 /* quickstart.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = quickstart.app; sourceTree = BUILT_PRODUCTS_DIR; };
33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = "<group>"; };
33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = "<group>"; };
33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = "<group>"; };
33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = "<group>"; };
33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = "<group>"; };
33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = "<group>"; };
33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = "<group>"; };
33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = "<group>"; };
33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = "<group>"; };
4DE9521732D230B91BB45C73 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
5C2B9597C21FB64F23F75F32 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
61CABADBE923C1C839256779 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
89306E3842C70B544B3CD9C8 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
914F20B2B6A55F4538F4FECA /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
93162ABED09E78126BD3CDE5 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
9491FF37DFB0425E4EA0B397 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
E5EDF04F05E94A7EC21CBB16 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
331C80D2294CF70F00263BE5 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
62AA8D6F0977DC04C5F3E47D /* Pods_RunnerTests.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
33CC10EA2044A3C60003C045 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
56F02897B820ADA2DE043C9B /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
0AD0DB307687B659B7995D8A /* Pods */ = {
isa = PBXGroup;
children = (
4DE9521732D230B91BB45C73 /* Pods-Runner.debug.xcconfig */,
89306E3842C70B544B3CD9C8 /* Pods-Runner.release.xcconfig */,
61CABADBE923C1C839256779 /* Pods-Runner.profile.xcconfig */,
914F20B2B6A55F4538F4FECA /* Pods-RunnerTests.debug.xcconfig */,
5C2B9597C21FB64F23F75F32 /* Pods-RunnerTests.release.xcconfig */,
E5EDF04F05E94A7EC21CBB16 /* Pods-RunnerTests.profile.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
};
331C80D6294CF71000263BE5 /* RunnerTests */ = {
isa = PBXGroup;
children = (
331C80D7294CF71000263BE5 /* RunnerTests.swift */,
);
path = RunnerTests;
sourceTree = "<group>";
};
33BA886A226E78AF003329D5 /* Configs */ = {
isa = PBXGroup;
children = (
33E5194F232828860026EE4D /* AppInfo.xcconfig */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
333000ED22D3DE5D00554162 /* Warnings.xcconfig */,
);
path = Configs;
sourceTree = "<group>";
};
33CC10E42044A3C60003C045 = {
isa = PBXGroup;
children = (
33FAB671232836740065AC1E /* Runner */,
33CEB47122A05771004F2AC0 /* Flutter */,
331C80D6294CF71000263BE5 /* RunnerTests */,
33CC10EE2044A3C60003C045 /* Products */,
D73912EC22F37F3D000D13A0 /* Frameworks */,
0AD0DB307687B659B7995D8A /* Pods */,
);
sourceTree = "<group>";
};
33CC10EE2044A3C60003C045 /* Products */ = {
isa = PBXGroup;
children = (
33CC10ED2044A3C60003C045 /* quickstart.app */,
331C80D5294CF71000263BE5 /* RunnerTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
33CC11242044D66E0003C045 /* Resources */ = {
isa = PBXGroup;
children = (
33CC10F22044A3C60003C045 /* Assets.xcassets */,
33CC10F42044A3C60003C045 /* MainMenu.xib */,
33CC10F72044A3C60003C045 /* Info.plist */,
);
name = Resources;
path = ..;
sourceTree = "<group>";
};
33CEB47122A05771004F2AC0 /* Flutter */ = {
isa = PBXGroup;
children = (
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */,
33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */,
33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */,
33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */,
);
path = Flutter;
sourceTree = "<group>";
};
33FAB671232836740065AC1E /* Runner */ = {
isa = PBXGroup;
children = (
33CC10F02044A3C60003C045 /* AppDelegate.swift */,
33CC11122044BFA00003C045 /* MainFlutterWindow.swift */,
33E51913231747F40026EE4D /* DebugProfile.entitlements */,
33E51914231749380026EE4D /* Release.entitlements */,
33CC11242044D66E0003C045 /* Resources */,
33BA886A226E78AF003329D5 /* Configs */,
);
path = Runner;
sourceTree = "<group>";
};
D73912EC22F37F3D000D13A0 /* Frameworks */ = {
isa = PBXGroup;
children = (
93162ABED09E78126BD3CDE5 /* Pods_Runner.framework */,
9491FF37DFB0425E4EA0B397 /* Pods_RunnerTests.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
331C80D4294CF70F00263BE5 /* RunnerTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
buildPhases = (
465FA95FF24452F333D1C1C1 /* [CP] Check Pods Manifest.lock */,
331C80D1294CF70F00263BE5 /* Sources */,
331C80D2294CF70F00263BE5 /* Frameworks */,
331C80D3294CF70F00263BE5 /* Resources */,
);
buildRules = (
);
dependencies = (
331C80DA294CF71000263BE5 /* PBXTargetDependency */,
);
name = RunnerTests;
productName = RunnerTests;
productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
33CC10EC2044A3C60003C045 /* Runner */ = {
isa = PBXNativeTarget;
buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
ED773E1A7DA74470DCD044C6 /* [CP] Check Pods Manifest.lock */,
33CC10E92044A3C60003C045 /* Sources */,
33CC10EA2044A3C60003C045 /* Frameworks */,
33CC10EB2044A3C60003C045 /* Resources */,
33CC110E2044A8840003C045 /* Bundle Framework */,
3399D490228B24CF009A79C7 /* ShellScript */,
CB1E43C40756BBF229674223 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
dependencies = (
33CC11202044C79F0003C045 /* PBXTargetDependency */,
);
name = Runner;
productName = Runner;
productReference = 33CC10ED2044A3C60003C045 /* quickstart.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
33CC10E52044A3C60003C045 /* Project object */ = {
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = YES;
LastSwiftUpdateCheck = 0920;
LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
331C80D4294CF70F00263BE5 = {
CreatedOnToolsVersion = 14.0;
TestTargetID = 33CC10EC2044A3C60003C045;
};
33CC10EC2044A3C60003C045 = {
CreatedOnToolsVersion = 9.2;
LastSwiftMigration = 1100;
ProvisioningStyle = Automatic;
SystemCapabilities = {
com.apple.Sandbox = {
enabled = 1;
};
};
};
33CC111A2044C6BA0003C045 = {
CreatedOnToolsVersion = 9.2;
ProvisioningStyle = Manual;
};
};
};
buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 33CC10E42044A3C60003C045;
productRefGroup = 33CC10EE2044A3C60003C045 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
33CC10EC2044A3C60003C045 /* Runner */,
331C80D4294CF70F00263BE5 /* RunnerTests */,
33CC111A2044C6BA0003C045 /* Flutter Assemble */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
331C80D3294CF70F00263BE5 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
33CC10EB2044A3C60003C045 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */,
33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
3399D490228B24CF009A79C7 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n";
};
33CC111E2044C6BF0003C045 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
Flutter/ephemeral/FlutterInputs.xcfilelist,
);
inputPaths = (
Flutter/ephemeral/tripwire,
);
outputFileListPaths = (
Flutter/ephemeral/FlutterOutputs.xcfilelist,
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire";
};
465FA95FF24452F333D1C1C1 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
CB1E43C40756BBF229674223 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
ED773E1A7DA74470DCD044C6 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
331C80D1294CF70F00263BE5 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
33CC10E92044A3C60003C045 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */,
33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */,
335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
331C80DA294CF71000263BE5 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 33CC10EC2044A3C60003C045 /* Runner */;
targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */;
};
33CC11202044C79F0003C045 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */;
targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
33CC10F42044A3C60003C045 /* MainMenu.xib */ = {
isa = PBXVariantGroup;
children = (
33CC10F52044A3C60003C045 /* Base */,
);
name = MainMenu.xib;
path = Runner;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
331C80DB294CF71000263BE5 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 914F20B2B6A55F4538F4FECA /* Pods-RunnerTests.debug.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.example.quickstart.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/quickstart.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/quickstart";
};
name = Debug;
};
331C80DC294CF71000263BE5 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 5C2B9597C21FB64F23F75F32 /* Pods-RunnerTests.release.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.example.quickstart.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/quickstart.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/quickstart";
};
name = Release;
};
331C80DD294CF71000263BE5 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = E5EDF04F05E94A7EC21CBB16 /* Pods-RunnerTests.profile.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.example.quickstart.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/quickstart.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/quickstart";
};
name = Profile;
};
338D0CE9231458BD00FA5F75 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.15;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
};
name = Profile;
};
338D0CEA231458BD00FA5F75 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 13.0;
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_VERSION = 5.0;
};
name = Profile;
};
338D0CEB231458BD00FA5F75 /* Profile */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Manual;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Profile;
};
33CC10F92044A3C60003C045 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.15;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
33CC10FA2044A3C60003C045 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.15;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
};
name = Release;
};
33CC10FC2044A3C60003C045 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 13.0;
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
};
name = Debug;
};
33CC10FD2044A3C60003C045 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 13.0;
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_VERSION = 5.0;
};
name = Release;
};
33CC111C2044C6BA0003C045 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Manual;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
33CC111D2044C6BA0003C045 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
331C80DB294CF71000263BE5 /* Debug */,
331C80DC294CF71000263BE5 /* Release */,
331C80DD294CF71000263BE5 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
33CC10F92044A3C60003C045 /* Debug */,
33CC10FA2044A3C60003C045 /* Release */,
338D0CE9231458BD00FA5F75 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
33CC10FC2044A3C60003C045 /* Debug */,
33CC10FD2044A3C60003C045 /* Release */,
338D0CEA231458BD00FA5F75 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = {
isa = XCConfigurationList;
buildConfigurations = (
33CC111C2044C6BA0003C045 /* Debug */,
33CC111D2044C6BA0003C045 /* Release */,
338D0CEB231458BD00FA5F75 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 33CC10E52044A3C60003C045 /* Project object */;
}

View File

@@ -1,103 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1510"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
BuildableName = "quickstart.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
BuildableName = "quickstart.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
<TestableReference
skipped = "NO"
parallelizable = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "331C80D4294CF70F00263BE5"
BuildableName = "RunnerTests.xctest"
BlueprintName = "RunnerTests"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
enableGPUFrameCaptureMode = "1"
enableGPUShaderValidationMode = "2"
showGraphicsOverview = "Yes"
logGraphicsOverview = "Yes"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
BuildableName = "quickstart.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Profile"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
BuildableName = "quickstart.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

Some files were not shown because too many files have changed in this diff Show More