You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
214 lines
5.4 KiB
214 lines
5.4 KiB
// This file is part of libigl, a simple c++ geometry processing library.
|
|
//
|
|
// Copyright (C) 2022 Alec Jacobson <alecjacobson@gmail.com>
|
|
//
|
|
// This Source Code Form is subject to the terms of the Mozilla Public License
|
|
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
|
// obtain one at http://mozilla.org/MPL/2.0/.
|
|
#include "SelectionWidget.h"
|
|
|
|
#include <imgui.h>
|
|
#include <backends/imgui_impl_glfw.h>
|
|
#include <backends/imgui_impl_opengl3.h>
|
|
#include <imgui_fonts_droid_sans.h>
|
|
#include <GLFW/glfw3.h>
|
|
#include "../../../PI.h"
|
|
|
|
namespace igl{ namespace opengl{ namespace glfw{ namespace imgui{
|
|
|
|
IGL_INLINE void SelectionWidget::init(Viewer *_viewer, ImGuiPlugin *_plugin)
|
|
{
|
|
ImGuiWidget::init(_viewer,_plugin);
|
|
std::cout<<R"(
|
|
igl::opengl::glfw::imgui::SelectionWidget usage:
|
|
[drag] Draw a 2D selection
|
|
l Turn on and toggle between lasso and polygonal lasso tool
|
|
M,m Turn on and toggle between rectangular and circular marquee tool
|
|
V,v Turn off interactive selection
|
|
)";
|
|
}
|
|
IGL_INLINE void SelectionWidget::draw()
|
|
{
|
|
if(mode == OFF){ return; }
|
|
ImGuiIO& io = ImGui::GetIO();
|
|
|
|
float width, height;
|
|
float highdpi = 1.0;
|
|
{
|
|
int fwidth, fheight;
|
|
glfwGetFramebufferSize(viewer->window, &fwidth, &fheight);
|
|
int iwidth, iheight;
|
|
glfwGetWindowSize(viewer->window, &iwidth, &iheight);
|
|
highdpi = float(iwidth)/float(fwidth);
|
|
// highdpi
|
|
width = (float)iwidth;
|
|
height = (float)iheight;
|
|
}
|
|
|
|
ImGui::SetNextWindowPos( ImVec2(0,0) );
|
|
ImGui::SetNextWindowSize(ImVec2(width,height), ImGuiCond_Always);
|
|
|
|
ImGui::Begin("testing", nullptr,
|
|
ImGuiWindowFlags_NoBackground
|
|
| ImGuiWindowFlags_NoTitleBar
|
|
| ImGuiWindowFlags_NoResize
|
|
| ImGuiWindowFlags_NoMove
|
|
| ImGuiWindowFlags_NoScrollbar
|
|
| ImGuiWindowFlags_NoSavedSettings
|
|
| ImGuiWindowFlags_NoInputs);
|
|
|
|
ImDrawList* list = ImGui::GetWindowDrawList();
|
|
for(int pass = 0;pass<2;pass++)
|
|
{
|
|
for(auto & p : L)
|
|
{
|
|
list->PathLineTo({ highdpi*p(0),height-highdpi*p(1) });
|
|
}
|
|
const bool closed = !(mode==LASSO || mode==POLYGONAL_LASSO) || !(is_down || is_drawing);
|
|
if(pass == 0)
|
|
{
|
|
list->PathStroke(IM_COL32(255, 255, 255, 255), closed, 2);
|
|
}else
|
|
{
|
|
list->PathStroke(IM_COL32(0, 0, 0, 255), closed, 1);
|
|
}
|
|
}
|
|
|
|
ImGui::End();
|
|
|
|
ImGui::Render();
|
|
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
|
|
|
}
|
|
|
|
IGL_INLINE bool SelectionWidget::mouse_down(int button, int modifier)
|
|
{
|
|
if(mode == OFF || (modifier & IGL_MOD_ALT) ){ return false;}
|
|
is_down = true;
|
|
has_moved_since_down = false;
|
|
if(!is_drawing)
|
|
{
|
|
L.clear();
|
|
is_drawing = true;
|
|
}
|
|
M.row(0) = xy(viewer);
|
|
M.row(1) = M.row(0);
|
|
L.emplace_back(M.row(0));
|
|
return true;
|
|
}
|
|
|
|
IGL_INLINE bool SelectionWidget::mouse_up(int button, int modifier)
|
|
{
|
|
is_down = false;
|
|
// are we done? Check first and last lasso point (need at least 3 (2 real
|
|
// points + 1 mouse-mouse point))
|
|
if(is_drawing &&
|
|
(mode!=POLYGONAL_LASSO ||(L.size()>=3&&(L[0]-L[L.size()-1]).norm()<=10.0)))
|
|
{
|
|
if(callback){ callback();}
|
|
is_drawing = false;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
IGL_INLINE bool SelectionWidget::mouse_move(int mouse_x, int mouse_y)
|
|
{
|
|
if(!is_drawing){ return false; }
|
|
if(!has_moved_since_down)
|
|
{
|
|
if(mode == POLYGONAL_LASSO) { L.emplace_back(L[L.size()-1]); }
|
|
has_moved_since_down = true;
|
|
}
|
|
M.row(1) = xy(viewer);
|
|
switch(mode)
|
|
{
|
|
case RECTANGULAR_MARQUEE:
|
|
rect(M,L);
|
|
break;
|
|
case ELLIPTICAL_MARQUEE:
|
|
circle(M,L);
|
|
break;
|
|
case POLYGONAL_LASSO:
|
|
// Over write last point
|
|
L[L.size()-1] = xy(viewer);
|
|
break;
|
|
case LASSO:
|
|
L.emplace_back(xy(viewer));
|
|
break;
|
|
default: assert(false);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
IGL_INLINE bool SelectionWidget::key_pressed(unsigned int key, int modifiers)
|
|
{
|
|
Mode old = mode;
|
|
if(OFF_KEY.find(char(key)) != std::string::npos)
|
|
{
|
|
mode = OFF;
|
|
}else if(LASSO_KEY.find(char(key)) != std::string::npos)
|
|
{
|
|
if(mode == LASSO)
|
|
{
|
|
mode = POLYGONAL_LASSO;
|
|
}else/*if(mode == POLYGONAL_LASSO)*/
|
|
{
|
|
mode = LASSO;
|
|
}
|
|
}else if(MARQUEE_KEY.find(char(key)) != std::string::npos)
|
|
{
|
|
if(mode == RECTANGULAR_MARQUEE)
|
|
{
|
|
mode = ELLIPTICAL_MARQUEE;
|
|
}else/*if(mode == ELLIPTICAL_MARQUEE)*/
|
|
{
|
|
mode = RECTANGULAR_MARQUEE;
|
|
}
|
|
}
|
|
if(old != mode)
|
|
{
|
|
clear();
|
|
if(callback_post_mode_change){ callback_post_mode_change(old); }
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
IGL_INLINE void SelectionWidget::clear()
|
|
{
|
|
M.setZero();
|
|
L.clear();
|
|
is_drawing = false;
|
|
is_down = false;
|
|
};
|
|
|
|
IGL_INLINE void SelectionWidget::circle(const Eigen::Matrix<float,2,2> & M, std::vector<Eigen::RowVector2f> & L)
|
|
{
|
|
L.clear();
|
|
L.reserve(64);
|
|
const float r = (M.row(1)-M.row(0)).norm();
|
|
for(float th = 0;th<2.*igl::PI;th+=0.1)
|
|
{
|
|
L.emplace_back(M(0,0)+r*cos(th),M(0,1)+r*sin(th));
|
|
}
|
|
}
|
|
|
|
IGL_INLINE void SelectionWidget::rect(const Eigen::Matrix<float,2,2> & M, std::vector<Eigen::RowVector2f> & L)
|
|
{
|
|
L.resize(4);
|
|
L[0] = Eigen::RowVector2f(M(0,0),M(0,1));
|
|
L[1] = Eigen::RowVector2f(M(1,0),M(0,1));
|
|
L[2] = Eigen::RowVector2f(M(1,0),M(1,1));
|
|
L[3] = Eigen::RowVector2f(M(0,0),M(1,1));
|
|
}
|
|
|
|
IGL_INLINE Eigen::RowVector2f SelectionWidget::xy(const Viewer * vr)
|
|
{
|
|
return Eigen::RowVector2f(
|
|
vr->current_mouse_x,
|
|
vr->core().viewport(3) - vr->current_mouse_y);
|
|
}
|
|
|
|
|
|
|
|
}}}}
|
|
|