Extract sidebar, lifecycle shell, and canvas unmerged draw
This commit is contained in:
@@ -97,6 +97,7 @@ set(PP_PANOPAINTER_APP_SOURCES
|
|||||||
src/app_dialogs_info_openers.cpp
|
src/app_dialogs_info_openers.cpp
|
||||||
src/app_events.cpp
|
src/app_events.cpp
|
||||||
src/app_layout.cpp
|
src/app_layout.cpp
|
||||||
|
src/app_layout_sidebar.cpp
|
||||||
src/app_layout_about_layer_menu.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
|
||||||
@@ -166,6 +167,8 @@ set(PP_PANOPAINTER_UI_SOURCES
|
|||||||
set(PP_WINDOWS_PLATFORM_SOURCES
|
set(PP_WINDOWS_PLATFORM_SOURCES
|
||||||
src/main.cpp
|
src/main.cpp
|
||||||
src/platform_windows/windows_bootstrap_helpers.cpp
|
src/platform_windows/windows_bootstrap_helpers.cpp
|
||||||
|
src/platform_windows/windows_lifecycle_shell.cpp
|
||||||
|
src/platform_windows/windows_lifecycle_shell.h
|
||||||
src/platform_windows/windows_platform_services.cpp
|
src/platform_windows/windows_platform_services.cpp
|
||||||
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
|
||||||
|
|||||||
@@ -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`: 1249 lines
|
- `src/app_layout.cpp`: 785 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`: 909 lines
|
- `src/main.cpp`: 882 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`: 905 lines
|
- `src/node_canvas.cpp`: 910 lines
|
||||||
- `src/app.cpp`: 502 lines
|
- `src/app.cpp`: 502 lines
|
||||||
- `src/app_dialogs.cpp`: 142 lines
|
- `src/app_dialogs.cpp`: 142 lines
|
||||||
|
|
||||||
@@ -138,7 +138,9 @@ Current architecture mismatches that must be treated as real blockers:
|
|||||||
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, while about-menu and layer-menu wiring now also live in
|
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
|
`src/app_layout_about_layer_menu.cpp` and `App::init_menu_about()` plus
|
||||||
`App::init_menu_layer()` are now thin call-throughs, while the informational
|
`App::init_menu_layer()` are now thin call-throughs, while sidebar panel
|
||||||
|
binding and popup wiring now also live in `src/app_layout_sidebar.cpp` and
|
||||||
|
`App::init_sidebar()` is now a thin call-through, while the informational
|
||||||
overlay opener family now also lives in `src/app_dialogs_info_openers.cpp`
|
overlay opener family now also lives in `src/app_dialogs_info_openers.cpp`
|
||||||
and the corresponding `App::dialog_*` entrypoints are thinner, while the
|
and the corresponding `App::dialog_*` entrypoints are thinner, while the
|
||||||
export/video/PPBR dialog family now also lives in
|
export/video/PPBR dialog family now also lives in
|
||||||
@@ -177,7 +179,10 @@ Current architecture mismatches that must be treated as real blockers:
|
|||||||
`src/main.cpp`, while RenderDoc startup/frame capture, SHCore DPI bootstrap,
|
`src/main.cpp`, while RenderDoc startup/frame capture, SHCore DPI bootstrap,
|
||||||
Win32 error-string conversion, and the GL debug pre/post callbacks now also
|
Win32 error-string conversion, and the GL debug pre/post callbacks now also
|
||||||
live in `src/platform_windows/windows_bootstrap_helpers.cpp` instead of
|
live in `src/platform_windows/windows_bootstrap_helpers.cpp` instead of
|
||||||
`src/main.cpp`,
|
`src/main.cpp`, while Win32 lifecycle running-state, close/shutdown
|
||||||
|
sequencing, FPS title update/wakeup posting, stylus frame update, window
|
||||||
|
preference save, and VR lifecycle wrappers now also live in
|
||||||
|
`src/platform_windows/windows_lifecycle_shell.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
|
||||||
|
|||||||
@@ -210,6 +210,11 @@ Current slice:
|
|||||||
`execute_node_canvas_draw_merge_tail(...)`, which trims another live tail
|
`execute_node_canvas_draw_merge_tail(...)`, which trims another live tail
|
||||||
block from `NodeCanvas::draw()` even though the broader outer draw shell is
|
block from `NodeCanvas::draw()` even though the broader outer draw shell is
|
||||||
still inline.
|
still inline.
|
||||||
|
- `NodeCanvas` non-`draw_merged` cache/background/layer-traversal/cache-
|
||||||
|
composite shell now also routes through
|
||||||
|
`execute_legacy_canvas_draw_unmerged_shell(...)`, which removes another
|
||||||
|
coherent orchestration block from `NodeCanvas::draw()` even though the
|
||||||
|
broader node draw loop still lives in `src/node_canvas.cpp`.
|
||||||
|
|
||||||
Write scope:
|
Write scope:
|
||||||
- `src/node_stroke_preview.cpp`
|
- `src/node_stroke_preview.cpp`
|
||||||
@@ -304,6 +309,10 @@ Current slice:
|
|||||||
`src/app_layout_about_layer_menu.cpp`, and `App::init_menu_about()` plus
|
`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
|
`App::init_menu_layer()` are now thin call-throughs, but edit/sidebar and
|
||||||
broader layout composition are still inline in `src/app_layout.cpp`.
|
broader layout composition are still inline in `src/app_layout.cpp`.
|
||||||
|
- Sidebar panel binding plus popup wiring now also live in
|
||||||
|
`src/app_layout_sidebar.cpp`, and `App::init_sidebar()` is now a thin
|
||||||
|
call-through, but edit-menu wiring and broader layout composition are still
|
||||||
|
inline in `src/app_layout.cpp`.
|
||||||
|
|
||||||
Write scope:
|
Write scope:
|
||||||
- `src/app_layout.cpp`
|
- `src/app_layout.cpp`
|
||||||
@@ -460,6 +469,10 @@ Current slice:
|
|||||||
conversion, `UnadjustWindowRectEx`, and GL debug pre/post callbacks now also
|
conversion, `UnadjustWindowRectEx`, and GL debug pre/post callbacks now also
|
||||||
live in `src/platform_windows/windows_bootstrap_helpers.cpp` instead of
|
live in `src/platform_windows/windows_bootstrap_helpers.cpp` instead of
|
||||||
`src/main.cpp`
|
`src/main.cpp`
|
||||||
|
- Win32 lifecycle running-state, close/shutdown handling, FPS title update and
|
||||||
|
wakeup posting, stylus frame update, window preference save, and VR
|
||||||
|
lifecycle wrappers now also live in
|
||||||
|
`src/platform_windows/windows_lifecycle_shell.cpp` instead of `src/main.cpp`
|
||||||
- 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
|
||||||
|
|||||||
@@ -74,27 +74,6 @@ std::shared_ptr<NodePopupMenu> add_menu_popup(
|
|||||||
return popup.value();
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename PopupOverlay, typename TickOverlay>
|
|
||||||
void close_legacy_overlay_handles_if_open(
|
|
||||||
Node& anchor,
|
|
||||||
const PopupOverlay& popup_overlay,
|
|
||||||
const TickOverlay& tick_overlay) noexcept
|
|
||||||
{
|
|
||||||
if (popup_overlay) {
|
|
||||||
close_legacy_overlay_handle_ignoring_status(anchor, popup_overlay.value());
|
|
||||||
}
|
|
||||||
if (tick_overlay) {
|
|
||||||
close_legacy_overlay_handle_ignoring_status(anchor, tick_overlay.value());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[[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;
|
||||||
@@ -135,16 +114,6 @@ void execute_document_layer_merge_plan(App& app, const pp::app::DocumentLayerMer
|
|||||||
LOG("Layer merge failed: %s", status.message);
|
LOG("Layer merge failed: %s", status.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void execute_document_layer_operation_plan(
|
|
||||||
App& app,
|
|
||||||
const pp::app::DocumentLayerOperationPlan& plan,
|
|
||||||
const std::shared_ptr<class Layer>& pending_layer = nullptr)
|
|
||||||
{
|
|
||||||
const auto status = pp::panopainter::execute_legacy_document_layer_operation_plan(app, plan, pending_layer);
|
|
||||||
if (!status.ok())
|
|
||||||
LOG("Layer operation failed: %s", status.message);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void App::title_update()
|
void App::title_update()
|
||||||
@@ -263,381 +232,6 @@ void App::init_toolbar_main()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> std::shared_ptr<T> create_panel(LayoutManager& manager)
|
|
||||||
{
|
|
||||||
std::shared_ptr<T> ret;
|
|
||||||
ret = std::make_shared<T>();
|
|
||||||
ret->set_manager(&manager);
|
|
||||||
ret->init();
|
|
||||||
ret->create();
|
|
||||||
ret->loaded();
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void App::init_sidebar()
|
|
||||||
{
|
|
||||||
sidebar = layout[main_id]->find<NodeBorder>("sidebar");
|
|
||||||
canvas = layout[main_id]->find<NodeCanvas>("paint-canvas");
|
|
||||||
quick = layout[main_id]->find<NodePanelQuick>("panel-quick");
|
|
||||||
floatings_container = layout[main_id]->find<Node>("floatings");
|
|
||||||
|
|
||||||
//brushes = layout[main_id]->find<NodePanelBrush>("panel-brush");
|
|
||||||
//layers = layout[main_id]->find<NodePanelLayer>("panel-layer");
|
|
||||||
//color = layout[main_id]->find<NodePanelColor>("panel-color");
|
|
||||||
//stroke = layout[main_id]->find<NodePanelStroke>("panel-stroke");
|
|
||||||
|
|
||||||
//brushes = find_or_create_panel<NodePanelBrush>(panels);
|
|
||||||
layers = create_panel<NodePanelLayer>(layout);
|
|
||||||
color = create_panel<NodePanelColor>(layout);
|
|
||||||
stroke = create_panel<NodePanelStroke>(layout);
|
|
||||||
grid = create_panel<NodePanelGrid>(layout);
|
|
||||||
presets = create_panel<NodePanelBrushPreset>(layout);
|
|
||||||
animation = create_panel<NodePanelAnimation>(layout);
|
|
||||||
//presets = find_or_create_panel<NodePanelBrushPreset>(panels);
|
|
||||||
|
|
||||||
canvas->m_canvas->on_mode_changed = [this](kCanvasMode prev, kCanvasMode mode) {
|
|
||||||
quick_mode_state[prev] = quick->get_state();
|
|
||||||
if (quick_mode_state.find(mode) != quick_mode_state.end())
|
|
||||||
quick->set_state(quick_mode_state[mode], true);
|
|
||||||
else
|
|
||||||
quick->reset_state(true);
|
|
||||||
brush_update(true, true);
|
|
||||||
};
|
|
||||||
color->on_color_changed = [this](Node* target, glm::vec4 color) {
|
|
||||||
apply_brush_color_plan(*this, color, true, false);
|
|
||||||
};
|
|
||||||
|
|
||||||
stroke->on_brush_changed = [this](Node* target, const std::string& path, const std::string& thumb) {
|
|
||||||
apply_brush_texture_plan(*this, pp::app::BrushUiTextureSlot::tip, path, thumb);
|
|
||||||
};
|
|
||||||
stroke->on_pattern_changed = [this](Node*target, const std::string& path, const std::string& thumb) {
|
|
||||||
apply_brush_texture_plan(*this, pp::app::BrushUiTextureSlot::pattern, path, thumb);
|
|
||||||
};
|
|
||||||
stroke->on_dual_changed = [this](Node*target, const std::string& path, const std::string& thumb) {
|
|
||||||
apply_brush_texture_plan(*this, pp::app::BrushUiTextureSlot::dual, path, thumb);
|
|
||||||
};
|
|
||||||
stroke->on_stroke_change = [this](Node*) {
|
|
||||||
const auto status = pp::panopainter::execute_legacy_brush_stroke_changed_plan(*this);
|
|
||||||
if (!status.ok())
|
|
||||||
LOG("Brush stroke settings action failed: %s", status.message);
|
|
||||||
};
|
|
||||||
|
|
||||||
quick->on_color_change = [this](Node*, glm::vec3 c) {
|
|
||||||
apply_brush_color_plan(*this, glm::vec4(c, 1.f), false, true);
|
|
||||||
};
|
|
||||||
quick->on_flow_change = [this](Node*, float value) {
|
|
||||||
stroke->set_flow(value, true, true);
|
|
||||||
};
|
|
||||||
quick->on_size_change = [this](Node*, float value) {
|
|
||||||
stroke->set_size(value, true, true);
|
|
||||||
};
|
|
||||||
quick->on_brush_change = [this](Node*, std::shared_ptr<Brush> b) {
|
|
||||||
apply_brush_preset_plan(*this, b);
|
|
||||||
};
|
|
||||||
|
|
||||||
layers->on_layer_add = [this](Node*, std::shared_ptr<class Layer> layer, int index) {
|
|
||||||
const auto plan = pp::app::plan_document_layer_add(
|
|
||||||
static_cast<int>(Canvas::I->m_layers.size()),
|
|
||||||
index,
|
|
||||||
layers->m_layers.back()->m_label_text);
|
|
||||||
if (!plan)
|
|
||||||
return;
|
|
||||||
execute_document_layer_operation_plan(*this, plan.value(), layer);
|
|
||||||
};
|
|
||||||
|
|
||||||
layers->on_layer_duplicate = [this](Node*, int source_index) {
|
|
||||||
const auto plan = pp::app::plan_document_layer_duplicate(
|
|
||||||
static_cast<int>(Canvas::I->m_layers.size()),
|
|
||||||
source_index);
|
|
||||||
if (!plan)
|
|
||||||
return;
|
|
||||||
execute_document_layer_operation_plan(*this, plan.value());
|
|
||||||
};
|
|
||||||
|
|
||||||
layers->on_layer_change = [this](Node*, int, int new_idx) {
|
|
||||||
const auto plan = pp::app::plan_document_layer_select(
|
|
||||||
static_cast<int>(canvas->m_canvas->m_layers.size()),
|
|
||||||
new_idx);
|
|
||||||
if (!plan)
|
|
||||||
return;
|
|
||||||
execute_document_layer_operation_plan(*this, plan.value());
|
|
||||||
};
|
|
||||||
|
|
||||||
layers->on_layer_order = [this](Node*, int old_idx, int new_idx) {
|
|
||||||
const auto plan = pp::app::plan_document_layer_reorder(
|
|
||||||
static_cast<int>(canvas->m_canvas->m_layers.size()),
|
|
||||||
old_idx,
|
|
||||||
new_idx);
|
|
||||||
if (!plan)
|
|
||||||
return;
|
|
||||||
execute_document_layer_operation_plan(*this, plan.value());
|
|
||||||
};
|
|
||||||
|
|
||||||
layers->on_layer_delete = [this](Node*, int idx) {
|
|
||||||
const auto plan = pp::app::plan_document_layer_remove(
|
|
||||||
static_cast<int>(canvas->m_canvas->m_layers.size()),
|
|
||||||
idx);
|
|
||||||
if (!plan)
|
|
||||||
return;
|
|
||||||
execute_document_layer_operation_plan(*this, plan.value());
|
|
||||||
};
|
|
||||||
|
|
||||||
layers->on_layer_opacity_changed = [this](Node*, int idx, float value) {
|
|
||||||
const auto plan = pp::app::plan_document_layer_opacity(
|
|
||||||
static_cast<int>(canvas->m_canvas->m_layers.size()),
|
|
||||||
idx,
|
|
||||||
value);
|
|
||||||
if (!plan)
|
|
||||||
return;
|
|
||||||
execute_document_layer_operation_plan(*this, plan.value());
|
|
||||||
};
|
|
||||||
|
|
||||||
layers->on_layer_visibility_changed = [this](Node*, int idx, bool visible) {
|
|
||||||
const auto plan = pp::app::plan_document_layer_visibility(
|
|
||||||
static_cast<int>(canvas->m_canvas->m_layers.size()),
|
|
||||||
idx,
|
|
||||||
visible);
|
|
||||||
if (!plan)
|
|
||||||
return;
|
|
||||||
execute_document_layer_operation_plan(*this, plan.value());
|
|
||||||
};
|
|
||||||
|
|
||||||
layers->on_layer_alpha_lock_changed = [this](Node*, int idx, bool locked) {
|
|
||||||
const auto plan = pp::app::plan_document_layer_alpha_lock(
|
|
||||||
static_cast<int>(canvas->m_canvas->m_layers.size()),
|
|
||||||
idx,
|
|
||||||
locked);
|
|
||||||
if (!plan)
|
|
||||||
return;
|
|
||||||
execute_document_layer_operation_plan(*this, plan.value());
|
|
||||||
};
|
|
||||||
|
|
||||||
layers->on_layer_blend_mode_changed = [this](Node*, int idx, int mode) {
|
|
||||||
const auto plan = pp::app::plan_document_layer_blend_mode(
|
|
||||||
static_cast<int>(canvas->m_canvas->m_layers.size()),
|
|
||||||
idx,
|
|
||||||
mode);
|
|
||||||
if (!plan)
|
|
||||||
return;
|
|
||||||
execute_document_layer_operation_plan(*this, plan.value());
|
|
||||||
};
|
|
||||||
|
|
||||||
layers->on_layer_highlight_changed = [this](Node*, int idx, bool highlight) {
|
|
||||||
const auto plan = pp::app::plan_document_layer_highlight(
|
|
||||||
static_cast<int>(canvas->m_canvas->m_layers.size()),
|
|
||||||
idx,
|
|
||||||
highlight);
|
|
||||||
if (!plan)
|
|
||||||
return;
|
|
||||||
execute_document_layer_operation_plan(*this, plan.value());
|
|
||||||
};
|
|
||||||
if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-stroke"))
|
|
||||||
{
|
|
||||||
button->on_click = [this, button](Node*) {
|
|
||||||
auto* popup_root = layout[main_id];
|
|
||||||
if (!popup_root) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto screen = popup_root->m_size;
|
|
||||||
glm::vec2 pos = button->m_pos + glm::vec2(button->m_size.x * 0.5f, button->m_size.y);
|
|
||||||
if (stroke->m_parent)
|
|
||||||
{
|
|
||||||
if (auto fp = dynamic_cast<NodePanelFloating*>(stroke->m_parent->m_parent))
|
|
||||||
{
|
|
||||||
pp::panopainter::detach_legacy_node_from_parent(*stroke);
|
|
||||||
pp::panopainter::close_legacy_dialog_node(*fp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const auto popup_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_root, stroke);
|
|
||||||
if (!popup_overlay) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
stroke->SetSize(350, glm::max(100.f, screen.y - pos.y - 50.f));
|
|
||||||
stroke->find("title")->SetVisibility(true);
|
|
||||||
auto tick = pp::panopainter::make_legacy_overlay_node_for_anchor<NodeImage>(*popup_root);
|
|
||||||
tick->SetPositioning(YGPositionTypeAbsolute);
|
|
||||||
tick->SetSize(32, 16);
|
|
||||||
tick->SetPosition(pos.x - 16, pos.y);
|
|
||||||
tick->set_image("data/ui/popup-tick-up.png");
|
|
||||||
auto tick_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_root, tick);
|
|
||||||
if (!popup_overlay || !tick_overlay)
|
|
||||||
{
|
|
||||||
close_legacy_overlay_handles_if_open(*popup_root, popup_overlay, tick_overlay);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const auto popup_handle = popup_overlay.value();
|
|
||||||
const auto tick_handle = tick_overlay.value();
|
|
||||||
popup_root->update();
|
|
||||||
|
|
||||||
stroke->SetPosition(pos.x - stroke->m_size.x / 2.f, pos.y + 16);
|
|
||||||
stroke->SetPositioning(YGPositionTypeAbsolute);
|
|
||||||
pp::panopainter::activate_legacy_popup_overlay(*stroke);
|
|
||||||
auto scroll = stroke->find<NodeScroll>("scroller");
|
|
||||||
//scroll->SetHeight(glm::max(100.f, screen.y - pos.y - 200.f));
|
|
||||||
stroke->m_popup_overlay_handle = popup_handle;
|
|
||||||
stroke->m_tick_overlay_handle = tick_handle;
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
|
||||||
//if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-brush"))
|
|
||||||
//{
|
|
||||||
// button->on_click = [this, button](Node*) {
|
|
||||||
// panels->get_child_index(brushes.get()) == -1 ? panels->add_child(brushes) : panels->remove_child(brushes.get());
|
|
||||||
// panels->fix_scroll();
|
|
||||||
// button->set_color(panels->get_child_index(brushes.get()) == -1 ? color_button_normal : color_button_hlight);
|
|
||||||
// };
|
|
||||||
//}
|
|
||||||
//if (auto* button = layout[main_id]->find<NodeButton>("btn-brush-preset"))
|
|
||||||
//{
|
|
||||||
// button->on_click = [this, button](Node*) {
|
|
||||||
// panels->get_child_index(presets.get()) == -1 ? panels->add_child(presets) : panels->remove_child(presets.get());
|
|
||||||
// panels->fix_scroll();
|
|
||||||
// button->set_color(panels->get_child_index(presets.get()) == -1 ? color_button_normal : color_button_hlight);
|
|
||||||
// };
|
|
||||||
//}
|
|
||||||
if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-color"))
|
|
||||||
{
|
|
||||||
button->on_click = [this, button](Node*) {
|
|
||||||
auto* popup_root = layout[main_id];
|
|
||||||
if (!popup_root) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
glm::vec2 pos = button->m_pos + glm::vec2(button->m_size.x * 0.5f, button->m_size.y);
|
|
||||||
const auto popup_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_root, color);
|
|
||||||
if (!popup_overlay)
|
|
||||||
{
|
|
||||||
LOG("Color popup overlay failed: %s", popup_overlay.status().message);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
color->find("title")->SetVisibility(true);
|
|
||||||
color->SetSize(350, 350);
|
|
||||||
auto tick = pp::panopainter::make_legacy_overlay_node_for_anchor<NodeImage>(*layout[main_id]);
|
|
||||||
tick->SetPositioning(YGPositionTypeAbsolute);
|
|
||||||
tick->SetSize(32, 16);
|
|
||||||
tick->SetPosition(pos.x - 16, pos.y);
|
|
||||||
tick->set_image("data/ui/popup-tick-up.png");
|
|
||||||
auto tick_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_root, tick);
|
|
||||||
if (!popup_overlay || !tick_overlay)
|
|
||||||
{
|
|
||||||
close_legacy_overlay_handles_if_open(*popup_root, popup_overlay, tick_overlay);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const auto popup_handle = popup_overlay.value();
|
|
||||||
const auto tick_handle = tick_overlay.value();
|
|
||||||
popup_root->update();
|
|
||||||
|
|
||||||
color->SetPosition(pos.x - color->m_size.x / 2.f, pos.y + 16);
|
|
||||||
color->SetPositioning(YGPositionTypeAbsolute);
|
|
||||||
pp::panopainter::activate_legacy_popup_overlay(*color);
|
|
||||||
color->on_popup_close = [popup_root, popup_handle, tick_handle](Node*) {
|
|
||||||
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
|
||||||
close_legacy_overlay_handle_ignoring_status(*popup_root, tick_handle);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-layer"))
|
|
||||||
{
|
|
||||||
button->on_click = [this, button](Node*) {
|
|
||||||
auto* popup_root = layout[main_id];
|
|
||||||
if (!popup_root) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto screen = popup_root->m_size;
|
|
||||||
glm::vec2 pos = button->m_pos + glm::vec2(button->m_size.x * 0.5f, button->m_size.y);
|
|
||||||
layers->find("title")->SetVisibility(true);
|
|
||||||
layers->SetSize(350, YGUndefined);
|
|
||||||
if (layers->m_parent)
|
|
||||||
{
|
|
||||||
if (auto fp = dynamic_cast<NodePanelFloating*>(layers->m_parent->m_parent))
|
|
||||||
{
|
|
||||||
pp::panopainter::detach_legacy_node_from_parent(*layers);
|
|
||||||
pp::panopainter::close_legacy_dialog_node(*fp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const auto popup_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_root, layers);
|
|
||||||
if (!popup_overlay) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto tick = pp::panopainter::make_legacy_overlay_node_for_anchor<NodeImage>(*popup_root);
|
|
||||||
tick->SetPositioning(YGPositionTypeAbsolute);
|
|
||||||
tick->SetSize(32, 16);
|
|
||||||
tick->SetPosition(pos.x - 16, pos.y);
|
|
||||||
tick->set_image("data/ui/popup-tick-up.png");
|
|
||||||
auto tick_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_root, tick);
|
|
||||||
if (!popup_overlay || !tick_overlay)
|
|
||||||
{
|
|
||||||
close_legacy_overlay_handles_if_open(*popup_root, popup_overlay, tick_overlay);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const auto popup_handle = popup_overlay.value();
|
|
||||||
const auto tick_handle = tick_overlay.value();
|
|
||||||
popup_root->update();
|
|
||||||
|
|
||||||
layers->SetPosition(pos.x - layers->m_size.x / 2.f, pos.y + 16);
|
|
||||||
layers->SetPositioning(YGPositionTypeAbsolute);
|
|
||||||
pp::panopainter::activate_legacy_popup_overlay(*layers);
|
|
||||||
auto scroll = layers->find<NodeScroll>("layers-container");
|
|
||||||
scroll->SetMaxHeight(glm::max(100.f, screen.y - pos.y - 200.f));
|
|
||||||
layers->on_popup_close = [popup_root, popup_handle, tick_handle](Node*) {
|
|
||||||
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
|
||||||
close_legacy_overlay_handle_ignoring_status(*popup_root, tick_handle);
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-grids-panel"))
|
|
||||||
{
|
|
||||||
button->on_click = [this, button](Node*) {
|
|
||||||
auto* popup_root = layout[main_id];
|
|
||||||
if (!popup_root) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto screen = popup_root->m_size;
|
|
||||||
glm::vec2 pos = button->m_pos + glm::vec2(button->m_size.x * 0.5f, button->m_size.y);
|
|
||||||
grid->find("title")->SetVisibility(true);
|
|
||||||
grid->SetSize(350, YGUndefined);
|
|
||||||
if (grid->m_parent)
|
|
||||||
{
|
|
||||||
if (auto fp = dynamic_cast<NodePanelFloating*>(grid->m_parent->m_parent))
|
|
||||||
{
|
|
||||||
pp::panopainter::detach_legacy_node_from_parent(*grid);
|
|
||||||
pp::panopainter::close_legacy_dialog_node(*fp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const auto popup_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_root, grid);
|
|
||||||
if (!popup_overlay)
|
|
||||||
{
|
|
||||||
LOG("Grid popup overlay failed: %s", popup_overlay.status().message);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto tick = pp::panopainter::make_legacy_overlay_node_for_anchor<NodeImage>(*popup_root);
|
|
||||||
tick->SetPositioning(YGPositionTypeAbsolute);
|
|
||||||
tick->SetSize(32, 16);
|
|
||||||
tick->SetPosition(pos.x - 16, pos.y);
|
|
||||||
tick->set_image("data/ui/popup-tick-up.png");
|
|
||||||
auto tick_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_root, tick);
|
|
||||||
if (!popup_overlay || !tick_overlay)
|
|
||||||
{
|
|
||||||
close_legacy_overlay_handles_if_open(*popup_root, popup_overlay, tick_overlay);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const auto popup_handle = popup_overlay.value();
|
|
||||||
const auto tick_handle = tick_overlay.value();
|
|
||||||
popup_root->update();
|
|
||||||
|
|
||||||
grid->SetPosition(pos.x - grid->m_size.x / 2.f, pos.y + 16);
|
|
||||||
grid->SetPositioning(YGPositionTypeAbsolute);
|
|
||||||
pp::panopainter::activate_legacy_popup_overlay(*grid);
|
|
||||||
auto scroll = grid->find<NodeScroll>("scroller");
|
|
||||||
scroll->SetMaxHeight(glm::max(100.f, screen.y - pos.y - 250.f));
|
|
||||||
|
|
||||||
grid->on_popup_close = [popup_root, popup_handle, tick_handle](Node*) {
|
|
||||||
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
|
||||||
close_legacy_overlay_handle_ignoring_status(*popup_root, tick_handle);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[[nodiscard]] bool current_canvas_mode_is_draw(App& app) noexcept
|
[[nodiscard]] bool current_canvas_mode_is_draw(App& app) noexcept
|
||||||
{
|
{
|
||||||
return app.canvas && app.canvas->m_canvas && app.canvas->m_canvas->m_current_mode == kCanvasMode::Draw;
|
return app.canvas && app.canvas->m_canvas && app.canvas->m_canvas->m_current_mode == kCanvasMode::Draw;
|
||||||
|
|||||||
435
src/app_layout_sidebar.cpp
Normal file
435
src/app_layout_sidebar.cpp
Normal file
@@ -0,0 +1,435 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "app.h"
|
||||||
|
#include "node_panel_grid.h"
|
||||||
|
#include "node_panel_floating.h"
|
||||||
|
#include "app_core/brush_ui.h"
|
||||||
|
#include "app_core/document_layer.h"
|
||||||
|
#include "legacy_brush_ui_services.h"
|
||||||
|
#include "legacy_document_layer_services.h"
|
||||||
|
#include "legacy_ui_overlay_services.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
bool apply_brush_color_plan(App& app, glm::vec4 color, bool update_quick, bool update_color_panel)
|
||||||
|
{
|
||||||
|
return pp::panopainter::apply_legacy_brush_color_plan(app, color, update_quick, update_color_panel);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool apply_brush_texture_plan(App& app, pp::app::BrushUiTextureSlot slot, const std::string& path, const std::string& thumb)
|
||||||
|
{
|
||||||
|
return pp::panopainter::apply_legacy_brush_texture_plan(app, slot, path, thumb);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool apply_brush_preset_plan(App& app, const std::shared_ptr<Brush>& brush)
|
||||||
|
{
|
||||||
|
return pp::panopainter::apply_legacy_brush_preset_plan(app, brush);
|
||||||
|
}
|
||||||
|
|
||||||
|
void execute_document_layer_operation_plan(
|
||||||
|
App& app,
|
||||||
|
const pp::app::DocumentLayerOperationPlan& plan,
|
||||||
|
const std::shared_ptr<class Layer>& pending_layer = nullptr)
|
||||||
|
{
|
||||||
|
const auto status = pp::panopainter::execute_legacy_document_layer_operation_plan(app, plan, pending_layer);
|
||||||
|
if (!status.ok())
|
||||||
|
LOG("Layer operation failed: %s", status.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void close_legacy_overlay_handle_ignoring_status(
|
||||||
|
Node& anchor,
|
||||||
|
pp::ui::NodeHandle overlay) noexcept
|
||||||
|
{
|
||||||
|
(void)pp::panopainter::close_legacy_overlay_node(anchor, overlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename PopupOverlay, typename TickOverlay>
|
||||||
|
void close_legacy_overlay_handles_if_open(
|
||||||
|
Node& anchor,
|
||||||
|
const PopupOverlay& popup_overlay,
|
||||||
|
const TickOverlay& tick_overlay) noexcept
|
||||||
|
{
|
||||||
|
if (popup_overlay) {
|
||||||
|
close_legacy_overlay_handle_ignoring_status(anchor, popup_overlay.value());
|
||||||
|
}
|
||||||
|
if (tick_overlay) {
|
||||||
|
close_legacy_overlay_handle_ignoring_status(anchor, tick_overlay.value());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
std::shared_ptr<T> create_panel(LayoutManager& manager)
|
||||||
|
{
|
||||||
|
auto ret = std::make_shared<T>();
|
||||||
|
ret->set_manager(&manager);
|
||||||
|
ret->init();
|
||||||
|
ret->create();
|
||||||
|
ret->loaded();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void App::init_sidebar()
|
||||||
|
{
|
||||||
|
sidebar = layout[main_id]->find<NodeBorder>("sidebar");
|
||||||
|
canvas = layout[main_id]->find<NodeCanvas>("paint-canvas");
|
||||||
|
quick = layout[main_id]->find<NodePanelQuick>("panel-quick");
|
||||||
|
floatings_container = layout[main_id]->find<Node>("floatings");
|
||||||
|
|
||||||
|
//brushes = layout[main_id]->find<NodePanelBrush>("panel-brush");
|
||||||
|
//layers = layout[main_id]->find<NodePanelLayer>("panel-layer");
|
||||||
|
//color = layout[main_id]->find<NodePanelColor>("panel-color");
|
||||||
|
//stroke = layout[main_id]->find<NodePanelStroke>("panel-stroke");
|
||||||
|
|
||||||
|
//brushes = find_or_create_panel<NodePanelBrush>(panels);
|
||||||
|
layers = create_panel<NodePanelLayer>(layout);
|
||||||
|
color = create_panel<NodePanelColor>(layout);
|
||||||
|
stroke = create_panel<NodePanelStroke>(layout);
|
||||||
|
grid = create_panel<NodePanelGrid>(layout);
|
||||||
|
presets = create_panel<NodePanelBrushPreset>(layout);
|
||||||
|
animation = create_panel<NodePanelAnimation>(layout);
|
||||||
|
//presets = find_or_create_panel<NodePanelBrushPreset>(panels);
|
||||||
|
|
||||||
|
canvas->m_canvas->on_mode_changed = [this](kCanvasMode prev, kCanvasMode mode) {
|
||||||
|
quick_mode_state[prev] = quick->get_state();
|
||||||
|
if (quick_mode_state.find(mode) != quick_mode_state.end())
|
||||||
|
quick->set_state(quick_mode_state[mode], true);
|
||||||
|
else
|
||||||
|
quick->reset_state(true);
|
||||||
|
brush_update(true, true);
|
||||||
|
};
|
||||||
|
color->on_color_changed = [this](Node* target, glm::vec4 color) {
|
||||||
|
apply_brush_color_plan(*this, color, true, false);
|
||||||
|
};
|
||||||
|
|
||||||
|
stroke->on_brush_changed = [this](Node* target, const std::string& path, const std::string& thumb) {
|
||||||
|
apply_brush_texture_plan(*this, pp::app::BrushUiTextureSlot::tip, path, thumb);
|
||||||
|
};
|
||||||
|
stroke->on_pattern_changed = [this](Node* target, const std::string& path, const std::string& thumb) {
|
||||||
|
apply_brush_texture_plan(*this, pp::app::BrushUiTextureSlot::pattern, path, thumb);
|
||||||
|
};
|
||||||
|
stroke->on_dual_changed = [this](Node* target, const std::string& path, const std::string& thumb) {
|
||||||
|
apply_brush_texture_plan(*this, pp::app::BrushUiTextureSlot::dual, path, thumb);
|
||||||
|
};
|
||||||
|
stroke->on_stroke_change = [this](Node*) {
|
||||||
|
const auto status = pp::panopainter::execute_legacy_brush_stroke_changed_plan(*this);
|
||||||
|
if (!status.ok())
|
||||||
|
LOG("Brush stroke settings action failed: %s", status.message);
|
||||||
|
};
|
||||||
|
|
||||||
|
quick->on_color_change = [this](Node*, glm::vec3 c) {
|
||||||
|
apply_brush_color_plan(*this, glm::vec4(c, 1.f), false, true);
|
||||||
|
};
|
||||||
|
quick->on_flow_change = [this](Node*, float value) {
|
||||||
|
stroke->set_flow(value, true, true);
|
||||||
|
};
|
||||||
|
quick->on_size_change = [this](Node*, float value) {
|
||||||
|
stroke->set_size(value, true, true);
|
||||||
|
};
|
||||||
|
quick->on_brush_change = [this](Node*, std::shared_ptr<Brush> b) {
|
||||||
|
apply_brush_preset_plan(*this, b);
|
||||||
|
};
|
||||||
|
|
||||||
|
layers->on_layer_add = [this](Node*, std::shared_ptr<class Layer> layer, int index) {
|
||||||
|
const auto plan = pp::app::plan_document_layer_add(
|
||||||
|
static_cast<int>(Canvas::I->m_layers.size()),
|
||||||
|
index,
|
||||||
|
layers->m_layers.back()->m_label_text);
|
||||||
|
if (!plan)
|
||||||
|
return;
|
||||||
|
execute_document_layer_operation_plan(*this, plan.value(), layer);
|
||||||
|
};
|
||||||
|
|
||||||
|
layers->on_layer_duplicate = [this](Node*, int source_index) {
|
||||||
|
const auto plan = pp::app::plan_document_layer_duplicate(
|
||||||
|
static_cast<int>(Canvas::I->m_layers.size()),
|
||||||
|
source_index);
|
||||||
|
if (!plan)
|
||||||
|
return;
|
||||||
|
execute_document_layer_operation_plan(*this, plan.value());
|
||||||
|
};
|
||||||
|
|
||||||
|
layers->on_layer_change = [this](Node*, int, int new_idx) {
|
||||||
|
const auto plan = pp::app::plan_document_layer_select(
|
||||||
|
static_cast<int>(canvas->m_canvas->m_layers.size()),
|
||||||
|
new_idx);
|
||||||
|
if (!plan)
|
||||||
|
return;
|
||||||
|
execute_document_layer_operation_plan(*this, plan.value());
|
||||||
|
};
|
||||||
|
|
||||||
|
layers->on_layer_order = [this](Node*, int old_idx, int new_idx) {
|
||||||
|
const auto plan = pp::app::plan_document_layer_reorder(
|
||||||
|
static_cast<int>(canvas->m_canvas->m_layers.size()),
|
||||||
|
old_idx,
|
||||||
|
new_idx);
|
||||||
|
if (!plan)
|
||||||
|
return;
|
||||||
|
execute_document_layer_operation_plan(*this, plan.value());
|
||||||
|
};
|
||||||
|
|
||||||
|
layers->on_layer_delete = [this](Node*, int idx) {
|
||||||
|
const auto plan = pp::app::plan_document_layer_remove(
|
||||||
|
static_cast<int>(canvas->m_canvas->m_layers.size()),
|
||||||
|
idx);
|
||||||
|
if (!plan)
|
||||||
|
return;
|
||||||
|
execute_document_layer_operation_plan(*this, plan.value());
|
||||||
|
};
|
||||||
|
|
||||||
|
layers->on_layer_opacity_changed = [this](Node*, int idx, float value) {
|
||||||
|
const auto plan = pp::app::plan_document_layer_opacity(
|
||||||
|
static_cast<int>(canvas->m_canvas->m_layers.size()),
|
||||||
|
idx,
|
||||||
|
value);
|
||||||
|
if (!plan)
|
||||||
|
return;
|
||||||
|
execute_document_layer_operation_plan(*this, plan.value());
|
||||||
|
};
|
||||||
|
|
||||||
|
layers->on_layer_visibility_changed = [this](Node*, int idx, bool visible) {
|
||||||
|
const auto plan = pp::app::plan_document_layer_visibility(
|
||||||
|
static_cast<int>(canvas->m_canvas->m_layers.size()),
|
||||||
|
idx,
|
||||||
|
visible);
|
||||||
|
if (!plan)
|
||||||
|
return;
|
||||||
|
execute_document_layer_operation_plan(*this, plan.value());
|
||||||
|
};
|
||||||
|
|
||||||
|
layers->on_layer_alpha_lock_changed = [this](Node*, int idx, bool locked) {
|
||||||
|
const auto plan = pp::app::plan_document_layer_alpha_lock(
|
||||||
|
static_cast<int>(canvas->m_canvas->m_layers.size()),
|
||||||
|
idx,
|
||||||
|
locked);
|
||||||
|
if (!plan)
|
||||||
|
return;
|
||||||
|
execute_document_layer_operation_plan(*this, plan.value());
|
||||||
|
};
|
||||||
|
|
||||||
|
layers->on_layer_blend_mode_changed = [this](Node*, int idx, int mode) {
|
||||||
|
const auto plan = pp::app::plan_document_layer_blend_mode(
|
||||||
|
static_cast<int>(canvas->m_canvas->m_layers.size()),
|
||||||
|
idx,
|
||||||
|
mode);
|
||||||
|
if (!plan)
|
||||||
|
return;
|
||||||
|
execute_document_layer_operation_plan(*this, plan.value());
|
||||||
|
};
|
||||||
|
|
||||||
|
layers->on_layer_highlight_changed = [this](Node*, int idx, bool highlight) {
|
||||||
|
const auto plan = pp::app::plan_document_layer_highlight(
|
||||||
|
static_cast<int>(canvas->m_canvas->m_layers.size()),
|
||||||
|
idx,
|
||||||
|
highlight);
|
||||||
|
if (!plan)
|
||||||
|
return;
|
||||||
|
execute_document_layer_operation_plan(*this, plan.value());
|
||||||
|
};
|
||||||
|
if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-stroke"))
|
||||||
|
{
|
||||||
|
button->on_click = [this, button](Node*) {
|
||||||
|
auto* popup_root = layout[main_id];
|
||||||
|
if (!popup_root) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto screen = popup_root->m_size;
|
||||||
|
glm::vec2 pos = button->m_pos + glm::vec2(button->m_size.x * 0.5f, button->m_size.y);
|
||||||
|
if (stroke->m_parent)
|
||||||
|
{
|
||||||
|
if (auto fp = dynamic_cast<NodePanelFloating*>(stroke->m_parent->m_parent))
|
||||||
|
{
|
||||||
|
pp::panopainter::detach_legacy_node_from_parent(*stroke);
|
||||||
|
pp::panopainter::close_legacy_dialog_node(*fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const auto popup_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_root, stroke);
|
||||||
|
if (!popup_overlay) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
stroke->SetSize(350, glm::max(100.f, screen.y - pos.y - 50.f));
|
||||||
|
stroke->find("title")->SetVisibility(true);
|
||||||
|
auto tick = pp::panopainter::make_legacy_overlay_node_for_anchor<NodeImage>(*popup_root);
|
||||||
|
tick->SetPositioning(YGPositionTypeAbsolute);
|
||||||
|
tick->SetSize(32, 16);
|
||||||
|
tick->SetPosition(pos.x - 16, pos.y);
|
||||||
|
tick->set_image("data/ui/popup-tick-up.png");
|
||||||
|
auto tick_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_root, tick);
|
||||||
|
if (!popup_overlay || !tick_overlay)
|
||||||
|
{
|
||||||
|
close_legacy_overlay_handles_if_open(*popup_root, popup_overlay, tick_overlay);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto popup_handle = popup_overlay.value();
|
||||||
|
const auto tick_handle = tick_overlay.value();
|
||||||
|
popup_root->update();
|
||||||
|
|
||||||
|
stroke->SetPosition(pos.x - stroke->m_size.x / 2.f, pos.y + 16);
|
||||||
|
stroke->SetPositioning(YGPositionTypeAbsolute);
|
||||||
|
pp::panopainter::activate_legacy_popup_overlay(*stroke);
|
||||||
|
auto scroll = stroke->find<NodeScroll>("scroller");
|
||||||
|
(void)scroll;
|
||||||
|
stroke->m_popup_overlay_handle = popup_handle;
|
||||||
|
stroke->m_tick_overlay_handle = tick_handle;
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
//if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-brush"))
|
||||||
|
//{
|
||||||
|
// button->on_click = [this, button](Node*) {
|
||||||
|
// panels->get_child_index(brushes.get()) == -1 ? panels->add_child(brushes) : panels->remove_child(brushes.get());
|
||||||
|
// panels->fix_scroll();
|
||||||
|
// button->set_color(panels->get_child_index(brushes.get()) == -1 ? color_button_normal : color_button_hlight);
|
||||||
|
// };
|
||||||
|
//}
|
||||||
|
//if (auto* button = layout[main_id]->find<NodeButton>("btn-brush-preset"))
|
||||||
|
//{
|
||||||
|
// button->on_click = [this, button](Node*) {
|
||||||
|
// panels->get_child_index(presets.get()) == -1 ? panels->add_child(presets) : panels->remove_child(presets.get());
|
||||||
|
// panels->fix_scroll();
|
||||||
|
// button->set_color(panels->get_child_index(presets.get()) == -1 ? color_button_normal : color_button_hlight);
|
||||||
|
// };
|
||||||
|
//}
|
||||||
|
if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-color"))
|
||||||
|
{
|
||||||
|
button->on_click = [this, button](Node*) {
|
||||||
|
auto* popup_root = layout[main_id];
|
||||||
|
if (!popup_root) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
glm::vec2 pos = button->m_pos + glm::vec2(button->m_size.x * 0.5f, button->m_size.y);
|
||||||
|
const auto popup_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_root, color);
|
||||||
|
if (!popup_overlay)
|
||||||
|
{
|
||||||
|
LOG("Color popup overlay failed: %s", popup_overlay.status().message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
color->find("title")->SetVisibility(true);
|
||||||
|
color->SetSize(350, 350);
|
||||||
|
auto tick = pp::panopainter::make_legacy_overlay_node_for_anchor<NodeImage>(*layout[main_id]);
|
||||||
|
tick->SetPositioning(YGPositionTypeAbsolute);
|
||||||
|
tick->SetSize(32, 16);
|
||||||
|
tick->SetPosition(pos.x - 16, pos.y);
|
||||||
|
tick->set_image("data/ui/popup-tick-up.png");
|
||||||
|
auto tick_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_root, tick);
|
||||||
|
if (!popup_overlay || !tick_overlay)
|
||||||
|
{
|
||||||
|
close_legacy_overlay_handles_if_open(*popup_root, popup_overlay, tick_overlay);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto popup_handle = popup_overlay.value();
|
||||||
|
const auto tick_handle = tick_overlay.value();
|
||||||
|
popup_root->update();
|
||||||
|
|
||||||
|
color->SetPosition(pos.x - color->m_size.x / 2.f, pos.y + 16);
|
||||||
|
color->SetPositioning(YGPositionTypeAbsolute);
|
||||||
|
pp::panopainter::activate_legacy_popup_overlay(*color);
|
||||||
|
color->on_popup_close = [popup_root, popup_handle, tick_handle](Node*) {
|
||||||
|
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
||||||
|
close_legacy_overlay_handle_ignoring_status(*popup_root, tick_handle);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-layer"))
|
||||||
|
{
|
||||||
|
button->on_click = [this, button](Node*) {
|
||||||
|
auto* popup_root = layout[main_id];
|
||||||
|
if (!popup_root) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto screen = popup_root->m_size;
|
||||||
|
glm::vec2 pos = button->m_pos + glm::vec2(button->m_size.x * 0.5f, button->m_size.y);
|
||||||
|
layers->find("title")->SetVisibility(true);
|
||||||
|
layers->SetSize(350, YGUndefined);
|
||||||
|
if (layers->m_parent)
|
||||||
|
{
|
||||||
|
if (auto fp = dynamic_cast<NodePanelFloating*>(layers->m_parent->m_parent))
|
||||||
|
{
|
||||||
|
pp::panopainter::detach_legacy_node_from_parent(*layers);
|
||||||
|
pp::panopainter::close_legacy_dialog_node(*fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const auto popup_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_root, layers);
|
||||||
|
if (!popup_overlay) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto tick = pp::panopainter::make_legacy_overlay_node_for_anchor<NodeImage>(*popup_root);
|
||||||
|
tick->SetPositioning(YGPositionTypeAbsolute);
|
||||||
|
tick->SetSize(32, 16);
|
||||||
|
tick->SetPosition(pos.x - 16, pos.y);
|
||||||
|
tick->set_image("data/ui/popup-tick-up.png");
|
||||||
|
auto tick_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_root, tick);
|
||||||
|
if (!popup_overlay || !tick_overlay)
|
||||||
|
{
|
||||||
|
close_legacy_overlay_handles_if_open(*popup_root, popup_overlay, tick_overlay);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto popup_handle = popup_overlay.value();
|
||||||
|
const auto tick_handle = tick_overlay.value();
|
||||||
|
popup_root->update();
|
||||||
|
|
||||||
|
layers->SetPosition(pos.x - layers->m_size.x / 2.f, pos.y + 16);
|
||||||
|
layers->SetPositioning(YGPositionTypeAbsolute);
|
||||||
|
pp::panopainter::activate_legacy_popup_overlay(*layers);
|
||||||
|
auto scroll = layers->find<NodeScroll>("layers-container");
|
||||||
|
scroll->SetMaxHeight(glm::max(100.f, screen.y - pos.y - 200.f));
|
||||||
|
layers->on_popup_close = [popup_root, popup_handle, tick_handle](Node*) {
|
||||||
|
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
||||||
|
close_legacy_overlay_handle_ignoring_status(*popup_root, tick_handle);
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-grids-panel"))
|
||||||
|
{
|
||||||
|
button->on_click = [this, button](Node*) {
|
||||||
|
auto* popup_root = layout[main_id];
|
||||||
|
if (!popup_root) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto screen = popup_root->m_size;
|
||||||
|
glm::vec2 pos = button->m_pos + glm::vec2(button->m_size.x * 0.5f, button->m_size.y);
|
||||||
|
grid->find("title")->SetVisibility(true);
|
||||||
|
grid->SetSize(350, YGUndefined);
|
||||||
|
if (grid->m_parent)
|
||||||
|
{
|
||||||
|
if (auto fp = dynamic_cast<NodePanelFloating*>(grid->m_parent->m_parent))
|
||||||
|
{
|
||||||
|
pp::panopainter::detach_legacy_node_from_parent(*grid);
|
||||||
|
pp::panopainter::close_legacy_dialog_node(*fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const auto popup_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_root, grid);
|
||||||
|
if (!popup_overlay)
|
||||||
|
{
|
||||||
|
LOG("Grid popup overlay failed: %s", popup_overlay.status().message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto tick = pp::panopainter::make_legacy_overlay_node_for_anchor<NodeImage>(*popup_root);
|
||||||
|
tick->SetPositioning(YGPositionTypeAbsolute);
|
||||||
|
tick->SetSize(32, 16);
|
||||||
|
tick->SetPosition(pos.x - 16, pos.y);
|
||||||
|
tick->set_image("data/ui/popup-tick-up.png");
|
||||||
|
auto tick_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_root, tick);
|
||||||
|
if (!popup_overlay || !tick_overlay)
|
||||||
|
{
|
||||||
|
close_legacy_overlay_handles_if_open(*popup_root, popup_overlay, tick_overlay);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto popup_handle = popup_overlay.value();
|
||||||
|
const auto tick_handle = tick_overlay.value();
|
||||||
|
popup_root->update();
|
||||||
|
|
||||||
|
grid->SetPosition(pos.x - grid->m_size.x / 2.f, pos.y + 16);
|
||||||
|
grid->SetPositioning(YGPositionTypeAbsolute);
|
||||||
|
pp::panopainter::activate_legacy_popup_overlay(*grid);
|
||||||
|
auto scroll = grid->find<NodeScroll>("scroller");
|
||||||
|
scroll->SetMaxHeight(glm::max(100.f, screen.y - pos.y - 250.f));
|
||||||
|
|
||||||
|
grid->on_popup_close = [popup_root, popup_handle, tick_handle](Node*) {
|
||||||
|
close_legacy_overlay_handle_ignoring_status(*popup_root, popup_handle);
|
||||||
|
close_legacy_overlay_handle_ignoring_status(*popup_root, tick_handle);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -945,6 +945,49 @@ inline void execute_legacy_canvas_draw_merge_background_setup(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <
|
||||||
|
typename PrepareBlendCache,
|
||||||
|
typename DrawBackground,
|
||||||
|
typename ConfigureBlendState,
|
||||||
|
typename DisableDepthTest,
|
||||||
|
typename PlanOnionRange,
|
||||||
|
typename ShouldDrawPlane,
|
||||||
|
typename VisitLayerPlane,
|
||||||
|
typename LogOnionRangeFailure,
|
||||||
|
typename CompositeBlendCache>
|
||||||
|
inline void execute_legacy_canvas_draw_unmerged_shell(
|
||||||
|
bool use_blend,
|
||||||
|
size_t layer_count,
|
||||||
|
PrepareBlendCache&& prepare_blend_cache,
|
||||||
|
DrawBackground&& draw_background,
|
||||||
|
ConfigureBlendState&& configure_blend_state,
|
||||||
|
DisableDepthTest&& disable_depth_test,
|
||||||
|
PlanOnionRange&& plan_onion_range,
|
||||||
|
ShouldDrawPlane&& should_draw_plane,
|
||||||
|
VisitLayerPlane&& visit_layer_plane,
|
||||||
|
LogOnionRangeFailure&& log_onion_range_failure,
|
||||||
|
CompositeBlendCache&& composite_blend_cache)
|
||||||
|
{
|
||||||
|
if (use_blend) {
|
||||||
|
prepare_blend_cache();
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_background();
|
||||||
|
configure_blend_state(use_blend);
|
||||||
|
disable_depth_test();
|
||||||
|
|
||||||
|
execute_legacy_canvas_draw_layer_traversal(
|
||||||
|
layer_count,
|
||||||
|
std::forward<PlanOnionRange>(plan_onion_range),
|
||||||
|
std::forward<ShouldDrawPlane>(should_draw_plane),
|
||||||
|
std::forward<VisitLayerPlane>(visit_layer_plane),
|
||||||
|
std::forward<LogOnionRangeFailure>(log_onion_range_failure));
|
||||||
|
|
||||||
|
if (use_blend) {
|
||||||
|
composite_blend_cache();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline void execute_legacy_canvas_draw_merge_plane_setup(
|
inline void execute_legacy_canvas_draw_merge_plane_setup(
|
||||||
const LegacyCanvasDrawMergePlaneSetupUniforms& uniforms,
|
const LegacyCanvasDrawMergePlaneSetupUniforms& uniforms,
|
||||||
const LegacyCanvasDrawMergePlaneSetupExecution& execution)
|
const LegacyCanvasDrawMergePlaneSetupExecution& execution)
|
||||||
|
|||||||
60
src/main.cpp
60
src/main.cpp
@@ -11,6 +11,7 @@
|
|||||||
#include "legacy_preference_storage.h"
|
#include "legacy_preference_storage.h"
|
||||||
#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_lifecycle_shell.h"
|
||||||
#include "platform_windows/windows_splash.h"
|
#include "platform_windows/windows_splash.h"
|
||||||
#include "platform_windows/windows_stylus_input.h"
|
#include "platform_windows/windows_stylus_input.h"
|
||||||
#include "platform_windows/windows_vr_shell.h"
|
#include "platform_windows/windows_vr_shell.h"
|
||||||
@@ -30,10 +31,6 @@
|
|||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <atomic>
|
|
||||||
|
|
||||||
#define WM_USER_CLOSE (WM_USER + 1)
|
|
||||||
#define WM_USER_WAKEUP (WM_USER + 2)
|
|
||||||
|
|
||||||
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp);
|
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp);
|
||||||
namespace pp::platform::windows {
|
namespace pp::platform::windows {
|
||||||
@@ -127,13 +124,10 @@ void pp_windows_enqueue_main_task(std::packaged_task<void()> task)
|
|||||||
enqueue_main_task_bridge(std::move(task));
|
enqueue_main_task_bridge(std::move(task));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::atomic<int> running{-1};
|
|
||||||
|
|
||||||
void destroy_window()
|
void destroy_window()
|
||||||
{
|
{
|
||||||
auto& state = retained_state();
|
enqueue_main_task([hWnd = retained_state().hWnd] {
|
||||||
enqueue_main_task([hWnd = state.hWnd] {
|
pp::platform::windows::request_window_close(hWnd);
|
||||||
PostMessage(hWnd, WM_USER_CLOSE, 0, 0);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,26 +153,16 @@ void async_unlock()
|
|||||||
|
|
||||||
void win32_update_stylus(float dt)
|
void win32_update_stylus(float dt)
|
||||||
{
|
{
|
||||||
pp::platform::windows::update_stylus_state(dt);
|
pp::platform::windows::update_stylus_frame(dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void win32_update_fps(int frames)
|
void win32_update_fps(int frames)
|
||||||
{
|
{
|
||||||
static wchar_t title_fps[512];
|
|
||||||
auto& state = retained_state();
|
auto& state = retained_state();
|
||||||
const int vr_fps = pp::platform::windows::current_vr_fps(state.vr);
|
enqueue_main_task([hWnd = state.hWnd, window_title = state.window_title, &vr = state.vr, frames] {
|
||||||
if (App::I->vr_active)
|
pp::platform::windows::update_window_fps(hWnd, window_title, vr, frames);
|
||||||
swprintf_s(title_fps, L"%s - %d fps - %d vr fps", state.window_title, frames, vr_fps);
|
|
||||||
else
|
|
||||||
swprintf_s(title_fps, L"%s - %d fps", state.window_title, frames);
|
|
||||||
|
|
||||||
{
|
|
||||||
enqueue_main_task([hWnd = state.hWnd] {
|
|
||||||
SetWindowText(hWnd, title_fps);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
PostMessage(state.hWnd, WM_USER_WAKEUP, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int read_WMI_info()
|
int read_WMI_info()
|
||||||
{
|
{
|
||||||
@@ -455,25 +439,17 @@ void init_vk_map()
|
|||||||
bool win32_vr_start()
|
bool win32_vr_start()
|
||||||
{
|
{
|
||||||
auto& state = retained_state();
|
auto& state = retained_state();
|
||||||
return pp::platform::windows::start_vr_shell(state.vr, state.sandboxed, running);
|
return pp::platform::windows::start_window_vr(state.vr, state.sandboxed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void win32_vr_stop()
|
void win32_vr_stop()
|
||||||
{
|
{
|
||||||
auto& state = retained_state();
|
pp::platform::windows::stop_window_vr(retained_state().vr);
|
||||||
pp::platform::windows::stop_vr_shell(state.vr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void win32_save_window_state()
|
void win32_save_window_state()
|
||||||
{
|
{
|
||||||
auto& state = retained_state();
|
pp::platform::windows::save_window_preferences(retained_state().hWnd);
|
||||||
WINDOWPLACEMENT p;
|
|
||||||
GetWindowPlacement(state.hWnd, &p);
|
|
||||||
pp::panopainter::set_legacy_window_preferences(p.showCmd, {
|
|
||||||
p.rcNormalPosition.left,
|
|
||||||
p.rcNormalPosition.top,
|
|
||||||
p.rcNormalPosition.right,
|
|
||||||
p.rcNormalPosition.bottom });
|
|
||||||
}
|
}
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
@@ -678,7 +654,7 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
wglMakeCurrent(NULL, NULL);
|
wglMakeCurrent(NULL, NULL);
|
||||||
|
|
||||||
running.store(1, std::memory_order_relaxed);
|
pp::platform::windows::mark_lifecycle_running();
|
||||||
App::I->runtime().render_thread_start(*App::I);
|
App::I->runtime().render_thread_start(*App::I);
|
||||||
App::I->runtime().ui_thread_start(*App::I);
|
App::I->runtime().ui_thread_start(*App::I);
|
||||||
|
|
||||||
@@ -724,14 +700,14 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
MSG msg;
|
MSG msg;
|
||||||
LOG("start main loop");
|
LOG("start main loop");
|
||||||
while (running.load(std::memory_order_relaxed) == 1)
|
while (pp::platform::windows::lifecycle_is_running())
|
||||||
{
|
{
|
||||||
// If there any message in the queue process it
|
// If there any message in the queue process it
|
||||||
auto present = App::I->animate || App::I->redraw ?
|
auto present = App::I->animate || App::I->redraw ?
|
||||||
PeekMessage(&msg, 0, 0, 0, PM_REMOVE) : GetMessage(&msg, 0, 0, 0);
|
PeekMessage(&msg, 0, 0, 0, PM_REMOVE) : GetMessage(&msg, 0, 0, 0);
|
||||||
|
|
||||||
if (msg.message == WM_QUIT)
|
if (msg.message == WM_QUIT)
|
||||||
running.store(0, std::memory_order_relaxed);
|
pp::platform::windows::mark_lifecycle_stopped();
|
||||||
|
|
||||||
if (present)
|
if (present)
|
||||||
{
|
{
|
||||||
@@ -762,14 +738,8 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
|
|||||||
|
|
||||||
switch (msg)
|
switch (msg)
|
||||||
{
|
{
|
||||||
case WM_USER_CLOSE:
|
case pp::platform::windows::kUserCloseMessage:
|
||||||
running.store(0, std::memory_order_relaxed);
|
pp::platform::windows::handle_window_close_message(state.vr);
|
||||||
pp::platform::windows::request_stop_and_join_vr_thread(state.vr);
|
|
||||||
App::I->runtime().ui_thread_stop();
|
|
||||||
App::I->runtime().render_thread_stop();
|
|
||||||
App::I->terminate();
|
|
||||||
delete App::I;
|
|
||||||
PostQuitMessage(0);
|
|
||||||
return 0;
|
return 0;
|
||||||
case WM_PAINT:
|
case WM_PAINT:
|
||||||
App::I->redraw = true;
|
App::I->redraw = true;
|
||||||
@@ -792,7 +762,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
|
|||||||
{
|
{
|
||||||
auto w = (float)LOWORD(lp);
|
auto w = (float)LOWORD(lp);
|
||||||
auto h = (float)HIWORD(lp);
|
auto h = (float)HIWORD(lp);
|
||||||
if (h != 0 && running.load(std::memory_order_relaxed) == 1)
|
if (h != 0 && pp::platform::windows::lifecycle_is_running())
|
||||||
{
|
{
|
||||||
App::I->ui_task_async([=]
|
App::I->ui_task_async([=]
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -668,13 +668,16 @@ void NodeCanvas::draw()
|
|||||||
const bool use_blend = blend_gate.shader_blend;
|
const bool use_blend = blend_gate.shader_blend;
|
||||||
const bool copy_blend_destination = use_blend && !blend_gate.reads_destination_color;
|
const bool copy_blend_destination = use_blend && !blend_gate.reads_destination_color;
|
||||||
|
|
||||||
if (use_blend)
|
const auto& b = m_canvas->m_current_stroke->m_brush;
|
||||||
{
|
pp::panopainter::execute_legacy_canvas_draw_unmerged_shell(
|
||||||
|
use_blend,
|
||||||
|
m_canvas->m_layers.size(),
|
||||||
|
[&] {
|
||||||
apply_node_canvas_viewport(0, 0, m_cache_rtt.getWidth(), m_cache_rtt.getHeight());
|
apply_node_canvas_viewport(0, 0, m_cache_rtt.getWidth(), m_cache_rtt.getHeight());
|
||||||
m_cache_rtt.bindFramebuffer();
|
m_cache_rtt.bindFramebuffer();
|
||||||
m_cache_rtt.clear({ 1, 1, 1, 0 });
|
m_cache_rtt.clear({ 1, 1, 1, 0 });
|
||||||
}
|
},
|
||||||
|
[&] {
|
||||||
pp::panopainter::execute_legacy_canvas_draw_merge_background_setup(
|
pp::panopainter::execute_legacy_canvas_draw_merge_background_setup(
|
||||||
{
|
{
|
||||||
.use_blend = use_blend,
|
.use_blend = use_blend,
|
||||||
@@ -692,14 +695,14 @@ void NodeCanvas::draw()
|
|||||||
m_face_plane.draw_fill();
|
m_face_plane.draw_fill();
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
[&](bool enable_shader_blend) {
|
||||||
// if not using shader blend, use gl rasterizer blend
|
// if not using shader blend, use gl rasterizer blend
|
||||||
use_blend ? apply_node_canvas_capability(pp::renderer::gl::blend_state(), false) : apply_node_canvas_capability(pp::renderer::gl::blend_state(), true);
|
apply_node_canvas_capability(pp::renderer::gl::blend_state(), !enable_shader_blend);
|
||||||
|
},
|
||||||
|
[&] {
|
||||||
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;
|
|
||||||
pp::panopainter::execute_legacy_canvas_draw_layer_traversal(
|
|
||||||
m_canvas->m_layers.size(),
|
|
||||||
[&](size_t layer_index) {
|
[&](size_t layer_index) {
|
||||||
return pp::app::plan_animation_onion_frame_range(
|
return pp::app::plan_animation_onion_frame_range(
|
||||||
m_canvas->m_layers[layer_index]->frames_count(),
|
m_canvas->m_layers[layer_index]->frames_count(),
|
||||||
@@ -748,9 +751,8 @@ void NodeCanvas::draw()
|
|||||||
},
|
},
|
||||||
[&](const char* message) {
|
[&](const char* message) {
|
||||||
LOG("NodeCanvas onion frame range failed: %s", message);
|
LOG("NodeCanvas onion frame range failed: %s", message);
|
||||||
});
|
},
|
||||||
if (use_blend)
|
[&] {
|
||||||
{
|
|
||||||
m_cache_rtt.unbindFramebuffer();
|
m_cache_rtt.unbindFramebuffer();
|
||||||
if (m_density != 1.f)
|
if (m_density != 1.f)
|
||||||
apply_node_canvas_viewport(0, 0, m_rtt.getWidth(), m_rtt.getHeight());
|
apply_node_canvas_viewport(0, 0, m_rtt.getWidth(), m_rtt.getHeight());
|
||||||
@@ -792,7 +794,7 @@ void NodeCanvas::draw()
|
|||||||
m_cache_rtt.unbindTexture();
|
m_cache_rtt.unbindTexture();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
execute_node_canvas_draw_merge_tail(*this, ortho_proj, proj, camera, c);
|
execute_node_canvas_draw_merge_tail(*this, ortho_proj, proj, camera, c);
|
||||||
|
|||||||
96
src/platform_windows/windows_lifecycle_shell.cpp
Normal file
96
src/platform_windows/windows_lifecycle_shell.cpp
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
|
||||||
|
#include "platform_windows/windows_lifecycle_shell.h"
|
||||||
|
|
||||||
|
#include "app.h"
|
||||||
|
#include "legacy_preference_storage.h"
|
||||||
|
#include "platform_windows/windows_stylus_input.h"
|
||||||
|
|
||||||
|
namespace pp::platform::windows {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
[[nodiscard]] std::atomic<int>& retained_running_state() noexcept
|
||||||
|
{
|
||||||
|
static std::atomic<int> running{-1};
|
||||||
|
return running;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::atomic<int>& lifecycle_running_state() noexcept
|
||||||
|
{
|
||||||
|
return retained_running_state();
|
||||||
|
}
|
||||||
|
|
||||||
|
void mark_lifecycle_running() noexcept
|
||||||
|
{
|
||||||
|
retained_running_state().store(1, std::memory_order_relaxed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mark_lifecycle_stopped() noexcept
|
||||||
|
{
|
||||||
|
retained_running_state().store(0, std::memory_order_relaxed);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool lifecycle_is_running() noexcept
|
||||||
|
{
|
||||||
|
return retained_running_state().load(std::memory_order_relaxed) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void request_window_close(HWND hWnd)
|
||||||
|
{
|
||||||
|
PostMessage(hWnd, kUserCloseMessage, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_window_close_message(VrShellState& vr)
|
||||||
|
{
|
||||||
|
mark_lifecycle_stopped();
|
||||||
|
request_stop_and_join_vr_thread(vr);
|
||||||
|
App::I->runtime().ui_thread_stop();
|
||||||
|
App::I->runtime().render_thread_stop();
|
||||||
|
App::I->terminate();
|
||||||
|
delete App::I;
|
||||||
|
PostQuitMessage(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_stylus_frame(float dt)
|
||||||
|
{
|
||||||
|
update_stylus_state(dt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_window_fps(HWND hWnd, const wchar_t* window_title, VrShellState& vr, int frames)
|
||||||
|
{
|
||||||
|
static wchar_t title_fps[512];
|
||||||
|
const int vr_fps = current_vr_fps(vr);
|
||||||
|
if (App::I->vr_active)
|
||||||
|
swprintf_s(title_fps, L"%s - %d fps - %d vr fps", window_title, frames, vr_fps);
|
||||||
|
else
|
||||||
|
swprintf_s(title_fps, L"%s - %d fps", window_title, frames);
|
||||||
|
|
||||||
|
SetWindowText(hWnd, title_fps);
|
||||||
|
PostMessage(hWnd, kUserWakeupMessage, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void save_window_preferences(HWND hWnd)
|
||||||
|
{
|
||||||
|
WINDOWPLACEMENT placement{};
|
||||||
|
GetWindowPlacement(hWnd, &placement);
|
||||||
|
pp::panopainter::set_legacy_window_preferences(placement.showCmd, {
|
||||||
|
placement.rcNormalPosition.left,
|
||||||
|
placement.rcNormalPosition.top,
|
||||||
|
placement.rcNormalPosition.right,
|
||||||
|
placement.rcNormalPosition.bottom });
|
||||||
|
}
|
||||||
|
|
||||||
|
bool start_window_vr(VrShellState& vr, bool sandboxed)
|
||||||
|
{
|
||||||
|
return start_vr_shell(vr, sandboxed, retained_running_state());
|
||||||
|
}
|
||||||
|
|
||||||
|
void stop_window_vr(VrShellState& vr)
|
||||||
|
{
|
||||||
|
stop_vr_shell(vr);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
29
src/platform_windows/windows_lifecycle_shell.h
Normal file
29
src/platform_windows/windows_lifecycle_shell.h
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
|
#include "platform_windows/windows_vr_shell.h"
|
||||||
|
|
||||||
|
namespace pp::platform::windows {
|
||||||
|
|
||||||
|
inline constexpr UINT kUserCloseMessage = WM_USER + 1;
|
||||||
|
inline constexpr UINT kUserWakeupMessage = WM_USER + 2;
|
||||||
|
|
||||||
|
[[nodiscard]] std::atomic<int>& lifecycle_running_state() noexcept;
|
||||||
|
void mark_lifecycle_running() noexcept;
|
||||||
|
void mark_lifecycle_stopped() noexcept;
|
||||||
|
[[nodiscard]] bool lifecycle_is_running() noexcept;
|
||||||
|
|
||||||
|
void request_window_close(HWND hWnd);
|
||||||
|
void handle_window_close_message(VrShellState& vr);
|
||||||
|
|
||||||
|
void update_stylus_frame(float dt);
|
||||||
|
void update_window_fps(HWND hWnd, const wchar_t* window_title, VrShellState& vr, int frames);
|
||||||
|
void save_window_preferences(HWND hWnd);
|
||||||
|
|
||||||
|
[[nodiscard]] bool start_window_vr(VrShellState& vr, bool sandboxed);
|
||||||
|
void stop_window_vr(VrShellState& vr);
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user