Compare commits
42 Commits
thermion_f
...
thermion_f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9420143a36 | ||
|
|
eb8835b63a | ||
|
|
f9468db266 | ||
|
|
1135ba054c | ||
|
|
8f7509a23f | ||
|
|
cba9ee98ad | ||
|
|
0ec0fef8f3 | ||
|
|
a348562f56 | ||
|
|
392a606bbc | ||
|
|
440bed4485 | ||
|
|
a321966e5b | ||
|
|
f180c1018f | ||
|
|
f267aa6dc6 | ||
|
|
1c74e83c2c | ||
|
|
099a895eb6 | ||
|
|
3b810f84da | ||
|
|
10f2c7d36b | ||
|
|
5b849638de | ||
|
|
857fd6f782 | ||
|
|
29edec63ab | ||
|
|
c6afc4756a | ||
|
|
365657cf88 | ||
|
|
5441dedcf4 | ||
|
|
254b6d8af2 | ||
|
|
1459aea5cf | ||
|
|
80d8525671 | ||
|
|
389a165ed3 | ||
|
|
d8f309d21b | ||
|
|
ee983ddfaa | ||
|
|
c1cdd37e9d | ||
|
|
646f05933d | ||
|
|
3f854a7f27 | ||
|
|
740dbea8bd | ||
|
|
95a44936ac | ||
|
|
9deafc7371 | ||
|
|
c1af7e374d | ||
|
|
cd71db72be | ||
|
|
a9d90f966b | ||
|
|
1a323ca551 | ||
|
|
2d85e191bc | ||
|
|
1b971a859c | ||
|
|
78b697d1c2 |
200
CHANGELOG.md
200
CHANGELOG.md
@@ -3,6 +3,206 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## 2024-10-14
|
||||
|
||||
### Changes
|
||||
|
||||
---
|
||||
|
||||
Packages with breaking changes:
|
||||
|
||||
- There are no breaking changes in this release.
|
||||
|
||||
Packages with other changes:
|
||||
|
||||
- [`thermion_dart` - `v0.2.1-dev.0.0.7`](#thermion_dart---v021-dev007)
|
||||
- [`thermion_flutter_web` - `v0.1.0+8`](#thermion_flutter_web---v0108)
|
||||
- [`thermion_flutter` - `v0.2.1-dev.6`](#thermion_flutter---v021-dev6)
|
||||
- [`thermion_flutter_platform_interface` - `v0.2.1-dev.6`](#thermion_flutter_platform_interface---v021-dev6)
|
||||
- [`thermion_flutter_ffi` - `v0.2.1-dev.6`](#thermion_flutter_ffi---v021-dev6)
|
||||
|
||||
Packages with dependency updates only:
|
||||
|
||||
> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project.
|
||||
|
||||
- `thermion_flutter_web` - `v0.1.0+8`
|
||||
- `thermion_flutter` - `v0.2.1-dev.6`
|
||||
- `thermion_flutter_platform_interface` - `v0.2.1-dev.6`
|
||||
- `thermion_flutter_ffi` - `v0.2.1-dev.6`
|
||||
|
||||
---
|
||||
|
||||
#### `thermion_dart` - `v0.2.1-dev.0.0.7`
|
||||
|
||||
- Bump "thermion_dart" to `0.2.1-dev.0.0.7`.
|
||||
|
||||
|
||||
## 2024-10-10
|
||||
|
||||
### Changes
|
||||
|
||||
---
|
||||
|
||||
Packages with breaking changes:
|
||||
|
||||
- There are no breaking changes in this release.
|
||||
|
||||
Packages with other changes:
|
||||
|
||||
- [`thermion_dart` - `v0.2.1-dev.0.0.6`](#thermion_dart---v021-dev006)
|
||||
- [`thermion_flutter_web` - `v0.1.0+7`](#thermion_flutter_web---v0107)
|
||||
- [`thermion_flutter_platform_interface` - `v0.2.1-dev.5`](#thermion_flutter_platform_interface---v021-dev5)
|
||||
- [`thermion_flutter` - `v0.2.1-dev.5`](#thermion_flutter---v021-dev5)
|
||||
- [`thermion_flutter_ffi` - `v0.2.1-dev.5`](#thermion_flutter_ffi---v021-dev5)
|
||||
|
||||
Packages with dependency updates only:
|
||||
|
||||
> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project.
|
||||
|
||||
- `thermion_flutter_web` - `v0.1.0+7`
|
||||
- `thermion_flutter_platform_interface` - `v0.2.1-dev.5`
|
||||
- `thermion_flutter` - `v0.2.1-dev.5`
|
||||
- `thermion_flutter_ffi` - `v0.2.1-dev.5`
|
||||
|
||||
---
|
||||
|
||||
#### `thermion_dart` - `v0.2.1-dev.0.0.6`
|
||||
|
||||
- Bump "thermion_dart" to `0.2.1-dev.0.0.6`.
|
||||
|
||||
|
||||
## 2024-10-10
|
||||
|
||||
### Changes
|
||||
|
||||
---
|
||||
|
||||
Packages with breaking changes:
|
||||
|
||||
- There are no breaking changes in this release.
|
||||
|
||||
Packages with other changes:
|
||||
|
||||
- [`thermion_dart` - `v0.2.1-dev.0.0.5`](#thermion_dart---v021-dev005)
|
||||
- [`thermion_flutter_platform_interface` - `v0.2.1-dev.4`](#thermion_flutter_platform_interface---v021-dev4)
|
||||
- [`thermion_flutter_web` - `v0.1.0+6`](#thermion_flutter_web---v0106)
|
||||
- [`thermion_flutter` - `v0.2.1-dev.4`](#thermion_flutter---v021-dev4)
|
||||
- [`thermion_flutter_ffi` - `v0.2.1-dev.4`](#thermion_flutter_ffi---v021-dev4)
|
||||
|
||||
Packages with dependency updates only:
|
||||
|
||||
> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project.
|
||||
|
||||
- `thermion_flutter_platform_interface` - `v0.2.1-dev.4`
|
||||
- `thermion_flutter_web` - `v0.1.0+6`
|
||||
- `thermion_flutter` - `v0.2.1-dev.4`
|
||||
- `thermion_flutter_ffi` - `v0.2.1-dev.4`
|
||||
|
||||
---
|
||||
|
||||
#### `thermion_dart` - `v0.2.1-dev.0.0.5`
|
||||
|
||||
- Bump "thermion_dart" to `0.2.1-dev.0.0.5`.
|
||||
|
||||
|
||||
## 2024-10-02
|
||||
|
||||
### Changes
|
||||
|
||||
---
|
||||
|
||||
Packages with breaking changes:
|
||||
|
||||
- There are no breaking changes in this release.
|
||||
|
||||
Packages with other changes:
|
||||
|
||||
- [`thermion_dart` - `v0.2.1-dev.0.0.4`](#thermion_dart---v021-dev004)
|
||||
- [`thermion_flutter_web` - `v0.1.0+5`](#thermion_flutter_web---v0105)
|
||||
- [`thermion_flutter` - `v0.2.1-dev.3`](#thermion_flutter---v021-dev3)
|
||||
- [`thermion_flutter_platform_interface` - `v0.2.1-dev.3`](#thermion_flutter_platform_interface---v021-dev3)
|
||||
- [`thermion_flutter_ffi` - `v0.2.1-dev.3`](#thermion_flutter_ffi---v021-dev3)
|
||||
|
||||
Packages with dependency updates only:
|
||||
|
||||
> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project.
|
||||
|
||||
- `thermion_flutter_web` - `v0.1.0+5`
|
||||
- `thermion_flutter` - `v0.2.1-dev.3`
|
||||
- `thermion_flutter_platform_interface` - `v0.2.1-dev.3`
|
||||
- `thermion_flutter_ffi` - `v0.2.1-dev.3`
|
||||
|
||||
---
|
||||
|
||||
#### `thermion_dart` - `v0.2.1-dev.0.0.4`
|
||||
|
||||
|
||||
## 2024-10-02
|
||||
|
||||
### Changes
|
||||
|
||||
---
|
||||
|
||||
Packages with breaking changes:
|
||||
|
||||
- There are no breaking changes in this release.
|
||||
|
||||
Packages with other changes:
|
||||
|
||||
- [`thermion_dart` - `v0.2.1-dev.0.0.3`](#thermion_dart---v021-dev003)
|
||||
- [`thermion_flutter_web` - `v0.1.0+4`](#thermion_flutter_web---v0104)
|
||||
- [`thermion_flutter` - `v0.2.1-dev.2`](#thermion_flutter---v021-dev2)
|
||||
- [`thermion_flutter_platform_interface` - `v0.2.1-dev.2`](#thermion_flutter_platform_interface---v021-dev2)
|
||||
- [`thermion_flutter_ffi` - `v0.2.1-dev.2`](#thermion_flutter_ffi---v021-dev2)
|
||||
|
||||
Packages with dependency updates only:
|
||||
|
||||
> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project.
|
||||
|
||||
- `thermion_flutter_web` - `v0.1.0+4`
|
||||
- `thermion_flutter` - `v0.2.1-dev.2`
|
||||
- `thermion_flutter_platform_interface` - `v0.2.1-dev.2`
|
||||
- `thermion_flutter_ffi` - `v0.2.1-dev.2`
|
||||
|
||||
---
|
||||
|
||||
#### `thermion_dart` - `v0.2.1-dev.0.0.3`
|
||||
|
||||
- Bump "thermion_dart" to `0.2.1-dev.0.0.3`.
|
||||
|
||||
|
||||
## 2024-10-02
|
||||
|
||||
### Changes
|
||||
|
||||
---
|
||||
|
||||
Packages with breaking changes:
|
||||
|
||||
- There are no breaking changes in this release.
|
||||
|
||||
Packages with other changes:
|
||||
|
||||
- [`thermion_dart` - `v0.2.1-dev.0.0.2`](#thermion_dart---v021-dev002)
|
||||
- [`thermion_flutter_web` - `v0.1.0+3`](#thermion_flutter_web---v0103)
|
||||
- [`thermion_flutter_ffi` - `v0.2.1-dev.1`](#thermion_flutter_ffi---v021-dev1)
|
||||
- [`thermion_flutter` - `v0.2.1-dev.1`](#thermion_flutter---v021-dev1)
|
||||
- [`thermion_flutter_platform_interface` - `v0.2.1-dev.1`](#thermion_flutter_platform_interface---v021-dev1)
|
||||
|
||||
Packages with dependency updates only:
|
||||
|
||||
> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project.
|
||||
|
||||
- `thermion_flutter_web` - `v0.1.0+3`
|
||||
- `thermion_flutter_ffi` - `v0.2.1-dev.1`
|
||||
- `thermion_flutter` - `v0.2.1-dev.1`
|
||||
- `thermion_flutter_platform_interface` - `v0.2.1-dev.1`
|
||||
|
||||
---
|
||||
|
||||
#### `thermion_dart` - `v0.2.1-dev.0.0.2`
|
||||
|
||||
|
||||
## 2024-10-02
|
||||
|
||||
### Changes
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
## Android
|
||||
|
||||
### Min SDK version
|
||||
|
||||
Thermion requires Android SDK version 22, so change your `app/android/build.gradle` to match this version or higher:
|
||||
|
||||
```groovy
|
||||
defaultConfig {
|
||||
...
|
||||
minSdk = 22
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
### Shrink/Minify Resources
|
||||
|
||||
In release mode, you must add the following to your `app/build.gradle`:
|
||||
|
||||
```
|
||||
|
||||
@@ -1,3 +1,23 @@
|
||||
## 0.2.1-dev.0.0.7
|
||||
|
||||
- Bump "thermion_dart" to `0.2.1-dev.0.0.7`.
|
||||
|
||||
## 0.2.1-dev.0.0.6
|
||||
|
||||
- Bump "thermion_dart" to `0.2.1-dev.0.0.6`.
|
||||
|
||||
## 0.2.1-dev.0.0.5
|
||||
|
||||
- Bump "thermion_dart" to `0.2.1-dev.0.0.5`.
|
||||
|
||||
## 0.2.1-dev.0.0.4
|
||||
|
||||
## 0.2.1-dev.0.0.3
|
||||
|
||||
- Bump "thermion_dart" to `0.2.1-dev.0.0.3`.
|
||||
|
||||
## 0.2.1-dev.0.0.2
|
||||
|
||||
## 0.2.1-dev.0.0.1
|
||||
|
||||
## 0.2.1-dev.0.0.0
|
||||
|
||||
30
thermion_dart/extras/windows/CMakeLists.txt
Normal file
30
thermion_dart/extras/windows/CMakeLists.txt
Normal file
@@ -0,0 +1,30 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
set(PROJECT_NAME "thermion_windows")
|
||||
project(${PROJECT_NAME} LANGUAGES C CXX)
|
||||
|
||||
cmake_policy(VERSION 3.14...3.25)
|
||||
|
||||
add_compile_definitions(WGL_USE_BACKING_WINDOW)
|
||||
add_compile_definitions(UNICODE)
|
||||
|
||||
add_library(${PROJECT_NAME} SHARED
|
||||
"thermion_window.cpp"
|
||||
)
|
||||
|
||||
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
|
||||
|
||||
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_20)
|
||||
target_include_directories(${PROJECT_NAME} INTERFACE
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include"
|
||||
"${CMAKE_SOURCE_DIR}/../../../../thermion_dart/native/include/filament"
|
||||
"${CMAKE_SOURCE_DIR}/../../../../thermion_dart/native/include"
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE
|
||||
Shlwapi
|
||||
opengl32
|
||||
dwmapi
|
||||
comctl32
|
||||
)
|
||||
|
||||
244
thermion_dart/extras/windows/thermion_window.cpp
Normal file
244
thermion_dart/extras/windows/thermion_window.cpp
Normal file
@@ -0,0 +1,244 @@
|
||||
#include "thermion_window.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
#include <Windows.h>
|
||||
#include <dwmapi.h>
|
||||
#include <ShObjIdl.h>
|
||||
|
||||
#pragma comment(lib, "dwmapi.lib")
|
||||
#pragma comment(lib, "comctl32.lib")
|
||||
|
||||
namespace thermion {
|
||||
|
||||
static constexpr auto kClassName = L"THERMION_WINDOW";
|
||||
static constexpr auto kWindowName = L"thermion_window";
|
||||
static bool was_window_hidden_due_to_minimize_ = false;
|
||||
static WPARAM last_wm_size_wparam_ = SIZE_RESTORED;
|
||||
uint64_t last_thread_time_ = 0;
|
||||
static constexpr auto kNativeViewPositionAndShowDelay = 300;
|
||||
|
||||
typedef enum _WINDOWCOMPOSITIONATTRIB {
|
||||
WCA_UNDEFINED = 0,
|
||||
WCA_NCRENDERING_ENABLED = 1,
|
||||
WCA_NCRENDERING_POLICY = 2,
|
||||
WCA_TRANSITIONS_FORCEDISABLED = 3,
|
||||
WCA_ALLOW_NCPAINT = 4,
|
||||
WCA_CAPTION_BUTTON_BOUNDS = 5,
|
||||
WCA_NONCLIENT_RTL_LAYOUT = 6,
|
||||
WCA_FORCE_ICONIC_REPRESENTATION = 7,
|
||||
WCA_EXTENDED_FRAME_BOUNDS = 8,
|
||||
WCA_HAS_ICONIC_BITMAP = 9,
|
||||
WCA_THEME_ATTRIBUTES = 10,
|
||||
WCA_NCRENDERING_EXILED = 11,
|
||||
WCA_NCADORNMENTINFO = 12,
|
||||
WCA_EXCLUDED_FROM_LIVEPREVIEW = 13,
|
||||
WCA_VIDEO_OVERLAY_ACTIVE = 14,
|
||||
WCA_FORCE_ACTIVEWINDOW_APPEARANCE = 15,
|
||||
WCA_DISALLOW_PEEK = 16,
|
||||
WCA_CLOAK = 17,
|
||||
WCA_CLOAKED = 18,
|
||||
WCA_ACCENT_POLICY = 19,
|
||||
WCA_FREEZE_REPRESENTATION = 20,
|
||||
WCA_EVER_UNCLOAKED = 21,
|
||||
WCA_VISUAL_OWNER = 22,
|
||||
WCA_HOLOGRAPHIC = 23,
|
||||
WCA_EXCLUDED_FROM_DDA = 24,
|
||||
WCA_PASSIVEUPDATEMODE = 25,
|
||||
WCA_USEDARKMODECOLORS = 26,
|
||||
WCA_LAST = 27
|
||||
} WINDOWCOMPOSITIONATTRIB;
|
||||
|
||||
typedef struct _WINDOWCOMPOSITIONATTRIBDATA {
|
||||
WINDOWCOMPOSITIONATTRIB Attrib;
|
||||
PVOID pvData;
|
||||
SIZE_T cbData;
|
||||
} WINDOWCOMPOSITIONATTRIBDATA;
|
||||
|
||||
typedef enum _ACCENT_STATE {
|
||||
ACCENT_DISABLED = 0,
|
||||
ACCENT_ENABLE_GRADIENT = 1,
|
||||
ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
|
||||
ACCENT_ENABLE_BLURBEHIND = 3,
|
||||
ACCENT_ENABLE_ACRYLICBLURBEHIND = 4,
|
||||
ACCENT_ENABLE_HOSTBACKDROP = 5,
|
||||
ACCENT_INVALID_STATE = 6
|
||||
} ACCENT_STATE;
|
||||
|
||||
typedef struct _ACCENT_POLICY {
|
||||
ACCENT_STATE AccentState;
|
||||
DWORD AccentFlags;
|
||||
DWORD GradientColor;
|
||||
DWORD AnimationId;
|
||||
} ACCENT_POLICY;
|
||||
|
||||
typedef BOOL(WINAPI* _GetWindowCompositionAttribute)(
|
||||
HWND, WINDOWCOMPOSITIONATTRIBDATA*);
|
||||
typedef BOOL(WINAPI* _SetWindowCompositionAttribute)(
|
||||
HWND, WINDOWCOMPOSITIONATTRIBDATA*);
|
||||
|
||||
static _SetWindowCompositionAttribute g_set_window_composition_attribute = NULL;
|
||||
static bool g_set_window_composition_attribute_initialized = false;
|
||||
|
||||
typedef LONG NTSTATUS, *PNTSTATUS;
|
||||
#define STATUS_SUCCESS (0x00000000)
|
||||
|
||||
typedef NTSTATUS(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
|
||||
|
||||
RTL_OSVERSIONINFOW GetWindowsVersion() {
|
||||
HMODULE hmodule = ::GetModuleHandleW(L"ntdll.dll");
|
||||
if (hmodule) {
|
||||
RtlGetVersionPtr rtl_get_version_ptr =
|
||||
(RtlGetVersionPtr)::GetProcAddress(hmodule, "RtlGetVersion");
|
||||
if (rtl_get_version_ptr != nullptr) {
|
||||
RTL_OSVERSIONINFOW rovi = {0};
|
||||
rovi.dwOSVersionInfoSize = sizeof(rovi);
|
||||
if (STATUS_SUCCESS == rtl_get_version_ptr(&rovi)) {
|
||||
return rovi;
|
||||
}
|
||||
}
|
||||
}
|
||||
RTL_OSVERSIONINFOW rovi = {0};
|
||||
return rovi;
|
||||
}
|
||||
|
||||
void SetWindowComposition(HWND window, int32_t accent_state,
|
||||
int32_t gradient_color) {
|
||||
// TODO: Look for a better available API.
|
||||
if (GetWindowsVersion().dwBuildNumber >= 18362) {
|
||||
if (!g_set_window_composition_attribute_initialized) {
|
||||
auto user32 = ::GetModuleHandleA("user32.dll");
|
||||
if (user32) {
|
||||
g_set_window_composition_attribute =
|
||||
reinterpret_cast<_SetWindowCompositionAttribute>(
|
||||
::GetProcAddress(user32, "SetWindowCompositionAttribute"));
|
||||
if (g_set_window_composition_attribute) {
|
||||
g_set_window_composition_attribute_initialized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
ACCENT_POLICY accent = {static_cast<ACCENT_STATE>(accent_state), 2,
|
||||
static_cast<DWORD>(gradient_color), 0};
|
||||
WINDOWCOMPOSITIONATTRIBDATA data;
|
||||
data.Attrib = WCA_ACCENT_POLICY;
|
||||
data.pvData = &accent;
|
||||
data.cbData = sizeof(accent);
|
||||
g_set_window_composition_attribute(window, &data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LRESULT CALLBACK FilamentWindowProc(HWND const window, UINT const message,
|
||||
WPARAM const wparam,
|
||||
LPARAM const lparam) noexcept {
|
||||
switch (message) {
|
||||
std::cout << message <<std::endl;
|
||||
case WM_MOUSEMOVE: {
|
||||
TRACKMOUSEEVENT event;
|
||||
event.cbSize = sizeof(event);
|
||||
event.hwndTrack = window;
|
||||
event.dwFlags = TME_HOVER;
|
||||
event.dwHoverTime = 200;
|
||||
auto user_data = ::GetWindowLongPtr(window, GWLP_USERDATA);
|
||||
if (user_data) {
|
||||
HWND flutterRootWindow = reinterpret_cast<HWND>(user_data);
|
||||
::SetForegroundWindow(flutterRootWindow);
|
||||
LONG ex_style = ::GetWindowLong(flutterRootWindow, GWL_EXSTYLE);
|
||||
ex_style &= ~(WS_EX_TRANSPARENT | WS_EX_LAYERED);
|
||||
::SetWindowLong(flutterRootWindow, GWL_EXSTYLE, ex_style);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_ERASEBKGND: {
|
||||
HDC hdc = (HDC)wparam;
|
||||
RECT rect;
|
||||
GetClientRect(window, &rect);
|
||||
|
||||
// Get the ThermionWindow instance associated with this window
|
||||
ThermionWindow* thermionWindow = reinterpret_cast<ThermionWindow*>(
|
||||
GetWindowLongPtr(window, GWLP_USERDATA));
|
||||
|
||||
if (thermionWindow) {
|
||||
HBRUSH brush = CreateSolidBrush(RGB(0, 0, 255));
|
||||
FillRect(hdc, &rect, brush);
|
||||
DeleteObject(brush);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case WM_SIZE:
|
||||
break;
|
||||
case WM_MOVE:
|
||||
case WM_MOVING:
|
||||
case WM_ACTIVATE:
|
||||
case WM_WINDOWPOSCHANGED: {
|
||||
// NativeViewCore::GetInstance()->SetHitTestBehavior(0);
|
||||
auto user_data = ::GetWindowLongPtr(window, GWLP_USERDATA);
|
||||
if (user_data) {
|
||||
HWND flutterRootWindow = reinterpret_cast<HWND>(user_data);
|
||||
::SetForegroundWindow(flutterRootWindow);
|
||||
// NativeViewCore::GetInstance()->SetHitTestBehavior(0);
|
||||
LONG ex_style = ::GetWindowLong(flutterRootWindow, GWL_EXSTYLE);
|
||||
ex_style &= ~(WS_EX_TRANSPARENT | WS_EX_LAYERED);
|
||||
::SetWindowLong(flutterRootWindow, GWL_EXSTYLE, ex_style);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ::DefWindowProc(window, message, wparam, lparam);
|
||||
}
|
||||
|
||||
ThermionWindow::ThermionWindow(int width,
|
||||
int height,
|
||||
int left,
|
||||
int top) : _width(width), _height(height), _left(left), _top(top) {
|
||||
// create the HWND for Filament
|
||||
auto window_class = WNDCLASSEX{};
|
||||
::SecureZeroMemory(&window_class, sizeof(window_class));
|
||||
window_class.cbSize = sizeof(window_class);
|
||||
window_class.style = CS_HREDRAW | CS_VREDRAW;
|
||||
window_class.lpfnWndProc = FilamentWindowProc;
|
||||
window_class.hInstance = 0;
|
||||
window_class.lpszClassName = kClassName;
|
||||
window_class.hCursor = ::LoadCursorW(nullptr, IDC_ARROW);
|
||||
window_class.hbrBackground = ::CreateSolidBrush(RGB(0,255,0));
|
||||
::RegisterClassExW(&window_class);
|
||||
_windowHandle = ::CreateWindow(kClassName, kWindowName, WS_OVERLAPPEDWINDOW,
|
||||
0, 0, _width, _height, nullptr,
|
||||
nullptr, GetModuleHandle(nullptr), nullptr);
|
||||
|
||||
// Disable DWM animations
|
||||
auto disable_window_transitions = TRUE;
|
||||
DwmSetWindowAttribute(_windowHandle, DWMWA_TRANSITIONS_FORCEDISABLED,
|
||||
&disable_window_transitions,
|
||||
sizeof(disable_window_transitions));
|
||||
|
||||
auto style = ::GetWindowLong(_windowHandle, GWL_STYLE);
|
||||
style &= ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX |
|
||||
WS_EX_APPWINDOW);
|
||||
::SetWindowLong(_windowHandle, GWL_STYLE, style);
|
||||
|
||||
// // remove taskbar entry for the window we created
|
||||
// ITaskbarList3* taskbar = nullptr;
|
||||
// ::CoCreateInstance(CLSID_TaskbarList, 0, CLSCTX_INPROC_SERVER,
|
||||
// IID_PPV_ARGS(&taskbar));
|
||||
// taskbar->DeleteTab(_windowHandle);
|
||||
// taskbar->Release();
|
||||
::ShowWindow(_windowHandle, SW_SHOW);
|
||||
UpdateWindow(_windowHandle);
|
||||
}
|
||||
|
||||
void ThermionWindow::Resize(int width, int height, int left, int top) {
|
||||
_width = width;
|
||||
_height = height;
|
||||
_left = left;
|
||||
_top = top;
|
||||
}
|
||||
|
||||
HWND ThermionWindow::GetHandle() { return _windowHandle; }
|
||||
} // namespace thermion_flutter
|
||||
57
thermion_dart/extras/windows/thermion_window.h
Normal file
57
thermion_dart/extras/windows/thermion_window.h
Normal file
@@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef IS_DLL
|
||||
#define EMSCRIPTEN_KEEPALIVE __declspec(dllimport)
|
||||
#else
|
||||
#define EMSCRIPTEN_KEEPALIVE __declspec(dllexport)
|
||||
#endif
|
||||
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <Windows.h>
|
||||
|
||||
namespace thermion {
|
||||
|
||||
///
|
||||
/// Instantiating a ThermionWindow creates a HWND that can be passed
|
||||
/// to Filament to create a swapchain.
|
||||
///
|
||||
///
|
||||
class ThermionWindow {
|
||||
public:
|
||||
ThermionWindow(
|
||||
int width,
|
||||
int height,
|
||||
int left,
|
||||
int top);
|
||||
HWND GetHandle();
|
||||
void Resize(int width, int height, int left, int top);
|
||||
private:
|
||||
HWND _windowHandle;
|
||||
uint32_t _width = 0;
|
||||
uint32_t _height = 0;
|
||||
uint32_t _left = 0;
|
||||
uint32_t _top = 0;
|
||||
};
|
||||
|
||||
static ThermionWindow* _window;
|
||||
|
||||
extern "C" {
|
||||
EMSCRIPTEN_KEEPALIVE intptr_t create_thermion_window(int width, int height, int left, int top) {
|
||||
_window = new ThermionWindow(width, height, left, top);
|
||||
return (intptr_t)_window->GetHandle();
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void update() {
|
||||
MSG msg;
|
||||
if(GetMessage(&msg, NULL, 0, 0))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -32,19 +32,14 @@ void main(List<String> args) async {
|
||||
final name = "thermion_dart.dart";
|
||||
final libUri = config.outputDirectory
|
||||
.resolve(config.targetOS.libraryFileName(name, linkMode));
|
||||
output.addAssets(
|
||||
[
|
||||
NativeCodeAsset(
|
||||
package: config.packageName,
|
||||
name: name,
|
||||
file: libUri,
|
||||
linkMode: linkMode,
|
||||
os: config.targetOS,
|
||||
architecture: config.dryRun ? null : config.targetArchitecture,
|
||||
)
|
||||
],
|
||||
linkInPackage: null,
|
||||
);
|
||||
output.addAsset(NativeCodeAsset(
|
||||
package: config.packageName,
|
||||
name: name,
|
||||
file: libUri,
|
||||
linkMode: linkMode,
|
||||
os: config.targetOS,
|
||||
architecture: config.dryRun ? null : config.targetArchitecture,
|
||||
));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -58,7 +53,7 @@ void main(List<String> args) async {
|
||||
.map((f) => f.path)
|
||||
.toList();
|
||||
sources.addAll([
|
||||
"${config.packageRoot.toFilePath()}/native/include/material/gizmo.c",
|
||||
"${config.packageRoot.toFilePath()}/native/include/material/gizmo_material.c",
|
||||
"${config.packageRoot.toFilePath()}/native/include/material/image.c",
|
||||
"${config.packageRoot.toFilePath()}/native/include/material/grid.c",
|
||||
"${config.packageRoot.toFilePath()}/native/include/material/unlit.c",
|
||||
@@ -92,7 +87,6 @@ void main(List<String> args) async {
|
||||
"basis_transcoder"
|
||||
];
|
||||
|
||||
|
||||
if (platform == "windows") {
|
||||
libDir = Directory(libDir).uri.toFilePath();
|
||||
libs = libs.map((lib) => "${libDir}${lib}.lib").toList();
|
||||
@@ -118,7 +112,12 @@ void main(List<String> args) async {
|
||||
defines["WIN32"] = "1";
|
||||
defines["_DEBUG"] = "1";
|
||||
defines["_DLL"] = "1";
|
||||
flags.addAll(["/std:c++20", "/MDd"]);
|
||||
flags.addAll([
|
||||
"/std:c++20",
|
||||
"/MDd",
|
||||
"/VERBOSE",
|
||||
...defines.keys.map((k) => "/D$k=${defines[k]}").toList()
|
||||
]);
|
||||
}
|
||||
|
||||
if (platform == "ios") {
|
||||
@@ -149,16 +148,26 @@ void main(List<String> args) async {
|
||||
name: packageName,
|
||||
language: Language.cpp,
|
||||
assetName: 'thermion_dart.dart',
|
||||
sources: sources,
|
||||
includes: ['native/include', 'native/include/filament'],
|
||||
defines: defines,
|
||||
sources: platform == "windows" ? [] : sources,
|
||||
includes: platform == "windows"
|
||||
? []
|
||||
: ['native/include', 'native/include/filament'],
|
||||
defines: platform == "windows" ? {} : defines,
|
||||
flags: [
|
||||
if (platform == "macos") '-mmacosx-version-min=13.0',
|
||||
if (platform == "ios") '-mios-version-min=13.0',
|
||||
...flags,
|
||||
...frameworks,
|
||||
...libs.map((lib) => "-l$lib"),
|
||||
"-L$libDir",
|
||||
if (platform != "windows") ...libs.map((lib) => "-l$lib"),
|
||||
if (platform != "windows") "-L$libDir",
|
||||
if (platform == "windows") ...[
|
||||
"/I${config.packageRoot.toFilePath()}\\native\\include",
|
||||
"/I${config.packageRoot.toFilePath()}native\\include\\filament",
|
||||
...sources,
|
||||
'/link',
|
||||
"/LIBPATH:$libDir",
|
||||
'/DLL',
|
||||
]
|
||||
],
|
||||
dartBuildFiles: ['hook/build.dart'],
|
||||
);
|
||||
@@ -177,17 +186,24 @@ void main(List<String> args) async {
|
||||
Architecture.ia32 => "i686-linux-android",
|
||||
_ => throw FormatException('Invalid')
|
||||
};
|
||||
|
||||
|
||||
var compilerPath = config.cCompiler.compiler!.path;
|
||||
|
||||
if(Platform.isWindows && compilerPath.startsWith("/")) {
|
||||
|
||||
if (Platform.isWindows && compilerPath.startsWith("/")) {
|
||||
compilerPath = compilerPath.substring(1);
|
||||
}
|
||||
|
||||
var ndkRoot = File(compilerPath).parent.parent.uri.toFilePath(windows:true);
|
||||
|
||||
var stlPath =
|
||||
File([ndkRoot, "sysroot", "usr", "lib", archExtension, "libc++_shared.so"].join(Platform.pathSeparator));
|
||||
var ndkRoot =
|
||||
File(compilerPath).parent.parent.uri.toFilePath(windows: true);
|
||||
|
||||
var stlPath = File([
|
||||
ndkRoot,
|
||||
"sysroot",
|
||||
"usr",
|
||||
"lib",
|
||||
archExtension,
|
||||
"libc++_shared.so"
|
||||
].join(Platform.pathSeparator));
|
||||
output.addAsset(NativeCodeAsset(
|
||||
package: "thermion_dart",
|
||||
name: "libc++_shared.so",
|
||||
@@ -201,7 +217,7 @@ void main(List<String> args) async {
|
||||
if (config.targetOS == "windows") {
|
||||
output.addAsset(
|
||||
NativeCodeAsset(
|
||||
package: "thermion_dart",
|
||||
package: config.packageName,
|
||||
name: "thermion_dart.dll",
|
||||
linkMode: DynamicLoadingBundled(),
|
||||
os: config.targetOS,
|
||||
|
||||
@@ -3,4 +3,5 @@ library;
|
||||
export 'src/input_handler.dart';
|
||||
export 'src/delegates.dart';
|
||||
export 'src/delegate_gesture_handler.dart';
|
||||
export 'src/implementations/default_pick_delegate.dart';
|
||||
export 'src/implementations/third_person_camera_delegate.dart';
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'dart:async';
|
||||
import 'dart:math';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:thermion_dart/thermion_dart.dart';
|
||||
import 'package:vector_math/vector_math_64.dart';
|
||||
@@ -10,9 +11,11 @@ class DelegateInputHandler implements InputHandler {
|
||||
final ThermionViewer viewer;
|
||||
|
||||
Stream<List<InputType>> get gestures => _gesturesController.stream;
|
||||
|
||||
final _gesturesController = StreamController<List<InputType>>.broadcast();
|
||||
|
||||
Stream get cameraUpdated => _cameraUpdatedController.stream;
|
||||
final _cameraUpdatedController = StreamController.broadcast();
|
||||
|
||||
final _logger = Logger("DelegateInputHandler");
|
||||
|
||||
InputHandlerDelegate? transformDelegate;
|
||||
@@ -24,6 +27,8 @@ class DelegateInputHandler implements InputHandler {
|
||||
|
||||
Map<InputType, InputAction> _actions = {
|
||||
InputType.LMB_HOLD_AND_MOVE: InputAction.TRANSLATE,
|
||||
InputType.SCALE1: InputAction.TRANSLATE,
|
||||
InputType.SCALE2: InputAction.ZOOM,
|
||||
InputType.MMB_HOLD_AND_MOVE: InputAction.ROTATE,
|
||||
InputType.SCROLLWHEEL: InputAction.TRANSLATE,
|
||||
InputType.POINTER_MOVE: InputAction.NONE,
|
||||
@@ -75,13 +80,20 @@ class DelegateInputHandler implements InputHandler {
|
||||
factory DelegateInputHandler.flight(ThermionViewer viewer,
|
||||
{PickDelegate? pickDelegate,
|
||||
bool freeLook = false,
|
||||
double panSensitivity = 0.1,
|
||||
double movementSensitivity = 0.1,
|
||||
double rotateSensitivity = 0.01,
|
||||
double? clampY,
|
||||
ThermionEntity? entity}) =>
|
||||
DelegateInputHandler(
|
||||
viewer: viewer,
|
||||
pickDelegate: pickDelegate,
|
||||
transformDelegate: FreeFlightInputHandlerDelegate(viewer,
|
||||
clampY: clampY, entity: entity),
|
||||
clampY: clampY,
|
||||
entity: entity,
|
||||
rotationSensitivity: rotateSensitivity,
|
||||
panSensitivity: panSensitivity,
|
||||
movementSensitivity: movementSensitivity),
|
||||
actions: {
|
||||
InputType.MMB_HOLD_AND_MOVE: InputAction.ROTATE,
|
||||
InputType.SCROLLWHEEL: InputAction.TRANSLATE,
|
||||
@@ -90,6 +102,8 @@ class DelegateInputHandler implements InputHandler {
|
||||
InputType.KEYDOWN_W: InputAction.TRANSLATE,
|
||||
InputType.KEYDOWN_S: InputAction.TRANSLATE,
|
||||
InputType.KEYDOWN_D: InputAction.TRANSLATE,
|
||||
InputType.SCALE1: InputAction.TRANSLATE,
|
||||
InputType.SCALE2: InputAction.ZOOM,
|
||||
if (freeLook) InputType.POINTER_MOVE: InputAction.ROTATE,
|
||||
});
|
||||
|
||||
@@ -134,6 +148,7 @@ class DelegateInputHandler implements InputHandler {
|
||||
break;
|
||||
}
|
||||
|
||||
// ignore: unnecessary_null_comparison
|
||||
if (keyType != null) {
|
||||
keyAction = _actions[keyType];
|
||||
|
||||
@@ -150,10 +165,11 @@ class DelegateInputHandler implements InputHandler {
|
||||
|
||||
await transformDelegate?.execute();
|
||||
var updates = _inputDeltas.keys.followedBy(keyTypes).toList();
|
||||
if(updates.isNotEmpty) {
|
||||
if (updates.isNotEmpty) {
|
||||
_gesturesController.add(updates);
|
||||
_cameraUpdatedController.add(true);
|
||||
}
|
||||
|
||||
|
||||
_inputDeltas.clear();
|
||||
_processing = false;
|
||||
}
|
||||
@@ -224,15 +240,6 @@ class DelegateInputHandler implements InputHandler {
|
||||
@override
|
||||
Future<bool> get initialized => viewer.initialized;
|
||||
|
||||
@override
|
||||
Future<void> onScaleEnd() async {}
|
||||
|
||||
@override
|
||||
Future<void> onScaleStart() async {}
|
||||
|
||||
@override
|
||||
Future<void> onScaleUpdate() async {}
|
||||
|
||||
@override
|
||||
void setActionForType(InputType gestureType, InputAction gestureAction) {
|
||||
_actions[gestureType] = gestureAction;
|
||||
@@ -250,4 +257,26 @@ class DelegateInputHandler implements InputHandler {
|
||||
void keyUp(PhysicalKey key) {
|
||||
_pressedKeys.remove(key);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> onScaleEnd(int pointerCount) async {}
|
||||
|
||||
@override
|
||||
Future<void> onScaleStart(Vector2 localPosition, int pointerCount) async {
|
||||
// noop
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> onScaleUpdate(Vector2 focalPoint, Vector2 focalPointDelta,
|
||||
double horizontalScale, double verticalScale, double scale, int pointerCount) async {
|
||||
if (pointerCount == 1) {
|
||||
_inputDeltas[InputType.SCALE1] =
|
||||
Vector3(focalPointDelta.x, focalPointDelta.y, 0);
|
||||
} else if (pointerCount == 2) {
|
||||
_inputDeltas[InputType.SCALE2] =
|
||||
Vector3(0, 0, max(horizontalScale, verticalScale));
|
||||
} else {
|
||||
throw UnimplementedError("Only pointerCount <= 2 supported");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import 'package:thermion_dart/thermion_dart.dart';
|
||||
import 'package:vector_math/vector_math_64.dart';
|
||||
|
||||
class DefaultPickDelegate extends PickDelegate {
|
||||
final ThermionViewer viewer;
|
||||
|
||||
const DefaultPickDelegate(this.viewer);
|
||||
|
||||
@override
|
||||
void pick(Vector2 location) {
|
||||
viewer.pick(location.x.toInt(), location.y.toInt());
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,6 @@ import '../../../viewer/src/shared_types/camera.dart';
|
||||
import '../../../viewer/viewer.dart';
|
||||
import '../../input.dart';
|
||||
import '../input_handler.dart';
|
||||
import 'dart:math';
|
||||
|
||||
class FixedOrbitRotateInputHandlerDelegate implements InputHandlerDelegate {
|
||||
final ThermionViewer viewer;
|
||||
@@ -46,15 +45,16 @@ class FixedOrbitRotateInputHandlerDelegate implements InputHandlerDelegate {
|
||||
_queuedRotationDelta += Vector2(delta.x, delta.y);
|
||||
break;
|
||||
case InputAction.TRANSLATE:
|
||||
_queuedZoomDelta += delta!.z;
|
||||
_queuedZoomDelta += delta.z;
|
||||
break;
|
||||
case InputAction.PICK:
|
||||
// Assuming PICK is used for zoom in this context
|
||||
_queuedZoomDelta += delta.z;
|
||||
break;
|
||||
case InputAction.NONE:
|
||||
// Do nothing
|
||||
break;
|
||||
case InputAction.ZOOM:
|
||||
_queuedZoomDelta += delta.z;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ class FreeFlightInputHandlerDelegate implements InputHandlerDelegate {
|
||||
static final Vector3 _right = Vector3(1, 0, 0);
|
||||
|
||||
Vector2 _queuedRotationDelta = Vector2.zero();
|
||||
Vector2 _queuedPanDelta = Vector2.zero();
|
||||
Vector3 _queuedTranslateDelta = Vector3.zero();
|
||||
double _queuedZoomDelta = 0.0;
|
||||
Vector3 _queuedMoveDelta = Vector3.zero();
|
||||
|
||||
@@ -49,14 +49,16 @@ class FreeFlightInputHandlerDelegate implements InputHandlerDelegate {
|
||||
_queuedRotationDelta += Vector2(delta.x, delta.y);
|
||||
break;
|
||||
case InputAction.TRANSLATE:
|
||||
_queuedPanDelta += Vector2(delta.x, delta.y);
|
||||
_queuedZoomDelta += delta.z;
|
||||
_queuedTranslateDelta += delta;
|
||||
break;
|
||||
case InputAction.PICK:
|
||||
_queuedZoomDelta += delta.z;
|
||||
break;
|
||||
case InputAction.NONE:
|
||||
break;
|
||||
case InputAction.ZOOM:
|
||||
_queuedZoomDelta += delta.z;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +73,7 @@ class FreeFlightInputHandlerDelegate implements InputHandlerDelegate {
|
||||
_executing = true;
|
||||
|
||||
if (_queuedRotationDelta.length2 == 0.0 &&
|
||||
_queuedPanDelta.length2 == 0.0 &&
|
||||
_queuedTranslateDelta.length2 == 0.0 &&
|
||||
_queuedZoomDelta == 0.0 &&
|
||||
_queuedMoveDelta.length2 == 0.0) {
|
||||
_executing = false;
|
||||
@@ -79,9 +81,9 @@ class FreeFlightInputHandlerDelegate implements InputHandlerDelegate {
|
||||
}
|
||||
|
||||
final activeCamera = await viewer.getActiveCamera();
|
||||
Matrix4 currentViewMatrix = await activeCamera.getViewMatrix();
|
||||
|
||||
Matrix4 currentTransform = await viewer.getLocalTransform(await entity);
|
||||
Vector3 currentPosition = currentTransform.getTranslation();
|
||||
|
||||
Quaternion currentRotation =
|
||||
Quaternion.fromRotation(currentTransform.getRotation());
|
||||
|
||||
@@ -92,10 +94,8 @@ class FreeFlightInputHandlerDelegate implements InputHandlerDelegate {
|
||||
|
||||
// Apply rotation
|
||||
if (_queuedRotationDelta.length2 > 0.0) {
|
||||
double deltaX =
|
||||
_queuedRotationDelta.x * rotationSensitivity;
|
||||
double deltaY =
|
||||
_queuedRotationDelta.y * rotationSensitivity;
|
||||
double deltaX = _queuedRotationDelta.x * rotationSensitivity;
|
||||
double deltaY = _queuedRotationDelta.y * rotationSensitivity;
|
||||
|
||||
Quaternion yawRotation = Quaternion.axisAngle(_up, -deltaX);
|
||||
Quaternion pitchRotation = Quaternion.axisAngle(_right, -deltaY);
|
||||
@@ -105,15 +105,13 @@ class FreeFlightInputHandlerDelegate implements InputHandlerDelegate {
|
||||
}
|
||||
|
||||
// Apply pan
|
||||
if (_queuedPanDelta.length2 > 0.0) {
|
||||
Vector3 right = _right.clone()..applyQuaternion(currentRotation);
|
||||
Vector3 up = _up.clone()..applyQuaternion(currentRotation);
|
||||
if (_queuedTranslateDelta.length2 > 0.0) {
|
||||
double deltaX = _queuedTranslateDelta.x * panSensitivity;
|
||||
double deltaY = _queuedTranslateDelta.y * panSensitivity;
|
||||
double deltaZ = -_queuedTranslateDelta.z * panSensitivity;
|
||||
|
||||
double deltaX = _queuedPanDelta.x * panSensitivity;
|
||||
double deltaY = _queuedPanDelta.y * panSensitivity;
|
||||
|
||||
relativeTranslation += right * deltaX + up * deltaY;
|
||||
_queuedPanDelta = Vector2.zero();
|
||||
relativeTranslation += _right * deltaX + _up * deltaY + _forward * deltaZ;
|
||||
_queuedTranslateDelta = Vector3.zero();
|
||||
}
|
||||
|
||||
// Apply zoom
|
||||
@@ -129,9 +127,10 @@ class FreeFlightInputHandlerDelegate implements InputHandlerDelegate {
|
||||
Vector3 right = _right.clone()..applyQuaternion(currentRotation);
|
||||
Vector3 up = _up.clone()..applyQuaternion(currentRotation);
|
||||
|
||||
relativeTranslation += right * _queuedMoveDelta.x +
|
||||
up * _queuedMoveDelta.y +
|
||||
forward * _queuedMoveDelta.z;
|
||||
relativeTranslation += (right * _queuedMoveDelta.x +
|
||||
up * _queuedMoveDelta.y +
|
||||
forward * _queuedMoveDelta.z) *
|
||||
movementSensitivity;
|
||||
|
||||
_queuedMoveDelta = Vector3.zero();
|
||||
}
|
||||
|
||||
@@ -56,6 +56,8 @@ class OverTheShoulderCameraDelegate implements InputHandlerDelegate {
|
||||
break;
|
||||
case InputAction.NONE:
|
||||
break;
|
||||
case InputAction.ZOOM:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,10 +24,10 @@ enum InputType {
|
||||
|
||||
enum PhysicalKey { W, A, S, D }
|
||||
|
||||
enum InputAction { TRANSLATE, ROTATE, PICK, NONE }
|
||||
enum InputAction { TRANSLATE, ROTATE, PICK, ZOOM, NONE }
|
||||
|
||||
abstract class InputHandler {
|
||||
Stream<List<InputType>> get gestures;
|
||||
Stream get cameraUpdated;
|
||||
|
||||
Future<void> onPointerHover(Vector2 localPosition, Vector2 delta);
|
||||
Future<void> onPointerScroll(Vector2 localPosition, double scrollDelta);
|
||||
@@ -35,9 +35,9 @@ abstract class InputHandler {
|
||||
Future<void> onPointerMove(
|
||||
Vector2 localPosition, Vector2 delta, bool isMiddle);
|
||||
Future<void> onPointerUp(bool isMiddle);
|
||||
Future<void> onScaleStart();
|
||||
Future<void> onScaleUpdate();
|
||||
Future<void> onScaleEnd();
|
||||
Future<void> onScaleStart(Vector2 focalPoint, int pointerCount);
|
||||
Future<void> onScaleUpdate(Vector2 focalPoint, Vector2 focalPointDelta, double horizontalScale, double verticalScale, double scale, int pointerCount);
|
||||
Future<void> onScaleEnd(int pointerCount);
|
||||
Future<bool> get initialized;
|
||||
Future dispose();
|
||||
|
||||
|
||||
44
thermion_dart/lib/src/utils/src/axis.dart
Normal file
44
thermion_dart/lib/src/utils/src/axis.dart
Normal file
@@ -0,0 +1,44 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:vector_math/vector_math_64.dart';
|
||||
|
||||
import '../../viewer/viewer.dart';
|
||||
|
||||
class Axis {
|
||||
final ThermionViewer _viewer;
|
||||
final ThermionEntity xAxis;
|
||||
final ThermionEntity yAxis;
|
||||
final ThermionEntity zAxis;
|
||||
|
||||
Axis._(this.xAxis, this.yAxis, this.zAxis, this._viewer);
|
||||
|
||||
static Future<Axis> create(ThermionViewer viewer) async {
|
||||
final xAxis = await viewer!.createGeometry(
|
||||
Geometry(Float32List.fromList([0, 0, 0, 10, 0, 0]), [0, 1],
|
||||
primitiveType: PrimitiveType.LINES),
|
||||
materialInstance: await viewer!.createUnlitMaterialInstance());
|
||||
final yAxis = await viewer!.createGeometry(
|
||||
Geometry(Float32List.fromList([0, 0, 0, 0, 10, 0]), [0, 1],
|
||||
primitiveType: PrimitiveType.LINES),
|
||||
materialInstance: await viewer!.createUnlitMaterialInstance());
|
||||
final zAxis = await viewer!.createGeometry(
|
||||
Geometry(Float32List.fromList([0, 0, 0, 0, 0, 10]), [0, 1],
|
||||
primitiveType: PrimitiveType.LINES),
|
||||
materialInstance: await viewer!.createUnlitMaterialInstance());
|
||||
|
||||
await viewer!.setMaterialPropertyFloat4(
|
||||
xAxis, "baseColorFactor", 0, 1.0, 0.0, 0.0, 1.0);
|
||||
await viewer!.setMaterialPropertyFloat4(
|
||||
yAxis, "baseColorFactor", 0, 0.0, 1.0, 0.0, 1.0);
|
||||
await viewer!.setMaterialPropertyFloat4(
|
||||
zAxis, "baseColorFactor", 0, 0.0, 0.0, 1.0, 1.0);
|
||||
return Axis._(xAxis, yAxis, zAxis, viewer);
|
||||
}
|
||||
|
||||
Future setTransform(Matrix4 transform) async {
|
||||
await _viewer.setTransform(xAxis, transform);
|
||||
await _viewer.setTransform(yAxis, transform);
|
||||
await _viewer.setTransform(zAxis, transform);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import 'dart:io';
|
||||
|
||||
import 'package:ffi/ffi.dart';
|
||||
|
||||
import '../viewer/src/ffi/src/thermion_dart.g.dart';
|
||||
import '../../viewer/src/ffi/src/thermion_dart.g.dart';
|
||||
|
||||
class DartResourceLoader {
|
||||
static final _assets = <int, Pointer>{};
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'dart:math';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import '../../thermion_dart.dart';
|
||||
import '../../../thermion_dart.dart';
|
||||
|
||||
class GeometryHelper {
|
||||
static Geometry sphere({bool normals = true, bool uvs = true}) {
|
||||
4
thermion_dart/lib/src/utils/utils.dart
Normal file
4
thermion_dart/lib/src/utils/utils.dart
Normal file
@@ -0,0 +1,4 @@
|
||||
library;
|
||||
|
||||
export 'src/geometry.dart';
|
||||
export 'src/axis.dart';
|
||||
@@ -2,7 +2,7 @@ import 'dart:ffi';
|
||||
|
||||
import 'package:vector_math/vector_math_64.dart';
|
||||
|
||||
import '../../../../utils/matrix.dart';
|
||||
import '../../../../utils/src/matrix.dart';
|
||||
import '../../thermion_viewer_base.dart';
|
||||
import 'thermion_dart.g.dart' as g;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import 'dart:ffi';
|
||||
|
||||
import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_dart.g.dart';
|
||||
|
||||
import '../../../../utils/gizmo.dart';
|
||||
import '../../../../utils/src/gizmo.dart';
|
||||
import '../../../viewer.dart';
|
||||
|
||||
class FFIGizmo extends BaseGizmo {
|
||||
|
||||
@@ -16,16 +16,6 @@ external ffi.Pointer<ffi.Void> make_resource_loader(
|
||||
ffi.Pointer<ffi.Void> owner,
|
||||
);
|
||||
|
||||
@ffi.Native<
|
||||
ffi.Pointer<TViewer> Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
|
||||
ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Char>)>(isLeaf: true)
|
||||
external ffi.Pointer<TViewer> Viewer_create(
|
||||
ffi.Pointer<ffi.Void> context,
|
||||
ffi.Pointer<ffi.Void> loader,
|
||||
ffi.Pointer<ffi.Void> platform,
|
||||
ffi.Pointer<ffi.Char> uberArchivePath,
|
||||
);
|
||||
|
||||
@ffi.Native<ffi.Void Function(ffi.Pointer<TViewer>)>(isLeaf: true)
|
||||
external void destroy_filament_viewer(
|
||||
ffi.Pointer<TViewer> viewer,
|
||||
@@ -152,6 +142,39 @@ external void Viewer_setViewRenderable(
|
||||
bool renderable,
|
||||
);
|
||||
|
||||
@ffi.Native<
|
||||
ffi.Void Function(ffi.Pointer<TViewer>, ffi.Pointer<ffi.Char>, ffi.Float,
|
||||
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(isLeaf: true)
|
||||
external void Viewer_loadIblRenderThread(
|
||||
ffi.Pointer<TViewer> viewer,
|
||||
ffi.Pointer<ffi.Char> iblPath,
|
||||
double intensity,
|
||||
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
|
||||
);
|
||||
|
||||
|
||||
@ffi.Native<
|
||||
ffi.Void Function(
|
||||
ffi.Pointer<TViewer>,
|
||||
ffi.Pointer<TView>,
|
||||
ffi.Int,
|
||||
ffi.Int,
|
||||
ffi.Pointer<
|
||||
ffi.NativeFunction<
|
||||
ffi.Void Function(EntityId entityId, ffi.Int x, ffi.Int y,
|
||||
ffi.Pointer<TView> tView)>>)>(isLeaf: true)
|
||||
external void Viewer_pick(
|
||||
ffi.Pointer<TViewer> viewer,
|
||||
ffi.Pointer<TView> tView,
|
||||
int x,
|
||||
int y,
|
||||
ffi.Pointer<
|
||||
ffi.NativeFunction<
|
||||
ffi.Void Function(EntityId entityId, ffi.Int x, ffi.Int y,
|
||||
ffi.Pointer<TView> tView)>>
|
||||
callback,
|
||||
);
|
||||
|
||||
@ffi.Native<ffi.Pointer<TEngine> Function(ffi.Pointer<TViewer>)>(isLeaf: true)
|
||||
external ffi.Pointer<TEngine> Viewer_getEngine(
|
||||
ffi.Pointer<TViewer> viewer,
|
||||
@@ -398,25 +421,6 @@ external bool set_morph_target_weights(
|
||||
int numWeights,
|
||||
);
|
||||
|
||||
@ffi.Native<
|
||||
ffi.Bool Function(
|
||||
ffi.Pointer<TSceneManager>,
|
||||
EntityId,
|
||||
ffi.Pointer<ffi.Float>,
|
||||
ffi.Pointer<ffi.Int>,
|
||||
ffi.Int,
|
||||
ffi.Int,
|
||||
ffi.Float)>(isLeaf: true)
|
||||
external bool set_morph_animation(
|
||||
ffi.Pointer<TSceneManager> sceneManager,
|
||||
int entity,
|
||||
ffi.Pointer<ffi.Float> morphData,
|
||||
ffi.Pointer<ffi.Int> morphIndices,
|
||||
int numMorphTargets,
|
||||
int numFrames,
|
||||
double frameLengthInMs,
|
||||
);
|
||||
|
||||
@ffi.Native<
|
||||
ffi.Pointer<TMaterialInstance> Function(
|
||||
ffi.Pointer<TSceneManager>, TMaterialKey)>(isLeaf: true)
|
||||
@@ -659,7 +663,7 @@ external ffi.Pointer<TScene> SceneManager_getScene(
|
||||
|
||||
@ffi.Native<
|
||||
EntityId Function(ffi.Pointer<TSceneManager>, ffi.Pointer<ffi.Uint8>,
|
||||
ffi.Size, ffi.Bool, ffi.Int, ffi.Int)>(isLeaf: true)
|
||||
ffi.Size, ffi.Bool, ffi.Int, ffi.Int, ffi.Bool)>(isLeaf: true)
|
||||
external int SceneManager_loadGlbFromBuffer(
|
||||
ffi.Pointer<TSceneManager> sceneManager,
|
||||
ffi.Pointer<ffi.Uint8> arg1,
|
||||
@@ -667,6 +671,26 @@ external int SceneManager_loadGlbFromBuffer(
|
||||
bool keepData,
|
||||
int priority,
|
||||
int layer,
|
||||
bool loadResourcesAsync,
|
||||
);
|
||||
|
||||
@ffi.Native<
|
||||
ffi.Bool Function(
|
||||
ffi.Pointer<TSceneManager>,
|
||||
EntityId,
|
||||
ffi.Pointer<ffi.Float>,
|
||||
ffi.Pointer<ffi.Uint32>,
|
||||
ffi.Int,
|
||||
ffi.Int,
|
||||
ffi.Float)>(isLeaf: true)
|
||||
external bool SceneManager_setMorphAnimation(
|
||||
ffi.Pointer<TSceneManager> sceneManager,
|
||||
int entity,
|
||||
ffi.Pointer<ffi.Float> morphData,
|
||||
ffi.Pointer<ffi.Uint32> morphIndices,
|
||||
int numMorphTargets,
|
||||
int numFrames,
|
||||
double frameLengthInMs,
|
||||
);
|
||||
|
||||
@ffi.Native<ffi.Bool Function(ffi.Pointer<TSceneManager>, EntityId)>(
|
||||
@@ -841,27 +865,6 @@ external int reveal_mesh(
|
||||
ffi.Pointer<ffi.Char> meshName,
|
||||
);
|
||||
|
||||
@ffi.Native<
|
||||
ffi.Void Function(
|
||||
ffi.Pointer<TViewer>,
|
||||
ffi.Pointer<TView>,
|
||||
ffi.Int,
|
||||
ffi.Int,
|
||||
ffi.Pointer<
|
||||
ffi.NativeFunction<
|
||||
ffi.Void Function(
|
||||
EntityId entityId, ffi.Int x, ffi.Int y)>>)>(isLeaf: true)
|
||||
external void filament_pick(
|
||||
ffi.Pointer<TViewer> viewer,
|
||||
ffi.Pointer<TView> tView,
|
||||
int x,
|
||||
int y,
|
||||
ffi.Pointer<
|
||||
ffi.NativeFunction<
|
||||
ffi.Void Function(EntityId entityId, ffi.Int x, ffi.Int y)>>
|
||||
callback,
|
||||
);
|
||||
|
||||
@ffi.Native<
|
||||
ffi.Pointer<ffi.Char> Function(
|
||||
ffi.Pointer<TSceneManager>, EntityId)>(isLeaf: true)
|
||||
@@ -1430,7 +1433,7 @@ external void Viewer_requestFrameRenderThread(
|
||||
external void View_setToneMappingRenderThread(
|
||||
ffi.Pointer<TView> tView,
|
||||
ffi.Pointer<TEngine> tEngine,
|
||||
int arg2,
|
||||
int thermion,
|
||||
);
|
||||
|
||||
@ffi.Native<ffi.Void Function(ffi.Pointer<TView>, ffi.Double)>(isLeaf: true)
|
||||
@@ -1524,6 +1527,7 @@ external void remove_skybox_render_thread(
|
||||
ffi.Bool,
|
||||
ffi.Int,
|
||||
ffi.Int,
|
||||
ffi.Bool,
|
||||
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(EntityId)>>)>(
|
||||
isLeaf: true)
|
||||
external void SceneManager_loadGlbFromBufferRenderThread(
|
||||
@@ -1534,6 +1538,7 @@ external void SceneManager_loadGlbFromBufferRenderThread(
|
||||
bool keepData,
|
||||
int priority,
|
||||
int layer,
|
||||
bool loadResourcesAsync,
|
||||
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(EntityId)>> callback,
|
||||
);
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@ import 'package:animation_tools_dart/animation_tools_dart.dart';
|
||||
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_gizmo.dart';
|
||||
import 'package:vector_math/vector_math_64.dart';
|
||||
import 'package:vector_math/vector_math_64.dart' as v64;
|
||||
import '../../../../utils/gizmo.dart';
|
||||
import '../../../../utils/matrix.dart';
|
||||
import '../../../../utils/src/gizmo.dart';
|
||||
import '../../../../utils/src/matrix.dart';
|
||||
import '../../events.dart';
|
||||
import '../../shared_types/view.dart';
|
||||
import '../../thermion_viewer_base.dart';
|
||||
@@ -83,9 +83,9 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
this._driver = driver ?? nullptr;
|
||||
this._sharedContext = sharedContext ?? nullptr;
|
||||
|
||||
// _onPickResultCallable =
|
||||
// NativeCallable<Void Function(EntityId entityId, Int x, Int y)>.listener(
|
||||
// _onPickResult);
|
||||
_onPickResultCallable =
|
||||
NativeCallable<Void Function(EntityId entityId, Int x, Int y, Pointer<TView> view)>.listener(
|
||||
_onPickResult);
|
||||
|
||||
_initialize();
|
||||
}
|
||||
@@ -360,7 +360,12 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
Future loadIbl(String lightingPath, {double intensity = 30000}) async {
|
||||
final pathPtr =
|
||||
lightingPath.toNativeUtf8(allocator: allocator).cast<Char>();
|
||||
load_ibl(_viewer!, pathPtr, intensity);
|
||||
|
||||
await withVoidCallback((cb) {
|
||||
Viewer_loadIblRenderThread(_viewer!, pathPtr, intensity, cb);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
///
|
||||
@@ -523,8 +528,8 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
throw Exception("Not yet implemented");
|
||||
}
|
||||
final pathPtr = path.toNativeUtf8(allocator: allocator).cast<Char>();
|
||||
var entity = await withIntCallback((callback)=> load_glb_render_thread(
|
||||
_sceneManager!, pathPtr, numInstances, keepData, callback));
|
||||
var entity = await withIntCallback((callback) => load_glb_render_thread(
|
||||
_sceneManager!, pathPtr, numInstances, keepData, callback));
|
||||
|
||||
allocator.free(pathPtr);
|
||||
if (entity == _FILAMENT_ASSET_ERROR) {
|
||||
@@ -546,7 +551,7 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
int numInstances = 1,
|
||||
bool keepData = false,
|
||||
int priority = 4,
|
||||
int layer = 0}) async {
|
||||
int layer = 0, bool loadResourcesAsync=false}) async {
|
||||
if (unlit) {
|
||||
throw Exception("Not yet implemented");
|
||||
}
|
||||
@@ -557,7 +562,7 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
|
||||
var entity = await withIntCallback((callback) =>
|
||||
SceneManager_loadGlbFromBufferRenderThread(_sceneManager!, data.address,
|
||||
data.length, numInstances, keepData, priority, layer, callback));
|
||||
data.length, numInstances, keepData, priority, layer, loadResourcesAsync, callback));
|
||||
|
||||
if (entity == _FILAMENT_ASSET_ERROR) {
|
||||
throw Exception("An error occurred loading GLB from buffer");
|
||||
@@ -729,7 +734,7 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
var meshEntity = meshEntities[i];
|
||||
|
||||
if (targetMeshNames?.contains(meshName) == false) {
|
||||
_logger.info("Skipping $meshName, not contained in target");
|
||||
// _logger.info("Skipping $meshName, not contained in target");
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -749,39 +754,24 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
Child meshes: ${meshNames}""");
|
||||
}
|
||||
|
||||
var indices =
|
||||
intersection.map((m) => meshMorphTargets.indexOf(m)).toList();
|
||||
var indices = Uint32List.fromList(
|
||||
intersection.map((m) => meshMorphTargets.indexOf(m)).toList());
|
||||
|
||||
var frameData = animation.extract(morphTargets: intersection);
|
||||
// var frameData = animation.data;
|
||||
var frameData = animation.subset(intersection);
|
||||
|
||||
assert(frameData.length == animation.numFrames * intersection.length);
|
||||
assert(
|
||||
frameData.data.length == animation.numFrames * intersection.length);
|
||||
|
||||
var dataPtr = allocator<Float>(frameData.length);
|
||||
|
||||
// not currently working on WASM :( wasted a lot of time figuring that out as no error is thrown
|
||||
// dataPtr
|
||||
// .asTypedList(frameData.length)
|
||||
// .setRange(0, frameData.length, frameData);
|
||||
for (int i = 0; i < frameData.length; i++) {
|
||||
dataPtr[i] = frameData[i];
|
||||
}
|
||||
|
||||
final idxPtr = allocator<Int>(indices.length);
|
||||
|
||||
for (int i = 0; i < indices.length; i++) {
|
||||
idxPtr[i] = indices[i];
|
||||
}
|
||||
|
||||
var result = set_morph_animation(
|
||||
var result = SceneManager_setMorphAnimation(
|
||||
_sceneManager!,
|
||||
meshEntity,
|
||||
dataPtr,
|
||||
idxPtr,
|
||||
frameData.data.address,
|
||||
indices.address,
|
||||
indices.length,
|
||||
animation.numFrames,
|
||||
animation.frameLengthInMs);
|
||||
allocator.free(dataPtr);
|
||||
allocator.free(idxPtr);
|
||||
|
||||
if (!result) {
|
||||
throw Exception("Failed to set morph animation data for ${meshName}");
|
||||
}
|
||||
@@ -1484,14 +1474,11 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
final view = FFIView(viewPtr, _viewer!);
|
||||
final viewport = await view.getViewport();
|
||||
|
||||
// _pickResultController.add((
|
||||
// entity: entityId,
|
||||
// x: (x / pixelRatio).toDouble(),
|
||||
// y: (viewport.height - y) / pixelRatio
|
||||
// ));
|
||||
_pickResultController
|
||||
.add((entity: entityId, x: x.ceil(), y: (viewport.height - y).ceil()));
|
||||
}
|
||||
|
||||
late NativeCallable<Void Function(EntityId entityId, Int x, Int y)>
|
||||
late NativeCallable<Void Function(EntityId entityId, Int x, Int y, Pointer<TView> view)>
|
||||
_onPickResultCallable;
|
||||
|
||||
///
|
||||
@@ -1499,11 +1486,11 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
///
|
||||
@override
|
||||
void pick(int x, int y) async {
|
||||
// x = (x * pixelRatio).ceil();
|
||||
// y = (viewportDimensions.$2 - (y * pixelRatio)).ceil();
|
||||
// final view = (await getViewAt(0)) as FFIView;
|
||||
// filament_pick(
|
||||
// _viewer!, view.view, x, y, _onPickResultCallable.nativeFunction);
|
||||
final view = (await getViewAt(0)) as FFIView;
|
||||
var viewport = await view.getViewport();
|
||||
y = (viewport.height - y).ceil();
|
||||
Viewer_pick(
|
||||
_viewer!, view.view, x, y, _onPickResultCallable.nativeFunction);
|
||||
}
|
||||
|
||||
///
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:thermion_dart/src/viewer/src/events.dart';
|
||||
import '../../utils/gizmo.dart';
|
||||
import '../../utils/src/gizmo.dart';
|
||||
import 'shared_types/shared_types.dart';
|
||||
export 'shared_types/shared_types.dart';
|
||||
|
||||
@@ -56,8 +56,10 @@ abstract class ThermionViewer {
|
||||
///
|
||||
/// Render a single frame and copy the pixel buffer to [out].
|
||||
///
|
||||
Future<Uint8List> capture({covariant SwapChain? swapChain,
|
||||
covariant View? view, covariant RenderTarget? renderTarget});
|
||||
Future<Uint8List> capture(
|
||||
{covariant SwapChain? swapChain,
|
||||
covariant View? view,
|
||||
covariant RenderTarget? renderTarget});
|
||||
|
||||
///
|
||||
///
|
||||
@@ -214,12 +216,16 @@ abstract class ThermionViewer {
|
||||
/// Specify [numInstances] to create multiple instances (this is more efficient than dynamically instantating at a later time). You can then retrieve the created instances with [getInstances].
|
||||
/// If you want to be able to call [createInstance] at a later time, you must pass true for [keepData].
|
||||
/// If [keepData] is false, the source glTF data will be released and [createInstance] will throw an exception.
|
||||
/// If [loadResourcesAsync] is true, resources (textures, materials, etc) will
|
||||
/// be loaded asynchronously (so expect some material/texture pop-in);
|
||||
///
|
||||
///
|
||||
Future<ThermionEntity> loadGlbFromBuffer(Uint8List data,
|
||||
{int numInstances = 1,
|
||||
bool keepData = false,
|
||||
int priority = 4,
|
||||
int layer = 0});
|
||||
int layer = 0,
|
||||
bool loadResourcesAsync});
|
||||
|
||||
///
|
||||
/// Create a new instance of [entity].
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'dart:math';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:thermion_dart/src/utils/gizmo.dart';
|
||||
import 'package:thermion_dart/src/utils/src/gizmo.dart';
|
||||
import 'package:thermion_dart/src/viewer/src/shared_types/swap_chain.dart';
|
||||
import 'package:thermion_dart/src/viewer/src/shared_types/view.dart';
|
||||
import 'package:thermion_dart/thermion_dart.dart';
|
||||
@@ -893,11 +893,7 @@ class ThermionViewerStub extends ThermionViewer {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ThermionEntity> loadGlbFromBuffer(Uint8List data, {int numInstances = 1, bool keepData = false, int priority = 4, int layer = 0}) {
|
||||
// TODO: implement loadGlbFromBuffer
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
Future setMaterialPropertyInt(ThermionEntity entity, String propertyName, int materialIndex, int value) {
|
||||
@@ -1060,6 +1056,12 @@ class ThermionViewerStub extends ThermionViewer {
|
||||
// TODO: implement getActiveCamera
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ThermionEntity> loadGlbFromBuffer(Uint8List data, {int numInstances = 1, bool keepData = false, int priority = 4, int layer = 0, bool loadResourcesAsync= false}) {
|
||||
// TODO: implement loadGlbFromBuffer
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,5 @@
|
||||
import 'package:vector_math/vector_math_64.dart';
|
||||
|
||||
import '../../shared_types/camera.dart';
|
||||
import '../../thermion_viewer_base.dart';
|
||||
|
||||
class ThermionWasmCamera extends Camera {
|
||||
@@ -69,4 +68,10 @@ class ThermionWasmCamera extends Camera {
|
||||
// TODO: implement getViewMatrix
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future setProjection(Projection projection, double left, double right, double bottom, double top, double near, double far) {
|
||||
// TODO: implement setProjection
|
||||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,4 +2,4 @@ library filament_dart;
|
||||
|
||||
export 'src/viewer/viewer.dart';
|
||||
export 'src/input/input.dart';
|
||||
export 'src/utils/geometry.dart';
|
||||
export 'src/utils/utils.dart';
|
||||
|
||||
@@ -21,14 +21,14 @@ extern "C"
|
||||
typedef struct TScene TScene;
|
||||
|
||||
struct TMaterialKey {
|
||||
bool doubleSided = 1;
|
||||
bool unlit = 1;
|
||||
bool hasVertexColors = 1;
|
||||
bool hasBaseColorTexture = 1;
|
||||
bool hasNormalTexture = 1;
|
||||
bool hasOcclusionTexture = 1;
|
||||
bool hasEmissiveTexture = 1;
|
||||
bool useSpecularGlossiness = 1;
|
||||
bool doubleSided = true;
|
||||
bool unlit = true;
|
||||
bool hasVertexColors = true;
|
||||
bool hasBaseColorTexture = true;
|
||||
bool hasNormalTexture = true;
|
||||
bool hasOcclusionTexture = true;
|
||||
bool hasEmissiveTexture = true;
|
||||
bool useSpecularGlossiness = true;
|
||||
int alphaMode = 4;
|
||||
bool enableDiagnostics = 4;
|
||||
union {
|
||||
@@ -43,42 +43,42 @@ extern "C"
|
||||
};
|
||||
#else
|
||||
struct {
|
||||
bool hasMetallicRoughnessTexture = 1;
|
||||
bool hasMetallicRoughnessTexture = true;
|
||||
uint8_t metallicRoughnessUV = 7;
|
||||
};
|
||||
struct {
|
||||
bool hasSpecularGlossinessTexture = 1;
|
||||
bool hasSpecularGlossinessTexture = true;
|
||||
uint8_t specularGlossinessUV = 7;
|
||||
};
|
||||
#endif
|
||||
};
|
||||
uint8_t baseColorUV;
|
||||
// -- 32 bit boundary --
|
||||
bool hasClearCoatTexture = 1;
|
||||
bool hasClearCoatTexture = true;
|
||||
uint8_t clearCoatUV = 7;
|
||||
bool hasClearCoatRoughnessTexture = 1;
|
||||
bool hasClearCoatRoughnessTexture = true;
|
||||
uint8_t clearCoatRoughnessUV = 7;
|
||||
bool hasClearCoatNormalTexture = 1;
|
||||
bool hasClearCoatNormalTexture = true;
|
||||
uint8_t clearCoatNormalUV = 7;
|
||||
bool hasClearCoat = 1;
|
||||
bool hasTransmission = 1;
|
||||
bool hasClearCoat = true;
|
||||
bool hasTransmission = true;
|
||||
bool hasTextureTransforms = 6;
|
||||
// -- 32 bit boundary --
|
||||
uint8_t emissiveUV;
|
||||
uint8_t aoUV;
|
||||
uint8_t normalUV;
|
||||
bool hasTransmissionTexture = 1;
|
||||
bool hasTransmissionTexture = true;
|
||||
uint8_t transmissionUV = 7;
|
||||
// -- 32 bit boundary --
|
||||
bool hasSheenColorTexture = 1;
|
||||
bool hasSheenColorTexture = true;
|
||||
uint8_t sheenColorUV = 7;
|
||||
bool hasSheenRoughnessTexture = 1;
|
||||
bool hasSheenRoughnessTexture = true;
|
||||
uint8_t sheenRoughnessUV = 7;
|
||||
bool hasVolumeThicknessTexture = 1;
|
||||
bool hasVolumeThicknessTexture = true;
|
||||
uint8_t volumeThicknessUV = 7;
|
||||
bool hasSheen = 1;
|
||||
bool hasIOR = 1;
|
||||
bool hasVolume = 1;
|
||||
bool hasSheen = true;
|
||||
bool hasIOR = true;
|
||||
bool hasVolume = true;
|
||||
} ;
|
||||
typedef struct TMaterialKey TMaterialKey;
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ namespace thermion
|
||||
void clearBackgroundImage();
|
||||
void setBackgroundImagePosition(float x, float y, bool clamp, uint32_t width, uint32_t height);
|
||||
|
||||
void pick(View *view, uint32_t x, uint32_t y, void (*callback)(EntityId entityId, int x, int y));
|
||||
void pick(View *view, uint32_t x, uint32_t y, void (*callback)(EntityId entityId, int x, int y, View *view));
|
||||
Engine* getEngine() {
|
||||
return _engine;
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ namespace thermion
|
||||
/// @return an Entity representing the FilamentAsset associated with the loaded FilamentAsset.
|
||||
///
|
||||
EntityId loadGlb(const char *uri, int numInstances, bool keepData);
|
||||
EntityId loadGlbFromBuffer(const uint8_t *data, size_t length, int numInstances = 1, bool keepData = false, int priority = 4, int layer = 0);
|
||||
EntityId loadGlbFromBuffer(const uint8_t *data, size_t length, int numInstances = 1, bool keepData = false, int priority = 4, int layer = 0, bool loadResourcesAsync = false);
|
||||
EntityId createInstance(EntityId entityId);
|
||||
|
||||
void remove(EntityId entity);
|
||||
@@ -125,7 +125,7 @@ namespace thermion
|
||||
bool setMorphAnimationBuffer(
|
||||
EntityId entityId,
|
||||
const float *const morphData,
|
||||
const int *const morphIndices,
|
||||
const uint32_t *const morphIndices,
|
||||
int numMorphTargets,
|
||||
int numFrames,
|
||||
float frameLengthInMs);
|
||||
|
||||
@@ -85,6 +85,7 @@ extern "C"
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_setMainCamera(TViewer *tViewer, TView *tView);
|
||||
EMSCRIPTEN_KEEPALIVE TSwapChain* Viewer_getSwapChainAt(TViewer *tViewer, int index);
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_setViewRenderable(TViewer *viewer, TSwapChain *swapChain, TView* view, bool renderable);
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_pick(TViewer *viewer, TView* tView, int x, int y, void (*callback)(EntityId entityId, int x, int y, TView *tView));
|
||||
|
||||
// Engine
|
||||
EMSCRIPTEN_KEEPALIVE TEngine *Viewer_getEngine(TViewer* viewer);
|
||||
@@ -98,7 +99,7 @@ extern "C"
|
||||
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void load_skybox(TViewer *viewer, const char *skyboxPath);
|
||||
EMSCRIPTEN_KEEPALIVE void load_ibl(TViewer *viewer, const char *iblPath, float intensity);
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_loadIbl(TViewer *viewer, const char *iblPath, float intensity);
|
||||
EMSCRIPTEN_KEEPALIVE void create_ibl(TViewer *viewer, float r, float g, float b, float intensity);
|
||||
EMSCRIPTEN_KEEPALIVE void rotate_ibl(TViewer *viewer, float *rotationMatrix);
|
||||
EMSCRIPTEN_KEEPALIVE void remove_skybox(TViewer *viewer);
|
||||
@@ -146,14 +147,6 @@ extern "C"
|
||||
EntityId entity,
|
||||
const float *const morphData,
|
||||
int numWeights);
|
||||
EMSCRIPTEN_KEEPALIVE bool set_morph_animation(
|
||||
TSceneManager *sceneManager,
|
||||
EntityId entity,
|
||||
const float *const morphData,
|
||||
const int *const morphIndices,
|
||||
int numMorphTargets,
|
||||
int numFrames,
|
||||
float frameLengthInMs);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE TMaterialInstance *create_material_instance(TSceneManager *sceneManager, TMaterialKey materialConfig);
|
||||
EMSCRIPTEN_KEEPALIVE TMaterialInstance *create_unlit_material_instance(TSceneManager *sceneManager);
|
||||
@@ -209,7 +202,15 @@ extern "C"
|
||||
EMSCRIPTEN_KEEPALIVE TCamera* SceneManager_findCameraByName(TSceneManager* tSceneManager, EntityId entity, const char* name);
|
||||
EMSCRIPTEN_KEEPALIVE void SceneManager_setVisibilityLayer(TSceneManager *tSceneManager, EntityId entity, int layer);
|
||||
EMSCRIPTEN_KEEPALIVE TScene* SceneManager_getScene(TSceneManager *tSceneManager);
|
||||
EMSCRIPTEN_KEEPALIVE EntityId SceneManager_loadGlbFromBuffer(TSceneManager *sceneManager, const uint8_t *const, size_t length, bool keepData, int priority, int layer);
|
||||
EMSCRIPTEN_KEEPALIVE EntityId SceneManager_loadGlbFromBuffer(TSceneManager *sceneManager, const uint8_t *const, size_t length, bool keepData, int priority, int layer, bool loadResourcesAsync);
|
||||
EMSCRIPTEN_KEEPALIVE bool SceneManager_setMorphAnimation(
|
||||
TSceneManager *sceneManager,
|
||||
EntityId entity,
|
||||
const float *const morphData,
|
||||
const uint32_t *const morphIndices,
|
||||
int numMorphTargets,
|
||||
int numFrames,
|
||||
float frameLengthInMs);
|
||||
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE bool update_bone_matrices(TSceneManager *sceneManager, EntityId entityId);
|
||||
@@ -239,7 +240,7 @@ extern "C"
|
||||
EMSCRIPTEN_KEEPALIVE int hide_mesh(TSceneManager *sceneManager, EntityId entity, const char *meshName);
|
||||
EMSCRIPTEN_KEEPALIVE int reveal_mesh(TSceneManager *sceneManager, EntityId entity, const char *meshName);
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void filament_pick(TViewer *viewer, TView* tView, int x, int y, void (*callback)(EntityId entityId, int x, int y));
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE const char *get_name_for_entity(TSceneManager *sceneManager, const EntityId entityId);
|
||||
EMSCRIPTEN_KEEPALIVE EntityId find_child_entity_by_name(TSceneManager *sceneManager, const EntityId parent, const char *name);
|
||||
EMSCRIPTEN_KEEPALIVE int get_entity_count(TSceneManager *sceneManager, const EntityId target, bool renderableOnly);
|
||||
|
||||
@@ -19,7 +19,7 @@ extern "C"
|
||||
typedef int32_t EntityId;
|
||||
typedef void (*FilamentRenderCallback)(void *const owner);
|
||||
|
||||
void Viewer_createOnRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_createOnRenderThread(
|
||||
void *const context,
|
||||
void *const platform,
|
||||
const char *uberArchivePath,
|
||||
@@ -27,68 +27,68 @@ extern "C"
|
||||
void (*renderCallback)(void *const renderCallbackOwner),
|
||||
void *const renderCallbackOwner,
|
||||
void (*callback)(TViewer *viewer));
|
||||
void Viewer_createSwapChainRenderThread(TViewer *viewer, void *const surface, void (*onComplete)(TSwapChain*));
|
||||
void Viewer_createHeadlessSwapChainRenderThread(TViewer *viewer, uint32_t width, uint32_t height, void (*onComplete)(TSwapChain*));
|
||||
void Viewer_destroySwapChainRenderThread(TViewer *viewer, TSwapChain* swapChain, void (*onComplete)());
|
||||
void Viewer_renderRenderThread(TViewer *viewer, TView* view, TSwapChain* swapChain);
|
||||
void Viewer_captureRenderThread(TViewer *viewer, TView* view, TSwapChain* swapChain, uint8_t* out, void (*onComplete)());
|
||||
void Viewer_captureRenderTargetRenderThread(TViewer *viewer, TView* view, TSwapChain* swapChain, TRenderTarget* renderTarget, uint8_t* out, void (*onComplete)());
|
||||
void Viewer_requestFrameRenderThread(TViewer *viewer, void(*onComplete)());
|
||||
|
||||
void View_setToneMappingRenderThread(TView *tView, TEngine *tEngine, thermion::ToneMapping toneMapping);
|
||||
void View_setBloomRenderThread(TView *tView, double bloom);
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_createSwapChainRenderThread(TViewer *viewer, void *const surface, void (*onComplete)(TSwapChain*));
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_createHeadlessSwapChainRenderThread(TViewer *viewer, uint32_t width, uint32_t height, void (*onComplete)(TSwapChain*));
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_destroySwapChainRenderThread(TViewer *viewer, TSwapChain* swapChain, void (*onComplete)());
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_renderRenderThread(TViewer *viewer, TView* view, TSwapChain* swapChain);
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderThread(TViewer *viewer, TView* view, TSwapChain* swapChain, uint8_t* out, void (*onComplete)());
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderTargetRenderThread(TViewer *viewer, TView* view, TSwapChain* swapChain, TRenderTarget* renderTarget, uint8_t* out, void (*onComplete)());
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_requestFrameRenderThread(TViewer *viewer, void(*onComplete)());
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_loadIblRenderThread(TViewer *viewer, const char *iblPath, float intensity, void(*onComplete)());
|
||||
EMSCRIPTEN_KEEPALIVE void View_setToneMappingRenderThread(TView *tView, TEngine *tEngine, thermion::ToneMapping toneMapping);
|
||||
EMSCRIPTEN_KEEPALIVE void View_setBloomRenderThread(TView *tView, double bloom);
|
||||
|
||||
|
||||
void destroy_filament_viewer_render_thread(TViewer *viewer);
|
||||
EMSCRIPTEN_KEEPALIVE void destroy_filament_viewer_render_thread(TViewer *viewer);
|
||||
|
||||
FilamentRenderCallback make_render_callback_fn_pointer(FilamentRenderCallback);
|
||||
void set_rendering_render_thread(TViewer *viewer, bool rendering, void(*onComplete)());
|
||||
EMSCRIPTEN_KEEPALIVE void set_rendering_render_thread(TViewer *viewer, bool rendering, void(*onComplete)());
|
||||
|
||||
void set_frame_interval_render_thread(TViewer *viewer, float frameInterval);
|
||||
void set_background_color_render_thread(TViewer *viewer, const float r, const float g, const float b, const float a);
|
||||
void clear_background_image_render_thread(TViewer *viewer);
|
||||
void set_background_image_render_thread(TViewer *viewer, const char *path, bool fillHeight, void (*onComplete)());
|
||||
void set_background_image_position_render_thread(TViewer *viewer, float x, float y, bool clamp);
|
||||
void load_skybox_render_thread(TViewer *viewer, const char *skyboxPath, void (*onComplete)());
|
||||
void remove_skybox_render_thread(TViewer *viewer);
|
||||
EMSCRIPTEN_KEEPALIVE void set_frame_interval_render_thread(TViewer *viewer, float frameInterval);
|
||||
EMSCRIPTEN_KEEPALIVE void set_background_color_render_thread(TViewer *viewer, const float r, const float g, const float b, const float a);
|
||||
EMSCRIPTEN_KEEPALIVE void clear_background_image_render_thread(TViewer *viewer);
|
||||
EMSCRIPTEN_KEEPALIVE void set_background_image_render_thread(TViewer *viewer, const char *path, bool fillHeight, void (*onComplete)());
|
||||
EMSCRIPTEN_KEEPALIVE void set_background_image_position_render_thread(TViewer *viewer, float x, float y, bool clamp);
|
||||
EMSCRIPTEN_KEEPALIVE void load_skybox_render_thread(TViewer *viewer, const char *skyboxPath, void (*onComplete)());
|
||||
EMSCRIPTEN_KEEPALIVE void remove_skybox_render_thread(TViewer *viewer);
|
||||
|
||||
void SceneManager_loadGlbFromBufferRenderThread(TSceneManager *sceneManager, const uint8_t *const data, size_t length, int numInstances, bool keepData, int priority, int layer, void (*callback)(EntityId));
|
||||
void load_glb_render_thread(TSceneManager *sceneManager, const char *assetPath, int numInstances, bool keepData, void (*callback)(EntityId));
|
||||
void load_gltf_render_thread(TSceneManager *sceneManager, const char *assetPath, const char *relativePath, bool keepData, void (*callback)(EntityId));
|
||||
void create_instance_render_thread(TSceneManager *sceneManager, EntityId entityId, void (*callback)(EntityId));
|
||||
void remove_entity_render_thread(TViewer *viewer, EntityId asset, void (*callback)());
|
||||
void clear_entities_render_thread(TViewer *viewer, void (*callback)());
|
||||
EMSCRIPTEN_KEEPALIVE void SceneManager_loadGlbFromBufferRenderThread(TSceneManager *sceneManager, const uint8_t *const data, size_t length, int numInstances, bool keepData, int priority, int layer, bool loadResourcesAsync, void (*callback)(EntityId));
|
||||
EMSCRIPTEN_KEEPALIVE void load_glb_render_thread(TSceneManager *sceneManager, const char *assetPath, int numInstances, bool keepData, void (*callback)(EntityId));
|
||||
EMSCRIPTEN_KEEPALIVE void load_gltf_render_thread(TSceneManager *sceneManager, const char *assetPath, const char *relativePath, bool keepData, void (*callback)(EntityId));
|
||||
EMSCRIPTEN_KEEPALIVE void create_instance_render_thread(TSceneManager *sceneManager, EntityId entityId, void (*callback)(EntityId));
|
||||
EMSCRIPTEN_KEEPALIVE void remove_entity_render_thread(TViewer *viewer, EntityId asset, void (*callback)());
|
||||
EMSCRIPTEN_KEEPALIVE void clear_entities_render_thread(TViewer *viewer, void (*callback)());
|
||||
|
||||
void apply_weights_render_thread(
|
||||
EMSCRIPTEN_KEEPALIVE void apply_weights_render_thread(
|
||||
TSceneManager *sceneManager,
|
||||
EntityId asset,
|
||||
const char *const entityName,
|
||||
float *const weights,
|
||||
int count);
|
||||
void set_animation_frame_render_thread(TSceneManager *sceneManager, EntityId asset, int animationIndex, int animationFrame);
|
||||
void stop_animation_render_thread(TSceneManager *sceneManager, EntityId asset, int index);
|
||||
void get_animation_count_render_thread(TSceneManager *sceneManager, EntityId asset, void (*callback)(int));
|
||||
void get_animation_name_render_thread(TSceneManager *sceneManager, EntityId asset, char *const outPtr, int index, void (*callback)());
|
||||
void get_morph_target_name_render_thread(TSceneManager *sceneManager, EntityId assetEntity, EntityId childEntity, char *const outPtr, int index, void (*callback)());
|
||||
void get_morph_target_name_count_render_thread(TSceneManager *sceneManager, EntityId asset, EntityId childEntity, void (*callback)(int32_t));
|
||||
void set_morph_target_weights_render_thread(TSceneManager *sceneManager,
|
||||
EMSCRIPTEN_KEEPALIVE void set_animation_frame_render_thread(TSceneManager *sceneManager, EntityId asset, int animationIndex, int animationFrame);
|
||||
EMSCRIPTEN_KEEPALIVE void stop_animation_render_thread(TSceneManager *sceneManager, EntityId asset, int index);
|
||||
EMSCRIPTEN_KEEPALIVE void get_animation_count_render_thread(TSceneManager *sceneManager, EntityId asset, void (*callback)(int));
|
||||
EMSCRIPTEN_KEEPALIVE void get_animation_name_render_thread(TSceneManager *sceneManager, EntityId asset, char *const outPtr, int index, void (*callback)());
|
||||
EMSCRIPTEN_KEEPALIVE void get_morph_target_name_render_thread(TSceneManager *sceneManager, EntityId assetEntity, EntityId childEntity, char *const outPtr, int index, void (*callback)());
|
||||
EMSCRIPTEN_KEEPALIVE void get_morph_target_name_count_render_thread(TSceneManager *sceneManager, EntityId asset, EntityId childEntity, void (*callback)(int32_t));
|
||||
EMSCRIPTEN_KEEPALIVE void set_morph_target_weights_render_thread(TSceneManager *sceneManager,
|
||||
EntityId asset,
|
||||
const float *const morphData,
|
||||
int numWeights,
|
||||
void (*callback)(bool));
|
||||
|
||||
void update_bone_matrices_render_thread(TSceneManager *sceneManager,
|
||||
EMSCRIPTEN_KEEPALIVE void update_bone_matrices_render_thread(TSceneManager *sceneManager,
|
||||
EntityId asset, void(*callback)(bool));
|
||||
void set_bone_transform_render_thread(
|
||||
EMSCRIPTEN_KEEPALIVE void set_bone_transform_render_thread(
|
||||
TSceneManager *sceneManager,
|
||||
EntityId asset,
|
||||
int skinIndex,
|
||||
int boneIndex,
|
||||
const float *const transform,
|
||||
void (*callback)(bool));
|
||||
void set_post_processing_render_thread(TViewer *viewer, bool enabled);
|
||||
void reset_to_rest_pose_render_thread(TSceneManager *sceneManager, EntityId entityId, void(*callback)());
|
||||
void create_geometry_render_thread(
|
||||
EMSCRIPTEN_KEEPALIVE void set_post_processing_render_thread(TViewer *viewer, bool enabled);
|
||||
EMSCRIPTEN_KEEPALIVE void reset_to_rest_pose_render_thread(TSceneManager *sceneManager, EntityId entityId, void(*callback)());
|
||||
EMSCRIPTEN_KEEPALIVE void create_geometry_render_thread(
|
||||
TSceneManager *sceneManager,
|
||||
float *vertices,
|
||||
int numVertices,
|
||||
@@ -102,7 +102,7 @@ extern "C"
|
||||
TMaterialInstance *materialInstance,
|
||||
bool keepData,
|
||||
void (*callback)(EntityId));
|
||||
void unproject_texture_render_thread(TViewer* viewer, EntityId entity, uint8_t* input, uint32_t inputWidth, uint32_t inputHeight, uint8_t* out, uint32_t outWidth, uint32_t outHeight, void(*callback)());
|
||||
EMSCRIPTEN_KEEPALIVE void unproject_texture_render_thread(TViewer* viewer, EntityId entity, uint8_t* input, uint32_t inputWidth, uint32_t inputHeight, uint8_t* out, uint32_t outWidth, uint32_t outHeight, void(*callback)());
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -764,10 +764,10 @@ namespace thermion
|
||||
view->setStereoscopicOptions({.enabled = true});
|
||||
#endif
|
||||
|
||||
// there's a glitch on certain iGPUs where nothing will render when postprocessing is enabled and bloom is disabled
|
||||
// set bloom to a small value here
|
||||
view->setBloomOptions({.strength = 0.01});
|
||||
view->setDithering(filament::Dithering::NONE);
|
||||
// bloom can be a bit glitchy (some Intel iGPUs won't render when postprocessing is enabled and bloom is disabled,
|
||||
// and render targets on MacOS flicker when bloom is disabled.
|
||||
// Here, we enable bloom, but set to 0 strength
|
||||
view->setBloomOptions({.strength = 0, .enabled=true });
|
||||
view->setShadowingEnabled(false);
|
||||
view->setScreenSpaceRefractionEnabled(false);
|
||||
view->setPostProcessingEnabled(false);
|
||||
@@ -1051,8 +1051,8 @@ namespace thermion
|
||||
_renderer->render(view);
|
||||
}
|
||||
}
|
||||
_renderer->endFrame();
|
||||
}
|
||||
_renderer->endFrame();
|
||||
}
|
||||
#ifdef __EMSCRIPTEN__
|
||||
_engine->execute();
|
||||
@@ -1198,9 +1198,8 @@ namespace thermion
|
||||
return _engine->getCameraComponent(Entity::import(entity));
|
||||
}
|
||||
|
||||
void FilamentViewer::pick(View *view, uint32_t x, uint32_t y, void (*callback)(EntityId entityId, int x, int y))
|
||||
void FilamentViewer::pick(View *view, uint32_t x, uint32_t y, void (*callback)(EntityId entityId, int x, int y, View *view))
|
||||
{
|
||||
|
||||
view->pick(x, y, [=](filament::View::PickingQueryResult const &result) {
|
||||
|
||||
if(_sceneManager->isGizmoEntity(result.renderable)) {
|
||||
@@ -1214,7 +1213,7 @@ namespace thermion
|
||||
};
|
||||
|
||||
if (nonPickableEntities.find(result.renderable) == nonPickableEntities.end()) {
|
||||
callback(Entity::smuggle(result.renderable), x, y);
|
||||
callback(Entity::smuggle(result.renderable), x, y, view);
|
||||
} });
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
#ifdef _WIN32
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <cmath>
|
||||
#endif
|
||||
|
||||
#include "GridOverlay.hpp"
|
||||
|
||||
#include <filament/Engine.h>
|
||||
|
||||
@@ -257,7 +257,7 @@ namespace thermion
|
||||
|
||||
}
|
||||
|
||||
EntityId SceneManager::loadGlbFromBuffer(const uint8_t *data, size_t length, int numInstances, bool keepData, int priority, int layer)
|
||||
EntityId SceneManager::loadGlbFromBuffer(const uint8_t *data, size_t length, int numInstances, bool keepData, int priority, int layer, bool loadResourcesAsync)
|
||||
{
|
||||
|
||||
FilamentAsset *asset = nullptr;
|
||||
@@ -304,10 +304,18 @@ namespace thermion
|
||||
_gltfResourceLoader->asyncUpdateLoad();
|
||||
}
|
||||
#else
|
||||
if (!_gltfResourceLoader->loadResources(asset))
|
||||
{
|
||||
Log("Unknown error loading glb asset");
|
||||
return 0;
|
||||
if(loadResourcesAsync) {
|
||||
if (!_gltfResourceLoader->asyncBeginLoad(asset))
|
||||
{
|
||||
Log("Unknown error loading glb asset");
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (!_gltfResourceLoader->loadResources(asset))
|
||||
{
|
||||
Log("Unknown error loading glb asset");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -806,7 +814,7 @@ namespace thermion
|
||||
bool SceneManager::setMorphAnimationBuffer(
|
||||
EntityId entityId,
|
||||
const float *const morphData,
|
||||
const int *const morphIndices,
|
||||
const uint32_t *const morphIndices,
|
||||
int numMorphTargets,
|
||||
int numFrames,
|
||||
float frameLengthInMs)
|
||||
|
||||
@@ -1,14 +1,7 @@
|
||||
#ifdef _WIN32
|
||||
#pragma comment(lib, "Shlwapi.lib")
|
||||
#pragma comment(lib, "opengl32.lib")
|
||||
#include "ThermionWin32.h"
|
||||
#endif
|
||||
|
||||
#include "ResourceBuffer.hpp"
|
||||
#include "FilamentViewer.hpp"
|
||||
#include "filament/LightManager.h"
|
||||
#include "Log.hpp"
|
||||
#include "ThreadPool.hpp"
|
||||
|
||||
#include <thread>
|
||||
#include <functional>
|
||||
|
||||
@@ -16,6 +9,12 @@
|
||||
#include <emscripten/emscripten.h>
|
||||
#endif
|
||||
|
||||
#include "filament/LightManager.h"
|
||||
#include "ResourceBuffer.hpp"
|
||||
#include "FilamentViewer.hpp"
|
||||
#include "Log.hpp"
|
||||
#include "ThreadPool.hpp"
|
||||
|
||||
using namespace thermion;
|
||||
|
||||
extern "C"
|
||||
@@ -50,6 +49,13 @@ extern "C"
|
||||
viewer->destroyRenderTarget(renderTarget);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_pick(TViewer *tViewer, TView* tView, int x, int y, void (*callback)(EntityId entityId, int x, int y, TView *tView))
|
||||
{
|
||||
auto *viewer = reinterpret_cast<FilamentViewer*>(tViewer);
|
||||
auto *view = reinterpret_cast<View*>(tView);
|
||||
((FilamentViewer *)viewer)->pick(view, static_cast<uint32_t>(x), static_cast<uint32_t>(y), reinterpret_cast<void (*)(EntityId entityId, int x, int y, View *view)>(callback));
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void destroy_filament_viewer(TViewer *viewer)
|
||||
{
|
||||
delete ((FilamentViewer *)viewer);
|
||||
@@ -86,7 +92,7 @@ extern "C"
|
||||
((FilamentViewer *)viewer)->createIbl(r, g, b, intensity);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void load_ibl(TViewer *viewer, const char *iblPath, float intensity)
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_loadIbl(TViewer *viewer, const char *iblPath, float intensity)
|
||||
{
|
||||
((FilamentViewer *)viewer)->loadIbl(iblPath, intensity);
|
||||
}
|
||||
@@ -162,7 +168,7 @@ extern "C"
|
||||
return ((SceneManager *)sceneManager)->loadGlb(assetPath, numInstances, keepData);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE EntityId SceneManager_loadGlbFromBuffer(TSceneManager *sceneManager, const uint8_t *const data, size_t length, bool keepData, int priority, int layer)
|
||||
EMSCRIPTEN_KEEPALIVE EntityId SceneManager_loadGlbFromBuffer(TSceneManager *sceneManager, const uint8_t *const data, size_t length, bool keepData, int priority, int layer, bool loadResourcesAsync)
|
||||
{
|
||||
return ((SceneManager *)sceneManager)->loadGlbFromBuffer((const uint8_t *)data, length, 1, keepData, priority, layer);
|
||||
}
|
||||
@@ -223,62 +229,62 @@ extern "C"
|
||||
return reinterpret_cast<TCamera *>(filamentCamera);
|
||||
}
|
||||
|
||||
double4x4 get_camera_model_matrix(TCamera *camera)
|
||||
EMSCRIPTEN_KEEPALIVE double4x4 get_camera_model_matrix(TCamera *camera)
|
||||
{
|
||||
const auto &mat = reinterpret_cast<filament::Camera *>(camera)->getModelMatrix();
|
||||
return convert_mat4_to_double4x4(mat);
|
||||
}
|
||||
|
||||
double4x4 get_camera_view_matrix(TCamera *camera)
|
||||
EMSCRIPTEN_KEEPALIVE double4x4 get_camera_view_matrix(TCamera *camera)
|
||||
{
|
||||
const auto &mat = reinterpret_cast<filament::Camera *>(camera)->getViewMatrix();
|
||||
return convert_mat4_to_double4x4(mat);
|
||||
}
|
||||
|
||||
double4x4 get_camera_projection_matrix(TCamera *camera)
|
||||
EMSCRIPTEN_KEEPALIVE double4x4 get_camera_projection_matrix(TCamera *camera)
|
||||
{
|
||||
const auto &mat = reinterpret_cast<filament::Camera *>(camera)->getProjectionMatrix();
|
||||
return convert_mat4_to_double4x4(mat);
|
||||
}
|
||||
|
||||
double4x4 get_camera_culling_projection_matrix(TCamera *camera)
|
||||
EMSCRIPTEN_KEEPALIVE double4x4 get_camera_culling_projection_matrix(TCamera *camera)
|
||||
{
|
||||
const auto &mat = reinterpret_cast<filament::Camera *>(camera)->getCullingProjectionMatrix();
|
||||
return convert_mat4_to_double4x4(mat);
|
||||
}
|
||||
|
||||
void set_camera_projection_matrix(TCamera *camera, double4x4 matrix, double near, double far)
|
||||
EMSCRIPTEN_KEEPALIVE void set_camera_projection_matrix(TCamera *camera, double4x4 matrix, double near, double far)
|
||||
{
|
||||
auto cam = reinterpret_cast<filament::Camera *>(camera);
|
||||
const auto &mat = convert_double4x4_to_mat4(matrix);
|
||||
cam->setCustomProjection(mat, near, far);
|
||||
}
|
||||
|
||||
void Camera_setLensProjection(TCamera *camera, double near, double far, double aspect, double focalLength)
|
||||
EMSCRIPTEN_KEEPALIVE void Camera_setLensProjection(TCamera *camera, double near, double far, double aspect, double focalLength)
|
||||
{
|
||||
auto cam = reinterpret_cast<filament::Camera *>(camera);
|
||||
cam->setLensProjection(focalLength, aspect, near, far);
|
||||
}
|
||||
|
||||
void Camera_setModelMatrix(TCamera *camera, double4x4 matrix)
|
||||
EMSCRIPTEN_KEEPALIVE void Camera_setModelMatrix(TCamera *camera, double4x4 matrix)
|
||||
{
|
||||
auto cam = reinterpret_cast<filament::Camera *>(camera);
|
||||
cam->setModelMatrix(convert_double4x4_to_mat4(matrix));
|
||||
}
|
||||
|
||||
double get_camera_near(TCamera *camera)
|
||||
EMSCRIPTEN_KEEPALIVE double get_camera_near(TCamera *camera)
|
||||
{
|
||||
auto cam = reinterpret_cast<filament::Camera *>(camera);
|
||||
return cam->getNear();
|
||||
}
|
||||
|
||||
double get_camera_culling_far(TCamera *camera)
|
||||
EMSCRIPTEN_KEEPALIVE double get_camera_culling_far(TCamera *camera)
|
||||
{
|
||||
auto cam = reinterpret_cast<filament::Camera *>(camera);
|
||||
return cam->getCullingFar();
|
||||
}
|
||||
|
||||
const double *const get_camera_frustum(TCamera *camera)
|
||||
EMSCRIPTEN_KEEPALIVE const double *const get_camera_frustum(TCamera *camera)
|
||||
{
|
||||
|
||||
const auto frustum = reinterpret_cast<filament::Camera *>(camera)->getFrustum();
|
||||
@@ -297,7 +303,6 @@ extern "C"
|
||||
return array;
|
||||
}
|
||||
|
||||
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_camera_focus_distance(TCamera *camera, float distance)
|
||||
{
|
||||
@@ -446,11 +451,11 @@ extern "C"
|
||||
return ((SceneManager *)sceneManager)->setMorphTargetWeights(asset, weights, numWeights);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE bool set_morph_animation(
|
||||
EMSCRIPTEN_KEEPALIVE bool SceneManager_setMorphAnimation(
|
||||
TSceneManager *sceneManager,
|
||||
EntityId asset,
|
||||
const float *const morphData,
|
||||
const int *const morphIndices,
|
||||
const uint32_t *const morphIndices,
|
||||
int numMorphTargets,
|
||||
int numFrames,
|
||||
float frameLengthInMs)
|
||||
@@ -696,8 +701,9 @@ extern "C"
|
||||
EMSCRIPTEN_KEEPALIVE void SceneManager_queueTransformUpdates(TSceneManager *tSceneManager, EntityId *entities, const double *const transforms, int numEntities)
|
||||
{
|
||||
auto *sceneManager = reinterpret_cast<SceneManager *>(tSceneManager);
|
||||
math::mat4 matrices[
|
||||
numEntities];
|
||||
|
||||
std::vector<math::mat4> matrices(
|
||||
numEntities);
|
||||
for (int i = 0; i < numEntities; i++)
|
||||
{
|
||||
matrices[i] = math::mat4(
|
||||
@@ -716,7 +722,7 @@ extern "C"
|
||||
transforms[i * 16 + 14],
|
||||
transforms[i * 16 + 15]);
|
||||
}
|
||||
sceneManager->queueTransformUpdates(entities, matrices, numEntities);
|
||||
sceneManager->queueTransformUpdates(entities, matrices.data(), numEntities);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE bool update_bone_matrices(TSceneManager *sceneManager, EntityId entityId)
|
||||
@@ -793,13 +799,6 @@ extern "C"
|
||||
return ((SceneManager *)sceneManager)->reveal(asset, meshName);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void filament_pick(TViewer *tViewer, TView* tView, int x, int y, void (*callback)(EntityId entityId, int x, int y))
|
||||
{
|
||||
auto *viewer = reinterpret_cast<FilamentViewer*>(tViewer);
|
||||
auto *view = reinterpret_cast<View*>(tView);
|
||||
((FilamentViewer *)viewer)->pick(view, static_cast<uint32_t>(x), static_cast<uint32_t>(y), callback);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE const char *get_name_for_entity(TSceneManager *sceneManager, const EntityId entityId)
|
||||
{
|
||||
return ((SceneManager *)sceneManager)->getNameForEntity(entityId);
|
||||
@@ -955,10 +954,10 @@ extern "C"
|
||||
EMSCRIPTEN_KEEPALIVE void set_material_property_float4(TSceneManager *sceneManager, EntityId entity, int materialIndex, const char *property, double4 value)
|
||||
{
|
||||
filament::math::float4 filamentValue;
|
||||
filamentValue.x = static_cast<float32_t>(value.x);
|
||||
filamentValue.y = static_cast<float32_t>(value.y);
|
||||
filamentValue.z = static_cast<float32_t>(value.z);
|
||||
filamentValue.w = static_cast<float32_t>(value.w);
|
||||
filamentValue.x = static_cast<float>(value.x);
|
||||
filamentValue.y = static_cast<float>(value.y);
|
||||
filamentValue.z = static_cast<float>(value.z);
|
||||
filamentValue.w = static_cast<float>(value.w);
|
||||
((SceneManager *)sceneManager)->setMaterialProperty(entity, materialIndex, property, filamentValue);
|
||||
}
|
||||
|
||||
|
||||
@@ -55,9 +55,10 @@ public:
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(_mutex);
|
||||
this->_requestFrameRenderCallback = callback;
|
||||
_cv.notify_one();
|
||||
}
|
||||
|
||||
void iter()
|
||||
void iter()
|
||||
{
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(_mutex);
|
||||
@@ -79,7 +80,7 @@ public:
|
||||
if (_accumulatedTime >= 1.0f) // Update FPS every second
|
||||
{
|
||||
_fps = _frameCount / _accumulatedTime;
|
||||
std::cout << "FPS: " << _fps << std::endl;
|
||||
// std::cout << "FPS: " << _fps << std::endl;
|
||||
_frameCount = 0;
|
||||
_accumulatedTime = 0.0f;
|
||||
}
|
||||
@@ -96,7 +97,7 @@ public:
|
||||
taskLock.lock();
|
||||
}
|
||||
|
||||
_cv.wait_for(taskLock, std::chrono::microseconds(1000), [this]
|
||||
_cv.wait_for(taskLock, std::chrono::microseconds(2000), [this]
|
||||
{ return !_tasks.empty() || _stop; });
|
||||
|
||||
}
|
||||
@@ -183,7 +184,7 @@ extern "C"
|
||||
|
||||
static RenderLoop *_rl;
|
||||
|
||||
void Viewer_createOnRenderThread(
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_createOnRenderThread(
|
||||
void *const context, void *const platform, const char *uberArchivePath,
|
||||
const void *const loader,
|
||||
void (*renderCallback)(void *const renderCallbackOwner),
|
||||
@@ -199,14 +200,14 @@ extern "C"
|
||||
renderCallback, renderCallbackOwner, callback);
|
||||
}
|
||||
|
||||
void destroy_filament_viewer_render_thread(TViewer *viewer)
|
||||
EMSCRIPTEN_KEEPALIVE void destroy_filament_viewer_render_thread(TViewer *viewer)
|
||||
{
|
||||
_rl->destroyViewer((FilamentViewer *)viewer);
|
||||
delete _rl;
|
||||
_rl = nullptr;
|
||||
}
|
||||
|
||||
void Viewer_createHeadlessSwapChainRenderThread(TViewer *viewer,
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_createHeadlessSwapChainRenderThread(TViewer *viewer,
|
||||
uint32_t width,
|
||||
uint32_t height,
|
||||
void (*onComplete)(TSwapChain*))
|
||||
@@ -220,7 +221,7 @@ extern "C"
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
void Viewer_createSwapChainRenderThread(TViewer *viewer,
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_createSwapChainRenderThread(TViewer *viewer,
|
||||
void *const surface,
|
||||
void (*onComplete)(TSwapChain*))
|
||||
{
|
||||
@@ -233,7 +234,7 @@ extern "C"
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
void Viewer_destroySwapChainRenderThread(TViewer *viewer, TSwapChain *swapChain, void (*onComplete)())
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_destroySwapChainRenderThread(TViewer *viewer, TSwapChain *swapChain, void (*onComplete)())
|
||||
{
|
||||
std::packaged_task<void()> lambda(
|
||||
[=]() mutable
|
||||
@@ -245,7 +246,7 @@ extern "C"
|
||||
}
|
||||
|
||||
|
||||
void Viewer_requestFrameRenderThread(TViewer *viewer, void(*onComplete)())
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_requestFrameRenderThread(TViewer *viewer, void(*onComplete)())
|
||||
{
|
||||
if (!_rl)
|
||||
{
|
||||
@@ -257,7 +258,17 @@ extern "C"
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_loadIblRenderThread(TViewer *viewer, const char *iblPath, float intensity, void(*onComplete)()) {
|
||||
std::packaged_task<void()> lambda(
|
||||
[=]() mutable
|
||||
{
|
||||
Viewer_loadIbl(viewer, iblPath, intensity);
|
||||
onComplete();
|
||||
});
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void
|
||||
set_frame_interval_render_thread(TViewer *viewer, float frameIntervalInMilliseconds)
|
||||
{
|
||||
_rl->setFrameIntervalInMilliseconds(frameIntervalInMilliseconds);
|
||||
@@ -266,7 +277,7 @@ extern "C"
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
void Viewer_renderRenderThread(TViewer *viewer, TView *tView, TSwapChain *tSwapChain)
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_renderRenderThread(TViewer *viewer, TView *tView, TSwapChain *tSwapChain)
|
||||
{
|
||||
std::packaged_task<void()> lambda([=]() mutable
|
||||
{
|
||||
@@ -275,21 +286,21 @@ extern "C"
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
void Viewer_captureRenderThread(TViewer *viewer, TView *view, TSwapChain *tSwapChain, uint8_t *pixelBuffer, void (*onComplete)())
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderThread(TViewer *viewer, TView *view, TSwapChain *tSwapChain, uint8_t *pixelBuffer, void (*onComplete)())
|
||||
{
|
||||
std::packaged_task<void()> lambda([=]() mutable
|
||||
{ Viewer_capture(viewer, view, tSwapChain, pixelBuffer, onComplete); });
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
void Viewer_captureRenderTargetRenderThread(TViewer *viewer, TView *view, TSwapChain *tSwapChain, TRenderTarget* tRenderTarget, uint8_t *pixelBuffer, void (*onComplete)())
|
||||
EMSCRIPTEN_KEEPALIVE void Viewer_captureRenderTargetRenderThread(TViewer *viewer, TView *view, TSwapChain *tSwapChain, TRenderTarget* tRenderTarget, uint8_t *pixelBuffer, void (*onComplete)())
|
||||
{
|
||||
std::packaged_task<void()> lambda([=]() mutable
|
||||
{ Viewer_captureRenderTarget(viewer, view, tSwapChain, tRenderTarget, pixelBuffer, onComplete); });
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
void
|
||||
EMSCRIPTEN_KEEPALIVE void
|
||||
set_background_color_render_thread(TViewer *viewer, const float r, const float g,
|
||||
const float b, const float a)
|
||||
{
|
||||
@@ -299,7 +310,7 @@ extern "C"
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
void load_gltf_render_thread(TSceneManager *sceneManager,
|
||||
EMSCRIPTEN_KEEPALIVE void load_gltf_render_thread(TSceneManager *sceneManager,
|
||||
const char *path,
|
||||
const char *relativeResourcePath,
|
||||
bool keepData,
|
||||
@@ -313,7 +324,7 @@ extern "C"
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
void load_glb_render_thread(TSceneManager *sceneManager,
|
||||
EMSCRIPTEN_KEEPALIVE void load_glb_render_thread(TSceneManager *sceneManager,
|
||||
const char *path,
|
||||
int numInstances,
|
||||
bool keepData,
|
||||
@@ -329,33 +340,34 @@ extern "C"
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
void SceneManager_loadGlbFromBufferRenderThread(TSceneManager *sceneManager,
|
||||
EMSCRIPTEN_KEEPALIVE void SceneManager_loadGlbFromBufferRenderThread(TSceneManager *sceneManager,
|
||||
const uint8_t *const data,
|
||||
size_t length,
|
||||
int numInstances,
|
||||
bool keepData,
|
||||
int priority,
|
||||
int layer,
|
||||
bool loadResourcesAsync,
|
||||
void (*callback)(EntityId))
|
||||
{
|
||||
std::packaged_task<EntityId()> lambda(
|
||||
[=]() mutable
|
||||
{
|
||||
auto entity = SceneManager_loadGlbFromBuffer(sceneManager, data, length, keepData, priority, layer);
|
||||
auto entity = SceneManager_loadGlbFromBuffer(sceneManager, data, length, keepData, priority, layer, loadResourcesAsync);
|
||||
callback(entity);
|
||||
return entity;
|
||||
});
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
void clear_background_image_render_thread(TViewer *viewer)
|
||||
EMSCRIPTEN_KEEPALIVE void clear_background_image_render_thread(TViewer *viewer)
|
||||
{
|
||||
std::packaged_task<void()> lambda([=]
|
||||
{ clear_background_image(viewer); });
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
void set_background_image_render_thread(TViewer *viewer,
|
||||
EMSCRIPTEN_KEEPALIVE void set_background_image_render_thread(TViewer *viewer,
|
||||
const char *path,
|
||||
bool fillHeight, void (*callback)())
|
||||
{
|
||||
@@ -367,7 +379,8 @@ extern "C"
|
||||
});
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
void set_background_image_position_render_thread(TViewer *viewer,
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void set_background_image_position_render_thread(TViewer *viewer,
|
||||
float x, float y,
|
||||
bool clamp)
|
||||
{
|
||||
@@ -377,7 +390,7 @@ extern "C"
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
void load_skybox_render_thread(TViewer *viewer,
|
||||
EMSCRIPTEN_KEEPALIVE void load_skybox_render_thread(TViewer *viewer,
|
||||
const char *skyboxPath,
|
||||
void (*onComplete)())
|
||||
{
|
||||
@@ -388,30 +401,22 @@ extern "C"
|
||||
});
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
void load_ibl_render_thread(TViewer *viewer, const char *iblPath,
|
||||
float intensity)
|
||||
{
|
||||
std::packaged_task<void()> lambda(
|
||||
[=]
|
||||
{ load_ibl(viewer, iblPath, intensity); });
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
void remove_skybox_render_thread(TViewer *viewer)
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE void remove_skybox_render_thread(TViewer *viewer)
|
||||
{
|
||||
std::packaged_task<void()> lambda([=]
|
||||
{ remove_skybox(viewer); });
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
void remove_ibl_render_thread(TViewer *viewer)
|
||||
EMSCRIPTEN_KEEPALIVE void remove_ibl_render_thread(TViewer *viewer)
|
||||
{
|
||||
std::packaged_task<void()> lambda([=]
|
||||
{ remove_ibl(viewer); });
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
void remove_entity_render_thread(TViewer *viewer,
|
||||
EMSCRIPTEN_KEEPALIVE void remove_entity_render_thread(TViewer *viewer,
|
||||
EntityId asset, void (*callback)())
|
||||
{
|
||||
std::packaged_task<void()> lambda([=]
|
||||
@@ -422,7 +427,7 @@ extern "C"
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
void clear_entities_render_thread(TViewer *viewer, void (*callback)())
|
||||
EMSCRIPTEN_KEEPALIVE void clear_entities_render_thread(TViewer *viewer, void (*callback)())
|
||||
{
|
||||
std::packaged_task<void()> lambda([=]
|
||||
{
|
||||
@@ -433,7 +438,7 @@ extern "C"
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EMSCRIPTEN_KEEPALIVE void
|
||||
get_morph_target_name_render_thread(TSceneManager *sceneManager, EntityId assetEntity,
|
||||
EntityId childEntity, char *const outPtr, int index, void (*callback)())
|
||||
{
|
||||
@@ -445,7 +450,7 @@ extern "C"
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
void
|
||||
EMSCRIPTEN_KEEPALIVE void
|
||||
get_morph_target_name_count_render_thread(TSceneManager *sceneManager, EntityId assetEntity,
|
||||
EntityId childEntity, void (*callback)(int))
|
||||
{
|
||||
@@ -457,7 +462,7 @@ extern "C"
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
void set_animation_frame_render_thread(TSceneManager *sceneManager,
|
||||
EMSCRIPTEN_KEEPALIVE void set_animation_frame_render_thread(TSceneManager *sceneManager,
|
||||
EntityId asset,
|
||||
int animationIndex,
|
||||
int animationFrame)
|
||||
@@ -467,7 +472,7 @@ extern "C"
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
void stop_animation_render_thread(TSceneManager *sceneManager,
|
||||
EMSCRIPTEN_KEEPALIVE void stop_animation_render_thread(TSceneManager *sceneManager,
|
||||
EntityId asset, int index)
|
||||
{
|
||||
std::packaged_task<void()> lambda(
|
||||
@@ -476,7 +481,7 @@ extern "C"
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
void get_animation_count_render_thread(TSceneManager *sceneManager,
|
||||
EMSCRIPTEN_KEEPALIVE void get_animation_count_render_thread(TSceneManager *sceneManager,
|
||||
EntityId asset,
|
||||
void (*callback)(int))
|
||||
{
|
||||
@@ -490,7 +495,7 @@ extern "C"
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
void get_animation_name_render_thread(TSceneManager *sceneManager,
|
||||
EMSCRIPTEN_KEEPALIVE void get_animation_name_render_thread(TSceneManager *sceneManager,
|
||||
EntityId asset,
|
||||
char *const outPtr,
|
||||
int index,
|
||||
@@ -505,7 +510,7 @@ extern "C"
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
void
|
||||
EMSCRIPTEN_KEEPALIVE void
|
||||
get_name_for_entity_render_thread(TSceneManager *sceneManager, const EntityId entityId, void (*callback)(const char *))
|
||||
{
|
||||
std::packaged_task<const char *()> lambda(
|
||||
@@ -518,7 +523,7 @@ extern "C"
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
void set_morph_target_weights_render_thread(TSceneManager *sceneManager,
|
||||
EMSCRIPTEN_KEEPALIVE void set_morph_target_weights_render_thread(TSceneManager *sceneManager,
|
||||
EntityId asset,
|
||||
const float *const morphData,
|
||||
int numWeights,
|
||||
@@ -533,7 +538,7 @@ extern "C"
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
void set_bone_transform_render_thread(
|
||||
EMSCRIPTEN_KEEPALIVE void set_bone_transform_render_thread(
|
||||
TSceneManager *sceneManager,
|
||||
EntityId asset,
|
||||
int skinIndex,
|
||||
@@ -551,7 +556,7 @@ extern "C"
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
void update_bone_matrices_render_thread(TSceneManager *sceneManager,
|
||||
EMSCRIPTEN_KEEPALIVE void update_bone_matrices_render_thread(TSceneManager *sceneManager,
|
||||
EntityId entity, void (*callback)(bool))
|
||||
{
|
||||
std::packaged_task<void()> lambda(
|
||||
@@ -563,7 +568,7 @@ extern "C"
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
void View_setToneMappingRenderThread(TView *tView, TEngine *tEngine, thermion::ToneMapping toneMapping) {
|
||||
EMSCRIPTEN_KEEPALIVE void View_setToneMappingRenderThread(TView *tView, TEngine *tEngine, thermion::ToneMapping toneMapping) {
|
||||
std::packaged_task<void()> lambda(
|
||||
[=]
|
||||
{
|
||||
@@ -572,7 +577,7 @@ extern "C"
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
void View_setBloomRenderThread(TView *tView, double bloom) {
|
||||
EMSCRIPTEN_KEEPALIVE void View_setBloomRenderThread(TView *tView, double bloom) {
|
||||
std::packaged_task<void()> lambda(
|
||||
[=]
|
||||
{
|
||||
@@ -581,7 +586,7 @@ extern "C"
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
void reset_to_rest_pose_render_thread(TSceneManager *sceneManager, EntityId entityId, void (*callback)())
|
||||
EMSCRIPTEN_KEEPALIVE void reset_to_rest_pose_render_thread(TSceneManager *sceneManager, EntityId entityId, void (*callback)())
|
||||
{
|
||||
std::packaged_task<void()> lambda(
|
||||
[=]
|
||||
@@ -592,7 +597,7 @@ extern "C"
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
void create_geometry_render_thread(
|
||||
EMSCRIPTEN_KEEPALIVE void create_geometry_render_thread(
|
||||
TSceneManager *sceneManager,
|
||||
float *vertices,
|
||||
int numVertices,
|
||||
@@ -617,7 +622,7 @@ extern "C"
|
||||
auto fut = _rl->add_task(lambda);
|
||||
}
|
||||
|
||||
void unproject_texture_render_thread(TViewer* viewer, EntityId entity, uint8_t *input, uint32_t inputWidth, uint32_t inputHeight, uint8_t *out, uint32_t outWidth, uint32_t outHeight, void (*callback)())
|
||||
EMSCRIPTEN_KEEPALIVE void unproject_texture_render_thread(TViewer* viewer, EntityId entity, uint8_t *input, uint32_t inputWidth, uint32_t inputHeight, uint8_t *out, uint32_t outWidth, uint32_t outHeight, void (*callback)())
|
||||
{
|
||||
std::packaged_task<void()> lambda(
|
||||
[=]
|
||||
|
||||
36
thermion_dart/native/src/ThermionWin32.h
Normal file
36
thermion_dart/native/src/ThermionWin32.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#pragma comment(lib, "Shlwapi.lib")
|
||||
#pragma comment(lib, "opengl32.lib")
|
||||
#pragma comment(lib, "gdi32.lib")
|
||||
#pragma comment(lib, "user32.lib")
|
||||
#pragma comment(lib, "shell32.lib")
|
||||
#pragma comment(lib, "dwmapi.lib")
|
||||
#pragma comment(lib, "comctl32.lib")
|
||||
#pragma comment(lib, "filament.lib")
|
||||
#pragma comment(lib, "bluevk.lib")
|
||||
#pragma comment(lib, "bluegl.lib")
|
||||
#pragma comment(lib, "backend.lib")
|
||||
#pragma comment(lib, "filameshio.lib")
|
||||
#pragma comment(lib, "viewer.lib")
|
||||
#pragma comment(lib, "filamat.lib")
|
||||
#pragma comment(lib, "geometry.lib")
|
||||
#pragma comment(lib, "utils.lib")
|
||||
#pragma comment(lib, "filabridge.lib")
|
||||
#pragma comment(lib, "gltfio_core.lib")
|
||||
#pragma comment(lib, "filament-iblprefilter.lib")
|
||||
#pragma comment(lib, "image.lib")
|
||||
#pragma comment(lib, "imageio.lib")
|
||||
#pragma comment(lib, "tinyexr.lib")
|
||||
#pragma comment(lib, "filaflat.lib")
|
||||
#pragma comment(lib, "dracodec.lib")
|
||||
#pragma comment(lib, "ibl.lib")
|
||||
#pragma comment(lib, "ktxreader.lib")
|
||||
#pragma comment(lib, "png.lib")
|
||||
#pragma comment(lib, "z.lib")
|
||||
#pragma comment(lib, "stb.lib")
|
||||
#pragma comment(lib, "uberzlib.lib")
|
||||
#pragma comment(lib, "smol-v.lib")
|
||||
#pragma comment(lib, "uberarchive.lib")
|
||||
#pragma comment(lib, "zstd.lib")
|
||||
#pragma comment(lib, "basis_transcoder.lib")
|
||||
@@ -177,6 +177,8 @@ namespace filament
|
||||
case Mode::ORBIT:
|
||||
return new OrbitManipulator<FLOAT>(mode, details);
|
||||
}
|
||||
// just to make MSVC happy
|
||||
return new OrbitManipulator<FLOAT>(mode, details);
|
||||
}
|
||||
|
||||
template <typename FLOAT>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: thermion_dart
|
||||
description: 3D rendering toolkit for Dart.
|
||||
version: 0.2.1-dev.0.0.1
|
||||
version: 0.2.1-dev.0.0.7
|
||||
homepage: https://thermion.dev
|
||||
repository: https://github.com/nmfisher/thermion
|
||||
|
||||
@@ -11,8 +11,9 @@ dependencies:
|
||||
vector_math: ^2.1.2
|
||||
plugin_platform_interface: ^2.0.0
|
||||
ffi: ^2.1.2
|
||||
animation_tools_dart: ^0.0.4
|
||||
animation_tools_dart: ^0.1.0
|
||||
native_toolchain_c: ^0.4.2
|
||||
native_assets_cli: ^0.6.1
|
||||
archive: ^3.6.1
|
||||
web: ^1.0.0
|
||||
logging: ^1.2.0
|
||||
|
||||
36
thermion_dart/test/animation_tests.dart
Normal file
36
thermion_dart/test/animation_tests.dart
Normal file
@@ -0,0 +1,36 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'dart:math';
|
||||
import 'dart:typed_data';
|
||||
import 'package:animation_tools_dart/animation_tools_dart.dart';
|
||||
import 'package:thermion_dart/src/viewer/src/events.dart';
|
||||
import 'package:thermion_dart/thermion_dart.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'package:vector_math/vector_math_64.dart';
|
||||
import 'helpers.dart';
|
||||
|
||||
void main() async {
|
||||
final testHelper = TestHelper("animation");
|
||||
|
||||
group('morph animation tests', () {
|
||||
test('set morph animation', () async {
|
||||
var viewer = await testHelper.createViewer(
|
||||
bg: kRed, cameraPosition: Vector3(0, 0, 5));
|
||||
|
||||
final cube = await viewer
|
||||
.loadGlb("${testHelper.testDir}/assets/cube_with_morph_targets.glb");
|
||||
var morphData = MorphAnimationData(
|
||||
Float32List.fromList(List<double>.generate(60, (i) => i / 60)),
|
||||
["Key 1"]);
|
||||
|
||||
await viewer.setMorphAnimationData(cube, morphData);
|
||||
for (int i = 0; i < 60; i++) {
|
||||
await viewer.requestFrame();
|
||||
await Future.delayed(Duration(milliseconds: 17));
|
||||
}
|
||||
|
||||
await testHelper.capture(viewer, "morph_animation");
|
||||
await viewer.dispose();
|
||||
});
|
||||
});
|
||||
}
|
||||
Binary file not shown.
BIN
thermion_dart/test/assets/cube_with_morph_targets.glb
Normal file
BIN
thermion_dart/test/assets/cube_with_morph_targets.glb
Normal file
Binary file not shown.
@@ -6,7 +6,7 @@ import 'dart:typed_data';
|
||||
import 'package:ffi/ffi.dart';
|
||||
import 'package:image/image.dart';
|
||||
import 'swift/swift_bindings.g.dart';
|
||||
import 'package:thermion_dart/src/utils/dart_resources.dart';
|
||||
import 'package:thermion_dart/src/utils/src/dart_resources.dart';
|
||||
import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_dart.g.dart';
|
||||
import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_viewer_ffi.dart';
|
||||
import 'package:thermion_dart/src/viewer/src/ffi/thermion_viewer_ffi.dart';
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:test/test.dart';
|
||||
import 'package:thermion_dart/thermion_dart.dart';
|
||||
import 'package:vector_math/vector_math_64.dart';
|
||||
@@ -17,7 +19,8 @@ void main() async {
|
||||
var viewer = await testHelper.createViewer();
|
||||
|
||||
final texture = await testHelper.createTexture(500, 500);
|
||||
final renderTarget = await viewer.createRenderTarget(500, 500, texture.metalTextureAddress);
|
||||
final renderTarget = await viewer.createRenderTarget(
|
||||
500, 500, texture.metalTextureAddress);
|
||||
viewer.setRenderTarget(renderTarget);
|
||||
|
||||
await viewer.setBackgroundColor(1.0, 0, 0, 1);
|
||||
@@ -76,14 +79,15 @@ void main() async {
|
||||
|
||||
var mainCamera = await viewer.getMainCamera();
|
||||
mainCamera.setTransform(Matrix4.translation(Vector3(0, 0, 5)));
|
||||
final swapChain = await viewer.createSwapChain(1, 1);
|
||||
final swapChain = await viewer.createHeadlessSwapChain(1, 1);
|
||||
await testHelper.capture(
|
||||
viewer, "create_swapchain_default_view_default_swapchain");
|
||||
|
||||
final view = await viewer.createView();
|
||||
|
||||
final texture = await testHelper.createTexture(200, 400);
|
||||
final renderTarget = await viewer.createRenderTarget(200, 400, texture.metalTextureAddress);
|
||||
final renderTarget = await viewer.createRenderTarget(
|
||||
200, 400, texture.metalTextureAddress);
|
||||
await view.setRenderTarget(renderTarget);
|
||||
|
||||
await view.updateViewport(200, 400);
|
||||
@@ -100,5 +104,30 @@ void main() async {
|
||||
|
||||
await viewer.dispose();
|
||||
});
|
||||
|
||||
test('pick', () async {
|
||||
var viewer = await testHelper.createViewer(
|
||||
bg: kRed, cameraPosition: Vector3(0, 0, 5));
|
||||
|
||||
final cube = await viewer.createGeometry(GeometryHelper.cube());
|
||||
|
||||
final completer = Completer();
|
||||
late StreamSubscription listener;
|
||||
listener = viewer.pickResult.listen((result) async {
|
||||
completer.complete(result.entity);
|
||||
await listener.cancel();
|
||||
});
|
||||
|
||||
viewer.pick(250, 250);
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
await viewer.requestFrame();
|
||||
await Future.delayed(Duration(milliseconds: 100));
|
||||
}
|
||||
|
||||
expect(completer.isCompleted, true);
|
||||
expect(await completer.future, cube);
|
||||
await viewer.dispose();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import 'dart:math';
|
||||
import 'package:ffi/ffi.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'swift/swift_bindings.g.dart';
|
||||
import 'package:thermion_dart/src/utils/dart_resources.dart';
|
||||
import 'package:thermion_dart/src/utils/src/dart_resources.dart';
|
||||
import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_dart.g.dart';
|
||||
import 'package:thermion_dart/src/viewer/src/ffi/thermion_viewer_ffi.dart';
|
||||
import 'package:thermion_dart/thermion_dart.dart';
|
||||
|
||||
@@ -2,7 +2,7 @@ import 'dart:ffi';
|
||||
import 'dart:io';
|
||||
import 'package:ffi/ffi.dart';
|
||||
import 'swift/swift_bindings.g.dart';
|
||||
import 'package:thermion_dart/src/utils/dart_resources.dart';
|
||||
import 'package:thermion_dart/src/utils/src/dart_resources.dart';
|
||||
import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_dart.g.dart';
|
||||
import 'package:thermion_dart/src/viewer/src/ffi/thermion_viewer_ffi.dart';
|
||||
|
||||
|
||||
@@ -1,3 +1,27 @@
|
||||
## 0.2.1-dev.6
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
## 0.2.1-dev.5
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
## 0.2.1-dev.4
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
## 0.2.1-dev.3
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
## 0.2.1-dev.2
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
## 0.2.1-dev.1
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
## 0.2.1-dev.0
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
@@ -110,7 +110,7 @@ class _ThermionListenerWidgetState extends State<ThermionListenerWidget> {
|
||||
|
||||
Widget _mobile(double pixelRatio) {
|
||||
return _MobileListenerWidget(
|
||||
gestureHandler: widget.gestureHandler, pixelRatio: pixelRatio);
|
||||
gestureHandler: widget.gestureHandler, pixelRatio: pixelRatio, child:widget.child);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -135,8 +135,10 @@ class _ThermionListenerWidgetState extends State<ThermionListenerWidget> {
|
||||
class _MobileListenerWidget extends StatefulWidget {
|
||||
final InputHandler gestureHandler;
|
||||
final double pixelRatio;
|
||||
final Widget? child;
|
||||
|
||||
const _MobileListenerWidget({Key? key, required this.gestureHandler, required this.pixelRatio})
|
||||
const _MobileListenerWidget(
|
||||
{Key? key, required this.gestureHandler, required this.pixelRatio, this.child})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
@@ -154,22 +156,29 @@ class _MobileListenerWidgetState extends State<_MobileListenerWidget> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
behavior: HitTestBehavior.translucent,
|
||||
onTapDown: (details) => widget.gestureHandler
|
||||
.onPointerDown(details.localPosition.toVector2() * widget.pixelRatio, false),
|
||||
onDoubleTap: () {
|
||||
widget.gestureHandler.setActionForType(InputType.SCALE1,
|
||||
isPan ? InputAction.TRANSLATE : InputAction.ROTATE);
|
||||
},
|
||||
onScaleStart: (details) async {
|
||||
await widget.gestureHandler.onScaleStart();
|
||||
},
|
||||
onScaleUpdate: (details) async {
|
||||
await widget.gestureHandler.onScaleUpdate();
|
||||
},
|
||||
onScaleEnd: (details) async {
|
||||
await widget.gestureHandler.onScaleUpdate();
|
||||
},
|
||||
);
|
||||
behavior: HitTestBehavior.translucent,
|
||||
onTapDown: (details) => widget.gestureHandler.onPointerDown(
|
||||
details.localPosition.toVector2() * widget.pixelRatio, false),
|
||||
onDoubleTap: () {
|
||||
widget.gestureHandler.setActionForType(InputType.SCALE1,
|
||||
isPan ? InputAction.TRANSLATE : InputAction.ROTATE);
|
||||
},
|
||||
onScaleStart: (details) async {
|
||||
await widget.gestureHandler.onScaleStart(
|
||||
details.localFocalPoint.toVector2(), details.pointerCount);
|
||||
},
|
||||
onScaleUpdate: (ScaleUpdateDetails details) async {
|
||||
await widget.gestureHandler.onScaleUpdate(
|
||||
details.localFocalPoint.toVector2(),
|
||||
details.focalPointDelta.toVector2(),
|
||||
details.horizontalScale,
|
||||
details.verticalScale,
|
||||
details.scale,
|
||||
details.pointerCount);
|
||||
},
|
||||
onScaleEnd: (details) async {
|
||||
await widget.gestureHandler.onScaleEnd(details.pointerCount);
|
||||
},
|
||||
child: widget.child);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ class ThermionWidget extends StatefulWidget {
|
||||
final ThermionViewer viewer;
|
||||
|
||||
///
|
||||
/// The [View] associated with this widget. If null, the default View will be used.
|
||||
/// The [t.View] associated with this widget. If null, the default View will be used.
|
||||
///
|
||||
final t.View? view;
|
||||
|
||||
@@ -95,7 +95,7 @@ class _ThermionWidgetState extends State<ThermionWidget> {
|
||||
}
|
||||
|
||||
if (Platform.isWindows) {
|
||||
return ThermionWidgetWindows(viewer: widget.viewer);
|
||||
return ThermionWidgetWindows(viewer: widget.viewer, view: view!, initial: widget.initial, onResize: widget.onResize);
|
||||
}
|
||||
|
||||
return ThermionTextureWidget(
|
||||
|
||||
@@ -1,14 +1,168 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:thermion_flutter/thermion_flutter.dart';
|
||||
import 'package:thermion_flutter/src/widgets/src/resize_observer.dart';
|
||||
import 'package:thermion_flutter/src/widgets/src/transparent_filament_widget.dart';
|
||||
import 'package:thermion_flutter/thermion_flutter.dart' as t;
|
||||
import 'package:thermion_flutter_platform_interface/thermion_flutter_window.dart';
|
||||
|
||||
class ThermionWidgetWindows extends StatelessWidget {
|
||||
class ThermionWidgetWindows extends StatefulWidget {
|
||||
|
||||
final ThermionViewer viewer;
|
||||
final t.ThermionViewer viewer;
|
||||
|
||||
final t.View view;
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
final Widget? initial;
|
||||
|
||||
///
|
||||
/// A callback that will be invoked whenever this widget (and the underlying texture is resized).
|
||||
///
|
||||
final Future Function(Size size, t.View view, double pixelRatio)? onResize;
|
||||
|
||||
const ThermionWidgetWindows({super.key, required this.viewer, this.initial, this.onResize, required this.view});
|
||||
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _ThermionWidgetWindowsState();
|
||||
}
|
||||
|
||||
class _ThermionWidgetWindowsState extends State<ThermionWidgetWindows> {
|
||||
|
||||
ThermionFlutterWindow? _window;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
||||
await widget.viewer.initialized;
|
||||
|
||||
var dpr = MediaQuery.of(context).devicePixelRatio;
|
||||
|
||||
final renderBox = ((context.findRenderObject()) as RenderBox);
|
||||
var size = renderBox.size;
|
||||
var width = (size.width * dpr).ceil();
|
||||
var height = (size.height * dpr).ceil();
|
||||
|
||||
final offset = renderBox.localToGlobal(Offset.zero);
|
||||
final offsetLeft = (offset.dx * dpr).toInt();
|
||||
final offsetTop = (offset.dy * dpr).toInt();
|
||||
|
||||
_window = await t.ThermionFlutterPlatform.instance.createWindow(width, height, offsetLeft, offsetTop);
|
||||
|
||||
await widget.view.updateViewport(_window!.width, _window!.height);
|
||||
|
||||
try {
|
||||
await widget.onResize?.call(
|
||||
Size(_window!.width.toDouble(), _window!.height.toDouble()),
|
||||
widget.view,
|
||||
dpr);
|
||||
} catch (err, st) {
|
||||
print(err);
|
||||
print(st);
|
||||
}
|
||||
|
||||
if (mounted) {
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
_requestFrame();
|
||||
|
||||
widget.viewer.onDispose(() async {
|
||||
var window = _window;
|
||||
if (mounted) {
|
||||
setState(() {});
|
||||
}
|
||||
await window?.destroy();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
bool _rendering = false;
|
||||
|
||||
void _requestFrame() {
|
||||
WidgetsBinding.instance.scheduleFrameCallback((d) async {
|
||||
if (widget.viewer.rendering && !_rendering) {
|
||||
_rendering = true;
|
||||
await widget.viewer.requestFrame();
|
||||
_rendering = false;
|
||||
}
|
||||
_requestFrame();
|
||||
});
|
||||
}
|
||||
|
||||
final _resizing = <Future>[];
|
||||
|
||||
Timer? _resizeTimer;
|
||||
|
||||
Future _resize(Size oldSize, Size newSize) async {
|
||||
await Future.wait(_resizing);
|
||||
|
||||
_resizeTimer?.cancel();
|
||||
|
||||
_resizeTimer = Timer(const Duration(milliseconds: 100), () async {
|
||||
await Future.wait(_resizing);
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (newSize.width == _window?.width &&
|
||||
newSize.height == _window?.height) {
|
||||
return;
|
||||
}
|
||||
|
||||
final completer = Completer();
|
||||
|
||||
_resizing.add(completer.future);
|
||||
|
||||
final dpr = MediaQuery.of(context).devicePixelRatio;
|
||||
|
||||
newSize *= dpr;
|
||||
|
||||
var newWidth = newSize.width.ceil();
|
||||
var newHeight = newSize.height.ceil();
|
||||
|
||||
final renderBox = context.findRenderObject() as RenderBox;
|
||||
final offset = renderBox.localToGlobal(Offset.zero);
|
||||
final offsetLeft = (offset.dx * dpr).toInt();
|
||||
final offsetTop = (offset.dy * dpr).toInt();
|
||||
|
||||
await _window?.resize(
|
||||
newWidth,
|
||||
newHeight,
|
||||
offsetLeft,
|
||||
offsetTop,
|
||||
);
|
||||
|
||||
await widget.view.updateViewport(_window!.width, _window!.height);
|
||||
|
||||
await widget.onResize?.call(
|
||||
Size(_window!.width.toDouble(), _window!.height.toDouble()),
|
||||
widget.view,
|
||||
dpr);
|
||||
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
setState(() {});
|
||||
completer.complete();
|
||||
_resizing.remove(completer.future);
|
||||
});
|
||||
}
|
||||
|
||||
const ThermionWidgetWindows({super.key, required this.viewer});
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// TODO: implement build
|
||||
throw UnimplementedError();
|
||||
if (_window == null) {
|
||||
return widget.initial ?? Container(color: Colors.red);
|
||||
}
|
||||
|
||||
return ResizeObserver(
|
||||
onResized: _resize,
|
||||
child: CustomPaint(painter:TransparencyPainter()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: thermion_flutter
|
||||
description: Flutter plugin for 3D rendering with the Thermion toolkit.
|
||||
version: 0.2.1-dev.0
|
||||
version: 0.2.1-dev.6
|
||||
homepage: https://thermion.dev
|
||||
repository: https://github.com/nmfisher/thermion
|
||||
|
||||
@@ -16,14 +16,20 @@ dependencies:
|
||||
vector_math: ^2.1.2
|
||||
plugin_platform_interface: ^2.0.0
|
||||
ffi: ^2.1.2
|
||||
animation_tools_dart: ^0.0.4
|
||||
thermion_dart: ^0.2.1-dev.0.0.1
|
||||
thermion_flutter_platform_interface: ^0.2.1-dev.0
|
||||
thermion_flutter_ffi: ^0.2.1-dev.0
|
||||
thermion_flutter_web: ^0.1.0+2
|
||||
animation_tools_dart: ^0.1.0
|
||||
thermion_dart: ^0.2.1-dev.0.0.7
|
||||
thermion_flutter_platform_interface: ^0.2.1-dev.6
|
||||
thermion_flutter_ffi: ^0.2.1-dev.6
|
||||
thermion_flutter_web: ^0.1.0+8
|
||||
logging: ^1.2.0
|
||||
web: ^1.0.0
|
||||
|
||||
dependency_overrides:
|
||||
thermion_dart:
|
||||
path: ../../thermion_dart
|
||||
thermion_flutter_platform_interface:
|
||||
path: ../thermion_flutter_platform_interface
|
||||
thermion_flutter_ffi:
|
||||
path: ../thermion_flutter_ffi
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
||||
@@ -152,8 +152,20 @@ LRESULT CALLBACK FilamentWindowProc(HWND const window, UINT const message,
|
||||
break;
|
||||
}
|
||||
case WM_ERASEBKGND: {
|
||||
// Prevent erasing of |window| when it is unfocused and minimized or
|
||||
// moved out of screen etc.
|
||||
HDC hdc = (HDC)wparam;
|
||||
RECT rect;
|
||||
GetClientRect(window, &rect);
|
||||
|
||||
// Get the BackingWindow instance associated with this window
|
||||
BackingWindow* backing_window = reinterpret_cast<BackingWindow*>(
|
||||
GetWindowLongPtr(window, GWLP_USERDATA));
|
||||
|
||||
if (backing_window) {
|
||||
HBRUSH brush = CreateSolidBrush(RGB(0, 255, 0));
|
||||
FillRect(hdc, &rect, brush);
|
||||
DeleteObject(brush);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case WM_SIZE:
|
||||
@@ -346,8 +358,6 @@ void BackingWindow::Resize(int width, int height, int left, int top) {
|
||||
_top = top;
|
||||
RECT flutterViewRect;
|
||||
::GetWindowRect(_flutterViewWindow, &flutterViewRect);
|
||||
std::cout << "Resizing to " << _width << " x " << _height << " with LT" << _left << " " << _top << " flutter view rect" << flutterViewRect.left << " " << flutterViewRect.top << " " << flutterViewRect.right << " " << flutterViewRect.bottom << std::endl;
|
||||
|
||||
::SetWindowPos(_windowHandle, _flutterRootWindow, flutterViewRect.left + _left,
|
||||
flutterViewRect.top + _top, _width, _height,
|
||||
SWP_NOACTIVATE);
|
||||
|
||||
@@ -172,8 +172,6 @@ void ThermionFlutterPlugin::CreateTexture(
|
||||
auto height = (uint32_t)round(dHeight );
|
||||
auto left = (uint32_t)round(dLeft );
|
||||
auto top = (uint32_t)round(dTop );
|
||||
|
||||
std::cout << "Using " << width << "x" << height << std::endl;
|
||||
|
||||
// create a single shared context for the life of the application
|
||||
// this will be used to create a backing texture and passed to Filament
|
||||
@@ -182,8 +180,10 @@ void ThermionFlutterPlugin::CreateTexture(
|
||||
_context = std::make_unique<FlutterEGLContext>(_pluginRegistrar, _textureRegistrar);
|
||||
#else
|
||||
_context = std::make_unique<WGLContext>(_pluginRegistrar, _textureRegistrar);
|
||||
std::cout << "Created WGL context" << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
_context->CreateRenderingSurface(width, height, std::move(result), left, top);
|
||||
}
|
||||
|
||||
@@ -210,7 +210,7 @@ void ThermionFlutterPlugin::DestroyTexture(
|
||||
void ThermionFlutterPlugin::HandleMethodCall(
|
||||
const flutter::MethodCall<flutter::EncodableValue> &methodCall,
|
||||
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result) {
|
||||
|
||||
// std::cout << methodCall.method_name().c_str() << std::endl;
|
||||
if (methodCall.method_name() == "usesBackingWindow") {
|
||||
result->Success(flutter::EncodableValue(
|
||||
#ifdef WGL_USE_BACKING_WINDOW
|
||||
@@ -239,18 +239,19 @@ void ThermionFlutterPlugin::HandleMethodCall(
|
||||
int dHeight = *(std::get_if<int>(&(args->at(1))));
|
||||
int dLeft = *(std::get_if<int>(&(args->at(2))));
|
||||
int dTop = *(std::get_if<int>(&(args->at(3))));
|
||||
auto width = (uint32_t)round(dWidth );
|
||||
auto height = (uint32_t)round(dHeight );
|
||||
auto left = (uint32_t)round(dLeft );
|
||||
auto top = (uint32_t)round(dTop );
|
||||
auto width = static_cast<uint32_t>(dWidth);
|
||||
auto height = static_cast<uint32_t>(dHeight);
|
||||
auto left = static_cast<uint32_t>(dLeft);
|
||||
auto top = static_cast<uint32_t>(dTop );
|
||||
|
||||
_context->ResizeRenderingSurface(width, height, left, top);
|
||||
result->Success();
|
||||
#else
|
||||
result->Error("ERROR", "resizeWindow is only available when using a backing window");
|
||||
#endif
|
||||
} else if (methodCall.method_name() == "createTexture") {
|
||||
} else if (methodCall.method_name() == "createWindow") {
|
||||
CreateTexture(methodCall, std::move(result));
|
||||
} else if (methodCall.method_name() == "destroyTexture") {
|
||||
} else if (methodCall.method_name() == "destroyWindow") {
|
||||
DestroyTexture(methodCall, std::move(result));
|
||||
} else if (methodCall.method_name() == "getRenderCallback") {
|
||||
flutter::EncodableList resultList;
|
||||
|
||||
@@ -45,7 +45,7 @@ WGLContext::WGLContext(flutter::PluginRegistrarWindows *pluginRegistrar,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
16, // Number of bits for the depthbuffer
|
||||
24, // Number of bits for the depthbuffer
|
||||
0, // Number of bits for the stencilbuffer
|
||||
0, // Number of Aux buffers in the framebuffer.
|
||||
PFD_MAIN_PLANE,
|
||||
@@ -117,6 +117,8 @@ void WGLContext::CreateRenderingSurface(
|
||||
} else {
|
||||
ResizeRenderingSurface(width, height, left, top);
|
||||
}
|
||||
|
||||
// std::cout << "created window size " << width << "x" << height << " at " << left << "," << top << " with backing handle" << _backingWindow->GetHandle() << std::endl;
|
||||
std::vector<flutter::EncodableValue> resultList;
|
||||
resultList.push_back(flutter::EncodableValue()); // return null for Flutter texture ID
|
||||
resultList.push_back(flutter::EncodableValue()); // return null for hardware texture ID
|
||||
|
||||
@@ -1,3 +1,27 @@
|
||||
## 0.2.1-dev.6
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
## 0.2.1-dev.5
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
## 0.2.1-dev.4
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
## 0.2.1-dev.3
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
## 0.2.1-dev.2
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
## 0.2.1-dev.1
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
## 0.2.1-dev.0
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
@@ -7,16 +7,19 @@ import 'package:thermion_flutter_ffi/thermion_flutter_method_channel_interface.d
|
||||
import 'package:thermion_flutter_platform_interface/thermion_flutter_platform_interface.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:thermion_flutter_platform_interface/thermion_flutter_texture.dart';
|
||||
import 'package:thermion_flutter_platform_interface/thermion_flutter_window.dart';
|
||||
|
||||
import 'platform_texture.dart';
|
||||
|
||||
///
|
||||
/// An implementation of [ThermionFlutterPlatform] that uses
|
||||
/// Flutter platform channels to create a rendering context,
|
||||
/// resource loaders, and surface/render target(s).
|
||||
/// resource loaders, and a texture that will be used as a render target
|
||||
/// for a headless swapchain.
|
||||
///
|
||||
class ThermionFlutterTextureBackedPlatform
|
||||
extends ThermionFlutterMethodChannelInterface {
|
||||
|
||||
final _logger = Logger("ThermionFlutterTextureBackedPlatform");
|
||||
|
||||
static SwapChain? _swapChain;
|
||||
@@ -52,11 +55,10 @@ class ThermionFlutterTextureBackedPlatform
|
||||
await texture.resize(width, height, 0, 0);
|
||||
return texture;
|
||||
}
|
||||
|
||||
// On MacOS, we currently use textures/render targets, so there's no window to resize
|
||||
|
||||
@override
|
||||
Future<ThermionFlutterTexture?> resizeWindow(
|
||||
int width, int height, int offsetTop, int offsetRight) {
|
||||
Future<ThermionFlutterWindow> createWindow(int width, int height, int offsetLeft, int offsetTop) {
|
||||
// TODO: implement createWindow
|
||||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,34 +1,45 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'dart:ffi';
|
||||
import 'package:thermion_dart/thermion_dart.dart';
|
||||
import 'package:thermion_dart/src/viewer/src/ffi/thermion_viewer_ffi.dart';
|
||||
import 'package:thermion_flutter_ffi/thermion_flutter_method_channel_interface.dart';
|
||||
import 'package:thermion_flutter_platform_interface/thermion_flutter_platform_interface.dart';
|
||||
import 'package:thermion_flutter_platform_interface/thermion_flutter_texture.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:thermion_flutter_platform_interface/thermion_flutter_window.dart';
|
||||
|
||||
///
|
||||
/// An implementation of [ThermionFlutterPlatform] that uses
|
||||
/// Flutter platform channels to create a rendering context,
|
||||
/// resource loaders, and surface/render target(s).
|
||||
/// A Windows-only implementation of [ThermionFlutterPlatform] that uses
|
||||
/// a Flutter platform channel to create a rendering context,
|
||||
/// resource loader and a native HWND that will be sit behind the running
|
||||
/// Flutter application.
|
||||
///
|
||||
class ThermionFlutterWindows
|
||||
extends ThermionFlutterMethodChannelInterface {
|
||||
|
||||
final _channel = const MethodChannel("dev.thermion.flutter/event");
|
||||
|
||||
final _logger = Logger("ThermionFlutterWindows");
|
||||
|
||||
ThermionViewerFFI? _viewer;
|
||||
|
||||
ThermionFlutterWindows._() {}
|
||||
ThermionViewer? _viewer;
|
||||
|
||||
SwapChain? _swapChain;
|
||||
|
||||
ThermionFlutterWindows._() {}
|
||||
|
||||
static void registerWith() {
|
||||
ThermionFlutterPlatform.instance = ThermionFlutterWindows._();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ThermionViewer> createViewer({ThermionFlutterOptions? options}) async {
|
||||
if(_viewer != null) {
|
||||
throw Exception("Only one viewer should be instantiated over the life of the app");
|
||||
}
|
||||
_viewer = await super.createViewer(options: options);
|
||||
return _viewer!;
|
||||
}
|
||||
|
||||
///
|
||||
/// Not supported on Windows. Throws an exception.
|
||||
///
|
||||
@@ -37,64 +48,85 @@ class ThermionFlutterWindows
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
bool _resizing = false;
|
||||
|
||||
@override
|
||||
Future<ThermionFlutterWindow> createWindow(int width, int height, int offsetLeft, int offsetTop) async {
|
||||
|
||||
|
||||
var result = await _channel
|
||||
.invokeMethod("createWindow", [width, height, offsetLeft, offsetLeft]);
|
||||
|
||||
if (result == null || result[2] == -1) {
|
||||
throw Exception("Failed to create window");
|
||||
}
|
||||
|
||||
var window =
|
||||
ThermionFlutterWindowImpl(result[2], _channel, viewer!);
|
||||
await window.resize(width, height, offsetLeft, offsetTop);
|
||||
var view = await _viewer!.getViewAt(0);
|
||||
|
||||
await view.updateViewport(width, height);
|
||||
_swapChain = await _viewer!.createSwapChain(window.handle);
|
||||
await view.setRenderable(true, _swapChain!);
|
||||
return window;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
class ThermionFlutterWindowImpl extends ThermionFlutterWindow {
|
||||
|
||||
final ThermionViewer viewer;
|
||||
final int handle;
|
||||
int height = 0;
|
||||
int width = 0;
|
||||
int offsetLeft = 0;
|
||||
int offsetTop = 0;
|
||||
final MethodChannel _channel;
|
||||
|
||||
|
||||
|
||||
ThermionFlutterWindowImpl(this.handle, this._channel, this.viewer);
|
||||
|
||||
@override
|
||||
Future destroy() async {
|
||||
await _channel
|
||||
.invokeMethod("destroyWindow", this.handle);
|
||||
}
|
||||
|
||||
@override
|
||||
Future markFrameAvailable() {
|
||||
// TODO: implement markFrameAvailable
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
bool _resizing = false;
|
||||
|
||||
///
|
||||
/// Called by [ThermionWidget] to resize a texture. Don't call this yourself.
|
||||
/// Called by [ThermionWidget] to resize the window. Don't call this yourself.
|
||||
///
|
||||
@override
|
||||
Future resizeWindow(
|
||||
Future resize(
|
||||
int width, int height, int offsetLeft, int offsetTop) async {
|
||||
if (_resizing) {
|
||||
throw Exception("Resize underway");
|
||||
}
|
||||
|
||||
throw Exception("TODO");
|
||||
if (width == this.width && height == this.height && this.offsetLeft == offsetLeft && this.offsetTop == offsetTop) {
|
||||
return;
|
||||
}
|
||||
|
||||
// final view = await this._viewer!.getViewAt(0);
|
||||
// final viewport = await view.getViewport();
|
||||
// final swapChain = await this._viewer.getSwapChainAt(0);
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.offsetLeft = offsetLeft;
|
||||
this.offsetTop = offsetTop;
|
||||
|
||||
// if (width == viewport.width && height - viewport.height == 0) {
|
||||
// return;
|
||||
// }
|
||||
_resizing = true;
|
||||
|
||||
// _resizing = true;
|
||||
// bool wasRendering = _viewer!.rendering;
|
||||
// await _viewer!.setRendering(false);
|
||||
// await _swapChain?.destroy();
|
||||
|
||||
// var result = await _channel
|
||||
// .invokeMethod("createTexture", [width, height, offsetLeft, offsetLeft]);
|
||||
|
||||
// if (result == null || result[0] == -1) {
|
||||
// throw Exception("Failed to create texture");
|
||||
// }
|
||||
|
||||
// var newTexture =
|
||||
// ThermionFlutterTexture(result[0], result[1], width, height, result[2]);
|
||||
|
||||
// await _viewer!.createSwapChain(width, height,
|
||||
// surface: newTexture.surfaceAddress == null
|
||||
// ? nullptr
|
||||
// : Pointer<Void>.fromAddress(newTexture.surfaceAddress!));
|
||||
|
||||
// if (newTexture.hardwareTextureId != null) {
|
||||
// // ignore: unused_local_variable
|
||||
// var renderTarget = await _viewer!
|
||||
// .createRenderTarget(width, height, newTexture.hardwareTextureId!);
|
||||
// }
|
||||
|
||||
// await _viewer!
|
||||
// .updateViewportAndCameraProjection(width.toDouble(), height.toDouble());
|
||||
|
||||
// if (wasRendering) {
|
||||
// await _viewer!.setRendering(true);
|
||||
// }
|
||||
// _textures.add(newTexture);
|
||||
// _resizing = false;
|
||||
// return newTexture;
|
||||
await _channel
|
||||
.invokeMethod("resizeWindow", [width, height, offsetLeft, offsetTop]);
|
||||
_resizing = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
name: thermion_flutter_ffi
|
||||
description: An FFI interface for the thermion_flutter plugin (all platforms except web).
|
||||
repository: https://github.com/nmfisher/thermion_flutter/thermion_flutter
|
||||
version: 0.2.1-dev.0
|
||||
version: 0.2.1-dev.6
|
||||
|
||||
environment:
|
||||
sdk: ">=3.3.0 <4.0.0"
|
||||
@@ -22,11 +22,17 @@ dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
plugin_platform_interface: ^2.1.0
|
||||
thermion_flutter_platform_interface: ^0.2.1-dev.0
|
||||
thermion_dart: ^0.2.1-dev.0.0.1
|
||||
thermion_flutter_platform_interface: ^0.2.1-dev.6
|
||||
thermion_dart: ^0.2.1-dev.0.0.7
|
||||
logging: ^1.2.0
|
||||
|
||||
dependency_overrides:
|
||||
thermion_dart:
|
||||
path: ../../thermion_dart
|
||||
thermion_flutter_platform_interface:
|
||||
path: ../thermion_flutter_platform_interface
|
||||
dev_dependencies:
|
||||
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
mockito: ^5.0.0
|
||||
|
||||
@@ -1,3 +1,27 @@
|
||||
## 0.2.1-dev.6
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
## 0.2.1-dev.5
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
## 0.2.1-dev.4
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
## 0.2.1-dev.3
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
## 0.2.1-dev.2
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
## 0.2.1-dev.1
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
## 0.2.1-dev.0
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'package:thermion_dart/thermion_dart.dart' as t;
|
||||
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
|
||||
import 'package:thermion_dart/thermion_dart.dart';
|
||||
import 'thermion_flutter_texture.dart';
|
||||
import 'thermion_flutter_window.dart';
|
||||
|
||||
class ThermionFlutterOptions {
|
||||
final String? uberarchivePath;
|
||||
@@ -41,7 +42,13 @@ abstract class ThermionFlutterPlatform extends PlatformInterface {
|
||||
t.View view, int width, int height);
|
||||
|
||||
///
|
||||
/// Create a rendering window.
|
||||
///
|
||||
/// This is internal; unless you are [thermion_*] package developer, don't
|
||||
/// call this yourself. May not be supported on all platforms.
|
||||
///
|
||||
Future resizeWindow(int width, int height, int offsetTop, int offsetRight);
|
||||
Future<ThermionFlutterWindow> createWindow(
|
||||
int width, int height, int offsetLeft, int offsetTop);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
abstract class ThermionFlutterWindow {
|
||||
|
||||
int get width;
|
||||
int get height;
|
||||
|
||||
int get handle;
|
||||
|
||||
///
|
||||
/// Destroy a texture and clean up the texture cache (if applicable).
|
||||
///
|
||||
Future destroy();
|
||||
|
||||
Future resize(int width, int height, int left, int top);
|
||||
|
||||
Future markFrameAvailable();
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
name: thermion_flutter_platform_interface
|
||||
description: A common platform interface for the thermion_flutter plugin.
|
||||
repository: https://github.com/nmfisher/thermion_flutter/thermion_flutter
|
||||
version: 0.2.1-dev.0
|
||||
version: 0.2.1-dev.6
|
||||
|
||||
environment:
|
||||
sdk: ">=3.3.0 <4.0.0"
|
||||
@@ -11,7 +11,7 @@ dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
plugin_platform_interface: ^2.1.0
|
||||
thermion_dart: ^0.2.1-dev.0.0.1
|
||||
thermion_dart: ^0.2.1-dev.0.0.7
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
||||
@@ -1,3 +1,27 @@
|
||||
## 0.1.0+8
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
## 0.1.0+7
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
## 0.1.0+6
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
## 0.1.0+5
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
## 0.1.0+4
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
## 0.1.0+3
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
## 0.1.0+2
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
name: thermion_flutter_web
|
||||
description: A web platform interface for the thermion_flutter plugin.
|
||||
repository: https://github.com/nmfisher/thermion_flutter/thermion_flutter
|
||||
version: 0.1.0+2
|
||||
version: 0.1.0+8
|
||||
|
||||
environment:
|
||||
sdk: ">=3.3.0 <4.0.0"
|
||||
@@ -20,8 +20,8 @@ dependencies:
|
||||
sdk: flutter
|
||||
plugin_platform_interface: ^2.1.0
|
||||
web: ^1.0.0
|
||||
thermion_dart: ^0.2.1-dev.0.0.1
|
||||
thermion_flutter_platform_interface: ^0.2.1-dev.0
|
||||
thermion_dart: ^0.2.1-dev.0.0.7
|
||||
thermion_flutter_platform_interface: ^0.2.1-dev.6
|
||||
flutter_web_plugins:
|
||||
sdk: flutter
|
||||
|
||||
|
||||
Reference in New Issue
Block a user