Extract menu, stylus, and canvas draw helpers
This commit is contained in:
@@ -94,6 +94,7 @@ set(PP_PANOPAINTER_APP_SOURCES
|
|||||||
src/app_dialogs.cpp
|
src/app_dialogs.cpp
|
||||||
src/app_events.cpp
|
src/app_events.cpp
|
||||||
src/app_layout.cpp
|
src/app_layout.cpp
|
||||||
|
src/app_layout_about_layer_menu.cpp
|
||||||
src/app_layout_file_menu.cpp
|
src/app_layout_file_menu.cpp
|
||||||
src/app_layout_tools_menu.cpp
|
src/app_layout_tools_menu.cpp
|
||||||
src/app_shaders.cpp
|
src/app_shaders.cpp
|
||||||
@@ -164,6 +165,8 @@ set(PP_WINDOWS_PLATFORM_SOURCES
|
|||||||
src/platform_windows/windows_platform_services.h
|
src/platform_windows/windows_platform_services.h
|
||||||
src/platform_windows/windows_splash.cpp
|
src/platform_windows/windows_splash.cpp
|
||||||
src/platform_windows/windows_splash.h
|
src/platform_windows/windows_splash.h
|
||||||
|
src/platform_windows/windows_stylus_input.cpp
|
||||||
|
src/platform_windows/windows_stylus_input.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(PP_WINDOWS_APP_SOURCES
|
set(PP_WINDOWS_APP_SOURCES
|
||||||
|
|||||||
@@ -80,13 +80,13 @@ What is still carrying too much live ownership:
|
|||||||
Current hotspot files:
|
Current hotspot files:
|
||||||
|
|
||||||
- `src/canvas.cpp`: 2645 lines
|
- `src/canvas.cpp`: 2645 lines
|
||||||
- `src/app_layout.cpp`: 1360 lines
|
- `src/app_layout.cpp`: 1249 lines
|
||||||
- `src/canvas_modes.cpp`: 1798 lines
|
- `src/canvas_modes.cpp`: 1798 lines
|
||||||
- `src/node.cpp`: 1551 lines
|
- `src/node.cpp`: 1551 lines
|
||||||
- `src/main.cpp`: 1181 lines
|
- `src/main.cpp`: 1218 lines
|
||||||
- `src/node_panel_brush.cpp`: 1197 lines
|
- `src/node_panel_brush.cpp`: 1197 lines
|
||||||
- `src/node_stroke_preview.cpp`: 933 lines
|
- `src/node_stroke_preview.cpp`: 933 lines
|
||||||
- `src/node_canvas.cpp`: 888 lines
|
- `src/node_canvas.cpp`: 968 lines
|
||||||
- `src/app.cpp`: 950 lines
|
- `src/app.cpp`: 950 lines
|
||||||
- `src/app_dialogs.cpp`: 908 lines
|
- `src/app_dialogs.cpp`: 908 lines
|
||||||
|
|
||||||
@@ -122,14 +122,19 @@ Current architecture mismatches that must be treated as real blockers:
|
|||||||
current-mode, and grid-mode callback setup now routed through the same
|
current-mode, and grid-mode callback setup now routed through the same
|
||||||
retained helper family, while post-draw callback assembly and the remaining
|
retained helper family, while post-draw callback assembly and the remaining
|
||||||
per-layer render-path orchestration now also route through retained
|
per-layer render-path orchestration now also route through retained
|
||||||
draw-merge helpers even though the broader node draw loop is still inline.
|
draw-merge helpers even though the broader node draw loop is still inline,
|
||||||
|
with the non-`draw_merged` outer layer/plane traversal now also routing
|
||||||
|
through `execute_legacy_canvas_draw_layer_traversal(...)` while the heavier
|
||||||
|
per-layer GL setup and draw lambdas still live in `src/node_canvas.cpp`.
|
||||||
- `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, even though tools-menu binding
|
rather than thin composition/binding surfaces, even though tools-menu binding
|
||||||
plus nested panels/options submenu wiring now live in
|
plus nested panels/options submenu wiring now live in
|
||||||
`src/app_layout_tools_menu.cpp` and `App::init_menu_tools()` is now a thin
|
`src/app_layout_tools_menu.cpp` and `App::init_menu_tools()` is now a thin
|
||||||
call-through, while file-menu binding plus the export submenu wiring now also
|
call-through, while file-menu binding plus the export submenu wiring now also
|
||||||
live in `src/app_layout_file_menu.cpp` and `App::init_menu_file()` is now a
|
live in `src/app_layout_file_menu.cpp` and `App::init_menu_file()` is now a
|
||||||
thin call-through.
|
thin call-through, while about-menu and layer-menu wiring now also live in
|
||||||
|
`src/app_layout_about_layer_menu.cpp` and `App::init_menu_about()` plus
|
||||||
|
`App::init_menu_layer()` are now thin call-throughs.
|
||||||
- `App`, `Canvas`, `Node`, retained workers, and platform entrypoints still use
|
- `App`, `Canvas`, `Node`, retained workers, and platform entrypoints still use
|
||||||
global singleton reach, raw observer pointers, retained static worker
|
global singleton reach, raw observer pointers, retained static worker
|
||||||
ownership in several app families, and ad hoc mutex/condition-variable
|
ownership in several app families, and ad hoc mutex/condition-variable
|
||||||
@@ -153,7 +158,9 @@ Current architecture mismatches that must be treated as real blockers:
|
|||||||
live under `AppRuntime` instead of retained static app-events/canvas
|
live under `AppRuntime` instead of retained static app-events/canvas
|
||||||
workers, and the splash-screen dialog loop, HWND ownership, and bitmap setup
|
workers, and the splash-screen dialog loop, HWND ownership, and bitmap setup
|
||||||
now live in `src/platform_windows/windows_splash.cpp` instead of
|
now live in `src/platform_windows/windows_splash.cpp` instead of
|
||||||
`src/main.cpp`,
|
`src/main.cpp`, while Win32 pointer API loading, stylus/ink timer decay,
|
||||||
|
Wintab packet reset, and `WM_POINTERUPDATE` pen/touch handling now also live
|
||||||
|
in `src/platform_windows/windows_stylus_input.cpp` instead of `src/main.cpp`,
|
||||||
while `App::rec_loop()` now delegates worker-iteration orchestration into
|
while `App::rec_loop()` now delegates worker-iteration orchestration into
|
||||||
the retained recording bridge, `App::update_rec_frames()` now delegates
|
the retained recording bridge, `App::update_rec_frames()` now delegates
|
||||||
recording label refresh through that same retained recording path, and the
|
recording label refresh through that same retained recording path, and the
|
||||||
|
|||||||
@@ -193,6 +193,10 @@ Current slice:
|
|||||||
remaining per-layer render-path orchestration now also routes through
|
remaining per-layer render-path orchestration now also routes through
|
||||||
`execute_legacy_canvas_draw_merge_layer_path(...)`, but the node still owns
|
`execute_legacy_canvas_draw_merge_layer_path(...)`, but the node still owns
|
||||||
broader draw-loop and renderer-state shell sequencing.
|
broader draw-loop and renderer-state shell sequencing.
|
||||||
|
- `NodeCanvas` outer non-`draw_merged` layer/plane traversal, onion-range
|
||||||
|
failure handling, and visit payload setup now also route through
|
||||||
|
`execute_legacy_canvas_draw_layer_traversal(...)`, but the node still owns
|
||||||
|
the heavier per-layer GL setup and draw lambdas.
|
||||||
|
|
||||||
Write scope:
|
Write scope:
|
||||||
- `src/node_stroke_preview.cpp`
|
- `src/node_stroke_preview.cpp`
|
||||||
@@ -271,7 +275,7 @@ targets look like helpers under one old monolith.
|
|||||||
Status: In Progress
|
Status: In Progress
|
||||||
|
|
||||||
Why now:
|
Why now:
|
||||||
`src/app_layout.cpp` is still a 1360-line mixed file that builds menus,
|
`src/app_layout.cpp` is still a 1249-line mixed file that builds menus,
|
||||||
attaches callbacks, computes planner inputs, and mutates UI state directly.
|
attaches callbacks, computes planner inputs, and mutates UI state directly.
|
||||||
|
|
||||||
Current slice:
|
Current slice:
|
||||||
@@ -283,6 +287,10 @@ Current slice:
|
|||||||
`src/app_layout_file_menu.cpp`, and `App::init_menu_file()` is now a thin
|
`src/app_layout_file_menu.cpp`, and `App::init_menu_file()` is now a thin
|
||||||
call-through, but about/layer/sidebar and broader layout composition are
|
call-through, but about/layer/sidebar and broader layout composition are
|
||||||
still inline in `src/app_layout.cpp`.
|
still inline in `src/app_layout.cpp`.
|
||||||
|
- About-menu and layer-menu wiring now also live in
|
||||||
|
`src/app_layout_about_layer_menu.cpp`, and `App::init_menu_about()` plus
|
||||||
|
`App::init_menu_layer()` are now thin call-throughs, but edit/sidebar and
|
||||||
|
broader layout composition are still inline in `src/app_layout.cpp`.
|
||||||
|
|
||||||
Write scope:
|
Write scope:
|
||||||
- `src/app_layout.cpp`
|
- `src/app_layout.cpp`
|
||||||
@@ -405,6 +413,10 @@ Current slice:
|
|||||||
pair during initialization and context recreation
|
pair during initialization and context recreation
|
||||||
- `main.cpp` main-thread queued task state now sits behind a narrow retained
|
- `main.cpp` main-thread queued task state now sits behind a narrow retained
|
||||||
helper instead of `RetainedState.main_tasklist` / `main_task_mutex` directly
|
helper instead of `RetainedState.main_tasklist` / `main_task_mutex` directly
|
||||||
|
- Win32 pointer API loading, stylus/ink timer ownership and decay, `WT_PACKET`
|
||||||
|
reset, and `WM_POINTERUPDATE` pen/touch handling now live in
|
||||||
|
`src/platform_windows/windows_stylus_input.cpp` instead of `src/main.cpp`,
|
||||||
|
but broader retained Win32 shell state is still open
|
||||||
- prepared-file background work now runs through an `AppRuntime`-owned worker
|
- prepared-file background work now runs through an `AppRuntime`-owned worker
|
||||||
queue instead of a retained static worker in `src/app_events.cpp`
|
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
|
- canvas async import/export/save/open background work now also runs through an
|
||||||
|
|||||||
@@ -33,6 +33,8 @@
|
|||||||
|
|
||||||
namespace pp::panopainter {
|
namespace pp::panopainter {
|
||||||
void bind_legacy_file_menu(App& app);
|
void bind_legacy_file_menu(App& app);
|
||||||
|
void bind_legacy_about_menu(App& app);
|
||||||
|
void bind_legacy_layer_menu(App& app);
|
||||||
void bind_legacy_tools_menu(App& app);
|
void bind_legacy_tools_menu(App& app);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,39 +95,6 @@ void close_legacy_overlay_handles_if_open(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pp::app::DocumentLayerMenuPlan make_layer_menu_plan(
|
|
||||||
pp::app::DocumentLayerMenuCommand command,
|
|
||||||
App& app)
|
|
||||||
{
|
|
||||||
const bool has_current_layer = app.layers && app.layers->m_current_layer;
|
|
||||||
const int current_index = app.canvas && app.canvas->m_canvas
|
|
||||||
? app.canvas->m_canvas->m_current_layer_idx
|
|
||||||
: 0;
|
|
||||||
const int animation_duration = Canvas::I
|
|
||||||
? Canvas::I->anim_duration()
|
|
||||||
: 0;
|
|
||||||
const std::string current_name = has_current_layer
|
|
||||||
? app.layers->m_current_layer->m_label_text
|
|
||||||
: std::string {};
|
|
||||||
std::string lower_name;
|
|
||||||
if (app.canvas && app.canvas->m_canvas && current_index > 0
|
|
||||||
&& current_index - 1 < static_cast<int>(app.canvas->m_canvas->m_layers.size()))
|
|
||||||
{
|
|
||||||
lower_name = app.canvas->m_canvas->m_layers[current_index - 1]->m_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto plan = pp::app::plan_document_layer_menu(
|
|
||||||
command,
|
|
||||||
has_current_layer,
|
|
||||||
current_index,
|
|
||||||
animation_duration,
|
|
||||||
current_name,
|
|
||||||
lower_name);
|
|
||||||
if (plan)
|
|
||||||
return plan.value();
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool should_open_tools_panel(const pp::app::ToolsPanelPlan& plan) noexcept
|
[[nodiscard]] bool should_open_tools_panel(const pp::app::ToolsPanelPlan& plan) noexcept
|
||||||
{
|
{
|
||||||
return plan.action == pp::app::ToolsPanelAction::open_floating_panel;
|
return plan.action == pp::app::ToolsPanelAction::open_floating_panel;
|
||||||
@@ -154,23 +123,11 @@ void execute_main_toolbar_plan(App& app, const pp::app::MainToolbarPlan& plan)
|
|||||||
pp::panopainter::execute_legacy_main_toolbar_plan(app, plan);
|
pp::panopainter::execute_legacy_main_toolbar_plan(app, plan);
|
||||||
}
|
}
|
||||||
|
|
||||||
void execute_about_menu_plan(App& app, const pp::app::AboutMenuPlan& plan)
|
|
||||||
{
|
|
||||||
pp::panopainter::execute_legacy_about_menu_plan(app, plan);
|
|
||||||
}
|
|
||||||
|
|
||||||
void execute_tools_menu_plan(App& app, const pp::app::ToolsMenuPlan& plan)
|
void execute_tools_menu_plan(App& app, const pp::app::ToolsMenuPlan& plan)
|
||||||
{
|
{
|
||||||
pp::panopainter::execute_legacy_tools_menu_plan(app, plan);
|
pp::panopainter::execute_legacy_tools_menu_plan(app, plan);
|
||||||
}
|
}
|
||||||
|
|
||||||
void execute_document_layer_menu_plan(App& app, const pp::app::DocumentLayerMenuPlan& plan)
|
|
||||||
{
|
|
||||||
const auto status = pp::panopainter::execute_legacy_document_layer_menu_plan(app, plan);
|
|
||||||
if (!status.ok())
|
|
||||||
LOG("Layer menu action failed: %s", status.message);
|
|
||||||
}
|
|
||||||
|
|
||||||
void execute_document_layer_merge_plan(App& app, const pp::app::DocumentLayerMergePlan& plan)
|
void execute_document_layer_merge_plan(App& app, const pp::app::DocumentLayerMergePlan& plan)
|
||||||
{
|
{
|
||||||
const auto status = pp::panopainter::execute_legacy_document_layer_merge_plan(app, plan);
|
const auto status = pp::panopainter::execute_legacy_document_layer_merge_plan(app, plan);
|
||||||
@@ -764,113 +721,7 @@ void App::init_menu_tools()
|
|||||||
|
|
||||||
void App::init_menu_about()
|
void App::init_menu_about()
|
||||||
{
|
{
|
||||||
if (auto* menu_file = layout[main_id]->find<NodeButtonCustom>("menu-about"))
|
pp::panopainter::bind_legacy_about_menu(*this);
|
||||||
{
|
|
||||||
menu_file->on_click = [=](Node*) {
|
|
||||||
auto* popup_root = layout[main_id];
|
|
||||||
if (!popup_root) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
glm::vec2 pos = menu_file->m_pos + glm::vec2(0, menu_file->m_size.y);
|
|
||||||
auto popup = add_menu_popup(*this, "about-menu", pos, menu_file->m_size.x);
|
|
||||||
if (!popup)
|
|
||||||
return;
|
|
||||||
pp::panopainter::detach_legacy_node_from_parent(*popup);
|
|
||||||
auto popup_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_root, popup);
|
|
||||||
if (!popup_overlay) {
|
|
||||||
pp::panopainter::destroy_legacy_node(*popup);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto popup_handle = popup_overlay.value();
|
|
||||||
|
|
||||||
popup->find<NodeButtonCustom>("about-app")->on_click = [this, popup_root, popup_handle](Node*) {
|
|
||||||
const auto plan = pp::app::plan_about_menu_command(
|
|
||||||
pp::app::AboutMenuCommand::about_app,
|
|
||||||
g_version_major,
|
|
||||||
g_version_minor,
|
|
||||||
g_version_fix);
|
|
||||||
execute_about_menu_plan(*this, plan);
|
|
||||||
if (plan.closes_root_popup)
|
|
||||||
{
|
|
||||||
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
popup->find<NodeButtonCustom>("about-doc")->on_click = [this, popup_root, popup_handle](Node*) {
|
|
||||||
// auto path = Asset::absolute("data/doc/test.pdf");
|
|
||||||
// display_file(path);
|
|
||||||
const auto plan = pp::app::plan_about_menu_command(
|
|
||||||
pp::app::AboutMenuCommand::help_guide,
|
|
||||||
g_version_major,
|
|
||||||
g_version_minor,
|
|
||||||
g_version_fix);
|
|
||||||
execute_about_menu_plan(*this, plan);
|
|
||||||
if (plan.closes_root_popup)
|
|
||||||
{
|
|
||||||
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (auto item = popup->find<NodeButtonCustom>("about-news"))
|
|
||||||
{
|
|
||||||
if (auto text = item->find<NodeText>("menu-label"))
|
|
||||||
{
|
|
||||||
const auto plan = pp::app::plan_about_menu_command(
|
|
||||||
pp::app::AboutMenuCommand::whats_new,
|
|
||||||
g_version_major,
|
|
||||||
g_version_minor,
|
|
||||||
g_version_fix);
|
|
||||||
text->set_text(plan.label.c_str());
|
|
||||||
}
|
|
||||||
item->on_click = [this, popup_root, popup_handle](Node*) {
|
|
||||||
const auto plan = pp::app::plan_about_menu_command(
|
|
||||||
pp::app::AboutMenuCommand::whats_new,
|
|
||||||
g_version_major,
|
|
||||||
g_version_minor,
|
|
||||||
g_version_fix);
|
|
||||||
execute_about_menu_plan(*this, plan);
|
|
||||||
if (plan.closes_root_popup)
|
|
||||||
{
|
|
||||||
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto b = popup->find<NodeButtonCustom>("about-crash"))
|
|
||||||
{
|
|
||||||
b->on_click = [this, popup_root, popup_handle](Node*) {
|
|
||||||
const auto plan = pp::app::plan_about_menu_command(
|
|
||||||
pp::app::AboutMenuCommand::induce_crash,
|
|
||||||
g_version_major,
|
|
||||||
g_version_minor,
|
|
||||||
g_version_fix);
|
|
||||||
execute_about_menu_plan(*this, plan);
|
|
||||||
if (plan.closes_root_popup)
|
|
||||||
{
|
|
||||||
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto b = popup->find<NodeButtonCustom>("about-perf"))
|
|
||||||
{
|
|
||||||
b->on_click = [this, popup_root, popup_handle](Node*) {
|
|
||||||
const auto plan = pp::app::plan_about_menu_command(
|
|
||||||
pp::app::AboutMenuCommand::performance_test,
|
|
||||||
g_version_major,
|
|
||||||
g_version_minor,
|
|
||||||
g_version_fix,
|
|
||||||
true,
|
|
||||||
Canvas::I != nullptr);
|
|
||||||
execute_about_menu_plan(*this, plan);
|
|
||||||
if (plan.closes_root_popup)
|
|
||||||
{
|
|
||||||
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::brush_update(bool update_color, bool update_brush)
|
void App::brush_update(bool update_color, bool update_brush)
|
||||||
@@ -933,63 +784,7 @@ void App::brush_update(bool update_color, bool update_brush)
|
|||||||
|
|
||||||
void App::init_menu_layer()
|
void App::init_menu_layer()
|
||||||
{
|
{
|
||||||
if (auto* menu_file = layout[main_id]->find<NodeButtonCustom>("menu-layers"))
|
pp::panopainter::bind_legacy_layer_menu(*this);
|
||||||
{
|
|
||||||
menu_file->on_click = [=](Node*) {
|
|
||||||
auto* popup_root = layout[main_id];
|
|
||||||
if (!popup_root) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
glm::vec2 pos = menu_file->m_pos + glm::vec2(0, menu_file->m_size.y);
|
|
||||||
auto popup = add_menu_popup(*this, "layers-menu", pos, menu_file->m_size.x);
|
|
||||||
if (!popup)
|
|
||||||
return;
|
|
||||||
pp::panopainter::detach_legacy_node_from_parent(*popup);
|
|
||||||
auto popup_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_root, popup);
|
|
||||||
if (!popup_overlay) {
|
|
||||||
pp::panopainter::destroy_legacy_node(*popup);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto popup_handle = popup_overlay.value();
|
|
||||||
|
|
||||||
popup->find<NodeButtonCustom>("layer-clear")->on_click = [this, popup_root, popup_handle](Node*) {
|
|
||||||
const auto plan = make_layer_menu_plan(pp::app::DocumentLayerMenuCommand::clear, *this);
|
|
||||||
execute_document_layer_menu_plan(*this, plan);
|
|
||||||
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
|
||||||
};
|
|
||||||
{
|
|
||||||
const auto plan = make_layer_menu_plan(pp::app::DocumentLayerMenuCommand::clear, *this);
|
|
||||||
popup->find<NodeButtonCustom>("layer-clear")->
|
|
||||||
find<NodeText>("menu-label")->
|
|
||||||
set_text(plan.label.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
popup->find<NodeButtonCustom>("layer-rename")->on_click = [this, popup_root, popup_handle](Node*) {
|
|
||||||
const auto plan = make_layer_menu_plan(pp::app::DocumentLayerMenuCommand::rename, *this);
|
|
||||||
execute_document_layer_menu_plan(*this, plan);
|
|
||||||
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
|
||||||
};
|
|
||||||
{
|
|
||||||
const auto plan = make_layer_menu_plan(pp::app::DocumentLayerMenuCommand::rename, *this);
|
|
||||||
popup->find<NodeButtonCustom>("layer-rename")->
|
|
||||||
find<NodeText>("menu-label")->
|
|
||||||
set_text(plan.label.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
popup->find<NodeButtonCustom>("layer-merge")->on_click = [this, popup_root, popup_handle](Node*) {
|
|
||||||
const auto plan = make_layer_menu_plan(pp::app::DocumentLayerMenuCommand::merge_down, *this);
|
|
||||||
execute_document_layer_menu_plan(*this, plan);
|
|
||||||
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
|
||||||
};
|
|
||||||
{
|
|
||||||
const auto plan = make_layer_menu_plan(pp::app::DocumentLayerMenuCommand::merge_down, *this);
|
|
||||||
popup->find<NodeButtonCustom>("layer-merge")->
|
|
||||||
find<NodeText>("menu-label")->
|
|
||||||
set_text(plan.label.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::initLayout()
|
void App::initLayout()
|
||||||
|
|||||||
264
src/app_layout_about_layer_menu.cpp
Normal file
264
src/app_layout_about_layer_menu.cpp
Normal file
@@ -0,0 +1,264 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "app.h"
|
||||||
|
#include "app_core/about_menu.h"
|
||||||
|
#include "app_core/document_layer.h"
|
||||||
|
#include "legacy_app_shell_services.h"
|
||||||
|
#include "legacy_document_layer_services.h"
|
||||||
|
#include "legacy_ui_overlay_services.h"
|
||||||
|
#include "node_button_custom.h"
|
||||||
|
#include "node_popup_menu.h"
|
||||||
|
#include "node_text.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
std::shared_ptr<NodePopupMenu> add_menu_popup(
|
||||||
|
App& app,
|
||||||
|
const char* template_id,
|
||||||
|
glm::vec2 position,
|
||||||
|
float rtl_anchor_width)
|
||||||
|
{
|
||||||
|
const auto popup = pp::panopainter::add_legacy_popup_menu(
|
||||||
|
app,
|
||||||
|
template_id,
|
||||||
|
position.x,
|
||||||
|
position.y,
|
||||||
|
rtl_anchor_width);
|
||||||
|
if (!popup) {
|
||||||
|
LOG("Popup menu '%s' failed: %s", template_id ? template_id : "<null>", popup.status().message);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return popup.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
void close_legacy_overlay_handle_ignoring_status(
|
||||||
|
Node& anchor,
|
||||||
|
pp::ui::NodeHandle overlay) noexcept
|
||||||
|
{
|
||||||
|
(void)pp::panopainter::close_legacy_overlay_node(anchor, overlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
pp::app::DocumentLayerMenuPlan make_layer_menu_plan(
|
||||||
|
pp::app::DocumentLayerMenuCommand command,
|
||||||
|
App& app)
|
||||||
|
{
|
||||||
|
const bool has_current_layer = app.layers && app.layers->m_current_layer;
|
||||||
|
const int current_index = app.canvas && app.canvas->m_canvas
|
||||||
|
? app.canvas->m_canvas->m_current_layer_idx
|
||||||
|
: 0;
|
||||||
|
const int animation_duration = Canvas::I
|
||||||
|
? Canvas::I->anim_duration()
|
||||||
|
: 0;
|
||||||
|
const std::string current_name = has_current_layer
|
||||||
|
? app.layers->m_current_layer->m_label_text
|
||||||
|
: std::string {};
|
||||||
|
std::string lower_name;
|
||||||
|
if (app.canvas && app.canvas->m_canvas && current_index > 0
|
||||||
|
&& current_index - 1 < static_cast<int>(app.canvas->m_canvas->m_layers.size()))
|
||||||
|
{
|
||||||
|
lower_name = app.canvas->m_canvas->m_layers[current_index - 1]->m_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto plan = pp::app::plan_document_layer_menu(
|
||||||
|
command,
|
||||||
|
has_current_layer,
|
||||||
|
current_index,
|
||||||
|
animation_duration,
|
||||||
|
current_name,
|
||||||
|
lower_name);
|
||||||
|
if (plan)
|
||||||
|
return plan.value();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void execute_about_menu_plan(App& app, const pp::app::AboutMenuPlan& plan)
|
||||||
|
{
|
||||||
|
pp::panopainter::execute_legacy_about_menu_plan(app, plan);
|
||||||
|
}
|
||||||
|
|
||||||
|
void execute_document_layer_menu_plan(App& app, const pp::app::DocumentLayerMenuPlan& plan)
|
||||||
|
{
|
||||||
|
const auto status = pp::panopainter::execute_legacy_document_layer_menu_plan(app, plan);
|
||||||
|
if (!status.ok())
|
||||||
|
LOG("Layer menu action failed: %s", status.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace pp::panopainter {
|
||||||
|
|
||||||
|
void bind_legacy_about_menu(App& app)
|
||||||
|
{
|
||||||
|
auto main = app.layout[app.main_id];
|
||||||
|
|
||||||
|
if (auto* menu_file = main->find<NodeButtonCustom>("menu-about"))
|
||||||
|
{
|
||||||
|
menu_file->on_click = [&app, menu_file](Node*) {
|
||||||
|
auto* popup_root = app.layout[app.main_id];
|
||||||
|
if (!popup_root) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
glm::vec2 pos = menu_file->m_pos + glm::vec2(0, menu_file->m_size.y);
|
||||||
|
auto popup = add_menu_popup(app, "about-menu", pos, menu_file->m_size.x);
|
||||||
|
if (!popup)
|
||||||
|
return;
|
||||||
|
pp::panopainter::detach_legacy_node_from_parent(*popup);
|
||||||
|
auto popup_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_root, popup);
|
||||||
|
if (!popup_overlay) {
|
||||||
|
pp::panopainter::destroy_legacy_node(*popup);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto popup_handle = popup_overlay.value();
|
||||||
|
|
||||||
|
popup->find<NodeButtonCustom>("about-app")->on_click = [&app, popup_root, popup_handle](Node*) {
|
||||||
|
const auto plan = pp::app::plan_about_menu_command(
|
||||||
|
pp::app::AboutMenuCommand::about_app,
|
||||||
|
g_version_major,
|
||||||
|
g_version_minor,
|
||||||
|
g_version_fix);
|
||||||
|
execute_about_menu_plan(app, plan);
|
||||||
|
if (plan.closes_root_popup)
|
||||||
|
{
|
||||||
|
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
popup->find<NodeButtonCustom>("about-doc")->on_click = [&app, popup_root, popup_handle](Node*) {
|
||||||
|
// auto path = Asset::absolute("data/doc/test.pdf");
|
||||||
|
// display_file(path);
|
||||||
|
const auto plan = pp::app::plan_about_menu_command(
|
||||||
|
pp::app::AboutMenuCommand::help_guide,
|
||||||
|
g_version_major,
|
||||||
|
g_version_minor,
|
||||||
|
g_version_fix);
|
||||||
|
execute_about_menu_plan(app, plan);
|
||||||
|
if (plan.closes_root_popup)
|
||||||
|
{
|
||||||
|
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (auto item = popup->find<NodeButtonCustom>("about-news"))
|
||||||
|
{
|
||||||
|
if (auto text = item->find<NodeText>("menu-label"))
|
||||||
|
{
|
||||||
|
const auto plan = pp::app::plan_about_menu_command(
|
||||||
|
pp::app::AboutMenuCommand::whats_new,
|
||||||
|
g_version_major,
|
||||||
|
g_version_minor,
|
||||||
|
g_version_fix);
|
||||||
|
text->set_text(plan.label.c_str());
|
||||||
|
}
|
||||||
|
item->on_click = [&app, popup_root, popup_handle](Node*) {
|
||||||
|
const auto plan = pp::app::plan_about_menu_command(
|
||||||
|
pp::app::AboutMenuCommand::whats_new,
|
||||||
|
g_version_major,
|
||||||
|
g_version_minor,
|
||||||
|
g_version_fix);
|
||||||
|
execute_about_menu_plan(app, plan);
|
||||||
|
if (plan.closes_root_popup)
|
||||||
|
{
|
||||||
|
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto b = popup->find<NodeButtonCustom>("about-crash"))
|
||||||
|
{
|
||||||
|
b->on_click = [&app, popup_root, popup_handle](Node*) {
|
||||||
|
const auto plan = pp::app::plan_about_menu_command(
|
||||||
|
pp::app::AboutMenuCommand::induce_crash,
|
||||||
|
g_version_major,
|
||||||
|
g_version_minor,
|
||||||
|
g_version_fix);
|
||||||
|
execute_about_menu_plan(app, plan);
|
||||||
|
if (plan.closes_root_popup)
|
||||||
|
{
|
||||||
|
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto b = popup->find<NodeButtonCustom>("about-perf"))
|
||||||
|
{
|
||||||
|
b->on_click = [&app, popup_root, popup_handle](Node*) {
|
||||||
|
const auto plan = pp::app::plan_about_menu_command(
|
||||||
|
pp::app::AboutMenuCommand::performance_test,
|
||||||
|
g_version_major,
|
||||||
|
g_version_minor,
|
||||||
|
g_version_fix,
|
||||||
|
true,
|
||||||
|
Canvas::I != nullptr);
|
||||||
|
execute_about_menu_plan(app, plan);
|
||||||
|
if (plan.closes_root_popup)
|
||||||
|
{
|
||||||
|
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bind_legacy_layer_menu(App& app)
|
||||||
|
{
|
||||||
|
auto main = app.layout[app.main_id];
|
||||||
|
|
||||||
|
if (auto* menu_file = main->find<NodeButtonCustom>("menu-layers"))
|
||||||
|
{
|
||||||
|
menu_file->on_click = [&app, menu_file](Node*) {
|
||||||
|
auto* popup_root = app.layout[app.main_id];
|
||||||
|
if (!popup_root) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
glm::vec2 pos = menu_file->m_pos + glm::vec2(0, menu_file->m_size.y);
|
||||||
|
auto popup = add_menu_popup(app, "layers-menu", pos, menu_file->m_size.x);
|
||||||
|
if (!popup)
|
||||||
|
return;
|
||||||
|
pp::panopainter::detach_legacy_node_from_parent(*popup);
|
||||||
|
auto popup_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_root, popup);
|
||||||
|
if (!popup_overlay) {
|
||||||
|
pp::panopainter::destroy_legacy_node(*popup);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto popup_handle = popup_overlay.value();
|
||||||
|
|
||||||
|
popup->find<NodeButtonCustom>("layer-clear")->on_click = [&app, popup_root, popup_handle](Node*) {
|
||||||
|
const auto plan = make_layer_menu_plan(pp::app::DocumentLayerMenuCommand::clear, app);
|
||||||
|
execute_document_layer_menu_plan(app, plan);
|
||||||
|
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
||||||
|
};
|
||||||
|
{
|
||||||
|
const auto plan = make_layer_menu_plan(pp::app::DocumentLayerMenuCommand::clear, app);
|
||||||
|
popup->find<NodeButtonCustom>("layer-clear")->
|
||||||
|
find<NodeText>("menu-label")->
|
||||||
|
set_text(plan.label.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
popup->find<NodeButtonCustom>("layer-rename")->on_click = [&app, popup_root, popup_handle](Node*) {
|
||||||
|
const auto plan = make_layer_menu_plan(pp::app::DocumentLayerMenuCommand::rename, app);
|
||||||
|
execute_document_layer_menu_plan(app, plan);
|
||||||
|
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
||||||
|
};
|
||||||
|
{
|
||||||
|
const auto plan = make_layer_menu_plan(pp::app::DocumentLayerMenuCommand::rename, app);
|
||||||
|
popup->find<NodeButtonCustom>("layer-rename")->
|
||||||
|
find<NodeText>("menu-label")->
|
||||||
|
set_text(plan.label.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
popup->find<NodeButtonCustom>("layer-merge")->on_click = [&app, popup_root, popup_handle](Node*) {
|
||||||
|
const auto plan = make_layer_menu_plan(pp::app::DocumentLayerMenuCommand::merge_down, app);
|
||||||
|
execute_document_layer_menu_plan(app, plan);
|
||||||
|
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
||||||
|
};
|
||||||
|
{
|
||||||
|
const auto plan = make_layer_menu_plan(pp::app::DocumentLayerMenuCommand::merge_down, app);
|
||||||
|
popup->find<NodeButtonCustom>("layer-merge")->
|
||||||
|
find<NodeText>("menu-label")->
|
||||||
|
set_text(plan.label.c_str());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace pp::panopainter
|
||||||
@@ -130,6 +130,14 @@ struct LegacyCanvasDrawMergeLayerPathExecution {
|
|||||||
std::function<void(int, float)> draw_frame;
|
std::function<void(int, float)> draw_frame;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct LegacyCanvasDrawLayerVisit {
|
||||||
|
size_t layer_index = 0;
|
||||||
|
int plane_index = 0;
|
||||||
|
int z = 0;
|
||||||
|
int first_frame = 0;
|
||||||
|
int last_frame = 0;
|
||||||
|
};
|
||||||
|
|
||||||
struct LegacyCanvasDrawMergeTemporaryCompositeExecution {
|
struct LegacyCanvasDrawMergeTemporaryCompositeExecution {
|
||||||
std::function<void()> setup;
|
std::function<void()> setup;
|
||||||
std::function<void()> bind_samplers;
|
std::function<void()> bind_samplers;
|
||||||
@@ -671,6 +679,39 @@ inline void execute_legacy_canvas_draw_merge_layer_path(
|
|||||||
execution.draw_debug_outline();
|
execution.draw_debug_outline();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename PlanOnionRange, typename ShouldDrawPlane, typename VisitLayerPlane, typename LogOnionRangeFailure>
|
||||||
|
inline void execute_legacy_canvas_draw_layer_traversal(
|
||||||
|
size_t layer_count,
|
||||||
|
PlanOnionRange&& plan_onion_range,
|
||||||
|
ShouldDrawPlane&& should_draw_plane,
|
||||||
|
VisitLayerPlane&& visit_layer_plane,
|
||||||
|
LogOnionRangeFailure&& log_onion_range_failure)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < layer_count; ++i) {
|
||||||
|
const auto layer_index = i;
|
||||||
|
const auto onion_range_result = plan_onion_range(layer_index);
|
||||||
|
if (!onion_range_result) {
|
||||||
|
log_onion_range_failure(onion_range_result.status().message);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto onion_range = onion_range_result.value();
|
||||||
|
for (int plane_index = 0; plane_index < 6; ++plane_index) {
|
||||||
|
if (!should_draw_plane(layer_index, plane_index, onion_range.first_frame, onion_range.last_frame)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
visit_layer_plane(LegacyCanvasDrawLayerVisit {
|
||||||
|
.layer_index = layer_index,
|
||||||
|
.plane_index = plane_index,
|
||||||
|
.z = static_cast<int>(layer_count - i),
|
||||||
|
.first_frame = onion_range.first_frame,
|
||||||
|
.last_frame = onion_range.last_frame,
|
||||||
|
}, onion_range);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline void execute_legacy_canvas_draw_merge_temporary_composite(
|
inline void execute_legacy_canvas_draw_merge_temporary_composite(
|
||||||
const LegacyCanvasDrawMergeTemporaryCompositeExecution& execution)
|
const LegacyCanvasDrawMergeTemporaryCompositeExecution& execution)
|
||||||
{
|
{
|
||||||
|
|||||||
124
src/main.cpp
124
src/main.cpp
@@ -13,6 +13,7 @@
|
|||||||
#include "renderer_gl/opengl_capabilities.h"
|
#include "renderer_gl/opengl_capabilities.h"
|
||||||
#include "platform_windows/windows_platform_services.h"
|
#include "platform_windows/windows_platform_services.h"
|
||||||
#include "platform_windows/windows_splash.h"
|
#include "platform_windows/windows_splash.h"
|
||||||
|
#include "platform_windows/windows_stylus_input.h"
|
||||||
#include "../resource.h"
|
#include "../resource.h"
|
||||||
|
|
||||||
#include <shellscalingapi.h>
|
#include <shellscalingapi.h>
|
||||||
@@ -55,9 +56,6 @@ struct RetainedState
|
|||||||
std::map<kKey, int> vkey_map;
|
std::map<kKey, int> vkey_map;
|
||||||
wchar_t window_title[512]{};
|
wchar_t window_title[512]{};
|
||||||
std::jthread hmd_renderer;
|
std::jthread hmd_renderer;
|
||||||
float timer_stylus = 0;
|
|
||||||
float timer_ink_touch = 0;
|
|
||||||
float timer_ink_pen = 0;
|
|
||||||
bool sandboxed = false;
|
bool sandboxed = false;
|
||||||
std::mutex hmd_render_mutex;
|
std::mutex hmd_render_mutex;
|
||||||
std::condition_variable hmd_render_cv;
|
std::condition_variable hmd_render_cv;
|
||||||
@@ -176,25 +174,6 @@ void init_shcore_API()
|
|||||||
SetProcessDpiAwareness_fn = (decltype(SetProcessDpiAwareness_fn))GetProcAddress(dll, "SetProcessDpiAwareness");
|
SetProcessDpiAwareness_fn = (decltype(SetProcessDpiAwareness_fn))GetProcAddress(dll, "SetProcessDpiAwareness");
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL(*GetPointerInfo_fn)(UINT32 pointerId, POINTER_INFO* pointerInfo);
|
|
||||||
BOOL(*GetPointerType_fn)(UINT32 pointerId, POINTER_INPUT_TYPE* pointerType);
|
|
||||||
BOOL(*GetPointerTouchInfo_fn)(UINT32 pointerId, POINTER_TOUCH_INFO* touchInfo);
|
|
||||||
BOOL(*GetPointerPenInfo_fn)(UINT32 pointerId, POINTER_PEN_INFO* penInfo);
|
|
||||||
void init_ink_API()
|
|
||||||
{
|
|
||||||
HMODULE dll = LoadLibrary(L"User32.dll");
|
|
||||||
if (!dll)
|
|
||||||
{
|
|
||||||
LOG("cannot load User32.dll");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
LOG("loaded User32.dll");
|
|
||||||
GetPointerInfo_fn = (decltype(GetPointerInfo_fn))GetProcAddress(dll, "GetPointerInfo");
|
|
||||||
GetPointerType_fn = (decltype(GetPointerType_fn))GetProcAddress(dll, "GetPointerType");
|
|
||||||
GetPointerTouchInfo_fn = (decltype(GetPointerTouchInfo_fn))GetProcAddress(dll, "GetPointerTouchInfo");
|
|
||||||
GetPointerPenInfo_fn = (decltype(GetPointerPenInfo_fn))GetProcAddress(dll, "GetPointerPenInfo");
|
|
||||||
}
|
|
||||||
|
|
||||||
//Returns the last Win32 error, in string format. Returns an empty string if there is no error.
|
//Returns the last Win32 error, in string format. Returns an empty string if there is no error.
|
||||||
std::string GetLastErrorAsString()
|
std::string GetLastErrorAsString()
|
||||||
{
|
{
|
||||||
@@ -245,27 +224,7 @@ void async_unlock()
|
|||||||
|
|
||||||
void win32_update_stylus(float dt)
|
void win32_update_stylus(float dt)
|
||||||
{
|
{
|
||||||
auto& state = retained_state();
|
pp::platform::windows::update_stylus_state(dt);
|
||||||
state.timer_stylus += dt;
|
|
||||||
state.timer_ink_touch += dt;
|
|
||||||
state.timer_ink_pen += dt;
|
|
||||||
|
|
||||||
if (state.timer_stylus > 0.1 && (WacomTablet::I.m_stylus || WacomTablet::I.m_eraser))
|
|
||||||
{
|
|
||||||
WacomTablet::I.m_stylus = false;
|
|
||||||
WacomTablet::I.m_eraser = false;
|
|
||||||
App::I->redraw = true;
|
|
||||||
}
|
|
||||||
if (state.timer_ink_pen > 0.1 && WacomTablet::I.m_ink_pen)
|
|
||||||
{
|
|
||||||
WacomTablet::I.m_ink_pen = false;
|
|
||||||
App::I->redraw = true;
|
|
||||||
}
|
|
||||||
if (state.timer_ink_touch > 0.1 && WacomTablet::I.m_ink_touch)
|
|
||||||
{
|
|
||||||
WacomTablet::I.m_ink_touch = false;
|
|
||||||
App::I->redraw = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void win32_update_fps(int frames)
|
void win32_update_fps(int frames)
|
||||||
@@ -710,7 +669,7 @@ int main(int argc, char** argv)
|
|||||||
App::I->initLog();
|
App::I->initLog();
|
||||||
|
|
||||||
init_shcore_API();
|
init_shcore_API();
|
||||||
init_ink_API();
|
pp::platform::windows::initialize_stylus_input();
|
||||||
|
|
||||||
if(SetProcessDpiAwareness_fn)
|
if(SetProcessDpiAwareness_fn)
|
||||||
SetProcessDpiAwareness_fn(PROCESS_PER_MONITOR_DPI_AWARE);
|
SetProcessDpiAwareness_fn(PROCESS_PER_MONITOR_DPI_AWARE);
|
||||||
@@ -1064,8 +1023,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
|
|||||||
// }
|
// }
|
||||||
case WT_PACKET:
|
case WT_PACKET:
|
||||||
{
|
{
|
||||||
App::I->set_stylus();
|
pp::platform::windows::note_wintab_packet();
|
||||||
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);
|
||||||
});
|
});
|
||||||
@@ -1229,79 +1187,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
|
|||||||
}
|
}
|
||||||
case WM_POINTERUPDATE:
|
case WM_POINTERUPDATE:
|
||||||
{
|
{
|
||||||
POINTER_TOUCH_INFO touchInfo;
|
pp::platform::windows::handle_pointer_update_message(wp);
|
||||||
POINTER_PEN_INFO penInfo;
|
|
||||||
POINTER_INFO pointerInfo;
|
|
||||||
UINT32 pointerId = GET_POINTERID_WPARAM(wp);
|
|
||||||
POINTER_INPUT_TYPE pointerType = PT_POINTER;
|
|
||||||
|
|
||||||
if(!GetPointerInfo_fn)
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Retrieve common pointer information
|
|
||||||
if (!GetPointerInfo_fn(pointerId, &pointerInfo))
|
|
||||||
{
|
|
||||||
// failure, call GetLastError()
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// success, process pointerInfo
|
|
||||||
if (!GetPointerType_fn(pointerId, &pointerType))
|
|
||||||
{
|
|
||||||
// failure, call GetLastError()
|
|
||||||
// set PT_POINTER to fall to default case below
|
|
||||||
pointerType = PT_POINTER;
|
|
||||||
}
|
|
||||||
switch (pointerType)
|
|
||||||
{
|
|
||||||
case PT_TOUCH:
|
|
||||||
// Retrieve touch information
|
|
||||||
if (!GetPointerTouchInfo_fn(pointerId, &touchInfo))
|
|
||||||
{
|
|
||||||
// failure, call GetLastError()
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// success, process touchInfo
|
|
||||||
// mark as handled to skip call to DefWindowProc
|
|
||||||
//fHandled = TRUE;
|
|
||||||
state.timer_ink_touch = 0;
|
|
||||||
WacomTablet::I.m_ink_touch = true;
|
|
||||||
WacomTablet::I.m_pen_pres = 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PT_PEN:
|
|
||||||
// Retrieve pen information
|
|
||||||
if (!GetPointerPenInfo_fn(pointerId, &penInfo))
|
|
||||||
{
|
|
||||||
// failure, call GetLastError()
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// success, process penInfo
|
|
||||||
// mark as handled to skip call to DefWindowProc
|
|
||||||
//fHandled = TRUE;
|
|
||||||
//penInfo.pressure
|
|
||||||
state.timer_ink_pen = 0;
|
|
||||||
WacomTablet::I.m_ink_pen = true;
|
|
||||||
WacomTablet::I.m_pen_pres = (float)penInfo.pressure / 1024.f;
|
|
||||||
App::I->set_stylus();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (!GetPointerInfo_fn(pointerId, &pointerInfo))
|
|
||||||
{
|
|
||||||
// failure.
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// success, proceed with pointerInfo.
|
|
||||||
//fHandled = HandleGenericPointerInfo(&pointerInfo);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -439,32 +439,31 @@ void NodeCanvas::draw()
|
|||||||
apply_node_canvas_capability(pp::renderer::gl::depth_test_state(), false);
|
apply_node_canvas_capability(pp::renderer::gl::depth_test_state(), false);
|
||||||
|
|
||||||
const auto& b = m_canvas->m_current_stroke->m_brush;
|
const auto& b = m_canvas->m_current_stroke->m_brush;
|
||||||
|
pp::panopainter::execute_legacy_canvas_draw_layer_traversal(
|
||||||
for (size_t i = 0; i < m_canvas->m_layers.size(); i++)
|
m_canvas->m_layers.size(),
|
||||||
{
|
[&](size_t layer_index) {
|
||||||
auto layer_index = i;
|
return pp::app::plan_animation_onion_frame_range(
|
||||||
for (int plane_index = 0; plane_index < 6; plane_index++)
|
|
||||||
{
|
|
||||||
const auto onion_range_result = pp::app::plan_animation_onion_frame_range(
|
|
||||||
m_canvas->m_layers[layer_index]->frames_count(),
|
m_canvas->m_layers[layer_index]->frames_count(),
|
||||||
m_canvas->m_layers[layer_index]->m_frame_index,
|
m_canvas->m_layers[layer_index]->m_frame_index,
|
||||||
App::I->animation->get_onion_size());
|
App::I->animation->get_onion_size());
|
||||||
if (!onion_range_result) {
|
},
|
||||||
LOG("NodeCanvas onion frame range failed: %s", onion_range_result.status().message);
|
[&](size_t layer_index, int plane_index, int first_frame, int last_frame) {
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const auto onion_range = onion_range_result.value();
|
|
||||||
bool faces = false;
|
bool faces = false;
|
||||||
for (int frame = onion_range.first_frame; frame <= onion_range.last_frame; frame++)
|
for (int frame = first_frame; frame <= last_frame; ++frame)
|
||||||
faces |= m_canvas->m_layers[layer_index]->face(plane_index, frame);
|
faces |= m_canvas->m_layers[layer_index]->face(plane_index, frame);
|
||||||
if (!(m_canvas->m_show_tmp && m_canvas->m_current_layer_idx == layer_index) &&
|
|
||||||
(!m_canvas->m_layers[layer_index]->m_visible ||
|
|
||||||
m_canvas->m_layers[layer_index]->m_opacity == .0f || !faces))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
int z = (int)(m_canvas->m_layers.size() - i);
|
if (m_canvas->m_show_tmp && m_canvas->m_current_layer_idx == layer_index)
|
||||||
auto plane_mvp_z = proj * camera *
|
return true;
|
||||||
glm::scale(glm::vec3(z + 1)) *
|
|
||||||
|
return m_canvas->m_layers[layer_index]->m_visible &&
|
||||||
|
m_canvas->m_layers[layer_index]->m_opacity != .0f &&
|
||||||
|
faces;
|
||||||
|
},
|
||||||
|
[&](const pp::panopainter::LegacyCanvasDrawLayerVisit& visit, const auto& onion_range) {
|
||||||
|
const auto layer_index = visit.layer_index;
|
||||||
|
const auto plane_index = visit.plane_index;
|
||||||
|
const auto plane_mvp_z = proj * camera *
|
||||||
|
glm::scale(glm::vec3(visit.z + 1)) *
|
||||||
glm::eulerAngleYXZ(yaw, pitch, roll) *
|
glm::eulerAngleYXZ(yaw, pitch, roll) *
|
||||||
m_canvas->m_plane_transform[plane_index] *
|
m_canvas->m_plane_transform[plane_index] *
|
||||||
glm::translate(glm::vec3(0, 0, -1));
|
glm::translate(glm::vec3(0, 0, -1));
|
||||||
@@ -480,8 +479,8 @@ void NodeCanvas::draw()
|
|||||||
m_canvas->m_current_stroke && m_canvas->m_current_mode == kCanvasMode::Erase && m_canvas->m_show_tmp && m_canvas->m_current_layer_idx == layer_index,
|
m_canvas->m_current_stroke && m_canvas->m_current_mode == kCanvasMode::Erase && m_canvas->m_show_tmp && m_canvas->m_current_layer_idx == layer_index,
|
||||||
m_canvas->m_current_stroke && m_canvas->m_show_tmp && m_canvas->m_current_layer_idx == layer_index,
|
m_canvas->m_current_stroke && m_canvas->m_show_tmp && m_canvas->m_current_layer_idx == layer_index,
|
||||||
use_blend,
|
use_blend,
|
||||||
onion_range.first_frame,
|
visit.first_frame,
|
||||||
onion_range.last_frame,
|
visit.last_frame,
|
||||||
[&](int frame) {
|
[&](int frame) {
|
||||||
return pp::app::animation_onion_frame_alpha(onion_range, frame);
|
return pp::app::animation_onion_frame_alpha(onion_range, frame);
|
||||||
},
|
},
|
||||||
@@ -649,9 +648,10 @@ void NodeCanvas::draw()
|
|||||||
#endif
|
#endif
|
||||||
.draw_frame = draw_layer_frame,
|
.draw_frame = draw_layer_frame,
|
||||||
});
|
});
|
||||||
|
},
|
||||||
}
|
[&](const char* message) {
|
||||||
}
|
LOG("NodeCanvas onion frame range failed: %s", message);
|
||||||
|
});
|
||||||
if (use_blend)
|
if (use_blend)
|
||||||
{
|
{
|
||||||
m_cache_rtt.unbindFramebuffer();
|
m_cache_rtt.unbindFramebuffer();
|
||||||
|
|||||||
129
src/platform_windows/windows_stylus_input.cpp
Normal file
129
src/platform_windows/windows_stylus_input.cpp
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
|
||||||
|
#include "platform_windows/windows_stylus_input.h"
|
||||||
|
|
||||||
|
#include "app.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "wacom.h"
|
||||||
|
|
||||||
|
namespace pp::platform::windows {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
struct StylusInputState final
|
||||||
|
{
|
||||||
|
float timer_stylus = 0.0f;
|
||||||
|
float timer_ink_touch = 0.0f;
|
||||||
|
float timer_ink_pen = 0.0f;
|
||||||
|
|
||||||
|
BOOL (*get_pointer_info)(UINT32, POINTER_INFO*) = nullptr;
|
||||||
|
BOOL (*get_pointer_type)(UINT32, POINTER_INPUT_TYPE*) = nullptr;
|
||||||
|
BOOL (*get_pointer_touch_info)(UINT32, POINTER_TOUCH_INFO*) = nullptr;
|
||||||
|
BOOL (*get_pointer_pen_info)(UINT32, POINTER_PEN_INFO*) = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
StylusInputState& stylus_input_state()
|
||||||
|
{
|
||||||
|
static StylusInputState state;
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void initialize_stylus_input()
|
||||||
|
{
|
||||||
|
auto& state = stylus_input_state();
|
||||||
|
HMODULE dll = LoadLibrary(L"User32.dll");
|
||||||
|
if (!dll)
|
||||||
|
{
|
||||||
|
LOG("cannot load User32.dll");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG("loaded User32.dll");
|
||||||
|
state.get_pointer_info =
|
||||||
|
reinterpret_cast<decltype(state.get_pointer_info)>(GetProcAddress(dll, "GetPointerInfo"));
|
||||||
|
state.get_pointer_type =
|
||||||
|
reinterpret_cast<decltype(state.get_pointer_type)>(GetProcAddress(dll, "GetPointerType"));
|
||||||
|
state.get_pointer_touch_info =
|
||||||
|
reinterpret_cast<decltype(state.get_pointer_touch_info)>(GetProcAddress(dll, "GetPointerTouchInfo"));
|
||||||
|
state.get_pointer_pen_info =
|
||||||
|
reinterpret_cast<decltype(state.get_pointer_pen_info)>(GetProcAddress(dll, "GetPointerPenInfo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_stylus_state(float dt)
|
||||||
|
{
|
||||||
|
auto& state = stylus_input_state();
|
||||||
|
state.timer_stylus += dt;
|
||||||
|
state.timer_ink_touch += dt;
|
||||||
|
state.timer_ink_pen += dt;
|
||||||
|
|
||||||
|
if (state.timer_stylus > 0.1f && (WacomTablet::I.m_stylus || WacomTablet::I.m_eraser))
|
||||||
|
{
|
||||||
|
WacomTablet::I.m_stylus = false;
|
||||||
|
WacomTablet::I.m_eraser = false;
|
||||||
|
App::I->redraw = true;
|
||||||
|
}
|
||||||
|
if (state.timer_ink_pen > 0.1f && WacomTablet::I.m_ink_pen)
|
||||||
|
{
|
||||||
|
WacomTablet::I.m_ink_pen = false;
|
||||||
|
App::I->redraw = true;
|
||||||
|
}
|
||||||
|
if (state.timer_ink_touch > 0.1f && WacomTablet::I.m_ink_touch)
|
||||||
|
{
|
||||||
|
WacomTablet::I.m_ink_touch = false;
|
||||||
|
App::I->redraw = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void note_wintab_packet()
|
||||||
|
{
|
||||||
|
auto& state = stylus_input_state();
|
||||||
|
App::I->set_stylus();
|
||||||
|
state.timer_stylus = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_pointer_update_message(WPARAM wp)
|
||||||
|
{
|
||||||
|
auto& state = stylus_input_state();
|
||||||
|
if (!state.get_pointer_info)
|
||||||
|
return;
|
||||||
|
|
||||||
|
POINTER_TOUCH_INFO touch_info {};
|
||||||
|
POINTER_PEN_INFO pen_info {};
|
||||||
|
POINTER_INFO pointer_info {};
|
||||||
|
const UINT32 pointer_id = GET_POINTERID_WPARAM(wp);
|
||||||
|
POINTER_INPUT_TYPE pointer_type = PT_POINTER;
|
||||||
|
|
||||||
|
if (!state.get_pointer_info(pointer_id, &pointer_info))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!state.get_pointer_type(pointer_id, &pointer_type))
|
||||||
|
pointer_type = PT_POINTER;
|
||||||
|
|
||||||
|
switch (pointer_type)
|
||||||
|
{
|
||||||
|
case PT_TOUCH:
|
||||||
|
if (!state.get_pointer_touch_info(pointer_id, &touch_info))
|
||||||
|
return;
|
||||||
|
|
||||||
|
state.timer_ink_touch = 0.0f;
|
||||||
|
WacomTablet::I.m_ink_touch = true;
|
||||||
|
WacomTablet::I.m_pen_pres = 1.0f;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case PT_PEN:
|
||||||
|
if (!state.get_pointer_pen_info(pointer_id, &pen_info))
|
||||||
|
return;
|
||||||
|
|
||||||
|
state.timer_ink_pen = 0.0f;
|
||||||
|
WacomTablet::I.m_ink_pen = true;
|
||||||
|
WacomTablet::I.m_pen_pres = static_cast<float>(pen_info.pressure) / 1024.0f;
|
||||||
|
App::I->set_stylus();
|
||||||
|
return;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
12
src/platform_windows/windows_stylus_input.h
Normal file
12
src/platform_windows/windows_stylus_input.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
namespace pp::platform::windows {
|
||||||
|
|
||||||
|
void initialize_stylus_input();
|
||||||
|
void update_stylus_state(float dt);
|
||||||
|
void note_wintab_packet();
|
||||||
|
void handle_pointer_update_message(WPARAM wp);
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user