// This file is part of libigl, a simple c++ geometry processing library. // // Copyright (C) 2022 Alec Jacobson // Copyright (C) 2018 Jérémie Dumas // // 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 "ImGuiMenu.h" #include "ImGuiHelpers.h" #include #include namespace igl { namespace opengl { namespace glfw { namespace imgui { // Is this needed? IGL_INLINE void ImGuiMenu::init( Viewer *_viewer, ImGuiPlugin *_plugin) { viewer = _viewer; plugin = _plugin; } IGL_INLINE void ImGuiMenu::shutdown() { } IGL_INLINE void ImGuiMenu::draw() { // Viewer settings if (callback_draw_viewer_window) { callback_draw_viewer_window(); } else { draw_viewer_window(); } // Other windows if (callback_draw_custom_window) { callback_draw_custom_window(); } else { draw_custom_window(); } } IGL_INLINE void ImGuiMenu::draw_viewer_window() { ImGui::SetNextWindowPos(ImVec2(0.0f, 0.0f), ImGuiCond_FirstUseEver); ImGui::SetNextWindowSize(ImVec2(0.0f, 0.0f), ImGuiCond_FirstUseEver); bool _viewer_menu_visible = true; ImGui::Begin( "Viewer", &_viewer_menu_visible, ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize ); ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.4f); if (callback_draw_viewer_menu) { callback_draw_viewer_menu(); } else { draw_viewer_menu(); } ImGui::PopItemWidth(); ImGui::End(); } IGL_INLINE void ImGuiMenu::draw_viewer_menu() { // Workspace if (ImGui::CollapsingHeader("Workspace", ImGuiTreeNodeFlags_DefaultOpen)) { float w = ImGui::GetContentRegionAvail().x; float p = ImGui::GetStyle().FramePadding.x; if (ImGui::Button("Load##Workspace", ImVec2((w-p)/2.f, 0))) { viewer->load_scene(); } ImGui::SameLine(0, p); if (ImGui::Button("Save##Workspace", ImVec2((w-p)/2.f, 0))) { viewer->save_scene(); } } // Mesh if (ImGui::CollapsingHeader("Mesh", ImGuiTreeNodeFlags_DefaultOpen)) { float w = ImGui::GetContentRegionAvail().x; float p = ImGui::GetStyle().FramePadding.x; if (ImGui::Button("Load##Mesh", ImVec2((w-p)/2.f, 0))) { viewer->open_dialog_load_mesh(); } ImGui::SameLine(0, p); if (ImGui::Button("Save##Mesh", ImVec2((w-p)/2.f, 0))) { viewer->open_dialog_save_mesh(); } } // Viewing options if (ImGui::CollapsingHeader("Viewing Options", ImGuiTreeNodeFlags_DefaultOpen)) { if (ImGui::Button("Center object", ImVec2(-1, 0))) { viewer->core().align_camera_center(viewer->data().V, viewer->data().F); } if (ImGui::Button("Snap canonical view", ImVec2(-1, 0))) { viewer->snap_to_canonical_quaternion(); } // Zoom ImGui::PushItemWidth(80 * menu_scaling()); ImGui::DragFloat("Zoom", &(viewer->core().camera_zoom), 0.05f, 0.1f, 20.0f); // Select rotation type int rotation_type = static_cast(viewer->core().rotation_type); static Eigen::Quaternionf trackball_angle = Eigen::Quaternionf::Identity(); static bool orthographic = true; if (ImGui::Combo("Camera Type", &rotation_type, "Trackball\0Two Axes\0002D Mode\0\0")) { using RT = igl::opengl::ViewerCore::RotationType; auto new_type = static_cast(rotation_type); if (new_type != viewer->core().rotation_type) { if (new_type == RT::ROTATION_TYPE_NO_ROTATION) { trackball_angle = viewer->core().trackball_angle; orthographic = viewer->core().orthographic; viewer->core().trackball_angle = Eigen::Quaternionf::Identity(); viewer->core().orthographic = true; } else if (viewer->core().rotation_type == RT::ROTATION_TYPE_NO_ROTATION) { viewer->core().trackball_angle = trackball_angle; viewer->core().orthographic = orthographic; } viewer->core().set_rotation_type(new_type); } } // Orthographic view ImGui::Checkbox("Orthographic view", &(viewer->core().orthographic)); ImGui::PopItemWidth(); } // Helper for setting viewport specific mesh options auto make_checkbox = [&](const char *label, unsigned int &option) { return ImGui::Checkbox(label, [&]() { return viewer->core().is_set(option); }, [&](bool value) { return viewer->core().set(option, value); } ); }; // Draw options if (ImGui::CollapsingHeader("Draw Options", ImGuiTreeNodeFlags_DefaultOpen)) { if (ImGui::Checkbox("Face-based", &(viewer->data().face_based))) { viewer->data().dirty = MeshGL::DIRTY_ALL; } make_checkbox("Show texture", viewer->data().show_texture); if (ImGui::Checkbox("Invert normals", &(viewer->data().invert_normals))) { viewer->data().dirty |= igl::opengl::MeshGL::DIRTY_NORMAL; } make_checkbox("Show overlay", viewer->data().show_overlay); make_checkbox("Show overlay depth", viewer->data().show_overlay_depth); ImGui::ColorEdit4("Background", viewer->core().background_color.data(), ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_PickerHueWheel); ImGui::ColorEdit4("Line color", viewer->data().line_color.data(), ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_PickerHueWheel); ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.3f); ImGui::DragFloat("Shininess", &(viewer->data().shininess), 0.05f, 0.0f, 100.0f); ImGui::PopItemWidth(); } // Overlays if (ImGui::CollapsingHeader("Overlays", ImGuiTreeNodeFlags_DefaultOpen)) { make_checkbox("Wireframe", viewer->data().show_lines); make_checkbox("Fill", viewer->data().show_faces); make_checkbox("Show vertex labels", viewer->data().show_vertex_labels); make_checkbox("Show faces labels", viewer->data().show_face_labels); make_checkbox("Show extra labels", viewer->data().show_custom_labels); } } } // end namespace } // end namespace } // end namespace } // end namespace