Retain Win32 entry state and trim canvas/platform seams
This commit is contained in:
@@ -18,6 +18,23 @@ agent or engineer to remove them without reconstructing context from chat.
|
|||||||
|
|
||||||
## Reductions
|
## Reductions
|
||||||
|
|
||||||
|
- 2026-06-16: `DEBT-0003` was narrowed again. `src/main.cpp` now keeps Win32
|
||||||
|
window handles, GL/task mutex state, stylus timers, splash-dialog state, and
|
||||||
|
VR worker state behind one retained local state object instead of separate
|
||||||
|
file-scope globals; retained entrypoint orchestration, direct `App::I`
|
||||||
|
mutation, and broader platform/runtime coupling remain.
|
||||||
|
- 2026-06-16: `DEBT-0017` was narrowed again. Retained GLFW window hooks and
|
||||||
|
the non-Linux fallback storage-path return in
|
||||||
|
`src/platform_legacy/legacy_platform_services.cpp` now route through local
|
||||||
|
retained-state helpers instead of direct method-body `App::I` reads; the
|
||||||
|
retained platform fallback adapter and broader platform-to-app singleton
|
||||||
|
reach remain.
|
||||||
|
- 2026-06-16: `DEBT-0036` was narrowed again. `NodeCanvas` heightmap draw
|
||||||
|
callback setup now routes through
|
||||||
|
`make_legacy_canvas_draw_merge_heightmap_draw(...)` in
|
||||||
|
`src/legacy_canvas_draw_merge_services.h` instead of keeping that callback
|
||||||
|
body inline in `NodeCanvas::draw()`; broader canvas draw orchestration and
|
||||||
|
retained GL resource ownership remain.
|
||||||
- 2026-06-16: `DEBT-0003` was narrowed again. The Windows main-loop run-state
|
- 2026-06-16: `DEBT-0003` was narrowed again. The Windows main-loop run-state
|
||||||
and VR worker coordination flags in `src/main.cpp` now use `std::atomic`
|
and VR worker coordination flags in `src/main.cpp` now use `std::atomic`
|
||||||
instead of unsynchronized globals; retained Win32 entrypoint ownership,
|
instead of unsynchronized globals; retained Win32 entrypoint ownership,
|
||||||
|
|||||||
@@ -104,7 +104,9 @@ Current architecture mismatches that must be treated as real blockers:
|
|||||||
while Linux/Web GLFW render-context acquire/present and Linux app-close now
|
while Linux/Web GLFW render-context acquire/present and Linux app-close now
|
||||||
route through retained local GLFW callback hooks, and retained Apple ObjC
|
route through retained local GLFW callback hooks, and retained Apple ObjC
|
||||||
handles plus storage paths now sit behind one local `platform_legacy`
|
handles plus storage paths now sit behind one local `platform_legacy`
|
||||||
helper instead of being re-read through `App::I` in each touched path.
|
helper instead of being re-read through `App::I` in each touched path, with
|
||||||
|
the retained GLFW window hooks and fallback storage-path return now also
|
||||||
|
using local retained-state helpers instead of direct method-body reads.
|
||||||
- `src/platform_legacy/legacy_platform_services.*` is still part of the live
|
- `src/platform_legacy/legacy_platform_services.*` is still part of the live
|
||||||
app shell.
|
app shell.
|
||||||
- `pp_panopainter_ui` still depends on `pp_legacy_app`.
|
- `pp_panopainter_ui` still depends on `pp_legacy_app`.
|
||||||
@@ -115,7 +117,8 @@ Current architecture mismatches that must be treated as real blockers:
|
|||||||
checkerboard background setup now route through retained draw-merge helpers,
|
checkerboard background setup now route through retained draw-merge helpers,
|
||||||
with the cache-to-screen checkerboard-plane callback setup also reduced and
|
with the cache-to-screen checkerboard-plane callback setup also reduced and
|
||||||
the merged-path per-plane merged-texture draw plus the smoothing-mask face
|
the merged-path per-plane merged-texture draw plus the smoothing-mask face
|
||||||
shader/draw pass now routed through the same retained helper family.
|
shader/draw pass plus heightmap callback setup now routed through the same
|
||||||
|
retained helper family.
|
||||||
- `app_layout.cpp` and `app_dialogs.cpp` are still mixed shell/controller files
|
- `app_layout.cpp` and `app_dialogs.cpp` are still mixed shell/controller files
|
||||||
rather than thin composition/binding surfaces.
|
rather than thin composition/binding surfaces.
|
||||||
- `App`, `Canvas`, `Node`, retained workers, and platform entrypoints still use
|
- `App`, `Canvas`, `Node`, retained workers, and platform entrypoints still use
|
||||||
@@ -128,7 +131,9 @@ Current architecture mismatches that must be treated as real blockers:
|
|||||||
also use owned `std::jthread` lifecycle, `LogRemote` now uses the same
|
also use owned `std::jthread` lifecycle, `LogRemote` now uses the same
|
||||||
ownership model, the Windows VR device now has explicit `std::unique_ptr`
|
ownership model, the Windows VR device now has explicit `std::unique_ptr`
|
||||||
ownership instead of raw global lifetime, and the Windows main-loop/VR
|
ownership instead of raw global lifetime, and the Windows main-loop/VR
|
||||||
coordination flags now use `std::atomic` instead of unsynchronized globals.
|
coordination flags now use `std::atomic` instead of unsynchronized globals,
|
||||||
|
while the main Win32 entrypoint now groups window/GL/task/VR state behind a
|
||||||
|
retained local state object instead of separate process-wide globals.
|
||||||
- Modern C++23 usage exists in extracted components, especially `std::span`,
|
- Modern C++23 usage exists in extracted components, especially `std::span`,
|
||||||
explicit result/status objects, and a few concepts, but the live app still
|
explicit result/status objects, and a few concepts, but the live app still
|
||||||
does not consistently express ownership, thread affinity, or renderer
|
does not consistently express ownership, thread affinity, or renderer
|
||||||
|
|||||||
@@ -143,6 +143,9 @@ Current slice:
|
|||||||
draw, heightmap draw, and current-mode draw now also route through
|
draw, heightmap draw, and current-mode draw now also route through
|
||||||
`execute_legacy_canvas_draw_merge_post_draw(...)`, but broader canvas draw
|
`execute_legacy_canvas_draw_merge_post_draw(...)`, but broader canvas draw
|
||||||
orchestration is still inline.
|
orchestration is still inline.
|
||||||
|
- `NodeCanvas` heightmap draw callback setup now also routes through
|
||||||
|
`make_legacy_canvas_draw_merge_heightmap_draw(...)`, but the node still owns
|
||||||
|
current-mode traversal and broader post-draw orchestration.
|
||||||
- `NodeCanvas` smoothing-mask face shader setup plus per-face draw execution
|
- `NodeCanvas` smoothing-mask face shader setup plus per-face draw execution
|
||||||
now also route through
|
now also route through
|
||||||
`execute_legacy_canvas_draw_merge_smask_faces(...)`, but the node still owns
|
`execute_legacy_canvas_draw_merge_smask_faces(...)`, but the node still owns
|
||||||
@@ -341,6 +344,9 @@ Current slice:
|
|||||||
explicit stop requests instead of raw `std::thread`
|
explicit stop requests instead of raw `std::thread`
|
||||||
- Windows main-loop run-state and VR worker coordination flags in `main.cpp`
|
- Windows main-loop run-state and VR worker coordination flags in `main.cpp`
|
||||||
now use `std::atomic` ownership instead of unsynchronized globals
|
now use `std::atomic` ownership instead of unsynchronized globals
|
||||||
|
- `main.cpp` Win32 window handles, GL task/mutex state, splash-dialog state,
|
||||||
|
stylus timers, and VR worker state now sit behind one retained local state
|
||||||
|
object instead of separate file-scope globals
|
||||||
- retained `App` composition, task call sites, and platform/runtime entrypoint
|
- retained `App` composition, task call sites, and platform/runtime entrypoint
|
||||||
coupling are still not fully reduced behind the runtime contract
|
coupling are still not fully reduced behind the runtime contract
|
||||||
|
|
||||||
@@ -616,6 +622,9 @@ Current slice:
|
|||||||
- Linux/Web GLFW render-context acquire/present hooks and Linux app-close now
|
- Linux/Web GLFW render-context acquire/present hooks and Linux app-close now
|
||||||
also route through retained local GLFW callback hooks instead of direct
|
also route through retained local GLFW callback hooks instead of direct
|
||||||
method-body `App::I` access in `LegacyPlatformServices`
|
method-body `App::I` access in `LegacyPlatformServices`
|
||||||
|
- retained GLFW window hooks and the non-Linux fallback storage-path return now
|
||||||
|
also route through retained local state helpers instead of reading `App::I`
|
||||||
|
directly in those method bodies
|
||||||
- retained Apple callback injection and broader `platform_legacy` singleton
|
- retained Apple callback injection and broader `platform_legacy` singleton
|
||||||
reach are still open
|
reach are still open
|
||||||
|
|
||||||
|
|||||||
@@ -239,6 +239,17 @@ struct LegacyCanvasDrawMergePostDrawExecution {
|
|||||||
std::function<void()> draw_current_modes;
|
std::function<void()> draw_current_modes;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename GridT>
|
||||||
|
[[nodiscard]] inline auto make_legacy_canvas_draw_merge_heightmap_draw(
|
||||||
|
GridT* grid,
|
||||||
|
const glm::mat4& proj,
|
||||||
|
const glm::mat4& camera)
|
||||||
|
{
|
||||||
|
return [grid, proj, camera] {
|
||||||
|
grid->draw_heightmap(proj, camera, false);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
struct LegacyCanvasDrawMergeSmaskFacesExecution {
|
struct LegacyCanvasDrawMergeSmaskFacesExecution {
|
||||||
std::function<void()> set_active_texture_unit;
|
std::function<void()> set_active_texture_unit;
|
||||||
std::function<void()> enable_blend;
|
std::function<void()> enable_blend;
|
||||||
|
|||||||
281
src/main.cpp
281
src/main.cpp
@@ -38,31 +38,43 @@
|
|||||||
#define WM_USER_WAKEUP (WM_USER + 2)
|
#define WM_USER_WAKEUP (WM_USER + 2)
|
||||||
|
|
||||||
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp);
|
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp);
|
||||||
HINSTANCE hInst;
|
struct RetainedState
|
||||||
HWND hWnd;
|
{
|
||||||
HDC hDC;
|
HINSTANCE hInst{};
|
||||||
HGLRC hRC;
|
HWND hWnd{};
|
||||||
const wchar_t* className;
|
HDC hDC{};
|
||||||
bool keys[256];
|
HGLRC hRC{};
|
||||||
std::mutex gl_mutex;
|
const wchar_t* className{};
|
||||||
std::mutex async_mutex;
|
bool keys[256]{};
|
||||||
std::thread::id gl_thread;
|
std::mutex gl_mutex;
|
||||||
std::map<kKey, int> vkey_map;
|
std::mutex async_mutex;
|
||||||
static wchar_t window_title[512];
|
std::thread::id gl_thread{};
|
||||||
|
std::map<kKey, int> vkey_map;
|
||||||
|
wchar_t window_title[512]{};
|
||||||
|
std::jthread hmd_renderer;
|
||||||
|
int gl_count = 0;
|
||||||
|
std::deque<std::packaged_task<void()>> main_tasklist;
|
||||||
|
std::mutex main_task_mutex;
|
||||||
|
float timer_stylus = 0;
|
||||||
|
float timer_ink_touch = 0;
|
||||||
|
float timer_ink_pen = 0;
|
||||||
|
bool sandboxed = false;
|
||||||
|
std::mutex hmd_render_mutex;
|
||||||
|
std::condition_variable hmd_render_cv;
|
||||||
|
std::unique_ptr<Vive> vive;
|
||||||
|
HWND splash_dialog{};
|
||||||
|
};
|
||||||
|
|
||||||
|
RetainedState& retained_state()
|
||||||
|
{
|
||||||
|
static RetainedState state;
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
std::jthread hmd_renderer;
|
|
||||||
std::atomic<int> vr_frames{0};
|
std::atomic<int> vr_frames{0};
|
||||||
std::atomic<int> running{-1};
|
std::atomic<int> running{-1};
|
||||||
std::atomic_bool vr_running{false};
|
std::atomic_bool vr_running{false};
|
||||||
|
|
||||||
int gl_count = 0;
|
|
||||||
std::deque<std::packaged_task<void()>> main_tasklist;
|
|
||||||
std::mutex main_task_mutex;
|
|
||||||
float timer_stylus = 0;
|
|
||||||
float timer_ink_touch = 0;
|
|
||||||
float timer_ink_pen = 0;
|
|
||||||
bool sandboxed = false;
|
|
||||||
|
|
||||||
#ifdef USE_RENDERDOC
|
#ifdef USE_RENDERDOC
|
||||||
RENDERDOC_API_1_4_0* rdoc_api = NULL;
|
RENDERDOC_API_1_4_0* rdoc_api = NULL;
|
||||||
bool win32_renderdoc_init()
|
bool win32_renderdoc_init()
|
||||||
@@ -149,8 +161,9 @@ std::string GetLastErrorAsString()
|
|||||||
|
|
||||||
void destroy_window()
|
void destroy_window()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(main_task_mutex);
|
auto& state = retained_state();
|
||||||
main_tasklist.emplace_back([=] {
|
std::lock_guard<std::mutex> lock(state.main_task_mutex);
|
||||||
|
state.main_tasklist.emplace_back([hWnd = state.hWnd] {
|
||||||
PostMessage(hWnd, WM_USER_CLOSE, 0, 0);
|
PostMessage(hWnd, WM_USER_CLOSE, 0, 0);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -158,73 +171,77 @@ void destroy_window()
|
|||||||
void async_lock()
|
void async_lock()
|
||||||
{
|
{
|
||||||
//std::lock_guard<std::mutex> _lock(async_mutex);
|
//std::lock_guard<std::mutex> _lock(async_mutex);
|
||||||
if (gl_count == 0 || gl_thread != std::this_thread::get_id())
|
auto& state = retained_state();
|
||||||
|
if (state.gl_count == 0 || state.gl_thread != std::this_thread::get_id())
|
||||||
{
|
{
|
||||||
gl_mutex.lock();
|
state.gl_mutex.lock();
|
||||||
bool ret = wglMakeCurrent(hDC, hRC);
|
bool ret = wglMakeCurrent(state.hDC, state.hRC);
|
||||||
if (ret == false)
|
if (ret == false)
|
||||||
LOG("FAILED wglMakeCurrent: %s", GetLastErrorAsString().c_str());
|
LOG("FAILED wglMakeCurrent: %s", GetLastErrorAsString().c_str());
|
||||||
gl_thread = std::this_thread::get_id();
|
state.gl_thread = std::this_thread::get_id();
|
||||||
//LOG("lock");
|
//LOG("lock");
|
||||||
}
|
}
|
||||||
gl_count++;
|
state.gl_count++;
|
||||||
//assert(ret == true);
|
//assert(ret == true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool async_lock_try()
|
bool async_lock_try()
|
||||||
{
|
{
|
||||||
//std::lock_guard<std::mutex> _lock(async_mutex);
|
//std::lock_guard<std::mutex> _lock(async_mutex);
|
||||||
if (gl_count == 0 || gl_thread != std::this_thread::get_id())
|
auto& state = retained_state();
|
||||||
|
if (state.gl_count == 0 || state.gl_thread != std::this_thread::get_id())
|
||||||
{
|
{
|
||||||
if (!gl_mutex.try_lock())
|
if (!state.gl_mutex.try_lock())
|
||||||
return false;
|
return false;
|
||||||
bool ret = wglMakeCurrent(hDC, hRC);
|
bool ret = wglMakeCurrent(state.hDC, state.hRC);
|
||||||
if (ret == false)
|
if (ret == false)
|
||||||
LOG("FAILED wglMakeCurrent: %s", GetLastErrorAsString().c_str());
|
LOG("FAILED wglMakeCurrent: %s", GetLastErrorAsString().c_str());
|
||||||
gl_thread = std::this_thread::get_id();
|
state.gl_thread = std::this_thread::get_id();
|
||||||
//LOG("lock");
|
//LOG("lock");
|
||||||
}
|
}
|
||||||
gl_count++;
|
state.gl_count++;
|
||||||
//assert(ret == true);
|
//assert(ret == true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void win32_async_swap()
|
void win32_async_swap()
|
||||||
{
|
{
|
||||||
SwapBuffers(hDC);
|
SwapBuffers(retained_state().hDC);
|
||||||
//LOG("swap");
|
//LOG("swap");
|
||||||
}
|
}
|
||||||
|
|
||||||
void async_unlock()
|
void async_unlock()
|
||||||
{
|
{
|
||||||
//std::lock_guard<std::mutex> _lock(async_mutex);
|
//std::lock_guard<std::mutex> _lock(async_mutex);
|
||||||
gl_count--;
|
auto& state = retained_state();
|
||||||
if (gl_count == 0)
|
state.gl_count--;
|
||||||
|
if (state.gl_count == 0)
|
||||||
{
|
{
|
||||||
//LOG("unlock");
|
//LOG("unlock");
|
||||||
wglMakeCurrent(0, 0);
|
wglMakeCurrent(0, 0);
|
||||||
gl_mutex.unlock();
|
state.gl_mutex.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void win32_update_stylus(float dt)
|
void win32_update_stylus(float dt)
|
||||||
{
|
{
|
||||||
timer_stylus += dt;
|
auto& state = retained_state();
|
||||||
timer_ink_touch += dt;
|
state.timer_stylus += dt;
|
||||||
timer_ink_pen += dt;
|
state.timer_ink_touch += dt;
|
||||||
|
state.timer_ink_pen += dt;
|
||||||
|
|
||||||
if (timer_stylus > 0.1 && (WacomTablet::I.m_stylus || WacomTablet::I.m_eraser))
|
if (state.timer_stylus > 0.1 && (WacomTablet::I.m_stylus || WacomTablet::I.m_eraser))
|
||||||
{
|
{
|
||||||
WacomTablet::I.m_stylus = false;
|
WacomTablet::I.m_stylus = false;
|
||||||
WacomTablet::I.m_eraser = false;
|
WacomTablet::I.m_eraser = false;
|
||||||
App::I->redraw = true;
|
App::I->redraw = true;
|
||||||
}
|
}
|
||||||
if (timer_ink_pen > 0.1 && WacomTablet::I.m_ink_pen)
|
if (state.timer_ink_pen > 0.1 && WacomTablet::I.m_ink_pen)
|
||||||
{
|
{
|
||||||
WacomTablet::I.m_ink_pen = false;
|
WacomTablet::I.m_ink_pen = false;
|
||||||
App::I->redraw = true;
|
App::I->redraw = true;
|
||||||
}
|
}
|
||||||
if (timer_ink_touch > 0.1 && WacomTablet::I.m_ink_touch)
|
if (state.timer_ink_touch > 0.1 && WacomTablet::I.m_ink_touch)
|
||||||
{
|
{
|
||||||
WacomTablet::I.m_ink_touch = false;
|
WacomTablet::I.m_ink_touch = false;
|
||||||
App::I->redraw = true;
|
App::I->redraw = true;
|
||||||
@@ -235,18 +252,19 @@ void win32_update_fps(int frames)
|
|||||||
{
|
{
|
||||||
static wchar_t title_fps[512];
|
static wchar_t title_fps[512];
|
||||||
const int vr_fps = vr_frames.load(std::memory_order_relaxed);
|
const int vr_fps = vr_frames.load(std::memory_order_relaxed);
|
||||||
|
auto& state = retained_state();
|
||||||
if (App::I->vr_active)
|
if (App::I->vr_active)
|
||||||
swprintf_s(title_fps, L"%s - %d fps - %d vr fps", window_title, frames, vr_fps);
|
swprintf_s(title_fps, L"%s - %d fps - %d vr fps", state.window_title, frames, vr_fps);
|
||||||
else
|
else
|
||||||
swprintf_s(title_fps, L"%s - %d fps", window_title, frames);
|
swprintf_s(title_fps, L"%s - %d fps", state.window_title, frames);
|
||||||
|
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(main_task_mutex);
|
std::lock_guard<std::mutex> lock(state.main_task_mutex);
|
||||||
main_tasklist.emplace_back([] {
|
state.main_tasklist.emplace_back([hWnd = state.hWnd] {
|
||||||
SetWindowText(hWnd, title_fps);
|
SetWindowText(hWnd, title_fps);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
PostMessage(hWnd, WM_USER_WAKEUP, 0, 0);
|
PostMessage(state.hWnd, WM_USER_WAKEUP, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int read_WMI_info()
|
int read_WMI_info()
|
||||||
@@ -403,7 +421,7 @@ int read_WMI_info()
|
|||||||
if (get_int(clsObj, L"CodeIntegrityPolicyEnforcementStatus") > 0)
|
if (get_int(clsObj, L"CodeIntegrityPolicyEnforcementStatus") > 0)
|
||||||
{
|
{
|
||||||
LOG("SANDBOX DETECTED");
|
LOG("SANDBOX DETECTED");
|
||||||
sandboxed = true;
|
retained_state().sandboxed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
SAFEARRAY *psaNames = NULL;
|
SAFEARRAY *psaNames = NULL;
|
||||||
@@ -491,7 +509,7 @@ static void SetupExceptionHandler()
|
|||||||
GetFullPathNameA(path.c_str(), MAX_PATH, abspath, NULL);
|
GetFullPathNameA(path.c_str(), MAX_PATH, abspath, NULL);
|
||||||
static char message[4096];
|
static char message[4096];
|
||||||
snprintf(message, sizeof(message), "File recovered in: %s", abspath);
|
snprintf(message, sizeof(message), "File recovered in: %s", abspath);
|
||||||
MessageBoxA(hWnd, message, "File Recovery", MB_OK | MB_ICONWARNING);
|
MessageBoxA(retained_state().hWnd, message, "File Recovery", MB_OK | MB_ICONWARNING);
|
||||||
}
|
}
|
||||||
LogRemote::I.file_close();
|
LogRemote::I.file_close();
|
||||||
}, 0);
|
}, 0);
|
||||||
@@ -500,50 +518,49 @@ static void SetupExceptionHandler()
|
|||||||
// create a reverse map from kKey to VK_XXX
|
// create a reverse map from kKey to VK_XXX
|
||||||
void init_vk_map()
|
void init_vk_map()
|
||||||
{
|
{
|
||||||
|
auto& state = retained_state();
|
||||||
for (int k = 1; k < 256; k++) // ignore kKey::Unknown = 0
|
for (int k = 1; k < 256; k++) // ignore kKey::Unknown = 0
|
||||||
{
|
{
|
||||||
for (int vk = 0; vk < 256; vk++)
|
for (int vk = 0; vk < 256; vk++)
|
||||||
{
|
{
|
||||||
if (k == (int)convert_key(vk))
|
if (k == (int)convert_key(vk))
|
||||||
{
|
{
|
||||||
if (vkey_map.find((kKey)k) == vkey_map.end())
|
if (state.vkey_map.find((kKey)k) == state.vkey_map.end())
|
||||||
{
|
{
|
||||||
vkey_map.insert({ (kKey)k, vk });
|
state.vkey_map.insert({ (kKey)k, vk });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG("KEY MAP COLLISION %d and %d maps to %d",
|
LOG("KEY MAP COLLISION %d and %d maps to %d",
|
||||||
(int)vk, (int)vkey_map[(kKey)k], (int)k);
|
(int)vk, (int)state.vkey_map[(kKey)k], (int)k);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::mutex hmd_render_mutex;
|
|
||||||
std::condition_variable hmd_render_cv;
|
|
||||||
std::unique_ptr<Vive> vive;
|
|
||||||
bool win32_vr_start()
|
bool win32_vr_start()
|
||||||
{
|
{
|
||||||
if (sandboxed)
|
auto& state = retained_state();
|
||||||
|
if (state.sandboxed)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
vive = std::make_unique<Vive>();
|
state.vive = std::make_unique<Vive>();
|
||||||
vive->on_draw = [](const glm::mat4& proj, const glm::mat4& view, const glm::mat4& pose) { App::I->vr_draw(proj, view, pose); };
|
state.vive->on_draw = [](const glm::mat4& proj, const glm::mat4& view, const glm::mat4& pose) { App::I->vr_draw(proj, view, pose); };
|
||||||
if (!vive->Initialize())
|
if (!state.vive->Initialize())
|
||||||
{
|
{
|
||||||
vive.reset();
|
state.vive.reset();
|
||||||
LOG("VR: failed to initialize vive");
|
LOG("VR: failed to initialize vive");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hmd_renderer.joinable())
|
if (state.hmd_renderer.joinable())
|
||||||
{
|
{
|
||||||
hmd_renderer.request_stop();
|
state.hmd_renderer.request_stop();
|
||||||
hmd_renderer.join();
|
state.hmd_renderer.join();
|
||||||
}
|
}
|
||||||
hmd_renderer = std::jthread([&](std::stop_token stop_token) {
|
state.hmd_renderer = std::jthread([&state](std::stop_token stop_token) {
|
||||||
if (!vive)
|
if (!state.vive)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
BT_SetTerminate();
|
BT_SetTerminate();
|
||||||
@@ -551,9 +568,9 @@ bool win32_vr_start()
|
|||||||
App::I->has_vr = true;
|
App::I->has_vr = true;
|
||||||
vr_running.store(true, std::memory_order_relaxed);
|
vr_running.store(true, std::memory_order_relaxed);
|
||||||
|
|
||||||
vive->on_analog_button = std::bind(&App::vr_analog, App::I, std::placeholders::_1,
|
state.vive->on_analog_button = std::bind(&App::vr_analog, App::I, std::placeholders::_1,
|
||||||
std::placeholders::_2, std::placeholders::_3, std::placeholders::_4);
|
std::placeholders::_2, std::placeholders::_3, std::placeholders::_4);
|
||||||
vive->on_button = std::bind(&App::vr_digital, App::I, std::placeholders::_1,
|
state.vive->on_button = std::bind(&App::vr_digital, App::I, std::placeholders::_1,
|
||||||
std::placeholders::_2, std::placeholders::_3, std::placeholders::_4);
|
std::placeholders::_2, std::placeholders::_3, std::placeholders::_4);
|
||||||
|
|
||||||
App::I->render_task([] {
|
App::I->render_task([] {
|
||||||
@@ -564,9 +581,9 @@ bool win32_vr_start()
|
|||||||
auto t0 = GetTickCount64();
|
auto t0 = GetTickCount64();
|
||||||
float one_sec_timer = 0;
|
float one_sec_timer = 0;
|
||||||
int frames = 0;
|
int frames = 0;
|
||||||
while (!stop_token.stop_requested() && vr_running.load(std::memory_order_relaxed) && running.load(std::memory_order_relaxed) == 1 && vive->Valid())
|
while (!stop_token.stop_requested() && vr_running.load(std::memory_order_relaxed) && running.load(std::memory_order_relaxed) == 1 && state.vive->Valid())
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(hmd_render_mutex);
|
std::unique_lock<std::mutex> lock(state.hmd_render_mutex);
|
||||||
auto t1 = GetTickCount64();
|
auto t1 = GetTickCount64();
|
||||||
float dt = (float)(t1 - t0) / 1000.0f;
|
float dt = (float)(t1 - t0) / 1000.0f;
|
||||||
|
|
||||||
@@ -579,28 +596,28 @@ bool win32_vr_start()
|
|||||||
}
|
}
|
||||||
frames++;
|
frames++;
|
||||||
|
|
||||||
vive->Update();
|
state.vive->Update();
|
||||||
App::I->vr_active = vive->m_active;
|
App::I->vr_active = state.vive->m_active;
|
||||||
App::I->vr_controllers[0] = vive->m_controllers[0];
|
App::I->vr_controllers[0] = state.vive->m_controllers[0];
|
||||||
App::I->vr_head = vive->m_pose;
|
App::I->vr_head = state.vive->m_pose;
|
||||||
App::I->vr_update(dt);
|
App::I->vr_update(dt);
|
||||||
|
|
||||||
if (vr_running.load(std::memory_order_relaxed) && vive->m_active)
|
if (vr_running.load(std::memory_order_relaxed) && state.vive->m_active)
|
||||||
{
|
{
|
||||||
App::I->render_task([] {
|
App::I->render_task([&state] {
|
||||||
vive->Draw();
|
state.vive->Draw();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const int framerate = (1.f / target_tick_rate) * 1000;
|
const int framerate = (1.f / target_tick_rate) * 1000;
|
||||||
const int diff = framerate - (t1 - t0);
|
const int diff = framerate - (t1 - t0);
|
||||||
//hmd_render_cv.wait_for(lock, std::chrono::milliseconds(diff));
|
//state.hmd_render_cv.wait_for(lock, std::chrono::milliseconds(diff));
|
||||||
t0 = t1;
|
t0 = t1;
|
||||||
}
|
}
|
||||||
App::I->vr_active = false;
|
App::I->vr_active = false;
|
||||||
App::I->has_vr = false;
|
App::I->has_vr = false;
|
||||||
vr_running.store(false, std::memory_order_relaxed);
|
vr_running.store(false, std::memory_order_relaxed);
|
||||||
vive->Terminate();
|
state.vive->Terminate();
|
||||||
LOG("hmd renderer terminated");
|
LOG("hmd renderer terminated");
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
@@ -608,23 +625,25 @@ bool win32_vr_start()
|
|||||||
|
|
||||||
void win32_vr_stop()
|
void win32_vr_stop()
|
||||||
{
|
{
|
||||||
if (vive)
|
auto& state = retained_state();
|
||||||
|
if (state.vive)
|
||||||
{
|
{
|
||||||
vr_running.store(false, std::memory_order_relaxed);
|
vr_running.store(false, std::memory_order_relaxed);
|
||||||
if (hmd_renderer.joinable())
|
if (state.hmd_renderer.joinable())
|
||||||
{
|
{
|
||||||
hmd_renderer.request_stop();
|
state.hmd_renderer.request_stop();
|
||||||
hmd_renderer.join();
|
state.hmd_renderer.join();
|
||||||
}
|
}
|
||||||
vive->Terminate();
|
state.vive->Terminate();
|
||||||
vive.reset();
|
state.vive.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void win32_save_window_state()
|
void win32_save_window_state()
|
||||||
{
|
{
|
||||||
|
auto& state = retained_state();
|
||||||
WINDOWPLACEMENT p;
|
WINDOWPLACEMENT p;
|
||||||
GetWindowPlacement(hWnd, &p);
|
GetWindowPlacement(state.hWnd, &p);
|
||||||
pp::panopainter::set_legacy_window_preferences(p.showCmd, {
|
pp::panopainter::set_legacy_window_preferences(p.showCmd, {
|
||||||
p.rcNormalPosition.left,
|
p.rcNormalPosition.left,
|
||||||
p.rcNormalPosition.top,
|
p.rcNormalPosition.top,
|
||||||
@@ -690,23 +709,23 @@ LRESULT CALLBACK splash_proc(HWND hWndDlg, UINT Msg, WPARAM wParam, LPARAM lPara
|
|||||||
return DefWindowProc(hWndDlg, Msg, wParam, lParam);;
|
return DefWindowProc(hWndDlg, Msg, wParam, lParam);;
|
||||||
}
|
}
|
||||||
|
|
||||||
HWND splash_dialog;
|
|
||||||
void splash_thread_loop()
|
void splash_thread_loop()
|
||||||
{
|
{
|
||||||
|
auto& state = retained_state();
|
||||||
BT_SetTerminate();
|
BT_SetTerminate();
|
||||||
splash_dialog = CreateDialog(hInst, MAKEINTRESOURCE(IDD_SPLASH), NULL, reinterpret_cast<DLGPROC>(splash_proc));
|
state.splash_dialog = CreateDialog(state.hInst, MAKEINTRESOURCE(IDD_SPLASH), NULL, reinterpret_cast<DLGPROC>(splash_proc));
|
||||||
|
|
||||||
MSG msg;
|
MSG msg;
|
||||||
while (GetMessage(&msg, 0, 0, 0) > 0)
|
while (GetMessage(&msg, 0, 0, 0) > 0)
|
||||||
{
|
{
|
||||||
if (IsDialogMessage(splash_dialog, &msg))
|
if (IsDialogMessage(state.splash_dialog, &msg))
|
||||||
{
|
{
|
||||||
DispatchMessage(&msg);
|
DispatchMessage(&msg);
|
||||||
TranslateMessage(&msg);
|
TranslateMessage(&msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DestroyWindow(splash_dialog);
|
DestroyWindow(state.splash_dialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL UnadjustWindowRectEx(LPRECT prc, DWORD dwStyle, BOOL fMenu, DWORD dwExStyle)
|
BOOL UnadjustWindowRectEx(LPRECT prc, DWORD dwStyle, BOOL fMenu, DWORD dwExStyle)
|
||||||
@@ -741,6 +760,7 @@ void _post_call_callback(const char* name, void* funcptr, int len_args, ...)
|
|||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
|
auto& state = retained_state();
|
||||||
WNDCLASS wc;
|
WNDCLASS wc;
|
||||||
PIXELFORMATDESCRIPTOR pfd;
|
PIXELFORMATDESCRIPTOR pfd;
|
||||||
|
|
||||||
@@ -785,17 +805,17 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
// Inizialize data structures to zero
|
// Inizialize data structures to zero
|
||||||
memset(&wc, 0, sizeof(wc));
|
memset(&wc, 0, sizeof(wc));
|
||||||
memset(&keys, 0, sizeof(keys));
|
memset(&state.keys, 0, sizeof(state.keys));
|
||||||
memset(&pfd, 0, sizeof(pfd));
|
memset(&pfd, 0, sizeof(pfd));
|
||||||
|
|
||||||
// Create the main window
|
// Create the main window
|
||||||
|
|
||||||
hInst = GetModuleHandle(NULL);
|
state.hInst = GetModuleHandle(NULL);
|
||||||
className = L"EngineMain";
|
state.className = L"EngineMain";
|
||||||
|
|
||||||
wc.hInstance = hInst;
|
wc.hInstance = state.hInst;
|
||||||
wc.lpfnWndProc = (WNDPROC)WndProc;
|
wc.lpfnWndProc = (WNDPROC)WndProc;
|
||||||
wc.lpszClassName = className;
|
wc.lpszClassName = state.className;
|
||||||
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
|
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
|
||||||
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||||
|
|
||||||
@@ -833,9 +853,9 @@ int main(int argc, char** argv)
|
|||||||
{
|
{
|
||||||
AdjustWindowRect(&clientRect, wnd_style, false);
|
AdjustWindowRect(&clientRect, wnd_style, false);
|
||||||
}
|
}
|
||||||
hWnd = CreateWindow(wc.lpszClassName, L"PanoPainter", wnd_style, clientPos.x, clientPos.y,
|
state.hWnd = CreateWindow(wc.lpszClassName, L"PanoPainter", wnd_style, clientPos.x, clientPos.y,
|
||||||
(float)(clientRect.right - clientRect.left),
|
(float)(clientRect.right - clientRect.left),
|
||||||
(float)(clientRect.bottom - clientRect.top), 0, 0, hInst, 0);
|
(float)(clientRect.bottom - clientRect.top), 0, 0, state.hInst, 0);
|
||||||
|
|
||||||
// Setup GL Rendering Context
|
// Setup GL Rendering Context
|
||||||
pfd.nSize = sizeof(pfd);
|
pfd.nSize = sizeof(pfd);
|
||||||
@@ -846,11 +866,11 @@ int main(int argc, char** argv)
|
|||||||
pfd.cDepthBits = 24;
|
pfd.cDepthBits = 24;
|
||||||
pfd.iLayerType = PFD_MAIN_PLANE;
|
pfd.iLayerType = PFD_MAIN_PLANE;
|
||||||
|
|
||||||
hDC = GetDC(hWnd);
|
state.hDC = GetDC(state.hWnd);
|
||||||
int pxfmt = ChoosePixelFormat(hDC, &pfd);
|
int pxfmt = ChoosePixelFormat(state.hDC, &pfd);
|
||||||
SetPixelFormat(hDC, pxfmt, &pfd);
|
SetPixelFormat(state.hDC, pxfmt, &pfd);
|
||||||
hRC = wglCreateContext(hDC); // Create OpenGL 2.1 or less
|
state.hRC = wglCreateContext(state.hDC); // Create OpenGL 2.1 or less
|
||||||
wglMakeCurrent(hDC, hRC);
|
wglMakeCurrent(state.hDC, state.hRC);
|
||||||
|
|
||||||
// Initialize extensions
|
// Initialize extensions
|
||||||
if (!gladLoadGL())
|
if (!gladLoadGL())
|
||||||
@@ -858,7 +878,7 @@ int main(int argc, char** argv)
|
|||||||
LOG("gladLoadGL() failed");
|
LOG("gladLoadGL() failed");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (!gladLoadWGL(hDC))
|
if (!gladLoadWGL(state.hDC))
|
||||||
{
|
{
|
||||||
LOG("gladLoadWGL() failed");
|
LOG("gladLoadWGL() failed");
|
||||||
return 0;
|
return 0;
|
||||||
@@ -882,7 +902,7 @@ int main(int argc, char** argv)
|
|||||||
#endif // USE_RENDERDOC
|
#endif // USE_RENDERDOC
|
||||||
|
|
||||||
const auto renderer_name = std::string(runtime_info.renderer != nullptr ? runtime_info.renderer : "");
|
const auto renderer_name = std::string(runtime_info.renderer != nullptr ? runtime_info.renderer : "");
|
||||||
swprintf_s(window_title, L"PanoPainter %s (%s)", g_version_number_w,
|
swprintf_s(state.window_title, L"PanoPainter %s (%s)", g_version_number_w,
|
||||||
str2wstr(renderer_name).c_str());
|
str2wstr(renderer_name).c_str());
|
||||||
|
|
||||||
// If supported create a 3.3 context
|
// If supported create a 3.3 context
|
||||||
@@ -892,18 +912,18 @@ int main(int argc, char** argv)
|
|||||||
UINT numFormat;
|
UINT numFormat;
|
||||||
|
|
||||||
wglMakeCurrent(NULL, NULL);
|
wglMakeCurrent(NULL, NULL);
|
||||||
wglDeleteContext(hRC);
|
wglDeleteContext(state.hRC);
|
||||||
DestroyWindow(hWnd);
|
DestroyWindow(state.hWnd);
|
||||||
|
|
||||||
hWnd = CreateWindow(wc.lpszClassName, window_title, wnd_style, clientPos.x, clientPos.y,
|
state.hWnd = CreateWindow(wc.lpszClassName, state.window_title, wnd_style, clientPos.x, clientPos.y,
|
||||||
(float)(clientRect.right - clientRect.left),
|
(float)(clientRect.right - clientRect.left),
|
||||||
(float)(clientRect.bottom - clientRect.top), 0, 0, hInst, 0);
|
(float)(clientRect.bottom - clientRect.top), 0, 0, state.hInst, 0);
|
||||||
|
|
||||||
hDC = GetDC(hWnd);
|
state.hDC = GetDC(state.hWnd);
|
||||||
wglChoosePixelFormatARB(hDC, wgl_config.pixel_format_attributes.data(), nullptr, 1, &pxfmt, &numFormat);
|
wglChoosePixelFormatARB(state.hDC, wgl_config.pixel_format_attributes.data(), nullptr, 1, &pxfmt, &numFormat);
|
||||||
SetPixelFormat(hDC, pxfmt, &pfd);
|
SetPixelFormat(state.hDC, pxfmt, &pfd);
|
||||||
hRC = wglCreateContextAttribsARB(hDC, NULL, wgl_config.context_attributes.data());
|
state.hRC = wglCreateContextAttribsARB(state.hDC, NULL, wgl_config.context_attributes.data());
|
||||||
wglMakeCurrent(hDC, hRC);
|
wglMakeCurrent(state.hDC, state.hRC);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -932,7 +952,7 @@ int main(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// link: https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-registertouchwindow
|
// link: https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-registertouchwindow
|
||||||
if (RegisterTouchWindow(hWnd, 0) == 0)
|
if (RegisterTouchWindow(state.hWnd, 0) == 0)
|
||||||
{
|
{
|
||||||
LOG("RegisterTouchWindow error: %s", GetLastErrorAsString().c_str());
|
LOG("RegisterTouchWindow error: %s", GetLastErrorAsString().c_str());
|
||||||
}
|
}
|
||||||
@@ -948,10 +968,10 @@ int main(int argc, char** argv)
|
|||||||
glad_set_post_callback(_post_call_callback);
|
glad_set_post_callback(_post_call_callback);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!sandboxed)
|
if (!state.sandboxed)
|
||||||
{
|
{
|
||||||
LOG("init WinTab");
|
LOG("init WinTab");
|
||||||
WacomTablet::I.init(hWnd);
|
WacomTablet::I.init(state.hWnd);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -959,16 +979,16 @@ int main(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
LOG("change icon");
|
LOG("change icon");
|
||||||
SendMessage(hWnd, WM_SETICON, ICON_SMALL,
|
SendMessage(state.hWnd, WM_SETICON, ICON_SMALL,
|
||||||
(LPARAM)LoadIcon(GetModuleHandle(0), MAKEINTRESOURCE(IDI_ICON1)));
|
(LPARAM)LoadIcon(GetModuleHandle(0), MAKEINTRESOURCE(IDI_ICON1)));
|
||||||
|
|
||||||
App::I->ui_sync();
|
App::I->ui_sync();
|
||||||
|
|
||||||
{
|
{
|
||||||
WINDOWPLACEMENT wp;
|
WINDOWPLACEMENT wp;
|
||||||
GetWindowPlacement(hWnd, &wp);
|
GetWindowPlacement(state.hWnd, &wp);
|
||||||
wp.showCmd = show_cmd;
|
wp.showCmd = show_cmd;
|
||||||
SetWindowPlacement(hWnd, &wp);
|
SetWindowPlacement(state.hWnd, &wp);
|
||||||
//GetClientRect(hWnd, &clientRect);
|
//GetClientRect(hWnd, &clientRect);
|
||||||
//App::I->width = clientRect.right - clientRect.left;
|
//App::I->width = clientRect.right - clientRect.left;
|
||||||
//App::I->height = clientRect.bottom - clientRect.top;
|
//App::I->height = clientRect.bottom - clientRect.top;
|
||||||
@@ -978,10 +998,10 @@ int main(int argc, char** argv)
|
|||||||
App::I->vr_start();
|
App::I->vr_start();
|
||||||
|
|
||||||
LOG("show main window");
|
LOG("show main window");
|
||||||
SetForegroundWindow(hWnd);
|
SetForegroundWindow(state.hWnd);
|
||||||
//ShowWindow(hWnd, show_cmd);
|
//ShowWindow(hWnd, show_cmd);
|
||||||
|
|
||||||
SendMessage(splash_dialog, WM_USER_CLOSE, 0, 0);
|
SendMessage(state.splash_dialog, WM_USER_CLOSE, 0, 0);
|
||||||
if (dialog_thread.joinable())
|
if (dialog_thread.joinable())
|
||||||
dialog_thread.join();
|
dialog_thread.join();
|
||||||
|
|
||||||
@@ -1006,8 +1026,8 @@ int main(int argc, char** argv)
|
|||||||
{
|
{
|
||||||
std::deque<std::packaged_task<void()>> working_list;
|
std::deque<std::packaged_task<void()>> working_list;
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(main_task_mutex);
|
std::lock_guard<std::mutex> lock(state.main_task_mutex);
|
||||||
working_list = std::move(main_tasklist);
|
working_list = std::move(state.main_tasklist);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!working_list.empty())
|
if (!working_list.empty())
|
||||||
@@ -1023,12 +1043,13 @@ int main(int argc, char** argv)
|
|||||||
// Clean up
|
// Clean up
|
||||||
WacomTablet::I.terminate();
|
WacomTablet::I.terminate();
|
||||||
|
|
||||||
UnregisterClass(className, hInst);
|
UnregisterClass(state.className, state.hInst);
|
||||||
LogRemote::I.stop();
|
LogRemote::I.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
|
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
|
||||||
{
|
{
|
||||||
|
auto& state = retained_state();
|
||||||
static bool leftDown = false;
|
static bool leftDown = false;
|
||||||
static DWORD lastTime;
|
static DWORD lastTime;
|
||||||
static glm::vec2 lastPoint;
|
static glm::vec2 lastPoint;
|
||||||
@@ -1041,10 +1062,10 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
|
|||||||
{
|
{
|
||||||
case WM_USER_CLOSE:
|
case WM_USER_CLOSE:
|
||||||
running.store(0, std::memory_order_relaxed);
|
running.store(0, std::memory_order_relaxed);
|
||||||
if (hmd_renderer.joinable())
|
if (state.hmd_renderer.joinable())
|
||||||
{
|
{
|
||||||
hmd_renderer.request_stop();
|
state.hmd_renderer.request_stop();
|
||||||
hmd_renderer.join();
|
state.hmd_renderer.join();
|
||||||
}
|
}
|
||||||
App::I->runtime().ui_thread_stop();
|
App::I->runtime().ui_thread_stop();
|
||||||
App::I->runtime().render_thread_stop();
|
App::I->runtime().render_thread_stop();
|
||||||
@@ -1093,7 +1114,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
|
|||||||
if (GetKeyboardState(keys))
|
if (GetKeyboardState(keys))
|
||||||
{
|
{
|
||||||
bool alt = keys[VK_MENU] & 0x80;
|
bool alt = keys[VK_MENU] & 0x80;
|
||||||
for (auto k : vkey_map)
|
for (auto k : state.vkey_map)
|
||||||
{
|
{
|
||||||
// ignore alt + tab
|
// ignore alt + tab
|
||||||
if (alt && k.first == kKey::KeyTab)
|
if (alt && k.first == kKey::KeyTab)
|
||||||
@@ -1118,7 +1139,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
|
|||||||
case WT_PACKET:
|
case WT_PACKET:
|
||||||
{
|
{
|
||||||
App::I->set_stylus();
|
App::I->set_stylus();
|
||||||
timer_stylus = 0;
|
state.timer_stylus = 0;
|
||||||
App::I->ui_task_async([=] {
|
App::I->ui_task_async([=] {
|
||||||
WacomTablet::I.handle_message(hWnd, msg, wp, lp);
|
WacomTablet::I.handle_message(hWnd, msg, wp, lp);
|
||||||
});
|
});
|
||||||
@@ -1318,7 +1339,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
|
|||||||
// success, process touchInfo
|
// success, process touchInfo
|
||||||
// mark as handled to skip call to DefWindowProc
|
// mark as handled to skip call to DefWindowProc
|
||||||
//fHandled = TRUE;
|
//fHandled = TRUE;
|
||||||
timer_ink_touch = 0;
|
state.timer_ink_touch = 0;
|
||||||
WacomTablet::I.m_ink_touch = true;
|
WacomTablet::I.m_ink_touch = true;
|
||||||
WacomTablet::I.m_pen_pres = 1;
|
WacomTablet::I.m_pen_pres = 1;
|
||||||
}
|
}
|
||||||
@@ -1335,7 +1356,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
|
|||||||
// mark as handled to skip call to DefWindowProc
|
// mark as handled to skip call to DefWindowProc
|
||||||
//fHandled = TRUE;
|
//fHandled = TRUE;
|
||||||
//penInfo.pressure
|
//penInfo.pressure
|
||||||
timer_ink_pen = 0;
|
state.timer_ink_pen = 0;
|
||||||
WacomTablet::I.m_ink_pen = true;
|
WacomTablet::I.m_ink_pen = true;
|
||||||
WacomTablet::I.m_pen_pres = (float)penInfo.pressure / 1024.f;
|
WacomTablet::I.m_pen_pres = (float)penInfo.pressure / 1024.f;
|
||||||
App::I->set_stylus();
|
App::I->set_stylus();
|
||||||
|
|||||||
@@ -769,9 +769,7 @@ void NodeCanvas::draw()
|
|||||||
for (auto& mode : Canvas::modes[(int)kCanvasMode::Grid])
|
for (auto& mode : Canvas::modes[(int)kCanvasMode::Grid])
|
||||||
mode->on_Draw(ortho_proj, proj, camera);
|
mode->on_Draw(ortho_proj, proj, camera);
|
||||||
},
|
},
|
||||||
.draw_heightmap = [&] {
|
.draw_heightmap = pp::panopainter::make_legacy_canvas_draw_merge_heightmap_draw(App::I->grid, proj, camera),
|
||||||
App::I->grid->draw_heightmap(proj, camera, false);
|
|
||||||
},
|
|
||||||
.draw_current_modes = [&] {
|
.draw_current_modes = [&] {
|
||||||
for (auto& mode : *m_canvas->m_mode)
|
for (auto& mode : *m_canvas->m_mode)
|
||||||
mode->on_Draw(ortho_proj, proj, camera);
|
mode->on_Draw(ortho_proj, proj, camera);
|
||||||
|
|||||||
@@ -101,26 +101,55 @@ struct RetainedLegacyGlfwWindowHooks final {
|
|||||||
std::function<void()> request_app_close;
|
std::function<void()> request_app_close;
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] RetainedLegacyGlfwWindowHooks& active_legacy_glfw_window_hooks()
|
struct RetainedLegacyGlfwWindowState final {
|
||||||
|
decltype(App::I->glfw_window) window = nullptr;
|
||||||
|
RetainedLegacyGlfwWindowHooks hooks;
|
||||||
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] RetainedLegacyGlfwWindowState& active_legacy_glfw_window_state()
|
||||||
{
|
{
|
||||||
static RetainedLegacyGlfwWindowHooks hooks = [] {
|
static RetainedLegacyGlfwWindowState state = [] {
|
||||||
RetainedLegacyGlfwWindowHooks retained;
|
RetainedLegacyGlfwWindowState retained;
|
||||||
GLFWwindow* const window = App::I->glfw_window;
|
retained.window = App::I->glfw_window;
|
||||||
retained.acquire_render_context = [window] {
|
retained.hooks.acquire_render_context = [window = retained.window] {
|
||||||
glfwMakeContextCurrent(window);
|
glfwMakeContextCurrent(window);
|
||||||
};
|
};
|
||||||
retained.present_render_context = [window] {
|
retained.hooks.present_render_context = [window = retained.window] {
|
||||||
glfwSwapBuffers(window);
|
glfwSwapBuffers(window);
|
||||||
};
|
};
|
||||||
retained.request_app_close = [window] {
|
retained.hooks.request_app_close = [window = retained.window] {
|
||||||
glfwSetWindowShouldClose(window, GLFW_TRUE);
|
glfwSetWindowShouldClose(window, GLFW_TRUE);
|
||||||
};
|
};
|
||||||
return retained;
|
return retained;
|
||||||
}();
|
}();
|
||||||
return hooks;
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] RetainedLegacyGlfwWindowHooks& active_legacy_glfw_window_hooks()
|
||||||
|
{
|
||||||
|
return active_legacy_glfw_window_state().hooks;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct RetainedLegacyStoragePaths final {
|
||||||
|
pp::platform::PlatformStoragePaths storage_paths;
|
||||||
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] RetainedLegacyStoragePaths& active_legacy_storage_paths()
|
||||||
|
{
|
||||||
|
static RetainedLegacyStoragePaths state = [] {
|
||||||
|
RetainedLegacyStoragePaths retained;
|
||||||
|
retained.storage_paths = {
|
||||||
|
App::I->data_path,
|
||||||
|
App::I->work_path,
|
||||||
|
App::I->rec_path,
|
||||||
|
App::I->tmp_path,
|
||||||
|
};
|
||||||
|
return retained;
|
||||||
|
}();
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(__IOS__) || defined(__OSX__)
|
#if defined(__IOS__) || defined(__OSX__)
|
||||||
[[nodiscard]] NSMutableArray<NSString*>* apple_file_types_array(const std::vector<std::string>& file_types)
|
[[nodiscard]] NSMutableArray<NSString*>* apple_file_types_array(const std::vector<std::string>& file_types)
|
||||||
{
|
{
|
||||||
@@ -377,12 +406,7 @@ public:
|
|||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
#else
|
#else
|
||||||
return {
|
return active_legacy_storage_paths().storage_paths;
|
||||||
App::I->data_path,
|
|
||||||
App::I->work_path,
|
|
||||||
App::I->rec_path,
|
|
||||||
App::I->tmp_path,
|
|
||||||
};
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user