mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-20 06:01:16 +00:00
* Remove Unused Project Includes and Forward-Declare Where a Type Is Only Referenced Generated with include-what-you-use and applied conservatively. Only OrcaSlicer's own headers, the ones under src/ and tests/, are removed or forward-declared; standard-library and third-party includes are left alone. An include is removed only when both the Release and the Debug configuration leave it unused, never from inside a conditional block, and never from a file with platform-specific blocks, which only gain includes. Files whose only use of a header sits behind a feature or debug macro (libvgcode's OpenGL ES and marker code, the ARACHNE/TESTS_EXPORT_SVGS debug output) keep their includes. clonable_ptr.hpp gains #pragma once; it had no include guard and was only safe while Config.hpp was its sole includer. * Remove Unused Project Includes From Files With Platform-Specific Code A Linux include-what-you-use run cannot see the code inside _WIN32, __APPLE__ or __linux__ blocks, so its verdict is only taken where nothing the removed header declares, directly or through what it includes, is named inside those blocks. Removals also have to hold in both the Release and Debug configuration and never touch a line inside a conditional block. * Restore the libslic3r Precompiled Header and Direct Includes Lost in the Platform Pass The platform-file pass treated pchheader.hpp as an ordinary header and emptied it, and left GUI_Preview.hpp and 14 other files relying on headers they no longer reached directly. * Restore MainFrame.hpp in ParamsDialog.cpp for the Windows-Only Reparent Call * Include Headers That Files Reached Through Ones the Cleanup Removed * Drop Includes Duplicated by the Cleanup or by Main's Own Additions * Leave PreciseSeam.cpp as Main Has It After the Precise Seam Rework
552 lines
20 KiB
C++
552 lines
20 KiB
C++
#include "GLGizmoBase.hpp"
|
|
#include "slic3r/GUI/GLCanvas3D.hpp"
|
|
|
|
#include <array>
|
|
#include <algorithm>
|
|
#include <cstddef>
|
|
#include <cassert>
|
|
#include <cstdlib>
|
|
#include <glad/gl.h>
|
|
#include "libslic3r/Color.hpp"
|
|
#include "slic3r/GUI/MeshUtils.hpp"
|
|
#include "libslic3r/TriangleMesh.hpp"
|
|
#include "libslic3r/Point.hpp"
|
|
#include <memory>
|
|
#include <utility>
|
|
#include "slic3r/GUI/SceneRaycaster.hpp"
|
|
#include "slic3r/GUI/GLShader.hpp"
|
|
#include "libslic3r/libslic3r.h"
|
|
#include "libslic3r/Geometry.hpp"
|
|
#include <string>
|
|
#include <vector>
|
|
#include <imgui.h>
|
|
#include "slic3r/GUI/OpenGLManager.hpp"
|
|
#include "slic3r/GUI/3DScene.hpp"
|
|
#include "slic3r/GUI/Event.hpp"
|
|
#include "libslic3r/Utils.hpp"
|
|
|
|
#include "slic3r/GUI/GUI_App.hpp"
|
|
#include "slic3r/GUI/Shortcuts.hpp"
|
|
#include "slic3r/GUI/Plater.hpp"
|
|
#include "slic3r/GUI/GUI_Colors.hpp"
|
|
#include "slic3r/GUI/Camera.hpp"
|
|
#include "slic3r/GUI/GLModel.hpp"
|
|
#include "slic3r/GUI/Gizmos/GLGizmosManager.hpp"
|
|
#include "slic3r/GUI/Gizmos/GizmoObjectManipulation.hpp"
|
|
#include "slic3r/GUI/ImGuiWrapper.hpp"
|
|
#include "slic3r/GUI/Selection.hpp"
|
|
|
|
// TODO: Display tooltips quicker on Linux
|
|
|
|
namespace Slic3r {
|
|
namespace GUI {
|
|
|
|
float GLGizmoBase::INV_ZOOM = 1.0f;
|
|
|
|
|
|
const float GLGizmoBase::Grabber::SizeFactor = 0.05f;
|
|
const float GLGizmoBase::Grabber::MinHalfSize = 4.0f;
|
|
const float GLGizmoBase::Grabber::DraggingScaleFactor = 1.25f;
|
|
const float GLGizmoBase::Grabber::FixedGrabberSize = 16.0f;
|
|
const float GLGizmoBase::Grabber::FixedRadiusSize = 80.0f;
|
|
|
|
|
|
ColorRGBA GLGizmoBase::DEFAULT_BASE_COLOR = { 0.625f, 0.625f, 0.625f, 1.0f };
|
|
ColorRGBA GLGizmoBase::DEFAULT_DRAG_COLOR = { 1.0f, 1.0f, 1.0f, 1.0f };
|
|
ColorRGBA GLGizmoBase::DEFAULT_HIGHLIGHT_COLOR = {1.0f, 0.38f, 0.0f, 1.0f};
|
|
std::array<ColorRGBA, 3> GLGizmoBase::AXES_HOVER_COLOR = {{
|
|
{ColorRGBA::X().r() * 1.2f, ColorRGBA::X().g() * 1.4f, ColorRGBA::X().b() * 1.4f, 1.0f},
|
|
{ColorRGBA::Y().r() * 1.2f, ColorRGBA::Y().g() * 1.2f, ColorRGBA::Y().b() * 1.2f, 1.0f},
|
|
{ColorRGBA::Z().r() * 1.2f, ColorRGBA::Z().g() * 1.2f, ColorRGBA::Z().b() * 1.2f, 1.0f},
|
|
}};
|
|
|
|
std::array<ColorRGBA, 3> GLGizmoBase::AXES_COLOR = {{
|
|
ColorRGBA::X(),
|
|
ColorRGBA::Y(),
|
|
ColorRGBA::Z()
|
|
}};
|
|
|
|
ColorRGBA GLGizmoBase::CONSTRAINED_COLOR = {0.5f, 0.5f, 0.5f, 1.0f};
|
|
ColorRGBA GLGizmoBase::FLATTEN_COLOR = {0.96f, 0.93f, 0.93f, 0.5f};
|
|
ColorRGBA GLGizmoBase::FLATTEN_HOVER_COLOR = {1.0f, 1.0f, 1.0f, 0.75f};
|
|
|
|
// new style color
|
|
ColorRGBA GLGizmoBase::GRABBER_NORMAL_COL = {1.0f, 1.0f, 1.0f, 1.0f};
|
|
ColorRGBA GLGizmoBase::GRABBER_HOVER_COL = {0.863f, 0.125f, 0.063f, 1.0f};
|
|
ColorRGBA GLGizmoBase::GRABBER_UNIFORM_COL = {0, 1.0, 1.0, 1.0f};
|
|
ColorRGBA GLGizmoBase::GRABBER_UNIFORM_HOVER_COL = {0, 0.7, 0.7, 1.0f};
|
|
|
|
|
|
void GLGizmoBase::update_render_colors()
|
|
{
|
|
GLGizmoBase::AXES_COLOR = { {
|
|
ImGuiWrapper::from_ImVec4(RenderColor::colors[RenderCol_Grabber_X]),
|
|
ImGuiWrapper::from_ImVec4(RenderColor::colors[RenderCol_Grabber_Y]),
|
|
ImGuiWrapper::from_ImVec4(RenderColor::colors[RenderCol_Grabber_Z])
|
|
} };
|
|
|
|
GLGizmoBase::FLATTEN_COLOR = ImGuiWrapper::from_ImVec4(RenderColor::colors[RenderCol_Flatten_Plane]);
|
|
GLGizmoBase::FLATTEN_HOVER_COLOR = ImGuiWrapper::from_ImVec4(RenderColor::colors[RenderCol_Flatten_Plane_Hover]);
|
|
}
|
|
|
|
void GLGizmoBase::load_render_colors()
|
|
{
|
|
RenderColor::colors[RenderCol_Grabber_X] = ImGuiWrapper::to_ImVec4(GLGizmoBase::AXES_COLOR[0]);
|
|
RenderColor::colors[RenderCol_Grabber_Y] = ImGuiWrapper::to_ImVec4(GLGizmoBase::AXES_COLOR[1]);
|
|
RenderColor::colors[RenderCol_Grabber_Z] = ImGuiWrapper::to_ImVec4(GLGizmoBase::AXES_COLOR[2]);
|
|
RenderColor::colors[RenderCol_Flatten_Plane] = ImGuiWrapper::to_ImVec4(GLGizmoBase::FLATTEN_COLOR);
|
|
RenderColor::colors[RenderCol_Flatten_Plane_Hover] = ImGuiWrapper::to_ImVec4(GLGizmoBase::FLATTEN_HOVER_COLOR);
|
|
}
|
|
|
|
PickingModel GLGizmoBase::Grabber::s_cube;
|
|
PickingModel GLGizmoBase::Grabber::s_cone;
|
|
|
|
GLGizmoBase::Grabber::~Grabber()
|
|
{
|
|
//if (s_cube.model.is_initialized())
|
|
// s_cube.model.reset();
|
|
|
|
//if (s_cone.model.is_initialized())
|
|
// s_cone.model.reset();
|
|
}
|
|
|
|
float GLGizmoBase::Grabber::get_half_size(float size) const
|
|
{
|
|
return std::max(size * SizeFactor, MinHalfSize);
|
|
}
|
|
|
|
float GLGizmoBase::Grabber::get_dragging_half_size(float size) const
|
|
{
|
|
return get_half_size(size) * DraggingScaleFactor;
|
|
}
|
|
|
|
PickingModel &GLGizmoBase::Grabber::get_cube()
|
|
{
|
|
if (!s_cube.model.is_initialized()) {
|
|
// This cannot be done in constructor, OpenGL is not yet
|
|
// initialized at that point (on Linux at least).
|
|
indexed_triangle_set its = its_make_cube(1.0, 1.0, 1.0);
|
|
its_translate(its, -0.5f * Vec3f::Ones());
|
|
s_cube.model.init_from(its);
|
|
s_cube.mesh_raycaster = std::make_unique<MeshRaycaster>(std::make_shared<const TriangleMesh>(std::move(its)));
|
|
}
|
|
return s_cube;
|
|
}
|
|
|
|
void GLGizmoBase::Grabber::register_raycasters_for_picking(int id)
|
|
{
|
|
picking_id = id;
|
|
// registration will happen on next call to render()
|
|
}
|
|
|
|
void GLGizmoBase::Grabber::unregister_raycasters_for_picking()
|
|
{
|
|
wxGetApp().plater()->canvas3D()->remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo, picking_id);
|
|
picking_id = -1;
|
|
raycasters = { nullptr };
|
|
}
|
|
|
|
void GLGizmoBase::Grabber::render(float size, const ColorRGBA& render_color)
|
|
{
|
|
GLShaderProgram* shader = wxGetApp().get_current_shader();
|
|
if (shader == nullptr)
|
|
return;
|
|
|
|
if (!s_cube.model.is_initialized()) {
|
|
// This cannot be done in constructor, OpenGL is not yet
|
|
// initialized at that point (on Linux at least).
|
|
indexed_triangle_set its = its_make_cube(1.0, 1.0, 1.0);
|
|
its_translate(its, -0.5f * Vec3f::Ones());
|
|
s_cube.model.init_from(its);
|
|
s_cube.mesh_raycaster = std::make_unique<MeshRaycaster>(std::make_shared<const TriangleMesh>(std::move(its)));
|
|
}
|
|
|
|
if (!s_cone.model.is_initialized()) {
|
|
indexed_triangle_set its = its_make_cone(1.0, 1.0, double(PI) / 18.0);
|
|
s_cone.model.init_from(its);
|
|
s_cone.mesh_raycaster = std::make_unique<MeshRaycaster>(std::make_shared<const TriangleMesh>(std::move(its)));
|
|
}
|
|
|
|
//BBS set to fixed size grabber
|
|
const float grabber_size = FixedGrabberSize * INV_ZOOM;
|
|
const double extension_size = 0.75 * FixedGrabberSize * INV_ZOOM;
|
|
|
|
s_cube.model.set_color(render_color);
|
|
s_cone.model.set_color(render_color);
|
|
|
|
const Camera& camera = wxGetApp().plater()->get_camera();
|
|
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
|
const Transform3d& view_matrix = camera.get_view_matrix();
|
|
const Matrix3d view_matrix_no_offset = view_matrix.matrix().block(0, 0, 3, 3);
|
|
|
|
auto render_extension = [&view_matrix, &view_matrix_no_offset, shader, this](int idx, PickingModel &model, const Transform3d &model_matrix) {
|
|
shader->set_uniform("view_model_matrix", view_matrix * model_matrix);
|
|
const Matrix3d view_normal_matrix = view_matrix_no_offset * model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose();
|
|
shader->set_uniform("view_normal_matrix", view_normal_matrix);
|
|
model.model.render();
|
|
|
|
if (raycasters[idx] == nullptr) {
|
|
GLCanvas3D &canvas = *wxGetApp().plater()->canvas3D();
|
|
raycasters[idx] = canvas.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, picking_id, *model.mesh_raycaster, model_matrix);
|
|
} else {
|
|
raycasters[idx]->set_transform(model_matrix);
|
|
}
|
|
};
|
|
|
|
if (extensions == EGrabberExtension::PosZ) {
|
|
const Transform3d model_matrix = matrix * Geometry::assemble_transform(center, angles, Vec3d(0.75 * extension_size, 0.75 * extension_size, 2.0 * extension_size));
|
|
render_extension(0, s_cone, model_matrix);
|
|
} else {
|
|
const Transform3d model_matrix = matrix * Geometry::assemble_transform(center, angles, grabber_size * Vec3d::Ones());
|
|
render_extension(0, s_cube, model_matrix);
|
|
|
|
const Transform3d extension_model_matrix_base = matrix * Geometry::assemble_transform(center, angles);
|
|
const Vec3d extension_scale(0.75 * extension_size, 0.75 * extension_size, 3.0 * extension_size);
|
|
if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::PosX)) != 0) {
|
|
render_extension(1, s_cone, extension_model_matrix_base * Geometry::assemble_transform(2.0 * extension_size * Vec3d::UnitX(), Vec3d(0.0, 0.5 * double(PI), 0.0), extension_scale));
|
|
}
|
|
if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::NegX)) != 0) {
|
|
render_extension(2, s_cone, extension_model_matrix_base * Geometry::assemble_transform(-2.0 * extension_size * Vec3d::UnitX(), Vec3d(0.0, -0.5 * double(PI), 0.0), extension_scale));
|
|
}
|
|
if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::PosY)) != 0) {
|
|
render_extension(3, s_cone, extension_model_matrix_base * Geometry::assemble_transform(2.0 * extension_size * Vec3d::UnitY(), Vec3d(-0.5 * double(PI), 0.0, 0.0), extension_scale));
|
|
}
|
|
if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::NegY)) != 0) {
|
|
render_extension(4, s_cone, extension_model_matrix_base * Geometry::assemble_transform(-2.0 * extension_size * Vec3d::UnitY(), Vec3d(0.5 * double(PI), 0.0, 0.0), extension_scale));
|
|
}
|
|
if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::PosZ)) != 0) {
|
|
render_extension(5, s_cone, extension_model_matrix_base * Geometry::assemble_transform(2.0 * extension_size * Vec3d::UnitZ(), Vec3d::Zero(), extension_scale));
|
|
}
|
|
if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::NegZ)) != 0) {
|
|
render_extension(6, s_cone, extension_model_matrix_base * Geometry::assemble_transform(-2.0 * extension_size * Vec3d::UnitZ(), Vec3d(double(PI), 0.0, 0.0), extension_scale));
|
|
}
|
|
}
|
|
}
|
|
|
|
bool GLGizmoBase::render_combo(const std::string &label, const std::vector<std::string> &lines, int &selection_idx, float label_width, float item_width)
|
|
{
|
|
ImGuiWrapper::push_combo_style(m_parent.get_scale());
|
|
ImGui::AlignTextToFramePadding();
|
|
m_imgui->text(label);
|
|
ImGui::SameLine(label_width);
|
|
ImGui::PushItemWidth(item_width);
|
|
|
|
size_t selection_out = selection_idx;
|
|
|
|
const char *selected_str = (selection_idx >= 0 && selection_idx < int(lines.size())) ? lines[selection_idx].c_str() : "";
|
|
if (ImGui::BBLBeginCombo(("##" + label).c_str(), selected_str, 0)) {
|
|
for (size_t line_idx = 0; line_idx < lines.size(); ++line_idx) {
|
|
ImGui::PushID(int(line_idx));
|
|
if (ImGui::Selectable("", line_idx == selection_idx)) selection_out = line_idx;
|
|
|
|
ImGui::SameLine();
|
|
ImGui::Text("%s", lines[line_idx].c_str());
|
|
ImGui::PopID();
|
|
}
|
|
|
|
ImGui::EndCombo();
|
|
}
|
|
|
|
bool is_changed = selection_idx != selection_out;
|
|
selection_idx = selection_out;
|
|
|
|
//if (is_changed) update_connector_shape();
|
|
ImGuiWrapper::pop_combo_style();
|
|
|
|
return is_changed;
|
|
}
|
|
|
|
void GLGizmoBase::render_cross_mark(const Vec3f &target, bool is_single)
|
|
{
|
|
const float half_length = 4.0f;
|
|
|
|
// ORCA: OpenGL Core Profile
|
|
#if !SLIC3R_OPENGL_ES
|
|
if (!OpenGLManager::get_gl_info().is_core_profile())
|
|
glsafe(::glLineWidth(2.0f));
|
|
#endif // !SLIC3R_OPENGL_ES
|
|
|
|
auto render_line = [](const Vec3f& p1, const Vec3f& p2, const ColorRGBA& color) {
|
|
GLModel::Geometry init_data;
|
|
init_data.format = {GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3};
|
|
init_data.color = color;
|
|
init_data.reserve_vertices(2);
|
|
init_data.reserve_indices(2);
|
|
|
|
// vertices
|
|
init_data.add_vertex(p1);
|
|
init_data.add_vertex(p2);
|
|
|
|
// indices
|
|
init_data.add_line(0, 1);
|
|
|
|
GLModel model;
|
|
model.init_from(std::move(init_data));
|
|
model.render();
|
|
};
|
|
|
|
// draw line for x axis
|
|
if (!is_single) {
|
|
render_line(
|
|
{target(0) - half_length, target(1), target(2)},
|
|
{target(0) + half_length, target(1), target(2)},
|
|
ColorRGBA::X()); // ORCA match axis colors
|
|
}
|
|
else {
|
|
render_line(
|
|
{target(0), target(1), target(2)},
|
|
{target(0) + half_length, target(1), target(2)},
|
|
ColorRGBA::X()); // ORCA match axis colors
|
|
}
|
|
// draw line for y axis
|
|
if (!is_single) {
|
|
render_line(
|
|
{target(0), target(1) - half_length, target(2)},
|
|
{target(0), target(1) + half_length, target(2)},
|
|
ColorRGBA::Y()); // ORCA match axis colors
|
|
} else {
|
|
render_line(
|
|
{target(0), target(1), target(2)},
|
|
{target(0), target(1) + half_length, target(2)},
|
|
ColorRGBA::Y()); // ORCA match axis colors
|
|
}
|
|
// draw line for z axis
|
|
if (!is_single) {
|
|
render_line(
|
|
{target(0), target(1), target(2) - half_length},
|
|
{target(0), target(1), target(2) + half_length},
|
|
ColorRGBA::Z()); // ORCA match axis colors
|
|
} else {
|
|
render_line(
|
|
{target(0), target(1), target(2)},
|
|
{target(0), target(1), target(2) + half_length},
|
|
ColorRGBA::Z()); // ORCA match axis colors
|
|
}
|
|
}
|
|
|
|
GLGizmoBase::GLGizmoBase(GLCanvas3D &parent, const std::string &icon_filename, unsigned int sprite_id)
|
|
: m_parent(parent)
|
|
, m_group_id(-1)
|
|
, m_state(Off)
|
|
, m_icon_filename(icon_filename)
|
|
, m_sprite_id(sprite_id)
|
|
, m_imgui(wxGetApp().imgui())
|
|
{
|
|
}
|
|
|
|
|
|
std::string GLGizmoBase::get_action_snapshot_name() const
|
|
{
|
|
return "Gizmo action";
|
|
}
|
|
|
|
void GLGizmoBase::set_icon_filename(const std::string &filename) {
|
|
m_icon_filename = filename;
|
|
}
|
|
|
|
void GLGizmoBase::set_hover_id(int id)
|
|
{
|
|
// do not change hover id during dragging
|
|
assert(!m_dragging);
|
|
|
|
// allow empty grabbers when not using grabbers but use hover_id - flatten, rotate
|
|
// if (!m_grabbers.empty() && id >= (int) m_grabbers.size())
|
|
// return;
|
|
|
|
m_hover_id = id;
|
|
on_set_hover_id();
|
|
}
|
|
|
|
bool GLGizmoBase::update_items_state()
|
|
{
|
|
bool res = m_dirty;
|
|
m_dirty = false;
|
|
return res;
|
|
}
|
|
|
|
bool GLGizmoBase::GizmoImguiBegin(const std::string &name, int flags)
|
|
{
|
|
return m_imgui->begin(name, flags);
|
|
}
|
|
|
|
void GLGizmoBase::GizmoImguiEnd()
|
|
{
|
|
last_input_window_width = ImGui::GetWindowWidth();
|
|
m_imgui->end();
|
|
}
|
|
|
|
void GLGizmoBase::GizmoImguiSetNextWIndowPos(float &x, float y, int flag, float pivot_x, float pivot_y)
|
|
{
|
|
GizmoImguiSetNextWIndowPos(x, y, last_input_window_width, 0, flag, pivot_x, pivot_y);
|
|
}
|
|
|
|
void GLGizmoBase::GizmoImguiSetNextWIndowPos(float &x, float y, float w, float h, int flag, float pivot_x, float pivot_y)
|
|
{
|
|
if (abs(w) > 0.01f) {
|
|
if (x + w > m_parent.get_canvas_size().get_width()) {
|
|
if (w > m_parent.get_canvas_size().get_width()) {
|
|
x = 0;
|
|
} else {
|
|
x = m_parent.get_canvas_size().get_width() - w;
|
|
}
|
|
}
|
|
}
|
|
|
|
m_imgui->set_next_window_pos(x, y, flag, pivot_x, pivot_y);
|
|
}
|
|
|
|
void GLGizmoBase::register_grabbers_for_picking()
|
|
{
|
|
for (size_t i = 0; i < m_grabbers.size(); ++i) {
|
|
m_grabbers[i].register_raycasters_for_picking((m_group_id >= 0) ? m_group_id : i);
|
|
}
|
|
}
|
|
|
|
void GLGizmoBase::unregister_grabbers_for_picking()
|
|
{
|
|
for (size_t i = 0; i < m_grabbers.size(); ++i) {
|
|
m_grabbers[i].unregister_raycasters_for_picking();
|
|
}
|
|
}
|
|
|
|
void GLGizmoBase::render_grabbers(const BoundingBoxf3& box) const
|
|
{
|
|
#if ENABLE_FIXED_GRABBER
|
|
render_grabbers((float)(GLGizmoBase::Grabber::FixedGrabberSize));
|
|
#else
|
|
render_grabbers((float)((box.size().x() + box.size().y() + box.size().z()) / 3.0));
|
|
#endif
|
|
}
|
|
|
|
void GLGizmoBase::render_grabbers(float size) const
|
|
{
|
|
render_grabbers(0, m_grabbers.size() - 1, size, false);
|
|
}
|
|
|
|
void GLGizmoBase::render_grabbers(size_t first, size_t last, float size, bool force_hover) const
|
|
{
|
|
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
|
|
if (shader == nullptr)
|
|
return;
|
|
shader->start_using();
|
|
shader->set_uniform("emission_factor", 0.1f);
|
|
glsafe(::glDisable(GL_CULL_FACE));
|
|
for (size_t i = first; i <= last; ++i) {
|
|
if (m_grabbers[i].enabled)
|
|
m_grabbers[i].render(force_hover ? true : m_hover_id == (int)i, size);
|
|
}
|
|
glsafe(::glEnable(GL_CULL_FACE));
|
|
shader->stop_using();
|
|
}
|
|
|
|
// help function to process grabbers
|
|
// call start_dragging, stop_dragging, on_dragging
|
|
bool GLGizmoBase::use_grabbers(const wxMouseEvent &mouse_event) {
|
|
bool is_dragging_finished = false;
|
|
if (mouse_event.Moving()) {
|
|
// it should not happen but for sure
|
|
assert(!m_dragging);
|
|
if (m_dragging) is_dragging_finished = true;
|
|
else return false;
|
|
}
|
|
|
|
if (mouse_event.LeftDown()) {
|
|
Selection &selection = m_parent.get_selection();
|
|
if (!selection.is_empty() && m_hover_id != -1 /* &&
|
|
(m_grabbers.empty() || m_hover_id < static_cast<int>(m_grabbers.size()))*/) {
|
|
selection.setup_cache();
|
|
|
|
m_dragging = true;
|
|
for (auto &grabber : m_grabbers) grabber.dragging = false;
|
|
// if (!m_grabbers.empty() && m_hover_id < int(m_grabbers.size()))
|
|
// m_grabbers[m_hover_id].dragging = true;
|
|
|
|
on_start_dragging();
|
|
|
|
// Let the plater know that the dragging started
|
|
m_parent.post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_STARTED));
|
|
m_parent.set_as_dirty();
|
|
return true;
|
|
}
|
|
} else if (m_dragging) {
|
|
// when mouse cursor leave window than finish actual dragging operation
|
|
bool is_leaving = mouse_event.Leaving() && !m_parent.has_mouse_capture(); // ORCA keep tracking mouse position while drag active and cursor not in window bounds
|
|
if (mouse_event.Dragging()) {
|
|
Point mouse_coord(mouse_event.GetX(), mouse_event.GetY());
|
|
auto ray = m_parent.mouse_ray(mouse_coord);
|
|
UpdateData data(ray, mouse_coord);
|
|
|
|
on_dragging(data);
|
|
|
|
wxGetApp().obj_manipul()->set_dirty();
|
|
m_parent.set_as_dirty();
|
|
return true;
|
|
}
|
|
else if (mouse_event.LeftUp() || is_leaving || is_dragging_finished) {
|
|
do_stop_dragging(is_leaving);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void GLGizmoBase::do_stop_dragging(bool perform_mouse_cleanup)
|
|
{
|
|
for (auto& grabber : m_grabbers) grabber.dragging = false;
|
|
m_dragging = false;
|
|
|
|
// NOTE: This should be part of GLCanvas3D
|
|
// Reset hover_id when leave window
|
|
if (perform_mouse_cleanup) m_parent.mouse_up_cleanup();
|
|
|
|
on_stop_dragging();
|
|
|
|
// There is prediction that after draggign, data are changed
|
|
// Data are updated twice also by canvas3D::reload_scene.
|
|
// Should be fixed.
|
|
m_parent.get_gizmos_manager().update_data();
|
|
|
|
wxGetApp().obj_manipul()->set_dirty();
|
|
|
|
// Let the plater know that the dragging finished, so a delayed
|
|
// refresh of the scene with the background processing data should
|
|
// be performed.
|
|
m_parent.post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED));
|
|
// updates camera target constraints
|
|
m_parent.refresh_camera_scene_box();
|
|
}
|
|
|
|
std::string GLGizmoBase::format(float value, unsigned int decimals) const
|
|
{
|
|
return Slic3r::string_printf("%.*f", decimals, value);
|
|
}
|
|
|
|
void GLGizmoBase::set_dirty() {
|
|
m_dirty = true;
|
|
}
|
|
|
|
void GLGizmoBase::render_input_window(float x, float y, float bottom_limit)
|
|
{
|
|
on_render_input_window(x, y, bottom_limit);
|
|
if (m_first_input_window_render) {
|
|
// imgui windows that don't have an initial size needs to be processed once to get one
|
|
// and are not rendered in the first frame
|
|
// so, we forces to render another frame the first time the imgui window is shown
|
|
// https://github.com/ocornut/imgui/issues/2949
|
|
m_parent.set_as_dirty();
|
|
m_parent.request_extra_frame();
|
|
m_first_input_window_render = false;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
std::string GLGizmoBase::get_name(bool include_shortcut) const
|
|
{
|
|
const std::string name = on_get_name();
|
|
return include_shortcut && m_shortcut.has_value() ? wxGetApp().shortcuts().with_key(name, *m_shortcut) : name;
|
|
}
|
|
|
|
} // namespace GUI
|
|
} // namespace Slic3r
|