From a8440db5ec6cff6319a8bb7b9824a416d1414be4 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Fri, 30 Sep 2022 14:07:17 +0200 Subject: [PATCH] Cut WIP: * ObjectList & Selection: Show Connectors in the Scene, when CutConnectors Item is selected * ObjectList: refactoring: extract the adding of volumes to the add_volumes_to_object_in_list() * If some connector is selected on 3dScene -> select all connectors of this object * GLGizmoScale3D : check if grabber is enabled, when do rendering + GLGizmoCut: refactoring : split render_cut_plane_grabbers to several functions --- src/slic3r/GUI/GUI_ObjectList.cpp | 235 +++++++++++++--------- src/slic3r/GUI/GUI_ObjectList.hpp | 2 + src/slic3r/GUI/GUI_ObjectManipulation.cpp | 2 +- src/slic3r/GUI/Gizmos/GLGizmoCut.cpp | 204 +++++++++---------- src/slic3r/GUI/Gizmos/GLGizmoCut.hpp | 6 +- src/slic3r/GUI/Gizmos/GLGizmoMove.cpp | 7 +- src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp | 7 +- src/slic3r/GUI/Gizmos/GLGizmoScale.cpp | 13 +- src/slic3r/GUI/Selection.cpp | 22 ++ src/slic3r/GUI/Selection.hpp | 2 + 10 files changed, 268 insertions(+), 232 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 05eb02778e..d3f1d1bf27 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -403,6 +403,13 @@ MeshErrorsInfo ObjectList::get_mesh_errors_info(const int obj_idx, const int vol if (obj_idx < 0) return { {}, {} }; // hide tooltip + const ModelObject* object = (*m_objects)[obj_idx]; + if (vol_idx != -1 && vol_idx >= int(object->volumes.size())) { + if (sidebar_info) + *sidebar_info = _L("Wrong volume index "); + return { {}, {} }; // hide tooltip + } + const TriangleMeshStats& stats = vol_idx == -1 ? (*m_objects)[obj_idx]->get_object_stl_stats() : (*m_objects)[obj_idx]->volumes[vol_idx]->mesh().stats(); @@ -2075,30 +2082,11 @@ void ObjectList::split() volume->split(nozzle_dmrs_cnt); + (*m_objects)[obj_idx]->input_file.clear(); + wxBusyCursor wait; - auto model_object = (*m_objects)[obj_idx]; - - auto parent = m_objects_model->GetTopParent(item); - if (parent) - m_objects_model->DeleteVolumeChildren(parent); - else - parent = item; - - for (const ModelVolume* volume : model_object->volumes) { - const wxDataViewItem& vol_item = m_objects_model->AddVolumeChild(parent, from_u8(volume->name), - volume->type(),// is_modifier() ? ModelVolumeType::PARAMETER_MODIFIER : ModelVolumeType::MODEL_PART, - get_warning_icon_name(volume->mesh().stats()), - volume->config.has("extruder") ? volume->config.extruder() : 0, - false); - // add settings to the part, if it has those - add_settings_item(vol_item, &volume->config.get()); - } - - model_object->input_file.clear(); - - if (parent == item) - Expand(parent); + add_volumes_to_object_in_list(obj_idx); changed_object(obj_idx); // update printable state for new volumes on canvas3D @@ -2524,7 +2512,14 @@ void ObjectList::part_selection_changed() GLGizmosManager& gizmos_mgr = wxGetApp().plater()->canvas3D()->get_gizmos_manager(); - if ( multiple_selection() || (item && m_objects_model->GetItemType(item) == itInstanceRoot )) { + if (item && m_objects_model->GetItemType(item) == itInfo && m_objects_model->GetInfoItemType(item) == InfoItemType::CutConnectors) { + og_name = _L("Cut Connectors information"); + + update_and_show_manipulations = true; + enable_manipulation = false; + disable_ununiform_scale = true; + } + else if ( multiple_selection() || (item && m_objects_model->GetItemType(item) == itInstanceRoot )) { og_name = _L("Group manipulation"); const Selection& selection = scene_selection(); @@ -2575,11 +2570,12 @@ void ObjectList::part_selection_changed() const wxDataViewItem parent = m_objects_model->GetParent(item); const ItemType parent_type = m_objects_model->GetItemType(parent); obj_idx = m_objects_model->GetObjectIdByItem(item); + ModelObject* object = (*m_objects)[obj_idx]; if (parent == wxDataViewItem(nullptr) || type == itInfo) { og_name = _L("Object manipulation"); - m_config = &(*m_objects)[obj_idx]->config; + m_config = &object->config; update_and_show_manipulations = true; if (type == itInfo) { @@ -2602,23 +2598,23 @@ void ObjectList::part_selection_changed() gizmos_mgr.open_gizmo(gizmo_type); break; } - case InfoItemType::Sinking: { break; } + case InfoItemType::Sinking: default: { break; } } } else - disable_ss_manipulation = (*m_objects)[obj_idx]->is_cut(); + disable_ss_manipulation = object->is_cut(); } else { if (type & itSettings) { if (parent_type & itObject) { og_name = _L("Object Settings to modify"); - m_config = &(*m_objects)[obj_idx]->config; + m_config = &object->config; } else if (parent_type & itVolume) { og_name = _L("Part Settings to modify"); volume_id = m_objects_model->GetVolumeIdByItem(parent); - m_config = &(*m_objects)[obj_idx]->volumes[volume_id]->config; + m_config = &object->volumes[volume_id]->config; } else if (parent_type & itLayer) { og_name = _L("Layer range Settings to modify"); @@ -2629,17 +2625,17 @@ void ObjectList::part_selection_changed() else if (type & itVolume) { og_name = _L("Part manipulation"); volume_id = m_objects_model->GetVolumeIdByItem(item); - m_config = &(*m_objects)[obj_idx]->volumes[volume_id]->config; + m_config = &object->volumes[volume_id]->config; update_and_show_manipulations = true; - enable_manipulation = !(*m_objects)[obj_idx]->is_cut(); + enable_manipulation = !(object->is_cut() && object->volumes[volume_id]->is_cut_connector()); } else if (type & itInstance) { og_name = _L("Instance manipulation"); update_and_show_manipulations = true; // fill m_config by object's values - m_config = &(*m_objects)[obj_idx]->config; - disable_ss_manipulation = (*m_objects)[obj_idx]->is_cut(); + m_config = &object->config; + disable_ss_manipulation = object->is_cut(); } else if (type & (itLayerRoot|itLayer)) { og_name = type & itLayerRoot ? _L("Height ranges") : _L("Settings for height range"); @@ -2658,7 +2654,6 @@ void ObjectList::part_selection_changed() wxGetApp().obj_manipul()->get_og()->set_name(" " + og_name + " "); if (item) { - // wxGetApp().obj_manipul()->get_og()->set_value("object_name", m_objects_model->GetName(item)); wxGetApp().obj_manipul()->update_item_name(m_objects_model->GetName(item)); wxGetApp().obj_manipul()->update_warning_icon_state(get_mesh_errors_info(obj_idx, volume_id)); } @@ -2817,43 +2812,70 @@ void ObjectList::update_info_items(size_t obj_idx, wxDataViewItemArray* selectio } } +static wxString extruder2str(int extruder) +{ + return extruder == 0 ? _L("default") : wxString::Format("%d", extruder); +} +static bool can_add_volumes_to_object(const ModelObject* object) +{ + bool can = object->volumes.size() > 1; + + if (can && object->is_cut()) { + int no_connectors_cnt = 0; + for (const ModelVolume* v : object->volumes) + if (!v->is_cut_connector()) + no_connectors_cnt++; + can = no_connectors_cnt > 1; + } + + return can; +} + +wxDataViewItemArray ObjectList::add_volumes_to_object_in_list(size_t obj_idx, std::function add_to_selection/* = nullptr*/) +{ + wxDataViewItem object_item = m_objects_model->GetItemById(int(obj_idx)); + m_objects_model->DeleteVolumeChildren(object_item); + + wxDataViewItemArray items; + + const ModelObject* object = (*m_objects)[obj_idx]; + // add volumes to the object + if (can_add_volumes_to_object(object)) { + int volume_idx{ -1 }; + for (const ModelVolume* volume : object->volumes) { + ++volume_idx; + if (object->is_cut() && volume->is_cut_connector()) + continue; + const wxDataViewItem& vol_item = m_objects_model->AddVolumeChild(object_item, + from_u8(volume->name), + volume_idx, + volume->type(), + get_warning_icon_name(volume->mesh().stats()), + extruder2str(volume->config.has("extruder") ? volume->config.extruder() : 0)); + add_settings_item(vol_item, &volume->config.get()); + + if (add_to_selection && add_to_selection(volume)) + items.Add(vol_item); + } + Expand(object_item); + } + + return items; +} void ObjectList::add_object_to_list(size_t obj_idx, bool call_selection_changed) { auto model_object = (*m_objects)[obj_idx]; const wxString& item_name = from_u8(model_object->name); - const auto item = m_objects_model->Add(item_name, - model_object->config.has("extruder") ? model_object->config.extruder() : 0, + const auto item = m_objects_model->AddObject(item_name, + extruder2str(model_object->config.has("extruder") ? model_object->config.extruder() : 0), get_warning_icon_name(model_object->mesh().stats()), model_object->is_cut()); update_info_items(obj_idx, nullptr, call_selection_changed); - bool can_add_volumes = model_object->volumes.size() > 1; - if (can_add_volumes && model_object->is_cut()) { - int no_connectors_cnt = 0; - for (const ModelVolume* v : model_object->volumes) - if (!v->is_cut_connector()) - no_connectors_cnt++; - can_add_volumes = no_connectors_cnt > 1; - } - - // add volumes to the object - if (can_add_volumes) { - for (const ModelVolume* volume : model_object->volumes) { - if (model_object->is_cut() && volume->is_cut_connector()) - continue; - const wxDataViewItem& vol_item = m_objects_model->AddVolumeChild(item, - from_u8(volume->name), - volume->type(), - get_warning_icon_name(volume->mesh().stats()), - volume->config.has("extruder") ? volume->config.extruder() : 0, - false); - add_settings_item(vol_item, &volume->config.get()); - } - Expand(item); - } + add_volumes_to_object_in_list(obj_idx); // add instances to the object, if it has those if (model_object->instances.size()>1) @@ -3327,7 +3349,7 @@ void ObjectList::add_layer_item(const t_layer_height_range& range, const auto layer_item = m_objects_model->AddLayersChild(layers_item, range, - config.opt_int("extruder"), + extruder2str(config.opt_int("extruder")), layer_idx); add_settings_item(layer_item, &config); } @@ -3421,6 +3443,24 @@ bool ObjectList::is_selected(const ItemType type) const return false; } +bool ObjectList::is_connectors_item_selected() const +{ + const wxDataViewItem& item = GetSelection(); + if (item) + return m_objects_model->GetItemType(item) == itInfo && m_objects_model->GetInfoItemType(item) == InfoItemType::CutConnectors; + + return false; +} + +bool ObjectList::is_connectors_item_selected(const wxDataViewItemArray& sels) const +{ + for (auto item : sels) + if (m_objects_model->GetItemType(item) == itInfo && m_objects_model->GetInfoItemType(item) == InfoItemType::CutConnectors) + return true; + + return false; +} + int ObjectList::get_selected_layers_range_idx() const { const wxDataViewItem& item = GetSelection(); @@ -3547,11 +3587,18 @@ void ObjectList::update_selections() else { for (auto idx : selection.get_volume_idxs()) { const auto gl_vol = selection.get_volume(idx); - if (gl_vol->volume_idx() >= 0) + if (gl_vol->volume_idx() >= 0) { // Only add GLVolumes with non-negative volume_ids. GLVolumes with negative volume ids // are not associated with ModelVolumes, but they are temporarily generated by the backend // (for example, SLA supports or SLA pad). - sels.Add(m_objects_model->GetItemByVolumeId(gl_vol->object_idx(), gl_vol->volume_idx())); + int obj_idx = gl_vol->object_idx(); + int vol_idx = gl_vol->volume_idx(); + assert(obj_idx >= 0 && vol_idx >= 0); + if (object(obj_idx)->volumes[vol_idx]->is_cut_connector()) + sels.Add(m_objects_model->GetInfoItemByType(m_objects_model->GetItemById(obj_idx), InfoItemType::CutConnectors)); + else + sels.Add(m_objects_model->GetItemByVolumeId(obj_idx, vol_idx)); + } } m_selection_mode = smVolume; } } @@ -3602,7 +3649,7 @@ void ObjectList::update_selections() if (sels.size() == 0 || m_selection_mode & smSettings) m_selection_mode = smUndef; - if (fix_cut_selection(sels)) { + if (fix_cut_selection(sels) || is_connectors_item_selected(sels)) { m_prevent_list_events = true; // If some part is selected, unselect all items except of selected parts of the current object @@ -3616,7 +3663,7 @@ void ObjectList::update_selections() update_selections_on_canvas(); // to update the toolbar and info sizer - if (!GetSelection() || m_objects_model->GetItemType(GetSelection()) == itObject) { + if (!GetSelection() || m_objects_model->GetItemType(GetSelection()) == itObject || is_connectors_item_selected()) { auto event = SimpleEvent(EVT_OBJ_LIST_OBJECT_SELECT); event.SetEventObject(this); wxPostEvent(this, event); @@ -3662,16 +3709,29 @@ void ObjectList::update_selections_on_canvas() volume_idxs.insert(volume_idxs.end(), idxs.begin(), idxs.end()); } else if (type == itInfo) { - // When selecting an info item, select one instance of the - // respective object - a gizmo may want to be opened. - int inst_idx = selection.get_instance_idx(); - int scene_obj_idx = selection.get_object_idx(); - mode = Selection::Instance; - // select first instance, unless an instance of the object is already selected - if (scene_obj_idx == -1 || inst_idx == -1 || scene_obj_idx != obj_idx) - inst_idx = 0; - std::vector idxs = selection.get_volume_idxs_from_instance(obj_idx, inst_idx); - volume_idxs.insert(volume_idxs.end(), idxs.begin(), idxs.end()); + if (m_objects_model->GetInfoItemType(item) == InfoItemType::CutConnectors) { + mode = Selection::Volume; + + // When selecting CutConnectors info item, select all object volumes, which are marked as a connector + const ModelObject* obj = object(obj_idx); + for (unsigned int vol_idx = 0; vol_idx < obj->volumes.size(); vol_idx++) + if (obj->volumes[vol_idx]->is_cut_connector()) { + std::vector idxs = selection.get_volume_idxs_from_volume(obj_idx, std::max(instance_idx, 0), vol_idx); + volume_idxs.insert(volume_idxs.end(), idxs.begin(), idxs.end()); + } + } + else { + // When selecting an info item, select one instance of the + // respective object - a gizmo may want to be opened. + int inst_idx = selection.get_instance_idx(); + int scene_obj_idx = selection.get_object_idx(); + mode = Selection::Instance; + // select first instance, unless an instance of the object is already selected + if (scene_obj_idx == -1 || inst_idx == -1 || scene_obj_idx != obj_idx) + inst_idx = 0; + std::vector idxs = selection.get_volume_idxs_from_instance(obj_idx, inst_idx); + volume_idxs.insert(volume_idxs.end(), idxs.begin(), idxs.end()); + } } else { @@ -4569,33 +4629,14 @@ void ObjectList::set_extruder_for_selected_items(const int extruder) const wxGetApp().plater()->update(); } -wxDataViewItemArray ObjectList::reorder_volumes_and_get_selection(int obj_idx, std::function add_to_selection/* = nullptr*/) +wxDataViewItemArray ObjectList::reorder_volumes_and_get_selection(size_t obj_idx, std::function add_to_selection/* = nullptr*/) { - wxDataViewItemArray items; + (*m_objects)[obj_idx]->sort_volumes(wxGetApp().app_config->get("order_volumes") == "1"); - ModelObject* object = (*m_objects)[obj_idx]; - if (object->volumes.size() <= 1) - return items; + wxDataViewItemArray items = add_volumes_to_object_in_list(obj_idx, std::move(add_to_selection)); - object->sort_volumes(wxGetApp().app_config->get("order_volumes") == "1"); + changed_object(int(obj_idx)); - wxDataViewItem object_item = m_objects_model->GetItemById(obj_idx); - m_objects_model->DeleteVolumeChildren(object_item); - - for (const ModelVolume* volume : object->volumes) { - wxDataViewItem vol_item = m_objects_model->AddVolumeChild(object_item, from_u8(volume->name), - volume->type(), - get_warning_icon_name(volume->mesh().stats()), - volume->config.has("extruder") ? volume->config.extruder() : 0, - false); - // add settings to the part, if it has those - add_settings_item(vol_item, &volume->config.get()); - - if (add_to_selection && add_to_selection(volume)) - items.Add(vol_item); - } - - changed_object(obj_idx); return items; } diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 3ae0d05332..cb498f87ef 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -343,6 +343,8 @@ public: void init_objects(); bool multiple_selection() const ; bool is_selected(const ItemType type) const; + bool is_connectors_item_selected() const; + bool is_connectors_item_selected(const wxDataViewItemArray& sels) const; int get_selected_layers_range_idx() const; void set_selected_layers_range_idx(const int range_idx) { m_selected_layers_range_idx = range_idx; } void set_selection_mode(SELECTION_MODE mode) { m_selection_mode = mode; } diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index e54a4cf56d..a2d687db01 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -763,7 +763,7 @@ void ObjectManipulation::update_settings_value(const Selection& selection) #endif // ENABLE_WORLD_COORDINATE m_new_enabled = true; } - else if (obj_list->multiple_selection() || obj_list->is_selected(itInstanceRoot)) { + else if (obj_list->is_connectors_item_selected() || obj_list->multiple_selection() || obj_list->is_selected(itInstanceRoot)) { reset_settings_value(); m_new_move_label_string = L("Translate"); m_new_rotate_label_string = L("Rotate"); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp index 97714ea62a..71a9c5dcf7 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp @@ -597,114 +597,109 @@ static float get_grabber_mean_size(const BoundingBoxf3& bb) return float((bb.size().x() + bb.size().y() + bb.size().z()) / 3.0); } -void GLGizmoCut3D::render_cut_center_grabber() +void GLGizmoCut3D::render_model(GLModel& model, const ColorRGBA& color, Transform3d view_model_matrix) +{ + GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); + if (shader) { + shader->start_using(); + + shader->set_uniform("view_model_matrix", view_model_matrix); + shader->set_uniform("projection_matrix", wxGetApp().plater()->get_camera().get_projection_matrix()); + + model.set_color(color); + model.render(); + + shader->stop_using(); + } +} + +void GLGizmoCut3D::render_line(GLModel& line_model, const ColorRGBA& color, Transform3d view_model_matrix, float width) +{ + GLShaderProgram* shader = OpenGLManager::get_gl_info().is_core_profile() ? wxGetApp().get_shader("dashed_thick_lines") : wxGetApp().get_shader("flat"); + if (shader) { + shader->start_using(); + + const Camera& camera = wxGetApp().plater()->get_camera(); + shader->set_uniform("view_model_matrix", view_model_matrix); + shader->set_uniform("projection_matrix", wxGetApp().plater()->get_camera().get_projection_matrix()); + shader->set_uniform("width", width); + + line_model.set_color(color); + line_model.render(); + + shader->stop_using(); + } +} + +void GLGizmoCut3D::render_rotation_snapping(Axis axis, const ColorRGBA& color) +{ + GLShaderProgram* line_shader = OpenGLManager::get_gl_info().is_core_profile() ? wxGetApp().get_shader("dashed_thick_lines") : wxGetApp().get_shader("flat"); + if (!line_shader) + return; + + const Camera& camera = wxGetApp().plater()->get_camera(); + Transform3d view_model_matrix = camera.get_view_matrix() * translation_transform(m_plane_center) * m_start_dragging_m; + + if (axis == X) + view_model_matrix = view_model_matrix * rotation_transform(0.5 * PI * Vec3d::UnitY()) * rotation_transform(-PI * Vec3d::UnitZ()); + else + view_model_matrix = view_model_matrix * rotation_transform(-0.5 * PI * Vec3d::UnitZ()) * rotation_transform(-0.5 * PI * Vec3d::UnitY()); + + line_shader->start_using(); + line_shader->set_uniform("projection_matrix", camera.get_projection_matrix()); + line_shader->set_uniform("view_model_matrix", view_model_matrix); + line_shader->set_uniform("width", 0.25f); + + m_circle.render(); + m_scale.render(); + m_snap_radii.render(); + m_reference_radius.render(); + if (m_dragging) { + line_shader->set_uniform("width", 1.5f); + m_angle_arc.set_color(color); + m_angle_arc.render(); + } + + line_shader->stop_using(); +} + +void GLGizmoCut3D::render_grabber_connection(const ColorRGBA& color, Transform3d view_matrix) +{ + const Transform3d line_view_matrix = view_matrix * scale_transform(Vec3d(1.0, 1.0, m_grabber_connection_len)); + + render_line(m_grabber_connection, color, line_view_matrix, 0.2f); +}; + +void GLGizmoCut3D::render_cut_plane_grabbers() { glsafe(::glClear(GL_DEPTH_BUFFER_BIT)); - GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); - if (!shader) - return; - ColorRGBA color = m_hover_id == Z ? complementary(GRABBER_COLOR) : GRABBER_COLOR; - const Camera& camera = wxGetApp().plater()->get_camera(); + const Transform3d view_matrix = wxGetApp().plater()->get_camera().get_view_matrix() * translation_transform(m_plane_center) * m_rotation_m; + const Grabber& grabber = m_grabbers.front(); + const float mean_size = get_grabber_mean_size(bounding_box()); - const BoundingBoxf3 box = bounding_box(); - - const float mean_size = get_grabber_mean_size(box); double size = m_dragging && m_hover_id == Z ? double(grabber.get_dragging_half_size(mean_size)) : double(grabber.get_half_size(mean_size)); Vec3d cone_scale = Vec3d(0.75 * size, 0.75 * size, 1.8 * size); Vec3d offset = 1.25 * size * Vec3d::UnitZ(); - shader->start_using(); - shader->set_uniform("emission_factor", 0.1f); - shader->set_uniform("projection_matrix", camera.get_projection_matrix()); - - const Transform3d view_matrix = camera.get_view_matrix() * translation_transform(m_plane_center) * m_rotation_m; - - auto render = [shader, this](GLModel& model, const ColorRGBA& color, Transform3d view_model_matrix) { - shader->set_uniform("view_model_matrix", view_model_matrix); - shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); - model.set_color(color); - model.render(); - }; - - auto render_grabber_connection = [shader, camera, view_matrix, this](const ColorRGBA& color) - { - shader->stop_using(); - GLShaderProgram* line_shader = OpenGLManager::get_gl_info().is_core_profile() ? wxGetApp().get_shader("dashed_thick_lines") : wxGetApp().get_shader("flat"); - if (!line_shader) - return; - - line_shader->start_using(); - line_shader->set_uniform("emission_factor", 0.1f); - line_shader->set_uniform("projection_matrix", camera.get_projection_matrix()); - - const Transform3d trafo = view_matrix * scale_transform(Vec3d(1.0, 1.0, m_grabber_connection_len)); - line_shader->set_uniform("view_model_matrix", trafo); - line_shader->set_uniform("normal_matrix", (Matrix3d)trafo.matrix().block(0, 0, 3, 3).inverse().transpose()); - line_shader->set_uniform("width", 0.2f); - - m_grabber_connection.set_color(color); - m_grabber_connection.render(); - - line_shader->stop_using(); - shader->start_using(); - }; - - auto render_rotation_snapping = [shader, camera, this](Axis axis, const ColorRGBA& color) - { - Transform3d view_model_matrix = camera.get_view_matrix() * translation_transform(m_plane_center) * m_start_dragging_m; - - if (axis == X) - view_model_matrix = view_model_matrix * rotation_transform( 0.5 * PI * Vec3d::UnitY()) * rotation_transform(-PI * Vec3d::UnitZ()); - else - view_model_matrix = view_model_matrix * rotation_transform(-0.5 * PI * Vec3d::UnitZ()) * rotation_transform(-0.5 * PI * Vec3d::UnitY()); - - shader->stop_using(); - - GLShaderProgram* line_shader = OpenGLManager::get_gl_info().is_core_profile() ? wxGetApp().get_shader("dashed_thick_lines") : wxGetApp().get_shader("flat"); - if (!line_shader) - return; - - line_shader->start_using(); - line_shader->set_uniform("emission_factor", 0.1f); - line_shader->set_uniform("projection_matrix", camera.get_projection_matrix()); - - line_shader->set_uniform("view_model_matrix", view_model_matrix); - line_shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); - line_shader->set_uniform("width", 0.25f); - - m_circle.render(); - m_scale.render(); - m_snap_radii.render(); - m_reference_radius.render(); - if (m_dragging) { - line_shader->set_uniform("width", 1.5f); - m_angle_arc.set_color(color); - m_angle_arc.render(); - } - - line_shader->stop_using(); - shader->start_using(); - }; - // render Z grabber if ((!m_dragging && m_hover_id < 0)) - render_grabber_connection(color); - render(m_sphere.model, color, view_matrix * scale_transform(size)); + render_grabber_connection(color, view_matrix); + render_model(m_sphere.model, color, view_matrix * scale_transform(size)); if (!m_dragging && m_hover_id < 0 || m_hover_id == Z) { const BoundingBoxf3 tbb = transformed_bounding_box(); if (tbb.min.z() <= 0.0) - render(m_cone.model, color, view_matrix * assemble_transform(-offset, PI * Vec3d::UnitX(), cone_scale)); + render_model(m_cone.model, color, view_matrix * assemble_transform(-offset, PI * Vec3d::UnitX(), cone_scale)); if (tbb.max.z() >= 0.0) - render(m_cone.model, color, view_matrix * assemble_transform(offset, Vec3d::Zero(), cone_scale)); + render_model(m_cone.model, color, view_matrix * assemble_transform(offset, Vec3d::Zero(), cone_scale)); } // render top sphere for X/Y grabbers @@ -714,7 +709,7 @@ void GLGizmoCut3D::render_cut_center_grabber() size = m_dragging ? double(grabber.get_dragging_half_size(mean_size)) : double(grabber.get_half_size(mean_size)); color = m_hover_id == Y ? complementary(ColorRGBA::GREEN()) : m_hover_id == X ? complementary(ColorRGBA::RED()) : ColorRGBA::GRAY(); - render(m_sphere.model, color, view_matrix * assemble_transform(m_grabber_connection_len * Vec3d::UnitZ(), Vec3d::Zero(), size * Vec3d::Ones())); + render_model(m_sphere.model, color, view_matrix * assemble_transform(m_grabber_connection_len * Vec3d::UnitZ(), Vec3d::Zero(), size * Vec3d::Ones())); } // render X grabber @@ -726,14 +721,14 @@ void GLGizmoCut3D::render_cut_center_grabber() color = m_hover_id == X ? complementary(ColorRGBA::RED()) : ColorRGBA::RED(); if (m_hover_id == X) { - render_grabber_connection(color); + render_grabber_connection(color, view_matrix); render_rotation_snapping(X, color); } offset = Vec3d(0.0, 1.25 * size, m_grabber_connection_len); - render(m_cone.model, color, view_matrix * assemble_transform(offset, -0.5 * PI * Vec3d::UnitX(), cone_scale)); + render_model(m_cone.model, color, view_matrix * assemble_transform(offset, -0.5 * PI * Vec3d::UnitX(), cone_scale)); offset = Vec3d(0.0, -1.25 * size, m_grabber_connection_len); - render(m_cone.model, color, view_matrix * assemble_transform(offset, 0.5 * PI * Vec3d::UnitX(), cone_scale)); + render_model(m_cone.model, color, view_matrix * assemble_transform(offset, 0.5 * PI * Vec3d::UnitX(), cone_scale)); } // render Y grabber @@ -745,17 +740,15 @@ void GLGizmoCut3D::render_cut_center_grabber() color = m_hover_id == Y ? complementary(ColorRGBA::GREEN()) : ColorRGBA::GREEN(); if (m_hover_id == Y) { - render_grabber_connection(color); + render_grabber_connection(color, view_matrix); render_rotation_snapping(Y, color); } offset = Vec3d(1.25 * size, 0.0, m_grabber_connection_len); - render(m_cone.model, color, view_matrix * assemble_transform(offset, 0.5 * PI * Vec3d::UnitY(), cone_scale)); + render_model(m_cone.model, color, view_matrix * assemble_transform(offset, 0.5 * PI * Vec3d::UnitY(), cone_scale)); offset = Vec3d(-1.25 * size, 0.0, m_grabber_connection_len); - render(m_cone.model, color, view_matrix * assemble_transform(offset, -0.5 * PI * Vec3d::UnitY(), cone_scale)); + render_model(m_cone.model, color, view_matrix * assemble_transform(offset, -0.5 * PI * Vec3d::UnitY(), cone_scale)); } - - shader->stop_using(); } void GLGizmoCut3D::render_cut_line() @@ -766,23 +759,10 @@ void GLGizmoCut3D::render_cut_line() glsafe(::glEnable(GL_DEPTH_TEST)); glsafe(::glClear(GL_DEPTH_BUFFER_BIT)); - GLShaderProgram* shader = OpenGLManager::get_gl_info().is_core_profile() ? wxGetApp().get_shader("dashed_thick_lines") : wxGetApp().get_shader("flat"); - if (shader != nullptr) { - shader->start_using(); + m_cut_line.reset(); + m_cut_line.init_from(its_make_line((Vec3f)m_line_beg.cast(), (Vec3f)m_line_end.cast())); - const Camera& camera = wxGetApp().plater()->get_camera(); - shader->set_uniform("view_model_matrix", camera.get_view_matrix()); - shader->set_uniform("projection_matrix", camera.get_projection_matrix()); - shader->set_uniform("width", 0.25f); - - m_cut_line.reset(); - m_cut_line.init_from(its_make_line((Vec3f)m_line_beg.cast(), (Vec3f)m_line_end.cast())); - - m_cut_line.set_color(GRABBER_COLOR); - m_cut_line.render(); - - shader->stop_using(); - } + render_line(m_cut_line, GRABBER_COLOR, wxGetApp().plater()->get_camera().get_view_matrix(), 0.25f); } bool GLGizmoCut3D::on_init() @@ -1303,7 +1283,7 @@ void GLGizmoCut3D::on_render() if (!m_hide_cut_plane && !m_connectors_editing) { render_cut_plane(); - render_cut_center_grabber(); + render_cut_plane_grabbers(); } render_cut_line(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp index fe8422865b..4335da35ae 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp @@ -221,7 +221,11 @@ private: void discard_cut_line_processing(); void render_cut_plane(); - void render_cut_center_grabber(); + void render_model(GLModel& model, const ColorRGBA& color, Transform3d view_model_matrix); + void render_line(GLModel& line_model, const ColorRGBA& color, Transform3d view_model_matrix, float width); + void render_rotation_snapping(Axis axis, const ColorRGBA& color); + void render_grabber_connection(const ColorRGBA& color, Transform3d view_matrix); + void render_cut_plane_grabbers(); void render_cut_line(); void perform_cut(const Selection&selection); void set_center_pos(const Vec3d¢er_pos, bool force = false); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp index dbe0ba7346..12c783c431 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp @@ -81,12 +81,7 @@ std::string GLGizmoMove3D::on_get_name() const bool GLGizmoMove3D::on_is_activable() const { const Selection& selection = m_parent.get_selection(); - if (selection.is_any_volume() || selection.is_any_modifier()) { - if (int obj_idx = selection.get_object_idx(); obj_idx >= 0) - return !m_parent.get_model()->objects[obj_idx]->is_cut(); - } - - return !selection.is_empty(); + return !selection.is_any_cut_volume() && !selection.is_any_connector() && !selection.is_empty(); } void GLGizmoMove3D::on_start_dragging() diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp index 99d5eb8814..80d6f1aa05 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp @@ -869,12 +869,7 @@ std::string GLGizmoRotate3D::on_get_name() const bool GLGizmoRotate3D::on_is_activable() const { const Selection& selection = m_parent.get_selection(); - if (selection.is_any_volume() || selection.is_any_modifier()) { - if (int obj_idx = selection.get_object_idx(); obj_idx >= 0) - return !m_parent.get_model()->objects[obj_idx]->is_cut(); - } - - return !selection.is_empty(); + return !selection.is_any_cut_volume() && !selection.is_any_connector() && !selection.is_empty(); } void GLGizmoRotate3D::on_start_dragging() diff --git a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp index 9adfa2241e..9b49cf0b4e 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp @@ -168,12 +168,7 @@ std::string GLGizmoScale3D::on_get_name() const bool GLGizmoScale3D::on_is_activable() const { const Selection& selection = m_parent.get_selection(); - if (selection.is_any_volume() || selection.is_any_modifier()) { - if (int obj_idx = selection.get_object_idx(); obj_idx >= 0) - return !m_parent.get_model()->objects[obj_idx]->is_cut(); - } - - return !selection.is_empty() && !selection.is_wipe_tower(); + return !selection.is_any_cut_volume() && !selection.is_any_connector() && !selection.is_empty() && !selection.is_wipe_tower(); } void GLGizmoScale3D::on_start_dragging() @@ -460,7 +455,7 @@ void GLGizmoScale3D::on_render() // draw grabbers render_grabbers(grabber_mean_size); } - else if (m_hover_id == 0 || m_hover_id == 1) { + else if ((m_hover_id == 0 || m_hover_id == 1) && m_grabbers[0].enabled && m_grabbers[1].enabled) { #if ENABLE_LEGACY_OPENGL_REMOVAL // draw connections #if ENABLE_GL_CORE_PROFILE @@ -505,7 +500,7 @@ void GLGizmoScale3D::on_render() shader->stop_using(); } } - else if (m_hover_id == 2 || m_hover_id == 3) { + else if ((m_hover_id == 2 || m_hover_id == 3) && m_grabbers[2].enabled && m_grabbers[3].enabled) { #if ENABLE_LEGACY_OPENGL_REMOVAL // draw connections #if ENABLE_GL_CORE_PROFILE @@ -550,7 +545,7 @@ void GLGizmoScale3D::on_render() shader->stop_using(); } } - else if (m_hover_id == 4 || m_hover_id == 5) { + else if ((m_hover_id == 4 || m_hover_id == 5) && m_grabbers[4].enabled && m_grabbers[5].enabled) { #if ENABLE_LEGACY_OPENGL_REMOVAL // draw connections #if ENABLE_GL_CORE_PROFILE diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index c6ddd1fa3e..a3828f53df 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -510,6 +510,28 @@ void Selection::volumes_changed(const std::vector &map_volume_old_to_new this->set_bounding_boxes_dirty(); } +bool Selection::is_any_connector() const +{ + const int obj_idx = get_object_idx(); + + if ((is_any_volume() || is_any_modifier() || is_mixed()) && // some solid_part AND/OR modifier is selected + obj_idx >= 0 && m_model->objects[obj_idx]->is_cut()) { + const ModelVolumePtrs& obj_volumes = m_model->objects[obj_idx]->volumes; + for (size_t vol_idx = 0; vol_idx < obj_volumes.size(); vol_idx++) + if (obj_volumes[vol_idx]->is_cut_connector()) + for (const GLVolume* v : *m_volumes) + if (v->object_idx() == obj_idx && v->volume_idx() == (int)vol_idx && v->selected) + return true; + } + return false; +} + +bool Selection::is_any_cut_volume() const +{ + const int obj_idx = get_object_idx(); + return is_any_volume() && obj_idx >= 0 && m_model->objects[obj_idx]->is_cut(); +} + bool Selection::is_single_full_instance() const { if (m_type == SingleFullInstance) diff --git a/src/slic3r/GUI/Selection.hpp b/src/slic3r/GUI/Selection.hpp index cebea29e05..97a85a2dcc 100644 --- a/src/slic3r/GUI/Selection.hpp +++ b/src/slic3r/GUI/Selection.hpp @@ -320,6 +320,8 @@ public: bool is_single_volume() const { return m_type == SingleVolume; } bool is_multiple_volume() const { return m_type == MultipleVolume; } bool is_any_volume() const { return is_single_volume() || is_multiple_volume(); } + bool is_any_connector() const; + bool is_any_cut_volume() const; bool is_mixed() const { return m_type == Mixed; } bool is_from_single_instance() const { return get_instance_idx() != -1; } bool is_from_single_object() const;