#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_sidebar_grid_popup_services.h" #include "legacy_sidebar_color_popup_services.h" #include "legacy_sidebar_stroke_popup_services.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) { 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& 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 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 std::shared_ptr create_panel(LayoutManager& manager) { auto ret = std::make_shared(); ret->set_manager(&manager); ret->init(); ret->create(); ret->loaded(); return ret; } } // namespace void App::init_sidebar() { sidebar = layout[main_id]->find("sidebar"); canvas = layout[main_id]->find("paint-canvas"); quick = layout[main_id]->find("panel-quick"); floatings_container = layout[main_id]->find("floatings"); //brushes = layout[main_id]->find("panel-brush"); //layers = layout[main_id]->find("panel-layer"); //color = layout[main_id]->find("panel-color"); //stroke = layout[main_id]->find("panel-stroke"); //brushes = find_or_create_panel(panels); layers = create_panel(layout); color = create_panel(layout); stroke = create_panel(layout); grid = create_panel(layout); presets = create_panel(layout); animation = create_panel(layout); //presets = find_or_create_panel(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 b) { apply_brush_preset_plan(*this, b); }; layers->on_layer_add = [this](Node*, std::shared_ptr layer, int index) { const auto plan = pp::app::plan_document_layer_add( static_cast(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(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(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(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(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(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(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(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(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(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("btn-stroke")) { button->on_click = [this, button](Node*) { auto* popup_root = layout[main_id]; if (!popup_root) { return; } pp::panopainter::open_legacy_sidebar_stroke_popup(*this, *popup_root, *button, *stroke); }; } //if (auto* button = layout[main_id]->find("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("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("btn-color")) { button->on_click = [this, button](Node*) { auto* popup_root = layout[main_id]; if (!popup_root) { return; } pp::panopainter::open_legacy_sidebar_color_popup(*this, *popup_root, *button, *color); }; } if (auto* button = layout[main_id]->find("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(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(*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("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("btn-grids-panel")) { button->on_click = [this, button](Node*) { auto* popup_root = layout[main_id]; if (!popup_root) { return; } pp::panopainter::open_legacy_sidebar_grid_popup(*popup_root, *button, *grid); }; } }