Compare commits
2 Commits
master
...
thermion_f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c59aa6f43e | ||
|
|
8e41c32bd2 |
29
.github/actions/setup-build-env/action.yml
vendored
@@ -1,29 +0,0 @@
|
||||
name: 'Setup Build Environment'
|
||||
description: 'Set up LLVM, MESA, and Flutter for builds'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup LLVM
|
||||
uses: KyleMayes/install-llvm-action@v1
|
||||
with:
|
||||
version: "16"
|
||||
- name: Add LLVM to PATH
|
||||
shell: bash
|
||||
run: |
|
||||
echo "${{ github.workspace }}/llvm/bin" >> $GITHUB_PATH
|
||||
echo "LD_LIBRARY_PATH=${{ github.workspace }}/llvm/lib/x86_64-unknown-linux-gnu/" >> $GITHUB_ENV
|
||||
- name: Verify installation
|
||||
shell: bash
|
||||
run: clang --version
|
||||
- name: Install MESA
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y xvfb
|
||||
sudo apt-get install -y libosmesa6-dev
|
||||
- name: Set up Flutter
|
||||
uses: subosito/flutter-action@v2
|
||||
with:
|
||||
channel: master
|
||||
architecture: X64
|
||||
219
.github/workflows/dart.yml
vendored
@@ -1,3 +1,7 @@
|
||||
# This workflow uses actions that are not certified by GitHub.
|
||||
# They are provided by a third-party and are governed by
|
||||
# separate terms of service, privacy policy, and support
|
||||
# documentation.
|
||||
name: Dart
|
||||
|
||||
on:
|
||||
@@ -7,130 +11,30 @@ on:
|
||||
branches: [ "develop" ]
|
||||
|
||||
jobs:
|
||||
compile-web-wasm:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup CMake
|
||||
uses: jwlawson/actions-setup-cmake@v2
|
||||
with:
|
||||
cmake-version: '3.25.0' # or 'latest'
|
||||
- name: Setup Emscripten
|
||||
uses: mymindstorm/setup-emsdk@v14
|
||||
with:
|
||||
version: 'latest'
|
||||
- name: Compile web
|
||||
run: make wasm
|
||||
dart-tests:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/setup-build-env
|
||||
- run: |
|
||||
cd thermion_dart
|
||||
dart pub get
|
||||
xvfb-run dart --enable-experiment=native-assets test \
|
||||
test/asset_tests.dart \
|
||||
test/instancing_tests.dart \
|
||||
test/light_tests.dart \
|
||||
test/entity_tests.dart \
|
||||
test/geometry_tests.dart \
|
||||
test/view_tests.dart \
|
||||
test/postprocessing_tests.dart \
|
||||
test/scene_tests.dart \
|
||||
test/picking_tests.dart \
|
||||
--concurrency=1
|
||||
#test/overlay_tests.dart \
|
||||
- name: Zip output
|
||||
run: zip -r output.zip ./thermion_dart/test/output
|
||||
- name: Upload test output
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: golden-images-${{ github.sha }}
|
||||
path: output.zip
|
||||
- name: Download golden images from previous run
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
gh run download 15990504915 \
|
||||
--name golden-images-4b9870244a529bf086280331d38c55e294425b4f \
|
||||
--dir ./thermion_dart/test/golden-downloads
|
||||
- name: Unzip golden images
|
||||
run: |
|
||||
cd thermion_dart/test/golden-downloads && unzip output.zip
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install Pillow numpy
|
||||
- name: Compare golden images
|
||||
run: cd thermion_dart/test && python compare_goldens.py
|
||||
- name: Upload logs
|
||||
if: failure() || steps.build.outcome == 'failure'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: build-logs
|
||||
path: |
|
||||
${{ github.workspace }}/thermion_dart/.dart_tool/thermion_dart/log/build.log
|
||||
retention-days: 5
|
||||
flutter_examples:
|
||||
name: flutter_examples
|
||||
runs-on: macos-latest
|
||||
thermion_dart:
|
||||
name: thermion_dart
|
||||
runs-on: self-hosted
|
||||
defaults:
|
||||
run:
|
||||
working-directory: examples/flutter
|
||||
working-directory: thermion_dart # Adjust this path
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Flutter
|
||||
uses: subosito/flutter-action@v2
|
||||
with:
|
||||
channel: master
|
||||
architecture: ARM64
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'temurin'
|
||||
- name: Install Android SDK
|
||||
uses: android-actions/setup-android@v3
|
||||
with:
|
||||
api-level: 34
|
||||
build-tools: 34.0.0
|
||||
cmake-version: 3.22.1
|
||||
ndk-version: 25.1.893739
|
||||
- name: Accept Android SDK licenses
|
||||
run: |
|
||||
yes | $ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager --licenses
|
||||
- run: cd quickstart && flutter pub get && flutter build macos
|
||||
# - run: cd quickstart && flutter pub get && flutter build ios
|
||||
- run: cd quickstart && flutter pub get && flutter build appbundle
|
||||
- run: cd quickstart && flutter build web
|
||||
- run: cd picking && flutter pub get && flutter build macos
|
||||
# - run: cd picking && flutter pub get && flutter build ios
|
||||
- run: cd picking && flutter pub get && flutter build appbundle
|
||||
- run: cd picking && flutter build web
|
||||
- name: Upload logs
|
||||
if: failure() || steps.build.outcome == 'failure'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: build-logs
|
||||
path: |
|
||||
# D:\a\thermion\thermion\thermion_dart\.dart_tool\thermion_dart\log\build.log
|
||||
/Users/runner/work/thermion/thermion/thermion_dart/.dart_tool/thermion_dart/log/build.log
|
||||
retention-days: 5
|
||||
flutter_examples_windows:
|
||||
name: flutter_examples_windows
|
||||
runs-on: windows-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: examples/flutter
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Flutter
|
||||
uses: subosito/flutter-action@v2
|
||||
with:
|
||||
channel: master
|
||||
- run: cd quickstart && flutter pub get && flutter build windows
|
||||
- run: cd picking && flutter pub get && flutter build windows
|
||||
- name: Install dependencies
|
||||
run: flutter pub get # even though this is a Dart package, it has as dev_dependency on objective_c for testing which for some reason has a Flutter dependency
|
||||
|
||||
# Uncomment this step to verify the use of 'dart format' on each commit.
|
||||
# - name: Verify formatting
|
||||
# run: dart format --output=none --set-exit-if-changed .
|
||||
|
||||
#- name: Analyze project source
|
||||
# run: dart analyze
|
||||
|
||||
- name: Build and Test
|
||||
shell: cmd
|
||||
run: dart --enable-experiment=native-assets test
|
||||
|
||||
# Upload logs on failure
|
||||
- name: Upload logs
|
||||
if: failure() || steps.build.outcome == 'failure'
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -138,66 +42,41 @@ jobs:
|
||||
name: build-logs
|
||||
path: |
|
||||
D:\a\thermion\thermion\thermion_dart\.dart_tool\thermion_dart\log\build.log
|
||||
# /Users/runner/work/thermion/thermion/thermion_dart//.dart_tool/thermion_dart/log/build.log
|
||||
retention-days: 5
|
||||
# thermion_dart:
|
||||
# name: thermion_dart
|
||||
# runs-on: macos-latest
|
||||
# defaults:
|
||||
# run:
|
||||
# working-directory: thermion_dart
|
||||
# steps:
|
||||
# - uses: actions/checkout@v4
|
||||
# - name: Set up Flutter
|
||||
# uses: subosito/flutter-action@v2
|
||||
# with:
|
||||
# channel: master
|
||||
# - run: flutter pub get
|
||||
# - run: dart --enable-experiment=native-assets test -j1 test/light_tests.dart
|
||||
|
||||
# Capture crash dumps if they exist
|
||||
- name: Collect crash dumps
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: crash-dumps
|
||||
path: |
|
||||
${{ runner.temp }}/*.dmp
|
||||
${{ env.LOCALAPPDATA }}/Temp/*.dmp
|
||||
${{ env.LOCALAPPDATA }}/CrashDumps/*.dmp
|
||||
|
||||
# thermion_flutter:
|
||||
# name: thermion_flutter
|
||||
# runs-on: macos-13
|
||||
# defaults:
|
||||
# run:
|
||||
# working-directory: thermion_flutter/thermion_flutter # Adjust this path
|
||||
|
||||
# steps:
|
||||
# - uses: actions/checkout@v4
|
||||
|
||||
# - uses: dart-lang/setup-dart@9a04e6d73cca37bd455e0608d7e5092f881fd603
|
||||
|
||||
# - name: Install dependencies
|
||||
# run: dart pub get
|
||||
#
|
||||
#
|
||||
##- uses: actions/checkout@v4
|
||||
#- name: Setup LLVM
|
||||
# uses: KyleMayes/install-llvm-action@v1
|
||||
# with:
|
||||
# version: "16"
|
||||
#- name: Add LLVM to PATH
|
||||
# run: |
|
||||
# echo "${{ github.workspace }}/llvm/bin" >> $GITHUB_PATH
|
||||
# echo "LD_LIBRARY_PATH=${{ github.workspace }}/llvm/lib/x86_64-unknown-linux-gnu/" >> $GITHUB_ENV
|
||||
#- name: Verify installation
|
||||
# run: clang --version
|
||||
#- name: Install MESA
|
||||
# run: |
|
||||
# sudo apt-get update
|
||||
# sudo apt-get install -y xvfb
|
||||
# sudo apt-get install -y libosmesa6-dev
|
||||
# #sudo apt-get -y build-dep mesa
|
||||
# #git clone https://gitlab.freedesktop.org/mesa/mesa.git
|
||||
# #cd mesa
|
||||
# #git checkout mesa-23.2.1
|
||||
# #mkdir -p out
|
||||
# #meson setup builddir/ -Dprefix="$(pwd)/out" -Dosmesa=true -Dglx=xlib -Dgallium-drivers=swrast -Dvulkan-drivers=swrast
|
||||
# #meson install -C builddir/
|
||||
#- name: Install Vulkan SDK and dependencies
|
||||
# run: |
|
||||
# wget -qO - https://packages.lunarg.com/lunarg-signing-key-pub.asc | sudo apt-key add -
|
||||
# sudo wget -qO /etc/apt/sources.list.d/lunarg-vulkan-jammy.list https://packages.lunarg.com/vulkan/lunarg-vulkan-jammy.list
|
||||
# sudo apt-get update
|
||||
# sudo apt-get install -y vulkan-sdk
|
||||
#- name: Set up Flutter
|
||||
# uses: subosito/flutter-action@v2
|
||||
# with:
|
||||
# channel: master
|
||||
# architecture: X64
|
||||
|
||||
# # Uncomment this step to verify the use of 'dart format' on each commit.
|
||||
# # - name: Verify formatting
|
||||
# # run: dart format --output=none --set-exit-if-changed .
|
||||
|
||||
# - name: Analyze project source
|
||||
# run: dart analyze
|
||||
|
||||
# - name: Run tests
|
||||
# run: dart --enable-experiment=native-assets test
|
||||
|
||||
2
.gitignore
vendored
@@ -1,4 +1,5 @@
|
||||
**/*/.cxx
|
||||
**/.github
|
||||
**/.idea
|
||||
.dart_tool
|
||||
**/.dart_tool
|
||||
@@ -9,4 +10,3 @@
|
||||
pubspec_overrides.yaml
|
||||
/pubspec.lock
|
||||
*.iml
|
||||
**/*/*.filamat
|
||||
|
||||
186
CHANGELOG.md
@@ -3,192 +3,6 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## 2025-07-24
|
||||
|
||||
### Changes
|
||||
|
||||
---
|
||||
|
||||
Packages with breaking changes:
|
||||
|
||||
- There are no breaking changes in this release.
|
||||
|
||||
Packages with other changes:
|
||||
|
||||
- [`thermion_dart` - `v0.3.3`](#thermion_dart---v033)
|
||||
- [`thermion_flutter_method_channel` - `v0.3.3`](#thermion_flutter_method_channel---v033)
|
||||
- [`thermion_flutter_platform_interface` - `v0.3.3`](#thermion_flutter_platform_interface---v033)
|
||||
- [`thermion_flutter_web` - `v0.3.3`](#thermion_flutter_web---v033)
|
||||
- [`thermion_flutter` - `v0.3.3`](#thermion_flutter---v033)
|
||||
|
||||
---
|
||||
|
||||
#### `thermion_dart` - `v0.3.3`
|
||||
|
||||
- Bump "thermion_dart" to `0.3.3`.
|
||||
|
||||
#### `thermion_flutter_method_channel` - `v0.3.3`
|
||||
|
||||
- Bump "thermion_flutter_method_channel" to `0.3.3`.
|
||||
|
||||
#### `thermion_flutter_platform_interface` - `v0.3.3`
|
||||
|
||||
- Bump "thermion_flutter_platform_interface" to `0.3.3`.
|
||||
|
||||
#### `thermion_flutter_web` - `v0.3.3`
|
||||
|
||||
- Bump "thermion_flutter_web" to `0.3.3`.
|
||||
|
||||
#### `thermion_flutter` - `v0.3.3`
|
||||
|
||||
- Bump "thermion_flutter" to `0.3.3`.
|
||||
|
||||
|
||||
## 2025-07-17
|
||||
|
||||
### Changes
|
||||
|
||||
---
|
||||
|
||||
Packages with breaking changes:
|
||||
|
||||
- There are no breaking changes in this release.
|
||||
|
||||
Packages with other changes:
|
||||
|
||||
- [`thermion_dart` - `v0.3.3-pre`](#thermion_dart---v033-pre)
|
||||
- [`thermion_flutter` - `v0.3.3-pre`](#thermion_flutter---v033-pre)
|
||||
- [`thermion_flutter_method_channel` - `v0.3.3-pre`](#thermion_flutter_method_channel---v033-pre)
|
||||
- [`thermion_flutter_platform_interface` - `v0.3.3-pre`](#thermion_flutter_platform_interface---v033-pre)
|
||||
- [`thermion_flutter_web` - `v0.3.3-pre`](#thermion_flutter_web---v033-pre)
|
||||
|
||||
---
|
||||
|
||||
#### `thermion_dart` - `v0.3.3-pre`
|
||||
|
||||
- **FIX**: fix Windows build.dart.
|
||||
- **FIX**: add nan/negative checks inside setLensProjection.
|
||||
|
||||
#### `thermion_flutter` - `v0.3.3-pre`
|
||||
|
||||
- **DOCS**: replace thermion_flutter README with symlink to thermion_dart README.
|
||||
|
||||
#### `thermion_flutter_method_channel` - `v0.3.3-pre`
|
||||
|
||||
- **FEAT**: allow passing renderTargetColorTextureFormat via ThermionFlutterOptions.
|
||||
|
||||
#### `thermion_flutter_platform_interface` - `v0.3.3-pre`
|
||||
|
||||
- **FEAT**: allow passing renderTargetColorTextureFormat via ThermionFlutterOptions.
|
||||
|
||||
#### `thermion_flutter_web` - `v0.3.3-pre`
|
||||
|
||||
- Bump "thermion_flutter_web" to `0.3.3-pre`.
|
||||
|
||||
|
||||
## 2025-07-08
|
||||
|
||||
### Changes
|
||||
|
||||
---
|
||||
|
||||
Packages with breaking changes:
|
||||
|
||||
- There are no breaking changes in this release.
|
||||
|
||||
Packages with other changes:
|
||||
|
||||
- [`thermion_dart` - `v0.3.2`](#thermion_dart---v032)
|
||||
- [`thermion_flutter` - `v0.3.2`](#thermion_flutter---v032)
|
||||
- [`thermion_flutter_method_channel` - `v0.3.2`](#thermion_flutter_method_channel---v032)
|
||||
- [`thermion_flutter_web` - `v0.3.2`](#thermion_flutter_web---v032)
|
||||
- [`thermion_flutter_platform_interface` - `v0.3.2`](#thermion_flutter_platform_interface---v032)
|
||||
|
||||
---
|
||||
|
||||
#### `thermion_dart` - `v0.3.2`
|
||||
|
||||
- Bump "thermion_dart" to `0.3.2`.
|
||||
|
||||
#### `thermion_flutter` - `v0.3.2`
|
||||
|
||||
- Bump "thermion_flutter" to `0.3.2`.
|
||||
|
||||
#### `thermion_flutter_method_channel` - `v0.3.2`
|
||||
|
||||
- Bump "thermion_flutter_method_channel" to `0.3.2`.
|
||||
|
||||
#### `thermion_flutter_web` - `v0.3.2`
|
||||
|
||||
- **FIX**: add missing destroySwapchain argument for web.
|
||||
|
||||
#### `thermion_flutter_platform_interface` - `v0.3.2`
|
||||
|
||||
- Bump "thermion_flutter_platform_interface" to `0.3.2`.
|
||||
|
||||
|
||||
## 2025-07-08
|
||||
|
||||
### Changes
|
||||
|
||||
---
|
||||
|
||||
Packages with breaking changes:
|
||||
|
||||
- There are no breaking changes in this release.
|
||||
|
||||
Packages with other changes:
|
||||
|
||||
- [`thermion_dart` - `v0.3.1`](#thermion_dart---v031)
|
||||
- [`thermion_flutter` - `v0.3.1`](#thermion_flutter---v031)
|
||||
- [`thermion_flutter_method_channel` - `v0.3.1`](#thermion_flutter_method_channel---v031)
|
||||
- [`thermion_flutter_web` - `v0.3.1`](#thermion_flutter_web---v031)
|
||||
- [`thermion_flutter_platform_interface` - `v0.3.1`](#thermion_flutter_platform_interface---v031)
|
||||
|
||||
---
|
||||
|
||||
#### `thermion_dart` - `v0.3.1`
|
||||
|
||||
- **REFACTOR**: remove covariant keyword from createInstance args.
|
||||
- **FIX**: add flush() to skybox/IBL destroy methods to ensure that textre upload callbacks are completed to avoid stalling.
|
||||
- **FIX**: duplicate setting for _grid.
|
||||
|
||||
#### `thermion_flutter` - `v0.3.1`
|
||||
|
||||
- **FIX**: addDestroySwapchain argument to createViewer() (true by default). This is only used on iOS/macOS where a single swapchain is shared between all render targets.
|
||||
- **DOCS**: fix typo in link.
|
||||
- **DOCS**: remove code from thermion_flutter README.md and point to docs/repository example instead.
|
||||
|
||||
#### `thermion_flutter_method_channel` - `v0.3.1`
|
||||
|
||||
- **FIX**: addDestroySwapchain argument to createViewer() (true by default). This is only used on iOS/macOS where a single swapchain is shared between all render targets.
|
||||
|
||||
#### `thermion_flutter_web` - `v0.3.1`
|
||||
|
||||
#### `thermion_flutter_platform_interface` - `v0.3.1`
|
||||
|
||||
- **FIX**: addDestroySwapchain argument to createViewer() (true by default). This is only used on iOS/macOS where a single swapchain is shared between all render targets.
|
||||
|
||||
# Change Log
|
||||
|
||||
#### v0.3.0
|
||||
|
||||
This release involved considerable internal refactoring, allowing us to expose more Filament functionality on the Dart side. Previously, most of this functionality was
|
||||
rigidly implemented in C++ and didn't allow for end-users to take advantage of Filament directly.
|
||||
|
||||
This also means there are a number of breaking changes from `0.2.1`. To summarize:
|
||||
|
||||
- `ViewerWidget` has been introduced. This is a Flutter widget for users who only need basic rendering and don't need/want to deal with camera/materials/etc directly.
|
||||
- Users who want more fine-grained control than a `ViewerWidget` can still work with `ThermionViewer` and `ThermionWidget`.
|
||||
- The singleton `FilamentApp.instance` exposes methods for working almost directly with the underlying Filament engine (e.g. loading custom materials from `Uint8List`, creating textures, etc).
|
||||
- New interfaces have been added for `Material`, `MaterialInstance`, `Texture`, `View`, `Scene` and `Camera`.
|
||||
- `ThermionAsset` replaces `ThermionEntity` as the main interface for scene objects.
|
||||
- Transforms/material instances should be set directly by `asset.setTransform`, `asset.setMaterialInstanceAt`
|
||||
- Material properties can be set directly on the `MaterialInstance`, e.g. `materialInstance.setParameterFloat4("baseColorFactor", 1.0, 0.0, 0.0, 1.0);
|
||||
- Linux binaries have been added to `thermion_dart`. This package can be run on Linux (which we are using for CI and automated testing) but there are not yet any Flutter bindings, so `thermion_flutter` cannot run on Linux yet.
|
||||
- On Windows, `thermion_flutter` now uses the Vulkan backend. This is still experimental and will have limited supported on older hardware (pre-2018).
|
||||
- Web support for `thermion_dart` has now reached parity with other platforms, though should still be considered experimental. Some manual steps are required to run in a Flutter app or a Dart web app.
|
||||
|
||||
## 2025-01-08
|
||||
|
||||
### Changes
|
||||
|
||||
76
Dockerfile
@@ -1,76 +0,0 @@
|
||||
FROM ubuntu:22.04
|
||||
|
||||
# Set non-interactive mode for apt
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# Install dependencies and add LLVM repository
|
||||
RUN apt-get update && apt-get install -y \
|
||||
git \
|
||||
build-essential \
|
||||
cmake \
|
||||
ninja-build \
|
||||
libgl1-mesa-dev \
|
||||
libc++-dev \
|
||||
libc++abi-dev \
|
||||
libsdl2-dev \
|
||||
libxi-dev \
|
||||
libtbb-dev \
|
||||
libassimp-dev \
|
||||
python3 \
|
||||
python3-pip \
|
||||
curl \
|
||||
wget \
|
||||
software-properties-common \
|
||||
lsb-release \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Add LLVM repository and install Clang 16
|
||||
RUN wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - \
|
||||
&& add-apt-repository "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-16 main" \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y \
|
||||
clang-16 \
|
||||
clang++-16 \
|
||||
libc++-16-dev \
|
||||
libc++abi-16-dev \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Set Clang 16 as default
|
||||
RUN update-alternatives --install /usr/bin/clang clang /usr/bin/clang-16 100 \
|
||||
&& update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-16 100
|
||||
|
||||
# Set environment variables for Clang
|
||||
ENV CC=clang-16
|
||||
ENV CXX=clang++-16
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /opt
|
||||
|
||||
# Clone the filament repository
|
||||
RUN git clone https://github.com/google/filament.git
|
||||
|
||||
# Change to filament directory
|
||||
WORKDIR /opt/filament
|
||||
|
||||
# Checkout the specific version
|
||||
RUN git checkout v1.58.0
|
||||
|
||||
# Add CMAKE_POSITION_INDEPENDENT_CODE setting after project() line
|
||||
RUN sed -i '/^project(/a set(CMAKE_POSITION_INDEPENDENT_CODE ON)\nadd_compile_definitions(GLTFIO_USE_FILESYSTEM=0)' CMakeLists.txt
|
||||
RUN sed -i -e '/^#define GLTFIO_USE_FILESYSTEM 1$/i\
|
||||
#ifndef GLTFIO_USE_FILESYSTEM' -e '/^#define GLTFIO_USE_FILESYSTEM 1$/a\
|
||||
#endif' libs/gltfio/src/FFilamentAsset.h
|
||||
|
||||
# Make build script executable
|
||||
RUN chmod +x build.sh
|
||||
|
||||
# Run the build commands
|
||||
RUN ./build.sh -l -i -f -p desktop release
|
||||
RUN ./build.sh -l -i -f -p desktop release zstd
|
||||
RUN ./build.sh -l -i -f -p desktop release tinyexr
|
||||
RUN ./build.sh -l -i -f -p desktop release imageio
|
||||
RUN zip -r filament-v1.58.0-linux-release.zip /opt/filament/out/release/filament/lib/x86_64/*.a /opt/filament/out/cmake-release/third_party/tinyexr/tnt/libtinyexr.a /opt/filament/out/cmake-release/libs/imageio/libimageio.a
|
||||
# Set the working directory to the build output
|
||||
WORKDIR /opt/filament/out/release
|
||||
|
||||
CMD ["/bin/bash"]
|
||||
52
Makefile
@@ -1,36 +1,21 @@
|
||||
wasm:
|
||||
@if [ ! -f thermion_dart/native/web/lib/release/filament-v1.58.0-web-release.zip ]; then \
|
||||
echo "Downloading filament-v1.58.0-web-release.zip..."; \
|
||||
mkdir -p thermion_dart/native/web/lib/release; \
|
||||
curl -L -o thermion_dart/native/web/lib/release/filament-v1.58.0-web-release.zip \
|
||||
https://pub-c8b6266320924116aaddce03b5313c0a.r2.dev/filament-v1.58.0-web-release.zip; \
|
||||
echo "Extracting filament-v1.58.0-web-release.zip..."; \
|
||||
cd thermion_dart/native/web/lib/release && \
|
||||
unzip filament-v1.58.0-web-release.zip; \
|
||||
fi
|
||||
cd thermion_dart/native/web && \
|
||||
mkdir -p build && \
|
||||
cd build && \
|
||||
emcmake cmake .. && \
|
||||
emmake make
|
||||
wasm-clean:
|
||||
dart-web:
|
||||
cd thermion_dart/native/web; mkdir -p build && cd build && emcmake cmake .. && emmake make
|
||||
dart-web-clean:
|
||||
cd thermion_dart/native/web && rm -rf build
|
||||
wasm-example-web:
|
||||
cd examples/dart/js_wasm
|
||||
mkdir -p build
|
||||
dart compile js web/example.dart -o build/example.dart.js
|
||||
|
||||
dart-wasm-cli-example: dart-web-clean dart-web
|
||||
cd thermion_dart/examples/cli_wasm/bin && dart compile wasm example_cli.dart && node main.js
|
||||
dart-web-example: dart-web
|
||||
cp thermion_dart/native/web/build/build/out/thermion_dart* examples/web_wasm/bin
|
||||
cd thermion_dart/examples/web_wasm/bin && dart compile wasm example_web.dart
|
||||
flutter-example-web: dart-web-clean dart-web
|
||||
cd thermion_flutter_federated/thermion_flutter/example/web && dart compile wasm main.dart && cd .. && flutter build web --wasm --profile
|
||||
flutter-example-macos:
|
||||
cd thermion_flutter_federated/thermion_flutter/example/web && flutter run -d macos
|
||||
swift-bindings:
|
||||
swiftc -c thermion_dart/native/macos/ThermionTexture.swift -module-name swift_module -emit-objc-header-path thermion_dart/native/include/generated/ThermionTextureSwiftObjCAPI.h -emit-library -o thermion_dart/test/generated/libThermionTextureSwift.dylib
|
||||
swiftc -c thermion_flutter/thermion_flutter/macos/Classes/ThermionTexture.swift -module-name swift_module -emit-objc-header-path thermion_dart/native/include/generated/ThermionTextureSwiftObjCAPI.h -emit-library -o thermion_dart/test/libThermionTextureSwift.dylib
|
||||
cd thermion_dart/ && dart --enable-experiment=native-assets run ffigen --config ffigen/swift.yaml
|
||||
bindings:
|
||||
cd thermion_dart/ && dart --enable-experiment=native-assets run ffigen --config ffigen/native.yaml
|
||||
shared:
|
||||
cd thermion_dart/native && make
|
||||
|
||||
# We compile a small set of custom materials for various helpers (background image, gizmo, etc)
|
||||
# You must specify the `FILAMENT_PATH` environment variable, either the path /out/release
|
||||
@@ -41,19 +26,12 @@ ifndef FILAMENT_PATH
|
||||
@echo "FILAMENT_PATH is not set"
|
||||
else
|
||||
@echo "Using Filament build from ${FILAMENT_PATH}"
|
||||
./materials/build.sh
|
||||
endif
|
||||
|
||||
resources: FORCE
|
||||
ifndef FILAMENT_PATH
|
||||
@echo "FILAMENT_PATH is not set"
|
||||
else
|
||||
@echo "Using Filament build from ${FILAMENT_PATH}"
|
||||
@for gizmo in translation rotation; do \
|
||||
$(FILAMENT_PATH)/resgen -c -p $${gizmo}_gizmo_glb -x thermion_dart/native/include/resources assets/$${gizmo}_gizmo.glb || exit 1; \
|
||||
echo '#include "'$${gizmo}_gizmo_glb.h'"' | cat - thermion_dart/native/include/resources/$${gizmo}_gizmo_glb.c > thermion_dart/native/include/resources/$${gizmo}_gizmo_glb.c.new; \
|
||||
mv thermion_dart/native/include/resources/$${gizmo}_gizmo_glb.c.new thermion_dart/native/include/resources/$${gizmo}_gizmo_glb.c; \
|
||||
@for material in unlit image unlit_fixed_size grid; do \
|
||||
${FILAMENT_PATH}/matc -a opengl -a metal -a vulkan -o materials/$$material.filamat materials/$$material.mat; \
|
||||
$(FILAMENT_PATH)/resgen -c -p $$material -x thermion_dart/native/include/material/ materials/$$material.filamat; \
|
||||
echo '#include "'$$material'.h"' | cat - thermion_dart/native/include/material/$$material.c > thermion_dart/native/include/material/$$material.c.new; \
|
||||
mv thermion_dart/native/include/material/$$material.c.new thermion_dart/native/include/material/$$material.c; \
|
||||
done
|
||||
endif
|
||||
|
||||
FORCE: ;
|
||||
FORCE: ;
|
||||
71
README.md
@@ -15,8 +15,6 @@
|
||||
<a href="https://discord.gg/h2VdDK3EAQ"><img src="https://img.shields.io/discord/993167615587520602?logo=discord&logoColor=fff&labelColor=333940" alt="discord"></a>
|
||||
<a href="https://github.com/nmfisher/thermion"><img src="https://img.shields.io/github/contributors/nmfisher/flutter_filament?logo=github&labelColor=333940" alt="contributors"></a>
|
||||
|
||||
https://github.com/user-attachments/assets/b0c07b5a-6156-4e42-a09b-5f9bd85fbf32
|
||||
|
||||
### Features
|
||||
|
||||
- Supports iOS (arm64), MacOS (arm64/x64), Android (arm64), Windows (x64) (>= 10), Web/WASM
|
||||
@@ -24,8 +22,6 @@ https://github.com/user-attachments/assets/b0c07b5a-6156-4e42-a09b-5f9bd85fbf32
|
||||
- camera/entity manipulation with mouse (desktop) and gestures (mobile)
|
||||
- skinning + morph animations
|
||||
|
||||
Uses the Filament PBR engine (currently v1.56.4).
|
||||
|
||||
### Quickstart (Flutter)
|
||||
|
||||
From the command line:
|
||||
@@ -39,31 +35,49 @@ flutter config --enable-native-assets
|
||||
In your Flutter app:
|
||||
|
||||
```dart
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Stack(children: [
|
||||
Positioned.fill(
|
||||
child: ViewerWidget(
|
||||
assetPath: "assets/cube.glb",
|
||||
skyboxPath: "assets/default_env_skybox.ktx",
|
||||
iblPath: "assets/default_env_ibl.ktx",
|
||||
transformToUnitCube: true,
|
||||
initialCameraPosition: Vector3(0, 0, 6),
|
||||
background: Colors.blue,
|
||||
manipulatorType: ManipulatorType.ORBIT,
|
||||
onViewerAvailable: (viewer) async {
|
||||
await Future.delayed(const Duration(seconds: 5));
|
||||
await viewer.removeSkybox();
|
||||
},
|
||||
initial: Container(
|
||||
color: Colors.red,
|
||||
),
|
||||
))]));
|
||||
}
|
||||
_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);
|
||||
```
|
||||
|
||||
> the first time you build an app that consumes this package, the Dart native-assets build system will download static binaries from Cloudflare. This may take a few minutes (depending on which platform you are compiling for). These will be cached, so subsequent builds will be much faster.
|
||||
and then in your widget tree:
|
||||
```dart
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(children: [
|
||||
if (_thermionViewer != null)
|
||||
Positioned.fill(
|
||||
child: ThermionWidget(
|
||||
viewer: _thermionViewer!,
|
||||
)),
|
||||
]);
|
||||
}
|
||||
```
|
||||
|
||||
### Sponsors, Contributors & Acknowledgments
|
||||
|
||||
@@ -78,5 +92,4 @@ Thank you to the following people:
|
||||
- @daverin for MacOS library contributions
|
||||
- @LukasPoque for CI/refactoring work
|
||||
- @alexmercerind for his work on integrating ANGLE textures on Flutter Windows
|
||||
- @BrutalCoding for documentation fixes
|
||||
- @chenriji for testing and bug fixes
|
||||
|
||||
|
||||
@@ -7,21 +7,15 @@
|
||||
"Getting Started",
|
||||
[
|
||||
["Overview", "/"],
|
||||
["Getting Started", "/getting_started"],
|
||||
["Quick Start", "/quickstart"],
|
||||
["Viewer", "/viewer"],
|
||||
["Camera Manipulation", "/camera_manipulation"]
|
||||
]
|
||||
],
|
||||
["Misc.", [
|
||||
["Debugging", "/debugging"],
|
||||
["Playground", "https://dartpad.thermion.dev"],
|
||||
["Showcase", "/showcase"],
|
||||
["Windows", "/windows"],
|
||||
["Android", "/android"],
|
||||
["iOS", "/ios"],
|
||||
["Web", "/web"],
|
||||
["Linux", "/linux"],
|
||||
["Contributing", "/contributing"],
|
||||
["Discord", "https://discord.gg/h2VdDK3EAQ"]
|
||||
]]
|
||||
|
||||
@@ -12,3 +12,15 @@ Thermion requires Android SDK version 22, so change your `app/android/build.grad
|
||||
}
|
||||
```
|
||||
|
||||
### Shrink/Minify Resources
|
||||
|
||||
In release mode, you must add the following to your `app/build.gradle`:
|
||||
|
||||
```
|
||||
buildTypes {
|
||||
release {
|
||||
shrinkResources false
|
||||
minifyEnabled false
|
||||
}
|
||||
}
|
||||
```
|
||||
63
docs/camera_manipulation.mdx
Normal file
@@ -0,0 +1,63 @@
|
||||
## Camera Manipulation (Flutter)
|
||||
|
||||
> You can find the entire project below in the [flutter/quickstart](https://github.com/nmfisher/thermion/examples/flutter/camera_manipulation) folder.
|
||||
|
||||
A `ThermionListenerWidget` is one option for manipulating the camera with an input device (e.g. mouse or touchscreen gestures).
|
||||
|
||||
This will generally wrap a `ThermionWidget`, meaning the entire viewport will act as a receiver for gesture events.
|
||||
|
||||
> You can position this independently (for example, stacked vertically beneath the viewport), but this will not translate picking queries correctly.
|
||||
|
||||
```
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(children: [
|
||||
if (_thermionViewer != null)
|
||||
Positioned.fill(
|
||||
child: ThermionListenerWidget(
|
||||
inputHandler:
|
||||
DelegateInputHandler.fixedOrbit(_thermionViewer!)
|
||||
..setActionForType(InputType.MMB_HOLD_AND_MOVE, InputAction.ROTATE)
|
||||
..setActionForType(InputType.SCALE1, InputAction.ROTATE)
|
||||
..setActionForType(InputType.SCALE2, InputAction.ZOOM)
|
||||
..setActionForType(InputType.SCROLLWHEEL, InputAction.ZOOM),
|
||||
child: ThermionWidget(
|
||||
viewer: _thermionViewer!,
|
||||
))),
|
||||
]);
|
||||
```
|
||||
|
||||
`ThermionListenerWidget` is a very simple widget; it simply forwards pointer, gesture and keyboard events to the provided [InputHandler], which must decide how to interpret those events.
|
||||
|
||||
For example, one [InputHandler] implementation might interpret mouse pointer movement as "rotate the camera", whereas a separate implementation might interpret it as "translate this specific entity".
|
||||
|
||||
Thermion provides two default InputHandler implementations for manipulating the camera: [DelegateInputHandler.fixedOrbit] and [DelegateInputHandler.flight].
|
||||
|
||||
[DelegateInputHandler.fixedOrbit] will rotate the camera in a fixed orbit around a target point (the origin, by default), and also allow zooming in/out (subject to a minimum distance, which is configurable).
|
||||
|
||||
By default, [DelegateInputHandler.fixedOrbit] will:
|
||||
- rotate the camera when the middle mouse button is held and the pointer is moved (on desktop), and when a single swipe left/right/up/down is detected (on mobile)
|
||||
- zoom the camera when the scroll wheel is scrolled up/down (on desktop), and when a pinch gesture is detected (on mobile)
|
||||
|
||||
You can change the action for a specific input type by calling `setActionForType`; for example, if you wanted to rotate the camera by moving the mouse pointer while holding the left mouse button, you would call:
|
||||
|
||||
```
|
||||
setActionForType(InputType.LMB_HOLD_AND_MOVE, InputAction.ROTATE)
|
||||
```
|
||||
|
||||
See the [InputType] and [InputAction] enums for available input types and actions.
|
||||
|
||||
[DelegateInputHandler.flight] will translate keyboard and mouse/touchscreen gestures to free flight camera manipulation.
|
||||
|
||||
By default:
|
||||
- holding the middle mouse button will control the pitch/roll/yaw of the camera
|
||||
- holding the left mouse button will pan the camera left/right/up/down
|
||||
- the middle mouse button will zoom/dolly the camera in/out
|
||||
- the WASD keys will pan the camera left/right/up/down and dolly the camera forward/backward
|
||||
|
||||
If these don't exactly fit your use case, you can create your own [InputHandler] implementation. If you think it would be useful to other users, please feel free to submit a PR for your implementation to be included in the base Thermion package.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
# Debugging
|
||||
|
||||
If something is crashing or not working as expected, you can enable verbose logging and/or debug builds (particularly useful for debugging with lldb or getting legible stack traces):
|
||||
|
||||
Add a `hooks` section to your app's `pubspec.yaml`, e.g.
|
||||
```
|
||||
name: example_cli
|
||||
description: A sample command-line application.
|
||||
version: 1.0.0
|
||||
|
||||
environment:
|
||||
sdk: ^3.3.0
|
||||
|
||||
# Add the below
|
||||
hooks:
|
||||
user_defines:
|
||||
thermion_dart:
|
||||
mode: debug
|
||||
tracing: enabled
|
||||
```
|
||||
|
||||
After changing the `hooks` section, make sure you run `flutter clean` to propagate the changes correctly.
|
||||
|
||||
> [!CAUTION]
|
||||
> Debug builds won't work for Android. This is a known upstream issue with Filament.
|
||||
|
||||
Unless `mode: debug` is specified in your `pubspec.yaml`, Thermion will use release builds under the hood, even if your app is compiled/runing in debug mode.
|
||||
@@ -1,40 +0,0 @@
|
||||
## Getting Started
|
||||
|
||||
Thermion currently requires the Flutter `master` channel with the `native-assets` experiment enabled.
|
||||
|
||||
1. Switch to Flutter master channel, upgrade Flutter, create a new project, then add `thermion_flutter` as a dependency
|
||||
|
||||
```bash
|
||||
$ flutter channel master
|
||||
$ flutter upgrade
|
||||
$ flutter config --enable-native-assets
|
||||
$ cd your_flutter_project
|
||||
$ flutter pub add thermion_flutter
|
||||
```
|
||||
|
||||
2. If running on iOS or MacOS, change the minimum deployment target to OSX 13
|
||||
|
||||
<Accordion title="Click to open iOS/MacOS instructions">
|
||||
|
||||
Make sure the `platform` entry refers to `13.0` in your Podfile.
|
||||
|
||||
In `macos/Podfile` (for macOS):
|
||||
```
|
||||
platform :osx, '13.0'
|
||||
```
|
||||
|
||||
In `ios/Podfile`, (for iOS):
|
||||
```
|
||||
platform :ios, '13.0'
|
||||
```
|
||||
|
||||
Then open XCode:
|
||||
```
|
||||
open macos/Runner.xcworkspace
|
||||
```
|
||||
|
||||
and change the minimum deployment target to 13.0:
|
||||
|
||||

|
||||
|
||||
</Accordion>
|
||||
@@ -16,7 +16,7 @@ Thermion is divided into two packages:
|
||||
|
||||
With this structure, the Flutter-specific components are not coupled to the Dart components, meaning Thermion can be used for rendering in both Flutter and non-Flutter applications.
|
||||
|
||||
For example, Thermion ships with examples for rendering with Dart only (no Flutter) with a CLI/headless application on MacOS, and with a Javascript/WASM/HTML application in browsers.
|
||||
For example, Thermion ships with examples for rendering with Dart only (no Flutter) with a CLI/headless application on MacOS, and with a Javascript/WASM/HTML applicaiton in browsers.
|
||||
|
||||
`thermion_flutter` exports `thermion_dart`, so if you are working with a Flutter application, you will only need to import `thermion_fluttter`.
|
||||
|
||||
|
||||
55
docs/ios.mdx
@@ -1,55 +0,0 @@
|
||||
## iOS
|
||||
|
||||
### Min iOS version
|
||||
|
||||
Thermion requires a minimum iOS version of 13.0. When building a Flutter application, ensure your application's `ios/Podfile` contains the following:
|
||||
|
||||
```ruby
|
||||
platform :ios, '13.0'
|
||||
```
|
||||
|
||||
and in ios/Info.plist:
|
||||
|
||||
```xml
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>13.0</string>
|
||||
```
|
||||
|
||||
When submitting to the App Store, you may encounter an error saying `thermion_dart.framework does not supported the minimum deployment target in Info.plist`.
|
||||
|
||||
This is because Flutter hardcodes a deployment target of iOS 12.0 when invoking the native assets build, which conflicts with actual requirement.
|
||||
|
||||
After running `flutter build ios` (but before archiving the build and submitting to the App Store), run the following script to replace the `MinimumOSVersion`:
|
||||
|
||||
```
|
||||
#!/bin/zsh
|
||||
|
||||
# Array of directories containing Info.plist files
|
||||
directories=(
|
||||
"./build/ios/iphoneos/Runner.app/Frameworks/thermion_dart.framework"
|
||||
"./build/ios/Release-iphoneos/Runner.app/Frameworks/thermion_dart.framework"
|
||||
"./build/native_assets/ios/thermion_dart.framework"
|
||||
)
|
||||
|
||||
# Loop through each directory
|
||||
for dir in "${directories[@]}"; do
|
||||
plist_path="$dir/Info.plist"
|
||||
|
||||
# Check if Info.plist exists in the directory
|
||||
if [[ -f "$plist_path" ]]; then
|
||||
echo "Processing: $plist_path"
|
||||
|
||||
# Use PlistBuddy to change the MinimumOSVersion
|
||||
/usr/libexec/PlistBuddy -c "Set :MinimumOSVersion 13.0" "$plist_path" 2>/dev/null
|
||||
|
||||
if [[ $? -eq 0 ]]; then
|
||||
echo "✓ Successfully updated version to 13.0"
|
||||
else
|
||||
echo "✗ Failed to update version in $plist_path"
|
||||
fi
|
||||
else
|
||||
echo "✗ Info.plist not found in $dir"
|
||||
fi
|
||||
done
|
||||
```
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
## Linux support
|
||||
|
||||
Currently, only the Dart package (`thermion_dart`) will work on Linux (primarily for the automated build/testing pipeline).
|
||||
|
||||
Filament has been built for Ubuntu 22.04; other distributions may work, but YMMV.
|
||||
|
||||
The Flutter package (`thermion_flutter`) won't work; it's missing the platform glue code necessary to set up the render target. Support will eventually be added, but there is currently no estimated timeline.
|
||||
|
||||
Contributions are welcome and it's actually not a lot of work. Join the Discord if you want to help out.
|
||||
|
||||
@@ -1,199 +1,216 @@
|
||||
# Quick Start
|
||||
## Quickstart (Flutter)
|
||||
|
||||
If all you need is a quick and easy route to rendering a single 3D model in your Flutter application, start with `ViewerWidget`.
|
||||
> You can find the entire project below in the [flutter/quickstart](https://github.com/nmfisher/thermion_examples/tree/master/flutter/quickstart) folder of the `thermion_examples` repository.
|
||||
|
||||
This is a simplified, Flutter-only wrapper around the underlying 3D rendering API with sane defaults for most people.
|
||||
1. Switch to Flutter master channel, upgrade Flutter, create a new project, then add `thermion_flutter` as a dependency
|
||||
|
||||
`ViewerWidget` handles all the setup and configuration of the underlying Thermion API, including:
|
||||
- Loading 3D models (glTF assets)
|
||||
- Configuring skyboxes and image-based lighting
|
||||
- Setting up camera positions and manipulators
|
||||
- Managing the rendering lifecycle
|
||||
```bash
|
||||
$ flutter channel master
|
||||
$ flutter upgrade
|
||||
$ flutter config --enable-native-assets
|
||||
$ flutter create thermion_sample_project && cd thermion_sample_project
|
||||
$ flutter pub add thermion_flutter
|
||||
```
|
||||
|
||||
## Setup
|
||||
2. If running on iOS or MacOS, change the minimum deployment target to OSX 13
|
||||
|
||||
Follow the steps listed in [Getting Started](./getting_started) to configure your Flutter installation and project.
|
||||
<Accordion title="Click to open iOS/MacOS instructions">
|
||||
|
||||
If you're running Windows, delete the `examples/flutter/quickstart/assets` symlink and copy the `assets` folder from `examples/assets` to `examples/flutter/quickstart/assets`.
|
||||
Make sure the `platform` entry refers to `13.0` in your Podfile.
|
||||
|
||||
## Basic Usage
|
||||
In `macos/Podfile` (for macOS):
|
||||
```
|
||||
platform :osx, '13.0'
|
||||
```
|
||||
|
||||
In `ios/Podfile`, (for iOS):
|
||||
```
|
||||
platform :ios, '13.0'
|
||||
```
|
||||
|
||||
Then open XCode:
|
||||
```
|
||||
open macos/Runner.xcworkspace
|
||||
```
|
||||
|
||||
and change the minimum deployment target to 13.0:
|
||||
|
||||

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

|
||||
|
||||
Your first Thermion project is complete!
|
||||
|
||||
@@ -1,25 +1,18 @@
|
||||
## Showcase
|
||||
|
||||
## KTX Viewer
|
||||
|
||||
https://ktxviewer.com
|
||||
|
||||
A basic HTML + Dart site for viewing KTX textures in browser.
|
||||
|
||||
## DartPad Playground
|
||||
|
||||
A custom DartPad that lets you experiment with Thermion from your browser (currently, only Chrome is supported).
|
||||
|
||||
[](https://dartpad.thermion.dev)
|
||||
|
||||
(Outdated, needs to be upgraded to Thermion `0.3.0`);
|
||||
|
||||
## mixreel (Flutter/Web)
|
||||
|
||||
Create 3D worlds and translate to AI video.
|
||||
|
||||
[](https://mixreel.ai)
|
||||
|
||||
|
||||
## Nick Fisher
|
||||
|
||||
My personal website, where I create an interactive clone of myself with Avaturn & Cartesia (no Flutter, made with Thermion and the [Jaspr Dart UI framework](https://github.com/schultek/jaspr)).
|
||||
@@ -28,4 +21,3 @@ My personal website, where I create an interactive clone of myself with Avaturn
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
186
docs/viewer.mdx
@@ -1,186 +0,0 @@
|
||||
## ThermionViewer (Flutter)
|
||||
|
||||
If you just want to display a 3D object in the viewport with some basic camera controls, use the [ViewerWidget described in the Quickstart section](./quickstart).
|
||||
|
||||
If you need want more fine-grained control
|
||||
|
||||
> You can find the entire project below in the [examples/flutter/viewer](https://github.com/nmfisher/thermion/tree/master/examples/flutter/viewer) folder of the repository.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
2. Add a folder containing your assets (glTF model + skybox ktx) to your `pubspec.yaml` asset list
|
||||
|
||||
```yaml
|
||||
...
|
||||
flutter
|
||||
assets:
|
||||
- assets/
|
||||
```
|
||||
|
||||
3. Create an instance of `ThermionFlutterPlugin` in your app.
|
||||
|
||||
```dart
|
||||
|
||||
class _MyAppState extends State<MyApp> {
|
||||
late Future<ThermionViewer> _thermionViewer;
|
||||
void initState() {
|
||||
ThermionFlutterPlugin.createViewer().then((viewer) {
|
||||
_thermionViewer = viewer;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
4. Add a `ThermionWidget` to your widget hierarchy
|
||||
|
||||
```dart
|
||||
|
||||
class _MyAppState extends State<MyApp> {
|
||||
|
||||
ThermionViewer? _thermionViewer;
|
||||
void initState() {
|
||||
_thermionFlutterPlugin.createViewer().then((viewer) {
|
||||
setState(() {
|
||||
_thermionViewer = viewer;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(children:[
|
||||
if(_thermionViewer != null)
|
||||
Positioned.fill(
|
||||
child:ThermionWidget(
|
||||
plugin:_thermionViewer!
|
||||
)
|
||||
)
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
4. Add a button to load the model when pressed
|
||||
|
||||
```dart
|
||||
|
||||
...
|
||||
|
||||
class _MyAppState extends State<MyApp> {
|
||||
|
||||
...
|
||||
|
||||
bool _loaded = false;
|
||||
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(children:[
|
||||
if(_thermionViewer != null)
|
||||
Positioned.fill(
|
||||
child:ThermionWidget(
|
||||
plugin:_thermionViewer!
|
||||
)
|
||||
),
|
||||
if (!_loaded)
|
||||
Center(
|
||||
child: ElevatedButton(
|
||||
child: const Text("Load"),
|
||||
onPressed: () async {
|
||||
// TODO
|
||||
_loaded = true;
|
||||
setState(() {});
|
||||
}))
|
||||
]);
|
||||
}}
|
||||
```
|
||||
|
||||
5. When the button is pressed, load a skybox, lighting and the glb asset
|
||||
|
||||
You will need to import the `dart:math` and `package:vector_math` libraries.
|
||||
|
||||
```dart
|
||||
import 'package:vector_math/vector_math_64.dart' as v;
|
||||
import 'dart:math';
|
||||
|
||||
...
|
||||
|
||||
class _MyAppState extends State<MyApp> {
|
||||
|
||||
...
|
||||
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(children:[
|
||||
...
|
||||
if(!_loaded)
|
||||
Center(
|
||||
child: ElevatedButton(
|
||||
child: const Text("Load"),
|
||||
onPressed: () async {
|
||||
var viewer = await _thermionViewer;
|
||||
await viewer.loadIbl("assets/default_env_ibl.ktx");
|
||||
await viewer.loadSkybox("assets/default_env_skybox.ktx");
|
||||
await viewer.loadGlb("assets/cube.glb");
|
||||
|
||||
await viewer.setCameraPosition(0, 1, 10);
|
||||
await viewer.setCameraRotation(v.Quaternion.axisAngle(
|
||||
v.Vector3(1, 0, 0), -30 / 180 * pi) *
|
||||
v.Quaternion.axisAngle(v.Vector3(0, 1, 0), 15 / 180 * pi));
|
||||
await viewer.addLight(
|
||||
LightType.SUN, 7500, 50000, 0, 0, 0, 1, -1, -1);
|
||||
await viewer.setRendering(true);
|
||||
_loaded = true;
|
||||
setState(() {});
|
||||
}
|
||||
)
|
||||
)
|
||||
]);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Here, we've added a skybox (the background (cube) image rendered behind all other elements in the scene), image-based lighting (where an image is used to determine the direction and intensity of a light source) and a directional light (Sun).
|
||||
|
||||
Anything added to the scene is referred to as an "entity" (including lights and cameras).
|
||||
|
||||
Entities are always added to the scene at position (0,0,0).
|
||||
|
||||
The default scene camera is located at (0,0,0) (and is looking at -Z, or "into" the screen), so by adding a cube at (0,0,0), the camera will now be inside the cube.
|
||||
|
||||
We need to move the camera outside the cube so it's visible.
|
||||
|
||||
6. Change the camera orientation
|
||||
```dart
|
||||
var viewer = await _thermionViewer;
|
||||
await viewer.loadSkybox("assets/default_env_skybox.ktx");
|
||||
await viewer.loadGlb("assets/cube.glb");
|
||||
|
||||
await viewer.setCameraPosition(0, 1, 10);
|
||||
await viewer.setCameraRotation(v.Quaternion.axisAngle(
|
||||
v.Vector3(1, 0, 0), -30 / 180 * pi) *
|
||||
v.Quaternion.axisAngle(v.Vector3(0, 1, 0), 15 / 180 * pi));
|
||||
```
|
||||
|
||||
The cube still won't be visible until we add a light to the scene and tell Thermion to start rendering.
|
||||
|
||||
7. Add a light and turn rendering on
|
||||
```dart
|
||||
...
|
||||
await viewer.addLight(
|
||||
LightType.SUN, 7500, 50000, 0, 0, 0, 1, -1, -1);
|
||||
await viewer.setRendering(true);
|
||||
...
|
||||
````
|
||||
|
||||
8. Run the project
|
||||
```
|
||||
$ flutter run -d macos
|
||||
```
|
||||
|
||||
> You may experience a noticeable delay the very first time you run the project. Don't panic, it's not frozen! This is due to the build system downloading the prebuilt Filament binaries from Cloudflare, which can take some time (particularly on Windows). These binaries will be cached after first download, so subsequent runs will be much faster (though every time you run flutter clean, the binaries will be re-downloaded).
|
||||
|
||||

|
||||
|
||||
Your first Thermion project is complete!
|
||||
42
docs/web.mdx
@@ -1,42 +0,0 @@
|
||||
## Web
|
||||
|
||||
Web support is still experimental and currently requires you to manually compile Thermion to WASM first.
|
||||
|
||||
Requirements:
|
||||
|
||||
1) GNU Make
|
||||
2) CMake
|
||||
3) Emscripten
|
||||
|
||||
From the project root directory
|
||||
|
||||
```
|
||||
thermion % ls -l
|
||||
total 272
|
||||
drwxr-xr-x 4 nickfisher staff 128 Jul 3 14:06 assets
|
||||
-rw-r--r-- 1 nickfisher staff 84532 Jul 3 14:06 CHANGELOG.md
|
||||
-rw-r--r-- 1 nickfisher staff 2349 Jul 3 14:06 Dockerfile
|
||||
drwxr-xr-x 19 nickfisher staff 608 Jul 3 14:06 docs
|
||||
-rw-r--r-- 1 nickfisher staff 748 Jul 3 14:06 docs.json
|
||||
drwxr-xr-x 7 nickfisher staff 224 Jan 8 17:01 examples
|
||||
-rw-r--r-- 1 nickfisher staff 11341 Oct 23 2024 LICENSE
|
||||
-rw-r--r-- 1 nickfisher staff 2161 Jul 3 14:06 Makefile
|
||||
drwxr-xr-x@ 13 nickfisher staff 416 Jul 3 14:06 materials
|
||||
-rw-r--r--@ 1 nickfisher staff 517 Oct 23 2024 melos_thermion_workspace.iml
|
||||
-rw-r--r-- 1 nickfisher staff 77 Oct 23 2024 melos.yaml
|
||||
-rw-r--r--@ 1 nickfisher staff 9865 Jul 1 13:03 pubspec.lock
|
||||
-rw-r--r-- 1 nickfisher staff 97 Jun 12 11:38 pubspec.yaml
|
||||
-rw-r--r-- 1 nickfisher staff 3355 Jul 3 14:06 README.md
|
||||
drwxr-xr-x@ 22 nickfisher staff 704 Jul 3 14:06 thermion_dart
|
||||
drwxr-xr-x 7 nickfisher staff 224 Jul 3 14:06 thermion_flutter
|
||||
thermion % make wasm
|
||||
```
|
||||
|
||||
### Flutter
|
||||
|
||||
Copy thermion_dart.js and thermion_dart.wasm to the `/web` folder for your target app.
|
||||
|
||||
|
||||
```
|
||||
flutter run -d chrome --web-header Cross-Origin-Embedder-Policy=require-corp --web-header Cross-Origin-Opener-Policy=same-origin
|
||||
```
|
||||
@@ -1,121 +0,0 @@
|
||||
{
|
||||
"asset":{
|
||||
"generator":"Khronos glTF Blender I/O v4.2.60",
|
||||
"version":"2.0"
|
||||
},
|
||||
"scene":0,
|
||||
"scenes":[
|
||||
{
|
||||
"name":"Scene",
|
||||
"nodes":[
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"nodes":[
|
||||
{
|
||||
"mesh":0,
|
||||
"name":"Cube"
|
||||
}
|
||||
],
|
||||
"materials":[
|
||||
{
|
||||
"doubleSided":true,
|
||||
"name":"Material",
|
||||
"pbrMetallicRoughness":{
|
||||
"baseColorFactor":[
|
||||
0.800000011920929,
|
||||
0.800000011920929,
|
||||
0.800000011920929,
|
||||
1
|
||||
],
|
||||
"metallicFactor":0,
|
||||
"roughnessFactor":0.5
|
||||
}
|
||||
}
|
||||
],
|
||||
"meshes":[
|
||||
{
|
||||
"name":"Cube",
|
||||
"primitives":[
|
||||
{
|
||||
"attributes":{
|
||||
"POSITION":0,
|
||||
"NORMAL":1,
|
||||
"TEXCOORD_0":2
|
||||
},
|
||||
"indices":3,
|
||||
"material":0
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"accessors":[
|
||||
{
|
||||
"bufferView":0,
|
||||
"componentType":5126,
|
||||
"count":24,
|
||||
"max":[
|
||||
1,
|
||||
1,
|
||||
1
|
||||
],
|
||||
"min":[
|
||||
-1,
|
||||
-1,
|
||||
-1
|
||||
],
|
||||
"type":"VEC3"
|
||||
},
|
||||
{
|
||||
"bufferView":1,
|
||||
"componentType":5126,
|
||||
"count":24,
|
||||
"type":"VEC3"
|
||||
},
|
||||
{
|
||||
"bufferView":2,
|
||||
"componentType":5126,
|
||||
"count":24,
|
||||
"type":"VEC2"
|
||||
},
|
||||
{
|
||||
"bufferView":3,
|
||||
"componentType":5123,
|
||||
"count":36,
|
||||
"type":"SCALAR"
|
||||
}
|
||||
],
|
||||
"bufferViews":[
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":288,
|
||||
"byteOffset":0,
|
||||
"target":34962
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":288,
|
||||
"byteOffset":288,
|
||||
"target":34962
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":192,
|
||||
"byteOffset":576,
|
||||
"target":34962
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":72,
|
||||
"byteOffset":768,
|
||||
"target":34963
|
||||
}
|
||||
],
|
||||
"buffers":[
|
||||
{
|
||||
"byteLength":840,
|
||||
"uri":"cube.bin"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,183 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="200"
|
||||
height="200"
|
||||
viewBox="0 0 1 1"
|
||||
version="1.1"
|
||||
id="svg10"
|
||||
sodipodi:docname="cube_texture2.svg"
|
||||
inkscape:export-filename="cube_texture_512x512.png"
|
||||
inkscape:export-xdpi="245.75999"
|
||||
inkscape:export-ydpi="245.75999"
|
||||
inkscape:version="1.4 (e7c3feb1, 2024-10-09)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs10" />
|
||||
<sodipodi:namedview
|
||||
id="namedview10"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="1.5185118"
|
||||
inkscape:cx="255.18405"
|
||||
inkscape:cy="172.86662"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="964"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="25"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg10"
|
||||
showgrid="false" />
|
||||
<!-- Background Grid (optional, for visual aid) -->
|
||||
<rect
|
||||
x="0"
|
||||
y="0"
|
||||
width="1"
|
||||
height="1"
|
||||
fill="#f0f0f0"
|
||||
id="rect1" />
|
||||
<line
|
||||
x1="0.333"
|
||||
y1="0"
|
||||
x2="0.333"
|
||||
y2="1"
|
||||
stroke="#ccc"
|
||||
stroke-width="0.005"
|
||||
id="line1" />
|
||||
<line
|
||||
x1="0.666"
|
||||
y1="0"
|
||||
x2="0.666"
|
||||
y2="1"
|
||||
stroke="#ccc"
|
||||
stroke-width="0.005"
|
||||
id="line2" />
|
||||
<line
|
||||
y1="0.25"
|
||||
x1="0"
|
||||
y2="0.25"
|
||||
x2="1"
|
||||
stroke="#ccc"
|
||||
stroke-width="0.005"
|
||||
id="line3" />
|
||||
<line
|
||||
y1="0.5"
|
||||
x1="0"
|
||||
y2="0.5"
|
||||
x2="1"
|
||||
stroke="#ccc"
|
||||
stroke-width="0.005"
|
||||
id="line4" />
|
||||
<line
|
||||
y1="0.75"
|
||||
x1="0"
|
||||
y2="0.75"
|
||||
x2="1"
|
||||
stroke="#ccc"
|
||||
stroke-width="0.005"
|
||||
id="line5" />
|
||||
<!-- Front Face -->
|
||||
<rect
|
||||
x="0.333"
|
||||
y="0"
|
||||
width="0.333"
|
||||
height="0.25"
|
||||
fill="#ff0000"
|
||||
id="rect5" />
|
||||
<text
|
||||
x="0.5"
|
||||
y="0.125"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="middle"
|
||||
font-size="0.1"
|
||||
fill="white"
|
||||
id="text5">Front</text>
|
||||
<!-- Back Face -->
|
||||
<rect
|
||||
x="0.333"
|
||||
y="0.5"
|
||||
width="0.333"
|
||||
height="0.25"
|
||||
fill="#00ff00"
|
||||
id="rect6" />
|
||||
<text
|
||||
x="0.5"
|
||||
y="0.625"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="middle"
|
||||
font-size="0.1"
|
||||
fill="white"
|
||||
id="text6">Back</text>
|
||||
<!-- Top Face -->
|
||||
<rect
|
||||
x="0.666"
|
||||
y="0.25"
|
||||
width="0.333"
|
||||
height="0.25"
|
||||
fill="#0000ff"
|
||||
id="rect7" />
|
||||
<text
|
||||
x="0.833"
|
||||
y="0.375"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="middle"
|
||||
font-size="0.1"
|
||||
fill="white"
|
||||
id="text7">Top</text>
|
||||
<!-- Bottom Face -->
|
||||
<rect
|
||||
x="0"
|
||||
y="0.25"
|
||||
width="0.333"
|
||||
height="0.25"
|
||||
fill="#ffff00"
|
||||
id="rect8" />
|
||||
<text
|
||||
x="0.15610458"
|
||||
y="0.37936932"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="middle"
|
||||
font-size="0.0733811px"
|
||||
fill="#000000"
|
||||
id="text8"
|
||||
style="stroke-width:0.733811">Bottom</text>
|
||||
<!-- Right Face -->
|
||||
<rect
|
||||
x="0.333"
|
||||
y="0.25"
|
||||
width="0.333"
|
||||
height="0.25"
|
||||
fill="#ff00ff"
|
||||
id="rect9" />
|
||||
<text
|
||||
x="0.5"
|
||||
y="0.375"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="middle"
|
||||
font-size="0.1"
|
||||
fill="white"
|
||||
id="text9">Right</text>
|
||||
<!-- Left Face -->
|
||||
<rect
|
||||
x="0.333"
|
||||
y="0.75"
|
||||
width="0.333"
|
||||
height="0.25"
|
||||
fill="#00ffff"
|
||||
id="rect10" />
|
||||
<text
|
||||
x="0.5"
|
||||
y="0.875"
|
||||
text-anchor="middle"
|
||||
dominant-baseline="middle"
|
||||
font-size="0.1"
|
||||
fill="black"
|
||||
id="text10">Left</text>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 960 KiB |
@@ -1 +0,0 @@
|
||||
{"asset":{"version":"2.0","generator":"babylon.js glTF exporter for 3dsmax 2021 v20210607.3"},"scene":0,"scenes":[{"nodes":[0]}],"nodes":[{"mesh":0,"translation":[0.0,-1.14751673,-5.015955E-08],"name":"Cylinder001"}],"meshes":[{"primitives":[{"attributes":{"POSITION":1,"NORMAL":2,"TEXCOORD_0":3},"indices":0,"material":0},{"attributes":{"POSITION":5,"NORMAL":6,"TEXCOORD_0":7},"indices":4,"material":1},{"attributes":{"POSITION":9,"NORMAL":10,"TEXCOORD_0":11},"indices":8,"material":2},{"attributes":{"POSITION":13,"NORMAL":14,"TEXCOORD_0":15},"indices":12,"material":3},{"attributes":{"POSITION":17,"NORMAL":18,"TEXCOORD_0":19},"indices":16,"material":4}],"name":"Cylinder001"}],"accessors":[{"bufferView":0,"componentType":5123,"count":858,"type":"SCALAR","name":"accessorIndices"},{"bufferView":1,"componentType":5126,"count":858,"max":[0.9673312,-0.0665806457,0.9673312],"min":[-0.9673312,-0.09678768,-0.9673312],"type":"VEC3","name":"accessorPositions"},{"bufferView":1,"byteOffset":10296,"componentType":5126,"count":858,"type":"VEC3","name":"accessorNormals"},{"bufferView":2,"componentType":5126,"count":858,"type":"VEC2","name":"accessorUVs"},{"bufferView":0,"byteOffset":1716,"componentType":5123,"count":14592,"type":"SCALAR","name":"accessorIndices"},{"bufferView":1,"byteOffset":20592,"componentType":5126,"count":14592,"max":[1.01214123,2.33892131,1.02725148],"min":[-1.01214123,-0.09678768,-1.01214123],"type":"VEC3","name":"accessorPositions"},{"bufferView":1,"byteOffset":195696,"componentType":5126,"count":14592,"type":"VEC3","name":"accessorNormals"},{"bufferView":2,"byteOffset":6864,"componentType":5126,"count":14592,"type":"VEC2","name":"accessorUVs"},{"bufferView":0,"byteOffset":30900,"componentType":5123,"count":1620,"type":"SCALAR","name":"accessorIndices"},{"bufferView":1,"byteOffset":370800,"componentType":5126,"count":1620,"max":[1.006612,2.3633275,1.006612],"min":[-1.006612,2.338921,-1.006612],"type":"VEC3","name":"accessorPositions"},{"bufferView":1,"byteOffset":390240,"componentType":5126,"count":1620,"type":"VEC3","name":"accessorNormals"},{"bufferView":2,"byteOffset":123600,"componentType":5126,"count":1620,"type":"VEC2","name":"accessorUVs"},{"bufferView":0,"byteOffset":34140,"componentType":5123,"count":318,"type":"SCALAR","name":"accessorIndices"},{"bufferView":1,"byteOffset":409680,"componentType":5126,"count":318,"max":[0.9454922,2.3548696,0.9454922],"min":[-0.9454921,0.0617354736,-0.945492268],"type":"VEC3","name":"accessorPositions"},{"bufferView":1,"byteOffset":413496,"componentType":5126,"count":318,"type":"VEC3","name":"accessorNormals"},{"bufferView":2,"byteOffset":136560,"componentType":5126,"count":318,"type":"VEC2","name":"accessorUVs"},{"bufferView":0,"byteOffset":34776,"componentType":5123,"count":11520,"type":"SCALAR","name":"accessorIndices"},{"bufferView":1,"byteOffset":417312,"componentType":5126,"count":11520,"max":[0.196413681,2.12139344,1.90955186],"min":[-0.196414649,0.165008187,1.00927675],"type":"VEC3","name":"accessorPositions"},{"bufferView":1,"byteOffset":555552,"componentType":5126,"count":11520,"type":"VEC3","name":"accessorNormals"},{"bufferView":2,"byteOffset":139104,"componentType":5126,"count":11520,"type":"VEC2","name":"accessorUVs"}],"bufferViews":[{"buffer":0,"byteLength":57816,"name":"bufferViewScalar"},{"buffer":0,"byteOffset":57816,"byteLength":693792,"byteStride":12,"name":"bufferViewFloatVec3"},{"buffer":0,"byteOffset":751608,"byteLength":231264,"byteStride":8,"name":"bufferViewFloatVec2"}],"buffers":[{"uri":"model.bin","byteLength":982872}],"materials":[{"pbrMetallicRoughness":{"metallicFactor":0.0,"roughnessFactor":0.9},"doubleSided":true,"name":"01 - Default"},{"pbrMetallicRoughness":{"baseColorTexture":{"index":0},"metallicFactor":0.0,"roughnessFactor":0.9},"doubleSided":true,"name":"02 - Default"},{"pbrMetallicRoughness":{"baseColorFactor":[0.0,1.0,0.117647067,1.0],"metallicFactor":0.0,"roughnessFactor":0.9},"doubleSided":true,"name":"03 - Default"},{"pbrMetallicRoughness":{"baseColorFactor":[0.2784314,0.0,0.9921569,1.0],"metallicFactor":0.0,"roughnessFactor":0.9},"doubleSided":true,"name":"04 - Default"},{"pbrMetallicRoughness":{"baseColorFactor":[0.9725491,0.776470661,0.0,1.0],"metallicFactor":0.0,"roughnessFactor":0.9},"doubleSided":true,"name":"05 - Default"}],"textures":[{"sampler":0,"source":0,"name":"texture.jpg"}],"images":[{"uri":"./texture.jpg"}],"samplers":[{"magFilter":9729,"minFilter":9987}]}
|
||||
|
Before Width: | Height: | Size: 720 KiB |
|
Before Width: | Height: | Size: 8.2 MiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 312 B |
|
Before Width: | Height: | Size: 8.2 MiB |
@@ -1,270 +0,0 @@
|
||||
7767517
|
||||
268 473
|
||||
Input input.1 0 1 data
|
||||
Convolution Conv_0 1 1 data 193 0=64 1=3 4=1 5=1 6=1728
|
||||
Split splitncnn_0 1 8 193 193_splitncnn_0 193_splitncnn_1 193_splitncnn_2 193_splitncnn_3 193_splitncnn_4 193_splitncnn_5 193_splitncnn_6 193_splitncnn_7
|
||||
Convolution Conv_1 1 1 193_splitncnn_7 195 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_1 1 4 195 195_splitncnn_0 195_splitncnn_1 195_splitncnn_2 195_splitncnn_3
|
||||
Concat Concat_3 2 1 193_splitncnn_6 195_splitncnn_3 196
|
||||
Convolution Conv_4 1 1 196 198 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_2 1 3 198 198_splitncnn_0 198_splitncnn_1 198_splitncnn_2
|
||||
Concat Concat_6 3 1 193_splitncnn_5 195_splitncnn_2 198_splitncnn_2 199
|
||||
Convolution Conv_7 1 1 199 201 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_3 1 2 201 201_splitncnn_0 201_splitncnn_1
|
||||
Concat Concat_9 4 1 193_splitncnn_4 195_splitncnn_1 198_splitncnn_1 201_splitncnn_1 202
|
||||
Convolution Conv_10 1 1 202 204 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
|
||||
Concat Concat_12 5 1 193_splitncnn_3 195_splitncnn_0 198_splitncnn_0 201_splitncnn_0 204 205
|
||||
Convolution Conv_13 1 1 205 206 0=64 1=3 4=1 5=1 6=110592
|
||||
Eltwise Add_16 2 1 206 193_splitncnn_2 209 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Split splitncnn_4 1 6 209 209_splitncnn_0 209_splitncnn_1 209_splitncnn_2 209_splitncnn_3 209_splitncnn_4 209_splitncnn_5
|
||||
Convolution Conv_17 1 1 209_splitncnn_5 211 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_5 1 4 211 211_splitncnn_0 211_splitncnn_1 211_splitncnn_2 211_splitncnn_3
|
||||
Concat Concat_19 2 1 209_splitncnn_4 211_splitncnn_3 212
|
||||
Convolution Conv_20 1 1 212 214 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_6 1 3 214 214_splitncnn_0 214_splitncnn_1 214_splitncnn_2
|
||||
Concat Concat_22 3 1 209_splitncnn_3 211_splitncnn_2 214_splitncnn_2 215
|
||||
Convolution Conv_23 1 1 215 217 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_7 1 2 217 217_splitncnn_0 217_splitncnn_1
|
||||
Concat Concat_25 4 1 209_splitncnn_2 211_splitncnn_1 214_splitncnn_1 217_splitncnn_1 218
|
||||
Convolution Conv_26 1 1 218 220 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
|
||||
Concat Concat_28 5 1 209_splitncnn_1 211_splitncnn_0 214_splitncnn_0 217_splitncnn_0 220 221
|
||||
Convolution Conv_29 1 1 221 222 0=64 1=3 4=1 5=1 6=110592
|
||||
Eltwise Add_32 2 1 222 209_splitncnn_0 225 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Split splitncnn_8 1 6 225 225_splitncnn_0 225_splitncnn_1 225_splitncnn_2 225_splitncnn_3 225_splitncnn_4 225_splitncnn_5
|
||||
Convolution Conv_33 1 1 225_splitncnn_5 227 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_9 1 4 227 227_splitncnn_0 227_splitncnn_1 227_splitncnn_2 227_splitncnn_3
|
||||
Concat Concat_35 2 1 225_splitncnn_4 227_splitncnn_3 228
|
||||
Convolution Conv_36 1 1 228 230 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_10 1 3 230 230_splitncnn_0 230_splitncnn_1 230_splitncnn_2
|
||||
Concat Concat_38 3 1 225_splitncnn_3 227_splitncnn_2 230_splitncnn_2 231
|
||||
Convolution Conv_39 1 1 231 233 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_11 1 2 233 233_splitncnn_0 233_splitncnn_1
|
||||
Concat Concat_41 4 1 225_splitncnn_2 227_splitncnn_1 230_splitncnn_1 233_splitncnn_1 234
|
||||
Convolution Conv_42 1 1 234 236 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
|
||||
Concat Concat_44 5 1 225_splitncnn_1 227_splitncnn_0 230_splitncnn_0 233_splitncnn_0 236 237
|
||||
Convolution Conv_45 1 1 237 238 0=64 1=3 4=1 5=1 6=110592
|
||||
Eltwise Add_48 2 1 238 225_splitncnn_0 241 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Eltwise Add_51 2 1 241 193_splitncnn_1 244 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Split splitncnn_12 1 7 244 244_splitncnn_0 244_splitncnn_1 244_splitncnn_2 244_splitncnn_3 244_splitncnn_4 244_splitncnn_5 244_splitncnn_6
|
||||
Convolution Conv_52 1 1 244_splitncnn_6 246 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_13 1 4 246 246_splitncnn_0 246_splitncnn_1 246_splitncnn_2 246_splitncnn_3
|
||||
Concat Concat_54 2 1 244_splitncnn_5 246_splitncnn_3 247
|
||||
Convolution Conv_55 1 1 247 249 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_14 1 3 249 249_splitncnn_0 249_splitncnn_1 249_splitncnn_2
|
||||
Concat Concat_57 3 1 244_splitncnn_4 246_splitncnn_2 249_splitncnn_2 250
|
||||
Convolution Conv_58 1 1 250 252 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_15 1 2 252 252_splitncnn_0 252_splitncnn_1
|
||||
Concat Concat_60 4 1 244_splitncnn_3 246_splitncnn_1 249_splitncnn_1 252_splitncnn_1 253
|
||||
Convolution Conv_61 1 1 253 255 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
|
||||
Concat Concat_63 5 1 244_splitncnn_2 246_splitncnn_0 249_splitncnn_0 252_splitncnn_0 255 256
|
||||
Convolution Conv_64 1 1 256 257 0=64 1=3 4=1 5=1 6=110592
|
||||
Eltwise Add_67 2 1 257 244_splitncnn_1 260 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Split splitncnn_16 1 6 260 260_splitncnn_0 260_splitncnn_1 260_splitncnn_2 260_splitncnn_3 260_splitncnn_4 260_splitncnn_5
|
||||
Convolution Conv_68 1 1 260_splitncnn_5 262 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_17 1 4 262 262_splitncnn_0 262_splitncnn_1 262_splitncnn_2 262_splitncnn_3
|
||||
Concat Concat_70 2 1 260_splitncnn_4 262_splitncnn_3 263
|
||||
Convolution Conv_71 1 1 263 265 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_18 1 3 265 265_splitncnn_0 265_splitncnn_1 265_splitncnn_2
|
||||
Concat Concat_73 3 1 260_splitncnn_3 262_splitncnn_2 265_splitncnn_2 266
|
||||
Convolution Conv_74 1 1 266 268 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_19 1 2 268 268_splitncnn_0 268_splitncnn_1
|
||||
Concat Concat_76 4 1 260_splitncnn_2 262_splitncnn_1 265_splitncnn_1 268_splitncnn_1 269
|
||||
Convolution Conv_77 1 1 269 271 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
|
||||
Concat Concat_79 5 1 260_splitncnn_1 262_splitncnn_0 265_splitncnn_0 268_splitncnn_0 271 272
|
||||
Convolution Conv_80 1 1 272 273 0=64 1=3 4=1 5=1 6=110592
|
||||
Eltwise Add_83 2 1 273 260_splitncnn_0 276 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Split splitncnn_20 1 6 276 276_splitncnn_0 276_splitncnn_1 276_splitncnn_2 276_splitncnn_3 276_splitncnn_4 276_splitncnn_5
|
||||
Convolution Conv_84 1 1 276_splitncnn_5 278 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_21 1 4 278 278_splitncnn_0 278_splitncnn_1 278_splitncnn_2 278_splitncnn_3
|
||||
Concat Concat_86 2 1 276_splitncnn_4 278_splitncnn_3 279
|
||||
Convolution Conv_87 1 1 279 281 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_22 1 3 281 281_splitncnn_0 281_splitncnn_1 281_splitncnn_2
|
||||
Concat Concat_89 3 1 276_splitncnn_3 278_splitncnn_2 281_splitncnn_2 282
|
||||
Convolution Conv_90 1 1 282 284 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_23 1 2 284 284_splitncnn_0 284_splitncnn_1
|
||||
Concat Concat_92 4 1 276_splitncnn_2 278_splitncnn_1 281_splitncnn_1 284_splitncnn_1 285
|
||||
Convolution Conv_93 1 1 285 287 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
|
||||
Concat Concat_95 5 1 276_splitncnn_1 278_splitncnn_0 281_splitncnn_0 284_splitncnn_0 287 288
|
||||
Convolution Conv_96 1 1 288 289 0=64 1=3 4=1 5=1 6=110592
|
||||
Eltwise Add_99 2 1 289 276_splitncnn_0 292 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Eltwise Add_102 2 1 292 244_splitncnn_0 295 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Split splitncnn_24 1 7 295 295_splitncnn_0 295_splitncnn_1 295_splitncnn_2 295_splitncnn_3 295_splitncnn_4 295_splitncnn_5 295_splitncnn_6
|
||||
Convolution Conv_103 1 1 295_splitncnn_6 297 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_25 1 4 297 297_splitncnn_0 297_splitncnn_1 297_splitncnn_2 297_splitncnn_3
|
||||
Concat Concat_105 2 1 295_splitncnn_5 297_splitncnn_3 298
|
||||
Convolution Conv_106 1 1 298 300 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_26 1 3 300 300_splitncnn_0 300_splitncnn_1 300_splitncnn_2
|
||||
Concat Concat_108 3 1 295_splitncnn_4 297_splitncnn_2 300_splitncnn_2 301
|
||||
Convolution Conv_109 1 1 301 303 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_27 1 2 303 303_splitncnn_0 303_splitncnn_1
|
||||
Concat Concat_111 4 1 295_splitncnn_3 297_splitncnn_1 300_splitncnn_1 303_splitncnn_1 304
|
||||
Convolution Conv_112 1 1 304 306 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
|
||||
Concat Concat_114 5 1 295_splitncnn_2 297_splitncnn_0 300_splitncnn_0 303_splitncnn_0 306 307
|
||||
Convolution Conv_115 1 1 307 308 0=64 1=3 4=1 5=1 6=110592
|
||||
Eltwise Add_118 2 1 308 295_splitncnn_1 311 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Split splitncnn_28 1 6 311 311_splitncnn_0 311_splitncnn_1 311_splitncnn_2 311_splitncnn_3 311_splitncnn_4 311_splitncnn_5
|
||||
Convolution Conv_119 1 1 311_splitncnn_5 313 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_29 1 4 313 313_splitncnn_0 313_splitncnn_1 313_splitncnn_2 313_splitncnn_3
|
||||
Concat Concat_121 2 1 311_splitncnn_4 313_splitncnn_3 314
|
||||
Convolution Conv_122 1 1 314 316 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_30 1 3 316 316_splitncnn_0 316_splitncnn_1 316_splitncnn_2
|
||||
Concat Concat_124 3 1 311_splitncnn_3 313_splitncnn_2 316_splitncnn_2 317
|
||||
Convolution Conv_125 1 1 317 319 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_31 1 2 319 319_splitncnn_0 319_splitncnn_1
|
||||
Concat Concat_127 4 1 311_splitncnn_2 313_splitncnn_1 316_splitncnn_1 319_splitncnn_1 320
|
||||
Convolution Conv_128 1 1 320 322 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
|
||||
Concat Concat_130 5 1 311_splitncnn_1 313_splitncnn_0 316_splitncnn_0 319_splitncnn_0 322 323
|
||||
Convolution Conv_131 1 1 323 324 0=64 1=3 4=1 5=1 6=110592
|
||||
Eltwise Add_134 2 1 324 311_splitncnn_0 327 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Split splitncnn_32 1 6 327 327_splitncnn_0 327_splitncnn_1 327_splitncnn_2 327_splitncnn_3 327_splitncnn_4 327_splitncnn_5
|
||||
Convolution Conv_135 1 1 327_splitncnn_5 329 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_33 1 4 329 329_splitncnn_0 329_splitncnn_1 329_splitncnn_2 329_splitncnn_3
|
||||
Concat Concat_137 2 1 327_splitncnn_4 329_splitncnn_3 330
|
||||
Convolution Conv_138 1 1 330 332 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_34 1 3 332 332_splitncnn_0 332_splitncnn_1 332_splitncnn_2
|
||||
Concat Concat_140 3 1 327_splitncnn_3 329_splitncnn_2 332_splitncnn_2 333
|
||||
Convolution Conv_141 1 1 333 335 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_35 1 2 335 335_splitncnn_0 335_splitncnn_1
|
||||
Concat Concat_143 4 1 327_splitncnn_2 329_splitncnn_1 332_splitncnn_1 335_splitncnn_1 336
|
||||
Convolution Conv_144 1 1 336 338 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
|
||||
Concat Concat_146 5 1 327_splitncnn_1 329_splitncnn_0 332_splitncnn_0 335_splitncnn_0 338 339
|
||||
Convolution Conv_147 1 1 339 340 0=64 1=3 4=1 5=1 6=110592
|
||||
Eltwise Add_150 2 1 340 327_splitncnn_0 343 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Eltwise Add_153 2 1 343 295_splitncnn_0 346 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Split splitncnn_36 1 7 346 346_splitncnn_0 346_splitncnn_1 346_splitncnn_2 346_splitncnn_3 346_splitncnn_4 346_splitncnn_5 346_splitncnn_6
|
||||
Convolution Conv_154 1 1 346_splitncnn_6 348 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_37 1 4 348 348_splitncnn_0 348_splitncnn_1 348_splitncnn_2 348_splitncnn_3
|
||||
Concat Concat_156 2 1 346_splitncnn_5 348_splitncnn_3 349
|
||||
Convolution Conv_157 1 1 349 351 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_38 1 3 351 351_splitncnn_0 351_splitncnn_1 351_splitncnn_2
|
||||
Concat Concat_159 3 1 346_splitncnn_4 348_splitncnn_2 351_splitncnn_2 352
|
||||
Convolution Conv_160 1 1 352 354 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_39 1 2 354 354_splitncnn_0 354_splitncnn_1
|
||||
Concat Concat_162 4 1 346_splitncnn_3 348_splitncnn_1 351_splitncnn_1 354_splitncnn_1 355
|
||||
Convolution Conv_163 1 1 355 357 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
|
||||
Concat Concat_165 5 1 346_splitncnn_2 348_splitncnn_0 351_splitncnn_0 354_splitncnn_0 357 358
|
||||
Convolution Conv_166 1 1 358 359 0=64 1=3 4=1 5=1 6=110592
|
||||
Eltwise Add_169 2 1 359 346_splitncnn_1 362 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Split splitncnn_40 1 6 362 362_splitncnn_0 362_splitncnn_1 362_splitncnn_2 362_splitncnn_3 362_splitncnn_4 362_splitncnn_5
|
||||
Convolution Conv_170 1 1 362_splitncnn_5 364 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_41 1 4 364 364_splitncnn_0 364_splitncnn_1 364_splitncnn_2 364_splitncnn_3
|
||||
Concat Concat_172 2 1 362_splitncnn_4 364_splitncnn_3 365
|
||||
Convolution Conv_173 1 1 365 367 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_42 1 3 367 367_splitncnn_0 367_splitncnn_1 367_splitncnn_2
|
||||
Concat Concat_175 3 1 362_splitncnn_3 364_splitncnn_2 367_splitncnn_2 368
|
||||
Convolution Conv_176 1 1 368 370 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_43 1 2 370 370_splitncnn_0 370_splitncnn_1
|
||||
Concat Concat_178 4 1 362_splitncnn_2 364_splitncnn_1 367_splitncnn_1 370_splitncnn_1 371
|
||||
Convolution Conv_179 1 1 371 373 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
|
||||
Concat Concat_181 5 1 362_splitncnn_1 364_splitncnn_0 367_splitncnn_0 370_splitncnn_0 373 374
|
||||
Convolution Conv_182 1 1 374 375 0=64 1=3 4=1 5=1 6=110592
|
||||
Eltwise Add_185 2 1 375 362_splitncnn_0 378 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Split splitncnn_44 1 6 378 378_splitncnn_0 378_splitncnn_1 378_splitncnn_2 378_splitncnn_3 378_splitncnn_4 378_splitncnn_5
|
||||
Convolution Conv_186 1 1 378_splitncnn_5 380 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_45 1 4 380 380_splitncnn_0 380_splitncnn_1 380_splitncnn_2 380_splitncnn_3
|
||||
Concat Concat_188 2 1 378_splitncnn_4 380_splitncnn_3 381
|
||||
Convolution Conv_189 1 1 381 383 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_46 1 3 383 383_splitncnn_0 383_splitncnn_1 383_splitncnn_2
|
||||
Concat Concat_191 3 1 378_splitncnn_3 380_splitncnn_2 383_splitncnn_2 384
|
||||
Convolution Conv_192 1 1 384 386 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_47 1 2 386 386_splitncnn_0 386_splitncnn_1
|
||||
Concat Concat_194 4 1 378_splitncnn_2 380_splitncnn_1 383_splitncnn_1 386_splitncnn_1 387
|
||||
Convolution Conv_195 1 1 387 389 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
|
||||
Concat Concat_197 5 1 378_splitncnn_1 380_splitncnn_0 383_splitncnn_0 386_splitncnn_0 389 390
|
||||
Convolution Conv_198 1 1 390 391 0=64 1=3 4=1 5=1 6=110592
|
||||
Eltwise Add_201 2 1 391 378_splitncnn_0 394 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Eltwise Add_204 2 1 394 346_splitncnn_0 397 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Split splitncnn_48 1 7 397 397_splitncnn_0 397_splitncnn_1 397_splitncnn_2 397_splitncnn_3 397_splitncnn_4 397_splitncnn_5 397_splitncnn_6
|
||||
Convolution Conv_205 1 1 397_splitncnn_6 399 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_49 1 4 399 399_splitncnn_0 399_splitncnn_1 399_splitncnn_2 399_splitncnn_3
|
||||
Concat Concat_207 2 1 397_splitncnn_5 399_splitncnn_3 400
|
||||
Convolution Conv_208 1 1 400 402 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_50 1 3 402 402_splitncnn_0 402_splitncnn_1 402_splitncnn_2
|
||||
Concat Concat_210 3 1 397_splitncnn_4 399_splitncnn_2 402_splitncnn_2 403
|
||||
Convolution Conv_211 1 1 403 405 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_51 1 2 405 405_splitncnn_0 405_splitncnn_1
|
||||
Concat Concat_213 4 1 397_splitncnn_3 399_splitncnn_1 402_splitncnn_1 405_splitncnn_1 406
|
||||
Convolution Conv_214 1 1 406 408 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
|
||||
Concat Concat_216 5 1 397_splitncnn_2 399_splitncnn_0 402_splitncnn_0 405_splitncnn_0 408 409
|
||||
Convolution Conv_217 1 1 409 410 0=64 1=3 4=1 5=1 6=110592
|
||||
Eltwise Add_220 2 1 410 397_splitncnn_1 413 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Split splitncnn_52 1 6 413 413_splitncnn_0 413_splitncnn_1 413_splitncnn_2 413_splitncnn_3 413_splitncnn_4 413_splitncnn_5
|
||||
Convolution Conv_221 1 1 413_splitncnn_5 415 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_53 1 4 415 415_splitncnn_0 415_splitncnn_1 415_splitncnn_2 415_splitncnn_3
|
||||
Concat Concat_223 2 1 413_splitncnn_4 415_splitncnn_3 416
|
||||
Convolution Conv_224 1 1 416 418 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_54 1 3 418 418_splitncnn_0 418_splitncnn_1 418_splitncnn_2
|
||||
Concat Concat_226 3 1 413_splitncnn_3 415_splitncnn_2 418_splitncnn_2 419
|
||||
Convolution Conv_227 1 1 419 421 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_55 1 2 421 421_splitncnn_0 421_splitncnn_1
|
||||
Concat Concat_229 4 1 413_splitncnn_2 415_splitncnn_1 418_splitncnn_1 421_splitncnn_1 422
|
||||
Convolution Conv_230 1 1 422 424 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
|
||||
Concat Concat_232 5 1 413_splitncnn_1 415_splitncnn_0 418_splitncnn_0 421_splitncnn_0 424 425
|
||||
Convolution Conv_233 1 1 425 426 0=64 1=3 4=1 5=1 6=110592
|
||||
Eltwise Add_236 2 1 426 413_splitncnn_0 429 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Split splitncnn_56 1 6 429 429_splitncnn_0 429_splitncnn_1 429_splitncnn_2 429_splitncnn_3 429_splitncnn_4 429_splitncnn_5
|
||||
Convolution Conv_237 1 1 429_splitncnn_5 431 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_57 1 4 431 431_splitncnn_0 431_splitncnn_1 431_splitncnn_2 431_splitncnn_3
|
||||
Concat Concat_239 2 1 429_splitncnn_4 431_splitncnn_3 432
|
||||
Convolution Conv_240 1 1 432 434 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_58 1 3 434 434_splitncnn_0 434_splitncnn_1 434_splitncnn_2
|
||||
Concat Concat_242 3 1 429_splitncnn_3 431_splitncnn_2 434_splitncnn_2 435
|
||||
Convolution Conv_243 1 1 435 437 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_59 1 2 437 437_splitncnn_0 437_splitncnn_1
|
||||
Concat Concat_245 4 1 429_splitncnn_2 431_splitncnn_1 434_splitncnn_1 437_splitncnn_1 438
|
||||
Convolution Conv_246 1 1 438 440 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
|
||||
Concat Concat_248 5 1 429_splitncnn_1 431_splitncnn_0 434_splitncnn_0 437_splitncnn_0 440 441
|
||||
Convolution Conv_249 1 1 441 442 0=64 1=3 4=1 5=1 6=110592
|
||||
Eltwise Add_252 2 1 442 429_splitncnn_0 445 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Eltwise Add_255 2 1 445 397_splitncnn_0 448 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Split splitncnn_60 1 7 448 448_splitncnn_0 448_splitncnn_1 448_splitncnn_2 448_splitncnn_3 448_splitncnn_4 448_splitncnn_5 448_splitncnn_6
|
||||
Convolution Conv_256 1 1 448_splitncnn_6 450 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_61 1 4 450 450_splitncnn_0 450_splitncnn_1 450_splitncnn_2 450_splitncnn_3
|
||||
Concat Concat_258 2 1 448_splitncnn_5 450_splitncnn_3 451
|
||||
Convolution Conv_259 1 1 451 453 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_62 1 3 453 453_splitncnn_0 453_splitncnn_1 453_splitncnn_2
|
||||
Concat Concat_261 3 1 448_splitncnn_4 450_splitncnn_2 453_splitncnn_2 454
|
||||
Convolution Conv_262 1 1 454 456 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_63 1 2 456 456_splitncnn_0 456_splitncnn_1
|
||||
Concat Concat_264 4 1 448_splitncnn_3 450_splitncnn_1 453_splitncnn_1 456_splitncnn_1 457
|
||||
Convolution Conv_265 1 1 457 459 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
|
||||
Concat Concat_267 5 1 448_splitncnn_2 450_splitncnn_0 453_splitncnn_0 456_splitncnn_0 459 460
|
||||
Convolution Conv_268 1 1 460 461 0=64 1=3 4=1 5=1 6=110592
|
||||
Eltwise Add_271 2 1 461 448_splitncnn_1 464 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Split splitncnn_64 1 6 464 464_splitncnn_0 464_splitncnn_1 464_splitncnn_2 464_splitncnn_3 464_splitncnn_4 464_splitncnn_5
|
||||
Convolution Conv_272 1 1 464_splitncnn_5 466 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_65 1 4 466 466_splitncnn_0 466_splitncnn_1 466_splitncnn_2 466_splitncnn_3
|
||||
Concat Concat_274 2 1 464_splitncnn_4 466_splitncnn_3 467
|
||||
Convolution Conv_275 1 1 467 469 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_66 1 3 469 469_splitncnn_0 469_splitncnn_1 469_splitncnn_2
|
||||
Concat Concat_277 3 1 464_splitncnn_3 466_splitncnn_2 469_splitncnn_2 470
|
||||
Convolution Conv_278 1 1 470 472 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_67 1 2 472 472_splitncnn_0 472_splitncnn_1
|
||||
Concat Concat_280 4 1 464_splitncnn_2 466_splitncnn_1 469_splitncnn_1 472_splitncnn_1 473
|
||||
Convolution Conv_281 1 1 473 475 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
|
||||
Concat Concat_283 5 1 464_splitncnn_1 466_splitncnn_0 469_splitncnn_0 472_splitncnn_0 475 476
|
||||
Convolution Conv_284 1 1 476 477 0=64 1=3 4=1 5=1 6=110592
|
||||
Eltwise Add_287 2 1 477 464_splitncnn_0 480 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Split splitncnn_68 1 6 480 480_splitncnn_0 480_splitncnn_1 480_splitncnn_2 480_splitncnn_3 480_splitncnn_4 480_splitncnn_5
|
||||
Convolution Conv_288 1 1 480_splitncnn_5 482 0=32 1=3 4=1 5=1 6=18432 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_69 1 4 482 482_splitncnn_0 482_splitncnn_1 482_splitncnn_2 482_splitncnn_3
|
||||
Concat Concat_290 2 1 480_splitncnn_4 482_splitncnn_3 483
|
||||
Convolution Conv_291 1 1 483 485 0=32 1=3 4=1 5=1 6=27648 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_70 1 3 485 485_splitncnn_0 485_splitncnn_1 485_splitncnn_2
|
||||
Concat Concat_293 3 1 480_splitncnn_3 482_splitncnn_2 485_splitncnn_2 486
|
||||
Convolution Conv_294 1 1 486 488 0=32 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Split splitncnn_71 1 2 488 488_splitncnn_0 488_splitncnn_1
|
||||
Concat Concat_296 4 1 480_splitncnn_2 482_splitncnn_1 485_splitncnn_1 488_splitncnn_1 489
|
||||
Convolution Conv_297 1 1 489 491 0=32 1=3 4=1 5=1 6=46080 9=2 -23310=1,2.000000e-01
|
||||
Concat Concat_299 5 1 480_splitncnn_1 482_splitncnn_0 485_splitncnn_0 488_splitncnn_0 491 492
|
||||
Convolution Conv_300 1 1 492 493 0=64 1=3 4=1 5=1 6=110592
|
||||
Eltwise Add_303 2 1 493 480_splitncnn_0 496 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Eltwise Add_306 2 1 496 448_splitncnn_0 499 0=1 -23301=2,2.000000e-01,1.000000e+00
|
||||
Convolution Conv_307 1 1 499 500 0=64 1=3 4=1 5=1 6=36864
|
||||
BinaryOp Add_308 2 1 193_splitncnn_0 500 501
|
||||
Interp Resize_310 1 1 501 506 0=1 1=2.000000e+00 2=2.000000e+00
|
||||
Convolution Conv_311 1 1 506 508 0=64 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Interp Resize_314 1 1 508 513 0=1 1=2.000000e+00 2=2.000000e+00
|
||||
Convolution Conv_315 1 1 513 515 0=64 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Convolution Conv_317 1 1 515 517 0=64 1=3 4=1 5=1 6=36864 9=2 -23310=1,2.000000e-01
|
||||
Convolution Conv_319 1 1 517 output 0=3 1=3 4=1 5=1 6=1728
|
||||
|
Before Width: | Height: | Size: 960 KiB |
@@ -1 +0,0 @@
|
||||
{"asset":{"version":"2.0","generator":"babylon.js glTF exporter for 3dsmax 2021 v20210607.3"},"scene":0,"scenes":[{"nodes":[0]}],"nodes":[{"mesh":0,"translation":[0.0,-1.14751673,-5.015955E-08],"name":"Cylinder001"}],"meshes":[{"primitives":[{"attributes":{"POSITION":1,"NORMAL":2,"TEXCOORD_0":3},"indices":0,"material":0},{"attributes":{"POSITION":5,"NORMAL":6,"TEXCOORD_0":7},"indices":4,"material":1},{"attributes":{"POSITION":9,"NORMAL":10,"TEXCOORD_0":11},"indices":8,"material":2},{"attributes":{"POSITION":13,"NORMAL":14,"TEXCOORD_0":15},"indices":12,"material":3},{"attributes":{"POSITION":17,"NORMAL":18,"TEXCOORD_0":19},"indices":16,"material":4}],"name":"Cylinder001"}],"accessors":[{"bufferView":0,"componentType":5123,"count":858,"type":"SCALAR","name":"accessorIndices"},{"bufferView":1,"componentType":5126,"count":858,"max":[0.9673312,-0.0665806457,0.9673312],"min":[-0.9673312,-0.09678768,-0.9673312],"type":"VEC3","name":"accessorPositions"},{"bufferView":1,"byteOffset":10296,"componentType":5126,"count":858,"type":"VEC3","name":"accessorNormals"},{"bufferView":2,"componentType":5126,"count":858,"type":"VEC2","name":"accessorUVs"},{"bufferView":0,"byteOffset":1716,"componentType":5123,"count":14592,"type":"SCALAR","name":"accessorIndices"},{"bufferView":1,"byteOffset":20592,"componentType":5126,"count":14592,"max":[1.01214123,2.33892131,1.02725148],"min":[-1.01214123,-0.09678768,-1.01214123],"type":"VEC3","name":"accessorPositions"},{"bufferView":1,"byteOffset":195696,"componentType":5126,"count":14592,"type":"VEC3","name":"accessorNormals"},{"bufferView":2,"byteOffset":6864,"componentType":5126,"count":14592,"type":"VEC2","name":"accessorUVs"},{"bufferView":0,"byteOffset":30900,"componentType":5123,"count":1620,"type":"SCALAR","name":"accessorIndices"},{"bufferView":1,"byteOffset":370800,"componentType":5126,"count":1620,"max":[1.006612,2.3633275,1.006612],"min":[-1.006612,2.338921,-1.006612],"type":"VEC3","name":"accessorPositions"},{"bufferView":1,"byteOffset":390240,"componentType":5126,"count":1620,"type":"VEC3","name":"accessorNormals"},{"bufferView":2,"byteOffset":123600,"componentType":5126,"count":1620,"type":"VEC2","name":"accessorUVs"},{"bufferView":0,"byteOffset":34140,"componentType":5123,"count":318,"type":"SCALAR","name":"accessorIndices"},{"bufferView":1,"byteOffset":409680,"componentType":5126,"count":318,"max":[0.9454922,2.3548696,0.9454922],"min":[-0.9454921,0.0617354736,-0.945492268],"type":"VEC3","name":"accessorPositions"},{"bufferView":1,"byteOffset":413496,"componentType":5126,"count":318,"type":"VEC3","name":"accessorNormals"},{"bufferView":2,"byteOffset":136560,"componentType":5126,"count":318,"type":"VEC2","name":"accessorUVs"},{"bufferView":0,"byteOffset":34776,"componentType":5123,"count":11520,"type":"SCALAR","name":"accessorIndices"},{"bufferView":1,"byteOffset":417312,"componentType":5126,"count":11520,"max":[0.196413681,2.12139344,1.90955186],"min":[-0.196414649,0.165008187,1.00927675],"type":"VEC3","name":"accessorPositions"},{"bufferView":1,"byteOffset":555552,"componentType":5126,"count":11520,"type":"VEC3","name":"accessorNormals"},{"bufferView":2,"byteOffset":139104,"componentType":5126,"count":11520,"type":"VEC2","name":"accessorUVs"}],"bufferViews":[{"buffer":0,"byteLength":57816,"name":"bufferViewScalar"},{"buffer":0,"byteOffset":57816,"byteLength":693792,"byteStride":12,"name":"bufferViewFloatVec3"},{"buffer":0,"byteOffset":751608,"byteLength":231264,"byteStride":8,"name":"bufferViewFloatVec2"}],"buffers":[{"uri":"model.bin","byteLength":982872}],"materials":[{"pbrMetallicRoughness":{"metallicFactor":0.0,"roughnessFactor":0.9},"doubleSided":true,"name":"01 - Default"},{"pbrMetallicRoughness":{"baseColorTexture":{"index":0},"metallicFactor":0.0,"roughnessFactor":0.9},"doubleSided":true,"name":"02 - Default"},{"pbrMetallicRoughness":{"baseColorFactor":[0.0,1.0,0.117647067,1.0],"metallicFactor":0.0,"roughnessFactor":0.9},"doubleSided":true,"name":"03 - Default"},{"pbrMetallicRoughness":{"baseColorFactor":[0.2784314,0.0,0.9921569,1.0],"metallicFactor":0.0,"roughnessFactor":0.9},"doubleSided":true,"name":"04 - Default"},{"pbrMetallicRoughness":{"baseColorFactor":[0.9725491,0.776470661,0.0,1.0],"metallicFactor":0.0,"roughnessFactor":0.9},"doubleSided":true,"name":"05 - Default"}],"textures":[{"sampler":0,"source":0,"name":"texture.jpg"}],"images":[{"uri":"./texture.jpg"}],"samplers":[{"magFilter":9729,"minFilter":9987}]}
|
||||
|
Before Width: | Height: | Size: 8.2 MiB |
@@ -1,74 +0,0 @@
|
||||
7767517
|
||||
72 73
|
||||
Input input.1 0 1 data
|
||||
Split splitncnn_input0 1 2 data input_splitncnn_0 input_splitncnn_1
|
||||
Convolution Conv_0 1 1 input_splitncnn_1 102 0=64 1=3 4=1 5=1 6=1728
|
||||
PReLU PRelu_1 1 1 102 105 0=64
|
||||
Convolution Conv_2 1 1 105 106 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_3 1 1 106 109 0=64
|
||||
Convolution Conv_4 1 1 109 110 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_5 1 1 110 113 0=64
|
||||
Convolution Conv_6 1 1 113 114 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_7 1 1 114 117 0=64
|
||||
Convolution Conv_8 1 1 117 118 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_9 1 1 118 121 0=64
|
||||
Convolution Conv_10 1 1 121 122 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_11 1 1 122 125 0=64
|
||||
Convolution Conv_12 1 1 125 126 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_13 1 1 126 129 0=64
|
||||
Convolution Conv_14 1 1 129 130 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_15 1 1 130 133 0=64
|
||||
Convolution Conv_16 1 1 133 134 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_17 1 1 134 137 0=64
|
||||
Convolution Conv_18 1 1 137 138 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_19 1 1 138 141 0=64
|
||||
Convolution Conv_20 1 1 141 142 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_21 1 1 142 145 0=64
|
||||
Convolution Conv_22 1 1 145 146 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_23 1 1 146 149 0=64
|
||||
Convolution Conv_24 1 1 149 150 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_25 1 1 150 153 0=64
|
||||
Convolution Conv_26 1 1 153 154 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_27 1 1 154 157 0=64
|
||||
Convolution Conv_28 1 1 157 158 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_29 1 1 158 161 0=64
|
||||
Convolution Conv_30 1 1 161 162 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_31 1 1 162 165 0=64
|
||||
Convolution Conv_32 1 1 165 166 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_33 1 1 166 169 0=64
|
||||
Convolution Conv_34 1 1 169 170 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_35 1 1 170 173 0=64
|
||||
Convolution Conv_36 1 1 173 174 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_37 1 1 174 177 0=64
|
||||
Convolution Conv_38 1 1 177 178 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_39 1 1 178 181 0=64
|
||||
Convolution Conv_40 1 1 181 182 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_41 1 1 182 185 0=64
|
||||
Convolution Conv_42 1 1 185 186 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_43 1 1 186 189 0=64
|
||||
Convolution Conv_44 1 1 189 190 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_45 1 1 190 193 0=64
|
||||
Convolution Conv_46 1 1 193 194 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_47 1 1 194 197 0=64
|
||||
Convolution Conv_48 1 1 197 198 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_49 1 1 198 201 0=64
|
||||
Convolution Conv_50 1 1 201 202 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_51 1 1 202 205 0=64
|
||||
Convolution Conv_52 1 1 205 206 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_53 1 1 206 209 0=64
|
||||
Convolution Conv_54 1 1 209 210 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_55 1 1 210 213 0=64
|
||||
Convolution Conv_56 1 1 213 214 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_57 1 1 214 217 0=64
|
||||
Convolution Conv_58 1 1 217 218 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_59 1 1 218 221 0=64
|
||||
Convolution Conv_60 1 1 221 222 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_61 1 1 222 225 0=64
|
||||
Convolution Conv_62 1 1 225 226 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_63 1 1 226 229 0=64
|
||||
Convolution Conv_64 1 1 229 230 0=64 1=3 4=1 5=1 6=36864
|
||||
PReLU PRelu_65 1 1 230 233 0=64
|
||||
Convolution Conv_66 1 1 233 234 0=48 1=3 4=1 5=1 6=27648
|
||||
PixelShuffle DepthToSpace_67 1 1 234 235 0=4
|
||||
Interp Resize_68 1 1 input_splitncnn_0 240 0=1 1=4.000000e+00 2=4.000000e+00
|
||||
BinaryOp Add_69 2 1 235 240 output
|
||||
|
Before Width: | Height: | Size: 313 B |
@@ -1,30 +0,0 @@
|
||||
#!/bin/zsh
|
||||
setopt null_glob
|
||||
|
||||
INPUT="./images"
|
||||
OUTPUT="./images_output"
|
||||
MODELPATH="./models"
|
||||
MODELNAME="ultramix-balanced-4x"
|
||||
TARGET_WIDTH="4320"
|
||||
FORMAT="jpg" # 或 webp
|
||||
SCALE=3
|
||||
MAX_SIZE=$((20 * 1024 * 1024)) # 20MB
|
||||
|
||||
|
||||
./bin/mac/upscayl-bin -i "$INPUT" -o "$OUTPUT" -f $FORMAT -m $MODELPATH -n $MODELNAME -w $TARGET_WIDTH -j 4:8:4 -v
|
||||
|
||||
echo "\n===== 输入目录: $INPUT ====="
|
||||
for img in "$INPUT"/*.{png,jpg,jpeg}; do
|
||||
[ -e "$img" ] || continue
|
||||
size=$(stat -f%z "$img")
|
||||
res=$(sips -g pixelWidth -g pixelHeight "$img" 2>/dev/null | awk '/pixelWidth|pixelHeight/ {print $2}' | xargs | sed 's/ /x/')
|
||||
echo "$(basename "$img"): ${size} bytes, ${res}"
|
||||
done
|
||||
|
||||
echo "\n===== 输出目录: $OUTPUT ====="
|
||||
for img in "$OUTPUT"/*.{png,jpg,jpeg}; do
|
||||
[ -e "$img" ] || continue
|
||||
size=$(stat -f%z "$img")
|
||||
res=$(sips -g pixelWidth -g pixelHeight "$img" 2>/dev/null | awk '/pixelWidth|pixelHeight/ {print $2}' | xargs | sed 's/ /x/')
|
||||
echo "$(basename "$img"): ${size} bytes, ${res}"
|
||||
done
|
||||
@@ -1,114 +0,0 @@
|
||||
#!/bin/zsh
|
||||
setopt null_glob
|
||||
|
||||
# 设置默认值或从环境变量获取
|
||||
INPUT="${INPUT_DIR:-./images}"
|
||||
OUTPUT="${OUTPUT_DIR:-./images_output}"
|
||||
MODELPATH="${MODELPATH:-./models}"
|
||||
MODELNAME="${MODELNAME:-ultramix-balanced-4x}"
|
||||
BIN_PATH="${BIN_PATH:-./bin/mac/upscayl-bin}"
|
||||
TARGET_WIDTH=4320
|
||||
TARGET_HEIGHT=7680
|
||||
FORMAT="jpg"
|
||||
THREADS="4:8:4"
|
||||
TARGET_SIZE=$((10 * 1024 * 1024)) # 10MB
|
||||
MAX_SIZE=$((20 * 1024 * 1024)) # 20MB
|
||||
|
||||
echo "===== 开始批量处理图片 ====="
|
||||
echo "输入目录: $INPUT"
|
||||
echo "输出目录: $OUTPUT"
|
||||
echo "模型路径: $MODELPATH"
|
||||
echo "模型名称: $MODELNAME"
|
||||
echo "二进制文件: $BIN_PATH"
|
||||
|
||||
# 确保输出目录存在
|
||||
mkdir -p "$OUTPUT"
|
||||
|
||||
# 循环对每个图片单独执行 upscayl-bin,输出路径为文件路径
|
||||
for img in "$INPUT"/*.{png,jpg,jpeg}; do
|
||||
[ -e "$img" ] || continue
|
||||
base=$(basename "$img")
|
||||
out_img="$OUTPUT/${base%.*}.$FORMAT"
|
||||
compress=10 # 0为无压缩,100为最大压缩
|
||||
try=1
|
||||
echo "\n==== 开始处理: $base ===="
|
||||
echo "输入文件: $img"
|
||||
echo "输出文件: $out_img"
|
||||
echo "模型: $MODELNAME, 模型路径: $MODELPATH"
|
||||
echo "格式: $FORMAT"
|
||||
|
||||
|
||||
# 获取原图宽高
|
||||
read orig_w orig_h <<< $(sips -g pixelWidth -g pixelHeight "$img" 2>/dev/null | awk '/pixelWidth/ {w=$2} /pixelHeight/ {h=$2} END{print w,h}')
|
||||
if [ "$orig_w" -lt "$orig_h" ]; then
|
||||
short=$orig_w
|
||||
long=$orig_h
|
||||
else
|
||||
short=$orig_h
|
||||
long=$orig_w
|
||||
fi
|
||||
echo "DEBUG: orig_w=$orig_w, orig_h=$orig_h, short=$short, long=$long"
|
||||
scale1=$(echo "scale=8; 4320/$short" | bc)
|
||||
scale2=$(echo "scale=8; 7680/$long" | bc)
|
||||
echo "DEBUG: scale1=$scale1, scale2=$scale2"
|
||||
# 取scale1和scale2的最大值
|
||||
scale=$(echo "$scale1 > $scale2" | bc -l)
|
||||
if [ "$scale" -eq 1 ]; then
|
||||
use_scale=$scale1
|
||||
else
|
||||
use_scale=$scale2
|
||||
fi
|
||||
use_scale=$(printf "%f" "$use_scale")
|
||||
echo "DEBUG: use_scale=$use_scale"
|
||||
# 保证不缩小
|
||||
scale_cmp=$(echo "$use_scale > 1" | bc -l)
|
||||
echo "DEBUG: scale_cmp=$scale_cmp"
|
||||
if [ "$scale_cmp" -eq 1 ]; then
|
||||
target_w=$(awk -v w="$orig_w" -v s="$use_scale" 'BEGIN{printf "%d", w*s+0.5}')
|
||||
target_h=$(awk -v h="$orig_h" -v s="$use_scale" 'BEGIN{printf "%d", h*s+0.5}')
|
||||
echo "原图分辨率: ${orig_w}x${orig_h}, 目标分辨率: ${target_w}x${target_h} (短边≥4320, 长边≥7680)"
|
||||
else
|
||||
target_w=$orig_w
|
||||
target_h=$orig_h
|
||||
echo "原图分辨率: ${orig_w}x${orig_h}, 已满足短边≥4320且长边≥7680,无需放大"
|
||||
fi
|
||||
|
||||
while true; do
|
||||
echo "尝试第 $try 次: compress=$compress"
|
||||
upscale_cmd="\"$BIN_PATH\" -i \"$img\" -o \"$out_img\" -f $FORMAT -m \"$MODELPATH\" -n $MODELNAME -r \"${target_w}x${target_h}\" -c $compress -j $THREADS -v"
|
||||
echo "执行命令: $upscale_cmd"
|
||||
eval $upscale_cmd
|
||||
if [ ! -f "$out_img" ]; then
|
||||
echo "$base: 未生成图片,compress=$compress"
|
||||
break
|
||||
fi
|
||||
size=$(stat -f%z "$out_img")
|
||||
res=$(sips -g pixelWidth -g pixelHeight "$out_img" 2>/dev/null | awk '/pixelWidth|pixelHeight/ {print $2}' | xargs | sed 's/ /x/')
|
||||
echo "$base: compress=$compress, size=${size} bytes, 分辨率=${res}"
|
||||
if [ $size -le $MAX_SIZE ] || [ $compress -ge 100 ]; then
|
||||
echo "$base: 满足大小要求,最终 compress=$compress"
|
||||
break
|
||||
fi
|
||||
# compress 每次递增10,最大不超过100
|
||||
compress=$((compress + 10))
|
||||
[ $compress -gt 100 ] && compress=100
|
||||
try=$((try+1))
|
||||
[ $try -gt 10 ] && echo "$base: 达到最大尝试次数,停止调整" && break
|
||||
done
|
||||
done
|
||||
|
||||
echo "\n===== 输入目录: $INPUT ====="
|
||||
for img in "$INPUT"/*.{png,jpg,jpeg}; do
|
||||
[ -e "$img" ] || continue
|
||||
size=$(stat -f%z "$img")
|
||||
res=$(sips -g pixelWidth -g pixelHeight "$img" 2>/dev/null | awk '/pixelWidth|pixelHeight/ {print $2}' | xargs | sed 's/ /x/')
|
||||
echo "$(basename "$img"): ${size} bytes, ${res}"
|
||||
done
|
||||
|
||||
echo "\n===== 输出目录: $OUTPUT ====="
|
||||
for img in "$OUTPUT"/*.{png,jpg,jpeg}; do
|
||||
[ -e "$img" ] || continue
|
||||
size=$(stat -f%z "$img")
|
||||
res=$(sips -g pixelWidth -g pixelHeight "$img" 2>/dev/null | awk '/pixelWidth|pixelHeight/ {print $2}' | xargs | sed 's/ /x/')
|
||||
echo "$(basename "$img"): ${size} bytes, ${res}"
|
||||
done
|
||||
@@ -1,131 +0,0 @@
|
||||
#!/bin/zsh
|
||||
setopt null_glob
|
||||
|
||||
# 从环境变量或参数获取配置
|
||||
INPUT_FILE="${INPUT_FILE:-$1}"
|
||||
OUTPUT_FILE="${OUTPUT_FILE:-$2}"
|
||||
MODELPATH="${MODELPATH:-./models}"
|
||||
MODELNAME="${MODELNAME:-ultramix-balanced-4x}"
|
||||
BIN_PATH="${BIN_PATH:-./bin/mac/upscayl-bin}"
|
||||
TARGET_WIDTH=4320
|
||||
TARGET_HEIGHT=7680
|
||||
FORMAT="jpg"
|
||||
THREADS="4:8:4"
|
||||
TARGET_SIZE=$((10 * 1024 * 1024)) # 10MB
|
||||
MAX_SIZE=$((20 * 1024 * 1024)) # 20MB
|
||||
|
||||
# 检查输入参数
|
||||
if [ -z "$INPUT_FILE" ] || [ -z "$OUTPUT_FILE" ]; then
|
||||
echo "错误: 需要指定输入和输出文件路径"
|
||||
echo "用法: $0 <输入文件> <输出文件>"
|
||||
echo "或者设置环境变量 INPUT_FILE 和 OUTPUT_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$INPUT_FILE" ]; then
|
||||
echo "错误: 输入文件不存在: $INPUT_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "===== 开始处理单张图片 ====="
|
||||
echo "输入文件: $INPUT_FILE"
|
||||
echo "输出文件: $OUTPUT_FILE"
|
||||
echo "模型路径: $MODELPATH"
|
||||
echo "模型名称: $MODELNAME"
|
||||
echo "二进制文件: $BIN_PATH"
|
||||
|
||||
# 确保输出目录存在
|
||||
output_dir=$(dirname "$OUTPUT_FILE")
|
||||
mkdir -p "$output_dir"
|
||||
|
||||
base=$(basename "$INPUT_FILE")
|
||||
compress=10 # 0为无压缩,100为最大压缩
|
||||
try=1
|
||||
|
||||
echo "\n==== 开始处理: $base ===="
|
||||
echo "输入文件: $INPUT_FILE"
|
||||
echo "输出文件: $OUTPUT_FILE"
|
||||
echo "模型: $MODELNAME, 模型路径: $MODELPATH"
|
||||
echo "格式: $FORMAT"
|
||||
|
||||
# 获取原图宽高
|
||||
read orig_w orig_h <<< $(sips -g pixelWidth -g pixelHeight "$INPUT_FILE" 2>/dev/null | awk '/pixelWidth/ {w=$2} /pixelHeight/ {h=$2} END{print w,h}')
|
||||
if [ "$orig_w" -lt "$orig_h" ]; then
|
||||
short=$orig_w
|
||||
long=$orig_h
|
||||
else
|
||||
short=$orig_h
|
||||
long=$orig_w
|
||||
fi
|
||||
echo "DEBUG: orig_w=$orig_w, orig_h=$orig_h, short=$short, long=$long"
|
||||
|
||||
scale1=$(echo "scale=8; 4320/$short" | bc)
|
||||
scale2=$(echo "scale=8; 7680/$long" | bc)
|
||||
echo "DEBUG: scale1=$scale1, scale2=$scale2"
|
||||
|
||||
# 取scale1和scale2的最大值
|
||||
scale=$(echo "$scale1 > $scale2" | bc -l)
|
||||
if [ "$scale" -eq 1 ]; then
|
||||
use_scale=$scale1
|
||||
else
|
||||
use_scale=$scale2
|
||||
fi
|
||||
use_scale=$(printf "%f" "$use_scale")
|
||||
echo "DEBUG: use_scale=$use_scale"
|
||||
|
||||
# 保证不缩小
|
||||
scale_cmp=$(echo "$use_scale > 1" | bc -l)
|
||||
echo "DEBUG: scale_cmp=$scale_cmp"
|
||||
if [ "$scale_cmp" -eq 1 ]; then
|
||||
target_w=$(awk -v w="$orig_w" -v s="$use_scale" 'BEGIN{printf "%d", w*s+0.5}')
|
||||
target_h=$(awk -v h="$orig_h" -v s="$use_scale" 'BEGIN{printf "%d", h*s+0.5}')
|
||||
echo "原图分辨率: ${orig_w}x${orig_h}, 目标分辨率: ${target_w}x${target_h} (短边≥4320, 长边≥7680)"
|
||||
else
|
||||
target_w=$orig_w
|
||||
target_h=$orig_h
|
||||
echo "原图分辨率: ${orig_w}x${orig_h}, 已满足短边≥4320且长边≥7680,无需放大"
|
||||
fi
|
||||
|
||||
# 处理图片,循环调整压缩率直到满足大小要求
|
||||
while true; do
|
||||
echo "尝试第 $try 次: compress=$compress"
|
||||
upscale_cmd="\"$BIN_PATH\" -i \"$INPUT_FILE\" -o \"$OUTPUT_FILE\" -f $FORMAT -m \"$MODELPATH\" -n $MODELNAME -r \"${target_w}x${target_h}\" -c $compress -j $THREADS -v"
|
||||
echo "执行命令: $upscale_cmd"
|
||||
eval $upscale_cmd
|
||||
|
||||
if [ ! -f "$OUTPUT_FILE" ]; then
|
||||
echo "$base: 未生成图片,compress=$compress"
|
||||
echo "处理失败"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
size=$(stat -f%z "$OUTPUT_FILE")
|
||||
res=$(sips -g pixelWidth -g pixelHeight "$OUTPUT_FILE" 2>/dev/null | awk '/pixelWidth|pixelHeight/ {print $2}' | xargs | sed 's/ /x/')
|
||||
echo "$base: compress=$compress, size=${size} bytes, 分辨率=${res}"
|
||||
|
||||
if [ $size -le $MAX_SIZE ] || [ $compress -ge 100 ]; then
|
||||
echo "$base: 满足大小要求,最终 compress=$compress"
|
||||
break
|
||||
fi
|
||||
|
||||
# compress 每次递增10,最大不超过100
|
||||
compress=$((compress + 10))
|
||||
[ $compress -gt 100 ] && compress=100
|
||||
try=$((try+1))
|
||||
[ $try -gt 10 ] && echo "$base: 达到最大尝试次数,停止调整" && break
|
||||
done
|
||||
|
||||
echo "\n===== 处理完成 ====="
|
||||
if [ -f "$OUTPUT_FILE" ]; then
|
||||
input_size=$(stat -f%z "$INPUT_FILE")
|
||||
output_size=$(stat -f%z "$OUTPUT_FILE")
|
||||
input_res=$(sips -g pixelWidth -g pixelHeight "$INPUT_FILE" 2>/dev/null | awk '/pixelWidth|pixelHeight/ {print $2}' | xargs | sed 's/ /x/')
|
||||
output_res=$(sips -g pixelWidth -g pixelHeight "$OUTPUT_FILE" 2>/dev/null | awk '/pixelWidth|pixelHeight/ {print $2}' | xargs | sed 's/ /x/')
|
||||
|
||||
echo "输入: $(basename "$INPUT_FILE") - ${input_size} bytes, ${input_res}"
|
||||
echo "输出: $(basename "$OUTPUT_FILE") - ${output_size} bytes, ${output_res}"
|
||||
echo "处理成功完成!"
|
||||
else
|
||||
echo "处理失败:未生成输出文件"
|
||||
exit 1
|
||||
fi
|
||||
4
examples/dart/cli_headless/.gitignore
vendored
@@ -1,4 +0,0 @@
|
||||
# https://dart.dev/guides/libraries/private-files
|
||||
# Created by `dart pub`
|
||||
.dart_tool/
|
||||
output/**
|
||||
@@ -1,3 +0,0 @@
|
||||
## 1.0.0
|
||||
|
||||
- Initial version.
|
||||
@@ -1,9 +0,0 @@
|
||||
# cli_headless
|
||||
|
||||
A simple headless Dart CLI app using Thermion to render to a bitmap.
|
||||
|
||||
To run:
|
||||
`dart --enable-experiment=native-assets run bin/example.dart`
|
||||
|
||||
Currently, this will probably only work on a non-virtualized macOS host.
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
# This file configures the static analysis results for your project (errors,
|
||||
# warnings, and lints).
|
||||
#
|
||||
# This enables the 'recommended' set of lints from `package:lints`.
|
||||
# This set helps identify many issues that may lead to problems when running
|
||||
# or consuming Dart code, and enforces writing Dart using a single, idiomatic
|
||||
# style and format.
|
||||
#
|
||||
# If you want a smaller set of lints you can change this to specify
|
||||
# 'package:lints/core.yaml'. These are just the most critical lints
|
||||
# (the recommended set includes the core lints).
|
||||
# The core lints are also what is used by pub.dev for scoring packages.
|
||||
|
||||
include: package:lints/recommended.yaml
|
||||
|
||||
# Uncomment the following section to specify additional rules.
|
||||
|
||||
# linter:
|
||||
# rules:
|
||||
# - camel_case_types
|
||||
|
||||
# analyzer:
|
||||
# exclude:
|
||||
# - path/to/excluded/files/**
|
||||
|
||||
# For more information about the core and recommended set of lints, see
|
||||
# https://dart.dev/go/core-lints
|
||||
|
||||
# For additional information about configuring this file, see
|
||||
# https://dart.dev/guides/language/analysis-options
|
||||
@@ -1,32 +0,0 @@
|
||||
import 'dart:io';
|
||||
import 'dart:isolate';
|
||||
|
||||
import 'package:thermion_dart/thermion_dart.dart';
|
||||
import 'package:thermion_dart/src/filament/src/implementation/ffi_filament_app.dart';
|
||||
|
||||
void main() async {
|
||||
await FFIFilamentApp.create();
|
||||
final (width, height) = (500, 500);
|
||||
final sc = await FilamentApp.instance!.createHeadlessSwapChain(width, height);
|
||||
var viewer = ThermionViewerFFI();
|
||||
await viewer.initialized;
|
||||
|
||||
await FilamentApp.instance!.register(sc, viewer.view);
|
||||
|
||||
await viewer.view.setFrustumCullingEnabled(false);
|
||||
await viewer.setBackgroundColor(1, 0, 1, 1);
|
||||
await viewer.setViewport(width, height);
|
||||
final result = await FilamentApp.instance!.capture(
|
||||
sc,
|
||||
view: viewer.view,
|
||||
);
|
||||
|
||||
final bitmap = await pixelBufferToBmp(result.first.$2, width, height,
|
||||
hasAlpha: true, isFloat: true);
|
||||
|
||||
var outfile = File("output/render.bmp");
|
||||
outfile.parent.create();
|
||||
outfile.writeAsBytesSync(bitmap);
|
||||
await FilamentApp.instance!.destroy();
|
||||
Isolate.current.kill();
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
name: example_cli
|
||||
description: A sample command-line application.
|
||||
version: 1.0.0
|
||||
|
||||
environment:
|
||||
sdk: ^3.3.0
|
||||
|
||||
hooks:
|
||||
user_defines:
|
||||
thermion_dart:
|
||||
mode: debug
|
||||
tracing: enabled
|
||||
|
||||
dependencies:
|
||||
thermion_dart:
|
||||
path: ../../../thermion_dart
|
||||
|
||||
dev_dependencies:
|
||||
ffigen: ^11.0.0
|
||||
lints: ^3.0.0
|
||||
test: ^1.24.0
|
||||
@@ -1,8 +1,9 @@
|
||||
import 'dart:ffi';
|
||||
import 'dart:io';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:ffi/ffi.dart';
|
||||
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_filament_app.dart';
|
||||
import 'package:thermion_dart/src/utils/src/dart_resources.dart';
|
||||
import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_viewer_ffi.dart';
|
||||
import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_dart.g.dart';
|
||||
import 'package:thermion_dart/thermion_dart.dart';
|
||||
@@ -12,17 +13,29 @@ import 'package:cli_windows/thermion_window.g.dart';
|
||||
void main(List<String> arguments) async {
|
||||
var hwnd = create_thermion_window(500, 500, 0, 0);
|
||||
update();
|
||||
await FFIFilamentApp.create();
|
||||
var viewer = ThermionViewerFFI(
|
||||
loadAssetFromUri: (path) async => File(path.replaceAll("file://", "")).readAsBytesSync());
|
||||
|
||||
final resourceLoader = calloc<ResourceLoaderWrapper>(1);
|
||||
|
||||
var loadToOut = NativeCallable<
|
||||
Void Function(Pointer<Char>,
|
||||
Pointer<ResourceBuffer>)>.listener(DartResourceLoader.loadResource);
|
||||
|
||||
resourceLoader.ref.loadToOut = loadToOut.nativeFunction;
|
||||
var freeResource = NativeCallable<Void Function(ResourceBuffer)>.listener(
|
||||
DartResourceLoader.freeResource);
|
||||
resourceLoader.ref.freeResource = freeResource.nativeFunction;
|
||||
|
||||
var viewer = ThermionViewerFFI(
|
||||
resourceLoader: resourceLoader.cast<Void>());
|
||||
|
||||
await viewer.initialized;
|
||||
var swapChain = await FilamentApp.instance!.createSwapChain(Pointer<Void>.fromAddress(hwnd));
|
||||
var view = viewer.view;
|
||||
await view.setViewport(500, 500);
|
||||
var camera = await viewer.getActiveCamera();
|
||||
var swapChain = await viewer.createHeadlessSwapChain(500,500);
|
||||
var view = await viewer.getViewAt(0);
|
||||
await view.updateViewport(500, 500);
|
||||
var camera = await viewer.getMainCamera();
|
||||
await camera.setLensProjection();
|
||||
await FilamentApp.instance!.register(swapChain, view);
|
||||
|
||||
await view.setRenderable(true, swapChain);
|
||||
|
||||
await viewer.setBackgroundColor(1.0, 0.0, 0.0, 1.0);
|
||||
|
||||
@@ -36,15 +49,15 @@ void main(List<String> arguments) async {
|
||||
|
||||
var last = 0;
|
||||
|
||||
await camera.lookAt(Vector3(0, 0, 10));
|
||||
await viewer.setCameraPosition(0, 0, 10);
|
||||
|
||||
while(true) {
|
||||
var angle = (stopwatch.elapsedMilliseconds / 1000) * 2 * pi;
|
||||
var rotation = Quaternion.axisAngle(Vector3(0,1,0), angle);
|
||||
var position = Vector3(10 * sin(angle), 0, 10 * cos(angle));
|
||||
var modelMatrix = Matrix4.compose(position, rotation, Vector3.all(1));
|
||||
await camera.setModelMatrix(modelMatrix);
|
||||
await FilamentApp.instance!.requestFrame();
|
||||
await viewer.setCameraModelMatrix4(modelMatrix);
|
||||
await viewer.render();
|
||||
update();
|
||||
await Future.delayed(Duration(milliseconds: 17));
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import 'dart:io';
|
||||
import 'package:archive/archive.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:native_assets_cli/native_assets_cli.dart';
|
||||
import 'package:native_toolchain_c/native_toolchain_c.dart';
|
||||
@@ -8,22 +10,23 @@ void main(List<String> args) async {
|
||||
..level = Level.ALL
|
||||
..onRecord.listen((record) => print(
|
||||
record.message + "\n"));
|
||||
await build(args, (input, output) async {
|
||||
|
||||
await build(args, (config, output) async {
|
||||
|
||||
final cbuilder = CBuilder.library(
|
||||
name: input.packageName,
|
||||
name: "thermion_window",
|
||||
language: Language.cpp,
|
||||
assetName: 'cli_windows.dart',
|
||||
assetName: 'thermion_window.dart',
|
||||
sources: ['native/thermion_window.cpp'],
|
||||
includes: ['native', '../../../thermion_dart/native/include'],
|
||||
defines: {"UNICODE":"1"},
|
||||
flags:[],
|
||||
dartBuildFiles: ['hook/build.dart'],
|
||||
|
||||
);
|
||||
|
||||
await cbuilder.run(
|
||||
input: input,
|
||||
output: output,
|
||||
buildConfig: config,
|
||||
buildOutput: output,
|
||||
logger: logger,
|
||||
);
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//
|
||||
// Generated by `package:ffigen`.
|
||||
// ignore_for_file: type=lint
|
||||
@ffi.DefaultAsset('package:cli_windows/cli_windows.dart')
|
||||
@ffi.DefaultAsset('package:cli_windows/thermion_window.dart')
|
||||
library;
|
||||
|
||||
import 'dart:ffi' as ffi;
|
||||
|
||||
@@ -1,21 +1,42 @@
|
||||
name: cli_windows
|
||||
description: A sample command-line application with basic argument parsing.
|
||||
version: 0.0.1
|
||||
# repository: https://github.com/my_org/my_repo
|
||||
|
||||
environment:
|
||||
sdk: ^3.6.0-326.0.dev
|
||||
|
||||
# Add regular dependencies here.
|
||||
dependencies:
|
||||
args: ^2.5.0
|
||||
thermion_dart:
|
||||
path: ../../../thermion_dart
|
||||
ffi: ^2.1.3
|
||||
vector_math: ^2.1.4
|
||||
native_toolchain_c: ^0.9.0
|
||||
native_assets_cli: ^0.12.0
|
||||
native_toolchain_c: ^0.4.2
|
||||
native_assets_cli: ^0.6.1
|
||||
|
||||
dev_dependencies:
|
||||
lints: ^5.0.0
|
||||
test: ^1.24.0
|
||||
ffigen: ^13.0.0
|
||||
ffigen:
|
||||
output: 'lib/thermion_window.g.dart'
|
||||
headers:
|
||||
entry-points:
|
||||
- 'native/thermion_window.h'
|
||||
include-directives:
|
||||
- 'native/thermion_window.h'
|
||||
ffi-native:
|
||||
assetId: package:cli_windows/thermion_window.dart
|
||||
ignore-source-errors: true
|
||||
llvm-path:
|
||||
- E:\clang+llvm-19.1.3-x86_64-pc-windows-msvc\bin
|
||||
- E:\clang+llvm-19.1.3-x86_64-pc-windows-msvc\
|
||||
- E:\clang+llvm-19.1.3-x86_64-pc-windows-msvc\lib
|
||||
functions:
|
||||
leaf:
|
||||
include:
|
||||
- '.*'
|
||||
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
name: example_web
|
||||
description: A sample command-line application.
|
||||
version: 1.0.0
|
||||
# repository: https://github.com/my_org/my_repo
|
||||
|
||||
environment:
|
||||
sdk: ^3.3.0
|
||||
|
||||
dependencies:
|
||||
thermion_dart:
|
||||
path: ../../../thermion_dart
|
||||
logging: ^1.3.0
|
||||
|
||||
dev_dependencies:
|
||||
lints: ^3.0.0
|
||||
test: ^1.24.0
|
||||
build_runner: ^2.4.13
|
||||
build_test: ^2.2.2
|
||||
build_web_compilers: ^4.1.5
|
||||
@@ -1 +0,0 @@
|
||||
../../../assets/
|
||||
@@ -1,101 +0,0 @@
|
||||
import 'dart:async';
|
||||
import 'dart:js_interop';
|
||||
import 'dart:math';
|
||||
import 'package:web/web.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:thermion_dart/thermion_dart.dart'
|
||||
hide NativeLibrary, Image_decode;
|
||||
import 'package:thermion_dart/src/filament/src/implementation/ffi_filament_app.dart';
|
||||
import 'web_input_handler.dart';
|
||||
import 'package:thermion_dart/src/bindings/src/thermion_dart_js_interop.g.dart';
|
||||
|
||||
void main(List<String> arguments) async {
|
||||
Logger.root.onRecord.listen((record) {
|
||||
print(record);
|
||||
});
|
||||
|
||||
NativeLibrary.initBindings("thermion_dart");
|
||||
|
||||
final canvas =
|
||||
document.getElementById("thermion_canvas") as HTMLCanvasElement;
|
||||
try {
|
||||
canvas.width = canvas.clientWidth;
|
||||
canvas.height = canvas.clientHeight;
|
||||
} catch (err) {
|
||||
print(err.toString());
|
||||
}
|
||||
|
||||
final config = FFIFilamentConfig(backend: Backend.OPENGL);
|
||||
|
||||
await FFIFilamentApp.create(config: config);
|
||||
|
||||
var swapChain = await FilamentApp.instance!
|
||||
.createHeadlessSwapChain(canvas.width, canvas.height);
|
||||
final viewer = ThermionViewerFFI();
|
||||
await viewer.initialized;
|
||||
await FilamentApp.instance!.setClearOptions(1.0, 0.0, 0.0, 1.0);
|
||||
await FilamentApp.instance!.register(swapChain, viewer.view);
|
||||
await viewer.setViewport(canvas.width, canvas.height);
|
||||
await viewer.setRendering(true);
|
||||
final rnd = Random();
|
||||
// ignore: prefer_function_declarations_over_variables
|
||||
bool resizing = false;
|
||||
// ignore: prefer_function_declarations_over_variables
|
||||
final resizer = () async {
|
||||
if (resizing) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
resizing = true;
|
||||
await viewer.setViewport(canvas.clientWidth, canvas.clientHeight);
|
||||
Thermion_resizeCanvas(canvas.clientWidth, canvas.clientHeight);
|
||||
} catch (err) {
|
||||
print(err);
|
||||
} finally {
|
||||
resizing = false;
|
||||
}
|
||||
};
|
||||
// ignore: unused_local_variable, prefer_function_declarations_over_variables
|
||||
final jsWrapper = () {
|
||||
var promise = resizer().toJS;
|
||||
return promise;
|
||||
};
|
||||
window.addEventListener('resize', jsWrapper.toJS);
|
||||
// // await FilamentApp.instance!.render();
|
||||
// // await Future.delayed(Duration(seconds: 1));
|
||||
|
||||
// // await FilamentApp.instance!.setClearOptions(1.0, 1.0, 0.0, 1.0);
|
||||
// // await FilamentApp.instance!.render();
|
||||
// // await Future.delayed(Duration(seconds: 1));
|
||||
|
||||
await viewer.loadSkybox("assets/default_env_skybox.ktx");
|
||||
await viewer.loadGltf("assets/cube.glb");
|
||||
final camera = await viewer.getActiveCamera();
|
||||
|
||||
var zOffset = 10.0;
|
||||
|
||||
final inputHandler = DelegateInputHandler.flight(viewer);
|
||||
|
||||
final webInputHandler =
|
||||
WebInputHandler(inputHandler: inputHandler, canvas: canvas);
|
||||
await camera.lookAt(Vector3(0, 0, zOffset));
|
||||
DateTime lastRender = DateTime.now();
|
||||
|
||||
while (true) {
|
||||
var stackPtr = stackSave();
|
||||
var now = DateTime.now();
|
||||
await FilamentApp.instance!.requestFrame();
|
||||
now = DateTime.now();
|
||||
var timeSinceLast =
|
||||
now.microsecondsSinceEpoch - lastRender.microsecondsSinceEpoch;
|
||||
lastRender = now;
|
||||
if (timeSinceLast < 1667) {
|
||||
var waitFor = 1667 - timeSinceLast;
|
||||
await Future.delayed(Duration(microseconds: waitFor));
|
||||
}
|
||||
stackRestore(stackPtr);
|
||||
// inputHandler.keyDown(PhysicalKey.S);
|
||||
// await camera.lookAt(Vector3(0,0,zOffset));
|
||||
// zOffset +=0.1;
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script type="text/javascript" src="./thermion_dart.js"></script>
|
||||
<script type="module">
|
||||
try {
|
||||
window.thermion_dart = await thermion_dart();
|
||||
} catch(err) {
|
||||
console.error(err);
|
||||
}
|
||||
const script = document.createElement('script')
|
||||
script.src = 'example.dart.js'
|
||||
document.head.append(script);
|
||||
</script>
|
||||
<style>
|
||||
html, body {
|
||||
margin:0;
|
||||
padding:0;
|
||||
}
|
||||
canvas {
|
||||
position:absolute;
|
||||
left:0;
|
||||
right:0;
|
||||
top:0;
|
||||
bottom:0;
|
||||
width:100%;
|
||||
height:100%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<canvas id="thermion_canvas"></canvas>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,35 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<script src="thermion_dart.js"></script>
|
||||
<style>
|
||||
html, body {
|
||||
margin:0;
|
||||
padding:0;
|
||||
}
|
||||
canvas {
|
||||
position:absolute;
|
||||
left:0;
|
||||
right:0;
|
||||
top:0;
|
||||
bottom:0;
|
||||
width:100%;
|
||||
height:100%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<script type="module">
|
||||
try {
|
||||
window.thermion_dart = await thermion_dart();
|
||||
} catch(err) {
|
||||
console.error(err);
|
||||
}
|
||||
const dartModulePromise = WebAssembly.compileStreaming(fetch('./example.wasm'));
|
||||
const imports = {};
|
||||
const dart2wasm_runtime = await import('./example.mjs');
|
||||
const moduleInstance = await dart2wasm_runtime.instantiate(dartModulePromise, imports);
|
||||
await dart2wasm_runtime.invoke(moduleInstance);
|
||||
</script>
|
||||
<body>
|
||||
<canvas id="canvas"></canvas>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,22 +0,0 @@
|
||||
import { readFile } from 'fs/promises';
|
||||
|
||||
import { compile } from './example.mjs';
|
||||
import thermion_dart from './thermion_dart.js';
|
||||
|
||||
|
||||
async function runDartWasm() {
|
||||
globalThis['thermion_dart'] = await thermion_dart();
|
||||
|
||||
const wasmBytes = await readFile('example.wasm');
|
||||
const compiledApp = await compile(wasmBytes);
|
||||
const instantiatedApp = await compiledApp.instantiate({});
|
||||
try {
|
||||
instantiatedApp.invokeMain();
|
||||
} catch(err) {
|
||||
console.error("Failed");
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
runDartWasm().catch(console.error);
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
../../../../thermion_dart/native/web/build/build/out/thermion_dart.js
|
||||
@@ -1 +0,0 @@
|
||||
../../../../thermion_dart/native/web/build/build/out/thermion_dart.wasm
|
||||
@@ -1,299 +0,0 @@
|
||||
import 'dart:js_interop';
|
||||
|
||||
import 'package:web/web.dart' as web;
|
||||
import 'package:thermion_dart/thermion_dart.dart';
|
||||
|
||||
class WebInputHandler {
|
||||
final InputHandler inputHandler;
|
||||
final web.HTMLCanvasElement canvas;
|
||||
late double pixelRatio;
|
||||
|
||||
final Map<int, Vector2> _touchPositions = {};
|
||||
|
||||
WebInputHandler({
|
||||
required this.inputHandler,
|
||||
required this.canvas,
|
||||
}) {
|
||||
pixelRatio = web.window.devicePixelRatio;
|
||||
_initializeEventListeners();
|
||||
}
|
||||
|
||||
void _initializeEventListeners() {
|
||||
canvas.addEventListener('mousedown', _onMouseDown.toJS);
|
||||
canvas.addEventListener('mousemove', _onMouseMove.toJS);
|
||||
canvas.addEventListener('mouseup', _onMouseUp.toJS);
|
||||
canvas.addEventListener('wheel', _onMouseWheel.toJS);
|
||||
web.window.addEventListener('keydown', _onKeyDown.toJS);
|
||||
web.window.addEventListener('keyup', _onKeyUp.toJS);
|
||||
|
||||
canvas.addEventListener('touchstart', _onTouchStart.toJS);
|
||||
canvas.addEventListener('touchmove', _onTouchMove.toJS);
|
||||
canvas.addEventListener('touchend', _onTouchEnd.toJS);
|
||||
canvas.addEventListener('touchcancel', _onTouchCancel.toJS);
|
||||
}
|
||||
|
||||
void _onMouseDown(web.MouseEvent event) {
|
||||
final localPos = _getLocalPositionFromEvent(event);
|
||||
final button = _getMouseButtonFromEvent(event);
|
||||
|
||||
inputHandler.handle(MouseEvent(
|
||||
MouseEventType.buttonDown,
|
||||
button,
|
||||
localPos,
|
||||
Vector2.zero(),
|
||||
));
|
||||
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
void _onMouseMove(web.MouseEvent event) {
|
||||
final localPos = _getLocalPositionFromEvent(event);
|
||||
final delta = Vector2(event.movementX ?? 0, event.movementY ?? 0);
|
||||
final button = _getMouseButtonFromEvent(event);
|
||||
|
||||
inputHandler.handle(MouseEvent(
|
||||
MouseEventType.move,
|
||||
button,
|
||||
localPos,
|
||||
delta,
|
||||
));
|
||||
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
void _onMouseUp(web.MouseEvent event) {
|
||||
final localPos = _getLocalPositionFromEvent(event);
|
||||
final button = _getMouseButtonFromEvent(event);
|
||||
|
||||
inputHandler.handle(MouseEvent(
|
||||
MouseEventType.buttonUp,
|
||||
button,
|
||||
localPos,
|
||||
Vector2.zero(),
|
||||
));
|
||||
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
void _onMouseWheel(web.WheelEvent event) {
|
||||
final localPos = _getLocalPositionFromEvent(event);
|
||||
final delta = event.deltaY;
|
||||
|
||||
inputHandler.handle(ScrollEvent(
|
||||
localPosition: localPos,
|
||||
delta: delta,
|
||||
));
|
||||
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
void _onKeyDown(web.KeyboardEvent event) {
|
||||
PhysicalKey? physicalKey = _getPhysicalKeyFromEvent(event);
|
||||
LogicalKey? logicalKey = _getLogicalKeyFromEvent(event);
|
||||
if (physicalKey != null && logicalKey != null) {
|
||||
inputHandler.handle(KeyEvent(KeyEventType.down, logicalKey, physicalKey));
|
||||
}
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
void _onKeyUp(web.KeyboardEvent event) {
|
||||
LogicalKey? logicalKey = _getLogicalKeyFromEvent(event);
|
||||
PhysicalKey? physicalKey = _getPhysicalKeyFromEvent(event);
|
||||
if (physicalKey != null && logicalKey != null) {
|
||||
inputHandler.handle(KeyEvent(KeyEventType.up, logicalKey, physicalKey));
|
||||
}
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
void _onTouchStart(web.TouchEvent event) {
|
||||
for (var touch in event.changedTouches.toList()) {
|
||||
final pos = _getLocalPositionFromTouch(touch);
|
||||
_touchPositions[touch.identifier] = pos;
|
||||
}
|
||||
|
||||
final touchCount = event.touches.toList().length;
|
||||
if (touchCount == 1) {
|
||||
final touch = event.touches.toList().first;
|
||||
final pos = _getLocalPositionFromTouch(touch);
|
||||
inputHandler.handle(TouchEvent(
|
||||
TouchEventType.tap,
|
||||
pos,
|
||||
null,
|
||||
));
|
||||
}
|
||||
|
||||
if (touchCount >= 2) {
|
||||
final focalPoint = _calculateFocalPoint(event.touches.toList());
|
||||
inputHandler.handle(ScaleStartEvent(
|
||||
numPointers: touchCount,
|
||||
localFocalPoint: (focalPoint.x, focalPoint.y),
|
||||
));
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
void _onTouchMove(web.TouchEvent event) {
|
||||
for (var touch in event.changedTouches.toList()) {
|
||||
final id = touch.identifier;
|
||||
final currPos = _getLocalPositionFromTouch(touch);
|
||||
final prevPos = _touchPositions[id];
|
||||
|
||||
if (prevPos != null) {
|
||||
_touchPositions[id] = currPos;
|
||||
}
|
||||
}
|
||||
|
||||
final touchCount = event.touches.toList().length;
|
||||
if (touchCount >= 2) {
|
||||
final touches = event.touches.toList();
|
||||
final focalPoint = _calculateFocalPoint(touches);
|
||||
|
||||
// Calculate scale
|
||||
final currPositions = touches.map((t) => _getLocalPositionFromTouch(t)).toList();
|
||||
final prevPositions = touches.map((t) => _touchPositions[t.identifier] ?? _getLocalPositionFromTouch(t)).toList();
|
||||
|
||||
final currDist = (currPositions[0] - currPositions[1]).length;
|
||||
final prevDist = (prevPositions[0] - prevPositions[1]).length;
|
||||
final scale = prevDist > 0 ? currDist / prevDist : 1.0;
|
||||
|
||||
// Calculate focal point delta
|
||||
final prevFocalPoint = _calculateFocalPoint(touches, prevPositions);
|
||||
final focalPointDelta = focalPoint - prevFocalPoint;
|
||||
|
||||
inputHandler.handle(ScaleUpdateEvent(
|
||||
numPointers: touchCount,
|
||||
localFocalPoint: (focalPoint.x, focalPoint.y),
|
||||
localFocalPointDelta: (focalPointDelta.x, focalPointDelta.y),
|
||||
rotation: 0.0, // We don't track rotation in the web implementation
|
||||
scale: scale,
|
||||
horizontalScale: scale,
|
||||
verticalScale: scale,
|
||||
));
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
void _onTouchEnd(web.TouchEvent event) {
|
||||
for (var touch in event.changedTouches.toList()) {
|
||||
_touchPositions.remove(touch.identifier);
|
||||
}
|
||||
|
||||
final touchCount = event.touches.toList().length;
|
||||
inputHandler.handle(ScaleEndEvent(
|
||||
numPointers: touchCount,
|
||||
));
|
||||
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
void _onTouchCancel(web.TouchEvent event) {
|
||||
for (var touch in event.changedTouches.toList()) {
|
||||
_touchPositions.remove(touch.identifier);
|
||||
}
|
||||
|
||||
final touchCount = event.touches.toList().length;
|
||||
inputHandler.handle(ScaleEndEvent(
|
||||
numPointers: touchCount,
|
||||
));
|
||||
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
MouseButton? _getMouseButtonFromEvent(web.MouseEvent event) {
|
||||
if (event.button == 1 || (event.buttons & 4 != 0)) {
|
||||
return MouseButton.middle;
|
||||
} else if (event.button == 0 || (event.buttons & 1 != 0)) {
|
||||
return MouseButton.left;
|
||||
} else if (event.button == 2 || (event.buttons & 2 != 0)) {
|
||||
return MouseButton.right;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
PhysicalKey? _getPhysicalKeyFromEvent(web.KeyboardEvent event) {
|
||||
switch (event.code) {
|
||||
case 'KeyW':
|
||||
return PhysicalKey.w;
|
||||
case 'KeyA':
|
||||
return PhysicalKey.a;
|
||||
case 'KeyS':
|
||||
return PhysicalKey.s;
|
||||
case 'KeyD':
|
||||
return PhysicalKey.d;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
LogicalKey? _getLogicalKeyFromEvent(web.KeyboardEvent event) {
|
||||
switch (event.key) {
|
||||
case 'KeyW':
|
||||
return LogicalKey.w;
|
||||
case 'KeyA':
|
||||
return LogicalKey.a;
|
||||
case 'KeyS':
|
||||
return LogicalKey.s;
|
||||
case 'KeyD':
|
||||
return LogicalKey.d;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Vector2 _getLocalPositionFromEvent(web.Event event) {
|
||||
final rect = canvas.getBoundingClientRect();
|
||||
double clientX = 0, clientY = 0;
|
||||
|
||||
if (event is web.MouseEvent) {
|
||||
clientX = event.clientX.toDouble();
|
||||
clientY = event.clientY.toDouble();
|
||||
} else if (event is web.TouchEvent) {
|
||||
final touch = event.touches.toList().firstOrNull;
|
||||
if (touch != null) {
|
||||
clientX = touch.clientX;
|
||||
clientY = touch.clientY;
|
||||
}
|
||||
}
|
||||
|
||||
return Vector2(
|
||||
(clientX - rect.left) * pixelRatio,
|
||||
(clientY - rect.top) * pixelRatio,
|
||||
);
|
||||
}
|
||||
|
||||
Vector2 _getLocalPositionFromTouch(web.Touch touch) {
|
||||
final rect = canvas.getBoundingClientRect();
|
||||
return Vector2(
|
||||
(touch.clientX - rect.left) * pixelRatio,
|
||||
(touch.clientY - rect.top) * pixelRatio,
|
||||
);
|
||||
}
|
||||
|
||||
Vector2 _calculateFocalPoint(List<web.Touch> touches, [List<Vector2>? positions]) {
|
||||
if (touches.isEmpty) return Vector2.zero();
|
||||
|
||||
final points = positions ?? touches.map((t) => _getLocalPositionFromTouch(t)).toList();
|
||||
|
||||
Vector2 sum = Vector2.zero();
|
||||
for (var point in points) {
|
||||
sum += point;
|
||||
}
|
||||
|
||||
return sum.scaled(1.0 / points.length);
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
canvas.removeEventListener('mousedown', _onMouseDown.toJS);
|
||||
canvas.removeEventListener('mousemove', _onMouseMove.toJS);
|
||||
canvas.removeEventListener('mouseup', _onMouseUp.toJS);
|
||||
canvas.removeEventListener('wheel', _onMouseWheel.toJS);
|
||||
web.window.removeEventListener('keydown', _onKeyDown.toJS);
|
||||
web.window.removeEventListener('keyup', _onKeyUp.toJS);
|
||||
canvas.removeEventListener('touchstart', _onTouchStart.toJS);
|
||||
canvas.removeEventListener('touchmove', _onTouchMove.toJS);
|
||||
canvas.removeEventListener('touchend', _onTouchEnd.toJS);
|
||||
canvas.removeEventListener('touchcancel', _onTouchCancel.toJS);
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
plugins {
|
||||
id "com.android.application"
|
||||
id "kotlin-android"
|
||||
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
|
||||
id "dev.flutter.flutter-gradle-plugin"
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.example.quickstart"
|
||||
compileSdk = flutter.compileSdkVersion
|
||||
ndkVersion = flutter.ndkVersion
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||
applicationId = "com.example.quickstart"
|
||||
// You can update the following values to match your application needs.
|
||||
// For more information, see: https://flutter.dev/to/review-gradle-config.
|
||||
minSdk = 22
|
||||
targetSdk = flutter.targetSdkVersion
|
||||
versionCode = flutter.versionCode
|
||||
versionName = flutter.versionName
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
// TODO: Add your own signing config for the release build.
|
||||
// Signing with the debug keys for now, so `flutter run --release` works.
|
||||
signingConfig = signingConfigs.debug
|
||||
shrinkResources false
|
||||
minifyEnabled false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flutter {
|
||||
source = "../.."
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<application
|
||||
android:label="camera_manipulation"
|
||||
android:name="${applicationName}"
|
||||
android:icon="@mipmap/ic_launcher">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
android:launchMode="singleTop"
|
||||
android:taskAffinity=""
|
||||
android:theme="@style/LaunchTheme"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<!-- Specifies an Android theme to apply to this Activity as soon as
|
||||
the Android process has started. This theme is visible to the user
|
||||
while the Flutter UI initializes. After that, this theme continues
|
||||
to determine the Window background behind the Flutter UI. -->
|
||||
<meta-data
|
||||
android:name="io.flutter.embedding.android.NormalTheme"
|
||||
android:resource="@style/NormalTheme"
|
||||
/>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<!-- Don't delete the meta-data below.
|
||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
||||
<meta-data
|
||||
android:name="flutterEmbedding"
|
||||
android:value="2" />
|
||||
<meta-data
|
||||
android:name="io.flutter.embedding.android.EnableImpeller"
|
||||
android:value="false" />
|
||||
</application>
|
||||
<!-- Required to query activities that can process text, see:
|
||||
https://developer.android.com/training/package-visibility and
|
||||
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
|
||||
|
||||
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
|
||||
<queries>
|
||||
<intent>
|
||||
<action android:name="android.intent.action.PROCESS_TEXT"/>
|
||||
<data android:mimeType="text/plain"/>
|
||||
</intent>
|
||||
</queries>
|
||||
</manifest>
|
||||
@@ -1,26 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>App</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>io.flutter.flutter.app</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>App</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>13.0</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,88 +0,0 @@
|
||||
PODS:
|
||||
- DKImagePickerController/Core (4.3.9):
|
||||
- DKImagePickerController/ImageDataManager
|
||||
- DKImagePickerController/Resource
|
||||
- DKImagePickerController/ImageDataManager (4.3.9)
|
||||
- DKImagePickerController/PhotoGallery (4.3.9):
|
||||
- DKImagePickerController/Core
|
||||
- DKPhotoGallery
|
||||
- DKImagePickerController/Resource (4.3.9)
|
||||
- DKPhotoGallery (0.0.19):
|
||||
- DKPhotoGallery/Core (= 0.0.19)
|
||||
- DKPhotoGallery/Model (= 0.0.19)
|
||||
- DKPhotoGallery/Preview (= 0.0.19)
|
||||
- DKPhotoGallery/Resource (= 0.0.19)
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
- DKPhotoGallery/Core (0.0.19):
|
||||
- DKPhotoGallery/Model
|
||||
- DKPhotoGallery/Preview
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
- DKPhotoGallery/Model (0.0.19):
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
- DKPhotoGallery/Preview (0.0.19):
|
||||
- DKPhotoGallery/Model
|
||||
- DKPhotoGallery/Resource
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
- DKPhotoGallery/Resource (0.0.19):
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
- file_picker (0.0.1):
|
||||
- DKImagePickerController/PhotoGallery
|
||||
- Flutter
|
||||
- Flutter (1.0.0)
|
||||
- package_info_plus (0.4.5):
|
||||
- Flutter
|
||||
- path_provider_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- SDWebImage (5.21.1):
|
||||
- SDWebImage/Core (= 5.21.1)
|
||||
- SDWebImage/Core (5.21.1)
|
||||
- SwiftyGif (5.4.5)
|
||||
- thermion_flutter (0.0.1):
|
||||
- Flutter
|
||||
|
||||
DEPENDENCIES:
|
||||
- file_picker (from `.symlinks/plugins/file_picker/ios`)
|
||||
- Flutter (from `Flutter`)
|
||||
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
||||
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
||||
- thermion_flutter (from `.symlinks/plugins/thermion_flutter/ios`)
|
||||
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
- DKImagePickerController
|
||||
- DKPhotoGallery
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
file_picker:
|
||||
:path: ".symlinks/plugins/file_picker/ios"
|
||||
Flutter:
|
||||
:path: Flutter
|
||||
package_info_plus:
|
||||
:path: ".symlinks/plugins/package_info_plus/ios"
|
||||
path_provider_foundation:
|
||||
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
||||
thermion_flutter:
|
||||
:path: ".symlinks/plugins/thermion_flutter/ios"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
|
||||
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
|
||||
file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be
|
||||
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
||||
package_info_plus: 580e9a5f1b6ca5594e7c9ed5f92d1dfb2a66b5e1
|
||||
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
|
||||
SDWebImage: f29024626962457f3470184232766516dee8dfea
|
||||
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
|
||||
thermion_flutter: d0c4adbb1de69e5ecc244d70bbde81d8497246b2
|
||||
|
||||
PODFILE CHECKSUM: a57f30d18f102dd3ce366b1d62a55ecbef2158e5
|
||||
|
||||
COCOAPODS: 1.16.2
|
||||
@@ -1,733 +0,0 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 54;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
||||
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
|
||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
||||
F657CCCFB062AF56C7F1E15C /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D988E66CA93AB1163F3B4F2 /* Pods_RunnerTests.framework */; };
|
||||
F8DC37C0013EE3DC8802435E /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B0831D015898C7047513698C /* Pods_Runner.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 97C146E61CF9000F007C117D /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 97C146ED1CF9000F007C117D;
|
||||
remoteInfo = Runner;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
);
|
||||
name = "Embed Frameworks";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
||||
31D54E0731320192F7631461 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
|
||||
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
3680A9DFE5EC3E59C051B544 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
||||
3D988E66CA93AB1163F3B4F2 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
704E1C99CAABFB056933D88F /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
||||
8C0FE5C77038897D844C5D42 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
|
||||
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
|
||||
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
9CD72080C199DAE3518D4C3D /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
B0831D015898C7047513698C /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
BA68F2C1572D8BC92CC4C4FF /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
97C146EB1CF9000F007C117D /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
F8DC37C0013EE3DC8802435E /* Pods_Runner.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
FA72758808529BDB8770545F /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
F657CCCFB062AF56C7F1E15C /* Pods_RunnerTests.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
0DB20859A61D425430A5D097 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B0831D015898C7047513698C /* Pods_Runner.framework */,
|
||||
3D988E66CA93AB1163F3B4F2 /* Pods_RunnerTests.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
331C8082294A63A400263BE5 /* RunnerTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
331C807B294A618700263BE5 /* RunnerTests.swift */,
|
||||
);
|
||||
path = RunnerTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4A129A4D3EB41F9DE0778AAC /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
704E1C99CAABFB056933D88F /* Pods-Runner.debug.xcconfig */,
|
||||
3680A9DFE5EC3E59C051B544 /* Pods-Runner.release.xcconfig */,
|
||||
8C0FE5C77038897D844C5D42 /* Pods-Runner.profile.xcconfig */,
|
||||
31D54E0731320192F7631461 /* Pods-RunnerTests.debug.xcconfig */,
|
||||
BA68F2C1572D8BC92CC4C4FF /* Pods-RunnerTests.release.xcconfig */,
|
||||
9CD72080C199DAE3518D4C3D /* Pods-RunnerTests.profile.xcconfig */,
|
||||
);
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9740EEB11CF90186004384FC /* Flutter */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
|
||||
9740EEB21CF90195004384FC /* Debug.xcconfig */,
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
|
||||
9740EEB31CF90195004384FC /* Generated.xcconfig */,
|
||||
);
|
||||
name = Flutter;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146E51CF9000F007C117D = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9740EEB11CF90186004384FC /* Flutter */,
|
||||
97C146F01CF9000F007C117D /* Runner */,
|
||||
97C146EF1CF9000F007C117D /* Products */,
|
||||
331C8082294A63A400263BE5 /* RunnerTests */,
|
||||
4A129A4D3EB41F9DE0778AAC /* Pods */,
|
||||
0DB20859A61D425430A5D097 /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146EF1CF9000F007C117D /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
97C146EE1CF9000F007C117D /* Runner.app */,
|
||||
331C8081294A63A400263BE5 /* RunnerTests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146F01CF9000F007C117D /* Runner */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
97C146FA1CF9000F007C117D /* Main.storyboard */,
|
||||
97C146FD1CF9000F007C117D /* Assets.xcassets */,
|
||||
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
|
||||
97C147021CF9000F007C117D /* Info.plist */,
|
||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
|
||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
|
||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
|
||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
|
||||
);
|
||||
path = Runner;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
331C8080294A63A400263BE5 /* RunnerTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
|
||||
buildPhases = (
|
||||
78F05AF37D9E628BE6E89ABD /* [CP] Check Pods Manifest.lock */,
|
||||
331C807D294A63A400263BE5 /* Sources */,
|
||||
331C807F294A63A400263BE5 /* Resources */,
|
||||
FA72758808529BDB8770545F /* Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
331C8086294A63A400263BE5 /* PBXTargetDependency */,
|
||||
);
|
||||
name = RunnerTests;
|
||||
productName = RunnerTests;
|
||||
productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
97C146ED1CF9000F007C117D /* Runner */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||
buildPhases = (
|
||||
C7C2718364AC4E2451407065 /* [CP] Check Pods Manifest.lock */,
|
||||
9740EEB61CF901F6004384FC /* Run Script */,
|
||||
97C146EA1CF9000F007C117D /* Sources */,
|
||||
97C146EB1CF9000F007C117D /* Frameworks */,
|
||||
97C146EC1CF9000F007C117D /* Resources */,
|
||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||
6DA127E3193C7EF5F7B6B4C0 /* [CP] Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = Runner;
|
||||
productName = Runner;
|
||||
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
97C146E61CF9000F007C117D /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
BuildIndependentTargetsInParallel = YES;
|
||||
LastUpgradeCheck = 1510;
|
||||
ORGANIZATIONNAME = "";
|
||||
TargetAttributes = {
|
||||
331C8080294A63A400263BE5 = {
|
||||
CreatedOnToolsVersion = 14.0;
|
||||
TestTargetID = 97C146ED1CF9000F007C117D;
|
||||
};
|
||||
97C146ED1CF9000F007C117D = {
|
||||
CreatedOnToolsVersion = 7.3.1;
|
||||
LastSwiftMigration = 1100;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
|
||||
compatibilityVersion = "Xcode 9.3";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 97C146E51CF9000F007C117D;
|
||||
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
97C146ED1CF9000F007C117D /* Runner */,
|
||||
331C8080294A63A400263BE5 /* RunnerTests */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
331C807F294A63A400263BE5 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
97C146EC1CF9000F007C117D /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
|
||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
|
||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
|
||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
|
||||
);
|
||||
name = "Thin Binary";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
|
||||
};
|
||||
6DA127E3193C7EF5F7B6B4C0 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
78F05AF37D9E628BE6E89ABD /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
9740EEB61CF901F6004384FC /* Run Script */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Run Script";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
||||
};
|
||||
C7C2718364AC4E2451407065 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
331C807D294A63A400263BE5 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
97C146EA1CF9000F007C117D /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
|
||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
331C8086294A63A400263BE5 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 97C146ED1CF9000F007C117D /* Runner */;
|
||||
targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
97C146FB1CF9000F007C117D /* Base */,
|
||||
);
|
||||
name = Main.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
97C147001CF9000F007C117D /* Base */,
|
||||
);
|
||||
name = LaunchScreen.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
249021D3217E4FDB00AE95B9 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
249021D4217E4FDB00AE95B9 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = 979UK3QQJ3;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.quickstart;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
331C8088294A63A400263BE5 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 31D54E0731320192F7631461 /* Pods-RunnerTests.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.quickstart.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
331C8089294A63A400263BE5 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = BA68F2C1572D8BC92CC4C4FF /* Pods-RunnerTests.release.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.quickstart.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
331C808A294A63A400263BE5 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 9CD72080C199DAE3518D4C3D /* Pods-RunnerTests.profile.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.quickstart.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
97C147031CF9000F007C117D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
97C147041CF9000F007C117D /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
97C147061CF9000F007C117D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = 979UK3QQJ3;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.quickstart;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
97C147071CF9000F007C117D /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = 979UK3QQJ3;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.quickstart;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
331C8088294A63A400263BE5 /* Debug */,
|
||||
331C8089294A63A400263BE5 /* Release */,
|
||||
331C808A294A63A400263BE5 /* Profile */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
97C147031CF9000F007C117D /* Debug */,
|
||||
97C147041CF9000F007C117D /* Release */,
|
||||
249021D3217E4FDB00AE95B9 /* Profile */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
97C147061CF9000F007C117D /* Debug */,
|
||||
97C147071CF9000F007C117D /* Release */,
|
||||
249021D4217E4FDB00AE95B9 /* Profile */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 97C146E61CF9000F007C117D /* Project object */;
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1510"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||
BuildableName = "Runner.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||
BuildableName = "Runner.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO"
|
||||
parallelizable = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "331C8080294A63A400263BE5"
|
||||
BuildableName = "RunnerTests.xctest"
|
||||
BlueprintName = "RunnerTests"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
enableGPUValidationMode = "1"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||
BuildableName = "Runner.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Profile"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||
BuildableName = "Runner.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
@@ -1,114 +0,0 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:thermion_flutter/thermion_flutter.dart';
|
||||
|
||||
class Cup extends StatefulWidget {
|
||||
const Cup({super.key});
|
||||
|
||||
@override
|
||||
State<Cup> createState() => _CupState();
|
||||
}
|
||||
|
||||
class _CupState extends State<Cup> {
|
||||
bool _isLoading = true;
|
||||
String? _modelPath, _modelUri;
|
||||
String _statusMessage = "正在加载本地模型...";
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_loadLocalModel();
|
||||
}
|
||||
|
||||
// 从应用支持目录加载模型
|
||||
Future<void> _loadLocalModel() async {
|
||||
try {
|
||||
setState(() {
|
||||
_statusMessage = "获取本地模型路径...";
|
||||
});
|
||||
|
||||
final supportDir = await getApplicationSupportDirectory();
|
||||
final modelFile = File(p.join(supportDir.path, 'cup', 'model.gltf'));
|
||||
|
||||
String modelPath =
|
||||
File(p.join(supportDir.path, 'cup', 'model.gltf')).absolute.path;
|
||||
final cupDir = Directory('${supportDir.path}/cup');
|
||||
final modelUri = File('${cupDir.path}/model.gltf').uri.toString();
|
||||
print('加载本地模modelPath: $modelPath');
|
||||
print('加载本地模modelUri: $modelUri');
|
||||
|
||||
if (await modelFile.exists()) {
|
||||
setState(() {
|
||||
_modelPath = modelPath;
|
||||
_modelUri = modelUri;
|
||||
|
||||
_isLoading = false;
|
||||
_statusMessage = "本地模型加载完成";
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
_statusMessage = "本地模型文件不存在";
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
print('加载本地模型失败: $e');
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
_statusMessage = "加载失败: $e";
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('本地模型查看'),
|
||||
),
|
||||
body: _isLoading
|
||||
? Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const CircularProgressIndicator(),
|
||||
const SizedBox(height: 16),
|
||||
Text(_statusMessage),
|
||||
],
|
||||
),
|
||||
)
|
||||
: _modelPath == null
|
||||
? Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(Icons.error, size: 48, color: Colors.red),
|
||||
const SizedBox(height: 16),
|
||||
Text(_statusMessage),
|
||||
const SizedBox(height: 16),
|
||||
ElevatedButton(
|
||||
onPressed: _loadLocalModel,
|
||||
child: const Text('重试'),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: ViewerWidget(
|
||||
// assetPath: "file://$_modelPath",
|
||||
assetPath: _modelUri,
|
||||
skyboxPath: "assets/default_env_skybox.ktx",
|
||||
iblPath: "assets/default_env_ibl.ktx",
|
||||
transformToUnitCube: true,
|
||||
initialCameraPosition: Vector3(0, 0, 6),
|
||||
background: Colors.grey[200],
|
||||
manipulatorType: ManipulatorType.ORBIT,
|
||||
initial: const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,142 +0,0 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:thermion_flutter/thermion_flutter.dart';
|
||||
// import 'package:thermion_dart/src/viewer/src/thermion_viewer_base.dart';
|
||||
|
||||
class CupPage1 extends StatelessWidget {
|
||||
const CupPage1({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Stack(children: [
|
||||
Positioned.fill(
|
||||
child: ViewerWidget(
|
||||
assetPath: "assets/cup/model.gltf",
|
||||
skyboxPath: "assets/default_env_skybox.ktx",
|
||||
iblPath: "assets/default_env_ibl.ktx",
|
||||
transformToUnitCube: true,
|
||||
initialCameraPosition: Vector3(0, 0, 6),
|
||||
background: Colors.blue,
|
||||
manipulatorType: ManipulatorType.ORBIT,
|
||||
onViewerAvailable: (viewer) async {
|
||||
await Future.delayed(const Duration(seconds: 5));
|
||||
await viewer.removeSkybox();
|
||||
},
|
||||
initial: Container(
|
||||
color: Colors.grey,
|
||||
),
|
||||
))
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
||||
class CupPage extends StatefulWidget {
|
||||
const CupPage({super.key});
|
||||
|
||||
@override
|
||||
State<CupPage> createState() => _CupPageState();
|
||||
}
|
||||
|
||||
class _CupPageState extends State<CupPage> {
|
||||
bool _isLoading = true;
|
||||
String? _modelPath, modelUri;
|
||||
String _statusMessage = "正在加载本地模型...";
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_loadLocalModel();
|
||||
}
|
||||
|
||||
// 从应用支持目录加载模型
|
||||
Future<void> _loadLocalModel() async {
|
||||
try {
|
||||
setState(() {
|
||||
_statusMessage = "获取本地模型路径...";
|
||||
});
|
||||
|
||||
final supportDir = await getApplicationSupportDirectory();
|
||||
final modelFile = File(p.join(supportDir.path, 'cup', 'model.gltf'));
|
||||
|
||||
String modelPath =
|
||||
File(p.join(supportDir.path, 'cup', 'model.gltf')).absolute.path;
|
||||
final cupDir = Directory('${supportDir.path}/cup');
|
||||
final modelUri = File('${cupDir.path}/model.gltf').uri;
|
||||
print('加载本地模modelPath: $modelPath');
|
||||
print('加载本地模modelUri: $modelUri');
|
||||
|
||||
if (await modelFile.exists()) {
|
||||
setState(() {
|
||||
_modelPath = modelPath;
|
||||
|
||||
_isLoading = false;
|
||||
_statusMessage = "本地模型加载完成";
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
_statusMessage = "本地模型文件不存在";
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
print('加载本地模型失败: $e');
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
_statusMessage = "加载失败: $e";
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('本地模型查看'),
|
||||
),
|
||||
body: _isLoading
|
||||
? Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const CircularProgressIndicator(),
|
||||
const SizedBox(height: 16),
|
||||
Text(_statusMessage),
|
||||
],
|
||||
),
|
||||
)
|
||||
: _modelPath == null
|
||||
? Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(Icons.error, size: 48, color: Colors.red),
|
||||
const SizedBox(height: 16),
|
||||
Text(_statusMessage),
|
||||
const SizedBox(height: 16),
|
||||
ElevatedButton(
|
||||
onPressed: _loadLocalModel,
|
||||
child: const Text('重试'),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: ViewerWidget(
|
||||
assetPath: "file://$_modelPath",
|
||||
// assetPath: modelUri,
|
||||
skyboxPath: "assets/default_env_skybox.ktx",
|
||||
iblPath: "assets/default_env_ibl.ktx",
|
||||
transformToUnitCube: true,
|
||||
initialCameraPosition: Vector3(0, 0, 6),
|
||||
background: Colors.grey[200],
|
||||
manipulatorType: ManipulatorType.ORBIT,
|
||||
initial: const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,570 +0,0 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:animations/utils/binary_manager.dart';
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
import 'cup.dart';
|
||||
|
||||
Future<void> main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
// 初始化3D模型资源
|
||||
try {
|
||||
await BinaryManager.initializeAppResources();
|
||||
print('3D模型资源初始化成功');
|
||||
} catch (e) {
|
||||
print('无法初始化3D模型资源: $e');
|
||||
}
|
||||
|
||||
runApp(const MyApp());
|
||||
}
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
const MyApp({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
title: '3D模型纹理替换',
|
||||
theme: ThemeData(
|
||||
primarySwatch: Colors.blue,
|
||||
visualDensity: VisualDensity.adaptivePlatformDensity,
|
||||
),
|
||||
home: ModelViewerWithTextureReplace(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ModelViewerWithTextureReplace extends StatefulWidget {
|
||||
const ModelViewerWithTextureReplace({super.key});
|
||||
|
||||
@override
|
||||
State<ModelViewerWithTextureReplace> createState() =>
|
||||
_ModelViewerWithTextureReplaceState();
|
||||
}
|
||||
|
||||
class _ModelViewerWithTextureReplaceState
|
||||
extends State<ModelViewerWithTextureReplace> {
|
||||
bool _isLoading = true;
|
||||
String? _modelPath;
|
||||
String? _texturePath;
|
||||
int _keyValue = 0;
|
||||
String _statusMessage = "正在加载模型...";
|
||||
bool _isReplacingTexture = false;
|
||||
File? _selectedImage;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_load3DModels();
|
||||
// _loadModel();
|
||||
}
|
||||
|
||||
// 加载3D模型文件
|
||||
Future<void> _load3DModels() async {
|
||||
try {
|
||||
setState(() {
|
||||
_statusMessage = "获取模型路径...";
|
||||
});
|
||||
|
||||
// 使用BinaryManager获取3D模型文件路径
|
||||
// final supportDir = await getApplicationSupportDirectory();
|
||||
// final cupDir = Directory('${supportDir.path}/cup');
|
||||
// final modelFile = File('${cupDir.path}/model.gltf');
|
||||
|
||||
final modelPath = await BinaryManager.get3DModelPath("model.gltf");
|
||||
|
||||
final texturePath = await BinaryManager.get3DModelPath("texture.jpg");
|
||||
|
||||
// print("路径: $modelPath");
|
||||
// print("文件是否存在: ${await File(modelPath).exists()}");
|
||||
// print("文件路径: ${await File(modelPath).uri}");
|
||||
//
|
||||
// setState(() {
|
||||
// _modelPath = File(modelPath).uri.toString(); // 确保是本地路径
|
||||
// });
|
||||
|
||||
// if (!await File(modelPath).exists()) {
|
||||
// print("❌ 模型文件不存在: $modelPath");
|
||||
// }
|
||||
// if (!await File(texturePath).exists()) {
|
||||
// print("❌ 纹理文件不存在: $texturePath");
|
||||
// }
|
||||
print('modelPath=${modelPath}\ntexturePath=${texturePath}');
|
||||
setState(() {
|
||||
_modelPath = modelPath;
|
||||
_texturePath = texturePath;
|
||||
_isLoading = false;
|
||||
_statusMessage = "加载完成";
|
||||
});
|
||||
} catch (e) {
|
||||
print('加载3D模型失败: $e');
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
_statusMessage = "加载失败: $e";
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 使用FilePicker选择新纹理
|
||||
Future<void> _pickNewTexture() async {
|
||||
if (_isReplacingTexture || _texturePath == null) return;
|
||||
|
||||
setState(() {
|
||||
_isReplacingTexture = true;
|
||||
_statusMessage = "正在选择纹理文件...";
|
||||
});
|
||||
|
||||
try {
|
||||
// 选择图片文件
|
||||
FilePickerResult? result = await FilePicker.platform.pickFiles(
|
||||
type: FileType.image,
|
||||
allowMultiple: false,
|
||||
);
|
||||
|
||||
if (result == null ||
|
||||
result.files.isEmpty ||
|
||||
result.files.single.path == null) {
|
||||
setState(() {
|
||||
_statusMessage = "取消选择";
|
||||
});
|
||||
return;
|
||||
}
|
||||
_selectedImage = File(result.files.single.path!);
|
||||
|
||||
final selectedFile = result.files.single;
|
||||
final fileExtension = p.extension(selectedFile.path!).toLowerCase();
|
||||
|
||||
// 可选:仅允许特定图片格式
|
||||
if (!['.jpg', '.jpeg', '.png'].contains(fileExtension)) {
|
||||
setState(() {
|
||||
_statusMessage = "仅支持 JPG / PNG 格式纹理";
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
final newTexture = File(selectedFile.path!);
|
||||
final supportDir = await getApplicationSupportDirectory();
|
||||
final modelDir = p.join(supportDir.path, 'cup');
|
||||
final modelPath = p.join(modelDir, 'model.gltf');
|
||||
final modelFile = File(modelPath);
|
||||
|
||||
if (!await newTexture.exists()) {
|
||||
setState(() {
|
||||
_statusMessage = "所选纹理文件不存在";
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 复制新纹理为固定名 new.jpg 到模型目录
|
||||
final newTexturePath = p.join(modelDir, 'new.jpg');
|
||||
await newTexture.copy(newTexturePath);
|
||||
_texturePath = newTexturePath;
|
||||
|
||||
// 修改 GLTF 文件
|
||||
if (await modelFile.exists()) {
|
||||
String gltfContent = await modelFile.readAsString();
|
||||
|
||||
// ✅ 修复 GLTF 中非法负号格式(例如 "- 0.123" => "-0.123")
|
||||
gltfContent = gltfContent.replaceAllMapped(
|
||||
RegExp(r'-\s+(\d+(\.\d+)?)'),
|
||||
(match) => '-${match.group(1)}',
|
||||
);
|
||||
|
||||
final gltfJson = jsonDecode(gltfContent);
|
||||
|
||||
// 安全修改 images[0].uri
|
||||
if (gltfJson['images'] != null && gltfJson['images'].isNotEmpty) {
|
||||
gltfJson['images'][0]['uri'] = './new.jpg';
|
||||
}
|
||||
|
||||
// 可选:修改 textures[0].name
|
||||
if (gltfJson['textures'] != null && gltfJson['textures'].isNotEmpty) {
|
||||
gltfJson['textures'][0]['name'] = 'new.jpg';
|
||||
}
|
||||
|
||||
// 写回更新后的内容
|
||||
final updatedContent =
|
||||
const JsonEncoder.withIndent(' ').convert(gltfJson);
|
||||
await modelFile.writeAsString(updatedContent);
|
||||
|
||||
print('GLTF文件已成功更新');
|
||||
|
||||
// 重建模型视图
|
||||
setState(() {
|
||||
_keyValue++;
|
||||
_statusMessage = "纹理已更新为 new.jpg";
|
||||
});
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('纹理已成功更新为 new.jpg')),
|
||||
);
|
||||
} else {
|
||||
print('GLTF文件不存在: $modelPath');
|
||||
setState(() {
|
||||
_statusMessage = "GLTF文件不存在";
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
print('更换纹理失败: $e');
|
||||
setState(() {
|
||||
_statusMessage = "更换纹理失败: $e";
|
||||
});
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('更换纹理失败: $e')),
|
||||
);
|
||||
} finally {
|
||||
setState(() {
|
||||
_isReplacingTexture = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 重置纹理到原始状态
|
||||
Future<void> _resetTexture() async {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => Cup(),
|
||||
// builder: (context) => CupPage(),
|
||||
),
|
||||
);
|
||||
return;
|
||||
|
||||
if (_isReplacingTexture || _texturePath == null) return;
|
||||
|
||||
setState(() {
|
||||
_isReplacingTexture = true;
|
||||
_statusMessage = "正在重置纹理...";
|
||||
});
|
||||
|
||||
try {
|
||||
// 检查备份文件是否存在
|
||||
final backupTexturePath = '${_texturePath!}.backup';
|
||||
final backupFile = File(backupTexturePath);
|
||||
|
||||
if (await backupFile.exists()) {
|
||||
// 恢复备份文件
|
||||
await backupFile.copy(_texturePath!);
|
||||
|
||||
// 给渲染器一点时间来处理文件变化
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
|
||||
// 强制重建ViewerWidget以应用恢复的纹理
|
||||
setState(() {
|
||||
_keyValue++;
|
||||
_statusMessage = "纹理已重置";
|
||||
});
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('纹理已重置到原始状态')),
|
||||
);
|
||||
} else {
|
||||
setState(() {
|
||||
_statusMessage = "没有备份文件可恢复";
|
||||
});
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('没有备份文件可恢复')),
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
print('重置纹理失败: $e');
|
||||
setState(() {
|
||||
_statusMessage = "重置纹理失败: $e";
|
||||
});
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('重置纹理失败: $e')),
|
||||
);
|
||||
} finally {
|
||||
setState(() {
|
||||
_isReplacingTexture = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('3D模型纹理替换'),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.texture),
|
||||
onPressed: _isReplacingTexture ? null : _pickNewTexture,
|
||||
tooltip: '更换纹理',
|
||||
),
|
||||
],
|
||||
),
|
||||
body: _isLoading
|
||||
? Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const CircularProgressIndicator(),
|
||||
const SizedBox(height: 16),
|
||||
Text(_statusMessage),
|
||||
],
|
||||
),
|
||||
)
|
||||
: _modelPath == null
|
||||
? Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(Icons.error, size: 48, color: Colors.red),
|
||||
const SizedBox(height: 16),
|
||||
const Text('加载模型失败'),
|
||||
const SizedBox(height: 16),
|
||||
ElevatedButton(
|
||||
onPressed: _load3DModels,
|
||||
child: const Text('重试'),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: Column(
|
||||
children: [
|
||||
if (_selectedImage != null)
|
||||
Container(
|
||||
width: 300,
|
||||
height: 300,
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.blue, width: 2),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
child: Image.file(
|
||||
_selectedImage!,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
),
|
||||
// Expanded(
|
||||
// child: ViewerWidget(
|
||||
// key: ValueKey(_keyValue),
|
||||
// assetPath: "file://$_modelPath",
|
||||
// skyboxPath: "assets/default_env_skybox.ktx",
|
||||
// iblPath: "assets/default_env_ibl.ktx",
|
||||
// transformToUnitCube: true,
|
||||
// initialCameraPosition: Vector3(0, 0, 6),
|
||||
// background: Colors.grey[200],
|
||||
// manipulatorType: ManipulatorType.ORBIT,
|
||||
// initial: const Center(
|
||||
// child: CircularProgressIndicator(),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
color: Colors.grey[100],
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
ElevatedButton.icon(
|
||||
icon: const Icon(Icons.texture),
|
||||
label: const Text('选择纹理图片'),
|
||||
onPressed: _isReplacingTexture
|
||||
? null
|
||||
: _pickNewTexture,
|
||||
),
|
||||
ElevatedButton.icon(
|
||||
icon: const Icon(Icons.refresh),
|
||||
label: const Text('3d查看'),
|
||||
onPressed:
|
||||
_isReplacingTexture ? null : _resetTexture,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
_statusMessage,
|
||||
style: TextStyle(
|
||||
color: Colors.grey[600],
|
||||
fontStyle: FontStyle.italic,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
/*
|
||||
import 'dart:async';
|
||||
import 'package:animations/cup_page.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:flutter/material.dart' hide View;
|
||||
import 'package:thermion_flutter/thermion_flutter.dart';
|
||||
|
||||
void main() {
|
||||
runApp(const MyApp());
|
||||
Logger.root.onRecord.listen((record) {
|
||||
print(record);
|
||||
});
|
||||
}
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
const MyApp({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
title: 'Thermion Animation Demo',
|
||||
theme: ThemeData(
|
||||
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
|
||||
useMaterial3: true,
|
||||
),
|
||||
home: const CupPage(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class MyHomePage extends StatefulWidget {
|
||||
const MyHomePage({super.key, required this.title});
|
||||
final String title;
|
||||
|
||||
@override
|
||||
State<MyHomePage> createState() => _MyHomePageState();
|
||||
}
|
||||
|
||||
class _MyHomePageState extends State<MyHomePage> {
|
||||
late DelegateInputHandler _inputHandler;
|
||||
ThermionViewer? _thermionViewer;
|
||||
|
||||
ThermionAsset? _asset;
|
||||
final _droneUri = "assets/cup/model.gltf";
|
||||
final _cubeUri = "assets/cube_with_morph_targets.glb";
|
||||
String? _loaded;
|
||||
|
||||
final gltfAnimations = <String>[];
|
||||
int selectedGltfAnimation = -1;
|
||||
|
||||
Future _load(String? uri) async {
|
||||
if (_asset != null) {
|
||||
await _thermionViewer!.destroyAsset(_asset!);
|
||||
_asset = null;
|
||||
}
|
||||
|
||||
_loaded = uri;
|
||||
if (uri != null) {
|
||||
_asset = await _thermionViewer!.loadGltf(uri);
|
||||
await _asset!.transformToUnitCube();
|
||||
final animations = await _asset!.getGltfAnimationNames();
|
||||
final durations = await Future.wait(List.generate(
|
||||
animations.length, (i) => _asset!.getGltfAnimationDuration(i)));
|
||||
|
||||
final labels = animations
|
||||
.asMap()
|
||||
.map((index, animation) =>
|
||||
MapEntry(index, "$animation (${durations[index]}s"))
|
||||
.values;
|
||||
gltfAnimations.clear();
|
||||
gltfAnimations.addAll(labels);
|
||||
selectedGltfAnimation = 0;
|
||||
}
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
Future _playGltfAnimation() async {
|
||||
if (selectedGltfAnimation == -1) {
|
||||
throw Exception();
|
||||
}
|
||||
await _asset!.playGltfAnimation(selectedGltfAnimation);
|
||||
}
|
||||
|
||||
Future _stopGltfAnimation() async {
|
||||
if (selectedGltfAnimation == -1) {
|
||||
throw Exception();
|
||||
}
|
||||
await _asset!.stopGltfAnimation(selectedGltfAnimation);
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
_thermionViewer = await ThermionFlutterPlugin.createViewer();
|
||||
|
||||
final camera = await _thermionViewer!.getActiveCamera();
|
||||
await camera.lookAt(Vector3(0, 0, 10));
|
||||
|
||||
await _thermionViewer!.loadSkybox("assets/default_env_skybox.ktx");
|
||||
await _thermionViewer!.loadIbl("assets/default_env_ibl.ktx");
|
||||
await _thermionViewer!.setPostProcessing(true);
|
||||
await _thermionViewer!.setRendering(true);
|
||||
|
||||
_inputHandler = DelegateInputHandler.fixedOrbit(_thermionViewer!);
|
||||
await _load(_droneUri);
|
||||
|
||||
setState(() {});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (_thermionViewer == null) {
|
||||
return Container();
|
||||
}
|
||||
return Stack(children: [
|
||||
Positioned.fill(
|
||||
child: ThermionListenerWidget(
|
||||
inputHandler: _inputHandler,
|
||||
child: ThermionWidget(
|
||||
viewer: _thermionViewer!,
|
||||
))),
|
||||
Card(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
|
||||
child: Row(children: [
|
||||
const Text("Asset: "),
|
||||
DropdownButton<String?>(
|
||||
value: _loaded,
|
||||
items: [_droneUri, _cubeUri, null]
|
||||
.map((uri) => DropdownMenuItem<String?>(
|
||||
value: uri,
|
||||
child: Text(
|
||||
uri ?? "None",
|
||||
style: const TextStyle(fontSize: 12),
|
||||
)))
|
||||
.toList(),
|
||||
onChanged: _load),
|
||||
const Text("Animation: "),
|
||||
DropdownButton<String>(
|
||||
value: selectedGltfAnimation == -1
|
||||
? null
|
||||
: gltfAnimations[selectedGltfAnimation],
|
||||
items: gltfAnimations
|
||||
.map((animation) => DropdownMenuItem<String>(
|
||||
value: animation,
|
||||
child: Text(
|
||||
animation,
|
||||
style: const TextStyle(fontSize: 12),
|
||||
)))
|
||||
.toList(),
|
||||
onChanged: (value) {
|
||||
if (value == null) {
|
||||
selectedGltfAnimation = -1;
|
||||
} else {
|
||||
selectedGltfAnimation = gltfAnimations.indexOf(value);
|
||||
}
|
||||
}),
|
||||
IconButton(
|
||||
onPressed: _playGltfAnimation,
|
||||
icon: const Icon(Icons.play_arrow)),
|
||||
IconButton(
|
||||
onPressed: _stopGltfAnimation, icon: const Icon(Icons.stop))
|
||||
]))),
|
||||
]);
|
||||
}
|
||||
}
|
||||
*/
|
||||
@@ -1,284 +0,0 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:thermion_flutter/thermion_flutter.dart';
|
||||
|
||||
void main() {
|
||||
runApp(const MyApp());
|
||||
}
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
const MyApp({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
title: '3D模型纹理替换',
|
||||
theme: ThemeData(
|
||||
primarySwatch: Colors.blue,
|
||||
visualDensity: VisualDensity.adaptivePlatformDensity,
|
||||
),
|
||||
home: const ModelViewerScreen(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ModelViewerScreen extends StatefulWidget {
|
||||
const ModelViewerScreen({super.key});
|
||||
|
||||
@override
|
||||
State<ModelViewerScreen> createState() => _ModelViewerScreenState();
|
||||
}
|
||||
|
||||
class _ModelViewerScreenState extends State<ModelViewerScreen> {
|
||||
bool _isLoading = true;
|
||||
String? _modelPath;
|
||||
String? _texturePath;
|
||||
int _keyValue = 0;
|
||||
String _statusMessage = "正在加载模型...";
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_loadModel();
|
||||
}
|
||||
|
||||
// 加载模型文件到临时目录
|
||||
Future<void> _loadModel() async {
|
||||
try {
|
||||
setState(() {
|
||||
_statusMessage = "准备模型目录...";
|
||||
});
|
||||
|
||||
final directory = await getApplicationDocumentsDirectory();
|
||||
final modelDir = Directory('${directory.path}/model');
|
||||
|
||||
// 确保目录存在
|
||||
if (!await modelDir.exists()) {
|
||||
await modelDir.create(recursive: true);
|
||||
}
|
||||
|
||||
setState(() {
|
||||
_statusMessage = "加载GLTF文件...";
|
||||
});
|
||||
|
||||
// 加载 .gltf 文件并写入本地
|
||||
final gltfData =
|
||||
await DefaultAssetBundle.of(context).load('assets/cup/model.gltf');
|
||||
final gltfFile = File('${modelDir.path}/model.gltf');
|
||||
await gltfFile.writeAsBytes(gltfData.buffer.asUint8List());
|
||||
|
||||
/// ✅ 打印本地路径(关键)
|
||||
print('✅ GLTF 本地路径: ${gltfFile.path}');
|
||||
print('✅ 是否存在: ${await gltfFile.exists()}');
|
||||
|
||||
setState(() {
|
||||
_statusMessage = "加载模型数据...";
|
||||
});
|
||||
|
||||
// 加载 .bin 文件并写入本地
|
||||
final binData =
|
||||
await DefaultAssetBundle.of(context).load('assets/cup/model.bin');
|
||||
final binFile = File('${modelDir.path}/model.bin');
|
||||
await binFile.writeAsBytes(binData.buffer.asUint8List());
|
||||
|
||||
setState(() {
|
||||
_statusMessage = "加载纹理...";
|
||||
});
|
||||
|
||||
// 加载纹理文件并写入本地
|
||||
final textureData =
|
||||
await DefaultAssetBundle.of(context).load('assets/cup/texture.jpg');
|
||||
final textureFile = File('${modelDir.path}/texture.jpg');
|
||||
await textureFile.writeAsBytes(textureData.buffer.asUint8List());
|
||||
|
||||
/// ✅ 打印纹理路径
|
||||
print('✅ 纹理本地路径: ${textureFile.path}');
|
||||
print('✅ 是否存在: ${await textureFile.exists()}');
|
||||
|
||||
setState(() {
|
||||
_modelPath = gltfFile.path;
|
||||
_texturePath = textureFile.path;
|
||||
_isLoading = false;
|
||||
_statusMessage = "加载完成";
|
||||
});
|
||||
} catch (e) {
|
||||
print('❌ 加载模型失败: $e');
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
_statusMessage = "加载失败: $e";
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 使用FilePicker选择新纹理 - 修复配置错误
|
||||
Future<void> _pickNewTexture() async {
|
||||
try {
|
||||
setState(() {
|
||||
_statusMessage = "正在选择纹理文件...";
|
||||
});
|
||||
|
||||
// 使用FilePicker选择文件 - 修复配置
|
||||
// 选项1: 使用FileType.image(不能指定allowedExtensions)
|
||||
FilePickerResult? result = await FilePicker.platform.pickFiles(
|
||||
type: FileType.image,
|
||||
allowMultiple: false,
|
||||
);
|
||||
|
||||
// 选项2: 如果需要特定扩展名,使用FileType.custom
|
||||
/*
|
||||
FilePickerResult? result = await FilePicker.platform.pickFiles(
|
||||
type: FileType.custom,
|
||||
allowMultiple: false,
|
||||
allowedExtensions: ['jpg', 'jpeg', 'png', 'bmp', 'tga'],
|
||||
);
|
||||
*/
|
||||
|
||||
if (result != null &&
|
||||
result.files.isNotEmpty &&
|
||||
result.files.single.path != null &&
|
||||
_texturePath != null) {
|
||||
setState(() {
|
||||
_statusMessage = "正在应用新纹理...";
|
||||
});
|
||||
|
||||
// 获取选中的文件
|
||||
PlatformFile file = result.files.first;
|
||||
File newTexture = File(file.path!);
|
||||
|
||||
// 检查文件是否存在
|
||||
if (await newTexture.exists()) {
|
||||
// 复制选中的图片到纹理路径
|
||||
await newTexture.copy(_texturePath!);
|
||||
|
||||
// 强制重建ViewerWidget以应用新纹理
|
||||
setState(() {
|
||||
_keyValue++;
|
||||
_statusMessage = "纹理已更新";
|
||||
});
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('纹理已成功更新')),
|
||||
);
|
||||
} else {
|
||||
setState(() {
|
||||
_statusMessage = "文件不存在";
|
||||
});
|
||||
}
|
||||
} else {
|
||||
setState(() {
|
||||
_statusMessage = "取消选择";
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
print('更换纹理失败: $e');
|
||||
setState(() {
|
||||
_statusMessage = "更换纹理失败";
|
||||
});
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('更换纹理失败: $e')),
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('3D模型纹理替换'),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.texture),
|
||||
onPressed: _pickNewTexture,
|
||||
tooltip: '更换纹理',
|
||||
),
|
||||
],
|
||||
),
|
||||
body: _isLoading
|
||||
? Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const CircularProgressIndicator(),
|
||||
const SizedBox(height: 16),
|
||||
Text(_statusMessage),
|
||||
],
|
||||
),
|
||||
)
|
||||
: _modelPath == null
|
||||
? Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(Icons.error, size: 48, color: Colors.red),
|
||||
const SizedBox(height: 16),
|
||||
const Text('加载模型失败'),
|
||||
const SizedBox(height: 16),
|
||||
ElevatedButton(
|
||||
onPressed: _loadModel,
|
||||
child: const Text('重试'),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: ViewerWidget(
|
||||
key: ValueKey(_keyValue),
|
||||
assetPath: _modelPath!,
|
||||
skyboxPath: "assets/default_env_skybox.ktx",
|
||||
iblPath: "assets/default_env_ibl.ktx",
|
||||
transformToUnitCube: true,
|
||||
initialCameraPosition: Vector3(0, 0, 6),
|
||||
background: Colors.grey[200],
|
||||
manipulatorType: ManipulatorType.ORBIT,
|
||||
initial: const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
color: Colors.grey[100],
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
ElevatedButton.icon(
|
||||
icon: const Icon(Icons.texture),
|
||||
label: const Text('选择纹理图片'),
|
||||
onPressed: _pickNewTexture,
|
||||
),
|
||||
ElevatedButton.icon(
|
||||
icon: const Icon(Icons.refresh),
|
||||
label: const Text('重置视图'),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_keyValue++;
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
_statusMessage,
|
||||
style: TextStyle(
|
||||
color: Colors.grey[600],
|
||||
fontStyle: FontStyle.italic,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,190 +0,0 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:thermion_flutter/thermion_flutter.dart';
|
||||
|
||||
class LocalModelViewer extends StatefulWidget {
|
||||
@override
|
||||
_LocalModelViewerState createState() => _LocalModelViewerState();
|
||||
}
|
||||
|
||||
class _LocalModelViewerState extends State<LocalModelViewer> {
|
||||
ThermionViewer? _viewer;
|
||||
ThermionAsset? _asset;
|
||||
bool _isLoading = true;
|
||||
bool _hasError = false;
|
||||
String _statusMessage = "初始化中...";
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
ThermionFlutterPlugin.createViewer().then((viewer) async {
|
||||
_viewer = viewer;
|
||||
_loadLocalModel(); // 在 viewer 初始化之后再加载模型
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _loadLocalModel() async {
|
||||
try {
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
_statusMessage = "获取本地模型路径...";
|
||||
});
|
||||
|
||||
final supportDir = await getApplicationSupportDirectory();
|
||||
final modelDir = p.join(supportDir.path, 'cup');
|
||||
final modelPath = p.join(modelDir, 'model.gltf');
|
||||
final modelFile = File(modelPath);
|
||||
|
||||
if (await modelFile.exists()) {
|
||||
// 检查二进制文件
|
||||
final binPath = p.join(modelDir, 'model.bin');
|
||||
final binFile = File(binPath);
|
||||
if (!await binFile.exists()) {
|
||||
throw Exception("二进制文件不存在: $binPath");
|
||||
}
|
||||
|
||||
// 检查文件大小
|
||||
final binSize = await binFile.length();
|
||||
if (binSize == 0) {
|
||||
throw Exception("二进制文件为空");
|
||||
}
|
||||
|
||||
// 检查纹理文件
|
||||
final texturePath = p.join(modelDir, 'texture.jpg');
|
||||
final textureFile = File(texturePath);
|
||||
if (!await textureFile.exists()) {
|
||||
throw Exception("纹理文件不存在: $texturePath");
|
||||
}
|
||||
|
||||
setState(() {
|
||||
_statusMessage = "读取和修改模型数据...";
|
||||
});
|
||||
|
||||
// 读取GLTF文件内容
|
||||
String gltfContent = await modelFile.readAsString();
|
||||
|
||||
// 修改纹理路径(去掉"./"前缀)
|
||||
gltfContent = gltfContent.replaceAll('"./texture.jpg"', '"new.jpg"');
|
||||
|
||||
// 转换为字节数组
|
||||
Uint8List gltfBytes = Uint8List.fromList(utf8.encode(gltfContent));
|
||||
|
||||
// 使用绝对路径作为资源URI
|
||||
final resourceUri = "file://${Directory(modelDir).absolute.path}";
|
||||
|
||||
setState(() {
|
||||
_statusMessage = "加载模型中...";
|
||||
});
|
||||
|
||||
final asset = await _viewer?.loadGltfFromBuffer(
|
||||
gltfBytes,
|
||||
resourceUri: resourceUri,
|
||||
addToScene: true,
|
||||
);
|
||||
|
||||
setState(() {
|
||||
_asset = asset;
|
||||
_isLoading = false;
|
||||
_statusMessage = "模型加载完成";
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
_statusMessage = "本地模型文件不存在";
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
print('加载本地模型失败: $e');
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
_hasError = true;
|
||||
_statusMessage = "加载失败: $e";
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (_isLoading) {
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
CircularProgressIndicator(),
|
||||
SizedBox(height: 16),
|
||||
Text(_statusMessage),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if (_hasError || _viewer == null) {
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(Icons.error_outline, color: Colors.red, size: 48),
|
||||
SizedBox(height: 16),
|
||||
Text("加载3D模型失败"),
|
||||
Text(_statusMessage, style: TextStyle(color: Colors.red)),
|
||||
SizedBox(height: 16),
|
||||
ElevatedButton(
|
||||
onPressed: _loadLocalModel,
|
||||
child: Text("重试"),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('本地模型查看'),
|
||||
),
|
||||
body: ThermionListenerWidget(
|
||||
inputHandler: DelegateInputHandler.fixedOrbit(_viewer!),
|
||||
child: ThermionWidget(
|
||||
viewer: _viewer!,
|
||||
showFpsCounter: true, // 可选:显示FPS计数器
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// 使用ThermionWidget显示3D内容
|
||||
return ThermionListenerWidget(
|
||||
inputHandler: DelegateInputHandler.fixedOrbit(_viewer!),
|
||||
child: ThermionWidget(
|
||||
viewer: _viewer!,
|
||||
showFpsCounter: true, // 可选:显示FPS计数器
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> deleteModelFile() async {
|
||||
// 获取应用支持目录
|
||||
final supportDir = await getApplicationSupportDirectory();
|
||||
|
||||
// 构建 model.gltf 的完整路径
|
||||
final modelFile = File(p.join(supportDir.path, 'cup', 'model.gltf'));
|
||||
|
||||
// 检查文件是否存在,然后删除
|
||||
if (await modelFile.exists()) {
|
||||
await modelFile.delete();
|
||||
print('model.gltf 已删除');
|
||||
} else {
|
||||
print('model.gltf 文件不存在');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// deleteModelFile();
|
||||
// 清理资源
|
||||
_viewer?.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
@@ -1,405 +0,0 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
class BinaryManager {
|
||||
/// 当前应用版本(用于初始化检查)
|
||||
static String? _currentVersion;
|
||||
|
||||
/// 获取当前应用版本
|
||||
static Future<String> _getCurrentVersion() async {
|
||||
if (_currentVersion == null) {
|
||||
final packageInfo = await PackageInfo.fromPlatform();
|
||||
_currentVersion = '${packageInfo.version}+${packageInfo.buildNumber}';
|
||||
}
|
||||
return _currentVersion!;
|
||||
}
|
||||
|
||||
/// 检查是否已完成初始化(基于版本号)
|
||||
static Future<bool> isInitialized() async {
|
||||
final supportDir = await getApplicationSupportDirectory();
|
||||
final currentVersion = await _getCurrentVersion();
|
||||
final initMarker = File(
|
||||
p.join(supportDir.path, '.initialized_$currentVersion'),
|
||||
);
|
||||
|
||||
return await initMarker.exists();
|
||||
}
|
||||
|
||||
/// 标记初始化完成(文件名包含版本号)
|
||||
static Future<void> markInitialized() async {
|
||||
final supportDir = await getApplicationSupportDirectory();
|
||||
final currentVersion = await _getCurrentVersion();
|
||||
final initMarker = File(
|
||||
p.join(supportDir.path, '.initialized_$currentVersion'),
|
||||
);
|
||||
await initMarker.writeAsString('${DateTime.now().toIso8601String()}\n');
|
||||
}
|
||||
|
||||
/// 从assets目录提取文件到指定路径
|
||||
static Future<void> _extractAsset(String assetPath, String localPath) async {
|
||||
final localFile = File(localPath);
|
||||
|
||||
try {
|
||||
// 从assets中读取数据
|
||||
final ByteData data = await rootBundle.load(assetPath);
|
||||
final List<int> bytes = data.buffer.asUint8List();
|
||||
|
||||
// 确保目录存在
|
||||
final dir = Directory(p.dirname(localPath));
|
||||
if (!await dir.exists()) {
|
||||
await dir.create(recursive: true);
|
||||
}
|
||||
|
||||
// 写入本地文件
|
||||
await localFile.writeAsBytes(bytes);
|
||||
print('成功提取文件: $assetPath -> $localPath');
|
||||
} catch (e) {
|
||||
print('提取资源文件失败 $assetPath: $e');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
/// 初始化应用程序资源 - 将所有必要的assets迁移到系统文件夹
|
||||
static Future<void> initializeAppResources() async {
|
||||
final currentVersion = await _getCurrentVersion();
|
||||
|
||||
if (await isInitialized()) {
|
||||
print('应用程序资源已初始化,当前版本: $currentVersion');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 迁移shell脚本
|
||||
await _migrateShellScript();
|
||||
|
||||
// 迁移二进制文件
|
||||
await _migrateBinaries();
|
||||
|
||||
// 迁移模型文件
|
||||
await _migrateModels();
|
||||
|
||||
// 迁移3D模型文件
|
||||
await migrate3DModels();
|
||||
|
||||
// 标记初始化完成
|
||||
await markInitialized();
|
||||
|
||||
print('应用程序资源初始化完成');
|
||||
} catch (e) {
|
||||
print('应用程序资源初始化失败: $e');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
/// 迁移3D模型文件
|
||||
static Future<void> migrate3DModels() async {
|
||||
print('开始迁移3D模型文件...');
|
||||
|
||||
final supportDir = await getApplicationSupportDirectory();
|
||||
final models3dDir = Directory(p.join(supportDir.path, 'cup'));
|
||||
|
||||
// 创建3D模型目录
|
||||
if (!await models3dDir.exists()) {
|
||||
await models3dDir.create(recursive: true);
|
||||
}
|
||||
|
||||
// 3D模型文件列表
|
||||
final model3dFiles = ['model.gltf', 'model.bin', 'texture.jpg'];
|
||||
|
||||
// 迁移所有3D模型文件
|
||||
for (final modelFile in model3dFiles) {
|
||||
try {
|
||||
// if (modelFile == 'model.gltf') {
|
||||
// // 对于GLTF文件,我们需要修改内容
|
||||
// await _extractAndModifyGltfAsset(
|
||||
// 'assets/cup/$modelFile',
|
||||
// p.join(models3dDir.path, modelFile),
|
||||
// );
|
||||
// } else {
|
||||
// 对于其他文件,直接复制
|
||||
await _extractAsset(
|
||||
'assets/cup/$modelFile',
|
||||
p.join(models3dDir.path, modelFile),
|
||||
);
|
||||
// }
|
||||
} catch (e) {
|
||||
print('迁移3D模型文件失败 $modelFile: $e');
|
||||
// 继续迁移其他模型文件
|
||||
}
|
||||
}
|
||||
|
||||
print('3D模型文件迁移完成');
|
||||
}
|
||||
|
||||
static Future<void> _extractAndModifyGltfAsset(
|
||||
String assetPath, String targetPath) async {
|
||||
try {
|
||||
// 读取资源文件内容
|
||||
final byteData = await rootBundle.load(assetPath);
|
||||
final buffer = byteData.buffer;
|
||||
final gltfContent = utf8.decode(
|
||||
buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
|
||||
|
||||
// 修改纹理路径(去掉"./"前缀)
|
||||
final modifiedGltfContent =
|
||||
gltfContent.replaceAll('"./texture.jpg"', '"texture.jpg"');
|
||||
|
||||
// 写入修改后的内容到目标文件
|
||||
final file = File(targetPath);
|
||||
await file.writeAsBytes(utf8.encode(modifiedGltfContent));
|
||||
|
||||
print('已修改并迁移: $assetPath -> $targetPath');
|
||||
} catch (e) {
|
||||
print('提取并修改GLTF资源失败: $e');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
static Future<void> _migrateShellScript() async {
|
||||
print('开始迁移脚本文件...');
|
||||
|
||||
final supportDir = await getApplicationSupportDirectory();
|
||||
|
||||
// 迁移 Shell 脚本 (macOS/Linux)
|
||||
final shellScriptPath = p.join(supportDir.path, 'upscale_to_8k_single.sh');
|
||||
await _extractAsset('assets/upscale_to_8k_single.sh', shellScriptPath);
|
||||
|
||||
// 设置脚本执行权限(仅限 macOS/Linux)
|
||||
if (Platform.isMacOS || Platform.isLinux) {
|
||||
try {
|
||||
final result = await Process.run('chmod', ['+x', shellScriptPath]);
|
||||
if (result.exitCode == 0) {
|
||||
print('成功设置Shell脚本执行权限: $shellScriptPath');
|
||||
} else {
|
||||
print('设置Shell脚本执行权限失败: ${result.stderr}');
|
||||
}
|
||||
} catch (e) {
|
||||
print('设置Shell脚本权限异常: $e');
|
||||
}
|
||||
}
|
||||
|
||||
print('脚本文件迁移完成');
|
||||
}
|
||||
|
||||
/// 迁移二进制文件
|
||||
static Future<void> _migrateBinaries() async {
|
||||
print('开始迁移二进制文件...');
|
||||
|
||||
final supportDir = await getApplicationSupportDirectory();
|
||||
final binDir = Directory(p.join(supportDir.path, 'bin'));
|
||||
|
||||
// 创建bin目录
|
||||
if (!await binDir.exists()) {
|
||||
await binDir.create(recursive: true);
|
||||
}
|
||||
|
||||
// macOS 二进制文件
|
||||
final macBinDir = Directory(p.join(binDir.path, 'macos'));
|
||||
if (!await macBinDir.exists()) {
|
||||
await macBinDir.create(recursive: true);
|
||||
}
|
||||
|
||||
await _extractAsset(
|
||||
'assets/bin/mac/upscayl-bin',
|
||||
p.join(macBinDir.path, 'upscayl-bin'),
|
||||
);
|
||||
|
||||
// Windows 二进制文件
|
||||
final winBinDir = Directory(p.join(binDir.path, 'windows'));
|
||||
if (!await winBinDir.exists()) {
|
||||
await winBinDir.create(recursive: true);
|
||||
}
|
||||
|
||||
await _extractAsset(
|
||||
'assets/bin/windows/upscayl-bin.exe',
|
||||
p.join(winBinDir.path, 'upscayl-bin.exe'),
|
||||
);
|
||||
|
||||
await _extractAsset(
|
||||
'assets/bin/windows/vcomp140.dll',
|
||||
p.join(winBinDir.path, 'vcomp140.dll'),
|
||||
);
|
||||
|
||||
await _extractAsset(
|
||||
'assets/bin/windows/vcomp140d.dll',
|
||||
p.join(winBinDir.path, 'vcomp140d.dll'),
|
||||
);
|
||||
|
||||
// 设置 macOS/Linux 二进制文件执行权限
|
||||
if (Platform.isMacOS || Platform.isLinux) {
|
||||
final binPath = p.join(macBinDir.path, 'upscayl-bin');
|
||||
try {
|
||||
final result = await Process.run('chmod', ['+x', binPath]);
|
||||
if (result.exitCode == 0) {
|
||||
print('成功设置执行权限: $binPath');
|
||||
} else {
|
||||
print('设置执行权限失败: ${result.stderr}');
|
||||
}
|
||||
} catch (e) {
|
||||
print('设置权限异常: $e');
|
||||
}
|
||||
}
|
||||
|
||||
print('二进制文件迁移完成');
|
||||
}
|
||||
|
||||
/// 迁移模型文件
|
||||
static Future<void> _migrateModels() async {
|
||||
print('开始迁移模型文件...');
|
||||
|
||||
final supportDir = await getApplicationSupportDirectory();
|
||||
final modelsDir = Directory(p.join(supportDir.path, 'models'));
|
||||
|
||||
// 创建models目录
|
||||
if (!await modelsDir.exists()) {
|
||||
await modelsDir.create(recursive: true);
|
||||
}
|
||||
|
||||
// 模型文件列表
|
||||
final modelFiles = [
|
||||
'high-fidelity-4x.bin',
|
||||
'high-fidelity-4x.param',
|
||||
'digital-art-4x.bin',
|
||||
'digital-art-4x.param',
|
||||
'remacri-4x.bin',
|
||||
'remacri-4x.param',
|
||||
'ultrasharp-4x.bin',
|
||||
'ultrasharp-4x.param',
|
||||
'upscayl-standard-4x.bin',
|
||||
'upscayl-standard-4x.param',
|
||||
'ultramix-balanced-4x.bin',
|
||||
'ultramix-balanced-4x.param',
|
||||
'upscayl-lite-4x.bin',
|
||||
'upscayl-lite-4x.param',
|
||||
];
|
||||
|
||||
// 迁移所有模型文件
|
||||
for (final modelFile in modelFiles) {
|
||||
try {
|
||||
await _extractAsset(
|
||||
'assets/models/$modelFile',
|
||||
p.join(modelsDir.path, modelFile),
|
||||
);
|
||||
} catch (e) {
|
||||
print('迁移模型文件失败 $modelFile: $e');
|
||||
// 继续迁移其他模型文件
|
||||
}
|
||||
}
|
||||
|
||||
print('模型文件迁移完成');
|
||||
}
|
||||
|
||||
/// 获取模型文件目录路径
|
||||
static Future<String> getModelsPath() async {
|
||||
final supportDir = await getApplicationSupportDirectory();
|
||||
return p.join(supportDir.path, 'cup', "model.gltf");
|
||||
}
|
||||
|
||||
/// 获取3D模型文件目录路径
|
||||
static Future<String> get3DModelsPath() async {
|
||||
final supportDir = await getApplicationSupportDirectory();
|
||||
return p.join(supportDir.path, 'cup');
|
||||
}
|
||||
|
||||
static Future<Map<String, dynamic>> readLocalJson() async {
|
||||
// 获取应用支持目录(默认在 ~/Library/Application Support/)
|
||||
final appSupportDir = await getApplicationSupportDirectory();
|
||||
final targetDir = Directory('${appSupportDir.path}/cup');
|
||||
|
||||
// 检查目录是否存在,若不存在则创建
|
||||
if (!await targetDir.exists()) {
|
||||
await targetDir.create(recursive: true);
|
||||
}
|
||||
print('file=${targetDir.path}/model.gltf');
|
||||
// 构建 JSON 文件路径
|
||||
final file = File('${targetDir.path}/model.gltf');
|
||||
|
||||
if (await file.exists()) {
|
||||
final content = await file.readAsString();
|
||||
return jsonDecode(content);
|
||||
} else {
|
||||
throw Exception('JSON 文件不存在');
|
||||
}
|
||||
}
|
||||
|
||||
/// 获取特定的3D模型文件路径
|
||||
static Future<String> get3DModelPath(String filename) async {
|
||||
final models3dPath = await get3DModelsPath();
|
||||
return p.join(models3dPath, filename);
|
||||
}
|
||||
|
||||
/// 获取脚本文件路径 (仅适用于macOS/Linux)
|
||||
static Future<String> getScriptPath() async {
|
||||
if (Platform.isWindows) {
|
||||
throw UnsupportedError('Windows平台已使用专门的UpscaleWindowsService,不再需要脚本文件');
|
||||
}
|
||||
|
||||
final supportDir = await getApplicationSupportDirectory();
|
||||
final scriptName = 'upscale_to_8k_single.sh';
|
||||
final scriptPath = p.join(supportDir.path, scriptName);
|
||||
final scriptFile = File(scriptPath);
|
||||
|
||||
if (!await scriptFile.exists()) {
|
||||
throw FileSystemException(
|
||||
'脚本文件不存在: $scriptPath\n请确保应用程序已正确初始化资源',
|
||||
scriptPath,
|
||||
);
|
||||
}
|
||||
|
||||
return scriptPath;
|
||||
}
|
||||
|
||||
/// 获取二进制文件路径
|
||||
static Future<String> getBinaryPath() async {
|
||||
final supportDir = await getApplicationSupportDirectory();
|
||||
|
||||
String platformDir;
|
||||
String binaryName;
|
||||
|
||||
if (Platform.isMacOS) {
|
||||
platformDir = 'macos';
|
||||
binaryName = 'upscayl-bin';
|
||||
} else if (Platform.isWindows) {
|
||||
platformDir = 'windows';
|
||||
binaryName = 'upscayl-bin.exe';
|
||||
} else if (Platform.isLinux) {
|
||||
platformDir = 'macos'; // Linux 使用 macOS 的二进制文件
|
||||
binaryName = 'upscayl-bin';
|
||||
} else {
|
||||
throw UnsupportedError('不支持的操作系统: ${Platform.operatingSystem}');
|
||||
}
|
||||
|
||||
final binPath = p.join(supportDir.path, 'bin', platformDir, binaryName);
|
||||
|
||||
// 检查文件是否存在
|
||||
final binFile = File(binPath);
|
||||
if (!await binFile.exists()) {
|
||||
throw FileSystemException('二进制文件不存在: $binPath\n请确保应用程序已正确初始化资源', binPath);
|
||||
}
|
||||
|
||||
return binPath;
|
||||
}
|
||||
|
||||
/// 设置脚本执行权限
|
||||
static Future<void> setScriptExecutable(String scriptPath) async {
|
||||
// 设置脚本执行权限(仅限 macOS/Linux)
|
||||
if (Platform.isMacOS || Platform.isLinux) {
|
||||
try {
|
||||
final result = await Process.run('chmod', ['+x', scriptPath]);
|
||||
if (result.exitCode == 0) {
|
||||
print('成功设置脚本执行权限: $scriptPath');
|
||||
} else {
|
||||
print('设置脚本执行权限失败: ${result.stderr}');
|
||||
}
|
||||
} catch (e) {
|
||||
print('设置脚本权限异常: $e');
|
||||
}
|
||||
}
|
||||
// Windows 不需要设置执行权限
|
||||
}
|
||||
}
|
||||
@@ -1,204 +0,0 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
class ModelManager {
|
||||
/// 当前应用版本(用于初始化检查)
|
||||
static String? _currentVersion;
|
||||
|
||||
/// 获取当前应用版本
|
||||
static Future<String> _getCurrentVersion() async {
|
||||
if (_currentVersion == null) {
|
||||
final packageInfo = await PackageInfo.fromPlatform();
|
||||
_currentVersion = '${packageInfo.version}+${packageInfo.buildNumber}';
|
||||
}
|
||||
return _currentVersion!;
|
||||
}
|
||||
|
||||
/// 检查3D模型资源是否已完成初始化(基于版本号)
|
||||
static Future<bool> isInitialized() async {
|
||||
final supportDir = await getApplicationSupportDirectory();
|
||||
final currentVersion = await _getCurrentVersion();
|
||||
final initMarker = File(
|
||||
p.join(supportDir.path, '3d_models', '.initialized_$currentVersion'),
|
||||
);
|
||||
|
||||
return await initMarker.exists();
|
||||
}
|
||||
|
||||
/// 标记3D模型资源初始化完成
|
||||
static Future<void> markInitialized() async {
|
||||
final supportDir = await getApplicationSupportDirectory();
|
||||
final currentVersion = await _getCurrentVersion();
|
||||
final modelsDir = Directory(p.join(supportDir.path, '3d_models'));
|
||||
|
||||
if (!await modelsDir.exists()) {
|
||||
await modelsDir.create(recursive: true);
|
||||
}
|
||||
|
||||
final initMarker = File(
|
||||
p.join(modelsDir.path, '.initialized_$currentVersion'),
|
||||
);
|
||||
await initMarker.writeAsString('${DateTime.now().toIso8601String()}\n');
|
||||
}
|
||||
|
||||
/// 从assets目录提取文件到指定路径
|
||||
static Future<void> _extractAsset(String assetPath, String localPath) async {
|
||||
final localFile = File(localPath);
|
||||
final localDir = Directory(p.dirname(localPath));
|
||||
|
||||
// 确保目录存在
|
||||
if (!await localDir.exists()) {
|
||||
await localDir.create(recursive: true);
|
||||
}
|
||||
|
||||
try {
|
||||
// 从assets中读取数据
|
||||
final ByteData data = await rootBundle.load(assetPath);
|
||||
final List<int> bytes = data.buffer.asUint8List();
|
||||
|
||||
// 写入本地文件
|
||||
await localFile.writeAsBytes(bytes);
|
||||
print('成功提取3D模型文件: $assetPath -> $localPath');
|
||||
} catch (e) {
|
||||
print('提取3D模型资源文件失败 $assetPath: $e');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
/// 初始化3D模型资源
|
||||
static Future<void> initializeAppResources() async {
|
||||
final currentVersion = await _getCurrentVersion();
|
||||
|
||||
if (await isInitialized()) {
|
||||
print('3D模型资源已初始化,当前版本: $currentVersion');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 迁移模型文件
|
||||
await _migrateModels();
|
||||
|
||||
// 标记初始化完成
|
||||
await markInitialized();
|
||||
|
||||
print('3D模型资源初始化完成');
|
||||
} catch (e) {
|
||||
print('3D模型资源初始化失败: $e');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
/// 迁移3D模型文件
|
||||
/// 迁移3D模型文件
|
||||
static Future<void> _migrateModels() async {
|
||||
print('开始迁移3D模型文件...');
|
||||
|
||||
final supportDir = await getApplicationSupportDirectory();
|
||||
final modelsDir = Directory(p.join(supportDir.path, 'models'));
|
||||
|
||||
// 创建3D模型目录
|
||||
if (!await modelsDir.exists()) {
|
||||
await modelsDir.create(recursive: true);
|
||||
}
|
||||
|
||||
// 创建cup子目录
|
||||
final cupDir = Directory(p.join(modelsDir.path, 'cup'));
|
||||
if (!await cupDir.exists()) {
|
||||
await cupDir.create(recursive: true);
|
||||
}
|
||||
|
||||
// 3D模型文件列表 - 修正路径
|
||||
final modelFiles = [
|
||||
'cup/model.gltf',
|
||||
'cup/model.bin',
|
||||
'cup/texture.jpg',
|
||||
];
|
||||
|
||||
// 迁移所有3D模型文件
|
||||
for (final modelFile in modelFiles) {
|
||||
try {
|
||||
// 确保源文件路径正确
|
||||
final assetPath = 'assets/$modelFile';
|
||||
|
||||
// 检查资源是否存在
|
||||
try {
|
||||
await rootBundle.load(assetPath);
|
||||
} catch (e) {
|
||||
print('资源文件不存在: $assetPath');
|
||||
continue;
|
||||
}
|
||||
|
||||
await _extractAsset(
|
||||
assetPath,
|
||||
p.join(modelsDir.path, modelFile),
|
||||
);
|
||||
} catch (e) {
|
||||
print('迁移3D模型文件失败 $modelFile: $e');
|
||||
// 继续迁移其他模型文件
|
||||
}
|
||||
}
|
||||
|
||||
print('3D模型文件迁移完成');
|
||||
}
|
||||
|
||||
/// 获取3D模型文件目录路径
|
||||
static Future<String> getModelsPath() async {
|
||||
final supportDir = await getApplicationSupportDirectory();
|
||||
return p.join(supportDir.path, 'models/cup/');
|
||||
}
|
||||
|
||||
/// 获取特定3D模型文件的路径
|
||||
static Future<String> getModelFilePath(String relativePath) async {
|
||||
final modelsPath = await getModelsPath();
|
||||
final filePath = p.join(modelsPath, relativePath);
|
||||
final file = File(filePath);
|
||||
|
||||
if (!await file.exists()) {
|
||||
throw FileSystemException(
|
||||
'3D模型文件不存在: $filePath\n请确保应用程序已正确初始化3D模型资源',
|
||||
filePath,
|
||||
);
|
||||
}
|
||||
|
||||
return filePath;
|
||||
}
|
||||
|
||||
/// 获取GLTF模型文件路径
|
||||
static Future<String> getGltfModelPath() async {
|
||||
return getModelFilePath('cup/model.gltf');
|
||||
}
|
||||
|
||||
/// 获取BIN模型文件路径
|
||||
static Future<String> getBinModelPath() async {
|
||||
return getModelFilePath('cup/model.bin');
|
||||
}
|
||||
|
||||
/// 获取纹理文件路径
|
||||
static Future<String> getTexturePath() async {
|
||||
return getModelFilePath('cup/texture.jpg');
|
||||
}
|
||||
|
||||
/// 更新纹理文件
|
||||
static Future<void> updateTexture(File newTextureFile) async {
|
||||
try {
|
||||
final texturePath = await getTexturePath();
|
||||
final textureFile = File(texturePath);
|
||||
|
||||
// 删除旧纹理文件
|
||||
if (await textureFile.exists()) {
|
||||
await textureFile.delete();
|
||||
}
|
||||
|
||||
// 复制新纹理文件
|
||||
await newTextureFile.copy(texturePath);
|
||||
print('纹理文件更新成功: $texturePath');
|
||||
} catch (e) {
|
||||
print('更新纹理文件失败: $e');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
import FlutterMacOS
|
||||
import Foundation
|
||||
|
||||
import file_picker
|
||||
import package_info_plus
|
||||
import path_provider_foundation
|
||||
import thermion_flutter
|
||||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
FilePickerPlugin.register(with: registry.registrar(forPlugin: "FilePickerPlugin"))
|
||||
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
|
||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||
SwiftThermionFlutterPlugin.register(with: registry.registrar(forPlugin: "SwiftThermionFlutterPlugin"))
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
PODS:
|
||||
- file_picker (0.0.1):
|
||||
- FlutterMacOS
|
||||
- FlutterMacOS (1.0.0)
|
||||
- package_info_plus (0.0.1):
|
||||
- FlutterMacOS
|
||||
- path_provider_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- thermion_flutter (0.0.1):
|
||||
- FlutterMacOS
|
||||
|
||||
DEPENDENCIES:
|
||||
- file_picker (from `Flutter/ephemeral/.symlinks/plugins/file_picker/macos`)
|
||||
- FlutterMacOS (from `Flutter/ephemeral`)
|
||||
- package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`)
|
||||
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
|
||||
- thermion_flutter (from `Flutter/ephemeral/.symlinks/plugins/thermion_flutter/macos`)
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
file_picker:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/file_picker/macos
|
||||
FlutterMacOS:
|
||||
:path: Flutter/ephemeral
|
||||
package_info_plus:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos
|
||||
path_provider_foundation:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin
|
||||
thermion_flutter:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/thermion_flutter/macos
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
file_picker: 7584aae6fa07a041af2b36a2655122d42f578c1a
|
||||
FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1
|
||||
package_info_plus: a8a591e70e87ce97ce5d21b2594f69cea9e0312f
|
||||
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
|
||||
thermion_flutter: d5d52ef933321eedbee6c4ddda4259c8cbcc84ed
|
||||
|
||||
PODFILE CHECKSUM: 1888651be91a8ad58692c1add9ce24279fd4e950
|
||||
|
||||
COCOAPODS: 1.16.2
|
||||
@@ -1,803 +0,0 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 54;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXAggregateTarget section */
|
||||
33CC111A2044C6BA0003C045 /* Flutter Assemble */ = {
|
||||
isa = PBXAggregateTarget;
|
||||
buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */;
|
||||
buildPhases = (
|
||||
33CC111E2044C6BF0003C045 /* ShellScript */,
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = "Flutter Assemble";
|
||||
productName = FLX;
|
||||
};
|
||||
/* End PBXAggregateTarget section */
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; };
|
||||
335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; };
|
||||
33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; };
|
||||
33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
|
||||
33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
|
||||
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
|
||||
56F02897B820ADA2DE043C9B /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 93162ABED09E78126BD3CDE5 /* Pods_Runner.framework */; };
|
||||
62AA8D6F0977DC04C5F3E47D /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9491FF37DFB0425E4EA0B397 /* Pods_RunnerTests.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 33CC10E52044A3C60003C045 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 33CC10EC2044A3C60003C045;
|
||||
remoteInfo = Runner;
|
||||
};
|
||||
33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 33CC10E52044A3C60003C045 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 33CC111A2044C6BA0003C045;
|
||||
remoteInfo = FLX;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
33CC110E2044A8840003C045 /* Bundle Framework */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
);
|
||||
name = "Bundle Framework";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
|
||||
333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = "<group>"; };
|
||||
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = "<group>"; };
|
||||
33CC10ED2044A3C60003C045 /* quickstart.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = quickstart.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = "<group>"; };
|
||||
33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
|
||||
33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = "<group>"; };
|
||||
33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = "<group>"; };
|
||||
33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = "<group>"; };
|
||||
33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = "<group>"; };
|
||||
33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = "<group>"; };
|
||||
33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = "<group>"; };
|
||||
33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = "<group>"; };
|
||||
33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = "<group>"; };
|
||||
4DE9521732D230B91BB45C73 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
5C2B9597C21FB64F23F75F32 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||
61CABADBE923C1C839256779 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
|
||||
89306E3842C70B544B3CD9C8 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
||||
914F20B2B6A55F4538F4FECA /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
93162ABED09E78126BD3CDE5 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
9491FF37DFB0425E4EA0B397 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
|
||||
E5EDF04F05E94A7EC21CBB16 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
331C80D2294CF70F00263BE5 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
62AA8D6F0977DC04C5F3E47D /* Pods_RunnerTests.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
33CC10EA2044A3C60003C045 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
56F02897B820ADA2DE043C9B /* Pods_Runner.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
0AD0DB307687B659B7995D8A /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4DE9521732D230B91BB45C73 /* Pods-Runner.debug.xcconfig */,
|
||||
89306E3842C70B544B3CD9C8 /* Pods-Runner.release.xcconfig */,
|
||||
61CABADBE923C1C839256779 /* Pods-Runner.profile.xcconfig */,
|
||||
914F20B2B6A55F4538F4FECA /* Pods-RunnerTests.debug.xcconfig */,
|
||||
5C2B9597C21FB64F23F75F32 /* Pods-RunnerTests.release.xcconfig */,
|
||||
E5EDF04F05E94A7EC21CBB16 /* Pods-RunnerTests.profile.xcconfig */,
|
||||
);
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
331C80D6294CF71000263BE5 /* RunnerTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
331C80D7294CF71000263BE5 /* RunnerTests.swift */,
|
||||
);
|
||||
path = RunnerTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
33BA886A226E78AF003329D5 /* Configs */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
33E5194F232828860026EE4D /* AppInfo.xcconfig */,
|
||||
9740EEB21CF90195004384FC /* Debug.xcconfig */,
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
|
||||
333000ED22D3DE5D00554162 /* Warnings.xcconfig */,
|
||||
);
|
||||
path = Configs;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
33CC10E42044A3C60003C045 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
33FAB671232836740065AC1E /* Runner */,
|
||||
33CEB47122A05771004F2AC0 /* Flutter */,
|
||||
331C80D6294CF71000263BE5 /* RunnerTests */,
|
||||
33CC10EE2044A3C60003C045 /* Products */,
|
||||
D73912EC22F37F3D000D13A0 /* Frameworks */,
|
||||
0AD0DB307687B659B7995D8A /* Pods */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
33CC10EE2044A3C60003C045 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
33CC10ED2044A3C60003C045 /* quickstart.app */,
|
||||
331C80D5294CF71000263BE5 /* RunnerTests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
33CC11242044D66E0003C045 /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
33CC10F22044A3C60003C045 /* Assets.xcassets */,
|
||||
33CC10F42044A3C60003C045 /* MainMenu.xib */,
|
||||
33CC10F72044A3C60003C045 /* Info.plist */,
|
||||
);
|
||||
name = Resources;
|
||||
path = ..;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
33CEB47122A05771004F2AC0 /* Flutter */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */,
|
||||
33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */,
|
||||
33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */,
|
||||
33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */,
|
||||
);
|
||||
path = Flutter;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
33FAB671232836740065AC1E /* Runner */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
33CC10F02044A3C60003C045 /* AppDelegate.swift */,
|
||||
33CC11122044BFA00003C045 /* MainFlutterWindow.swift */,
|
||||
33E51913231747F40026EE4D /* DebugProfile.entitlements */,
|
||||
33E51914231749380026EE4D /* Release.entitlements */,
|
||||
33CC11242044D66E0003C045 /* Resources */,
|
||||
33BA886A226E78AF003329D5 /* Configs */,
|
||||
);
|
||||
path = Runner;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D73912EC22F37F3D000D13A0 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
93162ABED09E78126BD3CDE5 /* Pods_Runner.framework */,
|
||||
9491FF37DFB0425E4EA0B397 /* Pods_RunnerTests.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
331C80D4294CF70F00263BE5 /* RunnerTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
|
||||
buildPhases = (
|
||||
465FA95FF24452F333D1C1C1 /* [CP] Check Pods Manifest.lock */,
|
||||
331C80D1294CF70F00263BE5 /* Sources */,
|
||||
331C80D2294CF70F00263BE5 /* Frameworks */,
|
||||
331C80D3294CF70F00263BE5 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
331C80DA294CF71000263BE5 /* PBXTargetDependency */,
|
||||
);
|
||||
name = RunnerTests;
|
||||
productName = RunnerTests;
|
||||
productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
33CC10EC2044A3C60003C045 /* Runner */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||
buildPhases = (
|
||||
ED773E1A7DA74470DCD044C6 /* [CP] Check Pods Manifest.lock */,
|
||||
33CC10E92044A3C60003C045 /* Sources */,
|
||||
33CC10EA2044A3C60003C045 /* Frameworks */,
|
||||
33CC10EB2044A3C60003C045 /* Resources */,
|
||||
33CC110E2044A8840003C045 /* Bundle Framework */,
|
||||
3399D490228B24CF009A79C7 /* ShellScript */,
|
||||
CB1E43C40756BBF229674223 /* [CP] Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
33CC11202044C79F0003C045 /* PBXTargetDependency */,
|
||||
);
|
||||
name = Runner;
|
||||
productName = Runner;
|
||||
productReference = 33CC10ED2044A3C60003C045 /* quickstart.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
33CC10E52044A3C60003C045 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
BuildIndependentTargetsInParallel = YES;
|
||||
LastSwiftUpdateCheck = 0920;
|
||||
LastUpgradeCheck = 1510;
|
||||
ORGANIZATIONNAME = "";
|
||||
TargetAttributes = {
|
||||
331C80D4294CF70F00263BE5 = {
|
||||
CreatedOnToolsVersion = 14.0;
|
||||
TestTargetID = 33CC10EC2044A3C60003C045;
|
||||
};
|
||||
33CC10EC2044A3C60003C045 = {
|
||||
CreatedOnToolsVersion = 9.2;
|
||||
LastSwiftMigration = 1100;
|
||||
ProvisioningStyle = Automatic;
|
||||
SystemCapabilities = {
|
||||
com.apple.Sandbox = {
|
||||
enabled = 1;
|
||||
};
|
||||
};
|
||||
};
|
||||
33CC111A2044C6BA0003C045 = {
|
||||
CreatedOnToolsVersion = 9.2;
|
||||
ProvisioningStyle = Manual;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */;
|
||||
compatibilityVersion = "Xcode 9.3";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 33CC10E42044A3C60003C045;
|
||||
productRefGroup = 33CC10EE2044A3C60003C045 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
33CC10EC2044A3C60003C045 /* Runner */,
|
||||
331C80D4294CF70F00263BE5 /* RunnerTests */,
|
||||
33CC111A2044C6BA0003C045 /* Flutter Assemble */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
331C80D3294CF70F00263BE5 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
33CC10EB2044A3C60003C045 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */,
|
||||
33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
3399D490228B24CF009A79C7 /* ShellScript */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n";
|
||||
};
|
||||
33CC111E2044C6BF0003C045 /* ShellScript */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
Flutter/ephemeral/FlutterInputs.xcfilelist,
|
||||
);
|
||||
inputPaths = (
|
||||
Flutter/ephemeral/tripwire,
|
||||
);
|
||||
outputFileListPaths = (
|
||||
Flutter/ephemeral/FlutterOutputs.xcfilelist,
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire";
|
||||
};
|
||||
465FA95FF24452F333D1C1C1 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
CB1E43C40756BBF229674223 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
ED773E1A7DA74470DCD044C6 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
331C80D1294CF70F00263BE5 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
33CC10E92044A3C60003C045 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */,
|
||||
33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */,
|
||||
335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
331C80DA294CF71000263BE5 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 33CC10EC2044A3C60003C045 /* Runner */;
|
||||
targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */;
|
||||
};
|
||||
33CC11202044C79F0003C045 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */;
|
||||
targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
33CC10F42044A3C60003C045 /* MainMenu.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
33CC10F52044A3C60003C045 /* Base */,
|
||||
);
|
||||
name = MainMenu.xib;
|
||||
path = Runner;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
331C80DB294CF71000263BE5 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 914F20B2B6A55F4538F4FECA /* Pods-RunnerTests.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.quickstart.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/quickstart.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/quickstart";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
331C80DC294CF71000263BE5 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 5C2B9597C21FB64F23F75F32 /* Pods-RunnerTests.release.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.quickstart.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/quickstart.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/quickstart";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
331C80DD294CF71000263BE5 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = E5EDF04F05E94A7EC21CBB16 /* Pods-RunnerTests.profile.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.quickstart.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/quickstart.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/quickstart";
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
338D0CE9231458BD00FA5F75 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
338D0CEA231458BD00FA5F75 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
338D0CEB231458BD00FA5F75 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
33CC10F92044A3C60003C045 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
33CC10FA2044A3C60003C045 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
33CC10FC2044A3C60003C045 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
33CC10FD2044A3C60003C045 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
33CC111C2044C6BA0003C045 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
33CC111D2044C6BA0003C045 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
331C80DB294CF71000263BE5 /* Debug */,
|
||||
331C80DC294CF71000263BE5 /* Release */,
|
||||
331C80DD294CF71000263BE5 /* Profile */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
33CC10F92044A3C60003C045 /* Debug */,
|
||||
33CC10FA2044A3C60003C045 /* Release */,
|
||||
338D0CE9231458BD00FA5F75 /* Profile */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
33CC10FC2044A3C60003C045 /* Debug */,
|
||||
33CC10FD2044A3C60003C045 /* Release */,
|
||||
338D0CEA231458BD00FA5F75 /* Profile */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
33CC111C2044C6BA0003C045 /* Debug */,
|
||||
33CC111D2044C6BA0003C045 /* Release */,
|
||||
338D0CEB231458BD00FA5F75 /* Profile */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 33CC10E52044A3C60003C045 /* Project object */;
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1510"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
|
||||
BuildableName = "quickstart.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
|
||||
BuildableName = "quickstart.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO"
|
||||
parallelizable = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "331C80D4294CF70F00263BE5"
|
||||
BuildableName = "RunnerTests.xctest"
|
||||
BlueprintName = "RunnerTests"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
enableGPUValidationMode = "1"
|
||||
enableGPUFrameCaptureMode = "1"
|
||||
enableGPUShaderValidationMode = "2"
|
||||
showGraphicsOverview = "Yes"
|
||||
logGraphicsOverview = "Yes"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
|
||||
BuildableName = "quickstart.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Profile"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
|
||||
BuildableName = "quickstart.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
@@ -1,22 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>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/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,22 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>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/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.server</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,54 +0,0 @@
|
||||
name: animations
|
||||
description: "Thermion animation example."
|
||||
publish_to: 'none'
|
||||
|
||||
version: 1.0.0+1
|
||||
|
||||
environment:
|
||||
sdk: '>=3.3.0 <4.0.0'
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
cupertino_icons: ^1.0.8
|
||||
vector_math: ^2.1.4
|
||||
|
||||
win32: 5.5.1
|
||||
web: 1.0.0
|
||||
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:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_lints: ^4.0.0
|
||||
|
||||
dependency_overrides:
|
||||
thermion_dart:
|
||||
path: ../../../thermion_dart
|
||||
thermion_flutter:
|
||||
path: ../../../thermion_flutter/thermion_flutter
|
||||
thermion_flutter_method_channel:
|
||||
path: ../../../thermion_flutter/thermion_flutter_method_channel
|
||||
thermion_flutter_platform_interface:
|
||||
path: ../../../thermion_flutter/thermion_flutter_platform_interface
|
||||
thermion_flutter_web:
|
||||
path: ../../../thermion_flutter/thermion_flutter_web
|
||||
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
assets:
|
||||
- assets/
|
||||
- assets/BusterDrone/
|
||||
- assets/BusterDrone/textures/
|
||||
- assets/cup/
|
||||
- assets/image/
|
||||
- assets/bin/mac/
|
||||
- assets/bin/windows/
|
||||
- assets/models/
|
||||
- assets/upscale_to_8k_single.sh
|
||||
@@ -1,59 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<base href="$FLUTTER_BASE_HREF">
|
||||
|
||||
<meta charset="UTF-8">
|
||||
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
|
||||
<meta name="description" content="A new Flutter project.">
|
||||
|
||||
<!-- iOS meta tags & icons -->
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||
<meta name="apple-mobile-web-app-title" content="quickstart">
|
||||
<link rel="apple-touch-icon" href="icons/Icon-192.png">
|
||||
|
||||
<!-- Favicon -->
|
||||
<link rel="icon" type="image/png" href="favicon.png" />
|
||||
|
||||
<title>quickstart</title>
|
||||
<link rel="manifest" href="manifest.json">
|
||||
<script>
|
||||
// The value below is injected by flutter build, do not touch.
|
||||
const serviceWorkerVersion = null;
|
||||
</script>
|
||||
<script src="flutter.js" defer></script>
|
||||
<script type="text/javascript" src="./thermion_dart.js"></script>
|
||||
<script type="module">
|
||||
try {
|
||||
window.thermion_dart = await thermion_dart();
|
||||
} catch(err) {
|
||||
console.error(err);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="flutter-container"></div>
|
||||
<script type="text/javascript">
|
||||
window.addEventListener('load', function (ev) {
|
||||
// Download main.dart.js
|
||||
_flutter.loader.loadEntrypoint({
|
||||
serviceWorker: {
|
||||
serviceWorkerVersion: serviceWorkerVersion,
|
||||
},
|
||||
onEntrypointLoaded: async function (engineInitializer) {
|
||||
const appRunner = await engineInitializer.initializeEngine({
|
||||
hostElement: document.querySelector('#flutter-app-container')
|
||||
});
|
||||
await appRunner.runApp();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1 +0,0 @@
|
||||
../../../../thermion_dart/native/web/build/build/out/thermion_dart.js
|
||||