From 21bbabc1b3a19b70d11362d9dc0335ba5b6eb45a Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 20 Feb 2023 12:42:10 +0100 Subject: [PATCH 01/34] Fixed rotation in Objects Coordinates of parts of mirrored objects --- src/slic3r/GUI/Selection.cpp | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index fd0a5ec59..0f6409cd1 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -1024,22 +1024,13 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_ } else { if (transformation_type.instance()) { - const Geometry::Transformation& vol_trafo = volume_data.get_volume_transform(); - const Geometry::Transformation world_trafo = inst_trafo * vol_trafo; // ensure proper sign of rotation for mirrored objects - if (world_trafo.is_left_handed() && !rotation.normalized().isApprox(Vec3d::UnitX())) + if (inst_trafo.is_left_handed() && !rotation.normalized().isApprox(Vec3d::UnitX())) rotation_matrix = rotation_matrix.inverse(); // ensure that the volume rotates as a rigid body - const Geometry::TransformationSVD world_svd(world_trafo); - if (world_svd.anisotropic_scale) { - const Transform3d vol_scale_matrix = vol_trafo.get_scaling_factor_matrix(); - rotation_matrix = vol_scale_matrix.inverse() * rotation_matrix * vol_scale_matrix; - } - const Transform3d vol_rotation_matrix = vol_trafo.get_rotation_matrix(); - rotation_matrix = vol_rotation_matrix.inverse() * rotation_matrix * vol_rotation_matrix; - - v.set_volume_transformation(vol_trafo.get_matrix() * rotation_matrix); + const Transform3d inst_scale_matrix = inst_trafo.get_scaling_factor_matrix(); + rotation_matrix = inst_scale_matrix.inverse() * rotation_matrix * inst_scale_matrix; } else { if (transformation_type.local()) { @@ -1056,8 +1047,8 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_ rotation_matrix = vol_scale_matrix.inverse() * rotation_matrix * vol_scale_matrix; } } - transform_volume_relative(v, volume_data, transformation_type, rotation_matrix, m_cache.dragging_center); } + transform_volume_relative(v, volume_data, transformation_type, rotation_matrix, m_cache.dragging_center); } } } From c9f807f4bb94f411ffb15cf44e17be3937ece3bf Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Tue, 21 Feb 2023 10:29:02 +0100 Subject: [PATCH 02/34] Fixed rotation of volumes in Part Coordinates when the instance matrix contains anisotropic scale --- src/slic3r/GUI/Selection.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index 0f6409cd1..e4f59dcc7 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -1041,10 +1041,9 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_ rotation_matrix = rotation_matrix.inverse(); // ensure that the volume rotates as a rigid body - const Geometry::TransformationSVD svd(world_trafo); - if (svd.anisotropic_scale) { - const Transform3d vol_scale_matrix = vol_trafo.get_scaling_factor_matrix(); - rotation_matrix = vol_scale_matrix.inverse() * rotation_matrix * vol_scale_matrix; + if (Geometry::TransformationSVD(world_trafo).anisotropic_scale) { + const Transform3d inst_scale_matrix = inst_trafo.get_scaling_factor_matrix(); + rotation_matrix = inst_scale_matrix.inverse() * rotation_matrix * inst_scale_matrix; } } } @@ -2762,6 +2761,7 @@ void Selection::render_debug_window() const return; ImGuiWrapper& imgui = *wxGetApp().imgui(); + ImGui::SetNextWindowCollapsed(true, ImGuiCond_Once); imgui.begin(std::string("Selection matrices"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize); auto volume_name = [this](size_t id) { From 6ca65cf84432487cab84faa8840fa456195115cc Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 22 Feb 2023 14:50:29 +0100 Subject: [PATCH 03/34] Fixed detection of skew in TransformationSVD --- src/libslic3r/Geometry.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/libslic3r/Geometry.cpp b/src/libslic3r/Geometry.cpp index ac4af4828..8065b81da 100644 --- a/src/libslic3r/Geometry.cpp +++ b/src/libslic3r/Geometry.cpp @@ -860,14 +860,26 @@ TransformationSVD::TransformationSVD(const Transform3d& trafo) rotation_90_degrees = true; for (int i = 0; i < 3; ++i) { const Vec3d row = v.row(i).cwiseAbs(); - size_t num_zeros = is_approx(row[0], 0.) + is_approx(row[1], 0.) + is_approx(row[2], 0.); - size_t num_ones = is_approx(row[0], 1.) + is_approx(row[1], 1.) + is_approx(row[2], 1.); + const size_t num_zeros = is_approx(row[0], 0.) + is_approx(row[1], 0.) + is_approx(row[2], 0.); + const size_t num_ones = is_approx(row[0], 1.) + is_approx(row[1], 1.) + is_approx(row[2], 1.); if (num_zeros != 2 || num_ones != 1) { rotation_90_degrees = false; break; } } - skew = ! rotation_90_degrees; + // Detect skew by brute force: check if the axes are still orthogonal after transformation + const Matrix3d trafo_linear = trafo.linear(); + const std::array axes = { Vec3d::UnitX(), Vec3d::UnitY(), Vec3d::UnitZ() }; + std::array transformed_axes; + for (int i = 0; i < 3; ++i) { + transformed_axes[i] = trafo_linear * axes[i]; + } + skew = std::abs(transformed_axes[0].dot(transformed_axes[1])) > EPSILON || + std::abs(transformed_axes[1].dot(transformed_axes[2])) > EPSILON || + std::abs(transformed_axes[2].dot(transformed_axes[0])) > EPSILON; + + // This following old code does not work under all conditions. The v matrix can become non diagonal (see SPE-1492) +// skew = ! rotation_90_degrees; } else skew = false; } From 5d38d3363c1b9496fec7f73d25873211357d769f Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 23 Feb 2023 12:55:59 +0100 Subject: [PATCH 04/34] Fixed synchronization of instances/volumes after resetting scale --- src/slic3r/GUI/GUI_ObjectManipulation.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index 6d4c916f1..531b2a8ce 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -506,6 +506,10 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : else return; + // Synchronize instances/volumes. + selection.synchronize_unselected_instances(Selection::SyncRotationType::GENERAL); + selection.synchronize_unselected_volumes(); + canvas->do_scale(L("Reset scale")); UpdateAndShow(true); #else From b92735ac3644faf0d86381e2588ee511145ffdcb Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 23 Feb 2023 14:16:55 +0100 Subject: [PATCH 05/34] Fixed synchronization of instances/volumes after resetting skew --- src/slic3r/GUI/GLCanvas3D.cpp | 36 ++++++++++++++++++++++++++++++----- src/slic3r/GUI/Selection.cpp | 9 +++++++++ 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 427c0e99f..677653a7d 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3746,12 +3746,22 @@ void GLCanvas3D::do_reset_skew(const std::string& snapshot_type) if (!snapshot_type.empty()) wxGetApp().plater()->take_snapshot(_(snapshot_type)); + // stores current min_z of instances + std::map, double> min_zs; + if (!snapshot_type.empty()) { + for (int i = 0; i < static_cast(m_model->objects.size()); ++i) { + const ModelObject* obj = m_model->objects[i]; + for (int j = 0; j < static_cast(obj->instances.size()); ++j) { + min_zs[{ i, j }] = obj->instance_bounding_box(j).min.z(); + } + } + } + std::set> done; // keeps track of modified instances - const Selection::IndicesList& idxs = m_selection.get_volume_idxs(); + Selection::EMode selection_mode = m_selection.get_mode(); - for (unsigned int id : idxs) { - const GLVolume* v = m_volumes.volumes[id]; + for (const GLVolume* v : m_volumes.volumes) { int object_idx = v->object_idx(); if (object_idx < 0 || (int)m_model->objects.size() <= object_idx) continue; @@ -3761,14 +3771,30 @@ void GLCanvas3D::do_reset_skew(const std::string& snapshot_type) done.insert(std::pair(object_idx, instance_idx)); + // Mirror instances/volumes ModelObject* model_object = m_model->objects[object_idx]; if (model_object != nullptr) { - model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation()); - model_object->volumes[volume_idx]->set_transformation(v->get_volume_transformation()); + if (selection_mode == Selection::Instance) + model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation()); + else if (selection_mode == Selection::Volume) + model_object->volumes[volume_idx]->set_transformation(v->get_volume_transformation()); model_object->invalidate_bounding_box(); } } + // Fixes sinking/flying instances + for (const std::pair& i : done) { + ModelObject* m = m_model->objects[i.first]; + double shift_z = m->get_instance_min_z(i.second); + // leave sinking instances as sinking + if (min_zs.empty() || min_zs.find({ i.first, i.second })->second >= SINKING_Z_THRESHOLD || shift_z > SINKING_Z_THRESHOLD) { + Vec3d shift(0.0, 0.0, -shift_z); + m_selection.translate(i.first, i.second, shift); + m->translate_instance(i.second, shift); + } + wxGetApp().obj_list()->update_info_items(static_cast(i.first)); + } + post_event(SimpleEvent(EVT_GLCANVAS_RESET_SKEW)); m_dirty = true; diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index e4f59dcc7..4a5ddb59c 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -1543,6 +1543,15 @@ void Selection::reset_skew() } } +#if !DISABLE_INSTANCES_SYNCH + if (m_mode == Instance) + // even if there is no rotation, we pass SyncRotationType::GENERAL to force + // synchronize_unselected_instances() to remove skew from the other instances + synchronize_unselected_instances(SyncRotationType::GENERAL); + else if (m_mode == Volume) + synchronize_unselected_volumes(); +#endif // !DISABLE_INSTANCES_SYNCH + ensure_on_bed(); set_bounding_boxes_dirty(); wxGetApp().plater()->canvas3D()->requires_check_outside_state(); From e5efbbc2c29ac2333590d85d1d15845417b5f8bb Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Fri, 24 Feb 2023 09:10:29 +0100 Subject: [PATCH 06/34] Follow-up of 5d38d3363c1b9496fec7f73d25873211357d769f - Completed fix of synchronization of instances/volumes after resetting scale --- src/slic3r/GUI/GUI_ObjectManipulation.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index 531b2a8ce..69280f7c7 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -490,6 +490,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : #if ENABLE_WORLD_COORDINATE GLCanvas3D* canvas = wxGetApp().plater()->canvas3D(); Selection& selection = canvas->get_selection(); + selection.setup_cache(); if (selection.is_single_volume_or_modifier()) { GLVolume* vol = const_cast(selection.get_first_volume()); Geometry::Transformation trafo = vol->get_volume_transformation(); From 2630c62f0414642c0c11c1bf073d71e884353123 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Fri, 24 Feb 2023 10:55:36 +0100 Subject: [PATCH 07/34] Fixed synchronization of instances after resetting rotation --- src/slic3r/GUI/GUI_ObjectManipulation.cpp | 8 +++++--- src/slic3r/GUI/Selection.cpp | 7 ++++++- src/slic3r/GUI/Selection.hpp | 4 ++++ 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index 69280f7c7..72c6a5666 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -446,7 +446,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : m_reset_rotation_button->Bind(wxEVT_BUTTON, [this](wxCommandEvent& e) { GLCanvas3D* canvas = wxGetApp().plater()->canvas3D(); Selection& selection = canvas->get_selection(); - + selection.setup_cache(); #if ENABLE_WORLD_COORDINATE if (selection.is_single_volume_or_modifier()) { GLVolume* vol = const_cast(selection.get_first_volume()); @@ -468,9 +468,11 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : else return; - // Update rotation at the GLVolumes. - selection.synchronize_unselected_instances(Selection::SyncRotationType::GENERAL); + // Synchronize instances/volumes. + + selection.synchronize_unselected_instances(Selection::SyncRotationType::RESET); selection.synchronize_unselected_volumes(); + // Copy rotation values from GLVolumes into Model (ModelInstance / ModelVolume), trigger background processing. canvas->do_rotate(L("Reset Rotation")); diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index 4a5ddb59c..ed7e0ce30 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -3010,7 +3010,12 @@ void Selection::synchronize_unselected_instances(SyncRotationType sync_rotation_ const Transform3d& old_inst_trafo_j = m_cache.volumes_data[j].get_instance_transform().get_matrix(); assert(is_rotation_xy_synchronized(old_inst_trafo_i, old_inst_trafo_j)); Transform3d new_inst_trafo_j = volume_j->get_instance_transformation().get_matrix(); - if (sync_rotation_type != SyncRotationType::NONE || mirrored) + if (sync_rotation_type == SyncRotationType::RESET) { + Geometry::Transformation new_inst_trafo_j_no_rotation(new_inst_trafo_j); + new_inst_trafo_j_no_rotation.reset_rotation(); + new_inst_trafo_j = new_inst_trafo_j_no_rotation.get_matrix(); + } + else if (sync_rotation_type != SyncRotationType::NONE || mirrored) new_inst_trafo_j.linear() = (old_inst_trafo_j.linear() * old_inst_trafo_i.linear().inverse()) * curr_inst_trafo_i.linear(); if (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA) new_inst_trafo_j.translation().z() = curr_inst_trafo_i.translation().z(); diff --git a/src/slic3r/GUI/Selection.hpp b/src/slic3r/GUI/Selection.hpp index c1c97bd2e..4c818f30c 100644 --- a/src/slic3r/GUI/Selection.hpp +++ b/src/slic3r/GUI/Selection.hpp @@ -499,6 +499,10 @@ public: NONE = 0, // Synchronize after rotation by an axis not parallel with Z. GENERAL = 1, +#if ENABLE_WORLD_COORDINATE + // Synchronize after rotation reset. + RESET = 2 +#endif // ENABLE_WORLD_COORDINATE }; void synchronize_unselected_instances(SyncRotationType sync_rotation_type); void synchronize_unselected_volumes(); From 23f4b6913594e6b4f43e1d007cf89f5717bad3e7 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Fri, 24 Feb 2023 12:03:55 +0100 Subject: [PATCH 08/34] Fixed synchronization of instances while rotating in Object Coordinates --- src/slic3r/GUI/Selection.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index ed7e0ce30..c6150ed68 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -1056,7 +1056,7 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_ if (m_mode == Instance) { int rot_axis_max = 0; rotation.cwiseAbs().maxCoeff(&rot_axis_max); - synchronize_unselected_instances((transformation_type.world() && rot_axis_max == 2) ? SyncRotationType::NONE : SyncRotationType::GENERAL); + synchronize_unselected_instances((rot_axis_max == 2) ? SyncRotationType::NONE : SyncRotationType::GENERAL); } else if (m_mode == Volume) synchronize_unselected_volumes(); From 77290b538c117016a288b4ed292ebf165498693a Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 27 Feb 2023 12:58:33 +0100 Subject: [PATCH 09/34] Fixed scale of mirrored objects shown in sidebar panel in Object Coordinates --- src/slic3r/GUI/GUI_ObjectManipulation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index 72c6a5666..c16d77751 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -757,7 +757,7 @@ void ObjectManipulation::update_settings_value(const Selection& selection) m_new_rotation = volume->get_instance_rotation() * (180.0 / M_PI); m_new_size = volume->get_instance_scaling_factor().cwiseProduct(wxGetApp().model().objects[volume->object_idx()]->raw_mesh_bounding_box().size()); #endif // ENABLE_WORLD_COORDINATE - m_new_scale = volume->get_instance_scaling_factor() * 100.0; + m_new_scale = m_new_size.cwiseQuotient(selection.get_full_unscaled_instance_local_bounding_box().size()) * 100.0; } m_new_enabled = true; From dcec7a8ad40eaad72789f6dba15cafc94664119f Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Tue, 28 Feb 2023 08:08:56 +0100 Subject: [PATCH 10/34] Fixed Rotate Gizmo orientation for mirrored objects + ensure that instances and volumes always rotate as rigid body --- src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp | 8 +--- src/slic3r/GUI/Selection.cpp | 59 ++++++++++++------------- src/slic3r/GUI/Selection.hpp | 2 +- 3 files changed, 30 insertions(+), 39 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp index f7951f97c..345d733af 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp @@ -238,13 +238,7 @@ void GLGizmoRotate::init_data_from_selection(const Selection& selection) selection.get_bounding_box_in_reference_system(ECoordinatesType::Local) : selection.get_bounding_box_in_current_reference_system(); m_bounding_box = box; m_center = box_trafo.translation(); - m_orient_matrix = Geometry::translation_transform(m_center); - if (!wxGetApp().obj_manipul()->is_world_coordinates() || m_force_local_coordinate) { - const GLVolume& v = *selection.get_first_volume(); - m_orient_matrix = m_orient_matrix * v.get_instance_transformation().get_rotation_matrix(); - if (selection.is_single_volume_or_modifier() && wxGetApp().obj_manipul()->is_local_coordinates() || m_force_local_coordinate) - m_orient_matrix = m_orient_matrix * v.get_volume_transformation().get_rotation_matrix(); - } + m_orient_matrix = box_trafo; m_radius = Offset + m_bounding_box.radius(); m_snap_coarse_in_radius = m_radius / 3.0f; diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index c6150ed68..4e9ac43ea 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -918,7 +918,7 @@ void Selection::translate(const Vec3d& displacement, TransformationType transfor v.set_instance_offset(inst_trafo.get_offset() + inst_trafo.get_rotation_matrix() * displacement); } else - transform_instance_relative_world(v, volume_data, transformation_type, Geometry::translation_transform(displacement), m_cache.dragging_center); + transform_instance_relative(v, volume_data, transformation_type, Geometry::translation_transform(displacement), m_cache.dragging_center); } else { if (transformation_type.local() && transformation_type.absolute()) { @@ -998,24 +998,24 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_ assert(transformation_type.relative() || (transformation_type.absolute() && transformation_type.local())); - Transform3d rotation_matrix = Geometry::rotation_transform(rotation); - for (unsigned int i : m_list) { + Transform3d rotation_matrix = Geometry::rotation_transform(rotation); GLVolume& v = *(*m_volumes)[i]; const VolumeCache& volume_data = m_cache.volumes_data[i]; const Geometry::Transformation& inst_trafo = volume_data.get_instance_transform(); if (m_mode == Instance && !is_wipe_tower()) { assert(is_from_fully_selected_instance(i)); if (transformation_type.instance()) { - const Vec3d world_inst_pivot = m_cache.dragging_center - inst_trafo.get_offset(); - const Vec3d local_inst_pivot = inst_trafo.get_matrix_no_offset().inverse() * world_inst_pivot; - Matrix3d inst_rotation, inst_scale; - inst_trafo.get_matrix().computeRotationScaling(&inst_rotation, &inst_scale); - const Transform3d trafo = inst_trafo.get_rotation_matrix() * rotation_matrix; - v.set_instance_transformation(Geometry::translation_transform(world_inst_pivot) * inst_trafo.get_offset_matrix() * trafo * Transform3d(inst_scale) * Geometry::translation_transform(-local_inst_pivot)); + // ensure that the instance rotates as a rigid body + const Transform3d inst_matrix_no_offset = inst_trafo.get_matrix_no_offset(); + const Transform3d inst_rotation_matrix = inst_trafo.get_rotation_matrix(); + rotation_matrix = inst_matrix_no_offset.inverse() * inst_rotation_matrix * rotation_matrix * inst_rotation_matrix.inverse() * inst_matrix_no_offset; + + // rotate around selection center + const Vec3d inst_pivot = inst_trafo.get_matrix_no_offset().inverse() * (m_cache.dragging_center - inst_trafo.get_offset()); + rotation_matrix = Geometry::translation_transform(inst_pivot) * rotation_matrix * Geometry::translation_transform(-inst_pivot); } - else - transform_instance_relative_world(v, volume_data, transformation_type, rotation_matrix, m_cache.dragging_center); + transform_instance_relative(v, volume_data, transformation_type, rotation_matrix, m_cache.dragging_center); } else { if (!is_single_volume_or_modifier()) { @@ -1024,27 +1024,19 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_ } else { if (transformation_type.instance()) { - // ensure proper sign of rotation for mirrored objects - if (inst_trafo.is_left_handed() && !rotation.normalized().isApprox(Vec3d::UnitX())) - rotation_matrix = rotation_matrix.inverse(); - // ensure that the volume rotates as a rigid body const Transform3d inst_scale_matrix = inst_trafo.get_scaling_factor_matrix(); rotation_matrix = inst_scale_matrix.inverse() * rotation_matrix * inst_scale_matrix; } else { if (transformation_type.local()) { - const Geometry::Transformation& vol_trafo = volume_data.get_volume_transform(); - const Geometry::Transformation world_trafo = inst_trafo * vol_trafo; - // ensure proper sign of rotation for mirrored objects - if (world_trafo.is_left_handed() && !rotation.normalized().isApprox(Vec3d::UnitX())) - rotation_matrix = rotation_matrix.inverse(); - // ensure that the volume rotates as a rigid body - if (Geometry::TransformationSVD(world_trafo).anisotropic_scale) { - const Transform3d inst_scale_matrix = inst_trafo.get_scaling_factor_matrix(); - rotation_matrix = inst_scale_matrix.inverse() * rotation_matrix * inst_scale_matrix; - } + const Geometry::Transformation& vol_trafo = volume_data.get_volume_transform(); + const Transform3d vol_matrix_no_offset = vol_trafo.get_matrix_no_offset(); + const Transform3d inst_scale_matrix = inst_trafo.get_scaling_factor_matrix(); + const Transform3d vol_rotation_matrix = vol_trafo.get_rotation_matrix(); + rotation_matrix = vol_matrix_no_offset.inverse() * inst_scale_matrix.inverse() * vol_rotation_matrix * rotation_matrix * + vol_rotation_matrix.inverse() * inst_scale_matrix * vol_matrix_no_offset; } } transform_volume_relative(v, volume_data, transformation_type, rotation_matrix, m_cache.dragging_center); @@ -1458,7 +1450,7 @@ void Selection::scale_and_translate(const Vec3d& scale, const Vec3d& translation v.set_instance_transformation(Geometry::translation_transform(world_inst_pivot) * offset_trafo * Transform3d(inst_rotation) * scale_trafo * Geometry::translation_transform(-local_inst_pivot)); } else - transform_instance_relative_world(v, volume_data, transformation_type, Geometry::translation_transform(translation) * Geometry::scale_transform(relative_scale), m_cache.dragging_center); + transform_instance_relative(v, volume_data, transformation_type, Geometry::translation_transform(translation) * Geometry::scale_transform(relative_scale), m_cache.dragging_center); } else { if (!is_single_volume_or_modifier()) { @@ -3331,16 +3323,21 @@ void Selection::paste_objects_from_clipboard() } #if ENABLE_WORLD_COORDINATE -void Selection::transform_instance_relative_world(GLVolume& volume, const VolumeCache& volume_data, TransformationType transformation_type, +void Selection::transform_instance_relative(GLVolume& volume, const VolumeCache& volume_data, TransformationType transformation_type, const Transform3d& transform, const Vec3d& world_pivot) { assert(transformation_type.relative()); - assert(transformation_type.world()); const Geometry::Transformation& inst_trafo = volume_data.get_instance_transform(); - const Vec3d inst_pivot = transformation_type.independent() && !is_from_single_instance() ? inst_trafo.get_offset() : world_pivot; - const Transform3d trafo = Geometry::translation_transform(inst_pivot) * transform * Geometry::translation_transform(-inst_pivot); - volume.set_instance_transformation(trafo * inst_trafo.get_matrix()); + if (transformation_type.world()) { + const Vec3d inst_pivot = transformation_type.independent() && !is_from_single_instance() ? inst_trafo.get_offset() : world_pivot; + const Transform3d trafo = Geometry::translation_transform(inst_pivot) * transform * Geometry::translation_transform(-inst_pivot); + volume.set_instance_transformation(trafo * inst_trafo.get_matrix()); + } + else if (transformation_type.instance()) + volume.set_instance_transformation(inst_trafo.get_matrix() * transform); + else + assert(false); } void Selection::transform_volume_relative(GLVolume& volume, const VolumeCache& volume_data, TransformationType transformation_type, diff --git a/src/slic3r/GUI/Selection.hpp b/src/slic3r/GUI/Selection.hpp index 4c818f30c..eb69d4491 100644 --- a/src/slic3r/GUI/Selection.hpp +++ b/src/slic3r/GUI/Selection.hpp @@ -516,7 +516,7 @@ private: void paste_objects_from_clipboard(); #if ENABLE_WORLD_COORDINATE - void transform_instance_relative_world(GLVolume& volume, const VolumeCache& volume_data, TransformationType transformation_type, + void transform_instance_relative(GLVolume& volume, const VolumeCache& volume_data, TransformationType transformation_type, const Transform3d& transform, const Vec3d& world_pivot); void transform_volume_relative(GLVolume& volume, const VolumeCache& volume_data, TransformationType transformation_type, const Transform3d& transform, const Vec3d& world_pivot); From 148732281d1b0cef815972f578e4035ec275eccd Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Tue, 28 Feb 2023 11:47:46 +0100 Subject: [PATCH 11/34] Fixed rotation of mirrored objects in Object Coordinates --- src/slic3r/GUI/Selection.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index 4e9ac43ea..e45f21467 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -1006,9 +1006,17 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_ if (m_mode == Instance && !is_wipe_tower()) { assert(is_from_fully_selected_instance(i)); if (transformation_type.instance()) { - // ensure that the instance rotates as a rigid body + // ensure that the instance rotates as a rigid body + Transform3d inst_rotation_matrix = inst_trafo.get_rotation_matrix(); + if (inst_trafo.is_left_handed()) { + Geometry::TransformationSVD inst_svd(inst_trafo); + inst_rotation_matrix = inst_svd.u * inst_svd.v.transpose(); + // ensure the rotation has the proper direction + if (!rotation.normalized().cwiseAbs().isApprox(Vec3d::UnitX())) + rotation_matrix = rotation_matrix.inverse(); + } + const Transform3d inst_matrix_no_offset = inst_trafo.get_matrix_no_offset(); - const Transform3d inst_rotation_matrix = inst_trafo.get_rotation_matrix(); rotation_matrix = inst_matrix_no_offset.inverse() * inst_rotation_matrix * rotation_matrix * inst_rotation_matrix.inverse() * inst_matrix_no_offset; // rotate around selection center From c1348079ed6b41a1f1c8740536f4a3736c64bf3e Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Tue, 28 Feb 2023 13:00:08 +0100 Subject: [PATCH 12/34] Fixed rotation of mirrored parts in Part Coordinates --- src/slic3r/GUI/Selection.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index e45f21467..fc2a6e0ea 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -1042,7 +1042,14 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_ const Geometry::Transformation& vol_trafo = volume_data.get_volume_transform(); const Transform3d vol_matrix_no_offset = vol_trafo.get_matrix_no_offset(); const Transform3d inst_scale_matrix = inst_trafo.get_scaling_factor_matrix(); - const Transform3d vol_rotation_matrix = vol_trafo.get_rotation_matrix(); + Transform3d vol_rotation_matrix = vol_trafo.get_rotation_matrix(); + if (vol_trafo.is_left_handed()) { + Geometry::TransformationSVD vol_svd(vol_trafo); + vol_rotation_matrix = vol_svd.u * vol_svd.v.transpose(); + // ensure the rotation has the proper direction + if (!rotation.normalized().cwiseAbs().isApprox(Vec3d::UnitX())) + rotation_matrix = rotation_matrix.inverse(); + } rotation_matrix = vol_matrix_no_offset.inverse() * inst_scale_matrix.inverse() * vol_rotation_matrix * rotation_matrix * vol_rotation_matrix.inverse() * inst_scale_matrix * vol_matrix_no_offset; } From 2ad6c7d4d53b1f7708ea56895bf8cb4c5c282d10 Mon Sep 17 00:00:00 2001 From: rtyr <36745189+rtyr@users.noreply.github.com> Date: Tue, 28 Feb 2023 20:25:10 +0100 Subject: [PATCH 13/34] Sync with PrusaSlicer settings --- resources/profiles/PrusaResearch.idx | 2 + resources/profiles/PrusaResearch.ini | 291 +++++++++++++++++++++++++-- 2 files changed, 281 insertions(+), 12 deletions(-) diff --git a/resources/profiles/PrusaResearch.idx b/resources/profiles/PrusaResearch.idx index 6a1792bcf..4995bc953 100644 --- a/resources/profiles/PrusaResearch.idx +++ b/resources/profiles/PrusaResearch.idx @@ -1,7 +1,9 @@ min_slic3r_version = 2.6.0-alpha1 +1.6.0-alpha2 Added profile for Prusament PETG Carbon Fiber and Fiberthree F3 PA-GF30 Pro. Updated acceleration settings for Prusa MINI. 1.6.0-alpha1 Updated FW version notification. Decreased min layer time for PLA. 1.6.0-alpha0 Default top fill set to monotonic lines. Updated infill/perimeter overlap values. Updated output filename format. Enabled dynamic overhang speeds. min_slic3r_version = 2.5.0-alpha0 +1.5.7 Added filament profile for Prusament PETG Carbon Fiber and Fiberthree F3 PA-GF30 Pro. 1.5.6 Updated FW version notification (MK2.5/MK3 family). Added filament profile for Kimya PEBA-S. 1.5.5 Added new Prusament Resin material profiles. Enabled g-code thumbnails for MK2.5 family printers. 1.5.4 Added material profiles for Prusament Resin BioBased60. diff --git a/resources/profiles/PrusaResearch.ini b/resources/profiles/PrusaResearch.ini index 5928e7a73..450ff0e92 100644 --- a/resources/profiles/PrusaResearch.ini +++ b/resources/profiles/PrusaResearch.ini @@ -5,7 +5,7 @@ name = Prusa Research # Configuration version of this file. Config file will only be installed, if the config_version differs. # This means, the server may force the PrusaSlicer configuration to be downgraded. -config_version = 1.6.0-alpha1 +config_version = 1.6.0-alpha2 # Where to get the updates from? config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/PrusaResearch/ changelog_url = https://files.prusa3d.com/?latest=slicer-profiles&lng=%1% @@ -145,7 +145,6 @@ bridge_flow_ratio = 1 bridge_speed = 25 brim_width = 0 brim_separation = 0.1 -clip_multipart_objects = 1 compatible_printers = complete_objects = 0 default_acceleration = 1000 @@ -268,8 +267,10 @@ fill_pattern = grid travel_speed = 150 wipe_tower = 0 default_acceleration = 1000 -first_layer_acceleration = 800 -infill_acceleration = 1000 +first_layer_acceleration = 600 +infill_acceleration = 1500 +solid_infill_acceleration = 1500 +top_solid_infill_acceleration = 800 bridge_acceleration = 1000 support_material_speed = 40 max_print_speed = 150 @@ -373,7 +374,9 @@ fill_pattern = gyroid fill_density = 15% travel_speed = 150 perimeter_acceleration = 800 -infill_acceleration = 1000 +infill_acceleration = 1500 +solid_infill_acceleration = 1500 +top_solid_infill_acceleration = 800 bridge_acceleration = 1000 first_layer_acceleration = 800 default_acceleration = 1250 @@ -1283,6 +1286,10 @@ support_material_extrusion_width = 0.35 bridge_acceleration = 300 support_material_contact_distance = 0.1 raft_contact_distance = 0.1 +infill_acceleration = 1000 +solid_infill_acceleration = 1000 +top_solid_infill_acceleration = 800 +external_perimeter_acceleration = 300 [print:0.07mm ULTRADETAIL @MINI] inherits = *0.07mm*; *MINI* @@ -1298,6 +1305,10 @@ support_material_extrusion_width = 0.35 bridge_acceleration = 300 support_material_contact_distance = 0.1 raft_contact_distance = 0.1 +infill_acceleration = 1000 +solid_infill_acceleration = 1000 +top_solid_infill_acceleration = 800 +external_perimeter_acceleration = 300 [print:0.10mm DETAIL @MINI] inherits = *0.10mm*; *MINI* @@ -1314,6 +1325,11 @@ fill_pattern = gyroid fill_density = 15% perimeters = 3 support_material_xy_spacing = 60% +infill_acceleration = 1200 +solid_infill_acceleration = 1000 +top_solid_infill_acceleration = 800 +perimeter_acceleration = 700 +external_perimeter_acceleration = 600 [print:0.15mm QUALITY @MINI] inherits = *0.15mm*; *MINI* @@ -1326,6 +1342,8 @@ top_solid_infill_speed = 40 fill_pattern = gyroid fill_density = 15% support_material_xy_spacing = 60% +perimeter_acceleration = 900 +external_perimeter_acceleration = 800 [print:0.15mm SPEED @MINI] inherits = *0.15mm*; *MINI* @@ -1336,6 +1354,8 @@ infill_speed = 140 solid_infill_speed = 140 top_solid_infill_speed = 40 support_material_xy_spacing = 60% +perimeter_acceleration = 1000 +external_perimeter_acceleration = 800 [print:0.20mm QUALITY @MINI] inherits = *0.20mm*; *MINI* @@ -1348,6 +1368,8 @@ top_solid_infill_speed = 40 fill_pattern = gyroid fill_density = 15% support_material_xy_spacing = 60% +perimeter_acceleration = 900 +external_perimeter_acceleration = 800 [print:0.20mm SPEED @MINI] inherits = *0.20mm*; *MINI* @@ -1359,6 +1381,8 @@ max_print_speed = 150 solid_infill_speed = 140 top_solid_infill_speed = 40 support_material_xy_spacing = 60% +perimeter_acceleration = 1000 +external_perimeter_acceleration = 800 [print:0.25mm DRAFT @MINI] inherits = *0.25mm*; *MINI* @@ -1378,6 +1402,8 @@ top_infill_extrusion_width = 0.4 support_material_xy_spacing = 60% support_material_contact_distance = 0.2 raft_contact_distance = 0.2 +perimeter_acceleration = 1000 +external_perimeter_acceleration = 800 # MINI - 0.25mm nozzle @@ -1389,6 +1415,10 @@ fill_density = 20% support_material_speed = 30 support_material_contact_distance = 0.07 raft_contact_distance = 0.07 +infill_acceleration = 1000 +solid_infill_acceleration = 1000 +top_solid_infill_acceleration = 800 +external_perimeter_acceleration = 300 [print:0.07mm ULTRADETAIL @0.25 nozzle MINI] inherits = *0.07mm*; *0.25nozzle*; *MINI* @@ -1401,6 +1431,10 @@ fill_pattern = grid fill_density = 20% support_material_contact_distance = 0.07 raft_contact_distance = 0.07 +infill_acceleration = 1000 +solid_infill_acceleration = 1000 +top_solid_infill_acceleration = 800 +external_perimeter_acceleration = 300 [print:0.10mm DETAIL @0.25 nozzle MINI] inherits = *0.10mm*; *0.25nozzleMINI*; *MINI* @@ -1409,6 +1443,10 @@ fill_pattern = grid fill_density = 20% support_material_contact_distance = 0.07 raft_contact_distance = 0.07 +infill_acceleration = 1200 +solid_infill_acceleration = 1000 +top_solid_infill_acceleration = 800 +external_perimeter_acceleration = 500 [print:0.15mm QUALITY @0.25 nozzle MINI] inherits = *0.15mm*; *0.25nozzleMINI*; *MINI* @@ -1421,6 +1459,10 @@ perimeter_extrusion_width = 0.27 external_perimeter_extrusion_width = 0.27 infill_extrusion_width = 0.27 solid_infill_extrusion_width = 0.27 +infill_acceleration = 1500 +solid_infill_acceleration = 1000 +top_solid_infill_acceleration = 800 +external_perimeter_acceleration = 500 # MINI - 0.6mm nozzle @@ -1433,11 +1475,17 @@ max_print_speed = 100 perimeter_speed = 45 solid_infill_speed = 70 top_solid_infill_speed = 45 -infill_extrusion_width = 0.65 -solid_infill_extrusion_width = 0.65 +perimeter_extrusion_width = 0.6 +external_perimeter_extrusion_width = 0.6 +infill_extrusion_width = 0.6 +solid_infill_extrusion_width = 0.6 +top_infill_extrusion_width = 0.5 support_material_contact_distance = 0.22 raft_contact_distance = 0.22 bridge_flow_ratio = 1 +top_solid_infill_acceleration = 800 +perimeter_acceleration = 900 +external_perimeter_acceleration = 800 [print:0.20mm DETAIL @0.6 nozzle MINI] inherits = *0.20mm*; *0.6nozzleMINI* @@ -1448,11 +1496,16 @@ max_print_speed = 100 perimeter_speed = 45 solid_infill_speed = 70 top_solid_infill_speed = 45 -infill_extrusion_width = 0.65 -solid_infill_extrusion_width = 0.65 +perimeter_extrusion_width = 0.6 +external_perimeter_extrusion_width = 0.6 +infill_extrusion_width = 0.6 +solid_infill_extrusion_width = 0.6 +top_infill_extrusion_width = 0.5 support_material_contact_distance = 0.22 raft_contact_distance = 0.22 bridge_flow_ratio = 1 +perimeter_acceleration = 900 +external_perimeter_acceleration = 800 [print:0.30mm QUALITY @0.6 nozzle MINI] inherits = *0.30mm*; *0.6nozzleMINI* @@ -1465,9 +1518,12 @@ solid_infill_speed = 65 top_solid_infill_speed = 45 external_perimeter_extrusion_width = 0.68 perimeter_extrusion_width = 0.68 +top_infill_extrusion_width = 0.55 support_material_contact_distance = 0.25 raft_contact_distance = 0.25 bridge_flow_ratio = 1 +perimeter_acceleration = 900 +external_perimeter_acceleration = 800 [print:0.35mm SPEED @0.6 nozzle MINI] inherits = *0.35mm*; *0.6nozzleMINI* @@ -1483,6 +1539,8 @@ perimeter_extrusion_width = 0.68 support_material_contact_distance = 0.25 raft_contact_distance = 0.25 bridge_flow_ratio = 0.95 +perimeter_acceleration = 1000 +external_perimeter_acceleration = 800 [print:0.40mm DRAFT @0.6 nozzle MINI] inherits = *0.40mm*; *0.6nozzleMINI* @@ -1500,6 +1558,8 @@ solid_infill_extrusion_width = 0.68 support_material_contact_distance = 0.25 raft_contact_distance = 0.25 bridge_flow_ratio = 0.95 +perimeter_acceleration = 1000 +external_perimeter_acceleration = 800 # MINI - 0.8mm nozzle @@ -1508,13 +1568,17 @@ inherits = 0.30mm DETAIL @0.8 nozzle compatible_printers_condition = printer_model=="MINI" and nozzle_diameter[0]==0.8 perimeter_speed = 35 external_perimeter_speed = 25 -infill_acceleration = 1000 infill_speed = 50 max_print_speed = 80 solid_infill_speed = 45 top_solid_infill_speed = 35 support_material_speed = 40 travel_speed = 150 +infill_acceleration = 1500 +solid_infill_acceleration = 1500 +top_solid_infill_acceleration = 800 +perimeter_acceleration = 900 +external_perimeter_acceleration = 800 [print:0.40mm QUALITY @0.8 nozzle MINI] inherits = 0.40mm QUALITY @0.8 nozzle @@ -1525,11 +1589,15 @@ solid_infill_speed = 40 top_solid_infill_speed = 30 support_material_speed = 40 travel_speed = 150 +infill_acceleration = 1500 +solid_infill_acceleration = 1500 +top_solid_infill_acceleration = 800 +perimeter_acceleration = 1000 +external_perimeter_acceleration = 800 [print:0.55mm DRAFT @0.8 nozzle MINI] inherits = 0.55mm DRAFT @0.8 nozzle compatible_printers_condition = printer_model=="MINI" and nozzle_diameter[0]==0.8 -infill_acceleration = 1000 infill_speed = 40 solid_infill_speed = 40 support_material_speed = 35 @@ -1539,6 +1607,11 @@ top_solid_infill_speed = 28 external_perimeter_extrusion_width = 1 perimeter_extrusion_width = 1 travel_speed = 150 +infill_acceleration = 1500 +solid_infill_acceleration = 1500 +top_solid_infill_acceleration = 800 +perimeter_acceleration = 1000 +external_perimeter_acceleration = 800 # XXXXXXxxXXXXXXXXXXXXXX # XXX--- filament ---XXX @@ -3865,6 +3938,17 @@ filament_spool_weight = 201 filament_type = PETG compatible_printers_condition = nozzle_diameter[0]!=0.8 and nozzle_diameter[0]!=0.6 and printer_model!="MK2SMM" and printer_model!="MINI" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material) +[filament:Prusament PETG Carbon Fiber] +inherits = Prusament PETG +filament_vendor = Prusa Polymers +first_layer_temperature = 260 +temperature = 265 +extrusion_multiplier = 1.03 +filament_cost = 54.99 +filament_density = 1.27 +filament_colour = #BBBBBB +compatible_printers_condition = nozzle_diameter[0]>=0.4 and nozzle_diameter[0]!=0.8 and nozzle_diameter[0]!=0.6 and printer_model!="MK2SMM" and printer_model!="MINI" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material) + [filament:Prusa PETG @0.6 nozzle] inherits = *PET06* renamed_from = "Prusa PET 0.6 nozzle"; "Prusa PETG 0.6 nozzle" @@ -3883,6 +3967,14 @@ filament_density = 1.27 filament_spool_weight = 201 filament_type = PETG +[filament:Prusament PETG Carbon Fiber @0.6 nozzle] +inherits = Prusament PETG @0.6 nozzle +first_layer_temperature = 260 +temperature = 265 +extrusion_multiplier = 1.03 +filament_cost = 54.99 +filament_colour = #BBBBBB + [filament:Filament PM PETG @0.6 nozzle] inherits = *PET06* renamed_from = "Plasty Mladec PETG @0.6 nozzle" @@ -3976,6 +4068,14 @@ filament_cost = 36.29 filament_density = 1.27 filament_spool_weight = 201 +[filament:Prusament PETG Carbon Fiber @MMU2] +inherits = Prusament PETG @MMU2 +first_layer_temperature = 260 +temperature = 260 +extrusion_multiplier = 1.03 +filament_cost = 54.99 +filament_colour = #BBBBBB + [filament:Generic PETG @MMU2 0.6 nozzle] inherits = *PET MMU2 06* renamed_from = "Generic PET MMU2 0.6 nozzle"; "Generic PETG MMU2 0.6 nozzle" @@ -3995,6 +4095,14 @@ filament_cost = 36.29 filament_density = 1.27 filament_spool_weight = 201 +[filament:Prusament PETG Carbon Fiber @MMU2 0.6 nozzle] +inherits = Prusament PETG @MMU2 0.6 nozzle +first_layer_temperature = 260 +temperature = 260 +extrusion_multiplier = 1.03 +filament_cost = 54.99 +filament_colour = #BBBBBB + [filament:Filament PM PETG @MMU2 0.6 nozzle] inherits = *PET MMU2 06* renamed_from = "Plasty Mladec PETG @MMU2 0.6 nozzle" @@ -4079,6 +4187,87 @@ bed_temperature = 30 filament_retract_length = 0 extrusion_multiplier = 1.16 +[filament:Print With Smile PLA] +inherits = *PLA* +filament_vendor = Print With Smile +filament_cost = 535 +filament_density = 1.24 +filament_spool_weight = 0 +filament_colour = #FFFF6F +filament_max_volumetric_speed = 15 +first_layer_temperature = 205 +temperature = 205 + +[filament:Print With Smile PETG] +inherits = *PET* +filament_vendor = Print With Smile +filament_cost = 590 +filament_density = 1.27 +filament_spool_weight = 0 +filament_colour = #4D9398 +filament_max_volumetric_speed = 8 +temperature = 245 +first_layer_bed_temperature = 85 +first_layer_temperature = 240 +bed_temperature = 90 + +[filament:Print With Smile PETG @MINI] +inherits = Print With Smile PETG; *PETMINI* + +[filament:Print With Smile ASA] +inherits = Ultrafuse ASA +filament_vendor = Print With Smile +filament_cost = 625 +first_layer_temperature = 250 +temperature = 250 +first_layer_bed_temperature = 105 +bed_temperature = 110 +filament_type = ASA +max_fan_speed = 40 +bridge_fan_speed = 70 +filament_max_volumetric_speed = 11 + +[filament:Print With Smile ABS] +inherits = *ABSC* +filament_vendor = Print With Smile +filament_cost = 535 +filament_density = 1.08 +first_layer_temperature = 240 +temperature = 240 + +[filament:Print With Smile PETG CF] +inherits = Extrudr XPETG CF +filament_vendor = Print With Smile +filament_cost = 899 +filament_density = 1.29 +filament_notes = +first_layer_temperature = 260 +temperature = 260 +first_layer_bed_temperature = 85 +bed_temperature = 85 +max_fan_speed = 55 +bridge_fan_speed = 60 +filament_max_volumetric_speed = 5 + +[filament:Print With Smile PETG CF @MINI] +inherits = Print With Smile PETG CF; *PETMINI* + +[filament:Print With Smile TPU96A] +inherits = *FLEX* +filament_vendor = Print With Smile +filament_cost = 1200 +filament_density = 1.31 +extrusion_multiplier = 1.1 +filament_max_volumetric_speed = 1.35 +fan_always_on = 1 +cooling = 0 +max_fan_speed = 60 +min_fan_speed = 60 +disable_fan_first_layers = 4 +full_fan_speed_layer = 6 +filament_retract_length = 1.2 +filament_deretract_speed = 20 + [filament:Fiberlogy Easy PLA] inherits = *PLA* renamed_from = Fiberlogy PLA @@ -4680,6 +4869,23 @@ fan_always_on = 1 max_fan_speed = 15 min_fan_speed = 15 +[filament:Fiberthree F3 PA-GF30 Pro] +inherits = Prusament PC Blend Carbon Fiber +filament_vendor = Fiberthree +filament_cost = 208.01 +filament_density = 1.35 +extrusion_multiplier = 1.03 +first_layer_temperature = 275 +temperature = 285 +first_layer_bed_temperature = 90 +bed_temperature = 90 +fan_below_layer_time = 10 +compatible_printers_condition = printer_model!="MINI" and ! single_extruder_multi_material +max_fan_speed = 15 +min_fan_speed = 15 +filament_type = PA +filament_max_volumetric_speed = 6 + [filament:Taulman T-Glase] inherits = *PET* filament_vendor = Taulman @@ -4889,6 +5095,13 @@ renamed_from = "Prusa PET MMU1"; "Prusa PETG MMU1" [filament:Prusament PETG @MMU1] inherits = Prusament PETG; *PETMMU1* +[filament:Prusament PETG Carbon Fiber @MMU1] +inherits = Prusament PETG @MMU1 +first_layer_temperature = 260 +temperature = 265 +filament_cost = 54.99 +filament_colour = #BBBBBB + [filament:Taulman T-Glase @MMU1] inherits = Taulman T-Glase; *PETMMU1* start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}30{endif}; Filament gcode" @@ -5016,6 +5229,19 @@ fan_always_on = 1 max_fan_speed = 15 min_fan_speed = 15 +[filament:Fiberthree F3 PA-GF30 Pro @MINI] +inherits = Fiberthree F3 PA-GF30 Pro +filament_vendor = Fiberthree +first_layer_temperature = 275 +temperature = 280 +compatible_printers_condition = nozzle_diameter[0]>=0.4 and printer_model=="MINI" +filament_retract_length = nil +filament_retract_speed = nil +filament_retract_lift = nil +filament_retract_before_travel = nil +filament_wipe = nil +filament_type = PA + [filament:Kimya ABS Carbon @MINI] inherits = Kimya ABS Carbon; *ABSMINI* filament_max_volumetric_speed = 6 @@ -5043,6 +5269,15 @@ inherits = Verbatim ABS; *ABSMINI* inherits = Prusament PETG; *PETMINI* compatible_printers_condition = printer_model=="MINI" and nozzle_diameter[0]!=0.8 and nozzle_diameter[0]!=0.6 +[filament:Prusament PETG Carbon Fiber @MINI] +inherits = Prusament PETG @MINI +first_layer_temperature = 260 +temperature = 265 +extrusion_multiplier = 1.03 +filament_cost = 54.99 +filament_colour = #BBBBBB +compatible_printers_condition = printer_model=="MINI" and nozzle_diameter[0]>=0.4 and nozzle_diameter[0]!=0.8 and nozzle_diameter[0]!=0.6 + [filament:Kimya PETG Carbon @MINI] inherits = Kimya PETG Carbon; *PETMINI* filament_max_volumetric_speed = 6 @@ -5053,6 +5288,14 @@ compatible_printers_condition = nozzle_diameter[0]>=0.4 and printer_model=="MINI [filament:Prusament PETG @0.6 nozzle MINI] inherits = Prusament PETG; *PETMINI06* +[filament:Prusament PETG Carbon Fiber @0.6 nozzle MINI] +inherits = Prusament PETG @0.6 nozzle MINI +first_layer_temperature = 260 +temperature = 265 +extrusion_multiplier = 1.03 +filament_cost = 54.99 +filament_colour = #BBBBBB + [filament:Generic PETG @0.6 nozzle MINI] inherits = Generic PETG; *PETMINI06* renamed_from = "Generic PET 0.6 nozzle MINI"; "Generic PETG 0.6 nozzle MINI" @@ -5358,6 +5601,14 @@ filament_retract_lift = 0.2 slowdown_below_layer_time = 20 compatible_printers_condition = nozzle_diameter[0]==0.8 and printer_model!="MK2SMM" and printer_model!="MINI" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material) +[filament:Prusament PETG Carbon Fiber @0.8 nozzle] +inherits = Prusament PETG @0.8 nozzle +first_layer_temperature = 265 +temperature = 270 +extrusion_multiplier = 1.03 +filament_cost = 54.99 +filament_colour = #BBBBBB + [filament:Prusament ASA @0.8 nozzle] inherits = Prusament ASA first_layer_temperature = 265 @@ -5437,6 +5688,14 @@ temperature = 240 slowdown_below_layer_time = 20 filament_ramming_parameters = "120 140 5.51613 5.6129 5.70968 5.77419 5.77419 5.74194 5.80645 5.93548 6.06452 6.19355 6.3871 6.74194 7.25806 7.87097 8.54839 9.22581 10 10.8387| 0.05 5.5032 0.45 5.63868 0.95 5.8 1.45 5.7839 1.95 6.02257 2.45 6.25811 2.95 7.08395 3.45 8.43875 3.95 9.92258 4.45 11.3419 4.95 7.6" +[filament:Prusament PETG Carbon Fiber @MMU2 0.8 nozzle] +inherits = Prusament PETG @MMU2 0.8 nozzle +first_layer_temperature = 265 +temperature = 270 +extrusion_multiplier = 1.03 +filament_cost = 54.99 +filament_colour = #BBBBBB + [filament:Generic PLA @MMU2 0.8 nozzle] inherits = Generic PLA @MMU2 compatible_printers_condition = nozzle_diameter[0]==0.8 and printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material @@ -5520,6 +5779,14 @@ filament_retract_lift = 0.25 slowdown_below_layer_time = 20 compatible_printers_condition = nozzle_diameter[0]==0.8 and printer_model=="MINI" +[filament:Prusament PETG Carbon Fiber @0.8 nozzle MINI] +inherits = Prusament PETG @0.8 nozzle MINI +first_layer_temperature = 265 +temperature = 270 +extrusion_multiplier = 1.03 +filament_cost = 54.99 +filament_colour = #BBBBBB + [filament:Prusament ASA @0.8 nozzle MINI] inherits = Prusament ASA @MINI first_layer_temperature = 265 @@ -10039,7 +10306,7 @@ default_filament_profile = "Prusament PLA" default_print_profile = 0.15mm QUALITY @MINI gcode_flavor = marlin2 machine_max_acceleration_e = 5000 -machine_max_acceleration_extruding = 1250 +machine_max_acceleration_extruding = 2000 machine_max_acceleration_retracting = 1250 machine_max_acceleration_travel = 2500 machine_max_acceleration_x = 2500 From 4536bd89d7e4acba522aa04f0a763f7ca425ac5e Mon Sep 17 00:00:00 2001 From: rtyr <36745189+rtyr@users.noreply.github.com> Date: Tue, 28 Feb 2023 20:47:08 +0100 Subject: [PATCH 14/34] Sync with PrusaSlicer-settings --- resources/profiles/Templates.idx | 1 + resources/profiles/Templates.ini | 29 ++++++++++++++++++++++++++--- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/resources/profiles/Templates.idx b/resources/profiles/Templates.idx index 3edb4400f..297aeb1fe 100644 --- a/resources/profiles/Templates.idx +++ b/resources/profiles/Templates.idx @@ -1,2 +1,3 @@ min_slic3r_version = 2.6.0-alpha0 +1.0.1 Added Prusament PETG Carbon Fiber, Fiberthree F3 PA-GF30 Pro. 1.0.0 Initial diff --git a/resources/profiles/Templates.ini b/resources/profiles/Templates.ini index 26b0c0f12..cf7b8ebe8 100644 --- a/resources/profiles/Templates.ini +++ b/resources/profiles/Templates.ini @@ -2,14 +2,12 @@ [vendor] name = Templates -config_version = 1.0.0 +config_version = 1.0.1 config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Templates/ templates_profile = 1 ## Generic filament profiles -# Print profiles for the Prusa Research printers. - [filament:*common*] cooling = 1 compatible_printers = @@ -1547,6 +1545,16 @@ filament_density = 1.27 filament_spool_weight = 201 filament_type = PETG +[filament:Prusament PETG Carbon Fiber] +inherits = Prusament PETG +filament_vendor = Prusa Polymers +first_layer_temperature = 260 +temperature = 265 +extrusion_multiplier = 1.03 +filament_cost = 54.99 +filament_density = 1.27 +filament_colour = #BBBBBB + [filament:Prusa PLA] inherits = *PLA* filament_vendor = Made for Prusa @@ -2055,6 +2063,21 @@ fan_always_on = 1 max_fan_speed = 15 min_fan_speed = 15 +[filament:Fiberthree F3 PA-GF30 Pro] +inherits = Prusament PC Blend Carbon Fiber +filament_vendor = Fiberthree +filament_cost = 208.01 +filament_density = 1.35 +extrusion_multiplier = 1.03 +first_layer_temperature = 275 +temperature = 285 +first_layer_bed_temperature = 90 +bed_temperature = 90 +fan_below_layer_time = 10 +max_fan_speed = 15 +min_fan_speed = 15 +filament_type = PA + [filament:Taulman T-Glase] inherits = *PET* filament_vendor = Taulman From daaa9669e9c6d559ffd4d190d0442bd61f57c686 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Tue, 21 Feb 2023 14:00:52 +0100 Subject: [PATCH 15/34] File -> Import -> Import Zip Archive --- src/slic3r/GUI/GUI_App.cpp | 13 +++++++++++++ src/slic3r/GUI/GUI_App.hpp | 3 +++ src/slic3r/GUI/MainFrame.cpp | 4 ++++ src/slic3r/GUI/Plater.cpp | 11 +++++++++++ src/slic3r/GUI/Plater.hpp | 1 + 5 files changed, 32 insertions(+) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 520f67aed..f189aeb47 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -480,6 +480,8 @@ static const FileWildcards file_wildcards_by_type[FT_SIZE] = { /* FT_TEX */ { "Texture"sv, { ".png"sv, ".svg"sv } }, /* FT_SL1 */ { "Masked SLA files"sv, { ".sl1"sv, ".sl1s"sv, ".pwmx"sv } }, + + /* FT_ZIP */ { "Zip files"sv, { ".zip"sv } }, }; #if ENABLE_ALTERNATIVE_FILE_WILDCARDS_GENERATOR @@ -1977,6 +1979,17 @@ void GUI_App::import_model(wxWindow *parent, wxArrayString& input_files) const dialog.GetPaths(input_files); } +void GUI_App::import_zip(wxWindow* parent, wxString& input_file) const +{ + wxFileDialog dialog(parent ? parent : GetTopWindow(), + _L("Choose ZIP file:"), + from_u8(app_config->get_last_dir()), "", + file_wildcards(FT_ZIP), wxFD_OPEN | wxFD_FILE_MUST_EXIST); + + if (dialog.ShowModal() == wxID_OK) + input_file = dialog.GetPath(); +} + void GUI_App::load_gcode(wxWindow* parent, wxString& input_file) const { input_file.Clear(); diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 3f8d47fd7..da231bae6 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -73,6 +73,8 @@ enum FileType FT_SL1, + FT_ZIP, + FT_SIZE, }; @@ -252,6 +254,7 @@ public: void keyboard_shortcuts(); void load_project(wxWindow *parent, wxString& input_file) const; void import_model(wxWindow *parent, wxArrayString& input_files) const; + void import_zip(wxWindow* parent, wxString& input_file) const; void load_gcode(wxWindow* parent, wxString& input_file) const; static bool catch_error(std::function cb, const std::string& err); diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index b656f056a..ab82c1033 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -1293,6 +1293,10 @@ void MainFrame::init_menubar_as_editor() [this](wxCommandEvent&) { if (m_plater) m_plater->import_sl1_archive(); }, "import_plater", nullptr, [this](){return m_plater != nullptr && m_plater->get_ui_job_worker().is_idle(); }, this); + append_menu_item(import_menu, wxID_ANY, _L("Import ZIP Achive") + dots, _L("Load a zip achive"), + [this](wxCommandEvent&) { if (m_plater) m_plater->import_zip_archive(); }, "import_plater", nullptr, + [this]() {return m_plater != nullptr; }, this); + import_menu->AppendSeparator(); append_menu_item(import_menu, wxID_ANY, _L("Import &Config") + dots + "\tCtrl+L", _L("Load exported configuration file"), [this](wxCommandEvent&) { load_config_file(); }, "import_config", nullptr, diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index e04b05033..5a948f577 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -5479,6 +5479,17 @@ void Plater::add_model(bool imperial_units/* = false*/) wxGetApp().mainframe->update_title(); } +void Plater::import_zip_archive() +{ + wxString input_file; + wxGetApp().import_zip(this, input_file); + if (input_file.empty()) + return; + + fs::path path = into_path(input_file); + preview_zip_archive(path); +} + void Plater::import_sl1_archive() { auto &w = get_ui_job_worker(); diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 3dcca746d..db4349101 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -166,6 +166,7 @@ public: void load_project(); void load_project(const wxString& filename); void add_model(bool imperial_units = false); + void import_zip_archive(); void import_sl1_archive(); void extract_config_from_project(); void load_gcode(); From 6f9e3c24259e63b9631f95307dc787dec2394cb1 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Wed, 1 Mar 2023 12:16:20 +0100 Subject: [PATCH 16/34] Allow XL for PrusaLink and PrusaConnect --- src/slic3r/GUI/PhysicalPrinterDialog.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/slic3r/GUI/PhysicalPrinterDialog.cpp b/src/slic3r/GUI/PhysicalPrinterDialog.cpp index f67af6dfc..25f8bea62 100644 --- a/src/slic3r/GUI/PhysicalPrinterDialog.cpp +++ b/src/slic3r/GUI/PhysicalPrinterDialog.cpp @@ -547,18 +547,19 @@ void PhysicalPrinterDialog::update_host_type(bool printer_change) } link, connect; // allowed models are: all MINI, all MK3 and newer, MK2.5 and MK2.5S auto model_supports_prusalink = [](const std::string& model) { - return model.size() >= 3 && + return model.size() >= 2 && (( boost::starts_with(model, "MK") && model[2] > '2' && model[2] <= '9') || boost::starts_with(model, "MINI") || boost::starts_with(model, "MK2.5") - //|| boost::starts_with(model, "MK2.5S") + || boost::starts_with(model, "XL") ); }; // allowed models are: all MK3/S and MK2.5/S auto model_supports_prusaconnect = [](const std::string& model) { - return model.size() >= 3 && - (boost::starts_with(model, "MK3") + return model.size() >= 2 && + ((boost::starts_with(model, "MK") && model[2] > '2' && model[2] <= '9') || boost::starts_with(model, "MK2.5") + || boost::starts_with(model, "XL") ); }; From 3985250b879e09b637c1bbf4d8960dab9536679c Mon Sep 17 00:00:00 2001 From: YuSanka Date: Wed, 1 Mar 2023 12:18:34 +0100 Subject: [PATCH 17/34] Fix for SPE-1544 - Dowels come from model during camera moving in edit connectors mode --- src/slic3r/GUI/Gizmos/GLGizmoCut.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp index a522f5533..7ce8376ba 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp @@ -996,6 +996,8 @@ void GLGizmoCut3D::update_raycasters_for_picking_transform() const Vec3d& instance_offset = mo->instances[inst_id]->get_offset(); const double sla_shift = double(m_c->selection_info()->get_sla_shift()); + const bool looking_forward = is_looking_forward(); + for (size_t i = 0; i < connectors.size(); ++i) { const CutConnector& connector = connectors[i]; @@ -1004,9 +1006,8 @@ void GLGizmoCut3D::update_raycasters_for_picking_transform() Vec3d pos = connector.pos + instance_offset; if (connector.attribs.type == CutConnectorType::Dowel && connector.attribs.style == CutConnectorStyle::Prism) { - if (is_looking_forward()) - pos -= static_cast(height - 0.05f) * m_clp_normal; - else + height = 0.05f; + if (!looking_forward) pos += 0.05 * m_clp_normal; } pos[Z] += sla_shift; @@ -2065,6 +2066,8 @@ void GLGizmoCut3D::render_connectors() m_has_invalid_connector = false; m_info_stats.invalidate(); + const bool looking_forward = is_looking_forward(); + for (size_t i = 0; i < connectors.size(); ++i) { const CutConnector& connector = connectors[i]; @@ -2093,20 +2096,19 @@ void GLGizmoCut3D::render_connectors() if (connector.attribs.type == CutConnectorType::Dowel && connector.attribs.style == CutConnectorStyle::Prism) { if (m_connectors_editing) { - if (is_looking_forward()) - pos -= static_cast(height-0.05f) * m_clp_normal; - else + height = 0.05f; + if (!looking_forward) pos += 0.05 * m_clp_normal; } else { - if (is_looking_forward()) + if (looking_forward) pos -= static_cast(height) * m_clp_normal; else pos += static_cast(height) * m_clp_normal; height *= 2; } } - else if (!is_looking_forward()) + else if (!looking_forward) pos += 0.05 * m_clp_normal; const Transform3d view_model_matrix = camera.get_view_matrix() * translation_transform(pos) * m_rotation_m * From e09bdef952c260425f21edb94b20bdc831fea114 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Wed, 1 Mar 2023 12:22:31 +0100 Subject: [PATCH 18/34] Fix for SPE-1543 - "T"- key add text to cut object with plugs/dowels --- src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp index 71374de23..0210de3b5 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp @@ -885,7 +885,7 @@ void GLGizmoEmboss::on_set_state() priv::get_volume(m_parent.get_selection().get_model()->objects, m_volume_id) == nullptr ) { // reopen gizmo when new object is created GLGizmoBase::m_state = GLGizmoBase::Off; - if (wxGetApp().get_mode() == comSimple) + if (wxGetApp().get_mode() == comSimple || wxGetApp().obj_list()->has_selected_cut_object()) // It's impossible to add a part in simple mode return; // start creating new object From dfe735fb6c4ee38bfd28a7bce97df431ba2ef897 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Wed, 1 Mar 2023 13:33:44 +0100 Subject: [PATCH 19/34] Postpone post_init() until opengl is initialized on all systems. Revert on win --- src/slic3r/GUI/GUI_App.cpp | 13 ++++++------- src/slic3r/GUI/GUI_App.hpp | 2 -- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index f189aeb47..cc60b3cff 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -887,13 +887,9 @@ wxGLContext* GUI_App::init_glcontext(wxGLCanvas& canvas) bool GUI_App::init_opengl() { -#ifdef __linux__ bool status = m_opengl_mgr.init_gl(); m_opengl_initialized = true; return status; -#else - return m_opengl_mgr.init_gl(); -#endif } // gets path to PrusaSlicer.ini, returns semver from first line comment @@ -1370,12 +1366,15 @@ bool GUI_App::on_init_inner() // An ugly solution to GH #5537 in which GUI_App::init_opengl (normally called from events wxEVT_PAINT // and wxEVT_SET_FOCUS before GUI_App::post_init is called) wasn't called before GUI_App::post_init and OpenGL wasn't initialized. -#ifdef __linux__ - if (! m_post_initialized && m_opengl_initialized) { + // Since issue #9774 Where same problem occured on MacOS Ventura, we decided to have this check on MacOS as well. + +#ifdef __linux__ || __APPLE__ + if (!m_post_initialized && m_opengl_initialized) { #else - if (! m_post_initialized) { + if (!m_post_initialized) { #endif m_post_initialized = true; + #ifdef WIN32 this->mainframe->register_win32_callbacks(); #endif diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index da231bae6..51900a9b6 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -127,9 +127,7 @@ private: bool m_last_app_conf_lower_version{ false }; EAppMode m_app_mode{ EAppMode::Editor }; bool m_is_recreating_gui{ false }; -#ifdef __linux__ bool m_opengl_initialized{ false }; -#endif wxColour m_color_label_modified; wxColour m_color_label_sys; From 1749f745782cd72ff28e993ada04b3419d24e766 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Wed, 1 Mar 2023 13:37:29 +0100 Subject: [PATCH 20/34] Fix bug when mini pillar widens and the end radius is too small. only affects SLA default supports fixes SPE-1542 --- src/libslic3r/SLA/SupportTreeUtilsLegacy.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libslic3r/SLA/SupportTreeUtilsLegacy.hpp b/src/libslic3r/SLA/SupportTreeUtilsLegacy.hpp index b504d82fb..f8e2f3024 100644 --- a/src/libslic3r/SLA/SupportTreeUtilsLegacy.hpp +++ b/src/libslic3r/SLA/SupportTreeUtilsLegacy.hpp @@ -141,6 +141,7 @@ std::pair create_ground_pillar( if (head_id >= 0) builder.head(head_id).bridge_id = br.id; endp = diffbr->endp; radius = diffbr->end_r; + end_radius = diffbr->end_r; builder.add_junction(endp, radius); non_head = true; dir = diffbr->get_dir(); From 55b3bf879acd987cce5d4553543ccb0979c8ca46 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 1 Mar 2023 15:17:43 +0100 Subject: [PATCH 21/34] SPE-1547 - Fixed object shown in preview while it should not --- src/slic3r/GUI/GLCanvas3D.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 29ef6e94d..d0967d3db 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -5016,8 +5016,10 @@ void GLCanvas3D::_refresh_if_shown_on_screen() // frequently enough, we call render() here directly when we can. render(); assert(m_initialized); - if (requires_reload_scene) - reload_scene(true); + if (requires_reload_scene) { + if (wxGetApp().plater()->is_view3D_shown()) + reload_scene(true); + } } } From a507504b228725bf056a86aa0ef4c0c1ea299c67 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Wed, 1 Mar 2023 15:33:13 +0100 Subject: [PATCH 22/34] PresetCollection::load_external_preset : Added check for m_idx_selected before call of the get_selected_preset. --- src/libslic3r/Preset.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index eebb4d54f..55a643ea1 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -879,7 +879,7 @@ std::pair PresetCollection::load_external_preset( // Insert a new profile. Preset &preset = this->load_preset(path, new_name, std::move(cfg), select == LoadAndSelect::Always); preset.is_external = true; - if (&this->get_selected_preset() == &preset) + if (this->m_idx_selected != size_t(-1) && &this->get_selected_preset() == &preset) this->get_edited_preset().is_external = true; return std::make_pair(&preset, false); From 61b31bfbc3b8a92993b6894040b2a22cc4e2850d Mon Sep 17 00:00:00 2001 From: David Kocik Date: Thu, 16 Feb 2023 16:30:25 +0100 Subject: [PATCH 23/34] PrusaLink storage names in Upload dialog --- src/slic3r/GUI/Plater.cpp | 7 ++++--- src/slic3r/GUI/PrintHostDialogs.cpp | 19 ++++++++++--------- src/slic3r/GUI/PrintHostDialogs.hpp | 3 ++- src/slic3r/Utils/OctoPrint.cpp | 25 ++++++++++++++----------- src/slic3r/Utils/OctoPrint.hpp | 2 +- src/slic3r/Utils/PrintHost.hpp | 2 +- 6 files changed, 32 insertions(+), 26 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 5a948f577..095147914 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -6948,18 +6948,19 @@ void Plater::send_gcode() upload_job.printhost->get_groups(groups); } // PrusaLink specific: Query the server for the list of file groups. - wxArrayString storage; + wxArrayString storage_paths; + wxArrayString storage_names; { wxBusyCursor wait; try { - upload_job.printhost->get_storage(storage); + upload_job.printhost->get_storage(storage_paths, storage_names); } catch (const Slic3r::IOError& ex) { show_error(this, ex.what(), false); return; } } - PrintHostSendDialog dlg(default_output_file, upload_job.printhost->get_post_upload_actions(), groups, storage); + PrintHostSendDialog dlg(default_output_file, upload_job.printhost->get_post_upload_actions(), groups, storage_paths, storage_names); if (dlg.ShowModal() == wxID_OK) { upload_job.upload_data.upload_path = dlg.filename(); upload_job.upload_data.post_action = dlg.post_action(); diff --git a/src/slic3r/GUI/PrintHostDialogs.cpp b/src/slic3r/GUI/PrintHostDialogs.cpp index dab033cfb..982fe99a7 100644 --- a/src/slic3r/GUI/PrintHostDialogs.cpp +++ b/src/slic3r/GUI/PrintHostDialogs.cpp @@ -38,13 +38,14 @@ static const char *CONFIG_KEY_PATH = "printhost_path"; static const char *CONFIG_KEY_GROUP = "printhost_group"; static const char* CONFIG_KEY_STORAGE = "printhost_storage"; -PrintHostSendDialog::PrintHostSendDialog(const fs::path &path, PrintHostPostUploadActions post_actions, const wxArrayString &groups, const wxArrayString& storage) +PrintHostSendDialog::PrintHostSendDialog(const fs::path &path, PrintHostPostUploadActions post_actions, const wxArrayString &groups, const wxArrayString& storage_paths, const wxArrayString& storage_names) : MsgDialog(static_cast(wxGetApp().mainframe), _L("Send G-Code to printer host"), _L("Upload to Printer Host with the following filename:"), 0) // Set style = 0 to avoid default creation of the "OK" button. // All buttons will be added later in this constructor , txt_filename(new wxTextCtrl(this, wxID_ANY)) , combo_groups(!groups.IsEmpty() ? new wxComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, groups, wxCB_READONLY) : nullptr) - , combo_storage(storage.GetCount() > 1 ? new wxComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, storage, wxCB_READONLY) : nullptr) + , combo_storage(storage_names.GetCount() > 1 ? new wxComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, storage_names, wxCB_READONLY) : nullptr) , post_upload_action(PrintHostPostUploadAction::None) + , m_paths(storage_paths) { #ifdef __APPLE__ txt_filename->OSXDisableAllSmartSubstitutions(); @@ -73,15 +74,15 @@ PrintHostSendDialog::PrintHostSendDialog(const fs::path &path, PrintHostPostUplo auto* label_group = new wxStaticText(this, wxID_ANY, _L("Upload to storage:")); content_sizer->Add(label_group); content_sizer->Add(combo_storage, 0, wxBOTTOM, 2 * VERT_SPACING); - combo_storage->SetValue(storage.front()); + combo_storage->SetValue(storage_names.front()); wxString recent_storage = from_u8(app_config->get("recent", CONFIG_KEY_STORAGE)); if (!recent_storage.empty()) combo_storage->SetValue(recent_storage); - } else if (storage.GetCount() == 1){ + } else if (storage_names.GetCount() == 1){ // PrusaLink specific: Show which storage has been detected. - auto* label_group = new wxStaticText(this, wxID_ANY, _L("Upload to storage: ") + storage.front()); + auto* label_group = new wxStaticText(this, wxID_ANY, _L("Upload to storage: ") + storage_names.front()); content_sizer->Add(label_group); - m_preselected_storage = storage.front(); + m_preselected_storage = storage_paths.front(); } @@ -196,7 +197,9 @@ std::string PrintHostSendDialog::storage() const { if (!combo_storage) return GUI::format("%1%", m_preselected_storage); - return boost::nowide::narrow(combo_storage->GetValue()); + if (combo_storage->GetSelection() < 0 || combo_storage->GetSelection() >= m_paths.size()) + return {}; + return boost::nowide::narrow(m_paths[combo_storage->GetSelection()]); } void PrintHostSendDialog::EndModal(int ret) @@ -226,8 +229,6 @@ void PrintHostSendDialog::EndModal(int ret) MsgDialog::EndModal(ret); } - - wxDEFINE_EVENT(EVT_PRINTHOST_PROGRESS, PrintHostQueueDialog::Event); wxDEFINE_EVENT(EVT_PRINTHOST_ERROR, PrintHostQueueDialog::Event); wxDEFINE_EVENT(EVT_PRINTHOST_CANCEL, PrintHostQueueDialog::Event); diff --git a/src/slic3r/GUI/PrintHostDialogs.hpp b/src/slic3r/GUI/PrintHostDialogs.hpp index 80e2a0f48..b3f550405 100644 --- a/src/slic3r/GUI/PrintHostDialogs.hpp +++ b/src/slic3r/GUI/PrintHostDialogs.hpp @@ -26,7 +26,7 @@ namespace GUI { class PrintHostSendDialog : public GUI::MsgDialog { public: - PrintHostSendDialog(const boost::filesystem::path &path, PrintHostPostUploadActions post_actions, const wxArrayString& groups, const wxArrayString& storage); + PrintHostSendDialog(const boost::filesystem::path &path, PrintHostPostUploadActions post_actions, const wxArrayString& groups, const wxArrayString& storage_paths, const wxArrayString& storage_names); boost::filesystem::path filename() const; PrintHostPostUploadAction post_action() const; std::string group() const; @@ -40,6 +40,7 @@ private: PrintHostPostUploadAction post_upload_action; wxString m_valid_suffix; wxString m_preselected_storage; + wxArrayString m_paths; }; diff --git a/src/slic3r/Utils/OctoPrint.cpp b/src/slic3r/Utils/OctoPrint.cpp index f76932014..1889a7d36 100644 --- a/src/slic3r/Utils/OctoPrint.cpp +++ b/src/slic3r/Utils/OctoPrint.cpp @@ -273,7 +273,6 @@ bool OctoPrint::test(wxString& msg) const return res; } - wxString OctoPrint::get_test_ok_msg () const { return _(L("Connection to OctoPrint works correctly.")); @@ -685,7 +684,7 @@ bool PrusaLink::test(wxString& msg) const return res; } -bool PrusaLink::get_storage(wxArrayString& output) const +bool PrusaLink::get_storage(wxArrayString& storage_path, wxArrayString& storage_name) const { const char* name = get_name(); @@ -693,10 +692,11 @@ bool PrusaLink::get_storage(wxArrayString& output) const auto url = make_url("api/v1/storage"); wxString error_msg; - struct StorageInfo{ + struct StorageInfo { + wxString path; wxString name; - bool read_only; - long long free_space; + bool read_only = false; + long long free_space = -1; }; std::vector storage; @@ -731,6 +731,7 @@ bool PrusaLink::get_storage(wxArrayString& output) const } // each storage has own subtree of storage_list for (const auto& section : ptree.front().second) { + const auto name = section.second.get_optional("name"); const auto path = section.second.get_optional("path"); const auto space = section.second.get_optional("free_space"); const auto read_only = section.second.get_optional("read_only"); @@ -738,7 +739,8 @@ bool PrusaLink::get_storage(wxArrayString& output) const const auto available = section.second.get_optional("available"); if (path && (!available || *available)) { StorageInfo si; - si.name = boost::nowide::widen(*path); + si.path = boost::nowide::widen(*path); + si.name = name ? boost::nowide::widen(*name) : wxString(); // If read_only is missing, assume it is NOT read only. // si.read_only = read_only ? *read_only : false; // version without "ro" si.read_only = (read_only ? *read_only : (ro ? *ro : false)); @@ -759,16 +761,17 @@ bool PrusaLink::get_storage(wxArrayString& output) const .perform_sync(); for (const auto& si : storage) { - if (!si.read_only && si.free_space > 0) - output.push_back(si.name); + if (!si.read_only && si.free_space > 0) { + storage_path.push_back(si.path); + storage_name.push_back(si.name); + } } - if (res && output.empty()) - { + if (res && storage_path.empty()) { if (!storage.empty()) { // otherwise error_msg is already filled error_msg = L"\n\n" + _L("Storages found:") + L" \n"; for (const auto& si : storage) { - error_msg += si.name + L" : " + (si.read_only ? _L("read only") : _L("no free space")) + L"\n"; + error_msg += si.path + L" : " + (si.read_only ? _L("read only") : _L("no free space")) + L"\n"; } } std::string message = GUI::format(_L("Upload has failed. There is no suitable storage found at %1%.%2%"), m_host, error_msg); diff --git a/src/slic3r/Utils/OctoPrint.hpp b/src/slic3r/Utils/OctoPrint.hpp index fadb5d924..d11cd9514 100644 --- a/src/slic3r/Utils/OctoPrint.hpp +++ b/src/slic3r/Utils/OctoPrint.hpp @@ -94,7 +94,7 @@ public: virtual PrintHostPostUploadActions get_post_upload_actions() const override { return PrintHostPostUploadAction::StartPrint; } // gets possible storage to be uploaded to. This allows different printer to have different storage. F.e. local vs sdcard vs usb. - bool get_storage(wxArrayString& /* storage */) const override; + bool get_storage(wxArrayString& storage_path, wxArrayString& storage_name) const override; protected: bool test(wxString& curl_msg) const override; bool validate_version_text(const boost::optional& version_text) const override; diff --git a/src/slic3r/Utils/PrintHost.hpp b/src/slic3r/Utils/PrintHost.hpp index c39f86288..becaf138b 100644 --- a/src/slic3r/Utils/PrintHost.hpp +++ b/src/slic3r/Utils/PrintHost.hpp @@ -66,7 +66,7 @@ public: virtual bool get_printers(wxArrayString & /* printers */) const { return false; } // Support for PrusaLink uploading to different storage. Not supported by other print hosts. // Returns false if not supported or fail. - virtual bool get_storage(wxArrayString& /* storage */) const { return false; } + virtual bool get_storage(wxArrayString& /*storage_path*/, wxArrayString& /*storage_name*/) const { return false; } static PrintHost* get_print_host(DynamicPrintConfig *config); From 370073812309a1212c2f8ae5e90dcc79fb98c3eb Mon Sep 17 00:00:00 2001 From: David Kocik Date: Wed, 1 Mar 2023 14:18:52 +0100 Subject: [PATCH 24/34] Accept-Language when getting PrusaLink storage --- src/slic3r/Utils/OctoPrint.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/slic3r/Utils/OctoPrint.cpp b/src/slic3r/Utils/OctoPrint.cpp index 1889a7d36..de3ae943f 100644 --- a/src/slic3r/Utils/OctoPrint.cpp +++ b/src/slic3r/Utils/OctoPrint.cpp @@ -702,8 +702,12 @@ bool PrusaLink::get_storage(wxArrayString& storage_path, wxArrayString& storage_ BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Get storage at: %2%") % name % url; + wxString wlang = GUI::wxGetApp().current_language_code(); + std::string lang = GUI::format(wlang.SubString(0, 1)); + auto http = Http::get(std::move(url)); set_auth(http); + http.header("Accept-Language", lang); http.on_error([&](std::string body, std::string error, unsigned status) { BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error getting storage: %2%, HTTP %3%, body: `%4%`") % name % error % status % body; error_msg = L"\n\n" + boost::nowide::widen(error); From dc7373514d6f694cfeb5820501717e242cbd22e6 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 2 Mar 2023 10:16:09 +0100 Subject: [PATCH 25/34] Fixed localization of the tooltips for settings parameters (follow-up https://github.com/Prusa-Development/PrusaSlicerPrivate/commit/6238595a) --- src/libslic3r/PrintConfig.cpp | 33 +++++---------------------------- src/slic3r/GUI/Field.cpp | 14 +++++--------- src/slic3r/GUI/OptionsGroup.cpp | 19 ++++++++++++++++--- src/slic3r/GUI/OptionsGroup.hpp | 3 +-- 4 files changed, 27 insertions(+), 42 deletions(-) diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 878acc10a..76fddebc4 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -3270,9 +3270,6 @@ void PrintConfigDef::init_sla_support_params(const std::string &prefix) { ConfigOptionDef* def; - constexpr const char * pretext_unavailable = L("Unavailable for this method.\n"); - std::string pretext; - def = this->add(prefix + "support_head_front_diameter", coFloat); def->label = L("Pinhead front diameter"); def->category = L("Supports"); @@ -3322,13 +3319,9 @@ void PrintConfigDef::init_sla_support_params(const std::string &prefix) def->mode = comExpert; def->set_default_value(new ConfigOptionPercent(50)); - pretext = ""; - if (prefix == "branching") - pretext = pretext_unavailable; - def = this->add(prefix + "support_max_bridges_on_pillar", coInt); def->label = L("Max bridges on a pillar"); - def->tooltip = pretext + L( + def->tooltip = L( "Maximum number of bridges that can be placed on a pillar. Bridges " "hold support point pinheads and connect to pillars as small branches."); def->min = 0; @@ -3336,14 +3329,10 @@ void PrintConfigDef::init_sla_support_params(const std::string &prefix) def->mode = comExpert; def->set_default_value(new ConfigOptionInt(prefix == "branching" ? 2 : 3)); - pretext = ""; - if (prefix.empty()) - pretext = pretext_unavailable; - def = this->add(prefix + "support_max_weight_on_model", coFloat); def->label = L("Max weight on model"); def->category = L("Supports"); - def->tooltip = pretext + L( + def->tooltip = L( "Maximum weight of sub-trees that terminate on the model instead of the print bed. The weight is the sum of the lenghts of all " "branches emanating from the endpoint."); def->sidetext = L("mm"); @@ -3351,13 +3340,9 @@ void PrintConfigDef::init_sla_support_params(const std::string &prefix) def->mode = comExpert; def->set_default_value(new ConfigOptionFloat(10.)); - pretext = ""; - if (prefix == "branching") - pretext = pretext_unavailable; - def = this->add(prefix + "support_pillar_connection_mode", coEnum); def->label = L("Pillar connection mode"); - def->tooltip = pretext + L("Controls the bridge type between two neighboring pillars." + def->tooltip = L("Controls the bridge type between two neighboring pillars." " Can be zig-zag, cross (double zig-zag) or dynamic which" " will automatically switch between the first two depending" " on the distance of the two pillars."); @@ -3378,11 +3363,7 @@ void PrintConfigDef::init_sla_support_params(const std::string &prefix) def->label = L("Pillar widening factor"); def->category = L("Supports"); - pretext = ""; - if (prefix.empty()) - pretext = pretext_unavailable; - - def->tooltip = pretext + + def->tooltip = L("Merging bridges or pillars into another pillars can " "increase the radius. Zero means no increase, one means " "full increase. The exact amount of increase is unspecified and can " @@ -3449,14 +3430,10 @@ void PrintConfigDef::init_sla_support_params(const std::string &prefix) def->set_default_value(new ConfigOptionFloat(default_val)); - pretext = ""; - if (prefix == "branching") - pretext = pretext_unavailable; - def = this->add(prefix + "support_max_pillar_link_distance", coFloat); def->label = L("Max pillar linking distance"); def->category = L("Supports"); - def->tooltip = pretext + L("The max distance of two pillars to get linked with each other." + def->tooltip = L("The max distance of two pillars to get linked with each other." " A zero value will prohibit pillar cascading."); def->sidetext = L("mm"); def->min = 0; // 0 means no linking diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index 13a9e6e07..ffd5a6bc3 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -175,24 +175,20 @@ void Field::on_back_to_sys_value() wxString Field::get_tooltip_text(const wxString& default_string) { - wxString tooltip_text(""); - wxString tooltip = _(m_opt.tooltip); - edit_tooltip(tooltip); + if (m_opt.tooltip.empty()) + return ""; std::string opt_id = m_opt_id; - auto hash_pos = opt_id.find("#"); + auto hash_pos = opt_id.find('#'); if (hash_pos != std::string::npos) { opt_id.replace(hash_pos, 1,"["); opt_id += "]"; } - if (tooltip.length() > 0) - tooltip_text = tooltip + "\n" + _(L("default value")) + "\t: " + + return from_u8(m_opt.tooltip) + "\n" + _L("default value") + "\t: " + (boost::iends_with(opt_id, "_gcode") ? "\n" : "") + default_string + (boost::iends_with(opt_id, "_gcode") ? "" : "\n") + - _(L("parameter name")) + "\t: " + opt_id; - - return tooltip_text; + _L("parameter name") + "\t: " + opt_id; } bool Field::is_matched(const std::string& string, const std::string& pattern) diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index 688570f90..e567ac7c6 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -118,6 +118,20 @@ OptionsGroup::OptionsGroup( wxWindow* _parent, const wxString& title, { } +Option::Option(const ConfigOptionDef& _opt, t_config_option_key id) : opt(_opt), opt_id(id) +{ + if (!opt.tooltip.empty()) { + wxString tooltip; + if (opt.opt_key.rfind("branching", 0) == 0) + tooltip = _L("Unavailable for this method.") + "\n"; + tooltip += _(opt.tooltip); + + edit_tooltip(tooltip); + + opt.tooltip = into_u8(tooltip); + } +} + void Line::clear() { if (near_label_widget_win) @@ -517,9 +531,8 @@ void OptionsGroup::clear(bool destroy_custom_ctrl) Line OptionsGroup::create_single_option_line(const Option& option, const std::string& path/* = std::string()*/) const { - wxString tooltip = _(option.opt.tooltip); - edit_tooltip(tooltip); - Line retval{ _(option.opt.label), tooltip }; + Line retval{ _(option.opt.label), from_u8(option.opt.tooltip) }; + retval.label_path = path; retval.append_option(option); return retval; diff --git a/src/slic3r/GUI/OptionsGroup.hpp b/src/slic3r/GUI/OptionsGroup.hpp index 88d0ff8bf..f754505dd 100644 --- a/src/slic3r/GUI/OptionsGroup.hpp +++ b/src/slic3r/GUI/OptionsGroup.hpp @@ -47,8 +47,7 @@ struct Option { return (rhs.opt_id == this->opt_id); } - Option(const ConfigOptionDef& _opt, t_config_option_key id) : - opt(_opt), opt_id(id) {} + Option(const ConfigOptionDef& _opt, t_config_option_key id); }; using t_option = std::unique_ptr