#include "pch.h" #include "legacy_quick_ui_services.h" #include "app.h" #include "node_image.h" #include "node_stroke_preview.h" namespace pp::panopainter { namespace { class LegacyQuickUiServices final : public pp::app::QuickUiServices { public: LegacyQuickUiServices(NodePanelQuick& panel, const NodePanelQuick::MiniState* restore_state = nullptr) noexcept : panel_(panel) , restore_state_(restore_state) { } void select_slot(pp::app::QuickUiSlotKind slot_kind, int slot_index, bool fire_event) override { if (slot_kind == pp::app::QuickUiSlotKind::brush) { panel_.set_selected_brush_index(slot_index, fire_event); return; } panel_.set_selected_color_index(slot_index, fire_event); } void open_slot_popup(pp::app::QuickUiSlotKind slot_kind, int slot_index) override { if (slot_kind == pp::app::QuickUiSlotKind::brush) { open_brush_popup(slot_index); return; } open_color_picker(slot_index); } void restore_state(int brush_index, int color_index, bool fire_event) override { if (!restore_state_) return; for (int i = 0; i < static_cast(panel_.m_button_brushes.size()); i++) { auto b = static_cast(panel_.m_button_brushes[i]->m_children[0].get()); b->m_brush = restore_state_->brushes[i]; b->draw_stroke(); auto c = static_cast(panel_.m_button_colors[i]->m_children[0].get()); c->m_color = restore_state_->colors[i]; } panel_.set_selected_color_index(color_index, fire_event); panel_.set_selected_brush_index(brush_index, fire_event); } void reset_state(bool fire_event) override { for (int i = 0; i < static_cast(panel_.m_button_brushes.size()); i++) { auto b = static_cast(panel_.m_button_brushes[i]->m_children[0].get()); b->m_brush = std::make_shared(); b->m_brush->load_tip("data/brushes/Round-Hard.png", "data/brushes/thumbs/Round-Hard.png"); b->draw_stroke(); } static_cast(panel_.m_button_colors[0]->m_children[0].get())->m_color = glm::vec4(0, 0, 0, 1); static_cast(panel_.m_button_colors[1]->m_children[0].get())->m_color = glm::vec4(.5, .5, .5, 1); static_cast(panel_.m_button_colors[2]->m_children[0].get())->m_color = glm::vec4(1, 1, 1, 1); panel_.set_selected_brush_index(0, fire_event); panel_.set_selected_color_index(0, fire_event); } private: void open_brush_popup(int slot_index) { auto button = panel_.m_button_brushes[slot_index]; if (!button) return; auto popup = App::I->presets; auto screen = panel_.root()->m_size; glm::vec2 tick_sz = { 16, 32 }; glm::vec2 tick_pos = button->m_pos + glm::vec2(button->m_size.x, 0); glm::vec2 popup_pos = { tick_pos.x + tick_sz.x, tick_pos.y }; auto tick = panel_.root()->add_child(); tick->SetPositioning(YGPositionTypeAbsolute); tick->SetPosition(tick_pos.x, tick_pos.y + (button->m_size.y - tick_sz.y) * 0.5f); tick->SetSize(tick_sz); tick->set_image("data/ui/popup-tick.png"); tick->m_scale = { 1, 1 }; float hh = popup->m_container->m_children.size() > 10 ? (screen.y - 90.f) : 400.f; popup->SetWidth(350); popup->SetHeight(glm::max(hh, 400.f)); popup->SetPositioning(YGPositionTypeAbsolute); popup->SetPosition(popup_pos); panel_.root()->add_child(popup); panel_.root()->update(); popup->tick(0); popup->update(); if (tick_pos.x + popup->m_size.x > screen.x) { tick_pos = button->m_pos - glm::vec2(tick_sz.x, 0); popup_pos = { tick_pos.x - popup->GetWidth(), tick_pos.y }; tick->m_scale.x = -1.f; } popup_pos = glm::clamp(popup_pos, { 0, 0 }, screen - popup->m_size); popup->SetPosition(popup_pos); tick->SetPosition(tick_pos.x, tick_pos.y + (button->m_size.y - tick_sz.y) * 0.5f); popup->update(); popup->m_mouse_ignore = false; popup->m_flood_events = true; popup->m_capture_children = false; popup->mouse_capture(); popup->on_popup_close = [tick](Node*) { tick->destroy(); }; auto* panel = &panel_; popup->on_brush_changed = [panel, button](Node*, std::shared_ptr& b) { auto pr = static_cast(button->m_children[0].get()); *pr->m_brush = *b; pr->m_brush->load(); pr->draw_stroke(); if (panel->on_brush_change) panel->on_brush_change(button, pr->m_brush); }; } void open_color_picker(int slot_index) { auto target = panel_.m_button_colors[slot_index]; if (!target) return; auto popup = panel_.m_picker; auto screen = panel_.root()->m_size; glm::vec2 tick_sz = { 16, 32 }; glm::vec2 tick_pos = target->m_pos + glm::vec2(target->m_size.x, 0); glm::vec2 popup_pos = { tick_pos.x + tick_sz.x, tick_pos.y - 140.f }; auto tick = panel_.root()->add_child(); tick->SetPositioning(YGPositionTypeAbsolute); tick->SetPosition(tick_pos.x, tick_pos.y + (target->m_size.y - tick_sz.y) * 0.5f); tick->SetSize(tick_sz); tick->set_image("data/ui/popup-tick.png"); tick->m_scale = { 1, 1 }; popup->SetPositioning(YGPositionTypeAbsolute); popup->SetPosition(popup_pos); panel_.root()->add_child(popup); panel_.root()->update(); popup->tick(0); popup->update(); if (tick_pos.x + popup->m_size.x > screen.x) { tick_pos = target->m_pos - glm::vec2(tick_sz.x, 0); popup_pos = { tick_pos.x - popup->GetWidth(), tick_pos.y - 140.f }; tick->m_scale.x = -1.f; } popup_pos = glm::clamp(popup_pos, { 0, 0 }, screen - popup->m_size); popup->SetPosition(popup_pos); tick->SetPosition(tick_pos.x, tick_pos.y + (target->m_size.y - tick_sz.y) * 0.5f); popup->update(); popup->m_mouse_ignore = false; popup->m_flood_events = true; popup->m_capture_children = false; popup->mouse_capture(); auto c = static_cast(target->m_children[0].get()); panel_.m_picker->set_color(c->m_color); panel_.m_picker->on_popup_close = [tick](Node*) { tick->destroy(); }; auto* panel = &panel_; panel_.m_picker->on_color_change = [panel, c](Node*, glm::vec3 rgb) { c->m_color = glm::vec4(rgb, 1.f); if (panel->on_color_change) panel->on_color_change(panel, rgb); }; } NodePanelQuick& panel_; const NodePanelQuick::MiniState* restore_state_ = nullptr; }; } // namespace pp::foundation::Status execute_legacy_quick_ui_plan( NodePanelQuick& panel, const pp::app::QuickUiPlan& plan, const NodePanelQuick::MiniState* restore_state) { LegacyQuickUiServices services(panel, restore_state); return pp::app::execute_quick_ui_plan(plan, services); } } // namespace pp::panopainter