Thin canvas state, tools menu, and node canvas draw
This commit is contained in:
@@ -33,6 +33,10 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace pp::panopainter {
|
||||
void bind_legacy_tools_menu(App& app);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
bool apply_brush_color_plan(App& app, glm::vec4 color, bool update_quick, bool update_color_panel)
|
||||
@@ -897,441 +901,7 @@ void App::init_menu_edit()
|
||||
|
||||
void App::init_menu_tools()
|
||||
{
|
||||
auto main = layout[main_id];
|
||||
|
||||
if (auto menu_exp = main->find<NodeButtonCustom>("menu-tools"))
|
||||
{
|
||||
menu_exp->on_click = [this, menu_exp, main](Node*) {
|
||||
glm::vec2 pos = menu_exp->m_pos + glm::vec2(0, menu_exp->m_size.y);
|
||||
auto popup_exp = add_menu_popup(*this, "tools-menu", pos, menu_exp->m_size.x);
|
||||
if (!popup_exp)
|
||||
return;
|
||||
|
||||
if (auto tick = popup_exp->find<NodeButtonCustom>("tools-panels")) tick->on_click = [this, popup_exp, main](Node* b)
|
||||
{
|
||||
const auto menu_plan = pp::app::plan_tools_menu_command(pp::app::ToolsMenuCommand::panels);
|
||||
if (menu_plan.action != pp::app::ToolsMenuAction::show_panels_submenu)
|
||||
return;
|
||||
|
||||
pp::panopainter::detach_legacy_node_from_parent(*popup_exp);
|
||||
const auto popup_exp_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*main, popup_exp);
|
||||
if (!popup_exp_overlay)
|
||||
return;
|
||||
const auto popup_exp_handle = popup_exp_overlay.value();
|
||||
|
||||
glm::vec2 pos = b->m_pos + glm::vec2(b->m_size.x, 0);
|
||||
auto popup_time = add_menu_popup(*this, "panels-menu", pos, b->m_size.x);
|
||||
if (!popup_time)
|
||||
{
|
||||
close_legacy_overlay_handle_ignoring_status(*main, popup_exp_handle);
|
||||
return;
|
||||
}
|
||||
pp::panopainter::detach_legacy_node_from_parent(*popup_time);
|
||||
const auto popup_time_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*main, popup_time);
|
||||
if (!popup_time_overlay)
|
||||
{
|
||||
close_legacy_overlay_handle_ignoring_status(*main, popup_exp_handle);
|
||||
return;
|
||||
}
|
||||
const auto popup_time_handle = popup_time_overlay.value();
|
||||
|
||||
const auto close_panel_popups = [main, popup_exp_handle, popup_time_handle]()
|
||||
{
|
||||
close_legacy_overlay_handle_ignoring_status(*main, popup_exp_handle);
|
||||
close_legacy_overlay_handle_ignoring_status(*main, popup_time_handle);
|
||||
};
|
||||
|
||||
auto visible = [this](Node* panel) {
|
||||
if (!panel)
|
||||
return false;
|
||||
for (auto& c : floatings_container->m_children)
|
||||
{
|
||||
if (auto fp = std::static_pointer_cast<NodePanelFloating>(c))
|
||||
{
|
||||
if (fp->m_container->is_child(panel))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
popup_time->find<NodeButtonCustom>("panel-presets")->on_click = [this, close_panel_popups, visible](Node*) {
|
||||
const auto plan = pp::app::plan_tools_panel(
|
||||
pp::app::ToolsPanel::presets,
|
||||
visible(floating_presets.get()));
|
||||
if (!should_open_tools_panel(plan))
|
||||
return;
|
||||
auto fpanel = floatings_container->add_child<NodePanelFloating>();
|
||||
fpanel->m_class = NodePanelFloating::kClass::Presets;
|
||||
apply_tools_panel_chrome(*fpanel, plan);
|
||||
if (!floating_presets)
|
||||
{
|
||||
floating_presets = fpanel->m_container->add_child_ref<NodePanelBrushPreset>();
|
||||
floating_presets->SetHeightP(100);
|
||||
//floating_presets->SetFlexGrow(1);
|
||||
//floating_presets->find("toolbar")->destroy();
|
||||
floating_presets->on_brush_changed = [this](Node* target, std::shared_ptr<Brush>& b) {
|
||||
apply_brush_preset_plan(*this, b);
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
fpanel->m_container->add_child(floating_presets);
|
||||
}
|
||||
close_panel_popups();
|
||||
};
|
||||
|
||||
popup_time->find<NodeButtonCustom>("panel-color")->on_click = [this, close_panel_popups, visible](Node*) {
|
||||
const auto plan = pp::app::plan_tools_panel(
|
||||
pp::app::ToolsPanel::color,
|
||||
visible(floating_color.get()));
|
||||
if (!should_open_tools_panel(plan))
|
||||
return;
|
||||
auto fpanel = floatings_container->add_child<NodePanelFloating>();
|
||||
fpanel->m_class = NodePanelFloating::kClass::Color;
|
||||
apply_tools_panel_chrome(*fpanel, plan);
|
||||
if (!floating_color)
|
||||
{
|
||||
floating_color = fpanel->m_container->add_child_ref<NodePanelColor>();
|
||||
floating_color->SetHeightP(100);
|
||||
//floating_color->SetMinHeight(300);
|
||||
if (plan.hides_embedded_title)
|
||||
floating_color->find("title")->SetVisibility(false);
|
||||
floating_color->on_color_changed = [this](Node* target, glm::vec4 color) {
|
||||
apply_brush_color_plan(*this, color, false, false);
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
fpanel->m_container->add_child(floating_color);
|
||||
}
|
||||
close_panel_popups();
|
||||
};
|
||||
popup_time->find<NodeButtonCustom>("panel-color-adv")->on_click = [this, close_panel_popups, visible](Node*) {
|
||||
const auto plan = pp::app::plan_tools_panel(
|
||||
pp::app::ToolsPanel::color_advanced,
|
||||
visible(floating_picker.get()));
|
||||
if (!should_open_tools_panel(plan))
|
||||
return;
|
||||
auto fpanel = floatings_container->add_child<NodePanelFloating>();
|
||||
fpanel->m_class = NodePanelFloating::kClass::ColorAdv;
|
||||
apply_tools_panel_chrome(*fpanel, plan);
|
||||
if (!floating_picker)
|
||||
{
|
||||
floating_picker = fpanel->m_container->add_child_ref<NodeColorPicker>();
|
||||
//floating_picker->find("title")->SetVisibility(false);
|
||||
//floating_picker->SetHeightP(100);
|
||||
//floating_picker->SetWidth(250);
|
||||
floating_picker->m_autohide = false;
|
||||
floating_picker->on_color_change = [this](Node* target, glm::vec3 color) {
|
||||
apply_brush_color_plan(*this, glm::vec4(color, 1.f), false, false);
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
fpanel->m_container->add_child(floating_picker);
|
||||
}
|
||||
close_panel_popups();
|
||||
};
|
||||
popup_time->find<NodeButtonCustom>("panel-layers")->on_click = [this, close_panel_popups, visible](Node*) {
|
||||
const auto plan = pp::app::plan_tools_panel(
|
||||
pp::app::ToolsPanel::layers,
|
||||
visible(layers.get()));
|
||||
if (!should_open_tools_panel(plan))
|
||||
return;
|
||||
auto fpanel = floatings_container->add_child<NodePanelFloating>();
|
||||
fpanel->m_class = NodePanelFloating::kClass::Layers;
|
||||
apply_tools_panel_chrome(*fpanel, plan);
|
||||
fpanel->m_container->add_child(layers);
|
||||
layers->SetPositioning(YGPositionTypeRelative);
|
||||
layers->SetPosition(0, 0);
|
||||
layers->SetWidthP(100);
|
||||
layers->SetHeightP(100);
|
||||
layers->SetFlexShrink(0);
|
||||
if (plan.hides_embedded_title)
|
||||
layers->find("title")->SetVisibility(false);
|
||||
|
||||
close_panel_popups();
|
||||
};
|
||||
popup_time->find<NodeButtonCustom>("panel-brush")->on_click = [this, close_panel_popups, visible](Node*) {
|
||||
const auto plan = pp::app::plan_tools_panel(
|
||||
pp::app::ToolsPanel::brush,
|
||||
visible(stroke.get()));
|
||||
if (!should_open_tools_panel(plan))
|
||||
return;
|
||||
auto fpanel = floatings_container->add_child<NodePanelFloating>();
|
||||
fpanel->m_class = NodePanelFloating::kClass::Brush;
|
||||
fpanel->m_container->add_child(stroke);
|
||||
apply_tools_panel_chrome(*fpanel, plan);
|
||||
stroke->SetPositioning(YGPositionTypeRelative);
|
||||
stroke->SetPosition(0, 0);
|
||||
stroke->SetWidthP(100);
|
||||
stroke->SetHeightP(100);
|
||||
if (plan.hides_embedded_title)
|
||||
stroke->find("title")->SetVisibility(false);
|
||||
|
||||
close_panel_popups();
|
||||
};
|
||||
popup_time->find<NodeButtonCustom>("panel-grids")->on_click = [this, close_panel_popups, visible](Node*) {
|
||||
const auto plan = pp::app::plan_tools_panel(
|
||||
pp::app::ToolsPanel::grids,
|
||||
visible(grid.get()));
|
||||
if (!should_open_tools_panel(plan))
|
||||
return;
|
||||
auto fpanel = floatings_container->add_child<NodePanelFloating>();
|
||||
fpanel->m_class = NodePanelFloating::kClass::Grids;
|
||||
fpanel->m_container->add_child(grid);
|
||||
apply_tools_panel_chrome(*fpanel, plan);
|
||||
grid->SetPositioning(YGPositionTypeRelative);
|
||||
grid->SetPosition(0, 0);
|
||||
grid->SetWidthP(100);
|
||||
grid->SetHeightP(100);
|
||||
if (plan.hides_embedded_title)
|
||||
grid->find("title")->SetVisibility(false);
|
||||
|
||||
close_panel_popups();
|
||||
};
|
||||
popup_time->find<NodeButtonCustom>("panel-animation")->on_click = [this, close_panel_popups, visible](Node*) {
|
||||
const auto plan = pp::app::plan_tools_panel(
|
||||
pp::app::ToolsPanel::animation,
|
||||
visible(animation.get()));
|
||||
if (!should_open_tools_panel(plan))
|
||||
return;
|
||||
auto fpanel = floatings_container->add_child<NodePanelFloating>();
|
||||
fpanel->m_class = NodePanelFloating::kClass::Animation;
|
||||
fpanel->m_container->add_child(animation);
|
||||
apply_tools_panel_chrome(*fpanel, plan);
|
||||
animation->SetPositioning(YGPositionTypeRelative);
|
||||
animation->SetPosition(0, 0);
|
||||
animation->SetWidthP(100);
|
||||
animation->SetHeightP(100);
|
||||
|
||||
close_panel_popups();
|
||||
};
|
||||
};
|
||||
|
||||
if (auto options = popup_exp->find<NodeButtonCustom>("tools-options")) options->on_click = [this, options, main](Node* b)
|
||||
{
|
||||
const auto menu_plan = pp::app::plan_tools_menu_command(pp::app::ToolsMenuCommand::options);
|
||||
if (menu_plan.action != pp::app::ToolsMenuAction::show_options_submenu)
|
||||
return;
|
||||
|
||||
glm::vec2 pos = b->m_pos + glm::vec2(b->m_size.x, 0);
|
||||
auto popup_time = add_menu_popup(*this, "options-menu", pos, b->m_size.x);
|
||||
if (!popup_time)
|
||||
return;
|
||||
|
||||
if (auto ui_scale = popup_time->find<NodeComboBox>("tools-ui-scale"))
|
||||
{
|
||||
std::vector<float> scale_options;
|
||||
scale_options.reserve(ui_scale->m_data.size());
|
||||
for (int i = 0; i < ui_scale->m_data.size(); i++)
|
||||
scale_options.push_back(ui_scale->get_float(i));
|
||||
|
||||
const auto selection = pp::app::plan_scale_option_selection(App::I->zoom, scale_options);
|
||||
if (selection.has_selection)
|
||||
ui_scale->set_index(static_cast<int>(selection.index));
|
||||
|
||||
ui_scale->on_select = [ui_scale](Node* target, int index)
|
||||
{
|
||||
const auto status = pp::panopainter::execute_legacy_ui_scale_preference(
|
||||
*App::I,
|
||||
ui_scale->get_float(index));
|
||||
if (!status.ok())
|
||||
LOG("UI scale preference failed: %s", status.message);
|
||||
};
|
||||
}
|
||||
|
||||
if (auto vp_scale = popup_time->find<NodeComboBox>("tools-vp-scale"))
|
||||
{
|
||||
std::vector<float> scale_options;
|
||||
scale_options.reserve(vp_scale->m_data.size());
|
||||
for (int i = 0; i < vp_scale->m_data.size(); i++)
|
||||
scale_options.push_back(vp_scale->get_float(i));
|
||||
|
||||
const auto selection = pp::app::plan_scale_option_selection(App::I->canvas->m_density, scale_options);
|
||||
if (selection.has_selection)
|
||||
vp_scale->set_index(static_cast<int>(selection.index));
|
||||
|
||||
vp_scale->on_select = [vp_scale](Node* target, int index)
|
||||
{
|
||||
const auto status = pp::panopainter::execute_legacy_viewport_scale_preference(
|
||||
*App::I,
|
||||
vp_scale->get_float(index));
|
||||
if (!status.ok())
|
||||
LOG("Viewport scale preference failed: %s", status.message);
|
||||
};
|
||||
}
|
||||
|
||||
if (auto rtl_btn = popup_time->find<NodeButtonCustom>("tools-rtl"))
|
||||
{
|
||||
NodeCheckBox* cb = rtl_btn->find<NodeCheckBox>("tools-rtl-check");
|
||||
cb->set_value(ui_rtl, false);
|
||||
|
||||
rtl_btn->on_click = [this, rtl_btn](Node* b)
|
||||
{
|
||||
NodeCheckBox* cb = rtl_btn->find<NodeCheckBox>("tools-rtl-check");
|
||||
cb->set_value(!cb->checked, true);
|
||||
};
|
||||
|
||||
rtl_btn->find<NodeCheckBox>("tools-rtl-check")->on_value_changed = [this, main](Node*, bool checked)
|
||||
{
|
||||
const auto status = pp::panopainter::execute_legacy_interface_direction_preference(
|
||||
*this,
|
||||
checked);
|
||||
if (!status.ok())
|
||||
LOG("Interface direction preference failed: %s", status.message);
|
||||
};
|
||||
}
|
||||
|
||||
if (auto vr_btn = popup_time->find<NodeButtonCustom>("tools-vr"))
|
||||
{
|
||||
NodeCheckBox* cb = vr_btn->find<NodeCheckBox>("tools-vr-check");
|
||||
cb->set_value(has_vr);
|
||||
|
||||
vr_btn->on_click = [this, vr_btn](Node* b)
|
||||
{
|
||||
NodeCheckBox* cb = vr_btn->find<NodeCheckBox>("tools-vr-check");
|
||||
cb->set_value(!cb->checked, true);
|
||||
};
|
||||
|
||||
vr_btn->find<NodeCheckBox>("tools-vr-check")->on_value_changed = [this, main](Node* target, bool checked)
|
||||
{
|
||||
const auto status = pp::panopainter::execute_legacy_vr_mode_preference(
|
||||
*this,
|
||||
checked);
|
||||
if (!status.ok()) {
|
||||
auto cb = static_cast<NodeCheckBox*>(target);
|
||||
cb->set_value(false);
|
||||
message_box("VR Failed", "Couldn't start Virtual Reality mode");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (auto vr_btn = popup_time->find<NodeButtonCustom>("tools-vr-controllers"))
|
||||
{
|
||||
NodeCheckBox* cb = vr_btn->find<NodeCheckBox>("tools-vr-controllers-check");
|
||||
cb->set_value(vr_controllers_enabled);
|
||||
|
||||
vr_btn->on_click = [this, vr_btn](Node* b)
|
||||
{
|
||||
NodeCheckBox* cb = vr_btn->find<NodeCheckBox>("tools-vr-controllers-check");
|
||||
cb->set_value(!cb->checked, true);
|
||||
};
|
||||
|
||||
vr_btn->find<NodeCheckBox>("tools-vr-controllers-check")->on_value_changed = [this, main](Node* target, bool checked)
|
||||
{
|
||||
const auto status = pp::panopainter::execute_legacy_vr_controllers_preference(
|
||||
*this,
|
||||
checked);
|
||||
if (!status.ok())
|
||||
LOG("VR controllers preference failed: %s", status.message);
|
||||
};
|
||||
}
|
||||
|
||||
if (auto btn = popup_time->find<NodeButtonCustom>("tools-timelapse"))
|
||||
{
|
||||
NodeCheckBox* cb = btn->find<NodeCheckBox>("tools-timelapse-check");
|
||||
cb->set_value(
|
||||
pp::panopainter::read_legacy_startup_preferences(vr_controllers_enabled).auto_timelapse,
|
||||
false);
|
||||
|
||||
btn->on_click = [this, btn](Node* b)
|
||||
{
|
||||
NodeCheckBox* cb = btn->find<NodeCheckBox>("tools-timelapse-check");
|
||||
cb->set_value(!cb->checked, true);
|
||||
};
|
||||
|
||||
btn->find<NodeCheckBox>("tools-timelapse-check")->on_value_changed = [this, main](Node*, bool checked)
|
||||
{
|
||||
const auto status = pp::panopainter::execute_legacy_timelapse_preference(
|
||||
*this,
|
||||
checked);
|
||||
if (!status.ok())
|
||||
LOG("Timelapse preference failed: %s", status.message);
|
||||
};
|
||||
}
|
||||
|
||||
if (auto mode = popup_time->find<NodeComboBox>("tools-show-cursor"))
|
||||
{
|
||||
mode->set_index(pp::panopainter::read_legacy_canvas_preferences().cursor_mode);
|
||||
|
||||
mode->on_select = [mode](Node* target, int index)
|
||||
{
|
||||
const auto status = pp::panopainter::execute_legacy_canvas_cursor_mode_preference(
|
||||
*App::I,
|
||||
index);
|
||||
if (!status.ok())
|
||||
LOG("Cursor mode preference failed: %s", status.message);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
popup_exp->find<NodeButtonCustom>("clear-grids")->on_click = [this, popup_exp](Node*) {
|
||||
auto popup_exp_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_exp->root(), popup_exp);
|
||||
if (!popup_exp_overlay)
|
||||
return;
|
||||
const auto popup_exp_handle = popup_exp_overlay.value();
|
||||
const auto plan = pp::app::plan_tools_menu_command(pp::app::ToolsMenuCommand::clear_grids);
|
||||
execute_tools_menu_plan(*this, plan);
|
||||
if (plan.closes_root_popup)
|
||||
{
|
||||
close_legacy_overlay_handle_ignoring_status(*popup_exp->root(), popup_exp_handle);
|
||||
}
|
||||
};
|
||||
|
||||
popup_exp->find<NodeButtonCustom>("camera-reset")->on_click = [this, popup_exp](Node*) {
|
||||
auto popup_exp_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_exp->root(), popup_exp);
|
||||
if (!popup_exp_overlay)
|
||||
return;
|
||||
const auto popup_exp_handle = popup_exp_overlay.value();
|
||||
const auto plan = pp::app::plan_tools_menu_command(pp::app::ToolsMenuCommand::reset_camera);
|
||||
execute_tools_menu_plan(*this, plan);
|
||||
if (plan.closes_root_popup)
|
||||
{
|
||||
close_legacy_overlay_handle_ignoring_status(*popup_exp->root(), popup_exp_handle);
|
||||
}
|
||||
};
|
||||
|
||||
popup_exp->find<NodeButtonCustom>("shortcuts")->on_click = [this, popup_exp](Node*) {
|
||||
auto popup_exp_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_exp->root(), popup_exp);
|
||||
if (!popup_exp_overlay)
|
||||
return;
|
||||
const auto popup_exp_handle = popup_exp_overlay.value();
|
||||
const auto plan = pp::app::plan_tools_menu_command(pp::app::ToolsMenuCommand::shortcuts);
|
||||
execute_tools_menu_plan(*this, plan);
|
||||
if (plan.closes_root_popup)
|
||||
{
|
||||
close_legacy_overlay_handle_ignoring_status(*popup_exp->root(), popup_exp_handle);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
popup_exp->find<NodeButtonCustom>("mp4test")->on_click = [this, popup_exp](Node*) {
|
||||
dialog_export_mp4();
|
||||
pp::panopainter::close_legacy_popup_overlay(*popup_exp);
|
||||
};
|
||||
*/
|
||||
|
||||
if (platform_supports_sonarpen())
|
||||
{
|
||||
popup_exp->find<NodeButtonCustom>("sonarpen")->on_click = [this, popup_exp](Node*) {
|
||||
auto popup_exp_overlay = pp::panopainter::open_legacy_overlay_node_with_handle(*popup_exp->root(), popup_exp);
|
||||
if (!popup_exp_overlay)
|
||||
return;
|
||||
const auto popup_exp_handle = popup_exp_overlay.value();
|
||||
const auto plan = pp::app::plan_tools_menu_command(
|
||||
pp::app::ToolsMenuCommand::sonarpen,
|
||||
platform_supports_sonarpen());
|
||||
execute_tools_menu_plan(*this, plan);
|
||||
if (plan.closes_root_popup)
|
||||
{
|
||||
close_legacy_overlay_handle_ignoring_status(*popup_exp->root(), popup_exp_handle);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
pp::panopainter::bind_legacy_tools_menu(*this);
|
||||
}
|
||||
|
||||
void App::init_menu_about()
|
||||
|
||||
Reference in New Issue
Block a user