Compare commits
18 Commits
thermion_d
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d16474784d | ||
|
|
1c07d576d3 | ||
|
|
961b2ae1ee | ||
|
|
a7ac118899 | ||
|
|
d92ad4ef12 | ||
|
|
437e91e7bd | ||
|
|
e169bf6c41 | ||
|
|
23b060c329 | ||
|
|
5fd0a10630 | ||
|
|
ddfb649733 | ||
|
|
ecffc5b62a | ||
|
|
429b8eb93b | ||
|
|
413faec849 | ||
|
|
433b6373a9 | ||
|
|
ad2c5afb7f | ||
|
|
a561c847a7 | ||
|
|
ef7ba24ecc | ||
|
|
ee176d2684 |
24
.github/workflows/dart.yml
vendored
@@ -117,8 +117,28 @@ jobs:
|
|||||||
# D:\a\thermion\thermion\thermion_dart\.dart_tool\thermion_dart\log\build.log
|
# 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
|
/Users/runner/work/thermion/thermion/thermion_dart/.dart_tool/thermion_dart/log/build.log
|
||||||
retention-days: 5
|
retention-days: 5
|
||||||
|
flutter_examples_windows:
|
||||||
|
name: flutter_examples_windows
|
||||||
|
runs-on: windows-latest
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
working-directory: examples/flutter
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Set up Flutter
|
||||||
|
uses: subosito/flutter-action@v2
|
||||||
|
with:
|
||||||
|
channel: master
|
||||||
|
- run: cd quickstart && flutter pub get && flutter build windows
|
||||||
|
- run: cd picking && flutter pub get && flutter build windows
|
||||||
|
- name: Upload logs
|
||||||
|
if: failure() || steps.build.outcome == 'failure'
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: build-logs
|
||||||
|
path: |
|
||||||
|
D:\a\thermion\thermion\thermion_dart\.dart_tool\thermion_dart\log\build.log
|
||||||
|
retention-days: 5
|
||||||
# thermion_dart:
|
# thermion_dart:
|
||||||
# name: thermion_dart
|
# name: thermion_dart
|
||||||
# runs-on: macos-latest
|
# runs-on: macos-latest
|
||||||
|
|||||||
83
CHANGELOG.md
@@ -3,6 +3,89 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
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
|
## 2025-07-08
|
||||||
|
|
||||||
### Changes
|
### Changes
|
||||||
|
|||||||
@@ -79,4 +79,4 @@ Thank you to the following people:
|
|||||||
- @LukasPoque for CI/refactoring work
|
- @LukasPoque for CI/refactoring work
|
||||||
- @alexmercerind for his work on integrating ANGLE textures on Flutter Windows
|
- @alexmercerind for his work on integrating ANGLE textures on Flutter Windows
|
||||||
- @BrutalCoding for documentation fixes
|
- @BrutalCoding for documentation fixes
|
||||||
|
- @chenriji for testing and bug fixes
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ This is a simplified, Flutter-only wrapper around the underlying 3D rendering AP
|
|||||||
|
|
||||||
Follow the steps listed in [Getting Started](./getting_started) to configure your Flutter installation and project.
|
Follow the steps listed in [Getting Started](./getting_started) to configure your Flutter installation and project.
|
||||||
|
|
||||||
|
If you're running Windows, delete the `examples/flutter/quickstart/assets` symlink and copy the `assets` folder from `examples/assets` to `examples/flutter/quickstart/assets`.
|
||||||
|
|
||||||
## Basic Usage
|
## Basic Usage
|
||||||
|
|
||||||
```dart
|
```dart
|
||||||
|
|||||||
BIN
examples/assets/bin/mac/upscayl-bin
Executable file
BIN
examples/assets/bin/windows/upscayl-bin.exe
Normal file
BIN
examples/assets/bin/windows/vcomp140.dll
Normal file
BIN
examples/assets/bin/windows/vcomp140d.dll
Normal file
BIN
examples/assets/cup/model.bin
Normal file
|
After Width: | Height: | Size: 960 KiB |
1
examples/assets/cup/model.gltf
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"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}]}
|
||||||
BIN
examples/assets/cup/new.jpg
Normal file
|
After Width: | Height: | Size: 720 KiB |
BIN
examples/assets/cup/texture.jpg
Normal file
|
After Width: | Height: | Size: 8.2 MiB |
BIN
examples/assets/cup/texture_tmp.jpg
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
examples/assets/image/texture.jpg
Normal file
|
After Width: | Height: | Size: 8.2 MiB |
BIN
examples/assets/models/digital-art-4x.bin
Normal file
270
examples/assets/models/digital-art-4x.param
Normal file
@@ -0,0 +1,270 @@
|
|||||||
|
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
|
||||||
BIN
examples/assets/models/high-fidelity-4x.bin
Normal file
1001
examples/assets/models/high-fidelity-4x.param
Normal file
BIN
examples/assets/models/model.bin
Normal file
|
After Width: | Height: | Size: 960 KiB |
1
examples/assets/models/model.gltf
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"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}]}
|
||||||
BIN
examples/assets/models/remacri-4x.bin
Normal file
1372
examples/assets/models/remacri-4x.param
Normal file
BIN
examples/assets/models/texture.jpg
Normal file
|
After Width: | Height: | Size: 8.2 MiB |
BIN
examples/assets/models/ultramix-balanced-4x.bin
Normal file
1372
examples/assets/models/ultramix-balanced-4x.param
Normal file
BIN
examples/assets/models/ultrasharp-4x.bin
Normal file
1001
examples/assets/models/ultrasharp-4x.param
Normal file
BIN
examples/assets/models/upscayl-lite-4x.bin
Normal file
74
examples/assets/models/upscayl-lite-4x.param
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
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
|
||||||
BIN
examples/assets/models/upscayl-standard-4x.bin
Normal file
1001
examples/assets/models/upscayl-standard-4x.param
Normal file
30
examples/assets/upscale_resize.sh
Executable file
@@ -0,0 +1,30 @@
|
|||||||
|
#!/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
|
||||||
114
examples/assets/upscale_to_8k.sh
Executable file
@@ -0,0 +1,114 @@
|
|||||||
|
#!/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
|
||||||
0
examples/assets/upscale_to_8k_single.bat
Normal file
131
examples/assets/upscale_to_8k_single.sh
Executable file
@@ -0,0 +1,131 @@
|
|||||||
|
#!/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
|
||||||
@@ -21,6 +21,6 @@
|
|||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1.0</string>
|
<string>1.0</string>
|
||||||
<key>MinimumOSVersion</key>
|
<key>MinimumOSVersion</key>
|
||||||
<string>12.0</string>
|
<string>13.0</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -1,22 +1,88 @@
|
|||||||
PODS:
|
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)
|
- 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):
|
- thermion_flutter (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
|
- file_picker (from `.symlinks/plugins/file_picker/ios`)
|
||||||
- Flutter (from `Flutter`)
|
- 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`)
|
- thermion_flutter (from `.symlinks/plugins/thermion_flutter/ios`)
|
||||||
|
|
||||||
|
SPEC REPOS:
|
||||||
|
trunk:
|
||||||
|
- DKImagePickerController
|
||||||
|
- DKPhotoGallery
|
||||||
|
- SDWebImage
|
||||||
|
- SwiftyGif
|
||||||
|
|
||||||
EXTERNAL SOURCES:
|
EXTERNAL SOURCES:
|
||||||
|
file_picker:
|
||||||
|
:path: ".symlinks/plugins/file_picker/ios"
|
||||||
Flutter:
|
Flutter:
|
||||||
:path: 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:
|
thermion_flutter:
|
||||||
:path: ".symlinks/plugins/thermion_flutter/ios"
|
:path: ".symlinks/plugins/thermion_flutter/ios"
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
|
||||||
thermion_flutter: c965e09831858465a1a8df59ff97e40a4d002773
|
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
|
PODFILE CHECKSUM: a57f30d18f102dd3ce366b1d62a55ecbef2158e5
|
||||||
|
|
||||||
COCOAPODS: 1.15.2
|
COCOAPODS: 1.16.2
|
||||||
|
|||||||
@@ -197,6 +197,7 @@
|
|||||||
97C146EC1CF9000F007C117D /* Resources */,
|
97C146EC1CF9000F007C117D /* Resources */,
|
||||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||||
|
6DA127E3193C7EF5F7B6B4C0 /* [CP] Embed Pods Frameworks */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
@@ -284,6 +285,23 @@
|
|||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
|
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 */ = {
|
78F05AF37D9E628BE6E89ABD /* [CP] Check Pods Manifest.lock */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
@@ -436,7 +454,7 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SUPPORTED_PLATFORMS = iphoneos;
|
SUPPORTED_PLATFORMS = iphoneos;
|
||||||
@@ -452,7 +470,7 @@
|
|||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
DEVELOPMENT_TEAM = TM2B4SJXNJ;
|
DEVELOPMENT_TEAM = 979UK3QQJ3;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||||
@@ -567,7 +585,7 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = YES;
|
MTL_ENABLE_DEBUG_INFO = YES;
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
@@ -618,7 +636,7 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SUPPORTED_PLATFORMS = iphoneos;
|
SUPPORTED_PLATFORMS = iphoneos;
|
||||||
@@ -636,7 +654,7 @@
|
|||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
DEVELOPMENT_TEAM = TM2B4SJXNJ;
|
DEVELOPMENT_TEAM = 979UK3QQJ3;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||||
@@ -660,7 +678,7 @@
|
|||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
DEVELOPMENT_TEAM = TM2B4SJXNJ;
|
DEVELOPMENT_TEAM = 979UK3QQJ3;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
<MacroExpansion>
|
<MacroExpansion>
|
||||||
<BuildableReference
|
<BuildableReference
|
||||||
@@ -54,11 +55,13 @@
|
|||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
|
||||||
launchStyle = "0"
|
launchStyle = "0"
|
||||||
useCustomWorkingDirectory = "NO"
|
useCustomWorkingDirectory = "NO"
|
||||||
ignoresPersistentStateOnLaunch = "NO"
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
debugDocumentVersioning = "YES"
|
debugDocumentVersioning = "YES"
|
||||||
debugServiceExtension = "internal"
|
debugServiceExtension = "internal"
|
||||||
|
enableGPUValidationMode = "1"
|
||||||
allowLocationSimulation = "YES">
|
allowLocationSimulation = "YES">
|
||||||
<BuildableProductRunnable
|
<BuildableProductRunnable
|
||||||
runnableDebuggingMode = "0">
|
runnableDebuggingMode = "0">
|
||||||
|
|||||||
114
examples/flutter/animations/lib/cup.dart
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
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(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
142
examples/flutter/animations/lib/cup_page.dart
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
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(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,407 @@
|
|||||||
|
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 'dart:async';
|
||||||
|
import 'package:animations/cup_page.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:flutter/material.dart' hide View;
|
import 'package:flutter/material.dart' hide View;
|
||||||
import 'package:thermion_flutter/thermion_flutter.dart';
|
import 'package:thermion_flutter/thermion_flutter.dart';
|
||||||
@@ -21,7 +424,7 @@ class MyApp extends StatelessWidget {
|
|||||||
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
|
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
|
||||||
useMaterial3: true,
|
useMaterial3: true,
|
||||||
),
|
),
|
||||||
home: const MyHomePage(title: 'Thermion Demo Home Page'),
|
home: const CupPage(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -39,7 +442,7 @@ class _MyHomePageState extends State<MyHomePage> {
|
|||||||
ThermionViewer? _thermionViewer;
|
ThermionViewer? _thermionViewer;
|
||||||
|
|
||||||
ThermionAsset? _asset;
|
ThermionAsset? _asset;
|
||||||
final _droneUri = "assets/BusterDrone/scene.gltf";
|
final _droneUri = "assets/cup/model.gltf";
|
||||||
final _cubeUri = "assets/cube_with_morph_targets.glb";
|
final _cubeUri = "assets/cube_with_morph_targets.glb";
|
||||||
String? _loaded;
|
String? _loaded;
|
||||||
|
|
||||||
@@ -68,7 +471,6 @@ class _MyHomePageState extends State<MyHomePage> {
|
|||||||
gltfAnimations.clear();
|
gltfAnimations.clear();
|
||||||
gltfAnimations.addAll(labels);
|
gltfAnimations.addAll(labels);
|
||||||
selectedGltfAnimation = 0;
|
selectedGltfAnimation = 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
setState(() {});
|
setState(() {});
|
||||||
}
|
}
|
||||||
@@ -165,3 +567,4 @@ class _MyHomePageState extends State<MyHomePage> {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|||||||
284
examples/flutter/animations/lib/main1.dart
Normal file
@@ -0,0 +1,284 @@
|
|||||||
|
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,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
190
examples/flutter/animations/lib/model_viewer.dart
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
405
examples/flutter/animations/lib/utils/binary_manager.dart
Normal file
@@ -0,0 +1,405 @@
|
|||||||
|
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 不需要设置执行权限
|
||||||
|
}
|
||||||
|
}
|
||||||
204
examples/flutter/animations/lib/utils/model_manager.dart
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,8 +5,14 @@
|
|||||||
import FlutterMacOS
|
import FlutterMacOS
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
|
import file_picker
|
||||||
|
import package_info_plus
|
||||||
|
import path_provider_foundation
|
||||||
import thermion_flutter
|
import thermion_flutter
|
||||||
|
|
||||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
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"))
|
SwiftThermionFlutterPlugin.register(with: registry.registrar(forPlugin: "SwiftThermionFlutterPlugin"))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,41 @@
|
|||||||
PODS:
|
PODS:
|
||||||
|
- file_picker (0.0.1):
|
||||||
|
- FlutterMacOS
|
||||||
- FlutterMacOS (1.0.0)
|
- FlutterMacOS (1.0.0)
|
||||||
|
- package_info_plus (0.0.1):
|
||||||
|
- FlutterMacOS
|
||||||
|
- path_provider_foundation (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- FlutterMacOS
|
||||||
- thermion_flutter (0.0.1):
|
- thermion_flutter (0.0.1):
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
|
- file_picker (from `Flutter/ephemeral/.symlinks/plugins/file_picker/macos`)
|
||||||
- FlutterMacOS (from `Flutter/ephemeral`)
|
- 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`)
|
- thermion_flutter (from `Flutter/ephemeral/.symlinks/plugins/thermion_flutter/macos`)
|
||||||
|
|
||||||
EXTERNAL SOURCES:
|
EXTERNAL SOURCES:
|
||||||
|
file_picker:
|
||||||
|
:path: Flutter/ephemeral/.symlinks/plugins/file_picker/macos
|
||||||
FlutterMacOS:
|
FlutterMacOS:
|
||||||
:path: Flutter/ephemeral
|
: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:
|
thermion_flutter:
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/thermion_flutter/macos
|
:path: Flutter/ephemeral/.symlinks/plugins/thermion_flutter/macos
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
|
file_picker: 7584aae6fa07a041af2b36a2655122d42f578c1a
|
||||||
FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1
|
FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1
|
||||||
thermion_flutter: debb51a861788780ce40e11e4400c2e5a8681fdf
|
package_info_plus: a8a591e70e87ce97ce5d21b2594f69cea9e0312f
|
||||||
|
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
|
||||||
|
thermion_flutter: d5d52ef933321eedbee6c4ddda4259c8cbcc84ed
|
||||||
|
|
||||||
PODFILE CHECKSUM: 1888651be91a8ad58692c1add9ce24279fd4e950
|
PODFILE CHECKSUM: 1888651be91a8ad58692c1add9ce24279fd4e950
|
||||||
|
|
||||||
COCOAPODS: 1.15.2
|
COCOAPODS: 1.16.2
|
||||||
|
|||||||
@@ -3,9 +3,19 @@
|
|||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>com.apple.security.app-sandbox</key>
|
<key>com.apple.security.app-sandbox</key>
|
||||||
<true/>
|
<false/>
|
||||||
<key>com.apple.security.cs.allow-jit</key>
|
<key>com.apple.security.cs.allow-jit</key>
|
||||||
<true/>
|
<true/>
|
||||||
|
<key>com.apple.security.files.user-selected.read-write</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.files.downloads.read-write</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.files.pictures.read-write</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.files.bookmarks.app-scope</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.network.client</key>
|
||||||
|
<true/>
|
||||||
<key>com.apple.security.network.server</key>
|
<key>com.apple.security.network.server</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
|
|||||||
@@ -3,6 +3,20 @@
|
|||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>com.apple.security.app-sandbox</key>
|
<key>com.apple.security.app-sandbox</key>
|
||||||
|
<false/>
|
||||||
|
<key>com.apple.security.cs.allow-jit</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.files.user-selected.read-write</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.files.downloads.read-write</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.files.pictures.read-write</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.files.bookmarks.app-scope</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.network.client</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.network.server</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -16,6 +16,12 @@ dependencies:
|
|||||||
win32: 5.5.1
|
win32: 5.5.1
|
||||||
web: 1.0.0
|
web: 1.0.0
|
||||||
thermion_flutter: ^0.2.1-dev.9
|
thermion_flutter: ^0.2.1-dev.9
|
||||||
|
file_picker: ^8.3.2
|
||||||
|
path_provider: ^2.1.5
|
||||||
|
package_info_plus: ^8.0.2
|
||||||
|
path: ^1.8.0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
@@ -40,3 +46,9 @@ flutter:
|
|||||||
- assets/
|
- assets/
|
||||||
- assets/BusterDrone/
|
- assets/BusterDrone/
|
||||||
- assets/BusterDrone/textures/
|
- assets/BusterDrone/textures/
|
||||||
|
- assets/cup/
|
||||||
|
- assets/image/
|
||||||
|
- assets/bin/mac/
|
||||||
|
- assets/bin/windows/
|
||||||
|
- assets/models/
|
||||||
|
- assets/upscale_to_8k_single.sh
|
||||||
103
examples/flutter/camera_manipulation/lib/main.dart
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:logging/logging.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:thermion_flutter/thermion_flutter.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
runApp(const MyApp());
|
||||||
|
Logger.root.onRecord.listen((record) {
|
||||||
|
print(record);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyApp extends StatelessWidget {
|
||||||
|
const MyApp({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return MaterialApp(
|
||||||
|
title: 'Thermion Demo',
|
||||||
|
theme: ThemeData(
|
||||||
|
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
|
||||||
|
useMaterial3: true,
|
||||||
|
),
|
||||||
|
home: const MyHomePage(title: 'Thermion Demo Home Page'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyHomePage extends StatefulWidget {
|
||||||
|
const MyHomePage({super.key, required this.title});
|
||||||
|
final String title;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<MyHomePage> createState() => _MyHomePageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MyHomePageState extends State<MyHomePage> {
|
||||||
|
|
||||||
|
late DelegateInputHandler _fixedOrbitInputHandler;
|
||||||
|
late DelegateInputHandler _freeFlightInputHandler;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||||
|
_thermionViewer = await ThermionFlutterPlugin.createViewer();
|
||||||
|
var assetData = await rootBundle.load("assets/cube.glb");
|
||||||
|
var asset =
|
||||||
|
await _thermionViewer!.loadGltfFromBuffer(assetData.buffer.asUint8List(assetData.offsetInBytes), keepData: true, loadResourcesAsync: true);
|
||||||
|
await _thermionViewer!.loadSkybox("assets/default_env_skybox.ktx");
|
||||||
|
await _thermionViewer!.loadIbl("assets/default_env_ibl.ktx");
|
||||||
|
await _thermionViewer!.setPostProcessing(true);
|
||||||
|
await _thermionViewer!.setRendering(true);
|
||||||
|
|
||||||
|
_fixedOrbitInputHandler =
|
||||||
|
DelegateInputHandler.fixedOrbit(_thermionViewer!)
|
||||||
|
..setActionForType(InputType.MMB_HOLD_AND_MOVE, InputAction.ROTATE)
|
||||||
|
..setActionForType(InputType.SCALE1, InputAction.ROTATE)
|
||||||
|
..setActionForType(InputType.SCALE2, InputAction.ZOOM)
|
||||||
|
..setActionForType(InputType.SCROLLWHEEL, InputAction.ZOOM);
|
||||||
|
|
||||||
|
_freeFlightInputHandler =
|
||||||
|
DelegateInputHandler.flight(_thermionViewer!)
|
||||||
|
..setActionForType(InputType.MMB_HOLD_AND_MOVE, InputAction.ROTATE)
|
||||||
|
..setActionForType(InputType.SCALE1, InputAction.ROTATE)
|
||||||
|
..setActionForType(InputType.SCALE2, InputAction.ZOOM)
|
||||||
|
..setActionForType(InputType.SCROLLWHEEL, InputAction.ZOOM);
|
||||||
|
|
||||||
|
setState(() {});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ThermionViewer? _thermionViewer;
|
||||||
|
|
||||||
|
bool isOrbit = true;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Stack(children: [
|
||||||
|
if (_thermionViewer != null) ...[
|
||||||
|
Positioned.fill(
|
||||||
|
child: ThermionListenerWidget(
|
||||||
|
inputHandler: isOrbit
|
||||||
|
? _fixedOrbitInputHandler : _freeFlightInputHandler,
|
||||||
|
child:ThermionWidget(
|
||||||
|
viewer: _thermionViewer!,
|
||||||
|
))),
|
||||||
|
Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
isOrbit = !isOrbit;
|
||||||
|
setState(() {});
|
||||||
|
},
|
||||||
|
child: Text("Switch to ${isOrbit ? "Free Flight" : "Orbit"}"))
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -108,10 +108,13 @@ fragment {
|
|||||||
1.0
|
1.0
|
||||||
);
|
);
|
||||||
|
|
||||||
color.rgb = (axes.x < 1e-8) ? color.rgb : AXIS_COLOR_X;
|
if(axes.x > 1e-8) {
|
||||||
color.rgb = (axes.z < 1e-8) ? color.rgb : AXIS_COLOR_Z;
|
material.baseColor = vec4(AXIS_COLOR_X, 1.0);
|
||||||
|
} else if(axes.z > 1e-8) {
|
||||||
material.baseColor = color * gridAlpha;
|
material.baseColor = vec4(AXIS_COLOR_Z, 1.0);
|
||||||
|
} else {
|
||||||
|
material.baseColor = color * gridAlpha;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,8 @@
|
|||||||
name: thermion_workspace
|
name: thermion_workspace
|
||||||
packages:
|
packages:
|
||||||
- thermion_dart
|
- thermion_dart
|
||||||
- thermion_flutter/**
|
- thermion_flutter/thermion_flutter_platform_interface
|
||||||
|
- thermion_flutter/thermion_flutter_method_channel
|
||||||
|
- thermion_flutter/thermion_flutter_web
|
||||||
|
- thermion_flutter/thermion_flutter
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,12 @@
|
|||||||
|
## 0.3.3
|
||||||
|
|
||||||
|
- Bump "thermion_dart" to `0.3.3`.
|
||||||
|
|
||||||
|
## 0.3.3-pre
|
||||||
|
|
||||||
|
- **FIX**: fix Windows build.dart.
|
||||||
|
- **FIX**: add nan/negative checks inside setLensProjection.
|
||||||
|
|
||||||
## 0.3.2
|
## 0.3.2
|
||||||
|
|
||||||
- Bump "thermion_dart" to `0.3.2`.
|
- Bump "thermion_dart" to `0.3.2`.
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:archive/archive.dart';
|
import 'package:archive/archive.dart';
|
||||||
import 'package:code_assets/code_assets.dart';
|
import 'package:code_assets/code_assets.dart';
|
||||||
import 'package:hooks/hooks.dart';
|
import 'package:hooks/hooks.dart';
|
||||||
|
import 'package:native_toolchain_c/native_toolchain_c.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
|
|
||||||
import 'package:native_toolchain_c/native_toolchain_c.dart';
|
|
||||||
import 'package:path/path.dart' as path;
|
import 'package:path/path.dart' as path;
|
||||||
|
|
||||||
void main(List<String> args) async {
|
void main(List<String> args) async {
|
||||||
@@ -130,7 +131,7 @@ void main(List<String> args) async {
|
|||||||
|
|
||||||
var frameworks = [];
|
var frameworks = [];
|
||||||
|
|
||||||
if (platform != "windows") {
|
if (targetOS != OS.windows) {
|
||||||
flags.addAll(['-std=c++17']);
|
flags.addAll(['-std=c++17']);
|
||||||
} else {
|
} else {
|
||||||
defines["WIN32"] = "1";
|
defines["WIN32"] = "1";
|
||||||
@@ -193,7 +194,7 @@ void main(List<String> args) async {
|
|||||||
name: packageName,
|
name: packageName,
|
||||||
language: Language.cpp,
|
language: Language.cpp,
|
||||||
assetName: 'thermion_dart.dart',
|
assetName: 'thermion_dart.dart',
|
||||||
sources: platform == "windows" ? [] : sources,
|
sources: targetOS == OS.windows ? [] : sources,
|
||||||
includes: platform == "windows"
|
includes: platform == "windows"
|
||||||
? []
|
? []
|
||||||
: ['native/include', 'native/include/filament'],
|
: ['native/include', 'native/include/filament'],
|
||||||
@@ -219,12 +220,12 @@ void main(List<String> args) async {
|
|||||||
"/I${path.join(pkgRootFilePath, "native", "include", "windows", "vulkan")}",
|
"/I${path.join(pkgRootFilePath, "native", "include", "windows", "vulkan")}",
|
||||||
"@${srcs.uri.toFilePath(windows: true)}",
|
"@${srcs.uri.toFilePath(windows: true)}",
|
||||||
// ...sources,
|
// ...sources,
|
||||||
'/link',
|
// '/link',
|
||||||
"/LIBPATH:$libDir",
|
// "/LIBPATH:$libDir",
|
||||||
'/DLL',
|
// '/DLL',
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
dartBuildFiles: ['hook/build.dart'],
|
libraryDirectories: [libDir],
|
||||||
);
|
);
|
||||||
|
|
||||||
await cbuilder.run(
|
await cbuilder.run(
|
||||||
|
|||||||
@@ -5,11 +5,10 @@ import '../../../utils/src/matrix.dart';
|
|||||||
|
|
||||||
class FFICamera extends Camera<Pointer<TCamera>> {
|
class FFICamera extends Camera<Pointer<TCamera>> {
|
||||||
final Pointer<TCamera> camera;
|
final Pointer<TCamera> camera;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Pointer<TCamera> getNativeHandle() {
|
Pointer<TCamera> getNativeHandle() {
|
||||||
return camera;
|
return camera;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final FFIFilamentApp app;
|
final FFIFilamentApp app;
|
||||||
@@ -92,6 +91,16 @@ class FFICamera extends Camera<Pointer<TCamera>> {
|
|||||||
double far = kFar,
|
double far = kFar,
|
||||||
double aspect = 1.0,
|
double aspect = 1.0,
|
||||||
double focalLength = kFocalLength}) async {
|
double focalLength = kFocalLength}) async {
|
||||||
|
if (near.isNaN ||
|
||||||
|
far.isNaN ||
|
||||||
|
aspect.isNaN ||
|
||||||
|
focalLength.isNaN ||
|
||||||
|
near.isNegative ||
|
||||||
|
far.isNegative ||
|
||||||
|
aspect.isNegative ||
|
||||||
|
focalLength.isNegative) {
|
||||||
|
throw FormatException();
|
||||||
|
}
|
||||||
Camera_setLensProjection(camera, near, far, aspect, focalLength);
|
Camera_setLensProjection(camera, near, far, aspect, focalLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -344,13 +344,14 @@ abstract class ThermionViewer {
|
|||||||
int getCameraCount();
|
int getCameraCount();
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Adds the asset to the scene, meaning the asset will be rendered/visible.
|
/// Adds the asset to the scene. All renderable entities attached to
|
||||||
|
/// the asset will be visible.
|
||||||
///
|
///
|
||||||
Future addToScene(covariant ThermionAsset asset);
|
Future addToScene(covariant ThermionAsset asset);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Removes the asset from the scene, meaning the asset will not be rendered/visible.
|
/// Removes the asset from the scene. None of the renderable entities
|
||||||
/// The asset itself will remain valid.
|
/// attached to the asset will be visible, but the asset itself remains valid.
|
||||||
///
|
///
|
||||||
Future removeFromScene(covariant ThermionAsset asset);
|
Future removeFromScene(covariant ThermionAsset asset);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,6 @@
|
|||||||
#pragma comment(lib, "dracodec.lib")
|
#pragma comment(lib, "dracodec.lib")
|
||||||
#pragma comment(lib, "ibl.lib")
|
#pragma comment(lib, "ibl.lib")
|
||||||
#pragma comment(lib, "ktxreader.lib")
|
#pragma comment(lib, "ktxreader.lib")
|
||||||
#pragma comment(lib, "png.lib")
|
|
||||||
#pragma comment(lib, "z.lib")
|
#pragma comment(lib, "z.lib")
|
||||||
#pragma comment(lib, "stb.lib")
|
#pragma comment(lib, "stb.lib")
|
||||||
#pragma comment(lib, "uberzlib.lib")
|
#pragma comment(lib, "uberzlib.lib")
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include "ThermionWin32.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
namespace thermion {
|
namespace thermion {
|
||||||
extern "C"
|
extern "C"
|
||||||
@@ -16,35 +20,35 @@ enum TProjection {
|
|||||||
typedef enum TProjection TProjection;
|
typedef enum TProjection TProjection;
|
||||||
|
|
||||||
// Camera methods
|
// Camera methods
|
||||||
void Camera_setExposure(TCamera *camera, float aperture, float shutterSpeed, float sensitivity);
|
EMSCRIPTEN_KEEPALIVE void Camera_setExposure(TCamera *camera, float aperture, float shutterSpeed, float sensitivity);
|
||||||
double4x4 Camera_getModelMatrix(TCamera *const camera);
|
EMSCRIPTEN_KEEPALIVE double4x4 Camera_getModelMatrix(TCamera *const camera);
|
||||||
double4x4 Camera_getViewMatrix(TCamera *const camera);
|
EMSCRIPTEN_KEEPALIVE double4x4 Camera_getViewMatrix(TCamera *const camera);
|
||||||
double4x4 Camera_getProjectionMatrix(TCamera *const camera);
|
EMSCRIPTEN_KEEPALIVE double4x4 Camera_getProjectionMatrix(TCamera *const camera);
|
||||||
double4x4 Camera_getCullingProjectionMatrix(TCamera *const camera);
|
EMSCRIPTEN_KEEPALIVE double4x4 Camera_getCullingProjectionMatrix(TCamera *const camera);
|
||||||
void Camera_getFrustum(TCamera *camera, double* out);
|
EMSCRIPTEN_KEEPALIVE void Camera_getFrustum(TCamera *camera, double* out);
|
||||||
void Camera_setProjectionMatrix(TCamera *camera, double *matrix, double near, double far);
|
EMSCRIPTEN_KEEPALIVE void Camera_setProjectionMatrix(TCamera *camera, double *matrix, double near, double far);
|
||||||
void Camera_setProjectionFromFov(TCamera *camera, double fovInDegrees, double aspect, double near, double far, bool horizontal);
|
EMSCRIPTEN_KEEPALIVE void Camera_setProjectionFromFov(TCamera *camera, double fovInDegrees, double aspect, double near, double far, bool horizontal);
|
||||||
double Camera_getFocalLength(TCamera *const camera);
|
EMSCRIPTEN_KEEPALIVE double Camera_getFocalLength(TCamera *const camera);
|
||||||
double4x4 Camera_getViewMatrix(TCamera *const camera);
|
EMSCRIPTEN_KEEPALIVE double4x4 Camera_getViewMatrix(TCamera *const camera);
|
||||||
double4x4 Camera_getModelMatrix(TCamera* camera);
|
EMSCRIPTEN_KEEPALIVE double4x4 Camera_getModelMatrix(TCamera* camera);
|
||||||
void Camera_lookAt(TCamera* camera, double3 eye, double3 focus, double3 up);
|
EMSCRIPTEN_KEEPALIVE void Camera_lookAt(TCamera* camera, double3 eye, double3 focus, double3 up);
|
||||||
|
|
||||||
double Camera_getNear(TCamera *camera);
|
EMSCRIPTEN_KEEPALIVE double Camera_getNear(TCamera *camera);
|
||||||
double Camera_getCullingFar(TCamera *camera);
|
EMSCRIPTEN_KEEPALIVE double Camera_getCullingFar(TCamera *camera);
|
||||||
float Camera_getFov(TCamera *camera, bool horizontal);
|
EMSCRIPTEN_KEEPALIVE float Camera_getFov(TCamera *camera, bool horizontal);
|
||||||
double Camera_getFocusDistance(TCamera *camera);
|
EMSCRIPTEN_KEEPALIVE double Camera_getFocusDistance(TCamera *camera);
|
||||||
void Camera_setFocusDistance(TCamera *camera, float focusDistance);
|
EMSCRIPTEN_KEEPALIVE void Camera_setFocusDistance(TCamera *camera, float focusDistance);
|
||||||
|
|
||||||
void Camera_setCustomProjectionWithCulling(
|
EMSCRIPTEN_KEEPALIVE void Camera_setCustomProjectionWithCulling(
|
||||||
TCamera* camera,
|
TCamera* camera,
|
||||||
double4x4 projectionMatrix,
|
double4x4 projectionMatrix,
|
||||||
double near,
|
double near,
|
||||||
double far
|
double far
|
||||||
);
|
);
|
||||||
void Camera_setModelMatrix(TCamera* camera, double *tModelMatrix);
|
EMSCRIPTEN_KEEPALIVE void Camera_setModelMatrix(TCamera* camera, double *tModelMatrix);
|
||||||
void Camera_setLensProjection(TCamera *camera, double near, double far, double aspect, double focalLength);
|
EMSCRIPTEN_KEEPALIVE void Camera_setLensProjection(TCamera *camera, double near, double far, double aspect, double focalLength);
|
||||||
EntityId Camera_getEntity(TCamera* camera);
|
EMSCRIPTEN_KEEPALIVE EntityId Camera_getEntity(TCamera* camera);
|
||||||
void Camera_setProjection(TCamera *const tCamera, TProjection projection, double left, double right,
|
EMSCRIPTEN_KEEPALIVE void Camera_setProjection(TCamera *const tCamera, TProjection projection, double left, double right,
|
||||||
double bottom, double top,
|
double bottom, double top,
|
||||||
double near, double far);
|
double near, double far);
|
||||||
|
|
||||||
|
|||||||
@@ -16,16 +16,16 @@ namespace thermion
|
|||||||
typedef int32_t EntityId;
|
typedef int32_t EntityId;
|
||||||
typedef void (*FilamentRenderCallback)(void *const owner);
|
typedef void (*FilamentRenderCallback)(void *const owner);
|
||||||
|
|
||||||
void RenderThread_create();
|
EMSCRIPTEN_KEEPALIVE void RenderThread_create();
|
||||||
void RenderThread_destroy();
|
EMSCRIPTEN_KEEPALIVE void RenderThread_destroy();
|
||||||
void RenderThread_requestFrameAsync();
|
EMSCRIPTEN_KEEPALIVE void RenderThread_requestFrameAsync();
|
||||||
void RenderThread_setRenderTicker(TRenderTicker *tRenderTicker);
|
EMSCRIPTEN_KEEPALIVE void RenderThread_setRenderTicker(TRenderTicker *tRenderTicker);
|
||||||
void RenderThread_addTask(void (*task)());
|
EMSCRIPTEN_KEEPALIVE void RenderThread_addTask(void (*task)());
|
||||||
|
|
||||||
void RenderTicker_renderRenderThread(TRenderTicker *tRenderTicker, uint64_t frameTimeInNanos, uint32_t requestId, VoidCallback onComplete);
|
EMSCRIPTEN_KEEPALIVE void RenderTicker_renderRenderThread(TRenderTicker *tRenderTicker, uint64_t frameTimeInNanos, uint32_t requestId, VoidCallback onComplete);
|
||||||
void AnimationManager_createRenderThread(TEngine *tEngine, TScene *tScene, void (*onComplete)(TAnimationManager *));
|
EMSCRIPTEN_KEEPALIVE void AnimationManager_createRenderThread(TEngine *tEngine, TScene *tScene, void (*onComplete)(TAnimationManager *));
|
||||||
|
|
||||||
void Engine_createRenderThread(
|
EMSCRIPTEN_KEEPALIVE void Engine_createRenderThread(
|
||||||
TBackend backend,
|
TBackend backend,
|
||||||
void* platform,
|
void* platform,
|
||||||
void* sharedContext,
|
void* sharedContext,
|
||||||
@@ -33,22 +33,22 @@ namespace thermion
|
|||||||
bool disableHandleUseAfterFreeCheck,
|
bool disableHandleUseAfterFreeCheck,
|
||||||
void (*onComplete)(TEngine *)
|
void (*onComplete)(TEngine *)
|
||||||
);
|
);
|
||||||
void Engine_createRendererRenderThread(TEngine *tEngine, void (*onComplete)(TRenderer *));
|
EMSCRIPTEN_KEEPALIVE void Engine_createRendererRenderThread(TEngine *tEngine, void (*onComplete)(TRenderer *));
|
||||||
void Engine_createSwapChainRenderThread(TEngine *tEngine, void *window, uint64_t flags, void (*onComplete)(TSwapChain *));
|
EMSCRIPTEN_KEEPALIVE void Engine_createSwapChainRenderThread(TEngine *tEngine, void *window, uint64_t flags, void (*onComplete)(TSwapChain *));
|
||||||
void Engine_createHeadlessSwapChainRenderThread(TEngine *tEngine, uint32_t width, uint32_t height, uint64_t flags, void (*onComplete)(TSwapChain *));
|
EMSCRIPTEN_KEEPALIVE void Engine_createHeadlessSwapChainRenderThread(TEngine *tEngine, uint32_t width, uint32_t height, uint64_t flags, void (*onComplete)(TSwapChain *));
|
||||||
void Engine_createCameraRenderThread(TEngine* tEngine, void (*onComplete)(TCamera *));
|
EMSCRIPTEN_KEEPALIVE void Engine_createCameraRenderThread(TEngine* tEngine, void (*onComplete)(TCamera *));
|
||||||
void Engine_createViewRenderThread(TEngine *tEngine, void (*onComplete)(TView *));
|
EMSCRIPTEN_KEEPALIVE void Engine_createViewRenderThread(TEngine *tEngine, void (*onComplete)(TView *));
|
||||||
void Engine_buildMaterialRenderThread(TEngine *tEngine, const uint8_t *materialData, size_t length, void (*onComplete)(TMaterial *));
|
EMSCRIPTEN_KEEPALIVE void Engine_buildMaterialRenderThread(TEngine *tEngine, const uint8_t *materialData, size_t length, void (*onComplete)(TMaterial *));
|
||||||
void Engine_destroyRenderThread(TEngine *tEngine, uint32_t requestId, VoidCallback onComplete);
|
EMSCRIPTEN_KEEPALIVE void Engine_destroyRenderThread(TEngine *tEngine, uint32_t requestId, VoidCallback onComplete);
|
||||||
void Engine_destroySwapChainRenderThread(TEngine *tEngine, TSwapChain *tSwapChain, uint32_t requestId, VoidCallback onComplete);
|
EMSCRIPTEN_KEEPALIVE void Engine_destroySwapChainRenderThread(TEngine *tEngine, TSwapChain *tSwapChain, uint32_t requestId, VoidCallback onComplete);
|
||||||
void Engine_destroyViewRenderThread(TEngine *tEngine, TView *tView, uint32_t requestId, VoidCallback onComplete);
|
EMSCRIPTEN_KEEPALIVE void Engine_destroyViewRenderThread(TEngine *tEngine, TView *tView, uint32_t requestId, VoidCallback onComplete);
|
||||||
void Engine_destroySceneRenderThread(TEngine *tEngine, TScene *tScene, uint32_t requestId, VoidCallback onComplete);
|
EMSCRIPTEN_KEEPALIVE void Engine_destroySceneRenderThread(TEngine *tEngine, TScene *tScene, uint32_t requestId, VoidCallback onComplete);
|
||||||
void Engine_destroyColorGradingRenderThread(TEngine *tEngine, TColorGrading *tColorGrading, uint32_t requestId, VoidCallback onComplete);
|
EMSCRIPTEN_KEEPALIVE void Engine_destroyColorGradingRenderThread(TEngine *tEngine, TColorGrading *tColorGrading, uint32_t requestId, VoidCallback onComplete);
|
||||||
void Engine_destroyMaterialRenderThread(TEngine *tEngine, TMaterial *tMaterial, uint32_t requestId, VoidCallback onComplete);
|
EMSCRIPTEN_KEEPALIVE void Engine_destroyMaterialRenderThread(TEngine *tEngine, TMaterial *tMaterial, uint32_t requestId, VoidCallback onComplete);
|
||||||
void Engine_destroyMaterialInstanceRenderThread(TEngine *tEngine, TMaterialInstance *tMaterialInstance, uint32_t requestId, VoidCallback onComplete);
|
EMSCRIPTEN_KEEPALIVE void Engine_destroyMaterialInstanceRenderThread(TEngine *tEngine, TMaterialInstance *tMaterialInstance, uint32_t requestId, VoidCallback onComplete);
|
||||||
void Engine_destroySkyboxRenderThread(TEngine *tEngine, TSkybox *tSkybox, uint32_t requestId, VoidCallback onComplete);
|
EMSCRIPTEN_KEEPALIVE void Engine_destroySkyboxRenderThread(TEngine *tEngine, TSkybox *tSkybox, uint32_t requestId, VoidCallback onComplete);
|
||||||
void Engine_destroyIndirectLightRenderThread(TEngine *tEngine, TIndirectLight *tIndirectLight, uint32_t requestId, VoidCallback onComplete);
|
EMSCRIPTEN_KEEPALIVE void Engine_destroyIndirectLightRenderThread(TEngine *tEngine, TIndirectLight *tIndirectLight, uint32_t requestId, VoidCallback onComplete);
|
||||||
void Texture_buildRenderThread(TEngine *engine,
|
EMSCRIPTEN_KEEPALIVE void Texture_buildRenderThread(TEngine *engine,
|
||||||
uint32_t width,
|
uint32_t width,
|
||||||
uint32_t height,
|
uint32_t height,
|
||||||
uint32_t depth,
|
uint32_t depth,
|
||||||
@@ -59,25 +59,25 @@ namespace thermion
|
|||||||
TTextureFormat format,
|
TTextureFormat format,
|
||||||
void (*onComplete)(TTexture*)
|
void (*onComplete)(TTexture*)
|
||||||
);
|
);
|
||||||
void Texture_generateMipMapsRenderThread(TTexture *tTexture, TEngine *tEngine, uint32_t requestId, VoidCallback onComplete);
|
EMSCRIPTEN_KEEPALIVE void Texture_generateMipMapsRenderThread(TTexture *tTexture, TEngine *tEngine, uint32_t requestId, VoidCallback onComplete);
|
||||||
void Ktx1Reader_createTextureRenderThread(TEngine *tEngine, TKtx1Bundle *tBundle, uint32_t requestId, VoidCallback onTextureUploadComplete, void (*onComplete)(TTexture *));
|
EMSCRIPTEN_KEEPALIVE void Ktx1Reader_createTextureRenderThread(TEngine *tEngine, TKtx1Bundle *tBundle, uint32_t requestId, VoidCallback onTextureUploadComplete, void (*onComplete)(TTexture *));
|
||||||
|
|
||||||
void Engine_destroyTextureRenderThread(TEngine *engine, TTexture* tTexture, uint32_t requestId, VoidCallback onComplete);
|
EMSCRIPTEN_KEEPALIVE void Engine_destroyTextureRenderThread(TEngine *engine, TTexture* tTexture, uint32_t requestId, VoidCallback onComplete);
|
||||||
void Engine_createFenceRenderThread(TEngine *tEngine, void (*onComplete)(TFence*));
|
EMSCRIPTEN_KEEPALIVE void Engine_createFenceRenderThread(TEngine *tEngine, void (*onComplete)(TFence*));
|
||||||
void Fence_waitAndDestroyRenderThread(TFence *tFence, uint32_t requestId, VoidCallback onComplete);
|
EMSCRIPTEN_KEEPALIVE void Fence_waitAndDestroyRenderThread(TFence *tFence, uint32_t requestId, VoidCallback onComplete);
|
||||||
void Engine_destroyFenceRenderThread(TEngine *tEngine, TFence *tFence, uint32_t requestId, VoidCallback onComplete);
|
EMSCRIPTEN_KEEPALIVE void Engine_destroyFenceRenderThread(TEngine *tEngine, TFence *tFence, uint32_t requestId, VoidCallback onComplete);
|
||||||
void Engine_flushAndWaitRenderThread(TEngine *tEngine, uint32_t requestId, VoidCallback onComplete);
|
EMSCRIPTEN_KEEPALIVE void Engine_flushAndWaitRenderThread(TEngine *tEngine, uint32_t requestId, VoidCallback onComplete);
|
||||||
void Engine_executeRenderThread(TEngine *tEngine, uint32_t requestId, VoidCallback onComplete);
|
EMSCRIPTEN_KEEPALIVE void Engine_executeRenderThread(TEngine *tEngine, uint32_t requestId, VoidCallback onComplete);
|
||||||
void Engine_buildSkyboxRenderThread(TEngine *tEngine, TTexture *tTexture, void (*onComplete)(TSkybox *));
|
EMSCRIPTEN_KEEPALIVE void Engine_buildSkyboxRenderThread(TEngine *tEngine, TTexture *tTexture, void (*onComplete)(TSkybox *));
|
||||||
void Engine_buildIndirectLightFromIrradianceTextureRenderThread(TEngine *tEngine, TTexture *tReflectionsTexture, TTexture* tIrradianceTexture, float intensity, void (*onComplete)(TIndirectLight *));
|
EMSCRIPTEN_KEEPALIVE void Engine_buildIndirectLightFromIrradianceTextureRenderThread(TEngine *tEngine, TTexture *tReflectionsTexture, TTexture* tIrradianceTexture, float intensity, void (*onComplete)(TIndirectLight *));
|
||||||
void Engine_buildIndirectLightFromIrradianceHarmonicsRenderThread(TEngine *tEngine, TTexture *tReflectionsTexture, float *harmonics, float intensity, void (*onComplete)(TIndirectLight *));
|
EMSCRIPTEN_KEEPALIVE void Engine_buildIndirectLightFromIrradianceHarmonicsRenderThread(TEngine *tEngine, TTexture *tReflectionsTexture, float *harmonics, float intensity, void (*onComplete)(TIndirectLight *));
|
||||||
|
|
||||||
void Renderer_setClearOptionsRenderThread(TRenderer *tRenderer, double clearR, double clearG, double clearB, double clearA, uint8_t clearStencil, bool clear, bool discard, uint32_t requestId, VoidCallback onComplete);
|
EMSCRIPTEN_KEEPALIVE void Renderer_setClearOptionsRenderThread(TRenderer *tRenderer, double clearR, double clearG, double clearB, double clearA, uint8_t clearStencil, bool clear, bool discard, uint32_t requestId, VoidCallback onComplete);
|
||||||
void Renderer_beginFrameRenderThread(TRenderer *tRenderer, TSwapChain *tSwapChain, uint64_t frameTimeInNanos, void (*onComplete)(bool));
|
EMSCRIPTEN_KEEPALIVE void Renderer_beginFrameRenderThread(TRenderer *tRenderer, TSwapChain *tSwapChain, uint64_t frameTimeInNanos, void (*onComplete)(bool));
|
||||||
void Renderer_endFrameRenderThread(TRenderer *tRenderer, uint32_t requestId, VoidCallback onComplete);
|
EMSCRIPTEN_KEEPALIVE void Renderer_endFrameRenderThread(TRenderer *tRenderer, uint32_t requestId, VoidCallback onComplete);
|
||||||
void Renderer_renderRenderThread(TRenderer *tRenderer, TView *tView, uint32_t requestId, VoidCallback onComplete);
|
EMSCRIPTEN_KEEPALIVE void Renderer_renderRenderThread(TRenderer *tRenderer, TView *tView, uint32_t requestId, VoidCallback onComplete);
|
||||||
void Renderer_renderStandaloneViewRenderThread(TRenderer *tRenderer, TView *tView, uint32_t requestId, VoidCallback onComplete);
|
EMSCRIPTEN_KEEPALIVE void Renderer_renderStandaloneViewRenderThread(TRenderer *tRenderer, TView *tView, uint32_t requestId, VoidCallback onComplete);
|
||||||
void Renderer_readPixelsRenderThread(
|
EMSCRIPTEN_KEEPALIVE void Renderer_readPixelsRenderThread(
|
||||||
TRenderer *tRenderer,
|
TRenderer *tRenderer,
|
||||||
uint32_t width, uint32_t height, uint32_t xOffset, uint32_t yOffset,
|
uint32_t width, uint32_t height, uint32_t xOffset, uint32_t yOffset,
|
||||||
TRenderTarget *tRenderTarget,
|
TRenderTarget *tRenderTarget,
|
||||||
@@ -87,29 +87,29 @@ namespace thermion
|
|||||||
size_t outLength,
|
size_t outLength,
|
||||||
uint32_t requestId, VoidCallback onComplete);
|
uint32_t requestId, VoidCallback onComplete);
|
||||||
|
|
||||||
void Material_createInstanceRenderThread(TMaterial *tMaterial, void (*onComplete)(TMaterialInstance *));
|
EMSCRIPTEN_KEEPALIVE void Material_createInstanceRenderThread(TMaterial *tMaterial, void (*onComplete)(TMaterialInstance *));
|
||||||
void Material_createImageMaterialRenderThread(TEngine *tEngine, void (*onComplete)(TMaterial *));
|
EMSCRIPTEN_KEEPALIVE void Material_createImageMaterialRenderThread(TEngine *tEngine, void (*onComplete)(TMaterial *));
|
||||||
void Material_createGizmoMaterialRenderThread(TEngine *tEngine, void (*onComplete)(TMaterial *));
|
EMSCRIPTEN_KEEPALIVE void Material_createGizmoMaterialRenderThread(TEngine *tEngine, void (*onComplete)(TMaterial *));
|
||||||
void Material_createOutlineMaterialRenderThread(TEngine *tEngine, void (*onComplete)(TMaterial *));
|
EMSCRIPTEN_KEEPALIVE void Material_createOutlineMaterialRenderThread(TEngine *tEngine, void (*onComplete)(TMaterial *));
|
||||||
|
|
||||||
void ColorGrading_createRenderThread(TEngine *tEngine, TToneMapping toneMapping, void (*callback)(TColorGrading *));
|
EMSCRIPTEN_KEEPALIVE void ColorGrading_createRenderThread(TEngine *tEngine, TToneMapping toneMapping, void (*callback)(TColorGrading *));
|
||||||
void View_pickRenderThread(TView *tView, uint32_t requestId, uint32_t x, uint32_t y, PickCallback callback);
|
EMSCRIPTEN_KEEPALIVE void View_pickRenderThread(TView *tView, uint32_t requestId, uint32_t x, uint32_t y, PickCallback callback);
|
||||||
void View_setColorGradingRenderThread(TView *tView, TColorGrading *tColorGrading, uint32_t requestId, VoidCallback onComplete);
|
EMSCRIPTEN_KEEPALIVE void View_setColorGradingRenderThread(TView *tView, TColorGrading *tColorGrading, uint32_t requestId, VoidCallback onComplete);
|
||||||
void View_setBloomRenderThread(TView *tView, bool enabled, double strength, uint32_t requestId, VoidCallback onComplete);
|
EMSCRIPTEN_KEEPALIVE void View_setBloomRenderThread(TView *tView, bool enabled, double strength, uint32_t requestId, VoidCallback onComplete);
|
||||||
void View_setCameraRenderThread(TView *tView, TCamera *tCamera, uint32_t requestId, VoidCallback onComplete);
|
EMSCRIPTEN_KEEPALIVE void View_setCameraRenderThread(TView *tView, TCamera *tCamera, uint32_t requestId, VoidCallback onComplete);
|
||||||
|
|
||||||
void SceneAsset_createGridRenderThread(TEngine *tEngine, TMaterial * tMaterial, void (*callback)(TSceneAsset *));
|
EMSCRIPTEN_KEEPALIVE void SceneAsset_createGridRenderThread(TEngine *tEngine, TMaterial * tMaterial, void (*callback)(TSceneAsset *));
|
||||||
|
|
||||||
void SceneAsset_destroyRenderThread(TSceneAsset *tSceneAsset, uint32_t requestId, VoidCallback onComplete);
|
EMSCRIPTEN_KEEPALIVE void SceneAsset_destroyRenderThread(TSceneAsset *tSceneAsset, uint32_t requestId, VoidCallback onComplete);
|
||||||
void SceneAsset_createFromFilamentAssetRenderThread(
|
EMSCRIPTEN_KEEPALIVE void SceneAsset_createFromFilamentAssetRenderThread(
|
||||||
TEngine *tEngine,
|
TEngine *tEngine,
|
||||||
TGltfAssetLoader *tAssetLoader,
|
TGltfAssetLoader *tAssetLoader,
|
||||||
TNameComponentManager *tNameComponentManager,
|
TNameComponentManager *tNameComponentManager,
|
||||||
TFilamentAsset *tFilamentAsset,
|
TFilamentAsset *tFilamentAsset,
|
||||||
void (*onComplete)(TSceneAsset *)
|
void (*onComplete)(TSceneAsset *)
|
||||||
);
|
);
|
||||||
void SceneAsset_createInstanceRenderThread(TSceneAsset *asset, TMaterialInstance **tMaterialInstances, int materialInstanceCount, void (*callback)(TSceneAsset *));
|
EMSCRIPTEN_KEEPALIVE void SceneAsset_createInstanceRenderThread(TSceneAsset *asset, TMaterialInstance **tMaterialInstances, int materialInstanceCount, void (*callback)(TSceneAsset *));
|
||||||
void SceneAsset_createGeometryRenderThread(
|
EMSCRIPTEN_KEEPALIVE void SceneAsset_createGeometryRenderThread(
|
||||||
TEngine *tEngine,
|
TEngine *tEngine,
|
||||||
float *vertices,
|
float *vertices,
|
||||||
uint32_t numVertices,
|
uint32_t numVertices,
|
||||||
@@ -124,7 +124,7 @@ namespace thermion
|
|||||||
int materialInstanceCount,
|
int materialInstanceCount,
|
||||||
void (*callback)(TSceneAsset *)
|
void (*callback)(TSceneAsset *)
|
||||||
);
|
);
|
||||||
void MaterialProvider_createMaterialInstanceRenderThread(
|
EMSCRIPTEN_KEEPALIVE void MaterialProvider_createMaterialInstanceRenderThread(
|
||||||
TMaterialProvider *tMaterialProvider,
|
TMaterialProvider *tMaterialProvider,
|
||||||
bool doubleSided,
|
bool doubleSided,
|
||||||
bool unlit,
|
bool unlit,
|
||||||
@@ -166,12 +166,12 @@ namespace thermion
|
|||||||
bool hasVolume,
|
bool hasVolume,
|
||||||
void (*callback)(TMaterialInstance *));
|
void (*callback)(TMaterialInstance *));
|
||||||
|
|
||||||
void AnimationManager_updateBoneMatricesRenderThread(
|
EMSCRIPTEN_KEEPALIVE void AnimationManager_updateBoneMatricesRenderThread(
|
||||||
TAnimationManager *tAnimationManager,
|
TAnimationManager *tAnimationManager,
|
||||||
TSceneAsset *sceneAsset,
|
TSceneAsset *sceneAsset,
|
||||||
void (*callback)(bool));
|
void (*callback)(bool));
|
||||||
|
|
||||||
void AnimationManager_setMorphTargetWeightsRenderThread(
|
EMSCRIPTEN_KEEPALIVE void AnimationManager_setMorphTargetWeightsRenderThread(
|
||||||
TAnimationManager *tAnimationManager,
|
TAnimationManager *tAnimationManager,
|
||||||
EntityId entityId,
|
EntityId entityId,
|
||||||
const float *const morphData,
|
const float *const morphData,
|
||||||
@@ -179,16 +179,16 @@ namespace thermion
|
|||||||
void (*callback)(bool));
|
void (*callback)(bool));
|
||||||
|
|
||||||
// Image methods
|
// Image methods
|
||||||
void Image_createEmptyRenderThread(uint32_t width, uint32_t height, uint32_t channel, void (*onComplete)(TLinearImage *));
|
EMSCRIPTEN_KEEPALIVE void Image_createEmptyRenderThread(uint32_t width, uint32_t height, uint32_t channel, void (*onComplete)(TLinearImage *));
|
||||||
void Image_decodeRenderThread(uint8_t* data, size_t length, const char* name, bool alpha, void (*onComplete)(TLinearImage *));
|
EMSCRIPTEN_KEEPALIVE void Image_decodeRenderThread(uint8_t* data, size_t length, const char* name, bool alpha, void (*onComplete)(TLinearImage *));
|
||||||
void Image_getBytesRenderThread(TLinearImage *tLinearImage, void (*onComplete)(float *));
|
EMSCRIPTEN_KEEPALIVE void Image_getBytesRenderThread(TLinearImage *tLinearImage, void (*onComplete)(float *));
|
||||||
void Image_destroyRenderThread(TLinearImage *tLinearImage, uint32_t requestId, VoidCallback onComplete);
|
EMSCRIPTEN_KEEPALIVE void Image_destroyRenderThread(TLinearImage *tLinearImage, uint32_t requestId, VoidCallback onComplete);
|
||||||
void Image_getWidthRenderThread(TLinearImage *tLinearImage, void (*onComplete)(uint32_t));
|
EMSCRIPTEN_KEEPALIVE void Image_getWidthRenderThread(TLinearImage *tLinearImage, void (*onComplete)(uint32_t));
|
||||||
void Image_getHeightRenderThread(TLinearImage *tLinearImage, void (*onComplete)(uint32_t));
|
EMSCRIPTEN_KEEPALIVE void Image_getHeightRenderThread(TLinearImage *tLinearImage, void (*onComplete)(uint32_t));
|
||||||
void Image_getChannelsRenderThread(TLinearImage *tLinearImage, void (*onComplete)(uint32_t));
|
EMSCRIPTEN_KEEPALIVE void Image_getChannelsRenderThread(TLinearImage *tLinearImage, void (*onComplete)(uint32_t));
|
||||||
|
|
||||||
|
|
||||||
void Texture_loadImageRenderThread(
|
EMSCRIPTEN_KEEPALIVE void Texture_loadImageRenderThread(
|
||||||
TEngine *tEngine,
|
TEngine *tEngine,
|
||||||
TTexture *tTexture,
|
TTexture *tTexture,
|
||||||
TLinearImage *tImage,
|
TLinearImage *tImage,
|
||||||
@@ -197,7 +197,7 @@ namespace thermion
|
|||||||
int level,
|
int level,
|
||||||
void (*onComplete)(bool)
|
void (*onComplete)(bool)
|
||||||
);
|
);
|
||||||
void Texture_setImageRenderThread(
|
EMSCRIPTEN_KEEPALIVE void Texture_setImageRenderThread(
|
||||||
TEngine *tEngine,
|
TEngine *tEngine,
|
||||||
TTexture *tTexture,
|
TTexture *tTexture,
|
||||||
uint32_t level,
|
uint32_t level,
|
||||||
@@ -213,8 +213,8 @@ namespace thermion
|
|||||||
uint32_t pixelDataType,
|
uint32_t pixelDataType,
|
||||||
void (*onComplete)(bool)
|
void (*onComplete)(bool)
|
||||||
);
|
);
|
||||||
void RenderTarget_getColorTextureRenderThread(TRenderTarget *tRenderTarget, void (*onComplete)(TTexture *));
|
EMSCRIPTEN_KEEPALIVE void RenderTarget_getColorTextureRenderThread(TRenderTarget *tRenderTarget, void (*onComplete)(TTexture *));
|
||||||
void RenderTarget_createRenderThread(
|
EMSCRIPTEN_KEEPALIVE void RenderTarget_createRenderThread(
|
||||||
TEngine *tEngine,
|
TEngine *tEngine,
|
||||||
uint32_t width,
|
uint32_t width,
|
||||||
uint32_t height,
|
uint32_t height,
|
||||||
@@ -222,7 +222,7 @@ namespace thermion
|
|||||||
TTexture *depth,
|
TTexture *depth,
|
||||||
void (*onComplete)(TRenderTarget *)
|
void (*onComplete)(TRenderTarget *)
|
||||||
);
|
);
|
||||||
void RenderTarget_destroyRenderThread(
|
EMSCRIPTEN_KEEPALIVE void RenderTarget_destroyRenderThread(
|
||||||
TEngine *tEngine,
|
TEngine *tEngine,
|
||||||
TRenderTarget *tRenderTarget,
|
TRenderTarget *tRenderTarget,
|
||||||
uint32_t requestId, VoidCallback onComplete
|
uint32_t requestId, VoidCallback onComplete
|
||||||
@@ -230,8 +230,8 @@ namespace thermion
|
|||||||
|
|
||||||
|
|
||||||
// TextureSampler methods
|
// TextureSampler methods
|
||||||
void TextureSampler_createRenderThread(void (*onComplete)(TTextureSampler*));
|
EMSCRIPTEN_KEEPALIVE void TextureSampler_createRenderThread(void (*onComplete)(TTextureSampler*));
|
||||||
void TextureSampler_createWithFilteringRenderThread(
|
EMSCRIPTEN_KEEPALIVE void TextureSampler_createWithFilteringRenderThread(
|
||||||
TSamplerMinFilter minFilter,
|
TSamplerMinFilter minFilter,
|
||||||
TSamplerMagFilter magFilter,
|
TSamplerMagFilter magFilter,
|
||||||
TSamplerWrapMode wrapS,
|
TSamplerWrapMode wrapS,
|
||||||
@@ -239,53 +239,53 @@ namespace thermion
|
|||||||
TSamplerWrapMode wrapR,
|
TSamplerWrapMode wrapR,
|
||||||
void (*onComplete)(TTextureSampler*)
|
void (*onComplete)(TTextureSampler*)
|
||||||
);
|
);
|
||||||
void TextureSampler_createWithComparisonRenderThread(
|
EMSCRIPTEN_KEEPALIVE void TextureSampler_createWithComparisonRenderThread(
|
||||||
TSamplerCompareMode compareMode,
|
TSamplerCompareMode compareMode,
|
||||||
TSamplerCompareFunc compareFunc,
|
TSamplerCompareFunc compareFunc,
|
||||||
void (*onComplete)(TTextureSampler*)
|
void (*onComplete)(TTextureSampler*)
|
||||||
);
|
);
|
||||||
void TextureSampler_setMinFilterRenderThread(
|
EMSCRIPTEN_KEEPALIVE void TextureSampler_setMinFilterRenderThread(
|
||||||
TTextureSampler* sampler,
|
TTextureSampler* sampler,
|
||||||
TSamplerMinFilter filter,
|
TSamplerMinFilter filter,
|
||||||
uint32_t requestId, VoidCallback onComplete
|
uint32_t requestId, VoidCallback onComplete
|
||||||
);
|
);
|
||||||
void TextureSampler_setMagFilterRenderThread(
|
EMSCRIPTEN_KEEPALIVE void TextureSampler_setMagFilterRenderThread(
|
||||||
TTextureSampler* sampler,
|
TTextureSampler* sampler,
|
||||||
TSamplerMagFilter filter,
|
TSamplerMagFilter filter,
|
||||||
uint32_t requestId, VoidCallback onComplete
|
uint32_t requestId, VoidCallback onComplete
|
||||||
);
|
);
|
||||||
void TextureSampler_setWrapModeSRenderThread(
|
EMSCRIPTEN_KEEPALIVE void TextureSampler_setWrapModeSRenderThread(
|
||||||
TTextureSampler* sampler,
|
TTextureSampler* sampler,
|
||||||
TSamplerWrapMode mode,
|
TSamplerWrapMode mode,
|
||||||
uint32_t requestId, VoidCallback onComplete
|
uint32_t requestId, VoidCallback onComplete
|
||||||
);
|
);
|
||||||
void TextureSampler_setWrapModeTRenderThread(
|
EMSCRIPTEN_KEEPALIVE void TextureSampler_setWrapModeTRenderThread(
|
||||||
TTextureSampler* sampler,
|
TTextureSampler* sampler,
|
||||||
TSamplerWrapMode mode,
|
TSamplerWrapMode mode,
|
||||||
uint32_t requestId, VoidCallback onComplete
|
uint32_t requestId, VoidCallback onComplete
|
||||||
);
|
);
|
||||||
void TextureSampler_setWrapModeRRenderThread(
|
EMSCRIPTEN_KEEPALIVE void TextureSampler_setWrapModeRRenderThread(
|
||||||
TTextureSampler* sampler,
|
TTextureSampler* sampler,
|
||||||
TSamplerWrapMode mode,
|
TSamplerWrapMode mode,
|
||||||
uint32_t requestId, VoidCallback onComplete
|
uint32_t requestId, VoidCallback onComplete
|
||||||
);
|
);
|
||||||
void TextureSampler_setAnisotropyRenderThread(
|
EMSCRIPTEN_KEEPALIVE void TextureSampler_setAnisotropyRenderThread(
|
||||||
TTextureSampler* sampler,
|
TTextureSampler* sampler,
|
||||||
double anisotropy,
|
double anisotropy,
|
||||||
uint32_t requestId, VoidCallback onComplete
|
uint32_t requestId, VoidCallback onComplete
|
||||||
);
|
);
|
||||||
void TextureSampler_setCompareModeRenderThread(
|
EMSCRIPTEN_KEEPALIVE void TextureSampler_setCompareModeRenderThread(
|
||||||
TTextureSampler* sampler,
|
TTextureSampler* sampler,
|
||||||
TSamplerCompareMode mode,
|
TSamplerCompareMode mode,
|
||||||
TTextureSamplerCompareFunc func,
|
TTextureSamplerCompareFunc func,
|
||||||
uint32_t requestId, VoidCallback onComplete
|
uint32_t requestId, VoidCallback onComplete
|
||||||
);
|
);
|
||||||
void TextureSampler_destroyRenderThread(
|
EMSCRIPTEN_KEEPALIVE void TextureSampler_destroyRenderThread(
|
||||||
TTextureSampler* sampler,
|
TTextureSampler* sampler,
|
||||||
uint32_t requestId, VoidCallback onComplete
|
uint32_t requestId, VoidCallback onComplete
|
||||||
);
|
);
|
||||||
|
|
||||||
void AnimationManager_setBoneTransformRenderThread(
|
EMSCRIPTEN_KEEPALIVE void AnimationManager_setBoneTransformRenderThread(
|
||||||
TAnimationManager *tAnimationManager,
|
TAnimationManager *tAnimationManager,
|
||||||
EntityId asset,
|
EntityId asset,
|
||||||
int skinIndex,
|
int skinIndex,
|
||||||
@@ -293,18 +293,18 @@ namespace thermion
|
|||||||
const float *const transform,
|
const float *const transform,
|
||||||
void (*callback)(bool));
|
void (*callback)(bool));
|
||||||
|
|
||||||
void AnimationManager_resetToRestPoseRenderThread(TAnimationManager *tAnimationManager, TSceneAsset *tSceneAsset, uint32_t requestId, VoidCallback onComplete);
|
EMSCRIPTEN_KEEPALIVE void AnimationManager_resetToRestPoseRenderThread(TAnimationManager *tAnimationManager, TSceneAsset *tSceneAsset, uint32_t requestId, VoidCallback onComplete);
|
||||||
|
|
||||||
void GltfAssetLoader_createRenderThread(TEngine *tEngine, TMaterialProvider *tMaterialProvider, TNameComponentManager *tNameComponentManager, void (*callback)(TGltfAssetLoader *));
|
EMSCRIPTEN_KEEPALIVE void GltfAssetLoader_createRenderThread(TEngine *tEngine, TMaterialProvider *tMaterialProvider, TNameComponentManager *tNameComponentManager, void (*callback)(TGltfAssetLoader *));
|
||||||
void GltfResourceLoader_createRenderThread(TEngine *tEngine, void (*callback)(TGltfResourceLoader *));
|
EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_createRenderThread(TEngine *tEngine, void (*callback)(TGltfResourceLoader *));
|
||||||
void GltfResourceLoader_destroyRenderThread(TEngine *tEngine, TGltfResourceLoader *tResourceLoader, uint32_t requestId, VoidCallback onComplete);
|
EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_destroyRenderThread(TEngine *tEngine, TGltfResourceLoader *tResourceLoader, uint32_t requestId, VoidCallback onComplete);
|
||||||
void GltfResourceLoader_loadResourcesRenderThread(TGltfResourceLoader *tGltfResourceLoader, TFilamentAsset *tFilamentAsset, void (*callback)(bool));
|
EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_loadResourcesRenderThread(TGltfResourceLoader *tGltfResourceLoader, TFilamentAsset *tFilamentAsset, void (*callback)(bool));
|
||||||
void GltfResourceLoader_addResourceDataRenderThread(TGltfResourceLoader *tGltfResourceLoader, const char *uri, uint8_t *data, size_t length, uint32_t requestId, VoidCallback onComplete);
|
EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_addResourceDataRenderThread(TGltfResourceLoader *tGltfResourceLoader, const char *uri, uint8_t *data, size_t length, uint32_t requestId, VoidCallback onComplete);
|
||||||
void GltfResourceLoader_asyncBeginLoadRenderThread(TGltfResourceLoader *tGltfResourceLoader, TFilamentAsset *tFilamentAsset, void (*callback)(bool));
|
EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_asyncBeginLoadRenderThread(TGltfResourceLoader *tGltfResourceLoader, TFilamentAsset *tFilamentAsset, void (*callback)(bool));
|
||||||
void GltfResourceLoader_asyncUpdateLoadRenderThread(TGltfResourceLoader *tGltfResourceLoader);
|
EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_asyncUpdateLoadRenderThread(TGltfResourceLoader *tGltfResourceLoader);
|
||||||
void GltfResourceLoader_asyncGetLoadProgressRenderThread(TGltfResourceLoader *tGltfResourceLoader, void (*callback)(float));
|
EMSCRIPTEN_KEEPALIVE void GltfResourceLoader_asyncGetLoadProgressRenderThread(TGltfResourceLoader *tGltfResourceLoader, void (*callback)(float));
|
||||||
|
|
||||||
void GltfAssetLoader_loadRenderThread(
|
EMSCRIPTEN_KEEPALIVE void GltfAssetLoader_loadRenderThread(
|
||||||
TEngine *tEngine,
|
TEngine *tEngine,
|
||||||
TGltfAssetLoader *tAssetLoader,
|
TGltfAssetLoader *tAssetLoader,
|
||||||
uint8_t *data,
|
uint8_t *data,
|
||||||
@@ -312,8 +312,8 @@ namespace thermion
|
|||||||
uint8_t numInstances,
|
uint8_t numInstances,
|
||||||
void (*callback)(TFilamentAsset *)
|
void (*callback)(TFilamentAsset *)
|
||||||
);
|
);
|
||||||
void Scene_addFilamentAssetRenderThread(TScene* tScene, TFilamentAsset *tAsset, uint32_t requestId, VoidCallback onComplete);
|
EMSCRIPTEN_KEEPALIVE void Scene_addFilamentAssetRenderThread(TScene* tScene, TFilamentAsset *tAsset, uint32_t requestId, VoidCallback onComplete);
|
||||||
void Gizmo_createRenderThread(
|
EMSCRIPTEN_KEEPALIVE void Gizmo_createRenderThread(
|
||||||
TEngine *tEngine,
|
TEngine *tEngine,
|
||||||
TGltfAssetLoader *tAssetLoader,
|
TGltfAssetLoader *tAssetLoader,
|
||||||
TGltfResourceLoader *tGltfResourceLoader,
|
TGltfResourceLoader *tGltfResourceLoader,
|
||||||
@@ -330,4 +330,3 @@ namespace thermion
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -8,5 +8,5 @@ GRID_PACKAGE:
|
|||||||
GRID_GRID_OFFSET:
|
GRID_GRID_OFFSET:
|
||||||
.int 0
|
.int 0
|
||||||
GRID_GRID_SIZE:
|
GRID_GRID_SIZE:
|
||||||
.int 50913
|
.int 49793
|
||||||
|
|
||||||
|
|||||||
@@ -8,5 +8,5 @@ _GRID_PACKAGE:
|
|||||||
_GRID_GRID_OFFSET:
|
_GRID_GRID_OFFSET:
|
||||||
.int 0
|
.int 0
|
||||||
_GRID_GRID_SIZE:
|
_GRID_GRID_SIZE:
|
||||||
.int 50913
|
.int 49793
|
||||||
|
|
||||||
|
|||||||
@@ -85,10 +85,10 @@ EMSCRIPTEN_KEEPALIVE TFilamentAsset *GltfAssetLoader_load(
|
|||||||
const char *const *const resourceUris = asset->getResourceUris();
|
const char *const *const resourceUris = asset->getResourceUris();
|
||||||
const size_t resourceUriCount = asset->getResourceUriCount();
|
const size_t resourceUriCount = asset->getResourceUriCount();
|
||||||
|
|
||||||
Log("glTF asset : %d resource URIs, %d instances", resourceUriCount, numInstances);
|
TRACE("Loading glTF asset with %d resource URIs (allocating %d reserved instances", resourceUriCount, numInstances);
|
||||||
|
|
||||||
for(int i = 0; i < resourceUriCount; i++) {
|
for(int i = 0; i < resourceUriCount; i++) {
|
||||||
Log("%s", resourceUris[i]);
|
TRACE("%s", resourceUris[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return reinterpret_cast<TFilamentAsset *>(asset);
|
return reinterpret_cast<TFilamentAsset *>(asset);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
name: thermion_dart
|
name: thermion_dart
|
||||||
description: 3D rendering toolkit for Dart.
|
description: 3D rendering toolkit for Dart.
|
||||||
version: 0.3.2
|
version: 0.3.3
|
||||||
homepage: https://thermion.dev
|
homepage: https://thermion.dev
|
||||||
repository: https://github.com/nmfisher/thermion
|
repository: https://github.com/nmfisher/thermion
|
||||||
|
|
||||||
|
|||||||
@@ -82,10 +82,6 @@ class TestHelper {
|
|||||||
testDir = Directory("${packageUri}test").path;
|
testDir = Directory("${packageUri}test").path;
|
||||||
outDir = Directory("$testDir/output/${dir}");
|
outDir = Directory("$testDir/output/${dir}");
|
||||||
outDir.createSync(recursive: true);
|
outDir.createSync(recursive: true);
|
||||||
if (Platform.isMacOS) {
|
|
||||||
DynamicLibrary.open('${testDir}/generated/objective_c.dylib');
|
|
||||||
DynamicLibrary.open('${testDir}/generated/libThermionTextureSwift.dylib');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -226,6 +222,10 @@ class TestHelper {
|
|||||||
|
|
||||||
FFIRenderTarget? renderTarget;
|
FFIRenderTarget? renderTarget;
|
||||||
if (createRenderTarget) {
|
if (createRenderTarget) {
|
||||||
|
// if (Platform.isMacOS) {
|
||||||
|
// DynamicLibrary.open('${testDir}/generated/objective_c.dylib');
|
||||||
|
// DynamicLibrary.open('${testDir}/generated/libThermionTextureSwift.dylib');
|
||||||
|
// }
|
||||||
// var metalColorTexture = await createTexture(
|
// var metalColorTexture = await createTexture(
|
||||||
// viewportDimensions.width, viewportDimensions.height);
|
// viewportDimensions.width, viewportDimensions.height);
|
||||||
// var metalDepthTexture = await createTexture(
|
// var metalDepthTexture = await createTexture(
|
||||||
|
|||||||
@@ -1,3 +1,11 @@
|
|||||||
|
## 0.3.3
|
||||||
|
|
||||||
|
- Bump "thermion_flutter" to `0.3.3`.
|
||||||
|
|
||||||
|
## 0.3.3-pre
|
||||||
|
|
||||||
|
- **DOCS**: replace thermion_flutter README with symlink to thermion_dart README.
|
||||||
|
|
||||||
## 0.3.2
|
## 0.3.2
|
||||||
|
|
||||||
- Bump "thermion_flutter" to `0.3.2`.
|
- Bump "thermion_flutter" to `0.3.2`.
|
||||||
|
|||||||
@@ -1,63 +0,0 @@
|
|||||||

|
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
<a href="https://thermion.dev/quickstart">Quickstart (Flutter)</a> •
|
|
||||||
<a href="https://thermion.dev/quickstart">Documentation</a> •
|
|
||||||
<a href="https://thermion.dev/showcase">Showcase</a> •
|
|
||||||
<a href="https://dartpad.thermion.dev/">Playground</a> •
|
|
||||||
<a href="https://discord.gg/h2VdDK3EAQ">Discord</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
## Cross-platform 3D engine for Dart and Flutter.
|
|
||||||
|
|
||||||
<a href="https://pub.dev/packages/thermion_dart"><img src="https://img.shields.io/pub/v/thermion_dart?label=pub.dev&labelColor=333940&logo=dart&color=00589B" alt="pub"></a>
|
|
||||||
<a href="https://github.com/nmfisher/thermion"><img src="https://img.shields.io/github/stars/nmfisher/flutter_filament?style=flat&label=stars&labelColor=333940&color=8957e5&logo=github" alt="github"></a>
|
|
||||||
<a href="https://discord.gg/h2VdDK3EAQ"><img src="https://img.shields.io/discord/993167615587520602?logo=discord&logoColor=fff&labelColor=333940" alt="discord"></a>
|
|
||||||
<a href="https://github.com/nmfisher/thermion"><img src="https://img.shields.io/github/contributors/nmfisher/flutter_filament?logo=github&labelColor=333940" alt="contributors"></a>
|
|
||||||
|
|
||||||
### Quickstart (Flutter)
|
|
||||||
|
|
||||||
```
|
|
||||||
_thermionViewer = await ThermionFlutterPlugin.createViewer();
|
|
||||||
|
|
||||||
// Geometry and models are represented as "entities". Here, we load a glTF
|
|
||||||
// file containing a plain cube.
|
|
||||||
// By default, all paths are treated as asset paths. To load from a file
|
|
||||||
// instead, use file:// URIs.
|
|
||||||
var entity =
|
|
||||||
await _thermionViewer!.loadGlb("assets/cube.glb", keepData: true);
|
|
||||||
|
|
||||||
// Thermion uses a right-handed coordinate system where +Y is up and -Z is
|
|
||||||
// "into" the screen.
|
|
||||||
// By default, the camera is located at (0,0,0) looking at (0,0,-1); this
|
|
||||||
// would place it directly inside the cube we just loaded.
|
|
||||||
//
|
|
||||||
// Let's move the camera to (0,0,10) to ensure the cube is visible in the
|
|
||||||
// viewport.
|
|
||||||
await _thermionViewer!.setCameraPosition(0, 0, 10);
|
|
||||||
|
|
||||||
// Without a light source, your scene will be totally black. Let's load a skybox
|
|
||||||
// (a cubemap image that is rendered behind everything else in the scene)
|
|
||||||
// and an image-based indirect light that has been precomputed from the same
|
|
||||||
// skybox.
|
|
||||||
await _thermionViewer!.loadSkybox("assets/default_env_skybox.ktx");
|
|
||||||
await _thermionViewer!.loadIbl("assets/default_env_ibl.ktx");
|
|
||||||
|
|
||||||
// Finally, you need to explicitly enable rendering. Setting rendering to
|
|
||||||
// false is designed to allow you to pause rendering to conserve battery life
|
|
||||||
await _thermionViewer!.setRendering(true);
|
|
||||||
```
|
|
||||||
|
|
||||||
and then in your Flutter application:
|
|
||||||
```
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Stack(children: [
|
|
||||||
if (_thermionViewer != null)
|
|
||||||
Positioned.fill(
|
|
||||||
child: ThermionWidget(
|
|
||||||
viewer: _thermionViewer!,
|
|
||||||
)),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
1
thermion_flutter/thermion_flutter/README.md
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../../thermion_dart/README.md
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
name: thermion_flutter
|
name: thermion_flutter
|
||||||
description: Flutter plugin for 3D rendering with the Thermion toolkit.
|
description: Flutter plugin for 3D rendering with the Thermion toolkit.
|
||||||
version: 0.3.2
|
version: 0.3.3
|
||||||
homepage: https://thermion.dev
|
homepage: https://thermion.dev
|
||||||
repository: https://github.com/nmfisher/thermion
|
repository: https://github.com/nmfisher/thermion
|
||||||
|
|
||||||
@@ -17,10 +17,10 @@ dependencies:
|
|||||||
plugin_platform_interface: ^2.0.0
|
plugin_platform_interface: ^2.0.0
|
||||||
ffi: ^2.1.2
|
ffi: ^2.1.2
|
||||||
animation_tools_dart: ^0.1.0
|
animation_tools_dart: ^0.1.0
|
||||||
thermion_dart: ^0.3.2
|
thermion_dart: ^0.3.3
|
||||||
thermion_flutter_platform_interface: ^0.3.2
|
thermion_flutter_platform_interface: ^0.3.3
|
||||||
thermion_flutter_method_channel: ^0.3.2
|
thermion_flutter_method_channel: ^0.3.3
|
||||||
thermion_flutter_web: ^0.3.2
|
thermion_flutter_web: ^0.3.3
|
||||||
logging: ^1.2.0
|
logging: ^1.2.0
|
||||||
web: ^1.0.0
|
web: ^1.0.0
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,11 @@
|
|||||||
|
## 0.3.3
|
||||||
|
|
||||||
|
- Bump "thermion_flutter_method_channel" to `0.3.3`.
|
||||||
|
|
||||||
|
## 0.3.3-pre
|
||||||
|
|
||||||
|
- **FEAT**: allow passing renderTargetColorTextureFormat via ThermionFlutterOptions.
|
||||||
|
|
||||||
## 0.3.2
|
## 0.3.2
|
||||||
|
|
||||||
- Bump "thermion_flutter_method_channel" to `0.3.2`.
|
- Bump "thermion_flutter_method_channel" to `0.3.2`.
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ class ThermionFlutterMethodChannelPlatform extends ThermionFlutterPlatform {
|
|||||||
TextureUsage.TEXTURE_USAGE_COLOR_ATTACHMENT,
|
TextureUsage.TEXTURE_USAGE_COLOR_ATTACHMENT,
|
||||||
TextureUsage.TEXTURE_USAGE_SAMPLEABLE,
|
TextureUsage.TEXTURE_USAGE_SAMPLEABLE,
|
||||||
},
|
},
|
||||||
textureFormat: TextureFormat.RGBA32F,
|
textureFormat: options.renderTargetColorTextureFormat,
|
||||||
textureSamplerType: TextureSamplerType.SAMPLER_2D,
|
textureSamplerType: TextureSamplerType.SAMPLER_2D,
|
||||||
);
|
);
|
||||||
final depth = await FilamentApp.instance!.createTexture(
|
final depth = await FilamentApp.instance!.createTexture(
|
||||||
@@ -225,7 +225,7 @@ class ThermionFlutterMethodChannelPlatform extends ThermionFlutterPlatform {
|
|||||||
TextureUsage.TEXTURE_USAGE_STENCIL_ATTACHMENT
|
TextureUsage.TEXTURE_USAGE_STENCIL_ATTACHMENT
|
||||||
},
|
},
|
||||||
textureFormat:
|
textureFormat:
|
||||||
TextureFormat.DEPTH24_STENCIL8, // TextureFormat.DEPTH32F,
|
options.renderTargetDepthTextureFormat,
|
||||||
textureSamplerType: TextureSamplerType.SAMPLER_2D,
|
textureSamplerType: TextureSamplerType.SAMPLER_2D,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
name: thermion_flutter_method_channel
|
name: thermion_flutter_method_channel
|
||||||
description: Desktop + mobile implementation for texture creation + registration with Flutter.
|
description: Desktop + mobile implementation for texture creation + registration with Flutter.
|
||||||
repository: https://github.com/nmfisher/thermion_flutter/thermion_flutter
|
repository: https://github.com/nmfisher/thermion_flutter/thermion_flutter
|
||||||
version: 0.3.2
|
version: 0.3.3
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=3.3.0 <4.0.0"
|
sdk: ">=3.3.0 <4.0.0"
|
||||||
@@ -23,8 +23,8 @@ dependencies:
|
|||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
plugin_platform_interface: ^2.1.0
|
plugin_platform_interface: ^2.1.0
|
||||||
thermion_flutter_platform_interface: ^0.3.2
|
thermion_flutter_platform_interface: ^0.3.3
|
||||||
thermion_dart: ^0.3.2
|
thermion_dart: ^0.3.3
|
||||||
logging: ^1.2.0
|
logging: ^1.2.0
|
||||||
dependency_overrides:
|
dependency_overrides:
|
||||||
thermion_dart:
|
thermion_dart:
|
||||||
|
|||||||
@@ -1,3 +1,11 @@
|
|||||||
|
## 0.3.3
|
||||||
|
|
||||||
|
- Bump "thermion_flutter_platform_interface" to `0.3.3`.
|
||||||
|
|
||||||
|
## 0.3.3-pre
|
||||||
|
|
||||||
|
- **FEAT**: allow passing renderTargetColorTextureFormat via ThermionFlutterOptions.
|
||||||
|
|
||||||
## 0.3.2
|
## 0.3.2
|
||||||
|
|
||||||
- Bump "thermion_flutter_platform_interface" to `0.3.2`.
|
- Bump "thermion_flutter_platform_interface" to `0.3.2`.
|
||||||
|
|||||||
@@ -7,13 +7,25 @@ import 'thermion_flutter_texture.dart';
|
|||||||
class ThermionFlutterOptions {
|
class ThermionFlutterOptions {
|
||||||
final String? uberarchivePath;
|
final String? uberarchivePath;
|
||||||
final Backend? backend;
|
final Backend? backend;
|
||||||
|
|
||||||
|
/// The format to use for the default render target color attachment.
|
||||||
|
/// Currently only applicable on iOS/macOS.
|
||||||
|
///
|
||||||
|
final TextureFormat renderTargetColorTextureFormat;
|
||||||
|
|
||||||
|
/// The format to use for the default render target depth attachment.
|
||||||
|
/// Currently only applicable on iOS/macOS.
|
||||||
|
///
|
||||||
|
final TextureFormat renderTargetDepthTextureFormat;
|
||||||
|
|
||||||
const ThermionFlutterOptions(
|
const ThermionFlutterOptions(
|
||||||
{this.uberarchivePath = null, this.backend = null});
|
{this.uberarchivePath = null,
|
||||||
|
this.backend = null,
|
||||||
|
this.renderTargetColorTextureFormat = TextureFormat.RGBA32F,
|
||||||
|
this.renderTargetDepthTextureFormat = TextureFormat.DEPTH24_STENCIL8});
|
||||||
}
|
}
|
||||||
|
|
||||||
class ThermionFlutterWebOptions extends ThermionFlutterOptions {
|
class ThermionFlutterWebOptions extends ThermionFlutterOptions {
|
||||||
|
|
||||||
final bool createCanvas;
|
final bool createCanvas;
|
||||||
final bool importCanvasAsWidget;
|
final bool importCanvasAsWidget;
|
||||||
|
|
||||||
@@ -22,8 +34,6 @@ class ThermionFlutterWebOptions extends ThermionFlutterOptions {
|
|||||||
this.createCanvas = true,
|
this.createCanvas = true,
|
||||||
String? uberarchivePath})
|
String? uberarchivePath})
|
||||||
: super(uberarchivePath: uberarchivePath);
|
: super(uberarchivePath: uberarchivePath);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class ThermionFlutterPlatform extends PlatformInterface {
|
abstract class ThermionFlutterPlatform extends PlatformInterface {
|
||||||
@@ -42,15 +52,11 @@ abstract class ThermionFlutterPlatform extends PlatformInterface {
|
|||||||
_options ??= const ThermionFlutterOptions();
|
_options ??= const ThermionFlutterOptions();
|
||||||
return _options!;
|
return _options!;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
void setOptions(covariant ThermionFlutterOptions options) {
|
void setOptions(covariant ThermionFlutterOptions options) {
|
||||||
if (_options != null) {
|
|
||||||
throw Exception(
|
|
||||||
"Options can only be set once for the entire app lifecycle.");
|
|
||||||
}
|
|
||||||
_options = options;
|
_options = options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
name: thermion_flutter_platform_interface
|
name: thermion_flutter_platform_interface
|
||||||
description: A common platform interface for the thermion_flutter plugin.
|
description: A common platform interface for the thermion_flutter plugin.
|
||||||
repository: https://github.com/nmfisher/thermion_flutter/thermion_flutter
|
repository: https://github.com/nmfisher/thermion_flutter/thermion_flutter
|
||||||
version: 0.3.2
|
version: 0.3.3
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=3.3.0 <4.0.0"
|
sdk: ">=3.3.0 <4.0.0"
|
||||||
@@ -11,7 +11,7 @@ dependencies:
|
|||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
plugin_platform_interface: ^2.1.0
|
plugin_platform_interface: ^2.1.0
|
||||||
thermion_dart: ^0.3.2
|
thermion_dart: ^0.3.3
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|||||||
@@ -1,3 +1,11 @@
|
|||||||
|
## 0.3.3
|
||||||
|
|
||||||
|
- Bump "thermion_flutter_web" to `0.3.3`.
|
||||||
|
|
||||||
|
## 0.3.3-pre
|
||||||
|
|
||||||
|
- Bump "thermion_flutter_web" to `0.3.3-pre`.
|
||||||
|
|
||||||
## 0.3.2
|
## 0.3.2
|
||||||
|
|
||||||
- **FIX**: add missing destroySwapchain argument for web.
|
- **FIX**: add missing destroySwapchain argument for web.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
name: thermion_flutter_web
|
name: thermion_flutter_web
|
||||||
description: A web platform interface for the thermion_flutter plugin.
|
description: A web platform interface for the thermion_flutter plugin.
|
||||||
repository: https://github.com/nmfisher/thermion_flutter/thermion_flutter
|
repository: https://github.com/nmfisher/thermion_flutter/thermion_flutter
|
||||||
version: 0.3.2
|
version: 0.3.3
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=3.3.0 <4.0.0"
|
sdk: ">=3.3.0 <4.0.0"
|
||||||
@@ -20,8 +20,8 @@ dependencies:
|
|||||||
sdk: flutter
|
sdk: flutter
|
||||||
plugin_platform_interface: ^2.1.0
|
plugin_platform_interface: ^2.1.0
|
||||||
web: ^1.0.0
|
web: ^1.0.0
|
||||||
thermion_dart: ^0.3.2
|
thermion_dart: ^0.3.3
|
||||||
thermion_flutter_platform_interface: ^0.3.2
|
thermion_flutter_platform_interface: ^0.3.3
|
||||||
flutter_web_plugins:
|
flutter_web_plugins:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
logging: ^1.3.0
|
logging: ^1.3.0
|
||||||
|
|||||||