SelectionWidget.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2022 Alec Jacobson <[email protected]>
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public License
  6. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  7. // obtain one at http://mozilla.org/MPL/2.0/.
  8. #include "SelectionWidget.h"
  9. #include <imgui.h>
  10. #include <backends/imgui_impl_glfw.h>
  11. #include <backends/imgui_impl_opengl3.h>
  12. #include <imgui_fonts_droid_sans.h>
  13. #include <GLFW/glfw3.h>
  14. #include "../../../PI.h"
  15. namespace igl{ namespace opengl{ namespace glfw{ namespace imgui{
  16. IGL_INLINE void SelectionWidget::init(Viewer *_viewer, ImGuiPlugin *_plugin)
  17. {
  18. ImGuiWidget::init(_viewer,_plugin);
  19. std::cout<<R"(
  20. igl::opengl::glfw::imgui::SelectionWidget usage:
  21. [drag] Draw a 2D selection
  22. l Turn on and toggle between lasso and polygonal lasso tool
  23. M,m Turn on and toggle between rectangular and circular marquee tool
  24. V,v Turn off interactive selection
  25. )";
  26. }
  27. IGL_INLINE void SelectionWidget::draw()
  28. {
  29. if(mode == OFF){ return; }
  30. // Is this call necessary?
  31. ImGui::GetIO();
  32. float width, height;
  33. float highdpi = 1.0;
  34. {
  35. int fwidth, fheight;
  36. glfwGetFramebufferSize(viewer->window, &fwidth, &fheight);
  37. int iwidth, iheight;
  38. glfwGetWindowSize(viewer->window, &iwidth, &iheight);
  39. highdpi = float(iwidth)/float(fwidth);
  40. // highdpi
  41. width = (float)iwidth;
  42. height = (float)iheight;
  43. }
  44. ImGui::SetNextWindowPos( ImVec2(0,0) );
  45. ImGui::SetNextWindowSize(ImVec2(width,height), ImGuiCond_Always);
  46. ImGui::Begin("testing", nullptr,
  47. ImGuiWindowFlags_NoBackground
  48. | ImGuiWindowFlags_NoTitleBar
  49. | ImGuiWindowFlags_NoResize
  50. | ImGuiWindowFlags_NoMove
  51. | ImGuiWindowFlags_NoScrollbar
  52. | ImGuiWindowFlags_NoSavedSettings
  53. | ImGuiWindowFlags_NoInputs);
  54. ImDrawList* list = ImGui::GetWindowDrawList();
  55. for(int pass = 0;pass<2;pass++)
  56. {
  57. for(auto & p : L)
  58. {
  59. list->PathLineTo({ highdpi*p(0),height-highdpi*p(1) });
  60. }
  61. const bool closed = !(mode==LASSO || mode==POLYGONAL_LASSO) || !(is_down || is_drawing);
  62. if(pass == 0)
  63. {
  64. list->PathStroke(IM_COL32(255, 255, 255, 255), closed, 2);
  65. }else
  66. {
  67. list->PathStroke(IM_COL32(0, 0, 0, 255), closed, 1);
  68. }
  69. }
  70. ImGui::End();
  71. ImGui::Render();
  72. ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
  73. }
  74. IGL_INLINE bool SelectionWidget::mouse_down(int /*button*/, int modifier)
  75. {
  76. if(mode == OFF || (modifier & IGL_MOD_ALT) ){ return false;}
  77. is_down = true;
  78. has_moved_since_down = false;
  79. if(!is_drawing)
  80. {
  81. L.clear();
  82. is_drawing = true;
  83. }
  84. M.row(0) = xy(viewer);
  85. M.row(1) = M.row(0);
  86. L.emplace_back(M.row(0));
  87. return true;
  88. }
  89. IGL_INLINE bool SelectionWidget::mouse_up(int /*button*/, int /*modifier*/)
  90. {
  91. is_down = false;
  92. // are we done? Check first and last lasso point (need at least 3 (2 real
  93. // points + 1 mouse-mouse point))
  94. if(is_drawing &&
  95. (mode!=POLYGONAL_LASSO ||(L.size()>=3&&(L[0]-L[L.size()-1]).norm()<=10.0)))
  96. {
  97. if(callback){ callback();}
  98. is_drawing = false;
  99. }
  100. return false;
  101. }
  102. IGL_INLINE bool SelectionWidget::mouse_move(int /*mouse_x*/, int /*mouse_y*/)
  103. {
  104. if(!is_drawing){ return false; }
  105. if(!has_moved_since_down)
  106. {
  107. if(mode == POLYGONAL_LASSO) { L.emplace_back(L[L.size()-1]); }
  108. has_moved_since_down = true;
  109. }
  110. M.row(1) = xy(viewer);
  111. switch(mode)
  112. {
  113. case RECTANGULAR_MARQUEE:
  114. rect(M,L);
  115. break;
  116. case ELLIPTICAL_MARQUEE:
  117. circle(M,L);
  118. break;
  119. case POLYGONAL_LASSO:
  120. // Over write last point
  121. L[L.size()-1] = xy(viewer);
  122. break;
  123. case LASSO:
  124. L.emplace_back(xy(viewer));
  125. break;
  126. default: assert(false);
  127. }
  128. return true;
  129. }
  130. IGL_INLINE bool SelectionWidget::key_pressed(unsigned int key, int /*modifiers*/)
  131. {
  132. Mode old = mode;
  133. if(OFF_KEY.find(char(key)) != std::string::npos)
  134. {
  135. mode = OFF;
  136. }else if(LASSO_KEY.find(char(key)) != std::string::npos)
  137. {
  138. if(mode == LASSO)
  139. {
  140. mode = POLYGONAL_LASSO;
  141. }else/*if(mode == POLYGONAL_LASSO)*/
  142. {
  143. mode = LASSO;
  144. }
  145. }else if(MARQUEE_KEY.find(char(key)) != std::string::npos)
  146. {
  147. if(mode == RECTANGULAR_MARQUEE)
  148. {
  149. mode = ELLIPTICAL_MARQUEE;
  150. }else/*if(mode == ELLIPTICAL_MARQUEE)*/
  151. {
  152. mode = RECTANGULAR_MARQUEE;
  153. }
  154. }
  155. if(old != mode)
  156. {
  157. clear();
  158. if(callback_post_mode_change){ callback_post_mode_change(old); }
  159. return true;
  160. }
  161. return false;
  162. }
  163. IGL_INLINE void SelectionWidget::clear()
  164. {
  165. M.setZero();
  166. L.clear();
  167. is_drawing = false;
  168. is_down = false;
  169. };
  170. IGL_INLINE void SelectionWidget::circle(const Eigen::Matrix<float,2,2> & M, std::vector<Eigen::RowVector2f> & L)
  171. {
  172. L.clear();
  173. L.reserve(64);
  174. const float r = (M.row(1)-M.row(0)).norm();
  175. for(float th = 0;th<2.*igl::PI;th+=0.1)
  176. {
  177. L.emplace_back(M(0,0)+r*cos(th),M(0,1)+r*sin(th));
  178. }
  179. }
  180. IGL_INLINE void SelectionWidget::rect(const Eigen::Matrix<float,2,2> & M, std::vector<Eigen::RowVector2f> & L)
  181. {
  182. L.resize(4);
  183. L[0] = Eigen::RowVector2f(M(0,0),M(0,1));
  184. L[1] = Eigen::RowVector2f(M(1,0),M(0,1));
  185. L[2] = Eigen::RowVector2f(M(1,0),M(1,1));
  186. L[3] = Eigen::RowVector2f(M(0,0),M(1,1));
  187. }
  188. IGL_INLINE Eigen::RowVector2f SelectionWidget::xy(const Viewer * vr)
  189. {
  190. return Eigen::RowVector2f(
  191. vr->current_mouse_x,
  192. vr->core().viewport(3) - vr->current_mouse_y);
  193. }
  194. }}}}