Rework of MMU segmentation gizmo to support more than three colors.

This commit is contained in:
Lukáš Hejl 2021-04-30 15:58:25 +02:00
parent 576c5b78e9
commit d11d15aa1e
3 changed files with 405 additions and 15 deletions

View File

@ -6,13 +6,14 @@
#include "slic3r/GUI/GLCanvas3D.hpp" #include "slic3r/GUI/GLCanvas3D.hpp"
#include "slic3r/GUI/GUI_App.hpp" #include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/ImGuiWrapper.hpp" #include "slic3r/GUI/ImGuiWrapper.hpp"
#include "slic3r/GUI/Camera.hpp"
#include "slic3r/GUI/Plater.hpp" #include "slic3r/GUI/Plater.hpp"
#include "slic3r/GUI/BitmapCache.hpp"
#include "libslic3r/PresetBundle.hpp" #include "libslic3r/PresetBundle.hpp"
#include <GL/glew.h> #include <GL/glew.h>
namespace Slic3r::GUI { namespace Slic3r::GUI {
void GLGizmoMmuSegmentation::on_shutdown() void GLGizmoMmuSegmentation::on_shutdown()
@ -34,6 +35,31 @@ bool GLGizmoMmuSegmentation::on_is_selectable() const
&& wxGetApp().get_mode() != comSimple && wxGetApp().extruders_cnt() > 1); && wxGetApp().get_mode() != comSimple && wxGetApp().extruders_cnt() > 1);
} }
static std::vector<std::array<uint8_t, 3>> get_extruders_colors()
{
unsigned char rgb_color[3] = {};
std::vector<std::string> colors = Slic3r::GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config();
std::vector<std::array<uint8_t, 3>> colors_out(colors.size());
for (const std::string &color : colors) {
Slic3r::GUI::BitmapCache::parse_color(color, rgb_color);
size_t color_idx = &color - &colors.front();
colors_out[color_idx] = {rgb_color[0], rgb_color[1], rgb_color[2]};
}
return colors_out;
}
static std::vector<std::string> get_extruders_names()
{
size_t extruders_count = wxGetApp().extruders_cnt();
std::vector<std::string> extruders_out;
extruders_out.reserve(extruders_count);
for (size_t extruder_idx = 1; extruder_idx <= extruders_count; ++extruder_idx)
extruders_out.emplace_back("Extruder " + std::to_string(extruder_idx));
return extruders_out;
}
bool GLGizmoMmuSegmentation::on_init() bool GLGizmoMmuSegmentation::on_init()
{ {
// FIXME Lukas H.: Discuss and change shortcut // FIXME Lukas H.: Discuss and change shortcut
@ -54,6 +80,9 @@ bool GLGizmoMmuSegmentation::on_init()
m_desc["sphere"] = _L("Sphere"); m_desc["sphere"] = _L("Sphere");
m_desc["seed_fill_angle"] = _L("Seed fill angle"); m_desc["seed_fill_angle"] = _L("Seed fill angle");
m_extruders_names = get_extruders_names();
m_extruders_colors = get_extruders_colors();
return true; return true;
} }
@ -72,6 +101,249 @@ void GLGizmoMmuSegmentation::render_painter_gizmo() const
glsafe(::glDisable(GL_BLEND)); glsafe(::glDisable(GL_BLEND));
} }
bool GLGizmoMmuSegmentation::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down)
{
if (action == SLAGizmoEventType::MouseWheelUp
|| action == SLAGizmoEventType::MouseWheelDown) {
if (control_down) {
double pos = m_c->object_clipper()->get_position();
pos = action == SLAGizmoEventType::MouseWheelDown
? std::max(0., pos - 0.01)
: std::min(1., pos + 0.01);
m_c->object_clipper()->set_position(pos, true);
return true;
}
else if (alt_down) {
m_cursor_radius = action == SLAGizmoEventType::MouseWheelDown
? std::max(m_cursor_radius - CursorRadiusStep, CursorRadiusMin)
: std::min(m_cursor_radius + CursorRadiusStep, CursorRadiusMax);
m_parent.set_as_dirty();
return true;
}
}
if (action == SLAGizmoEventType::ResetClippingPlane) {
m_c->object_clipper()->set_position(-1., false);
return true;
}
if (action == SLAGizmoEventType::LeftDown
|| action == SLAGizmoEventType::RightDown
|| (action == SLAGizmoEventType::Dragging && m_button_down != Button::None)) {
if (m_triangle_selectors.empty())
return false;
EnforcerBlockerType new_state = EnforcerBlockerType::NONE;
if (! shift_down) {
if (action == SLAGizmoEventType::Dragging)
new_state = m_button_down == Button::Left
? EnforcerBlockerType(m_first_selected_extruder_idx)
: EnforcerBlockerType(m_second_selected_extruder_idx);
else
new_state = action == SLAGizmoEventType::LeftDown
? EnforcerBlockerType(m_first_selected_extruder_idx)
: EnforcerBlockerType(m_second_selected_extruder_idx);
}
const Camera& camera = wxGetApp().plater()->get_camera();
const Selection& selection = m_parent.get_selection();
const ModelObject* mo = m_c->selection_info()->model_object();
const ModelInstance* mi = mo->instances[selection.get_instance_idx()];
const Transform3d& instance_trafo = mi->get_transformation().get_matrix();
// List of mouse positions that will be used as seeds for painting.
std::vector<Vec2d> mouse_positions{mouse_position};
// In case current mouse position is far from the last one,
// add several positions from between into the list, so there
// are no gaps in the painted region.
{
if (m_last_mouse_click == Vec2d::Zero())
m_last_mouse_click = mouse_position;
// resolution describes minimal distance limit using circle radius
// as a unit (e.g., 2 would mean the patches will be touching).
double resolution = 0.7;
double diameter_px = resolution * m_cursor_radius * camera.get_zoom();
int patches_in_between = int(((mouse_position - m_last_mouse_click).norm() - diameter_px) / diameter_px);
if (patches_in_between > 0) {
Vec2d diff = (mouse_position - m_last_mouse_click)/(patches_in_between+1);
for (int i=1; i<=patches_in_between; ++i)
mouse_positions.emplace_back(m_last_mouse_click + i*diff);
}
}
m_last_mouse_click = Vec2d::Zero(); // only actual hits should be saved
// Precalculate transformations of individual meshes.
std::vector<Transform3d> trafo_matrices;
for (const ModelVolume* mv : mo->volumes) {
if (mv->is_model_part())
trafo_matrices.emplace_back(instance_trafo * mv->get_matrix());
}
// Now "click" into all the prepared points and spill paint around them.
for (const Vec2d& mp : mouse_positions) {
update_raycast_cache(mp, camera, trafo_matrices);
bool dragging_while_painting = (action == SLAGizmoEventType::Dragging && m_button_down != Button::None);
// The mouse button click detection is enabled when there is a valid hit.
// Missing the object entirely
// shall not capture the mouse.
if (m_rr.mesh_id != -1) {
if (m_button_down == Button::None)
m_button_down = ((action == SLAGizmoEventType::LeftDown) ? Button::Left : Button::Right);
}
if (m_rr.mesh_id == -1) {
// In case we have no valid hit, we can return. The event will be stopped when
// dragging while painting (to prevent scene rotations and moving the object)
return dragging_while_painting;
}
const Transform3d& trafo_matrix = trafo_matrices[m_rr.mesh_id];
// Calculate direction from camera to the hit (in mesh coords):
Vec3f camera_pos = (trafo_matrix.inverse() * camera.get_position()).cast<float>();
assert(m_rr.mesh_id < int(m_triangle_selectors.size()));
if (m_seed_fill_enabled)
m_triangle_selectors[m_rr.mesh_id]->seed_fill_apply_on_triangles(new_state);
else
m_triangle_selectors[m_rr.mesh_id]->select_patch(m_rr.hit, m_rr.facet, camera_pos, m_cursor_radius, m_cursor_type,
new_state, trafo_matrix, m_triangle_splitting_enabled);
m_last_mouse_click = mouse_position;
}
return true;
}
if (action == SLAGizmoEventType::Moving && m_seed_fill_enabled) {
if (m_triangle_selectors.empty())
return false;
const Camera & camera = wxGetApp().plater()->get_camera();
const Selection & selection = m_parent.get_selection();
const ModelObject * mo = m_c->selection_info()->model_object();
const ModelInstance *mi = mo->instances[selection.get_instance_idx()];
const Transform3d & instance_trafo = mi->get_transformation().get_matrix();
// Precalculate transformations of individual meshes.
std::vector<Transform3d> trafo_matrices;
for (const ModelVolume *mv : mo->volumes)
if (mv->is_model_part())
trafo_matrices.emplace_back(instance_trafo * mv->get_matrix());
// Now "click" into all the prepared points and spill paint around them.
update_raycast_cache(mouse_position, camera, trafo_matrices);
if (m_rr.mesh_id == -1) {
// Clean selected by seed fill for all triangles
for (auto &triangle_selector : m_triangle_selectors)
triangle_selector->seed_fill_unselect_all_triangles();
// In case we have no valid hit, we can return.
return false;
}
assert(m_rr.mesh_id < int(m_triangle_selectors.size()));
m_triangle_selectors[m_rr.mesh_id]->seed_fill_select_triangles(m_rr.hit, m_rr.facet, m_seed_fill_angle);
return true;
}
if ((action == SLAGizmoEventType::LeftUp || action == SLAGizmoEventType::RightUp)
&& m_button_down != Button::None) {
// Take snapshot and update ModelVolume data.
wxString action_name;
if (get_painter_type() == PainterGizmoType::FDM_SUPPORTS) {
if (shift_down)
action_name = _L("Remove selection");
else {
if (m_button_down == Button::Left)
action_name = _L("Add supports");
else
action_name = _L("Block supports");
}
}
if (get_painter_type() == PainterGizmoType::SEAM) {
if (shift_down)
action_name = _L("Remove selection");
else {
if (m_button_down == Button::Left)
action_name = _L("Enforce seam");
else
action_name = _L("Block seam");
}
}
activate_internal_undo_redo_stack(true);
Plater::TakeSnapshot(wxGetApp().plater(), action_name);
update_model_object();
m_button_down = Button::None;
m_last_mouse_click = Vec2d::Zero();
return true;
}
return false;
}
static void render_extruders_combo(const std::string &label,
const std::vector<std::string> &extruders,
const std::vector<std::array<uint8_t, 3>> &extruders_colors,
size_t &selection_idx)
{
assert(!extruders_colors.empty());
assert(extruders_colors.size() == extruders_colors.size());
size_t selection_out = selection_idx;
// It is necessary to use BeginGroup(). Otherwise, when using SameLine() is called, then other items will be drawn inside the combobox.
ImGui::BeginGroup();
ImVec2 combo_pos = ImGui::GetCursorScreenPos();
if (ImGui::BeginCombo(label.c_str(), "")) {
for (size_t extruder_idx = 0; extruder_idx < extruders.size(); ++extruder_idx) {
ImGui::PushID(extruder_idx);
ImVec2 start_position = ImGui::GetCursorScreenPos();
if (ImGui::Selectable("", extruder_idx == selection_idx))
selection_out = extruder_idx;
ImGui::SameLine();
ImGuiStyle &style = ImGui::GetStyle();
float height = ImGui::GetTextLineHeight();
ImGui::GetWindowDrawList()->AddRectFilled(start_position, ImVec2(start_position.x + height + height / 2, start_position.y + height),
IM_COL32(extruders_colors[extruder_idx][0], extruders_colors[extruder_idx][1], extruders_colors[extruder_idx][2], 255));
ImGui::GetWindowDrawList()->AddRect(start_position, ImVec2(start_position.x + height + height / 2, start_position.y + height), IM_COL32_BLACK);
ImGui::SetCursorScreenPos(ImVec2(start_position.x + height + height / 2 + style.FramePadding.x, start_position.y));
ImGui::Text("%s", extruders[extruder_idx].c_str());
ImGui::PopID();
}
ImGui::EndCombo();
}
ImVec2 backup_pos = ImGui::GetCursorScreenPos();
ImGuiStyle &style = ImGui::GetStyle();
ImGui::SetCursorScreenPos(ImVec2(combo_pos.x + style.FramePadding.x, combo_pos.y + style.FramePadding.y));
ImVec2 p = ImGui::GetCursorScreenPos();
float height = ImGui::GetTextLineHeight();
ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x + height + height / 2, p.y + height),
IM_COL32(extruders_colors[selection_idx][0], extruders_colors[selection_idx][1],
extruders_colors[selection_idx][2], 255));
ImGui::GetWindowDrawList()->AddRect(p, ImVec2(p.x + height + height / 2, p.y + height), IM_COL32_BLACK);
ImGui::SetCursorScreenPos(ImVec2(p.x + height + height / 2 + style.FramePadding.x, p.y));
ImGui::Text("%s", extruders[selection_out].c_str());
ImGui::SetCursorScreenPos(backup_pos);
ImGui::EndGroup();
selection_idx = selection_out;
}
void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bottom_limit) void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bottom_limit)
{ {
if (!m_c->selection_info()->model_object()) if (!m_c->selection_info()->model_object())
@ -94,6 +366,9 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
const float button_width = m_imgui->calc_text_size(m_desc.at("remove_all")).x + m_imgui->scaled(1.f); const float button_width = m_imgui->calc_text_size(m_desc.at("remove_all")).x + m_imgui->scaled(1.f);
const float buttons_width = m_imgui->scaled(0.5f); const float buttons_width = m_imgui->scaled(0.5f);
const float minimal_slider_width = m_imgui->scaled(4.f); const float minimal_slider_width = m_imgui->scaled(4.f);
const float color_button_width = m_imgui->calc_text_size("").x + m_imgui->scaled(1.75f);
const float combo_label_width = std::max(m_imgui->calc_text_size(m_desc.at("first_color")).x,
m_imgui->calc_text_size(m_desc.at("second_color")).x) + m_imgui->scaled(1.f);
float caption_max = 0.f; float caption_max = 0.f;
float total_text_max = 0.; float total_text_max = 0.;
@ -122,6 +397,30 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
m_imgui->text(""); m_imgui->text("");
ImGui::Separator(); ImGui::Separator();
const std::array<uint8_t, 3> &select_first_color = m_extruders_colors[m_first_selected_extruder_idx];
const std::array<uint8_t, 3> &select_second_color = m_extruders_colors[m_second_selected_extruder_idx];
m_imgui->text(m_desc.at("first_color"));
ImGui::SameLine(combo_label_width);
ImGui::PushItemWidth(window_width - combo_label_width - color_button_width);
render_extruders_combo("##first_color_combo", m_extruders_names, get_extruders_colors(), m_first_selected_extruder_idx);
ImGui::SameLine();
ImVec4 first_color = ImVec4(float(select_first_color[0]) / 255.0f, float(select_first_color[1]) / 255.0f, float(select_first_color[2]) / 255.0f, 1.0f);
ImVec4 second_color = ImVec4(float(select_second_color[0]) / 255.0f, float(select_second_color[1]) / 255.0f, float(select_second_color[2]) / 255.0f, 1.0f);
if(ImGui::ColorEdit4("First color##color_picker", (float*)&first_color, ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel))
m_extruders_colors[m_first_selected_extruder_idx] = {uint8_t(first_color.x * 255.0f), uint8_t(first_color.y * 255.0f), uint8_t(first_color.z * 255.0f)};
m_imgui->text(m_desc.at("second_color"));
ImGui::SameLine(combo_label_width);
ImGui::PushItemWidth(window_width - combo_label_width - color_button_width);
render_extruders_combo("##second_color_combo", m_extruders_names, get_extruders_colors(), m_second_selected_extruder_idx);
ImGui::SameLine();
if(ImGui::ColorEdit4("Second color##color_picker", (float*)&second_color, ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel))
m_extruders_colors[m_second_selected_extruder_idx] = {uint8_t(second_color.x * 255.0f), uint8_t(second_color.y * 255.0f), uint8_t(second_color.z * 255.0f)};
ImGui::Separator();
if (m_imgui->checkbox(_L("Seed fill"), m_seed_fill_enabled)) if (m_imgui->checkbox(_L("Seed fill"), m_seed_fill_enabled))
if (!m_seed_fill_enabled) if (!m_seed_fill_enabled)
for (auto &triangle_selector : m_triangle_selectors) for (auto &triangle_selector : m_triangle_selectors)
@ -134,12 +433,9 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
ImGui::SameLine(autoset_slider_left); ImGui::SameLine(autoset_slider_left);
ImGui::PushItemWidth(window_width - autoset_slider_left); ImGui::PushItemWidth(window_width - autoset_slider_left);
m_imgui->disabled_begin(!m_seed_fill_enabled); m_imgui->disabled_begin(!m_seed_fill_enabled);
m_imgui->slider_float("", &m_seed_fill_angle, 0.f, 90.f, format_str.data()); m_imgui->slider_float("##seed_fill_angle", &m_seed_fill_angle, 0.f, 90.f, format_str.data());
m_imgui->disabled_end(); m_imgui->disabled_end();
ImGui::NewLine();
ImGui::SameLine(window_width - 2.f * buttons_width - m_imgui->scaled(0.5f));
ImGui::Separator(); ImGui::Separator();
if (m_imgui->button(m_desc.at("remove_all"))) { if (m_imgui->button(m_desc.at("remove_all"))) {
@ -265,7 +561,7 @@ void GLGizmoMmuSegmentation::update_from_model_object()
// This mesh does not account for the possible Z up SLA offset. // This mesh does not account for the possible Z up SLA offset.
const TriangleMesh* mesh = &mv->mesh(); const TriangleMesh* mesh = &mv->mesh();
m_triangle_selectors.emplace_back(std::make_unique<TriangleSelectorGUI>(*mesh)); m_triangle_selectors.emplace_back(std::make_unique<TriangleSelectorMmuGui>(*mesh, wxGetApp().extruders_cnt(), m_extruders_colors));
m_triangle_selectors.back()->deserialize(mv->mmu_segmentation_facets.get_data()); m_triangle_selectors.back()->deserialize(mv->mmu_segmentation_facets.get_data());
} }
} }
@ -275,5 +571,78 @@ PainterGizmoType GLGizmoMmuSegmentation::get_painter_type() const
return PainterGizmoType::MMU_SEGMENTATION; return PainterGizmoType::MMU_SEGMENTATION;
} }
void TriangleSelectorMmuGui::render(ImGuiWrapper *imgui)
{
std::vector<int> color_cnt(m_iva_colors.size());
int seed_fill_cnt = 0;
for (auto &iva_color : m_iva_colors)
iva_color.release_geometry();
m_iva_seed_fill.release_geometry();
for (size_t color_idx = 0; color_idx < m_iva_colors.size(); ++color_idx) {
for (const Triangle &tr : m_triangles) {
if (!tr.valid || tr.is_split() || /*tr.get_state() == EnforcerBlockerType::NONE ||*/ tr.is_selected_by_seed_fill() ||
tr.get_state() != EnforcerBlockerType(color_idx))
continue;
for (int i = 0; i < 3; ++i)
m_iva_colors[color_idx].push_geometry(double(m_vertices[tr.verts_idxs[i]].v[0]),
double(m_vertices[tr.verts_idxs[i]].v[1]),
double(m_vertices[tr.verts_idxs[i]].v[2]),
double(tr.normal[0]),
double(tr.normal[1]),
double(tr.normal[2]));
m_iva_colors[color_idx].push_triangle(color_cnt[color_idx], color_cnt[color_idx] + 1, color_cnt[color_idx] + 2);
color_cnt[color_idx] += 3;
}
}
for (const Triangle &tr : m_triangles) {
if (!tr.valid || tr.is_split() || !tr.is_selected_by_seed_fill()) continue;
for (int i = 0; i < 3; ++i)
m_iva_seed_fill.push_geometry(double(m_vertices[tr.verts_idxs[i]].v[0]),
double(m_vertices[tr.verts_idxs[i]].v[1]),
double(m_vertices[tr.verts_idxs[i]].v[2]),
double(tr.normal[0]),
double(tr.normal[1]),
double(tr.normal[2]));
m_iva_seed_fill.push_triangle(seed_fill_cnt, seed_fill_cnt + 1, seed_fill_cnt + 2);
seed_fill_cnt += 3;
}
for (auto &iva_color : m_iva_colors)
iva_color.finalize_geometry(true);
m_iva_seed_fill.finalize_geometry(true);
std::vector<bool> render_colors(m_iva_colors.size());
for (size_t color_idx = 0; color_idx < m_iva_colors.size(); ++color_idx)
render_colors[color_idx] = m_iva_colors[color_idx].has_VBOs();
bool render_seed_fill = m_iva_seed_fill.has_VBOs();
auto *shader = wxGetApp().get_shader("gouraud");
if (!shader) return;
shader->start_using();
ScopeGuard guard([shader]() {
if (shader)
shader->stop_using();
});
shader->set_uniform("slope.actived", false);
for (size_t color_idx = 0; color_idx < m_iva_colors.size(); ++color_idx) {
if (render_colors[color_idx]) {
std::array<float, 4> color = {m_colors[color_idx][0] / 255.0f, m_colors[color_idx][1] / 255.0f, m_colors[color_idx][2] / 255.0f, 1.f};
shader->set_uniform("uniform_color", color);
m_iva_colors[color_idx].render();
}
}
if (render_seed_fill) {
std::array<float, 4> color = {0.f, 1.00f, 0.44f, 1.f};
shader->set_uniform("uniform_color", color);
m_iva_seed_fill.render();
}
}
} // namespace Slic3r } // namespace Slic3r

View File

@ -3,9 +3,23 @@
#include "GLGizmoPainterBase.hpp" #include "GLGizmoPainterBase.hpp"
namespace Slic3r { namespace Slic3r::GUI {
namespace GUI { class TriangleSelectorMmuGui : public TriangleSelectorGUI {
public:
explicit TriangleSelectorMmuGui(const TriangleMesh& mesh, size_t extruder_count, const std::vector<std::array<uint8_t, 3>> &colors)
: TriangleSelectorGUI(mesh), m_colors(colors) {
m_iva_colors = std::vector<GLIndexedVertexArray>(extruder_count);
}
// Render current selection. Transformation matrices are supposed
// to be already set.
virtual void render(ImGuiWrapper* imgui = nullptr);
private:
const std::vector<std::array<uint8_t, 3>> &m_colors;
std::vector<GLIndexedVertexArray> m_iva_colors;
};
class GLGizmoMmuSegmentation : public GLGizmoPainterBase class GLGizmoMmuSegmentation : public GLGizmoPainterBase
{ {
@ -15,12 +29,19 @@ public:
void render_painter_gizmo() const override; void render_painter_gizmo() const override;
virtual bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down) override;
protected: protected:
void on_render_input_window(float x, float y, float bottom_limit) override; void on_render_input_window(float x, float y, float bottom_limit) override;
std::string on_get_name() const override; std::string on_get_name() const override;
bool on_is_selectable() const override; bool on_is_selectable() const override;
size_t m_first_selected_extruder_idx = 0;
size_t m_second_selected_extruder_idx = 1;
std::vector<std::string> m_extruders_names;
std::vector<std::array<uint8_t, 3>> m_extruders_colors;
private: private:
bool on_init() override; bool on_init() override;
@ -36,9 +57,6 @@ private:
std::map<std::string, wxString> m_desc; std::map<std::string, wxString> m_desc;
}; };
} // namespace GUI
} // namespace Slic3r } // namespace Slic3r

View File

@ -10,7 +10,7 @@
#include <cereal/types/vector.hpp> #include <cereal/types/vector.hpp>
class GLGizmoMmuSegmentation;
namespace Slic3r { namespace Slic3r {
@ -37,7 +37,7 @@ public:
// Render current selection. Transformation matrices are supposed // Render current selection. Transformation matrices are supposed
// to be already set. // to be already set.
void render(ImGuiWrapper* imgui = nullptr); virtual void render(ImGuiWrapper* imgui = nullptr);
#ifdef PRUSASLICER_TRIANGLE_SELECTOR_DEBUG #ifdef PRUSASLICER_TRIANGLE_SELECTOR_DEBUG
void render_debug(ImGuiWrapper* imgui); void render_debug(ImGuiWrapper* imgui);
@ -48,8 +48,9 @@ public:
private: private:
GLIndexedVertexArray m_iva_enforcers; GLIndexedVertexArray m_iva_enforcers;
GLIndexedVertexArray m_iva_blockers; GLIndexedVertexArray m_iva_blockers;
GLIndexedVertexArray m_iva_seed_fill;
std::array<GLIndexedVertexArray, 3> m_varrays; std::array<GLIndexedVertexArray, 3> m_varrays;
protected:
GLIndexedVertexArray m_iva_seed_fill;
}; };
@ -68,7 +69,7 @@ public:
GLGizmoPainterBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); GLGizmoPainterBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
~GLGizmoPainterBase() override {} ~GLGizmoPainterBase() override {}
void set_painter_gizmo_data(const Selection& selection); void set_painter_gizmo_data(const Selection& selection);
bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down); virtual bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down);
// Following function renders the triangles and cursor. Having this separated // Following function renders the triangles and cursor. Having this separated
// from usual on_render method allows to render them before transparent objects, // from usual on_render method allows to render them before transparent objects,
@ -146,6 +147,8 @@ protected:
void on_load(cereal::BinaryInputArchive& ar) override; void on_load(cereal::BinaryInputArchive& ar) override;
void on_save(cereal::BinaryOutputArchive& ar) const override {} void on_save(cereal::BinaryOutputArchive& ar) const override {}
CommonGizmosDataID on_get_requirements() const override; CommonGizmosDataID on_get_requirements() const override;
friend class GLGizmoMmuSegmentation;
}; };