This example shows how to enhance the default Easy3D viewer with menus using ImGui.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27#ifndef EASY3D_TUTORIAL_VIEWER_IMGUI_H
28#define EASY3D_TUTORIAL_VIEWER_IMGUI_H
29
30
31#include <easy3d/viewer/viewer.h>
32
33
34
35
36
37
38
39
40struct ImGuiContext;
41
42
44
45 class ViewerImGui : public Viewer
46 {
47 public:
61 explicit ViewerImGui(
62 const std::string& title = "Easy3D ViewerImGui",
63 int samples = 4,
64 int gl_major = 3,
65 int gl_minor = 2,
66 bool full_screen = false,
67 bool resizable = true,
68 int depth_bits = 24,
69 int stencil_bits = 8,
70 int width = 800,
71 int height = 600
72 );
73
77 ~ViewerImGui() override;
78
79 protected:
80
81
82 void init() override;
83
84
85 void pre_draw() override;
86
87
88 void post_draw() override;
89
90 void post_resize(int w, int h) override;
91
92 bool callback_event_cursor_pos(double x, double y) override;
93 bool callback_event_mouse_button(int button, int action, int modifiers) override;
94 bool callback_event_keyboard(int key, int action, int modifiers) override;
95 bool callback_event_character(unsigned int codepoint) override;
96 bool callback_event_scroll(double dx, double dy) override;
97
98 void draw_menu_file();
99 void draw_menu_view();
100
101 protected:
102
103
104 float pixel_ratio();
105
106 float widget_scaling() { return dpi_scaling() / pixel_ratio(); }
107
108
109 void reload_font(int font_size = 16);
110
111 protected:
112
113 static ImGuiContext * context_;
114
115 float menu_height_;
116 };
117
118}
119
120#endif
Definition collider.cpp:182
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27#include "viewer.h"
28
29#include <easy3d/util/file_system.h>
30#include <easy3d/core/point_cloud.h>
31#include <easy3d/core/surface_mesh.h>
32#include <easy3d/renderer/text_renderer.h>
33#include <easy3d/renderer/camera.h>
34
35#include <3rd_party/glfw/include/GLFW/glfw3.h>
36
37#include <3rd_party/imgui/misc/fonts/imgui_fonts_droid_sans.h>
38#include <3rd_party/imgui/imgui.h>
39#include <3rd_party/imgui/backends/imgui_impl_glfw.h>
40#include <3rd_party/imgui/backends/imgui_impl_opengl3.h>
41
42
44
45
46
47 ImGuiContext* ViewerImGui::context_ = nullptr;
48
49 ViewerImGui::ViewerImGui(
50 const std::string& title ,
51 int samples ,
52 int gl_major ,
53 int gl_minor ,
54 bool full_screen ,
55 bool resizable ,
56 int depth_bits ,
57 int stencil_bits ,
58 int width ,
59 int height
60 ) : Viewer(title, samples, gl_major, gl_minor, full_screen, resizable, depth_bits, stencil_bits, width, height)
61 {
62#if defined(_WIN32) && defined(_MSC_VER)
63
64
65 glfwInit();
66#endif
67 }
68
69
70 ViewerImGui::~ViewerImGui() {
71 ImGui_ImplOpenGL3_Shutdown();
72 ImGui_ImplGlfw_Shutdown();
73
74 ImGui::DestroyContext(context_);
75
76
77
78 }
79
80
81 void ViewerImGui::init() {
82 Viewer::init();
83
84 if (!context_) {
85
86 IMGUI_CHECKVERSION();
87
88 context_ = ImGui::CreateContext();
89
90 const char* glsl_version = "#version 150";
91 ImGui_ImplGlfw_InitForOpenGL(window_, true);
92 ImGui_ImplOpenGL3_Init(glsl_version);
93 ImGuiIO& io = ImGui::GetIO();
94 io.WantCaptureKeyboard = true;
95 io.WantTextInput = true;
96 io.IniFilename = nullptr;
97 ImGui::StyleColorsLight();
98 ImGuiStyle& style = ImGui::GetStyle();
99 style.FrameRounding = 5.0f;
100
101
102 reload_font();
103 }
104 }
105
106
107 float ViewerImGui::pixel_ratio() {
108
109 int fw = framebuffer_width();
110 int vw = width();
111 return static_cast<float>(fw) / static_cast<float>(vw);
112 }
113
114
115 void ViewerImGui::reload_font(int font_size)
116 {
117 ImGuiIO& io = ImGui::GetIO();
118 io.Fonts->Clear();
119 io.Fonts->AddFontFromMemoryCompressedTTF(droid_sans_compressed_data, droid_sans_compressed_size, static_cast<float>(font_size) * dpi_scaling());
120 io.FontGlobalScale = 1.0f / pixel_ratio();
121 ImGui_ImplOpenGL3_DestroyDeviceObjects();
122 }
123
124
125 void ViewerImGui::post_resize(int w, int h) {
126 Viewer::post_resize(w, h);
127 if (context_) {
128 ImGui::GetIO().DisplaySize.x = float(w);
129 ImGui::GetIO().DisplaySize.y = float(h);
130 }
131 }
132
133
134 bool ViewerImGui::callback_event_cursor_pos(double x, double y) {
135 if (ImGui::GetIO().WantCaptureMouse)
136 return true;
137 return Viewer::callback_event_cursor_pos(x, y);
138 }
139
140
141 bool ViewerImGui::callback_event_mouse_button(int button, int action, int modifiers) {
142 if (ImGui::GetIO().WantCaptureMouse)
143 return true;
144 return Viewer::callback_event_mouse_button(button, action, modifiers);
145 }
146
147
148 bool ViewerImGui::callback_event_keyboard(int key, int action, int modifiers) {
149 if (ImGui::GetIO().WantCaptureKeyboard)
150 return true;
151 return Viewer::callback_event_keyboard(key, action, modifiers);
152 }
153
154
155 bool ViewerImGui::callback_event_character(unsigned int codepoint) {
156 if (ImGui::GetIO().WantCaptureKeyboard)
157 return true;
158 return Viewer::callback_event_character(codepoint);
159 }
160
161
162 bool ViewerImGui::callback_event_scroll(double dx, double dy) {
163 if (ImGui::GetIO().WantCaptureMouse)
164 return true;
165 return Viewer::callback_event_scroll(dx, dy);
166 }
167
168
169 void ViewerImGui::pre_draw() {
170 ImGui_ImplGlfw_NewFrame();
171 ImGui_ImplOpenGL3_NewFrame();
172 ImGui::NewFrame();
173
174 Viewer::pre_draw();
175 }
176
177
178 void ViewerImGui::post_draw() {
179 static bool show_about = false;
180 if (show_about) {
181 ImGui::SetNextWindowPos(ImVec2(static_cast<float>(width()) * 0.5f, static_cast<float>(height()) * 0.5f), ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
182 ImGui::Begin("About Easy3D ImGui Viewer", &show_about, ImGuiWindowFlags_NoResize);
183 ImGui::Text("This viewer shows how to use ImGui for GUI creation and event handling");
184 ImGui::Separator();
185 ImGui::Text(
186 "\n"
187 "Liangliang Nan\n"
188 "liangliang.nan@gmail.com\n"
189 "https://3d.bk.tudelft.nl/liangliang/\n"
190 );
191 ImGui::End();
192 }
193
194 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(5, 8));
195 if (ImGui::BeginMainMenuBar())
196 {
197 draw_menu_file();
198 draw_menu_view();
199
200 if (ImGui::BeginMenu("Help")) {
201 ImGui::MenuItem("About", nullptr, &show_about);
202 ImGui::EndMenu();
203 }
204 menu_height_ = ImGui::GetWindowHeight();
205 ImGui::EndMainMenuBar();
206 }
207 ImGui::PopStyleVar();
208
209 ImGui::Render();
210 ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
211
212
213 auto show_logo = show_easy3d_logo_;
214 auto show_fps = show_frame_rate_;
215 show_easy3d_logo_ = false;
216 show_frame_rate_ = false;
217 Viewer::post_draw();
218 show_easy3d_logo_ = show_logo;
219 show_frame_rate_ = show_fps;
220
221
222 if (texter_) {
223 const float font_size = 15.0f;
224 const float offset_x = (width() - texter_->string_width("Easy3D", font_size) - 50.0f) * dpi_scaling();
225 if (show_easy3d_logo_) {
226 const float offset_y = (20.0f + menu_height_) * dpi_scaling();
227 texter_->draw("Easy3D", offset_x, offset_y, font_size, 0);
228 }
229
230
231 if (show_frame_rate_) {
232 const float offset_y = (50.0f + menu_height_) * dpi_scaling();
233 texter_->draw(framerate_, offset_x, offset_y, font_size, 1);
234 }
235 }
236 }
237
238
239 void ViewerImGui::draw_menu_file() {
240 if (ImGui::BeginMenu("File"))
241 {
242 if (ImGui::MenuItem("Open", "Ctrl+O"))
243 open();
244 if (ImGui::MenuItem("Save As...", "Ctrl+S"))
245 save();
246
247 ImGui::Separator();
248 if (ImGui::MenuItem("Quit", "Alt+F4"))
249 glfwSetWindowShouldClose(window_, GLFW_TRUE);
250
251 ImGui::EndMenu();
252 }
253 }
254
255
256 void ViewerImGui::draw_menu_view() {
257 if (ImGui::BeginMenu("View"))
258 {
259 if (ImGui::MenuItem("Snapshot", nullptr))
260 snapshot();
261
262 ImGui::EndMenu();
263 }
264 }
265
266
267
268}