mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-07-14 13:31:51 +08:00
Rework of MMU segmentation gizmo to support more than three colors.
This commit is contained in:
parent
576c5b78e9
commit
d11d15aa1e
@ -6,13 +6,14 @@
|
||||
#include "slic3r/GUI/GLCanvas3D.hpp"
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
#include "slic3r/GUI/ImGuiWrapper.hpp"
|
||||
#include "slic3r/GUI/Camera.hpp"
|
||||
#include "slic3r/GUI/Plater.hpp"
|
||||
#include "slic3r/GUI/BitmapCache.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
|
||||
namespace Slic3r::GUI {
|
||||
|
||||
void GLGizmoMmuSegmentation::on_shutdown()
|
||||
@ -34,6 +35,31 @@ bool GLGizmoMmuSegmentation::on_is_selectable() const
|
||||
&& 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()
|
||||
{
|
||||
// FIXME Lukas H.: Discuss and change shortcut
|
||||
@ -54,6 +80,9 @@ bool GLGizmoMmuSegmentation::on_init()
|
||||
m_desc["sphere"] = _L("Sphere");
|
||||
m_desc["seed_fill_angle"] = _L("Seed fill angle");
|
||||
|
||||
m_extruders_names = get_extruders_names();
|
||||
m_extruders_colors = get_extruders_colors();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -72,6 +101,249 @@ void GLGizmoMmuSegmentation::render_painter_gizmo() const
|
||||
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)
|
||||
{
|
||||
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 buttons_width = m_imgui->scaled(0.5f);
|
||||
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 total_text_max = 0.;
|
||||
@ -122,6 +397,30 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
|
||||
m_imgui->text("");
|
||||
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_seed_fill_enabled)
|
||||
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::PushItemWidth(window_width - autoset_slider_left);
|
||||
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();
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::SameLine(window_width - 2.f * buttons_width - m_imgui->scaled(0.5f));
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
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.
|
||||
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());
|
||||
}
|
||||
}
|
||||
@ -275,5 +571,78 @@ PainterGizmoType GLGizmoMmuSegmentation::get_painter_type() const
|
||||
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
|
||||
|
@ -3,9 +3,23 @@
|
||||
|
||||
#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
|
||||
{
|
||||
@ -15,12 +29,19 @@ public:
|
||||
|
||||
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:
|
||||
void on_render_input_window(float x, float y, float bottom_limit) override;
|
||||
std::string on_get_name() 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:
|
||||
bool on_init() override;
|
||||
|
||||
@ -36,9 +57,6 @@ private:
|
||||
std::map<std::string, wxString> m_desc;
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
#include <cereal/types/vector.hpp>
|
||||
|
||||
|
||||
class GLGizmoMmuSegmentation;
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
@ -37,7 +37,7 @@ public:
|
||||
|
||||
// Render current selection. Transformation matrices are supposed
|
||||
// to be already set.
|
||||
void render(ImGuiWrapper* imgui = nullptr);
|
||||
virtual void render(ImGuiWrapper* imgui = nullptr);
|
||||
|
||||
#ifdef PRUSASLICER_TRIANGLE_SELECTOR_DEBUG
|
||||
void render_debug(ImGuiWrapper* imgui);
|
||||
@ -48,8 +48,9 @@ public:
|
||||
private:
|
||||
GLIndexedVertexArray m_iva_enforcers;
|
||||
GLIndexedVertexArray m_iva_blockers;
|
||||
GLIndexedVertexArray m_iva_seed_fill;
|
||||
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() override {}
|
||||
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
|
||||
// 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_save(cereal::BinaryOutputArchive& ar) const override {}
|
||||
CommonGizmosDataID on_get_requirements() const override;
|
||||
|
||||
friend class GLGizmoMmuSegmentation;
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user