diff --git a/applications/gui2/src/modules/camera_tools.hpp b/applications/gui2/src/modules/camera_tools.hpp index 5616a89aa63dfe5205ac14c518a167d92393df05..8e665b8421fa07d32f39bd1d43928cb5cb9a66e8 100644 --- a/applications/gui2/src/modules/camera_tools.hpp +++ b/applications/gui2/src/modules/camera_tools.hpp @@ -4,7 +4,7 @@ namespace ftl { namespace gui2 { -enum class CameraTools { +enum class Tools { NONE, SELECT_POINT, // Touch 2D MOVEMENT, // 3D first person camera controls @@ -27,6 +27,13 @@ enum class CameraTools { INSPECT_POINT }; +enum class ToolGroup { + MOUSE_MOTION, + VIEW_2D_ACTIONS, + VIEW_3D_LAYERS, + VIEW_3D_ACTIONS +}; + } } diff --git a/applications/gui2/src/views/camera.cpp b/applications/gui2/src/views/camera.cpp index a1a3592c96d98fd60f06c64c13c8f8c7bb8df1d9..451a032ee9f4aa450547594aeb8929c8b9252afb 100644 --- a/applications/gui2/src/views/camera.cpp +++ b/applications/gui2/src/views/camera.cpp @@ -23,7 +23,8 @@ using ftl::gui2::ToolPanel; using ftl::gui2::CameraView; using ftl::gui2::PopupButton; using ftl::gui2::VolumeButton; -using ftl::gui2::CameraTools; +using ftl::gui2::Tools; +using ftl::gui2::ToolGroup; using ftl::codecs::Channel; @@ -388,26 +389,53 @@ ToolPanel::ToolPanel(nanogui::Widget *parent, ftl::gui2::Camera* ctrl, CameraVie auto theme = dynamic_cast<ftl::gui2::Screen*>(screen())->getTheme("media_small"); this->setTheme(theme); - _addButton(CameraTools::SELECT_POINT, ENTYPO_ICON_MOUSE_POINTER, "Select Point"); - _addButton(CameraTools::MOVEMENT, ENTYPO_ICON_MAN, "First Person Camera"); - _addButton(CameraTools::MOVE_CURSOR, ENTYPO_ICON_DIRECTION, "Move 3D Cursor"); - _addButton(CameraTools::PAN, ENTYPO_ICON_MOUSE, "Pan Image"); - _addButton(CameraTools::CENTRE_VIEW, ENTYPO_ICON_ALIGN_HORIZONTAL_MIDDLE, "Centre the View (c)"); - _addButton(CameraTools::ZOOM_FIT, ENTYPO_ICON_RESIZE_FULL_SCREEN, "Zoom to Fit (f)"); - _addButton(CameraTools::ZOOM_IN, ENTYPO_ICON_CIRCLE_WITH_PLUS, "Zoom In (+)"); - _addButton(CameraTools::ZOOM_OUT, ENTYPO_ICON_CIRCLE_WITH_MINUS, "Zoom Out (-)"); - _addButton(CameraTools::INSPECT_POINT, ENTYPO_ICON_MAGNIFYING_GLASS, "Inspect Point"); + auto *mouse_group = _addGroup(ToolGroup::MOUSE_MOTION, Button::Flags::RadioButton, { + Tools::SELECT_POINT, + Tools::MOVEMENT, + Tools::MOVE_CURSOR, + Tools::ROTATE_CURSOR, + Tools::PAN, + Tools::INSPECT_POINT, + Tools::ZOOM_IN, + Tools::ZOOM_OUT + }); + _addButton(mouse_group, Tools::SELECT_POINT, ENTYPO_ICON_MOUSE_POINTER, "Select Point"); + _addButton(mouse_group, Tools::MOVEMENT, ENTYPO_ICON_MAN, "First Person Camera"); + _addButton(mouse_group, Tools::MOVE_CURSOR, ENTYPO_ICON_DIRECTION, "Move 3D Cursor"); + _addButton(mouse_group, Tools::PAN, ENTYPO_ICON_MOUSE, "Pan Image"); + _addButton(mouse_group, Tools::INSPECT_POINT, ENTYPO_ICON_MAGNIFYING_GLASS, "Inspect Point"); + _addButton(mouse_group, Tools::ZOOM_IN, ENTYPO_ICON_CIRCLE_WITH_PLUS, "Zoom In (+)"); + _addButton(mouse_group, Tools::ZOOM_OUT, ENTYPO_ICON_CIRCLE_WITH_MINUS, "Zoom Out (-)"); + + auto *view2d_group = _addGroup(ToolGroup::VIEW_2D_ACTIONS, Button::Flags::NormalButton, { + Tools::CENTRE_VIEW, + Tools::ZOOM_FIT + }); + _addButton(view2d_group, Tools::CENTRE_VIEW, ENTYPO_ICON_ALIGN_HORIZONTAL_MIDDLE, "Centre the View (c)"); + _addButton(view2d_group, Tools::ZOOM_FIT, ENTYPO_ICON_RESIZE_FULL_SCREEN, "Zoom to Fit (f)"); + + //_addButton(CameraTools::ORIGIN_TO_CURSOR, ENTYPO_ICON_LOCATION, "Origin to 3D Cursor"); - auto *cur_but = _addButton({ - CameraTools::ORIGIN_TO_CURSOR, - CameraTools::RESET_ORIGIN, - CameraTools::SAVE_CURSOR + auto *action3d_group = _addGroup(ToolGroup::VIEW_3D_ACTIONS, Button::Flags::NormalButton, { + Tools::ORIGIN_TO_CURSOR, + Tools::RESET_ORIGIN, + Tools::SAVE_CURSOR + }); + auto *cur_but = _addButton(action3d_group, { + Tools::ORIGIN_TO_CURSOR, + Tools::RESET_ORIGIN, + Tools::SAVE_CURSOR }, ENTYPO_ICON_LOCATION, "Use Cursor"); - _addButton(cur_but, CameraTools::ORIGIN_TO_CURSOR, "Origin to Cursor"); - _addButton(cur_but, CameraTools::RESET_ORIGIN, "Reset Origin"); - _addButton(cur_but, CameraTools::SAVE_CURSOR, "Save Cursor as Pose"); - _addButton(CameraTools::OVERLAY, ENTYPO_ICON_LINE_GRAPH, "Show/Hide Overlay"); - _addButton(CameraTools::CLIPPING, ENTYPO_ICON_SCISSORS, "Enable/Disable Clipping"); + _addButton(cur_but, Tools::ORIGIN_TO_CURSOR, "Origin to Cursor"); + _addButton(cur_but, Tools::RESET_ORIGIN, "Reset Origin"); + _addButton(cur_but, Tools::SAVE_CURSOR, "Save Cursor as Pose"); + + auto *view3d_group = _addGroup(ToolGroup::VIEW_3D_LAYERS, Button::Flags::ToggleButton, { + Tools::OVERLAY, + Tools::CLIPPING + }); + _addButton(view3d_group, Tools::OVERLAY, ENTYPO_ICON_LINE_GRAPH, "Show/Hide Overlay"); + _addButton(view3d_group, Tools::CLIPPING, ENTYPO_ICON_SCISSORS, "Enable/Disable Clipping"); auto *b = new Button(this, "", ENTYPO_ICON_CHEVRON_THIN_UP); b->setTooltip("Show/Hide Tools"); @@ -429,33 +457,86 @@ ToolPanel::~ToolPanel() { } -void ToolPanel::_addButton(ftl::gui2::CameraTools tool, int icon, const std::string &tooltip) { - auto *b = new nanogui::Button(container_, "", icon); - b->setTooltip(tooltip); - //b->setFlags(nanogui::Button::Flags::RadioButton); - b->setCallback([this, tool]() { - active_ = tool; +bool ToolPanel::isActive(ftl::gui2::Tools tool) { + if (group_map_.count(tool)) { + auto &grp = group_data_[group_map_[tool]]; + return grp.active.count(tool) > 0; + } + return false; +} + +void ToolPanel::setTool(ftl::gui2::Tools tool) { + if (group_map_.count(tool)) { + auto &grp = group_data_[group_map_[tool]]; + + if (grp.type == nanogui::Button::Flags::RadioButton) { + for (auto t : grp.active) { + if (t != tool) { + if (buttons_.count(t)) { + auto *b = buttons_[t]; + b->setTextColor(nanogui::Color(255,255,255,255)); + b->setPushed(false); + } + } + } + + grp.active.clear(); + grp.active.insert(tool); + + if (buttons_.count(tool)) { + auto *b = buttons_[tool]; + b->setTextColor(dynamic_cast<Screen*>(screen())->getColor("highlight1")); + b->setPushed(true); + } + } else if (grp.type == nanogui::Button::Flags::ToggleButton) { + grp.active.insert(tool); + + if (buttons_.count(tool)) { + auto *b = buttons_[tool]; + b->setTextColor(dynamic_cast<Screen*>(screen())->getColor("highlight1")); + b->setPushed(true); + } + } else { + + } + for (auto &f : callbacks_) { if (f(tool)) break; } + } +} + +nanogui::Widget *ToolPanel::_addGroup(ftl::gui2::ToolGroup group, nanogui::Button::Flags type, const std::unordered_set<ftl::gui2::Tools> &tools) { + auto &grp = group_data_[group]; + grp.tools = tools; + grp.type = type; + for (auto t : tools) group_map_[t] = group; + + auto *w = new nanogui::Widget(container_); + w->setLayout(new nanogui::BoxLayout(nanogui::Orientation::Vertical, nanogui::Alignment::Middle, 0, 10)); + return w; +} + +void ToolPanel::_addButton(nanogui::Widget *g, ftl::gui2::Tools tool, int icon, const std::string &tooltip) { + auto *b = new nanogui::Button(g, "", icon); + b->setTooltip(tooltip); + b->setCallback([this, tool]() { + setTool(tool); }); buttons_[tool] = b; } -void ToolPanel::_addButton(ftl::gui2::PopupButton *parent, ftl::gui2::CameraTools tool, const std::string &label) { +void ToolPanel::_addButton(ftl::gui2::PopupButton *parent, ftl::gui2::Tools tool, const std::string &label) { auto *b = new nanogui::Button(parent->popup(), label); b->setCallback([this, parent, tool]() { parent->setPushed(false); - active_ = tool; - for (auto &f : callbacks_) { - if (f(tool)) break; - } + setTool(tool); }); //buttons_[tool] = b; } -ftl::gui2::PopupButton *ToolPanel::_addButton(std::unordered_set<ftl::gui2::CameraTools> tools, int icon, const std::string &tooltip) { - auto *b = new ftl::gui2::PopupButton(container_, "", icon); +ftl::gui2::PopupButton *ToolPanel::_addButton(nanogui::Widget *g, std::unordered_set<ftl::gui2::Tools> tools, int icon, const std::string &tooltip) { + auto *b = new ftl::gui2::PopupButton(g, "", icon); b->setTooltip(tooltip); b->setSide(nanogui::Popup::Side::Left); b->setChevronIcon(0); @@ -474,14 +555,7 @@ ftl::gui2::PopupButton *ToolPanel::_addButton(std::unordered_set<ftl::gui2::Came return b; } -void ToolPanel::setTool(ftl::gui2::CameraTools tool) { - active_ = tool; - if (buttons_.count(tool)) { - buttons_[tool]->setPushed(true); - } -} - -void ToolPanel::setAvailable(const std::unordered_set<ftl::gui2::CameraTools> &s) { +void ToolPanel::setAvailable(const std::unordered_set<ftl::gui2::Tools> &s) { for (auto &b : buttons_) { if (s.count(b.first)) { b.second->setVisible(true); @@ -491,7 +565,7 @@ void ToolPanel::setAvailable(const std::unordered_set<ftl::gui2::CameraTools> &s } } -void ToolPanel::setEnabled(const std::unordered_set<ftl::gui2::CameraTools> &s) { +void ToolPanel::setEnabled(const std::unordered_set<ftl::gui2::Tools> &s) { for (auto &b : buttons_) { if (s.count(b.first)) { b.second->setVisible(true); @@ -502,7 +576,7 @@ void ToolPanel::setEnabled(const std::unordered_set<ftl::gui2::CameraTools> &s) } } -void ToolPanel::enable(const std::unordered_set<ftl::gui2::CameraTools> &s) { +void ToolPanel::enable(const std::unordered_set<ftl::gui2::Tools> &s) { for (auto &b : buttons_) { if (s.count(b.first)) { b.second->setVisible(true); @@ -511,7 +585,7 @@ void ToolPanel::enable(const std::unordered_set<ftl::gui2::CameraTools> &s) { } } -void ToolPanel::disable(const std::unordered_set<ftl::gui2::CameraTools> &s) { +void ToolPanel::disable(const std::unordered_set<ftl::gui2::Tools> &s) { for (auto &b : buttons_) { if (s.count(b.first)) { b.second->setEnabled(false); @@ -528,16 +602,6 @@ void ToolPanel::draw(NVGcontext *ctx) { FixedWindow::draw(ctx); } -nanogui::Button* ToolPanel::addButton(int pos) { - auto* button = new nanogui::Button(this, "", 0); - if (pos >= 0) { - mChildren.pop_back(); - mChildren.insert(mChildren.begin() + pos, button); - } - performLayout(screen()->nvgContext()); - return button; -} - // ==== CameraView ============================================================= CameraView::CameraView(ftl::gui2::Screen* parent, ftl::gui2::Camera* ctrl) : @@ -583,21 +647,21 @@ CameraView::CameraView(ftl::gui2::Screen* parent, ftl::gui2::Camera* ctrl) : }); tools_->setAvailable({ - CameraTools::SELECT_POINT, - CameraTools::OVERLAY, - CameraTools::PAN, - CameraTools::ZOOM_FIT, - CameraTools::ZOOM_IN, - CameraTools::ZOOM_OUT, - CameraTools::CENTRE_VIEW, - CameraTools::INSPECT_POINT + Tools::SELECT_POINT, + Tools::OVERLAY, + Tools::PAN, + Tools::ZOOM_FIT, + Tools::ZOOM_IN, + Tools::ZOOM_OUT, + Tools::CENTRE_VIEW, + Tools::INSPECT_POINT }); - tools_->addCallback([this](ftl::gui2::CameraTools tool) { + tools_->addCallback([this](ftl::gui2::Tools tool) { switch (tool) { - case CameraTools::OVERLAY : ctrl_->toggleOverlay(); return true; - case CameraTools::ZOOM_FIT : imview_->fit(); return true; - case CameraTools::CENTRE_VIEW : imview_->center(); return true; + case Tools::OVERLAY : ctrl_->toggleOverlay(); return true; + case Tools::ZOOM_FIT : imview_->fit(); return true; + case Tools::CENTRE_VIEW : imview_->center(); return true; //case CameraTools::ZOOM_OUT : imview_->zoom(-1, imview_->sizeF() / 2); return true; //case CameraTools::ZOOM_IN : imview_->zoom(1, imview_->sizeF() / 2); return true; default: return false; @@ -668,7 +732,7 @@ void CameraView::setPan(bool v) { bool CameraView::mouseMotionEvent(const Eigen::Vector2i &p, const Eigen::Vector2i &rel, int button, int modifiers) { //if (button == 1) { - if (tools_->activeTool() == CameraTools::SELECT_POINT) { + if (tools_->isActive(Tools::SELECT_POINT)) { auto pos = imview_->imageCoordinateAt((p - mPos + rel).cast<float>()); if (pos.x() >= 0.0f && pos.y() >= 0.0f) { ctrl_->touch(0, ftl::codecs::TouchType::MOUSE_LEFT, pos.x(), pos.y(), 0.0f, (button > 0) ? 255 : 0); @@ -684,14 +748,14 @@ bool CameraView::mouseMotionEvent(const Eigen::Vector2i &p, const Eigen::Vector2 bool CameraView::mouseButtonEvent(const Eigen::Vector2i &p, int button, bool down, int modifiers) { //LOG(INFO) << "mouseButtonEvent: " << p << " - " << button; if (button == 0) { - if (tools_->activeTool() == CameraTools::SELECT_POINT) { + if (tools_->isActive(Tools::SELECT_POINT)) { auto pos = imview_->imageCoordinateAt((p - mPos).cast<float>()); if (pos.x() >= 0.0f && pos.y() >= 0.0f) { ctrl_->touch(0, ftl::codecs::TouchType::MOUSE_LEFT, pos.x(), pos.y(), 0.0f, (down) ? 255 : 0); } - } else if (tools_->activeTool() == CameraTools::ZOOM_IN) { + } else if (tools_->isActive(Tools::ZOOM_IN)) { imview_->zoom(1, p.cast<float>()); - } else if (tools_->activeTool() == CameraTools::ZOOM_OUT) { + } else if (tools_->isActive(Tools::ZOOM_OUT)) { imview_->zoom(-1, p.cast<float>()); } @@ -729,7 +793,7 @@ void CameraView::draw(NVGcontext*ctx) { auto osize = imview_->scaledImageSizeF(); ctrl_->drawOverlay(ctx, screen()->size().cast<float>(), osize, imview_->offset()); - if (tools_->activeTool() == CameraTools::INSPECT_POINT) { + if (tools_->isActive(Tools::INSPECT_POINT)) { auto mouse = screen()->mousePos(); auto pos = imview_->imageCoordinateAt((mouse - mPos).cast<float>()); float d = ctrl_->depthAt(pos.x(), pos.y()); diff --git a/applications/gui2/src/views/camera.hpp b/applications/gui2/src/views/camera.hpp index da1dc3db7a2460868b27918c6b35da8636a4519c..179f4eff2c2bdc49140051ef27ceafdbf385f6ed 100644 --- a/applications/gui2/src/views/camera.hpp +++ b/applications/gui2/src/views/camera.hpp @@ -18,38 +18,44 @@ class MediaPanel; class CameraView; +struct ToolGroupData { + nanogui::Button::Flags type; + std::unordered_set<ftl::gui2::Tools> active; + std::unordered_set<ftl::gui2::Tools> tools; +}; + class ToolPanel : public FixedWindow { public: ToolPanel(nanogui::Widget *parent, Camera* ctrl, CameraView* view); virtual ~ToolPanel(); - void setAvailable(const std::unordered_set<ftl::gui2::CameraTools> &); - void setEnabled(const std::unordered_set<ftl::gui2::CameraTools> &); - void enable(const std::unordered_set<ftl::gui2::CameraTools> &); - void disable(const std::unordered_set<ftl::gui2::CameraTools> &); + void setAvailable(const std::unordered_set<ftl::gui2::Tools> &); + void setEnabled(const std::unordered_set<ftl::gui2::Tools> &); + void enable(const std::unordered_set<ftl::gui2::Tools> &); + void disable(const std::unordered_set<ftl::gui2::Tools> &); void draw(NVGcontext *ctx) override; - /** add button to position. */ - nanogui::Button* addButton(int position = -1); - - inline ftl::gui2::CameraTools activeTool() const { return active_; } - void setTool(ftl::gui2::CameraTools tool); + //inline ftl::gui2::Tools activeTool() const { return active_; } + bool isActive(ftl::gui2::Tools); + void setTool(ftl::gui2::Tools tool); - inline void addCallback(const std::function<bool(ftl::gui2::CameraTools)> &cb) { callbacks_.push_back(cb); } + inline void addCallback(const std::function<bool(ftl::gui2::Tools)> &cb) { callbacks_.push_back(cb); } private: Camera* ctrl_; CameraView* view_; nanogui::Widget *container_; - std::unordered_map<ftl::gui2::CameraTools, nanogui::Button*> buttons_; - ftl::gui2::CameraTools active_ = ftl::gui2::CameraTools::NONE; + std::unordered_map<ftl::gui2::Tools, nanogui::Button*> buttons_; + std::unordered_map<ftl::gui2::ToolGroup, ftl::gui2::ToolGroupData> group_data_; + std::unordered_map<ftl::gui2::Tools, ftl::gui2::ToolGroup> group_map_; - std::list<std::function<bool(ftl::gui2::CameraTools)>> callbacks_; + std::list<std::function<bool(ftl::gui2::Tools)>> callbacks_; - void _addButton(ftl::gui2::CameraTools, int icon, const std::string &tooltip); - void _addButton(ftl::gui2::PopupButton *parent, ftl::gui2::CameraTools, const std::string &label); - ftl::gui2::PopupButton *_addButton(std::unordered_set<ftl::gui2::CameraTools> tools, int icon, const std::string &tooltip); + nanogui::Widget *_addGroup(ftl::gui2::ToolGroup group, nanogui::Button::Flags type, const std::unordered_set<ftl::gui2::Tools> &tools); + void _addButton(nanogui::Widget *, ftl::gui2::Tools, int icon, const std::string &tooltip); + void _addButton(ftl::gui2::PopupButton *parent, ftl::gui2::Tools, const std::string &label); + ftl::gui2::PopupButton *_addButton(nanogui::Widget *, std::unordered_set<ftl::gui2::Tools> tools, int icon, const std::string &tooltip); public: EIGEN_MAKE_ALIGNED_OPERATOR_NEW diff --git a/applications/gui2/src/views/camera3d.cpp b/applications/gui2/src/views/camera3d.cpp index 3af17ba6c6a7533705a609d2a0e35f710ab920da..29bb0ae4d82b0599dfa0ddd44bee6bb0ac51d676 100644 --- a/applications/gui2/src/views/camera3d.cpp +++ b/applications/gui2/src/views/camera3d.cpp @@ -36,24 +36,30 @@ CameraView3D::CameraView3D(ftl::gui2::Screen *parent, ftl::gui2::Camera *ctrl) : pose_up_to_date_.test_and_set(); tools_->setAvailable({ - CameraTools::SELECT_POINT, - CameraTools::MOVEMENT, - CameraTools::OVERLAY, - CameraTools::INSPECT_POINT, - CameraTools::CLIPPING, - CameraTools::MOVE_CURSOR, - CameraTools::ORIGIN_TO_CURSOR, + Tools::SELECT_POINT, + Tools::MOVEMENT, + Tools::OVERLAY, + Tools::INSPECT_POINT, + Tools::CLIPPING, + Tools::MOVE_CURSOR, + Tools::ORIGIN_TO_CURSOR, + Tools::RESET_ORIGIN, + Tools::SAVE_CURSOR }); setZoom(false); setPan(false); - tools_->setTool(CameraTools::MOVEMENT); + tools_->setTool(Tools::MOVEMENT); - tools_->addCallback([this](ftl::gui2::CameraTools tool) { - if (tool == CameraTools::ORIGIN_TO_CURSOR) { + tools_->addCallback([this](ftl::gui2::Tools tool) { + if (tool == Tools::ORIGIN_TO_CURSOR) { ctrl_->setOriginToCursor(); - tools_->setTool(CameraTools::MOVEMENT); + tools_->setTool(Tools::MOVEMENT); + return true; + } else if (tool == Tools::RESET_ORIGIN) { + ctrl_->resetOrigin(); + tools_->setTool(Tools::MOVEMENT); return true; } return false; @@ -87,16 +93,16 @@ bool CameraView3D::keyboardEvent(int key, int scancode, int action, int modifier bool CameraView3D::mouseButtonEvent(const Eigen::Vector2i &p, int button, bool down, int modifiers) { if (button == 0 && !down) { - if (tools_->activeTool() == CameraTools::MOVE_CURSOR) { + if (tools_->isActive(Tools::MOVE_CURSOR)) { auto mouse = screen()->mousePos(); auto pos = imview_->imageCoordinateAt((mouse - mPos).cast<float>()); //Eigen::Vector3f world = ctrl_->worldAt(pos.x(), pos.y()); ctrl_->setCursor(pos.x(), pos.y()); - tools_->setTool(CameraTools::ROTATE_CURSOR); + tools_->setTool(Tools::ROTATE_CURSOR); return true; - } else if (tools_->activeTool() == CameraTools::ROTATE_CURSOR) { - tools_->setTool(CameraTools::MOVE_CURSOR); + } else if (tools_->isActive(Tools::ROTATE_CURSOR)) { + tools_->setTool(Tools::MOVEMENT); } } @@ -108,12 +114,12 @@ bool CameraView3D::mouseMotionEvent(const Eigen::Vector2i &p, const Eigen::Vecto // return true; //} - if (button == 1 && tools_->activeTool() == CameraTools::MOVEMENT) { + if (button == 1 && tools_->isActive(Tools::MOVEMENT)) { rx_ += rel[0]; ry_ += rel[1]; pose_up_to_date_.clear(); return true; - } else if (tools_->activeTool() == CameraTools::ROTATE_CURSOR) { + } else if (tools_->isActive(Tools::ROTATE_CURSOR)) { auto mouse = screen()->mousePos(); auto pos = imview_->imageCoordinateAt((mouse - mPos).cast<float>());