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_events.cpp
|
||||
src/app_layout.cpp
|
||||
src/app_layout_about_layer_menu.cpp
|
||||
src/app_layout_file_menu.cpp
|
||||
src/app_layout_tools_menu.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_splash.cpp
|
||||
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
|
||||
|
||||
@@ -80,13 +80,13 @@ What is still carrying too much live ownership:
|
||||
Current hotspot files:
|
||||
|
||||
- `src/canvas.cpp`: 2645 lines
|
||||
- `src/app_layout.cpp`: 1360 lines
|
||||
- `src/app_layout.cpp`: 1249 lines
|
||||
- `src/canvas_modes.cpp`: 1798 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_stroke_preview.cpp`: 933 lines
|
||||
- `src/node_canvas.cpp`: 888 lines
|
||||
- `src/node_canvas.cpp`: 968 lines
|
||||
- `src/app.cpp`: 950 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
|
||||
retained helper family, while post-draw callback assembly and the remaining
|
||||
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
|
||||
rather than thin composition/binding surfaces, even though tools-menu binding
|
||||
plus nested panels/options submenu wiring now live in
|
||||
`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
|
||||
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
|
||||
global singleton reach, raw observer pointers, retained static worker
|
||||
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
|
||||
workers, and the splash-screen dialog loop, HWND ownership, and bitmap setup
|
||||
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
|
||||
the retained recording bridge, `App::update_rec_frames()` now delegates
|
||||
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
|
||||
`execute_legacy_canvas_draw_merge_layer_path(...)`, but the node still owns
|
||||
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:
|
||||
- `src/node_stroke_preview.cpp`
|
||||
@@ -271,7 +275,7 @@ targets look like helpers under one old monolith.
|
||||
Status: In Progress
|
||||
|
||||
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.
|
||||
|
||||
Current slice:
|
||||
@@ -283,6 +287,10 @@ Current slice:
|
||||
`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
|
||||
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:
|
||||
- `src/app_layout.cpp`
|
||||
@@ -405,6 +413,10 @@ Current slice:
|
||||
pair during initialization and context recreation
|
||||
- `main.cpp` main-thread queued task state now sits behind a narrow retained
|
||||
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
|
||||
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
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
|
||||
namespace pp::panopainter {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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()
|
||||
{
|
||||
if (auto* menu_file = layout[main_id]->find<NodeButtonCustom>("menu-about"))
|
||||
{
|
||||
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);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
pp::panopainter::bind_legacy_about_menu(*this);
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
if (auto* menu_file = layout[main_id]->find<NodeButtonCustom>("menu-layers"))
|
||||
{
|
||||
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());
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
pp::panopainter::bind_legacy_layer_menu(*this);
|
||||
}
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
struct LegacyCanvasDrawLayerVisit {
|
||||
size_t layer_index = 0;
|
||||
int plane_index = 0;
|
||||
int z = 0;
|
||||
int first_frame = 0;
|
||||
int last_frame = 0;
|
||||
};
|
||||
|
||||
struct LegacyCanvasDrawMergeTemporaryCompositeExecution {
|
||||
std::function<void()> setup;
|
||||
std::function<void()> bind_samplers;
|
||||
@@ -671,6 +679,39 @@ inline void execute_legacy_canvas_draw_merge_layer_path(
|
||||
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(
|
||||
const LegacyCanvasDrawMergeTemporaryCompositeExecution& execution)
|
||||
{
|
||||
|
||||
124
src/main.cpp
124
src/main.cpp
@@ -13,6 +13,7 @@
|
||||
#include "renderer_gl/opengl_capabilities.h"
|
||||
#include "platform_windows/windows_platform_services.h"
|
||||
#include "platform_windows/windows_splash.h"
|
||||
#include "platform_windows/windows_stylus_input.h"
|
||||
#include "../resource.h"
|
||||
|
||||
#include <shellscalingapi.h>
|
||||
@@ -55,9 +56,6 @@ struct RetainedState
|
||||
std::map<kKey, int> vkey_map;
|
||||
wchar_t window_title[512]{};
|
||||
std::jthread hmd_renderer;
|
||||
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;
|
||||
@@ -176,25 +174,6 @@ void init_shcore_API()
|
||||
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.
|
||||
std::string GetLastErrorAsString()
|
||||
{
|
||||
@@ -245,27 +224,7 @@ void async_unlock()
|
||||
|
||||
void win32_update_stylus(float dt)
|
||||
{
|
||||
auto& state = retained_state();
|
||||
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;
|
||||
}
|
||||
pp::platform::windows::update_stylus_state(dt);
|
||||
}
|
||||
|
||||
void win32_update_fps(int frames)
|
||||
@@ -710,7 +669,7 @@ int main(int argc, char** argv)
|
||||
App::I->initLog();
|
||||
|
||||
init_shcore_API();
|
||||
init_ink_API();
|
||||
pp::platform::windows::initialize_stylus_input();
|
||||
|
||||
if(SetProcessDpiAwareness_fn)
|
||||
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:
|
||||
{
|
||||
App::I->set_stylus();
|
||||
state.timer_stylus = 0;
|
||||
pp::platform::windows::note_wintab_packet();
|
||||
App::I->ui_task_async([=] {
|
||||
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:
|
||||
{
|
||||
POINTER_TOUCH_INFO touchInfo;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
pp::platform::windows::handle_pointer_update_message(wp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -439,34 +439,33 @@ void NodeCanvas::draw()
|
||||
apply_node_canvas_capability(pp::renderer::gl::depth_test_state(), false);
|
||||
|
||||
const auto& b = m_canvas->m_current_stroke->m_brush;
|
||||
|
||||
for (size_t i = 0; i < m_canvas->m_layers.size(); i++)
|
||||
{
|
||||
auto layer_index = i;
|
||||
for (int plane_index = 0; plane_index < 6; plane_index++)
|
||||
{
|
||||
const auto onion_range_result = pp::app::plan_animation_onion_frame_range(
|
||||
pp::panopainter::execute_legacy_canvas_draw_layer_traversal(
|
||||
m_canvas->m_layers.size(),
|
||||
[&](size_t layer_index) {
|
||||
return pp::app::plan_animation_onion_frame_range(
|
||||
m_canvas->m_layers[layer_index]->frames_count(),
|
||||
m_canvas->m_layers[layer_index]->m_frame_index,
|
||||
App::I->animation->get_onion_size());
|
||||
if (!onion_range_result) {
|
||||
LOG("NodeCanvas onion frame range failed: %s", onion_range_result.status().message);
|
||||
continue;
|
||||
}
|
||||
const auto onion_range = onion_range_result.value();
|
||||
},
|
||||
[&](size_t layer_index, int plane_index, int first_frame, int last_frame) {
|
||||
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);
|
||||
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);
|
||||
auto plane_mvp_z = proj * camera *
|
||||
glm::scale(glm::vec3(z + 1)) *
|
||||
if (m_canvas->m_show_tmp && m_canvas->m_current_layer_idx == layer_index)
|
||||
return true;
|
||||
|
||||
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) *
|
||||
m_canvas->m_plane_transform[plane_index] *
|
||||
m_canvas->m_plane_transform[plane_index] *
|
||||
glm::translate(glm::vec3(0, 0, -1));
|
||||
|
||||
const auto draw_layer_frame = pp::panopainter::make_legacy_canvas_draw_merge_layer_frame_draw(
|
||||
@@ -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_show_tmp && m_canvas->m_current_layer_idx == layer_index,
|
||||
use_blend,
|
||||
onion_range.first_frame,
|
||||
onion_range.last_frame,
|
||||
visit.first_frame,
|
||||
visit.last_frame,
|
||||
[&](int frame) {
|
||||
return pp::app::animation_onion_frame_alpha(onion_range, frame);
|
||||
},
|
||||
@@ -649,9 +648,10 @@ void NodeCanvas::draw()
|
||||
#endif
|
||||
.draw_frame = draw_layer_frame,
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
[&](const char* message) {
|
||||
LOG("NodeCanvas onion frame range failed: %s", message);
|
||||
});
|
||||
if (use_blend)
|
||||
{
|
||||
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