From 24d9d5b6e2c463b138d0eaca9898e3c6e114f7d0 Mon Sep 17 00:00:00 2001 From: omigamedev Date: Tue, 16 Jun 2026 22:03:27 +0200 Subject: [PATCH] Extract brush panel UI, app startup shell, and Win32 runtime shell --- cmake/PanoPainterSources.cmake | 4 + docs/modernization/roadmap.md | 15 +- docs/modernization/tasks.md | 19 ++- src/app.cpp | 143 +----------------- src/legacy_app_startup_services.cpp | 134 ++++++++++++++++ src/legacy_app_startup_services.h | 5 + src/legacy_brush_panel_ui.cpp | 139 +++++++++++++++++ src/legacy_brush_panel_ui.h | 15 ++ src/main.cpp | 79 +--------- src/node_panel_brush.cpp | 116 +------------- src/node_panel_brush.h | 2 + .../windows_runtime_shell.cpp | 131 ++++++++++++++++ src/platform_windows/windows_runtime_shell.h | 10 ++ 13 files changed, 480 insertions(+), 332 deletions(-) create mode 100644 src/legacy_brush_panel_ui.cpp create mode 100644 src/legacy_brush_panel_ui.h create mode 100644 src/platform_windows/windows_runtime_shell.cpp create mode 100644 src/platform_windows/windows_runtime_shell.h diff --git a/cmake/PanoPainterSources.cmake b/cmake/PanoPainterSources.cmake index db95ddb6..87da8899 100644 --- a/cmake/PanoPainterSources.cmake +++ b/cmake/PanoPainterSources.cmake @@ -167,6 +167,8 @@ set(PP_PANOPAINTER_UI_SOURCES src/legacy_brush_ui_services.h src/legacy_brush_panel_services.cpp src/legacy_brush_panel_services.h + src/legacy_brush_panel_ui.cpp + src/legacy_brush_panel_ui.h src/legacy_document_animation_services.cpp src/legacy_document_animation_services.h src/legacy_node_canvas_draw_services.cpp @@ -217,6 +219,8 @@ set(PP_WINDOWS_PLATFORM_SOURCES src/platform_windows/windows_lifecycle_shell.h src/platform_windows/windows_platform_services.cpp src/platform_windows/windows_platform_services.h + src/platform_windows/windows_runtime_shell.cpp + src/platform_windows/windows_runtime_shell.h src/platform_windows/windows_splash.cpp src/platform_windows/windows_splash.h src/platform_windows/windows_stylus_input.cpp diff --git a/docs/modernization/roadmap.md b/docs/modernization/roadmap.md index c4cf6cc7..cd8ce898 100644 --- a/docs/modernization/roadmap.md +++ b/docs/modernization/roadmap.md @@ -83,11 +83,11 @@ Current hotspot files: - `src/app_layout.cpp`: 125 lines - `src/canvas_modes.cpp`: 402 lines - `src/node.cpp`: 389 lines -- `src/main.cpp`: 271 lines -- `src/node_panel_brush.cpp`: 435 lines +- `src/main.cpp`: 166 lines +- `src/node_panel_brush.cpp`: 337 lines - `src/node_stroke_preview.cpp`: 562 lines - `src/node_canvas.cpp`: 219 lines -- `src/app.cpp`: 292 lines +- `src/app.cpp`: 171 lines - `src/app_dialogs.cpp`: 168 lines Current architecture mismatches that must be treated as real blockers: @@ -216,8 +216,13 @@ Current architecture mismatches that must be treated as real blockers: `src/platform_windows/windows_bootstrap_helpers.cpp` instead of `src/main.cpp`, while the Win32 window procedure and retained message-handling shell now also live in `src/platform_windows/windows_window_shell.*` - instead of `src/main.cpp`, which materially thins `src/main.cpp` even - though broader entrypoint/runtime composition still remains there, + instead of `src/main.cpp`, while the remaining interactive Win32 runtime + pocket for touch registration, render/UI thread startup, GL debug callback + hookup, Wintab initialization/skip, icon setup, placement restore, optional + VR start, splash dismissal, message loop, and shutdown cleanup now also + lives in `src/platform_windows/windows_runtime_shell.*` instead of + `src/main.cpp`, which materially thins `src/main.cpp` even though broader + entrypoint/runtime composition still remains there, while `App::rec_loop()` now delegates worker-iteration orchestration into the retained recording bridge, `App::update_rec_frames()` now delegates recording label refresh through that same retained recording path, and the diff --git a/docs/modernization/tasks.md b/docs/modernization/tasks.md index 8822cbe1..f290d0a0 100644 --- a/docs/modernization/tasks.md +++ b/docs/modernization/tasks.md @@ -536,7 +536,7 @@ Status: In Progress Why now: `src/app.cpp` still carries startup, frame flow, queue draining, recording, -and composition logic in one 292-line file. +and composition logic in one 171-line file. Current slice: - UI observer math now routes through `src/legacy_app_frame_services.cpp` @@ -553,6 +553,11 @@ Current slice: `App::render_thread_tick(...)` now also live in `src/legacy_app_runtime_shell_services.cpp` instead of staying inline in `src/app.cpp`, which materially thins the remaining frame/runtime shell. +- `App::create(...)`, `App::initAssets(...)`, `App::initLog(...)`, and + `App::init(...)` now also live in `src/legacy_app_startup_services.*` + instead of staying inline in `src/app.cpp`, which reduces the remaining app + file to a thinner retained composition surface around startup and runtime + delegation. Write scope: - `src/app.cpp` @@ -639,6 +644,12 @@ Current slice: in `src/platform_windows/windows_window_shell.*` instead of `src/main.cpp`, which materially thins the entry file even though broader runtime/entrypoint composition is still open +- the remaining interactive Win32 runtime pocket for touch registration, + render/UI thread startup, debug GL callback hookup, Wintab init/skip, icon + setup, placement restore, optional VR start, splash dismissal, message + loop, and shutdown cleanup now also lives in + `src/platform_windows/windows_runtime_shell.*` instead of `src/main.cpp`, + which reduces the entry TU to a much smaller composition root - prepared-file background work now runs through an `AppRuntime`-owned worker queue instead of a retained static worker in `src/app_events.cpp` - canvas async import/export/save/open background work now also runs through an @@ -1089,6 +1100,12 @@ Current slice: `src/node_panel_brush.cpp`, which materially thins another retained preset panel UI pocket even though cloud/package worker ownership remains the follow-up. +- `NodePanelBrush` brush texture panel init, selection dispatch, + popup-close event handling, restore-failure prompt flow, and added-state + reset now also live in `src/legacy_brush_panel_ui.*` instead of staying + inline in `src/node_panel_brush.cpp`, which trims another retained brush UI + workflow pocket while preserving the live node as a thinner controller + surface. Write scope: - `src/legacy_cloud_services.*` diff --git a/src/app.cpp b/src/app.cpp index 3b7c2f98..a6dcaa42 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -18,12 +18,8 @@ #include "legacy_app_startup_services.h" #include "legacy_document_open_services.h" #include "legacy_document_session_services.h" -#include "legacy_gl_runtime_dispatch.h" #include "legacy_preference_storage.h" -#include "legacy_recording_services.h" -#include "legacy_ui_gl_dispatch.h" #include "platform_api/platform_services.h" -#include "renderer_gl/opengl_capabilities.h" #ifdef __APPLE__ #include @@ -32,36 +28,9 @@ App* App::I = nullptr; // singleton -[[nodiscard]] GLenum linear_texture_filter() noexcept -{ - return static_cast(pp::renderer::gl::linear_texture_filter()); -} - -[[nodiscard]] GLenum nearest_texture_filter() noexcept -{ - return static_cast(pp::renderer::gl::nearest_texture_filter()); -} - -[[nodiscard]] GLenum repeat_texture_wrap() noexcept -{ - return static_cast(pp::renderer::gl::repeat_texture_wrap()); -} - -[[nodiscard]] GLenum framebuffer_target() noexcept -{ - return static_cast(pp::renderer::gl::framebuffer_target()); -} - -[[nodiscard]] GLuint default_framebuffer_id() noexcept -{ - return static_cast(pp::renderer::gl::default_framebuffer_id()); -} - void App::create() { - const auto initial_surface = pp::app::plan_app_initial_surface(); - width = initial_surface.width; - height = initial_surface.height; + pp::panopainter::execute_legacy_app_create(*this); } void App::open_document(std::string path) @@ -107,39 +76,12 @@ void App::clear() void App::initAssets() { - LOG("initializing assets"); - FontManager::init(); - - LOG("initializing assets create sampler"); - sampler.create(nearest_texture_filter()); - sampler_stencil.create(linear_texture_filter(), repeat_texture_wrap()); - sampler_linear.create(linear_texture_filter()); - m_face_plane.create<1>(2, 2); - sphere.create<8, 8>(1); - LOG("initializing assets load uvs texture"); - LOG("initializing assets completed"); + pp::panopainter::execute_legacy_app_init_assets(*this); } void App::initLog() { - const auto paths = prepare_storage_paths(); - if (!paths.data_path.empty()) - data_path = paths.data_path; - if (!paths.recording_path.empty()) - rec_path = paths.recording_path; - if (!paths.temporary_path.empty()) - tmp_path = paths.temporary_path; - - // TODO: save this path somewhere in the settings, don't overwrite every start - work_path = paths.work_path.empty() ? data_path : paths.work_path; - - //LogRemote::I.start(); - LogRemote::I.file_init(); - LOG("%s", g_version); - - LOG("load preferences"); - if (!pp::panopainter::load_legacy_preferences()) - LOG("load preferences failed"); + pp::panopainter::execute_legacy_app_init_log(*this); } namespace pp::panopainter @@ -183,84 +125,7 @@ bool App::check_license() void App::init() { - LOG("Screen Resolution: %dx%d", (int)width, (int)height); - - render_task([] - { - App::I->install_render_debug_callback(); - const auto runtime_info_result = pp::renderer::gl::query_opengl_runtime_info( - pp::legacy::gl_runtime::runtime_info_dispatch()); - if (runtime_info_result.ok()) - { - const auto& runtime_info = runtime_info_result.value(); - LOG("GL version: %s", runtime_info.version); - LOG("GL vendor: %s", runtime_info.vendor); - LOG("GL renderer: %s", runtime_info.renderer); - LOG("GLSL version: %s", runtime_info.shading_language_version); - } - else - { - LOG("OpenGL runtime info failed: %s", runtime_info_result.status().message); - } - - //GLint n_exts; - //glGetIntegerv(GL_NUM_EXTENSIONS, &n_exts); - //for (int i = 0; i < n_exts; i++) - //{ - // std::string ext = (const char*)glGetStringi(GL_EXTENSIONS, i); - // //if (ext.find("debug") != std::string::npos) - // { - // LOG("%s", glGetStringi(GL_EXTENSIONS, i)); - // } - //} - - App::I->apply_render_platform_hints(); - const auto startup_state_status = pp::renderer::gl::apply_panopainter_initial_state( - pp::renderer::gl::OpenGlStateDispatch { - .enable = pp::legacy::ui_gl::enable_opengl_state, - .disable = pp::legacy::ui_gl::disable_opengl_state, - .blend_func = pp::legacy::ui_gl::set_opengl_blend_func, - .blend_equation_separate = pp::legacy::ui_gl::set_opengl_blend_equation_separate, - }); - if (!startup_state_status.ok()) - LOG("OpenGL startup state failed: %s", startup_state_status.message); - }); - - const auto startup_preferences = - pp::panopainter::read_legacy_startup_preferences(vr_controllers_enabled); - const auto startup_plan = pp::app::plan_app_startup( - startup_preferences.run_counter, - startup_preferences.auto_timelapse, - startup_preferences.vr_controllers_enabled, - check_license()); - if (!startup_plan) { - LOG("App startup plan failed: %s", startup_plan.status().message); - } else { - const auto persistence_status = pp::panopainter::execute_legacy_app_startup_persistence_plan( - *this, - startup_plan.value()); - if (!persistence_status.ok()) - LOG("App startup persistence failed: %s", persistence_status.message); - } - - const auto startup_resources = pp::app::plan_app_startup_resources(width, height); - if (!startup_resources) { - LOG("App startup resource plan failed: %s", startup_resources.status().message); - } else { - const auto resource_status = pp::panopainter::execute_legacy_app_startup_resources( - *this, - startup_resources.value()); - if (!resource_status.ok()) - LOG("App startup resources failed: %s", resource_status.message); - } - - if (startup_plan) { - const auto startup_status = pp::panopainter::execute_legacy_app_startup_runtime_plan( - *this, - startup_plan.value()); - if (!startup_status.ok()) - LOG("App startup runtime execution failed: %s", startup_status.message); - } + pp::panopainter::execute_legacy_app_init(*this); } void App::async_start() diff --git a/src/legacy_app_startup_services.cpp b/src/legacy_app_startup_services.cpp index 49a045e9..77e01e2e 100644 --- a/src/legacy_app_startup_services.cpp +++ b/src/legacy_app_startup_services.cpp @@ -3,12 +3,31 @@ #include "legacy_app_startup_services.h" #include "app.h" +#include "app_core/app_frame.h" +#include "legacy_gl_runtime_dispatch.h" #include "legacy_preference_storage.h" +#include "legacy_ui_gl_dispatch.h" +#include "platform_api/platform_services.h" #include "renderer_gl/opengl_capabilities.h" namespace pp::panopainter { namespace { +[[nodiscard]] GLenum linear_texture_filter() noexcept +{ + return static_cast(pp::renderer::gl::linear_texture_filter()); +} + +[[nodiscard]] GLenum nearest_texture_filter() noexcept +{ + return static_cast(pp::renderer::gl::nearest_texture_filter()); +} + +[[nodiscard]] GLenum repeat_texture_wrap() noexcept +{ + return static_cast(pp::renderer::gl::repeat_texture_wrap()); +} + class LegacyAppStartupServices final : public pp::app::AppStartupServices , public pp::app::AppStartupResourceServices { @@ -81,6 +100,121 @@ private: } // namespace +void execute_legacy_app_create(App& app) +{ + const auto initial_surface = pp::app::plan_app_initial_surface(); + app.width = initial_surface.width; + app.height = initial_surface.height; +} + +void execute_legacy_app_init_assets(App& app) +{ + LOG("initializing assets"); + FontManager::init(); + + LOG("initializing assets create sampler"); + app.sampler.create(nearest_texture_filter()); + app.sampler_stencil.create(linear_texture_filter(), repeat_texture_wrap()); + app.sampler_linear.create(linear_texture_filter()); + app.m_face_plane.create<1>(2, 2); + app.sphere.create<8, 8>(1); + LOG("initializing assets load uvs texture"); + LOG("initializing assets completed"); +} + +void execute_legacy_app_init_log(App& app) +{ + const auto paths = app.prepare_storage_paths(); + if (!paths.data_path.empty()) + app.data_path = paths.data_path; + if (!paths.recording_path.empty()) + app.rec_path = paths.recording_path; + if (!paths.temporary_path.empty()) + app.tmp_path = paths.temporary_path; + + // TODO: save this path somewhere in the settings, don't overwrite every start + app.work_path = paths.work_path.empty() ? app.data_path : paths.work_path; + + //LogRemote::I.start(); + LogRemote::I.file_init(); + LOG("%s", g_version); + + LOG("load preferences"); + if (!load_legacy_preferences()) + LOG("load preferences failed"); +} + +void execute_legacy_app_init(App& app) +{ + LOG("Screen Resolution: %dx%d", static_cast(app.width), static_cast(app.height)); + + app.render_task([&app] + { + app.install_render_debug_callback(); + const auto runtime_info_result = pp::renderer::gl::query_opengl_runtime_info( + pp::legacy::gl_runtime::runtime_info_dispatch()); + if (runtime_info_result.ok()) + { + const auto& runtime_info = runtime_info_result.value(); + LOG("GL version: %s", runtime_info.version); + LOG("GL vendor: %s", runtime_info.vendor); + LOG("GL renderer: %s", runtime_info.renderer); + LOG("GLSL version: %s", runtime_info.shading_language_version); + } + else + { + LOG("OpenGL runtime info failed: %s", runtime_info_result.status().message); + } + + app.apply_render_platform_hints(); + const auto startup_state_status = pp::renderer::gl::apply_panopainter_initial_state( + pp::renderer::gl::OpenGlStateDispatch { + .enable = pp::legacy::ui_gl::enable_opengl_state, + .disable = pp::legacy::ui_gl::disable_opengl_state, + .blend_func = pp::legacy::ui_gl::set_opengl_blend_func, + .blend_equation_separate = pp::legacy::ui_gl::set_opengl_blend_equation_separate, + }); + if (!startup_state_status.ok()) + LOG("OpenGL startup state failed: %s", startup_state_status.message); + }); + + const auto startup_preferences = + read_legacy_startup_preferences(app.vr_controllers_enabled); + const auto startup_plan = pp::app::plan_app_startup( + startup_preferences.run_counter, + startup_preferences.auto_timelapse, + startup_preferences.vr_controllers_enabled, + app.check_license()); + if (!startup_plan) { + LOG("App startup plan failed: %s", startup_plan.status().message); + } else { + const auto persistence_status = execute_legacy_app_startup_persistence_plan( + app, + startup_plan.value()); + if (!persistence_status.ok()) + LOG("App startup persistence failed: %s", persistence_status.message); + } + + const auto startup_resources = pp::app::plan_app_startup_resources(app.width, app.height); + if (!startup_resources) { + LOG("App startup resource plan failed: %s", startup_resources.status().message); + } else { + const auto resource_status = execute_legacy_app_startup_resources( + app, + startup_resources.value()); + if (!resource_status.ok()) + LOG("App startup resources failed: %s", resource_status.message); + } + + if (startup_plan) { + const auto startup_status = execute_legacy_app_startup_runtime_plan( + app, + startup_plan.value()); + if (!startup_status.ok()) + LOG("App startup runtime execution failed: %s", startup_status.message); + } +} + pp::foundation::Status execute_legacy_app_startup_plan( App& app, const pp::app::AppStartupPlan& plan) diff --git a/src/legacy_app_startup_services.h b/src/legacy_app_startup_services.h index e554b2d1..0e398ef6 100644 --- a/src/legacy_app_startup_services.h +++ b/src/legacy_app_startup_services.h @@ -6,6 +6,11 @@ class App; namespace pp::panopainter { +void execute_legacy_app_create(App& app); +void execute_legacy_app_init_assets(App& app); +void execute_legacy_app_init_log(App& app); +void execute_legacy_app_init(App& app); + [[nodiscard]] pp::foundation::Status execute_legacy_app_startup_plan( App& app, const pp::app::AppStartupPlan& plan); diff --git a/src/legacy_brush_panel_ui.cpp b/src/legacy_brush_panel_ui.cpp new file mode 100644 index 00000000..161e7bdc --- /dev/null +++ b/src/legacy_brush_panel_ui.cpp @@ -0,0 +1,139 @@ +#include "pch.h" + +#include "legacy_brush_panel_ui.h" + +#include "app.h" +#include "app_core/brush_ui.h" +#include "asset.h" +#include "legacy_ui_overlay_services.h" + +namespace pp::panopainter { + +void LegacyBrushPanelUi::init(NodePanelBrush& owner) +{ + owner.init_template_file("data/dialogs/panel-brushes.xml", "tpl-panel-brushes"); + + owner.m_btn_add = owner.find("btn-add"); + owner.m_btn_add->on_click = [&owner](Node*) { + App::I->pick_file({ "JPG", "PNG" }, [&owner](std::string path) { + const auto plan = pp::app::plan_brush_texture_list_add(owner.m_dir_name, App::I->data_path, path); + if (plan) { + owner.execute_texture_list_plan(plan.value()); + } + }); + }; + + owner.m_btn_remove = owner.find("btn-remove"); + owner.m_btn_remove->on_click = [&owner](Node*) { + if (owner.m_current) + { + const int idx = owner.m_container->get_child_index(owner.m_current); + const auto plan = pp::app::plan_brush_texture_list_remove( + static_cast(owner.m_container->m_children.size()), + idx, + owner.m_current->m_user_brush); + if (plan) { + owner.execute_texture_list_plan(plan.value()); + } + } + }; + + owner.m_btn_up = owner.find("btn-up"); + owner.m_btn_up->on_click = [&owner](Node*) { + if (owner.m_current) + { + const int idx = owner.m_container->get_child_index(owner.m_current); + const auto plan = pp::app::plan_brush_texture_list_move( + static_cast(owner.m_container->m_children.size()), + idx, + -1); + if (plan) { + owner.execute_texture_list_plan(plan.value()); + } + } + }; + + owner.m_btn_down = owner.find("btn-down"); + owner.m_btn_down->on_click = [&owner](Node*) { + if (owner.m_current) + { + const int idx = owner.m_container->get_child_index(owner.m_current); + const auto plan = pp::app::plan_brush_texture_list_move( + static_cast(owner.m_container->m_children.size()), + idx, + 1); + if (plan) { + owner.execute_texture_list_plan(plan.value()); + } + } + }; + + owner.m_container = owner.find("brushes"); + + if (Asset::exist(App::I->data_path + "/settings/" + owner.m_dir_name + ".bin") && !owner.restore()) + { + auto mb = App::I->message_box("Brushes", "Could not read brush textures file, it will be deleted.", true); + mb->btn_ok->on_click = [&owner, mb](Node*) { + Asset::delete_file(App::I->data_path + "/settings/" + owner.m_dir_name + ".bin"); + pp::panopainter::close_legacy_dialog_node(*mb); + }; + mb->btn_cancel->on_click = [mb](Node*) { + pp::panopainter::close_legacy_dialog_node(*mb); + }; + } + + if (owner.m_container->m_children.empty() && !owner.m_dir_name.empty()) { + owner.scan(); + } + owner.save(); +} + +kEventResult LegacyBrushPanelUi::handle_event(NodePanelBrush& owner, Event* event) +{ + switch (event->m_type) + { + case kEventType::MouseLeave: + if (!owner.m_interacted) + break; + // else fall through + case kEventType::MouseUpL: + if (!owner.m_mouse_inside) + { + pp::panopainter::release_legacy_mouse_capture(owner); + if (owner.m_parent) + { + pp::panopainter::detach_legacy_node_from_parent(owner); + } + if (owner.on_popup_close) + { + owner.on_popup_close(&owner); + } + } + break; + default: + return kEventResult::Available; + } + return kEventResult::Consumed; +} + +void LegacyBrushPanelUi::handle_click(NodePanelBrush& owner, Node* target) +{ + if (target == owner.m_current) + return; + if (owner.m_current) { + owner.m_current->m_selected = false; + } + owner.m_current = static_cast(target); + owner.m_current->m_selected = true; + if (owner.on_brush_changed) { + owner.on_brush_changed(&owner, owner.m_container->get_child_index(target)); + } + owner.m_interacted = true; +} + +void LegacyBrushPanelUi::added(NodePanelBrush& owner) +{ + owner.m_interacted = false; +} + +} // namespace pp::panopainter diff --git a/src/legacy_brush_panel_ui.h b/src/legacy_brush_panel_ui.h new file mode 100644 index 00000000..dae89c77 --- /dev/null +++ b/src/legacy_brush_panel_ui.h @@ -0,0 +1,15 @@ +#pragma once + +#include "node_panel_brush.h" + +namespace pp::panopainter { + +class LegacyBrushPanelUi final { +public: + static void init(NodePanelBrush& owner); + static kEventResult handle_event(NodePanelBrush& owner, Event* event); + static void handle_click(NodePanelBrush& owner, Node* target); + static void added(NodePanelBrush& owner); +}; + +} // namespace pp::panopainter diff --git a/src/main.cpp b/src/main.cpp index a45566fc..e65a4179 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -10,6 +10,7 @@ #include "platform_windows/windows_bootstrap_helpers.h" #include "platform_windows/windows_platform_services.h" #include "platform_windows/windows_lifecycle_shell.h" +#include "platform_windows/windows_runtime_shell.h" #include "platform_windows/windows_splash.h" #include "platform_windows/windows_stylus_input.h" #include "platform_windows/windows_window_shell.h" @@ -172,83 +173,7 @@ int main(int argc, char** argv) } } - // link: https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-registertouchwindow - if (RegisterTouchWindow(state.hWnd, 0) == 0) - { - LOG("RegisterTouchWindow error: %s", pp::platform::windows::GetLastErrorAsString().c_str()); - } - - wglMakeCurrent(NULL, NULL); - - pp::platform::windows::mark_lifecycle_running(); - App::I->runtime().render_thread_start(*App::I); - App::I->runtime().ui_thread_start(*App::I); - -#ifdef _DEBUG - glad_set_pre_callback(pp::platform::windows::_pre_call_callback); - glad_set_post_callback(pp::platform::windows::_post_call_callback); -#endif - - if (!state.sandboxed) - { - LOG("init WinTab"); - WacomTablet::I.init(state.hWnd); - } - else - { - LOG("SKIP init WinTab"); - } - - LOG("change icon"); - SendMessage(state.hWnd, WM_SETICON, ICON_SMALL, - (LPARAM)LoadIcon(GetModuleHandle(0), MAKEINTRESOURCE(IDI_ICON1))); - - App::I->ui_sync(); - - { - WINDOWPLACEMENT wp; - GetWindowPlacement(state.hWnd, &wp); - wp.showCmd = startup.show_command; - SetWindowPlacement(state.hWnd, &wp); - //GetClientRect(hWnd, &clientRect); - //App::I->width = clientRect.right - clientRect.left; - //App::I->height = clientRect.bottom - clientRect.top; - } - - if (start_in_vr) - App::I->vr_start(); - - LOG("show main window"); - SetForegroundWindow(state.hWnd); - //ShowWindow(hWnd, show_cmd); - - splash.dismiss(); - - MSG msg; - LOG("start main loop"); - while (pp::platform::windows::lifecycle_is_running()) - { - // If there any message in the queue process it - auto present = App::I->animate || App::I->redraw ? - PeekMessage(&msg, 0, 0, 0, PM_REMOVE) : GetMessage(&msg, 0, 0, 0); - - if (msg.message == WM_QUIT) - pp::platform::windows::mark_lifecycle_stopped(); - - if (present) - { - DispatchMessage(&msg); - TranslateMessage(&msg); - } - - // list of tasks for the main thread - pp::platform::windows::drain_main_thread_tasks(); - } - // Clean up - WacomTablet::I.terminate(); - - UnregisterClass(startup.window_class.lpszClassName, state.hInst); - LogRemote::I.stop(); + pp::platform::windows::run_main_window_runtime(startup, start_in_vr, splash); } int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) diff --git a/src/node_panel_brush.cpp b/src/node_panel_brush.cpp index 3dbdf7cb..f62bf7d2 100644 --- a/src/node_panel_brush.cpp +++ b/src/node_panel_brush.cpp @@ -1,13 +1,13 @@ #include "pch.h" #include "log.h" #include "node_panel_brush.h" +#include "legacy_brush_panel_ui.h" #include "legacy_brush_preset_panel_ui.h" #include "legacy_brush_panel_services.h" #include "app_core/brush_ui.h" #include "legacy_brush_ui_services.h" #include "legacy_brush_preset_services.h" #include "legacy_ui_overlay_services.h" -#include "asset.h" #include "texture.h" #ifdef __APPLE__ @@ -89,122 +89,17 @@ void NodePanelBrush::execute_texture_list_plan(const pp::app::BrushTextureListPl void NodePanelBrush::init() { - init_template_file("data/dialogs/panel-brushes.xml", "tpl-panel-brushes"); - - m_btn_add = find("btn-add"); - m_btn_add->on_click = [this](Node*) { - App::I->pick_file({ "JPG", "PNG" }, [this](std::string path) { - const auto plan = pp::app::plan_brush_texture_list_add(m_dir_name, App::I->data_path, path); - if (plan) { - execute_texture_list_plan(plan.value()); - } - }); - }; - - m_btn_remove = find("btn-remove"); - m_btn_remove->on_click = [this](Node*) { - if (m_current) - { - int idx = m_container->get_child_index(m_current); - const auto plan = pp::app::plan_brush_texture_list_remove( - static_cast(m_container->m_children.size()), - idx, - m_current->m_user_brush); - if (plan) { - execute_texture_list_plan(plan.value()); - } - } - }; - - m_btn_up = find("btn-up"); - m_btn_up->on_click = [this](Node*) { - if (m_current) - { - int idx = m_container->get_child_index(m_current); - const auto plan = pp::app::plan_brush_texture_list_move( - static_cast(m_container->m_children.size()), - idx, - -1); - if (plan) { - execute_texture_list_plan(plan.value()); - } - } - }; - - m_btn_down = find("btn-down"); - m_btn_down->on_click = [this](Node*) { - if (m_current) - { - int idx = m_container->get_child_index(m_current); - const auto plan = pp::app::plan_brush_texture_list_move( - static_cast(m_container->m_children.size()), - idx, - 1); - if (plan) { - execute_texture_list_plan(plan.value()); - } - } - }; - - m_container = find("brushes"); - - if (Asset::exist(App::I->data_path + "/settings/" + m_dir_name + ".bin") && !restore()) - { - auto mb = App::I->message_box("Brushes", "Could not read brush textures file, it will be deleted.", true); - mb->btn_ok->on_click = [this, mb](Node*) { - Asset::delete_file(App::I->data_path + "/settings/" + m_dir_name + ".bin"); - pp::panopainter::close_legacy_dialog_node(*mb); - }; - mb->btn_cancel->on_click = [mb](Node*) { - pp::panopainter::close_legacy_dialog_node(*mb); - }; - } - - if (m_container->m_children.empty() && !m_dir_name.empty()) - scan(); - save(); + pp::panopainter::LegacyBrushPanelUi::init(*this); } kEventResult NodePanelBrush::handle_event(Event* e) { - switch (e->m_type) - { - case kEventType::MouseLeave: - if (!m_interacted) - break; - // else fall through - case kEventType::MouseUpL: - if (!m_mouse_inside) - { - pp::panopainter::release_legacy_mouse_capture(*this); - if (m_parent) - { - pp::panopainter::detach_legacy_node_from_parent(*this); - } - if (on_popup_close) - { - on_popup_close(this); - } - } - break; - default: - return kEventResult::Available; - break; - } - return kEventResult::Consumed; + return pp::panopainter::LegacyBrushPanelUi::handle_event(*this, e); } void NodePanelBrush::handle_click(Node* target) { - if (target == m_current) - return; - if (m_current) - m_current->m_selected = false; - m_current = (NodeButtonBrush*)target; - m_current->m_selected = true; - if (on_brush_changed) - on_brush_changed(this, m_container->get_child_index(target)); - m_interacted = true; + pp::panopainter::LegacyBrushPanelUi::handle_click(*this, target); } int NodePanelBrush::find_brush(const std::string & name) const @@ -249,7 +144,8 @@ void NodePanelBrush::reload() void NodePanelBrush::added(Node* parent) { - m_interacted = false; + (void)parent; + pp::panopainter::LegacyBrushPanelUi::added(*this); } // ----------------------------------------------------------------------- diff --git a/src/node_panel_brush.h b/src/node_panel_brush.h index 0f3225d1..41ebe99b 100644 --- a/src/node_panel_brush.h +++ b/src/node_panel_brush.h @@ -15,6 +15,7 @@ struct BrushPresetListPlan; } namespace pp::panopainter { class LegacyBrushTextureListServices; +class LegacyBrushPanelUi; class LegacyBrushPresetListServices; class LegacyBrushPresetServices; class LegacyBrushPresetPanelUi; @@ -42,6 +43,7 @@ public: class NodePanelBrush : public Node { friend class pp::panopainter::LegacyBrushTextureListServices; + friend class pp::panopainter::LegacyBrushPanelUi; // brushes that are marked as deleted but file still exists std::vector m_deleted; diff --git a/src/platform_windows/windows_runtime_shell.cpp b/src/platform_windows/windows_runtime_shell.cpp new file mode 100644 index 00000000..a7330ba5 --- /dev/null +++ b/src/platform_windows/windows_runtime_shell.cpp @@ -0,0 +1,131 @@ +#include "pch.h" + +#include "platform_windows/windows_runtime_shell.h" + +#include "app.h" +#include "log.h" +#include "platform_windows/windows_bootstrap_helpers.h" +#include "platform_windows/windows_lifecycle_shell.h" +#include "platform_windows/windows_platform_services.h" +#include "platform_windows/windows_window_shell.h" +#include "wacom.h" +#include "../resource.h" + +namespace pp::platform::windows { + +namespace { + +void register_touch_window(HWND hWnd) +{ + // link: https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-registertouchwindow + if (RegisterTouchWindow(hWnd, 0) == 0) + { + LOG("RegisterTouchWindow error: %s", GetLastErrorAsString().c_str()); + } +} + +void initialize_runtime_threads() +{ + mark_lifecycle_running(); + App::I->runtime().render_thread_start(*App::I); + App::I->runtime().ui_thread_start(*App::I); +} + +void install_debug_gl_callbacks() +{ +#ifdef _DEBUG + glad_set_pre_callback(_pre_call_callback); + glad_set_post_callback(_post_call_callback); +#endif +} + +void initialize_wintab(HWND hWnd, bool sandboxed) +{ + if (!sandboxed) + { + LOG("init WinTab"); + WacomTablet::I.init(hWnd); + } + else + { + LOG("SKIP init WinTab"); + } +} + +void set_main_window_icon(HWND hWnd) +{ + LOG("change icon"); + SendMessage( + hWnd, + WM_SETICON, + ICON_SMALL, + (LPARAM)LoadIcon(GetModuleHandle(0), MAKEINTRESOURCE(IDI_ICON1))); +} + +void restore_window_placement(HWND hWnd, int show_command) +{ + WINDOWPLACEMENT wp; + GetWindowPlacement(hWnd, &wp); + wp.showCmd = show_command; + SetWindowPlacement(hWnd, &wp); +} + +void run_main_message_loop() +{ + MSG msg; + LOG("start main loop"); + while (lifecycle_is_running()) + { + auto present = App::I->animate || App::I->redraw ? + PeekMessage(&msg, 0, 0, 0, PM_REMOVE) : GetMessage(&msg, 0, 0, 0); + + if (msg.message == WM_QUIT) + mark_lifecycle_stopped(); + + if (present) + { + DispatchMessage(&msg); + TranslateMessage(&msg); + } + + drain_main_thread_tasks(); + } +} + +void shutdown_main_window_runtime(const MainWindowStartupState& startup, HINSTANCE hInst) +{ + WacomTablet::I.terminate(); + UnregisterClass(startup.window_class.lpszClassName, hInst); + LogRemote::I.stop(); +} + +} + +void run_main_window_runtime(const MainWindowStartupState& startup, bool start_in_vr, SplashScreen& splash) +{ + auto& state = retained_state(); + register_touch_window(state.hWnd); + + wglMakeCurrent(NULL, NULL); + + initialize_runtime_threads(); + install_debug_gl_callbacks(); + initialize_wintab(state.hWnd, state.sandboxed); + set_main_window_icon(state.hWnd); + + App::I->ui_sync(); + restore_window_placement(state.hWnd, startup.show_command); + + if (start_in_vr) + App::I->vr_start(); + + LOG("show main window"); + SetForegroundWindow(state.hWnd); + + splash.dismiss(); + + run_main_message_loop(); + shutdown_main_window_runtime(startup, state.hInst); +} + +} diff --git a/src/platform_windows/windows_runtime_shell.h b/src/platform_windows/windows_runtime_shell.h new file mode 100644 index 00000000..f3e1d2ce --- /dev/null +++ b/src/platform_windows/windows_runtime_shell.h @@ -0,0 +1,10 @@ +#pragma once + +#include "platform_windows/windows_bootstrap_helpers.h" +#include "platform_windows/windows_splash.h" + +namespace pp::platform::windows { + +void run_main_window_runtime(const MainWindowStartupState& startup, bool start_in_vr, SplashScreen& splash); + +}