chore: update cli_windows project
This commit is contained in:
@@ -1,19 +1,22 @@
|
|||||||
import 'dart:ffi';
|
import 'dart:ffi';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
// import 'package:thermion_dart/thermion_dart/thermion_viewer_ffi.dart';
|
// import 'package:thermion_dart/thermion_dart/thermion_viewer_ffi.dart';
|
||||||
import 'package:thermion_dart/src/utils/src/dart_resources.dart';
|
import 'package:thermion_dart/src/utils/src/dart_resources.dart';
|
||||||
import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_viewer_ffi.dart';
|
import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_viewer_ffi.dart';
|
||||||
import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_dart.g.dart';
|
import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_dart.g.dart';
|
||||||
|
import 'package:thermion_dart/thermion_dart.dart';
|
||||||
|
import 'package:vector_math/vector_math_64.dart';
|
||||||
|
import 'package:cli_windows/thermion_window.g.dart';
|
||||||
|
|
||||||
void main(List<String> arguments) async {
|
void main(List<String> arguments) async {
|
||||||
var lib = DynamicLibrary.open("thermion_windows.dll");
|
var hwnd = create_thermion_window(500, 500, 0, 0);
|
||||||
var createWindow = lib.lookupFunction<Int Function(Int width, Int height, Int left, Int top), int Function(int, int, int, int)>("create_thermion_window");
|
|
||||||
var update = lib.lookupFunction<Void Function(), void Function()>("update");
|
|
||||||
var hwnd = createWindow(500, 500, 0, 0);
|
|
||||||
update();
|
update();
|
||||||
|
|
||||||
|
print("VISIBLE");
|
||||||
|
|
||||||
final resourceLoader = calloc<ResourceLoaderWrapper>(1);
|
final resourceLoader = calloc<ResourceLoaderWrapper>(1);
|
||||||
|
|
||||||
var loadToOut = NativeCallable<
|
var loadToOut = NativeCallable<
|
||||||
@@ -25,26 +28,41 @@ void main(List<String> arguments) async {
|
|||||||
DartResourceLoader.freeResource);
|
DartResourceLoader.freeResource);
|
||||||
resourceLoader.ref.freeResource = freeResource.nativeFunction;
|
resourceLoader.ref.freeResource = freeResource.nativeFunction;
|
||||||
|
|
||||||
var viewer = ThermionViewerFFI(
|
var viewer = ThermionViewerFFI(
|
||||||
|
|
||||||
resourceLoader: resourceLoader.cast<Void>());
|
resourceLoader: resourceLoader.cast<Void>());
|
||||||
|
|
||||||
await viewer.initialized;
|
await viewer.initialized;
|
||||||
var swapChain = await viewer.createSwapChain(hwnd);
|
var swapChain = await viewer.createSwapChain(hwnd);
|
||||||
var view = await viewer.getViewAt(0);
|
var view = await viewer.getViewAt(0);
|
||||||
await view.updateViewport(500, 500);
|
await view.updateViewport(500, 500);
|
||||||
|
var camera = await viewer.getMainCamera();
|
||||||
|
await camera.setLensProjection();
|
||||||
|
|
||||||
await view.setRenderable(true, swapChain);
|
await view.setRenderable(true, swapChain);
|
||||||
|
|
||||||
await viewer.setBackgroundColor(1.0, 0.0, 0.0, 1.0);
|
await viewer.setBackgroundColor(1.0, 0.0, 0.0, 1.0);
|
||||||
|
|
||||||
var skyboxPath = File("..\\..\\assets\\default_env_skybox.ktx").absolute;
|
var skyboxPath = File("..\\..\\assets\\default_env_skybox.ktx").absolute;
|
||||||
|
|
||||||
await viewer.loadSkybox("file://${skyboxPath.uri.toFilePath(windows: true)}");
|
await viewer.loadSkybox("file://${skyboxPath.uri.toFilePath(windows: true)}");
|
||||||
while(true) {
|
|
||||||
|
final cube = await viewer.createGeometry(GeometryHelper.cube());
|
||||||
|
|
||||||
|
var stopwatch = Stopwatch();
|
||||||
|
stopwatch.start();
|
||||||
|
|
||||||
|
var last = 0;
|
||||||
|
|
||||||
|
await viewer.setCameraPosition(0, 0, 10);
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
var angle = (stopwatch.elapsedMilliseconds / 1000) * 2 * pi;
|
||||||
|
var rotation = Quaternion.axisAngle(Vector3(0,1,0), angle);
|
||||||
|
var position = Vector3(10 * sin(angle), 0, 10 * cos(angle));
|
||||||
|
var modelMatrix = Matrix4.compose(position, rotation, Vector3.all(1));
|
||||||
|
await viewer.setCameraModelMatrix4(modelMatrix);
|
||||||
await viewer.render();
|
await viewer.render();
|
||||||
update();
|
|
||||||
await Future.delayed(Duration(milliseconds: 16));
|
await Future.delayed(Duration(milliseconds: 16));
|
||||||
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,132 @@
|
|||||||
#include "thermion_window.h"
|
#pragma comment(lib, "dwmapi.lib")
|
||||||
|
#pragma comment(lib, "comctl32.lib")
|
||||||
|
#pragma comment(lib, "Shlwapi.lib")
|
||||||
|
#pragma comment(lib, "opengl32.lib")
|
||||||
|
#pragma comment(lib, "Gdi32.lib")
|
||||||
|
#pragma comment(lib, "User32.lib")
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <iostream>
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <algorithm>
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <dwmapi.h>
|
#include <dwmapi.h>
|
||||||
#include <ShObjIdl.h>
|
#include <ShObjIdl.h>
|
||||||
|
|
||||||
#pragma comment(lib, "dwmapi.lib")
|
#include <iostream>
|
||||||
#pragma comment(lib, "comctl32.lib")
|
#include <Windows.h>
|
||||||
|
|
||||||
|
#include "thermion_window.h"
|
||||||
|
|
||||||
namespace thermion {
|
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);
|
||||||
|
uint32_t _width = 0;
|
||||||
|
uint32_t _height = 0;
|
||||||
|
uint32_t _left = 0;
|
||||||
|
uint32_t _top = 0;
|
||||||
|
private:
|
||||||
|
HWND _windowHandle;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
static ThermionWindow* _window;
|
||||||
|
|
||||||
|
|
||||||
|
static bool _running = false;
|
||||||
|
static std::thread _renderThread;
|
||||||
|
|
||||||
|
// Add these for timing and stats
|
||||||
|
static int _frameCount = 0;
|
||||||
|
static std::chrono::time_point<std::chrono::steady_clock> _lastFpsLog;
|
||||||
|
|
||||||
|
static void RenderLoop() {
|
||||||
|
_lastFpsLog = std::chrono::steady_clock::now();
|
||||||
|
auto lastFrame = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
|
while (_running) {
|
||||||
|
auto now = std::chrono::steady_clock::now();
|
||||||
|
auto frameDuration = std::chrono::duration_cast<std::chrono::microseconds>(now - lastFrame).count();
|
||||||
|
|
||||||
|
// Force a redraw
|
||||||
|
InvalidateRect(_window->GetHandle(), NULL, FALSE);
|
||||||
|
|
||||||
|
// Process any pending messages
|
||||||
|
MSG msg;
|
||||||
|
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
|
||||||
|
if (msg.message == WM_QUIT) {
|
||||||
|
_running = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessage(&msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for vsync
|
||||||
|
DwmFlush();
|
||||||
|
|
||||||
|
// Update timing stats
|
||||||
|
lastFrame = now;
|
||||||
|
_frameCount++;
|
||||||
|
|
||||||
|
// Log FPS every second
|
||||||
|
auto timeSinceLastLog = std::chrono::duration_cast<std::chrono::milliseconds>(now - _lastFpsLog).count();
|
||||||
|
if (timeSinceLastLog >= 1000) { // Every second
|
||||||
|
float fps = (_frameCount * 1000.0f) / timeSinceLastLog;
|
||||||
|
float avgFrameTime = timeSinceLastLog / (float)_frameCount;
|
||||||
|
std::cout << "FPS: " << fps << " Frame Time: " << avgFrameTime << "ms"
|
||||||
|
<< " Last Frame: " << frameDuration / 1000.0f << "ms" << std::endl;
|
||||||
|
|
||||||
|
_frameCount = 0;
|
||||||
|
_lastFpsLog = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
EMSCRIPTEN_KEEPALIVE intptr_t create_thermion_window(int width, int height, int left, int top) {
|
||||||
|
_window = new ThermionWindow(width, height, left, top);
|
||||||
|
|
||||||
|
// Start the render thread
|
||||||
|
_running = true;
|
||||||
|
_renderThread = std::thread(RenderLoop);
|
||||||
|
|
||||||
|
return (intptr_t)_window->GetHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update function can now be simplified or removed since rendering happens in the thread
|
||||||
|
EMSCRIPTEN_KEEPALIVE void update() {
|
||||||
|
// This could be used to trigger specific updates if needed
|
||||||
|
InvalidateRect(_window->GetHandle(), NULL, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a cleanup function
|
||||||
|
EMSCRIPTEN_KEEPALIVE void cleanup() {
|
||||||
|
_running = false;
|
||||||
|
if (_renderThread.joinable()) {
|
||||||
|
_renderThread.join();
|
||||||
|
}
|
||||||
|
if (_window) {
|
||||||
|
delete _window;
|
||||||
|
_window = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static constexpr auto kClassName = L"THERMION_WINDOW";
|
static constexpr auto kClassName = L"THERMION_WINDOW";
|
||||||
static constexpr auto kWindowName = L"thermion_window";
|
static constexpr auto kWindowName = L"thermion_window";
|
||||||
static bool was_window_hidden_due_to_minimize_ = false;
|
static bool was_window_hidden_due_to_minimize_ = false;
|
||||||
@@ -131,114 +244,126 @@ void SetWindowComposition(HWND window, int32_t accent_state,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Add tracking for drag state
|
||||||
|
static bool isDragging = false;
|
||||||
|
static POINT dragStart = {0, 0};
|
||||||
|
static POINT windowStart = {0, 0};
|
||||||
|
|
||||||
|
|
||||||
LRESULT CALLBACK FilamentWindowProc(HWND const window, UINT const message,
|
LRESULT CALLBACK FilamentWindowProc(HWND const window, UINT const message,
|
||||||
WPARAM const wparam,
|
WPARAM const wparam,
|
||||||
LPARAM const lparam) noexcept {
|
LPARAM const lparam) noexcept {
|
||||||
switch (message) {
|
switch (message) {
|
||||||
std::cout << message <<std::endl;
|
case WM_DESTROY: {
|
||||||
case WM_MOUSEMOVE: {
|
PostQuitMessage(0);
|
||||||
TRACKMOUSEEVENT event;
|
return 0;
|
||||||
event.cbSize = sizeof(event);
|
}
|
||||||
event.hwndTrack = window;
|
case WM_NCHITTEST: {
|
||||||
event.dwFlags = TME_HOVER;
|
POINT pt = { LOWORD(lparam), HIWORD(lparam) };
|
||||||
event.dwHoverTime = 200;
|
ScreenToClient(window, &pt);
|
||||||
auto user_data = ::GetWindowLongPtr(window, GWLP_USERDATA);
|
return HTCAPTION;
|
||||||
if (user_data) {
|
}
|
||||||
HWND flutterRootWindow = reinterpret_cast<HWND>(user_data);
|
|
||||||
::SetForegroundWindow(flutterRootWindow);
|
case WM_MOUSEMOVE: {
|
||||||
LONG ex_style = ::GetWindowLong(flutterRootWindow, GWL_EXSTYLE);
|
TRACKMOUSEEVENT event;
|
||||||
ex_style &= ~(WS_EX_TRANSPARENT | WS_EX_LAYERED);
|
event.cbSize = sizeof(event);
|
||||||
::SetWindowLong(flutterRootWindow, GWL_EXSTYLE, ex_style);
|
event.hwndTrack = window;
|
||||||
|
event.dwFlags = TME_HOVER;
|
||||||
|
event.dwHoverTime = 200;
|
||||||
|
auto user_data = ::GetWindowLongPtr(window, GWLP_USERDATA);
|
||||||
|
if (user_data) {
|
||||||
|
HWND flutterRootWindow = reinterpret_cast<HWND>(user_data);
|
||||||
|
LONG ex_style = ::GetWindowLong(flutterRootWindow, GWL_EXSTYLE);
|
||||||
|
ex_style &= ~(WS_EX_TRANSPARENT | WS_EX_LAYERED);
|
||||||
|
::SetWindowLong(flutterRootWindow, GWL_EXSTYLE, ex_style);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WM_ERASEBKGND: {
|
||||||
|
HDC hdc = (HDC)wparam;
|
||||||
|
RECT rect;
|
||||||
|
GetClientRect(window, &rect);
|
||||||
|
|
||||||
|
ThermionWindow* thermionWindow = reinterpret_cast<ThermionWindow*>(
|
||||||
|
GetWindowLongPtr(window, GWLP_USERDATA));
|
||||||
|
|
||||||
|
if (thermionWindow) {
|
||||||
|
HBRUSH brush = CreateSolidBrush(RGB(0, 0, 255));
|
||||||
|
FillRect(hdc, &rect, brush);
|
||||||
|
DeleteObject(brush);
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WM_SIZE:
|
||||||
|
case WM_MOVE:
|
||||||
|
case WM_MOVING:
|
||||||
|
case WM_WINDOWPOSCHANGED: {
|
||||||
|
auto user_data = ::GetWindowLongPtr(window, GWLP_USERDATA);
|
||||||
|
if (user_data) {
|
||||||
|
HWND flutterRootWindow = reinterpret_cast<HWND>(user_data);
|
||||||
|
LONG ex_style = ::GetWindowLong(flutterRootWindow, GWL_EXSTYLE);
|
||||||
|
ex_style &= ~(WS_EX_TRANSPARENT | WS_EX_LAYERED);
|
||||||
|
::SetWindowLong(flutterRootWindow, GWL_EXSTYLE, ex_style);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return ::DefWindowProc(window, message, wparam, lparam);
|
||||||
}
|
}
|
||||||
break;
|
return 0;
|
||||||
}
|
|
||||||
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,
|
ThermionWindow::ThermionWindow(int width,
|
||||||
int height,
|
int height,
|
||||||
int left,
|
int left,
|
||||||
int top) : _width(width), _height(height), _left(left), _top(top) {
|
int top) : _width(width), _height(height), _left(left), _top(top) {
|
||||||
// create the HWND for Filament
|
auto window_class = WNDCLASSEX{};
|
||||||
auto window_class = WNDCLASSEX{};
|
::SecureZeroMemory(&window_class, sizeof(window_class));
|
||||||
::SecureZeroMemory(&window_class, sizeof(window_class));
|
window_class.cbSize = sizeof(window_class);
|
||||||
window_class.cbSize = sizeof(window_class);
|
window_class.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
|
||||||
window_class.style = CS_HREDRAW | CS_VREDRAW;
|
window_class.lpfnWndProc = FilamentWindowProc;
|
||||||
window_class.lpfnWndProc = FilamentWindowProc;
|
window_class.hInstance = GetModuleHandle(nullptr);
|
||||||
window_class.hInstance = 0;
|
window_class.lpszClassName = L"THERMION_WINDOW";
|
||||||
window_class.lpszClassName = kClassName;
|
window_class.hCursor = ::LoadCursorW(nullptr, IDC_ARROW);
|
||||||
window_class.hCursor = ::LoadCursorW(nullptr, IDC_ARROW);
|
window_class.hbrBackground = ::CreateSolidBrush(RGB(0,255,0));
|
||||||
window_class.hbrBackground = ::CreateSolidBrush(RGB(0,255,0));
|
::RegisterClassExW(&window_class);
|
||||||
::RegisterClassExW(&window_class);
|
|
||||||
_windowHandle = ::CreateWindow(kClassName, kWindowName, WS_OVERLAPPEDWINDOW,
|
|
||||||
0, 0, _width, _height, nullptr,
|
|
||||||
nullptr, GetModuleHandle(nullptr), nullptr);
|
|
||||||
|
|
||||||
// Disable DWM animations
|
// Create a normal popup window without forcing it to be topmost
|
||||||
auto disable_window_transitions = TRUE;
|
_windowHandle = ::CreateWindowW(
|
||||||
DwmSetWindowAttribute(_windowHandle, DWMWA_TRANSITIONS_FORCEDISABLED,
|
L"THERMION_WINDOW",
|
||||||
|
L"thermion_window",
|
||||||
|
WS_OVERLAPPEDWINDOW,
|
||||||
|
left, top, width, height,
|
||||||
|
nullptr, nullptr,
|
||||||
|
GetModuleHandle(nullptr),
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
|
||||||
|
// Store the this pointer for use in window procedure
|
||||||
|
::SetWindowLongPtr(_windowHandle, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
|
||||||
|
|
||||||
|
// Disable DWM animations
|
||||||
|
auto disable_window_transitions = TRUE;
|
||||||
|
DwmSetWindowAttribute(_windowHandle, DWMWA_TRANSITIONS_FORCEDISABLED,
|
||||||
&disable_window_transitions,
|
&disable_window_transitions,
|
||||||
sizeof(disable_window_transitions));
|
sizeof(disable_window_transitions));
|
||||||
|
|
||||||
auto style = ::GetWindowLong(_windowHandle, GWL_STYLE);
|
::ShowWindow(_windowHandle, SW_SHOW);
|
||||||
style &= ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX |
|
UpdateWindow(_windowHandle);
|
||||||
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) {
|
void ThermionWindow::Resize(int width, int height, int left, int top) {
|
||||||
_width = width;
|
_width = width;
|
||||||
_height = height;
|
_height = height;
|
||||||
_left = left;
|
_left = left;
|
||||||
_top = top;
|
_top = top;
|
||||||
|
::SetWindowPos(_windowHandle, nullptr, left, top, width, height,
|
||||||
|
SWP_NOZORDER | SWP_NOACTIVATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
HWND ThermionWindow::GetHandle() { return _windowHandle; }
|
HWND ThermionWindow::GetHandle() { return _windowHandle; }
|
||||||
} // namespace thermion_flutter
|
|
||||||
|
} // namespace thermion
|
||||||
@@ -1,64 +1,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#pragma comment(lib, "Shlwapi.lib")
|
|
||||||
#pragma comment(lib, "opengl32.lib")
|
|
||||||
#pragma comment(lib, "dwmapi.lib")
|
|
||||||
#pragma comment(lib, "comctl32.lib")
|
|
||||||
#pragma comment(lib, "Gdi32.lib")
|
|
||||||
#pragma comment(lib, "User32.lib")
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#ifdef IS_DLL
|
#ifdef IS_DLL
|
||||||
#define EMSCRIPTEN_KEEPALIVE __declspec(dllimport)
|
#define EMSCRIPTEN_KEEPALIVE __declspec(dllimport)
|
||||||
#else
|
#else
|
||||||
#define EMSCRIPTEN_KEEPALIVE __declspec(dllexport)
|
#define EMSCRIPTEN_KEEPALIVE __declspec(dllexport)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <cstdint>
|
extern "C" {
|
||||||
#include <iostream>
|
|
||||||
#include <Windows.h>
|
|
||||||
|
|
||||||
namespace thermion {
|
intptr_t create_thermion_window(int width, int height, int left, int top);
|
||||||
|
void update();
|
||||||
|
|
||||||
///
|
}
|
||||||
/// 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
|
|
||||||
@@ -28,8 +28,12 @@ ffigen:
|
|||||||
include-directives:
|
include-directives:
|
||||||
- 'native/thermion_window.h'
|
- 'native/thermion_window.h'
|
||||||
ffi-native:
|
ffi-native:
|
||||||
assetId: package:thermion_window/thermion_window.dart
|
assetId: package:cli_windows/thermion_window.dart
|
||||||
ignore-source-errors: true
|
ignore-source-errors: true
|
||||||
|
llvm-path:
|
||||||
|
- E:\clang+llvm-19.1.3-x86_64-pc-windows-msvc\bin
|
||||||
|
- E:\clang+llvm-19.1.3-x86_64-pc-windows-msvc\
|
||||||
|
- E:\clang+llvm-19.1.3-x86_64-pc-windows-msvc\lib
|
||||||
functions:
|
functions:
|
||||||
leaf:
|
leaf:
|
||||||
include:
|
include:
|
||||||
|
|||||||
Reference in New Issue
Block a user