mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-10 18:56:13 +00:00
Add fuzzy skin painting (#9979)
* SPE-2486: Refactor function apply_mm_segmentation() to prepare support for fuzzy skin painting. (cherry picked from commit 2c06c81159f7aadd6ac20c7a7583c8f4959a5601) * SPE-2585: Fix empty layers when multi-material painting and modifiers are used. (cherry picked from commit 4b3da02ec26d43bfad91897cb34779fb21419e3e) * Update project structure to match Prusa * SPE-2486: Add a new gizmo for fuzzy skin painting. (cherry picked from commit 886faac74ebe6978b828f51be62d26176e2900e5) * Fix render * Remove duplicated painting gizmo `render_triangles` code * SPE-2486: Extend multi-material segmentation to allow segmentation of any painted faces. (cherry picked from commit 519f5eea8e3be0d7c2cd5d030323ff264727e3d0) --------- Co-authored-by: Lukáš Hejl <hejl.lukas@gmail.com> * SPE-2486: Implement segmentation of layers based on fuzzy skin painting. (cherry picked from commit 800b742b950438c5ed8323693074b6171300131c) * SPE-2486: Separate fuzzy skin implementation into the separate file. (cherry picked from commit efd95c1c66dc09fca7695fb82405056c687c2291) * Move more fuzzy code to separate file * Don't hide fuzzy skin option, so it can be applied to paint on fuzzy * Fix build * Add option group for fuzzy skin * Update icon color * Fix reset painting * Update UI style * Store fuzzy painting in bbs_3mf * Add missing fuzzy paint code * SPE-2486: Limit the depth of the painted fuzzy skin regions to make regions cover just external perimeters. This reduces the possibility of artifacts that could happen during regions merging. (cherry picked from commit fa2663f02647f80b239da4f45d92ef66f5ce048a) * Update icons --------- Co-authored-by: yw4z <ywsyildiz@gmail.com> * Make the region compatible check a separate function * Only warn about multi-material if it's truly multi-perimeters * Improve gizmo UI & tooltips --------- Co-authored-by: Lukáš Hejl <hejl.lukas@gmail.com> Co-authored-by: yw4z <ywsyildiz@gmail.com>
This commit is contained in:
@@ -151,54 +151,6 @@ bool GLGizmoFdmSupports::on_key_down_select_tool_type(int keyCode) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// BBS
|
||||
void GLGizmoFdmSupports::render_triangles(const Selection& selection) const
|
||||
{
|
||||
ClippingPlaneDataWrapper clp_data = this->get_clipping_plane_data();
|
||||
auto* shader = wxGetApp().get_shader("mm_gouraud");
|
||||
if (!shader)
|
||||
return;
|
||||
shader->start_using();
|
||||
shader->set_uniform("clipping_plane", clp_data.clp_dataf);
|
||||
shader->set_uniform("z_range", clp_data.z_range);
|
||||
ScopeGuard guard([shader]() { if (shader) shader->stop_using(); });
|
||||
|
||||
const ModelObject* mo = m_c->selection_info()->model_object();
|
||||
int mesh_id = -1;
|
||||
for (const ModelVolume* mv : mo->volumes) {
|
||||
if (!mv->is_model_part())
|
||||
continue;
|
||||
|
||||
++mesh_id;
|
||||
|
||||
const Transform3d trafo_matrix = mo->instances[selection.get_instance_idx()]->get_transformation().get_matrix() * mv->get_matrix();
|
||||
|
||||
bool is_left_handed = trafo_matrix.matrix().determinant() < 0.;
|
||||
if (is_left_handed)
|
||||
glsafe(::glFrontFace(GL_CW));
|
||||
|
||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||
const Transform3d& view_matrix = camera.get_view_matrix();
|
||||
shader->set_uniform("view_model_matrix", view_matrix * trafo_matrix);
|
||||
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||
const Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * trafo_matrix.matrix().block(0, 0, 3, 3).inverse().transpose();
|
||||
shader->set_uniform("view_normal_matrix", view_normal_matrix);
|
||||
|
||||
float normal_z = -::cos(Geometry::deg2rad(m_highlight_by_angle_threshold_deg));
|
||||
Matrix3f normal_matrix = static_cast<Matrix3f>(trafo_matrix.matrix().block(0, 0, 3, 3).inverse().transpose().cast<float>());
|
||||
|
||||
shader->set_uniform("volume_world_matrix", trafo_matrix);
|
||||
shader->set_uniform("volume_mirrored", is_left_handed);
|
||||
shader->set_uniform("slope.actived", m_parent.is_using_slope());
|
||||
shader->set_uniform("slope.volume_world_normal_matrix", normal_matrix);
|
||||
shader->set_uniform("slope.normal_z", normal_z);
|
||||
m_triangle_selectors[mesh_id]->render(m_imgui, trafo_matrix);
|
||||
|
||||
if (is_left_handed)
|
||||
glsafe(::glFrontFace(GL_CCW));
|
||||
}
|
||||
}
|
||||
|
||||
void GLGizmoFdmSupports::on_set_state()
|
||||
{
|
||||
GLGizmoPainterBase::on_set_state();
|
||||
|
||||
@@ -32,8 +32,6 @@ protected:
|
||||
void on_render_input_window(float x, float y, float bottom_limit) override;
|
||||
std::string on_get_name() const override;
|
||||
|
||||
// BBS
|
||||
void render_triangles(const Selection& selection) const override;
|
||||
void on_set_state() override;
|
||||
void show_tooltip_information(float caption_max, float x, float y);
|
||||
wxString handle_snapshot_action_name(bool shift_down, Button button_down) const override;
|
||||
|
||||
390
src/slic3r/GUI/Gizmos/GLGizmoFuzzySkin.cpp
Normal file
390
src/slic3r/GUI/Gizmos/GLGizmoFuzzySkin.cpp
Normal file
@@ -0,0 +1,390 @@
|
||||
#include "GLGizmoFuzzySkin.hpp"
|
||||
|
||||
#include "libslic3r/Model.hpp"
|
||||
#include "libslic3r/Print.hpp"
|
||||
|
||||
#include "slic3r/GUI/GLCanvas3D.hpp"
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
#include "slic3r/GUI/GUI_ObjectList.hpp"
|
||||
#include "slic3r/GUI/ImGuiWrapper.hpp"
|
||||
#include "slic3r/GUI/MsgDialog.hpp"
|
||||
#include "slic3r/GUI/Plater.hpp"
|
||||
#include "slic3r/Utils/UndoRedo.hpp"
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <algorithm>
|
||||
|
||||
namespace Slic3r::GUI {
|
||||
|
||||
void GLGizmoFuzzySkin::on_shutdown()
|
||||
{
|
||||
m_parent.use_slope(false);
|
||||
m_parent.toggle_model_objects_visibility(true);
|
||||
}
|
||||
|
||||
std::string GLGizmoFuzzySkin::on_get_name() const
|
||||
{
|
||||
return _u8L("Paint-on fuzzy skin");
|
||||
}
|
||||
|
||||
bool GLGizmoFuzzySkin::on_init()
|
||||
{
|
||||
m_shortcut_key = WXK_CONTROL_H;
|
||||
|
||||
m_desc["clipping_of_view_caption"] = _L("Alt + Mouse wheel");
|
||||
m_desc["clipping_of_view"] = _L("Section view");
|
||||
m_desc["reset_direction"] = _L("Reset direction");
|
||||
m_desc["cursor_size_caption"] = _L("Ctrl + Mouse wheel");
|
||||
m_desc["cursor_size"] = _L("Brush size");
|
||||
m_desc["cursor_type"] = _L("Brush shape") ;
|
||||
m_desc["add_fuzzy_skin_caption"] = _L("Left mouse button");
|
||||
m_desc["add_fuzzy_skin"] = _L("Add fuzzy skin");
|
||||
m_desc["remove_fuzzy_skin_caption"] = _L("Shift + Left mouse button");
|
||||
m_desc["remove_fuzzy_skin"] = _L("Remove fuzzy skin");
|
||||
m_desc["remove_all"] = _L("Erase all painting");
|
||||
m_desc["circle"] = _L("Circle");
|
||||
m_desc["sphere"] = _L("Sphere");
|
||||
m_desc["pointer"] = _L("Triangles");
|
||||
m_desc["tool_type"] = _L("Tool type");
|
||||
m_desc["tool_brush"] = _L("Brush");
|
||||
m_desc["tool_smart_fill"] = _L("Smart fill");
|
||||
m_desc["smart_fill_angle_caption"] = _L("Ctrl + Mouse wheel");
|
||||
m_desc["smart_fill_angle"] = _L("Smart fill angle");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
GLGizmoFuzzySkin::GLGizmoFuzzySkin(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
||||
: GLGizmoPainterBase(parent, icon_filename, sprite_id), m_current_tool(ImGui::CircleButtonIcon)
|
||||
{
|
||||
}
|
||||
|
||||
void GLGizmoFuzzySkin::render_painter_gizmo()
|
||||
{
|
||||
const Selection &selection = m_parent.get_selection();
|
||||
|
||||
glsafe(::glEnable(GL_BLEND));
|
||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
|
||||
render_triangles(selection);
|
||||
m_c->object_clipper()->render_cut();
|
||||
m_c->instances_hider()->render_cut();
|
||||
render_cursor();
|
||||
|
||||
glsafe(::glDisable(GL_BLEND));
|
||||
}
|
||||
|
||||
void GLGizmoFuzzySkin::show_tooltip_information(float caption_max, float x, float y)
|
||||
{
|
||||
ImTextureID normal_id = m_parent.get_gizmos_manager().get_icon_texture_id(GLGizmosManager::MENU_ICON_NAME::IC_TOOLBAR_TOOLTIP);
|
||||
ImTextureID hover_id = m_parent.get_gizmos_manager().get_icon_texture_id(GLGizmosManager::MENU_ICON_NAME::IC_TOOLBAR_TOOLTIP_HOVER);
|
||||
|
||||
caption_max += m_imgui->calc_text_size(std::string_view{": "}).x + 15.f;
|
||||
|
||||
float scale = m_parent.get_scale();
|
||||
ImVec2 button_size = ImVec2(25 * scale, 25 * scale); // ORCA: Use exact resolution will prevent blur on icon
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, {0, 0}); // ORCA: Dont add padding
|
||||
ImGui::ImageButton3(normal_id, hover_id, button_size);
|
||||
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::BeginTooltip2(ImVec2(x, y));
|
||||
auto draw_text_with_caption = [this, &caption_max](const wxString& caption, const wxString& text) {
|
||||
m_imgui->text_colored(ImGuiWrapper::COL_ACTIVE, caption);
|
||||
ImGui::SameLine(caption_max);
|
||||
m_imgui->text_colored(ImGuiWrapper::COL_WINDOW_BG, text);
|
||||
};
|
||||
|
||||
std::vector<std::string> tip_items;
|
||||
switch (m_tool_type) {
|
||||
case ToolType::BRUSH:
|
||||
if (m_cursor_type == TriangleSelector::POINTER) {
|
||||
tip_items = {"add_fuzzy_skin", "remove_fuzzy_skin", "clipping_of_view"};
|
||||
} else {
|
||||
tip_items = {"add_fuzzy_skin", "remove_fuzzy_skin", "cursor_size", "clipping_of_view"};
|
||||
}
|
||||
break;
|
||||
case ToolType::SMART_FILL:
|
||||
tip_items = {"add_fuzzy_skin", "remove_fuzzy_skin", "smart_fill_angle", "clipping_of_view"};
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
for (const auto &t : tip_items) draw_text_with_caption(m_desc.at(t + "_caption") + ": ", m_desc.at(t));
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
ImGui::PopStyleVar(2);
|
||||
}
|
||||
|
||||
void GLGizmoFuzzySkin::on_render_input_window(float x, float y, float bottom_limit)
|
||||
{
|
||||
if (!m_c->selection_info()->model_object())
|
||||
return;
|
||||
|
||||
const float approx_height = m_imgui->scaled(22.f);
|
||||
y = std::min(y, bottom_limit - approx_height);
|
||||
//BBS: GUI refactor: move gizmo to the right
|
||||
#if BBS_TOOLBAR_ON_TOP
|
||||
GizmoImguiSetNextWIndowPos(x, y, ImGuiCond_Always, 0.0f, 0.0f);
|
||||
#else
|
||||
GizmoImguiSetNextWIndowPos(x, y, ImGuiCond_Always, 1.0f, 0.0f);
|
||||
#endif
|
||||
//m_imgui->set_next_window_pos(x, y, ImGuiCond_Always);
|
||||
|
||||
// BBS
|
||||
ImGuiWrapper::push_toolbar_style(m_parent.get_scale());
|
||||
|
||||
GizmoImguiBegin(get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar);
|
||||
|
||||
// First calculate width of all the texts that are could possibly be shown. We will decide set the dialog width based on that:
|
||||
const float space_size = m_imgui->get_style_scaling() * 8;
|
||||
const float clipping_slider_left = std::max(m_imgui->calc_text_size(m_desc.at("clipping_of_view")).x + m_imgui->scaled(1.5f),
|
||||
m_imgui->calc_text_size(m_desc.at("reset_direction")).x + m_imgui->scaled(1.5f) + ImGui::GetStyle().FramePadding.x * 2);
|
||||
const float cursor_slider_left = m_imgui->calc_text_size(m_desc.at("cursor_size")).x + m_imgui->scaled(1.5f);
|
||||
const float smart_fill_slider_left = m_imgui->calc_text_size(m_desc.at("smart_fill_angle")).x + m_imgui->scaled(1.5f);
|
||||
|
||||
const float cursor_type_radio_circle = m_imgui->calc_text_size(m_desc["circle"]).x + m_imgui->scaled(2.5f);
|
||||
const float cursor_type_radio_sphere = m_imgui->calc_text_size(m_desc["sphere"]).x + m_imgui->scaled(2.5f);
|
||||
const float cursor_type_radio_pointer = m_imgui->calc_text_size(m_desc["pointer"]).x + m_imgui->scaled(2.5f);
|
||||
|
||||
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 tool_type_radio_left = m_imgui->calc_text_size(m_desc["tool_type"]).x + m_imgui->scaled(1.f);
|
||||
const float tool_type_radio_brush = m_imgui->calc_text_size(m_desc["tool_brush"]).x + m_imgui->scaled(2.5f);
|
||||
const float tool_type_radio_smart_fill = m_imgui->calc_text_size(m_desc["tool_smart_fill"]).x + m_imgui->scaled(2.5f);
|
||||
|
||||
float caption_max = 0.f;
|
||||
float total_text_max = 0.f;
|
||||
for (const std::string t : {"add_fuzzy_skin", "remove_fuzzy_skin"}) {
|
||||
caption_max = std::max(caption_max, m_imgui->calc_text_size(m_desc[t + "_caption"]).x);
|
||||
total_text_max = std::max(total_text_max, m_imgui->calc_text_size(m_desc[t]).x);
|
||||
}
|
||||
total_text_max += caption_max + m_imgui->scaled(1.f);
|
||||
caption_max += m_imgui->scaled(1.f);
|
||||
|
||||
const float circle_max_width = std::max(clipping_slider_left, cursor_slider_left);
|
||||
|
||||
const float sliders_left_width = std::max(smart_fill_slider_left, std::max(cursor_slider_left, clipping_slider_left));
|
||||
const float slider_icon_width = m_imgui->get_slider_icon_size().x;
|
||||
float window_width = minimal_slider_width + sliders_left_width + slider_icon_width;
|
||||
const float empty_button_width = m_imgui->calc_button_size("").x;
|
||||
|
||||
window_width = std::max(window_width, total_text_max);
|
||||
window_width = std::max(window_width, button_width);
|
||||
window_width = std::max(window_width, cursor_type_radio_circle + cursor_type_radio_sphere + cursor_type_radio_pointer);
|
||||
window_width = std::max(window_width, tool_type_radio_left + tool_type_radio_brush + tool_type_radio_smart_fill);
|
||||
window_width = std::max(window_width, 2.f * buttons_width + m_imgui->scaled(1.f));
|
||||
|
||||
const float sliders_width = m_imgui->scaled(7.0f);
|
||||
const float drag_left_width = ImGui::GetStyle().WindowPadding.x + sliders_width - space_size;
|
||||
|
||||
const float max_tooltip_width = ImGui::GetFontSize() * 20.0f;
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
m_imgui->text(m_desc["tool_type"]);
|
||||
|
||||
std::array<wchar_t, 4> tool_ids;
|
||||
tool_ids = { ImGui::CircleButtonIcon, ImGui::SphereButtonIcon, ImGui::TriangleButtonIcon, ImGui::FillButtonIcon };
|
||||
std::array<wchar_t, 4> icons;
|
||||
if (m_is_dark_mode)
|
||||
icons = { ImGui::CircleButtonDarkIcon, ImGui::SphereButtonDarkIcon, ImGui::TriangleButtonDarkIcon, ImGui::FillButtonDarkIcon };
|
||||
else
|
||||
icons = { ImGui::CircleButtonIcon, ImGui::SphereButtonIcon, ImGui::TriangleButtonIcon, ImGui::FillButtonIcon };
|
||||
std::array<wxString, 4> tool_tips = { _L("Circle"), _L("Sphere"), _L("Triangle"), _L("Fill") };
|
||||
for (int i = 0; i < tool_ids.size(); i++) {
|
||||
std::string str_label = std::string("");
|
||||
std::wstring btn_name = icons[i] + boost::nowide::widen(str_label);
|
||||
|
||||
if (i != 0) ImGui::SameLine((empty_button_width + m_imgui->scaled(1.75f)) * i + m_imgui->scaled(1.5f));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0);
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.f, 0.f, 0.f, 0.f)); // ORCA Removes button background on dark mode
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f)); // ORCA Fixes icon rendered without colors while using Light theme
|
||||
if (m_current_tool == tool_ids[i]) {
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.f, 0.59f, 0.53f, 0.25f)); // ORCA use orca color for selected tool / brush
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.f, 0.59f, 0.53f, 0.25f)); // ORCA use orca color for selected tool / brush
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.f, 0.59f, 0.53f, 0.30f)); // ORCA use orca color for selected tool / brush
|
||||
ImGui::PushStyleColor(ImGuiCol_Border, ImGuiWrapper::COL_ORCA); // ORCA use orca color for border on selected tool / brush
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 1.0);
|
||||
}
|
||||
bool btn_clicked = ImGui::Button(into_u8(btn_name).c_str());
|
||||
if (m_current_tool == tool_ids[i])
|
||||
{
|
||||
ImGui::PopStyleColor(4);
|
||||
ImGui::PopStyleVar(2);
|
||||
}
|
||||
ImGui::PopStyleColor(2);
|
||||
ImGui::PopStyleVar(1);
|
||||
|
||||
if (btn_clicked && m_current_tool != tool_ids[i]) {
|
||||
m_current_tool = tool_ids[i];
|
||||
for (auto &triangle_selector : m_triangle_selectors) {
|
||||
triangle_selector->seed_fill_unselect_all_triangles();
|
||||
triangle_selector->request_update_render_data();
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::IsItemHovered()) {
|
||||
m_imgui->tooltip(tool_tips[i], max_tooltip_width);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Dummy(ImVec2(0.0f, ImGui::GetFontSize() * 0.1));
|
||||
|
||||
if (m_current_tool == ImGui::CircleButtonIcon || m_current_tool == ImGui::SphereButtonIcon) {
|
||||
if (m_current_tool == ImGui::CircleButtonIcon)
|
||||
m_cursor_type = TriangleSelector::CursorType::CIRCLE;
|
||||
else
|
||||
m_cursor_type = TriangleSelector::CursorType::SPHERE;
|
||||
m_tool_type = ToolType::BRUSH;
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
m_imgui->text(m_desc.at("cursor_size"));
|
||||
ImGui::SameLine(circle_max_width);
|
||||
ImGui::PushItemWidth(sliders_width);
|
||||
m_imgui->bbl_slider_float_style("##cursor_radius", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f", 1.0f, true);
|
||||
ImGui::SameLine(drag_left_width + circle_max_width);
|
||||
ImGui::PushItemWidth(1.5 * slider_icon_width);
|
||||
ImGui::BBLDragFloat("##cursor_radius_input", &m_cursor_radius, 0.05f, 0.0f, 0.0f, "%.2f");
|
||||
} else if (m_current_tool == ImGui::TriangleButtonIcon) {
|
||||
m_cursor_type = TriangleSelector::CursorType::POINTER;
|
||||
m_tool_type = ToolType::BRUSH;
|
||||
} else {
|
||||
assert(m_current_tool == ImGui::FillButtonIcon);
|
||||
m_cursor_type = TriangleSelector::CursorType::POINTER;
|
||||
m_tool_type = ToolType::SMART_FILL;
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
m_imgui->text(m_desc["smart_fill_angle"]);
|
||||
std::string format_str = std::string("%.f") +
|
||||
I18N::translate_utf8("°", "Degree sign to use in the respective slider in fuzzy skin gizmo,"
|
||||
"placed after the number with no whitespace in between.");
|
||||
ImGui::SameLine(sliders_left_width);
|
||||
ImGui::PushItemWidth(sliders_width);
|
||||
if (m_imgui->bbl_slider_float_style("##smart_fill_angle", &m_smart_fill_angle, SmartFillAngleMin, SmartFillAngleMax, format_str.data(), 1.0f, true))
|
||||
for (auto &triangle_selector : m_triangle_selectors) {
|
||||
triangle_selector->seed_fill_unselect_all_triangles();
|
||||
triangle_selector->request_update_render_data();
|
||||
}
|
||||
ImGui::SameLine(drag_left_width + sliders_left_width);
|
||||
ImGui::PushItemWidth(1.5 * slider_icon_width);
|
||||
ImGui::BBLDragFloat("##smart_fill_angle_input", &m_smart_fill_angle, 0.05f, 0.0f, 0.0f, "%.2f");
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
if (m_c->object_clipper()->get_position() == 0.f) {
|
||||
ImGui::AlignTextToFramePadding();
|
||||
m_imgui->text(m_desc.at("clipping_of_view"));
|
||||
}
|
||||
else {
|
||||
if (m_imgui->button(m_desc.at("reset_direction"))) {
|
||||
wxGetApp().CallAfter([this](){
|
||||
m_c->object_clipper()->set_position_by_ratio(-1., false);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
auto clp_dist = float(m_c->object_clipper()->get_position());
|
||||
ImGui::SameLine(sliders_left_width);
|
||||
|
||||
ImGui::PushItemWidth(sliders_width);
|
||||
bool slider_clp_dist = m_imgui->bbl_slider_float_style("##clp_dist", &clp_dist, 0.f, 1.f, "%.2f", 1.0f, true);
|
||||
|
||||
ImGui::SameLine(drag_left_width + sliders_left_width);
|
||||
ImGui::PushItemWidth(1.5 * slider_icon_width);
|
||||
bool b_clp_dist_input = ImGui::BBLDragFloat("##clp_dist_input", &clp_dist, 0.05f, 0.0f, 0.0f, "%.2f");
|
||||
if (slider_clp_dist || b_clp_dist_input) { m_c->object_clipper()->set_position_by_ratio(clp_dist, true); }
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(6.0f, 10.0f));
|
||||
float get_cur_y = ImGui::GetContentRegionMax().y + ImGui::GetFrameHeight() + y;
|
||||
show_tooltip_information(caption_max, x, get_cur_y);
|
||||
|
||||
float f_scale = m_parent.get_gizmos_manager().get_layout_scale();
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6.0f, 4.0f * f_scale));
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (m_imgui->button(m_desc.at("remove_all"))) {
|
||||
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _u8L("Reset selection"), UndoRedo::SnapshotType::GizmoAction);
|
||||
ModelObject *mo = m_c->selection_info()->model_object();
|
||||
int idx = -1;
|
||||
for (ModelVolume *mv : mo->volumes)
|
||||
if (mv->is_model_part()) {
|
||||
++idx;
|
||||
m_triangle_selectors[idx]->reset();
|
||||
m_triangle_selectors[idx]->request_update_render_data(true);
|
||||
}
|
||||
|
||||
update_model_object();
|
||||
m_parent.set_as_dirty();
|
||||
}
|
||||
ImGui::PopStyleVar(2);
|
||||
GizmoImguiEnd();
|
||||
|
||||
// BBS
|
||||
ImGuiWrapper::pop_toolbar_style();
|
||||
}
|
||||
|
||||
void GLGizmoFuzzySkin::update_model_object()
|
||||
{
|
||||
bool updated = false;
|
||||
ModelObject *mo = m_c->selection_info()->model_object();
|
||||
int idx = -1;
|
||||
for (ModelVolume *mv : mo->volumes) {
|
||||
if (!mv->is_model_part())
|
||||
continue;
|
||||
|
||||
++idx;
|
||||
updated |= mv->fuzzy_skin_facets.set(*m_triangle_selectors[idx]);
|
||||
}
|
||||
|
||||
if (updated) {
|
||||
const ModelObjectPtrs &mos = wxGetApp().model().objects;
|
||||
wxGetApp().obj_list()->update_info_items(std::find(mos.begin(), mos.end(), mo) - mos.begin());
|
||||
|
||||
m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
|
||||
}
|
||||
}
|
||||
|
||||
void GLGizmoFuzzySkin::update_from_model_object(bool first_update)
|
||||
{
|
||||
wxBusyCursor wait;
|
||||
|
||||
const ModelObject *mo = m_c->selection_info()->model_object();
|
||||
m_triangle_selectors.clear();
|
||||
|
||||
int volume_id = -1;
|
||||
std::vector<ColorRGBA> ebt_colors;
|
||||
ebt_colors.push_back(GLVolume::NEUTRAL_COLOR);
|
||||
ebt_colors.push_back(TriangleSelectorGUI::enforcers_color);
|
||||
ebt_colors.push_back(TriangleSelectorGUI::blockers_color);
|
||||
for (const ModelVolume *mv : mo->volumes) {
|
||||
if (!mv->is_model_part())
|
||||
continue;
|
||||
|
||||
++volume_id;
|
||||
|
||||
// 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<TriangleSelectorPatch>(*mesh, ebt_colors));
|
||||
// Reset of TriangleSelector is done inside TriangleSelectorGUI's constructor, so we don't need it to perform it again in deserialize().
|
||||
m_triangle_selectors.back()->deserialize(mv->fuzzy_skin_facets.get_data(), false);
|
||||
m_triangle_selectors.back()->request_update_render_data();
|
||||
}
|
||||
}
|
||||
|
||||
PainterGizmoType GLGizmoFuzzySkin::get_painter_type() const
|
||||
{
|
||||
return PainterGizmoType::FUZZY_SKIN;
|
||||
}
|
||||
|
||||
wxString GLGizmoFuzzySkin::handle_snapshot_action_name(bool shift_down, GLGizmoPainterBase::Button button_down) const
|
||||
{
|
||||
return shift_down ? _L("Remove fuzzy skin") : _L("Add fuzzy skin");
|
||||
}
|
||||
|
||||
} // namespace Slic3r::GUI
|
||||
52
src/slic3r/GUI/Gizmos/GLGizmoFuzzySkin.hpp
Normal file
52
src/slic3r/GUI/Gizmos/GLGizmoFuzzySkin.hpp
Normal file
@@ -0,0 +1,52 @@
|
||||
#ifndef slic3r_GLGizmoFuzzySkin_hpp_
|
||||
#define slic3r_GLGizmoFuzzySkin_hpp_
|
||||
|
||||
#include "GLGizmoPainterBase.hpp"
|
||||
|
||||
#include "slic3r/GUI/I18N.hpp"
|
||||
|
||||
namespace Slic3r::GUI {
|
||||
|
||||
class GLGizmoFuzzySkin : public GLGizmoPainterBase
|
||||
{
|
||||
public:
|
||||
GLGizmoFuzzySkin(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
|
||||
|
||||
void render_painter_gizmo() override;
|
||||
|
||||
protected:
|
||||
void on_render_input_window(float x, float y, float bottom_limit) override;
|
||||
std::string on_get_name() const override;
|
||||
|
||||
void show_tooltip_information(float caption_max, float x, float y);
|
||||
|
||||
wxString handle_snapshot_action_name(bool shift_down, Button button_down) const override;
|
||||
|
||||
std::string get_gizmo_entering_text() const override { return _u8L("Entering Paint-on fuzzy skin"); }
|
||||
std::string get_gizmo_leaving_text() const override { return _u8L("Leaving Paint-on fuzzy skin"); }
|
||||
std::string get_action_snapshot_name() const override { return _u8L("Paint-on fuzzy skin editing"); }
|
||||
|
||||
EnforcerBlockerType get_left_button_state_type() const override { return EnforcerBlockerType::FUZZY_SKIN; }
|
||||
EnforcerBlockerType get_right_button_state_type() const override { return EnforcerBlockerType::NONE; }
|
||||
|
||||
// BBS
|
||||
wchar_t m_current_tool = 0;
|
||||
|
||||
private:
|
||||
bool on_init() override;
|
||||
|
||||
void update_model_object() override;
|
||||
void update_from_model_object(bool first_update) override;
|
||||
|
||||
void on_opening() override {}
|
||||
void on_shutdown() override;
|
||||
PainterGizmoType get_painter_type() const override;
|
||||
|
||||
// This map holds all translated description texts, so they can be easily referenced during layout calculations
|
||||
// etc. When language changes, GUI is recreated, and this class constructed again, so the change takes effect.
|
||||
std::map<std::string, wxString> m_desc;
|
||||
};
|
||||
|
||||
} // namespace Slic3r::GUI
|
||||
|
||||
#endif // slic3r_GLGizmoFuzzySkin_hpp_
|
||||
@@ -189,58 +189,6 @@ void GLGizmoMmuSegmentation::data_changed(bool is_serializing)
|
||||
}
|
||||
}
|
||||
|
||||
void GLGizmoMmuSegmentation::render_triangles(const Selection &selection) const
|
||||
{
|
||||
ClippingPlaneDataWrapper clp_data = this->get_clipping_plane_data();
|
||||
auto* shader = wxGetApp().get_shader("mm_gouraud");
|
||||
if (!shader)
|
||||
return;
|
||||
shader->start_using();
|
||||
shader->set_uniform("clipping_plane", clp_data.clp_dataf);
|
||||
shader->set_uniform("z_range", clp_data.z_range);
|
||||
shader->set_uniform("slope.actived", m_parent.is_using_slope());
|
||||
ScopeGuard guard([shader]() { if (shader) shader->stop_using(); });
|
||||
|
||||
//BBS: to improve the random white pixel issue
|
||||
glsafe(::glDisable(GL_CULL_FACE));
|
||||
|
||||
const ModelObject *mo = m_c->selection_info()->model_object();
|
||||
int mesh_id = -1;
|
||||
for (const ModelVolume *mv : mo->volumes) {
|
||||
if (!mv->is_model_part())
|
||||
continue;
|
||||
|
||||
++mesh_id;
|
||||
|
||||
Transform3d trafo_matrix;
|
||||
if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) {
|
||||
trafo_matrix = mo->instances[selection.get_instance_idx()]->get_assemble_transformation().get_matrix() * mv->get_matrix();
|
||||
trafo_matrix.translate(mv->get_transformation().get_offset() * (GLVolume::explosion_ratio - 1.0) + mo->instances[selection.get_instance_idx()]->get_offset_to_assembly() * (GLVolume::explosion_ratio - 1.0));
|
||||
}
|
||||
else {
|
||||
trafo_matrix = mo->instances[selection.get_instance_idx()]->get_transformation().get_matrix()* mv->get_matrix();
|
||||
}
|
||||
|
||||
const bool is_left_handed = trafo_matrix.matrix().determinant() < 0.0;
|
||||
if (is_left_handed)
|
||||
glsafe(::glFrontFace(GL_CW));
|
||||
|
||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||
const Transform3d& view_matrix = camera.get_view_matrix();
|
||||
shader->set_uniform("view_model_matrix", view_matrix * trafo_matrix);
|
||||
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||
const Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * trafo_matrix.matrix().block(0, 0, 3, 3).inverse().transpose();
|
||||
shader->set_uniform("view_normal_matrix", view_normal_matrix);
|
||||
|
||||
shader->set_uniform("volume_world_matrix", trafo_matrix);
|
||||
shader->set_uniform("volume_mirrored", is_left_handed);
|
||||
m_triangle_selectors[mesh_id]->render(m_imgui, trafo_matrix);
|
||||
|
||||
if (is_left_handed)
|
||||
glsafe(::glFrontFace(GL_CCW));
|
||||
}
|
||||
}
|
||||
|
||||
// BBS
|
||||
bool GLGizmoMmuSegmentation::on_number_key_down(int number)
|
||||
{
|
||||
@@ -869,7 +817,7 @@ void GLGizmoMmuSegmentation::tool_changed(wchar_t old_tool, wchar_t new_tool)
|
||||
|
||||
PainterGizmoType GLGizmoMmuSegmentation::get_painter_type() const
|
||||
{
|
||||
return PainterGizmoType::MMU_SEGMENTATION;
|
||||
return PainterGizmoType::MM_SEGMENTATION;
|
||||
}
|
||||
|
||||
// BBS
|
||||
|
||||
@@ -71,8 +71,6 @@ public:
|
||||
|
||||
void data_changed(bool is_serializing) override;
|
||||
|
||||
void render_triangles(const Selection& selection) const override;
|
||||
|
||||
// TriangleSelector::serialization/deserialization has a limit to store 19 different states.
|
||||
// EXTRUDER_LIMIT + 1 states are used to storing the painting because also uncolored triangles are stored.
|
||||
// When increasing EXTRUDER_LIMIT, it needs to ensure that TriangleSelector::serialization/deserialization
|
||||
|
||||
@@ -75,23 +75,27 @@ GLGizmoPainterBase::ClippingPlaneDataWrapper GLGizmoPainterBase::get_clipping_pl
|
||||
|
||||
void GLGizmoPainterBase::render_triangles(const Selection& selection) const
|
||||
{
|
||||
auto* shader = wxGetApp().get_shader("gouraud");
|
||||
if (! shader)
|
||||
auto* shader = wxGetApp().get_shader("mm_gouraud");
|
||||
if (!shader)
|
||||
return;
|
||||
shader->start_using();
|
||||
shader->set_uniform("slope.actived", false);
|
||||
shader->set_uniform("print_volume.type", 0);
|
||||
shader->set_uniform("clipping_plane", this->get_clipping_plane_data().clp_dataf);
|
||||
ScopeGuard guard([shader]() { if (shader) shader->stop_using(); });
|
||||
|
||||
const ModelObject *mo = m_c->selection_info()->model_object();
|
||||
ClippingPlaneDataWrapper clp_data = this->get_clipping_plane_data();
|
||||
shader->set_uniform("clipping_plane", clp_data.clp_dataf);
|
||||
shader->set_uniform("z_range", clp_data.z_range);
|
||||
|
||||
// BBS: to improve the random white pixel issue
|
||||
glsafe(::glDisable(GL_CULL_FACE));
|
||||
|
||||
const ModelObject* mo = m_c->selection_info()->model_object();
|
||||
int mesh_id = -1;
|
||||
for (const ModelVolume* mv : mo->volumes) {
|
||||
if (! mv->is_model_part())
|
||||
if (!mv->is_model_part())
|
||||
continue;
|
||||
|
||||
++mesh_id;
|
||||
|
||||
|
||||
Transform3d trafo_matrix;
|
||||
if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) {
|
||||
trafo_matrix = mo->instances[selection.get_instance_idx()]->get_assemble_transformation().get_matrix() * mv->get_matrix();
|
||||
@@ -112,13 +116,16 @@ void GLGizmoPainterBase::render_triangles(const Selection& selection) const
|
||||
const Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * trafo_matrix.matrix().block(0, 0, 3, 3).inverse().transpose();
|
||||
shader->set_uniform("view_normal_matrix", view_normal_matrix);
|
||||
|
||||
// For printers with multiple extruders, it is necessary to pass trafo_matrix
|
||||
// to the shader input variable print_box.volume_world_matrix before
|
||||
// rendering the painted triangles. When this matrix is not set, the
|
||||
// wrong transformation matrix is used for "Clipping of view".
|
||||
shader->set_uniform("volume_world_matrix", trafo_matrix);
|
||||
float normal_z = -::cos(Geometry::deg2rad(m_highlight_by_angle_threshold_deg));
|
||||
Matrix3f normal_matrix = static_cast<Matrix3f>(trafo_matrix.matrix().block(0, 0, 3, 3).inverse().transpose().cast<float>());
|
||||
|
||||
shader->set_uniform("volume_world_matrix", trafo_matrix);
|
||||
shader->set_uniform("volume_mirrored", is_left_handed);
|
||||
shader->set_uniform("slope.actived", m_parent.is_using_slope());
|
||||
shader->set_uniform("slope.volume_world_normal_matrix", normal_matrix);
|
||||
shader->set_uniform("slope.normal_z", normal_z);
|
||||
m_triangle_selectors[mesh_id]->render(m_imgui, trafo_matrix);
|
||||
|
||||
if (is_left_handed)
|
||||
glsafe(::glFrontFace(GL_CCW));
|
||||
}
|
||||
|
||||
@@ -26,7 +26,8 @@ class Selection;
|
||||
enum class PainterGizmoType {
|
||||
FDM_SUPPORTS,
|
||||
SEAM,
|
||||
MMU_SEGMENTATION
|
||||
MM_SEGMENTATION,
|
||||
FUZZY_SKIN
|
||||
};
|
||||
|
||||
class TriangleSelectorGUI : public TriangleSelector {
|
||||
|
||||
@@ -95,53 +95,6 @@ bool GLGizmoSeam::on_key_down_select_tool_type(int keyCode) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void GLGizmoSeam::render_triangles(const Selection& selection) const
|
||||
{
|
||||
ClippingPlaneDataWrapper clp_data = this->get_clipping_plane_data();
|
||||
auto* shader = wxGetApp().get_shader("mm_gouraud");
|
||||
if (!shader)
|
||||
return;
|
||||
shader->start_using();
|
||||
shader->set_uniform("clipping_plane", clp_data.clp_dataf);
|
||||
shader->set_uniform("z_range", clp_data.z_range);
|
||||
ScopeGuard guard([shader]() { if (shader) shader->stop_using(); });
|
||||
|
||||
const ModelObject* mo = m_c->selection_info()->model_object();
|
||||
int mesh_id = -1;
|
||||
for (const ModelVolume* mv : mo->volumes) {
|
||||
if (!mv->is_model_part())
|
||||
continue;
|
||||
|
||||
++mesh_id;
|
||||
|
||||
const Transform3d trafo_matrix = mo->instances[selection.get_instance_idx()]->get_transformation().get_matrix() * mv->get_matrix();
|
||||
|
||||
bool is_left_handed = trafo_matrix.matrix().determinant() < 0.;
|
||||
if (is_left_handed)
|
||||
glsafe(::glFrontFace(GL_CW));
|
||||
|
||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||
const Transform3d& view_matrix = camera.get_view_matrix();
|
||||
shader->set_uniform("view_model_matrix", view_matrix * trafo_matrix);
|
||||
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||
const Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * trafo_matrix.matrix().block(0, 0, 3, 3).inverse().transpose();
|
||||
shader->set_uniform("view_normal_matrix", view_normal_matrix);
|
||||
|
||||
float normal_z = -::cos(Geometry::deg2rad(m_highlight_by_angle_threshold_deg));
|
||||
Matrix3f normal_matrix = static_cast<Matrix3f>(trafo_matrix.matrix().block(0, 0, 3, 3).inverse().transpose().cast<float>());
|
||||
|
||||
shader->set_uniform("volume_world_matrix", trafo_matrix);
|
||||
shader->set_uniform("volume_mirrored", is_left_handed);
|
||||
shader->set_uniform("slope.actived", m_parent.is_using_slope());
|
||||
shader->set_uniform("slope.volume_world_normal_matrix", normal_matrix);
|
||||
shader->set_uniform("slope.normal_z", normal_z);
|
||||
m_triangle_selectors[mesh_id]->render(m_imgui, trafo_matrix);
|
||||
|
||||
if (is_left_handed)
|
||||
glsafe(::glFrontFace(GL_CCW));
|
||||
}
|
||||
}
|
||||
|
||||
void GLGizmoSeam::show_tooltip_information(float caption_max, float x, float y)
|
||||
{
|
||||
ImTextureID normal_id = m_parent.get_gizmos_manager().get_icon_texture_id(GLGizmosManager::MENU_ICON_NAME::IC_TOOLBAR_TOOLTIP);
|
||||
|
||||
@@ -24,8 +24,6 @@ protected:
|
||||
std::string on_get_name() const override;
|
||||
PainterGizmoType get_painter_type() const override;
|
||||
|
||||
void render_triangles(const Selection &selection) const override;
|
||||
|
||||
void show_tooltip_information(float caption_max, float x, float y);
|
||||
|
||||
void tool_changed(wchar_t old_tool, wchar_t new_tool);
|
||||
|
||||
@@ -32,6 +32,7 @@ enum class SLAGizmoEventType : unsigned char {
|
||||
#include "slic3r/GUI/Gizmos/GLGizmoFlatten.hpp"
|
||||
#include "slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp"
|
||||
#include "slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp"
|
||||
#include "slic3r/GUI/Gizmos/GLGizmoFuzzySkin.hpp"
|
||||
#include "slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp"
|
||||
// BBS
|
||||
#include "slic3r/GUI/Gizmos/GLGizmoAdvancedCut.hpp"
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "slic3r/GUI/Gizmos/GLGizmoFlatten.hpp"
|
||||
//#include "slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp"
|
||||
#include "slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp"
|
||||
#include "slic3r/GUI/Gizmos/GLGizmoFuzzySkin.hpp"
|
||||
#include "slic3r/GUI/Gizmos/GLGizmoBrimEars.hpp"
|
||||
#include "slic3r/GUI/Gizmos/GLGizmoCut.hpp"
|
||||
//#include "slic3r/GUI/Gizmos/GLGizmoFaceDetector.hpp"
|
||||
@@ -66,7 +67,7 @@ std::vector<size_t> GLGizmosManager::get_selectable_idxs() const
|
||||
m_gizmos[i]->get_sprite_id() == (unsigned int) Rotate ||
|
||||
m_gizmos[i]->get_sprite_id() == (unsigned int) Measure ||
|
||||
m_gizmos[i]->get_sprite_id() == (unsigned int) Assembly ||
|
||||
m_gizmos[i]->get_sprite_id() == (unsigned int) MmuSegmentation)
|
||||
m_gizmos[i]->get_sprite_id() == (unsigned int) MmSegmentation)
|
||||
out.push_back(i);
|
||||
}
|
||||
else {
|
||||
@@ -157,9 +158,12 @@ void GLGizmosManager::switch_gizmos_icon_filename()
|
||||
case(EType::Emboss):
|
||||
gizmo->set_icon_filename(m_is_dark ? "toolbar_text_dark.svg" : "toolbar_text.svg");
|
||||
break;
|
||||
case(EType::MmuSegmentation):
|
||||
case(EType::MmSegmentation):
|
||||
gizmo->set_icon_filename(m_is_dark ? "mmu_segmentation_dark.svg" : "mmu_segmentation.svg");
|
||||
break;
|
||||
case(EType::FuzzySkin):
|
||||
gizmo->set_icon_filename(m_is_dark ? "toolbar_fuzzy_skin_paint_dark.svg" : "toolbar_fuzzy_skin_paint.svg");
|
||||
break;
|
||||
case(EType::MeshBoolean):
|
||||
gizmo->set_icon_filename(m_is_dark ? "toolbar_meshboolean_dark.svg" : "toolbar_meshboolean.svg");
|
||||
break;
|
||||
@@ -206,7 +210,8 @@ bool GLGizmosManager::init()
|
||||
m_gizmos.emplace_back(new GLGizmoMeshBoolean(m_parent, m_is_dark ? "toolbar_meshboolean_dark.svg" : "toolbar_meshboolean.svg", EType::MeshBoolean));
|
||||
m_gizmos.emplace_back(new GLGizmoFdmSupports(m_parent, m_is_dark ? "toolbar_support_dark.svg" : "toolbar_support.svg", EType::FdmSupports));
|
||||
m_gizmos.emplace_back(new GLGizmoSeam(m_parent, m_is_dark ? "toolbar_seam_dark.svg" : "toolbar_seam.svg", EType::Seam));
|
||||
m_gizmos.emplace_back(new GLGizmoMmuSegmentation(m_parent, m_is_dark ? "mmu_segmentation_dark.svg" : "mmu_segmentation.svg", EType::MmuSegmentation));
|
||||
m_gizmos.emplace_back(new GLGizmoFuzzySkin(m_parent, m_is_dark ? "toolbar_fuzzy_skin_paint_dark.svg" : "toolbar_fuzzy_skin_paint.svg", EType::FuzzySkin));
|
||||
m_gizmos.emplace_back(new GLGizmoMmuSegmentation(m_parent, m_is_dark ? "mmu_segmentation_dark.svg" : "mmu_segmentation.svg", EType::MmSegmentation));
|
||||
m_gizmos.emplace_back(new GLGizmoEmboss(m_parent, m_is_dark ? "toolbar_text_dark.svg" : "toolbar_text.svg", EType::Emboss));
|
||||
m_gizmos.emplace_back(new GLGizmoSVG(m_parent));
|
||||
m_gizmos.emplace_back(new GLGizmoMeasure(m_parent, m_is_dark ? "toolbar_measure_dark.svg" : "toolbar_measure.svg", EType::Measure));
|
||||
@@ -465,14 +470,16 @@ bool GLGizmosManager::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_p
|
||||
return dynamic_cast<GLGizmoFdmSupports*>(m_gizmos[FdmSupports].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
|
||||
else if (m_current == Seam)
|
||||
return dynamic_cast<GLGizmoSeam*>(m_gizmos[Seam].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
|
||||
else if (m_current == MmuSegmentation)
|
||||
return dynamic_cast<GLGizmoMmuSegmentation*>(m_gizmos[MmuSegmentation].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
|
||||
else if (m_current == MmSegmentation)
|
||||
return dynamic_cast<GLGizmoMmuSegmentation*>(m_gizmos[MmSegmentation].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
|
||||
else if (m_current == Measure)
|
||||
return dynamic_cast<GLGizmoMeasure *>(m_gizmos[Measure].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
|
||||
else if (m_current == Assembly)
|
||||
return dynamic_cast<GLGizmoAssembly *>(m_gizmos[Assembly].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
|
||||
else if (m_current == Cut)
|
||||
return dynamic_cast<GLGizmoCut3D*>(m_gizmos[Cut].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
|
||||
else if (m_current == FuzzySkin)
|
||||
return dynamic_cast<GLGizmoFuzzySkin*>(m_gizmos[FuzzySkin].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
|
||||
else if (m_current == MeshBoolean)
|
||||
return dynamic_cast<GLGizmoMeshBoolean*>(m_gizmos[MeshBoolean].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
|
||||
else if (m_current == BrimEars)
|
||||
@@ -484,7 +491,8 @@ bool GLGizmosManager::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_p
|
||||
bool GLGizmosManager::is_paint_gizmo()
|
||||
{
|
||||
return m_current == EType::FdmSupports ||
|
||||
m_current == EType::MmuSegmentation ||
|
||||
m_current == EType::MmSegmentation ||
|
||||
m_current == EType::FuzzySkin ||
|
||||
m_current == EType::Seam;
|
||||
}
|
||||
|
||||
@@ -583,7 +591,7 @@ bool GLGizmosManager::on_mouse_wheel(const wxMouseEvent &evt)
|
||||
{
|
||||
bool processed = false;
|
||||
|
||||
if (/*m_current == SlaSupports || m_current == Hollow ||*/ m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation || m_current == BrimEars) {
|
||||
if (/*m_current == SlaSupports || m_current == Hollow ||*/ m_current == FdmSupports || m_current == Seam || m_current == MmSegmentation || m_current == FuzzySkin || m_current == BrimEars) {
|
||||
float rot = (float)evt.GetWheelRotation() / (float)evt.GetWheelDelta();
|
||||
if (gizmo_event((rot > 0.f ? SLAGizmoEventType::MouseWheelUp : SLAGizmoEventType::MouseWheelDown), Vec2d::Zero(), evt.ShiftDown(), evt.AltDown()
|
||||
// BBS
|
||||
@@ -781,7 +789,7 @@ bool GLGizmosManager::on_char(wxKeyEvent& evt)
|
||||
//case 'r' :
|
||||
//case 'R' :
|
||||
//{
|
||||
//if ((m_current == SlaSupports || m_current == Hollow || m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation) && gizmo_event(SLAGizmoEventType::ResetClippingPlane))
|
||||
//if ((m_current == SlaSupports || m_current == Hollow || m_current == FdmSupports || m_current == Seam || m_current == MmSegmentation || m_current == FuzzySkin) && gizmo_event(SLAGizmoEventType::ResetClippingPlane))
|
||||
// processed = true;
|
||||
|
||||
//break;
|
||||
@@ -890,7 +898,7 @@ bool GLGizmosManager::on_key(wxKeyEvent& evt)
|
||||
}
|
||||
}
|
||||
// BBS
|
||||
if (m_current == MmuSegmentation && keyCode > '0' && keyCode <= '9') {
|
||||
if (m_current == MmSegmentation && keyCode > '0' && keyCode <= '9') {
|
||||
// capture number key
|
||||
processed = true;
|
||||
}
|
||||
@@ -939,7 +947,7 @@ bool GLGizmosManager::on_key(wxKeyEvent& evt)
|
||||
processed = simplify->on_esc_key_down();
|
||||
}
|
||||
// BBS
|
||||
else if (m_current == MmuSegmentation) {
|
||||
else if (m_current == MmSegmentation) {
|
||||
GLGizmoMmuSegmentation* mmu_seg = dynamic_cast<GLGizmoMmuSegmentation*>(get_current());
|
||||
if (mmu_seg != nullptr) {
|
||||
if (keyCode >= WXK_NUMPAD0 && keyCode <= WXK_NUMPAD9) {
|
||||
@@ -1002,7 +1010,7 @@ bool GLGizmosManager::on_key(wxKeyEvent& evt)
|
||||
|
||||
void GLGizmosManager::on_set_color_timer(wxTimerEvent& evt)
|
||||
{
|
||||
if (m_current == MmuSegmentation) {
|
||||
if (m_current == MmSegmentation) {
|
||||
GLGizmoMmuSegmentation* mmu_seg = dynamic_cast<GLGizmoMmuSegmentation*>(get_current());
|
||||
mmu_seg->on_number_key_down(1);
|
||||
m_parent.set_as_dirty();
|
||||
@@ -1415,8 +1423,10 @@ std::string get_name_from_gizmo_etype(GLGizmosManager::EType type)
|
||||
return "Seam";
|
||||
case GLGizmosManager::EType::Emboss:
|
||||
return "Text";
|
||||
case GLGizmosManager::EType::MmuSegmentation:
|
||||
case GLGizmosManager::EType::MmSegmentation:
|
||||
return "Color Painting";
|
||||
case GLGizmosManager::EType::FuzzySkin:
|
||||
return "Fuzzy Skin Painting";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -82,7 +82,8 @@ public:
|
||||
MeshBoolean,
|
||||
FdmSupports,
|
||||
Seam,
|
||||
MmuSegmentation,
|
||||
FuzzySkin,
|
||||
MmSegmentation,
|
||||
Emboss,
|
||||
Svg,
|
||||
Measure,
|
||||
|
||||
Reference in New Issue
Block a user