diff --git a/resources/profiles/Anycubic/PHOTON MONO SE_thumbnail.png b/resources/profiles/Anycubic/PHOTON MONO SE_thumbnail.png index 9fa39cb4f1..1815510983 100644 Binary files a/resources/profiles/Anycubic/PHOTON MONO SE_thumbnail.png and b/resources/profiles/Anycubic/PHOTON MONO SE_thumbnail.png differ diff --git a/resources/profiles/Anycubic/PHOTON MONO_thumbnail.png b/resources/profiles/Anycubic/PHOTON MONO_thumbnail.png index 0aaf5c4cd6..1008ecffef 100644 Binary files a/resources/profiles/Anycubic/PHOTON MONO_thumbnail.png and b/resources/profiles/Anycubic/PHOTON MONO_thumbnail.png differ diff --git a/src/libslic3r/Arrange.hpp b/src/libslic3r/Arrange.hpp index 4ed00668c9..874742ecb5 100644 --- a/src/libslic3r/Arrange.hpp +++ b/src/libslic3r/Arrange.hpp @@ -1,9 +1,9 @@ #ifndef ARRANGE_HPP #define ARRANGE_HPP -#include "ExPolygon.hpp" - #include + +#include #include namespace Slic3r { diff --git a/src/libslic3r/PlaceholderParser.cpp b/src/libslic3r/PlaceholderParser.cpp index 348825106e..786f4093ca 100644 --- a/src/libslic3r/PlaceholderParser.cpp +++ b/src/libslic3r/PlaceholderParser.cpp @@ -882,14 +882,20 @@ namespace client } } if (opt == nullptr) - ctx->throw_exception("Variable does not exist", IteratorRange(opt_key.begin(), opt_key.end())); - if (opt->is_scalar()) + ctx->throw_exception("Variable does not exist", opt_key); + if (opt->is_scalar()) { + if (opt->is_nil()) + ctx->throw_exception("Trying to reference an undefined (nil) optional variable", opt_key); output = opt->serialize(); - else { + } else { const ConfigOptionVectorBase *vec = static_cast(opt); if (vec->empty()) ctx->throw_exception("Indexing an empty vector variable", opt_key); - output = vec->vserialize()[(idx >= vec->size()) ? 0 : idx]; + if (idx >= vec->size()) + idx = 0; + if (vec->is_nil(idx)) + ctx->throw_exception("Trying to reference an undefined (nil) element of vector of optional values", opt_key); + output = vec->vserialize()[idx]; } } @@ -917,7 +923,7 @@ namespace client ctx->throw_exception("Trying to index a scalar variable", opt_key); const ConfigOptionVectorBase *vec = static_cast(opt); if (vec->empty()) - ctx->throw_exception("Indexing an empty vector variable", IteratorRange(opt_key.begin(), opt_key.end())); + ctx->throw_exception("Indexing an empty vector variable", opt_key); const ConfigOption *opt_index = ctx->resolve_symbol(std::string(opt_vector_index.begin(), opt_vector_index.end())); if (opt_index == nullptr) ctx->throw_exception("Variable does not exist", opt_key); @@ -926,7 +932,11 @@ namespace client int idx = opt_index->getInt(); if (idx < 0) ctx->throw_exception("Negative vector index", opt_key); - output = vec->vserialize()[(idx >= (int)vec->size()) ? 0 : idx]; + if (idx >= (int)vec->size()) + idx = 0; + if (vec->is_nil(idx)) + ctx->throw_exception("Trying to reference an undefined (nil) element of vector of optional values", opt_key); + output = vec->vserialize()[idx]; } static void resolve_variable( @@ -976,6 +986,9 @@ namespace client assert(opt.opt->is_scalar()); + if (opt.opt->is_nil()) + ctx->throw_exception("Trying to reference an undefined (nil) optional variable", opt.it_range); + switch (opt.opt->type()) { case coFloat: output.set_d(opt.opt->getFloat()); break; case coInt: output.set_i(opt.opt->getInt()); break; @@ -1041,6 +1054,8 @@ namespace client if (vec->empty()) ctx->throw_exception("Indexing an empty vector variable", opt.it_range); size_t idx = (opt.index < 0) ? 0 : (opt.index >= int(vec->size())) ? 0 : size_t(opt.index); + if (vec->is_nil(idx)) + ctx->throw_exception("Trying to reference an undefined (nil) element of vector of optional values", opt.it_range); switch (opt.opt->type()) { case coFloats: output.set_d(static_cast(opt.opt)->values[idx]); break; case coInts: output.set_i(static_cast(opt.opt)->values[idx]); break; @@ -1434,6 +1449,8 @@ namespace client assert(lhs.opt->is_vector()); if (rhs.has_index() || ! rhs.opt->is_vector()) ctx->throw_exception("Cannot assign scalar to a vector", lhs.it_range); + if (rhs.opt->is_nil()) + ctx->throw_exception("Some elements of the right hand side vector variable of optional values are undefined (nil)", rhs.it_range); if (lhs.opt->type() != rhs.opt->type()) { // Vector types are not compatible. switch (lhs.opt->type()) { @@ -1470,6 +1487,8 @@ namespace client if (rhs.has_index() || ! rhs.opt->is_vector()) // Stop parsing, let the other rules resolve this case. return false; + if (rhs.opt->is_nil()) + ctx->throw_exception("Some elements of the right hand side vector variable of optional values are undefined (nil)", rhs.it_range); // Clone the vector variable. std::unique_ptr opt_new; if (one_of(rhs.opt->type(), { coFloats, coInts, coStrings, coBools })) diff --git a/src/libslic3r/Support/TreeSupport.cpp b/src/libslic3r/Support/TreeSupport.cpp index 72d1bda030..5bfbe55265 100644 --- a/src/libslic3r/Support/TreeSupport.cpp +++ b/src/libslic3r/Support/TreeSupport.cpp @@ -2970,7 +2970,7 @@ static void create_nodes_from_area( assert(radius_increase >= 0); double shift = (elem.state.result_on_layer - parent.state.result_on_layer).cast().norm(); //FIXME this assert fails a lot. Is it correct? - assert(shift < radius_increase + 2. * config.maximum_move_distance_slow); +// assert(shift < radius_increase + 2. * config.maximum_move_distance_slow); } } } @@ -2995,7 +2995,7 @@ static void create_nodes_from_area( assert(radius_increase >= 0); double shift = (elem.state.result_on_layer - parent.state.result_on_layer).cast().norm(); //FIXME this assert fails a lot. Is it correct? - assert(shift < radius_increase + 2. * config.maximum_move_distance_slow); +// assert(shift < radius_increase + 2. * config.maximum_move_distance_slow); } } } diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 4e58e68ec2..0585ce58c8 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -2354,13 +2354,23 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool size_t last = path_id; // check adjacent paths - while (first > 0 && path.sub_paths.front().first.position.isApprox(buffer.paths[first - 1].sub_paths.back().last.position)) { + while (first > 0) { + const Path& ref_path = buffer.paths[first - 1]; + if (!path.sub_paths.front().first.position.isApprox(ref_path.sub_paths.back().last.position) || + path.role != ref_path.role) + break; + + path.sub_paths.front().first = ref_path.sub_paths.front().first; --first; - path.sub_paths.front().first = buffer.paths[first].sub_paths.front().first; } - while (last < buffer.paths.size() - 1 && path.sub_paths.back().last.position.isApprox(buffer.paths[last + 1].sub_paths.front().first.position)) { + while (last < buffer.paths.size() - 1) { + const Path& ref_path = buffer.paths[last + 1]; + if (!path.sub_paths.back().last.position.isApprox(ref_path.sub_paths.front().first.position) || + path.role != ref_path.role) + break; + + path.sub_paths.back().last = ref_path.sub_paths.back().last; ++last; - path.sub_paths.back().last = buffer.paths[last].sub_paths.back().last; } const size_t min_s_id = m_layers.get_range_at(min_id).first; diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 88e8f86913..65be4ba91e 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -955,7 +955,7 @@ void ObjectList::list_manipulation(const wxPoint& mouse_pos, bool evt_context_me if (!item) { if (col == nullptr) { - if (wxOSX && !multiple_selection()) + if (wxOSX) UnselectAll(); else if (!evt_context_menu) // Case, when last item was deleted and under GTK was called wxEVT_DATAVIEW_SELECTION_CHANGED, @@ -972,11 +972,17 @@ void ObjectList::list_manipulation(const wxPoint& mouse_pos, bool evt_context_me if (wxOSX && item && col) { wxDataViewItemArray sels; GetSelections(sels); - UnselectAll(); - if (sels.Count() > 1) - SetSelections(sels); - else + bool is_selection_changed = true; + for (const auto& sel_item : sels) + if (sel_item == item) { + // item is one oth the already selected items, so resection is no needed + is_selection_changed = false; + break; + } + if (is_selection_changed) { + UnselectAll(); Select(item); + } } if (col != nullptr) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp index 556d5b61e3..d3538a7c06 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp @@ -67,23 +67,10 @@ bool GLGizmoMove3D::on_is_activable() const void GLGizmoMove3D::on_start_dragging() { assert(m_hover_id != -1); - m_displacement = Vec3d::Zero(); - const Selection& selection = m_parent.get_selection(); - const ECoordinatesType coordinates_type = wxGetApp().obj_manipul()->get_coordinates_type(); - if (coordinates_type == ECoordinatesType::World) - m_starting_drag_position = m_center + m_grabbers[m_hover_id].center; - else if (coordinates_type == ECoordinatesType::Local && selection.is_single_volume_or_modifier()) { - const GLVolume& v = *selection.get_first_volume(); - m_starting_drag_position = m_center + v.get_instance_transformation().get_rotation_matrix() * v.get_volume_transformation().get_rotation_matrix() * m_grabbers[m_hover_id].center; - } - else { - const GLVolume& v = *selection.get_first_volume(); - m_starting_drag_position = m_center + v.get_instance_transformation().get_rotation_matrix() * m_grabbers[m_hover_id].center; - } + m_starting_drag_position = m_grabbers[m_hover_id].matrix * m_grabbers[m_hover_id].center; m_starting_box_center = m_center; - m_starting_box_bottom_center = m_center; - m_starting_box_bottom_center.z() = m_bounding_box.min.z(); + m_starting_box_bottom_center = Vec3d(m_center.x(), m_center.y(), m_bounding_box.min.z()); } void GLGizmoMove3D::on_stop_dragging() @@ -122,7 +109,8 @@ void GLGizmoMove3D::on_render() const auto& [box, box_trafo] = selection.get_bounding_box_in_current_reference_system(); m_bounding_box = box; m_center = box_trafo.translation(); - const Transform3d base_matrix = local_transform(m_parent.get_selection()); + const Transform3d base_matrix = box_trafo; + for (int i = 0; i < 3; ++i) { m_grabbers[i].matrix = base_matrix; } @@ -230,10 +218,12 @@ void GLGizmoMove3D::on_render() if (shader != nullptr) { shader->start_using(); shader->set_uniform("emission_factor", 0.1f); + glsafe(::glDisable(GL_CULL_FACE)); // draw grabber const Vec3d box_size = m_bounding_box.size(); const float mean_size = (float)((box_size.x() + box_size.y() + box_size.z()) / 3.0); m_grabbers[m_hover_id].render(true, mean_size); + glsafe(::glEnable(GL_CULL_FACE)); shader->stop_using(); } } diff --git a/src/slic3r/GUI/Jobs/ArrangeJob.hpp b/src/slic3r/GUI/Jobs/ArrangeJob.hpp index a422d44070..6ff25923e2 100644 --- a/src/slic3r/GUI/Jobs/ArrangeJob.hpp +++ b/src/slic3r/GUI/Jobs/ArrangeJob.hpp @@ -86,7 +86,7 @@ arrangement::ArrangePolygon get_arrange_poly(T obj, const Plater *plater) using ArrangePolygon = arrangement::ArrangePolygon; ArrangePolygon ap = obj.get_arrange_polygon(); - ap.bed_idx = ap.translation.x() / bed_stride(plater); + ap.bed_idx = get_extents(ap.transformed_poly()).min.x() / bed_stride(plater); ap.setter = [obj, plater](const ArrangePolygon &p) { if (p.is_arranged()) { Vec2d t = p.translation.cast(); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 2d473646cf..2e22dc0de0 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -6057,36 +6057,36 @@ void Plater::remove_selected() p->view3D->delete_selected(); } -void Plater::increase_instances(size_t num, int obj_idx, std::optional selection_map) +void Plater::increase_instances(size_t num, int obj_idx, int inst_idx) { if (! can_increase_instances()) { return; } Plater::TakeSnapshot snapshot(this, _L("Increase Instances")); - if (obj_idx < 0) - obj_idx = p->get_selected_object_idx(); - if (obj_idx < 0) { - if (const auto obj_idxs = get_selection().get_object_idxs(); !obj_idxs.empty()) { - // we need a copy made here because the selection changes at every call of increase_instances() - const Selection::ObjectIdxsToInstanceIdxsMap content = selection_map.has_value() ? *selection_map : p->get_selection().get_content(); - for (const size_t obj_id : obj_idxs) { - increase_instances(1, int(obj_id), content); + obj_idx = p->get_selected_object_idx(); + if (obj_idx < 0) { + // It's a case of increasing per 1 instance, when multiple objects are selected + if (const auto obj_idxs = get_selection().get_object_idxs(); !obj_idxs.empty()) { + // we need a copy made here because the selection changes at every call of increase_instances() + const Selection::ObjectIdxsToInstanceIdxsMap content = p->get_selection().get_content(); + for (const size_t& obj_id : obj_idxs) { + if (auto obj_it = content.find(int(obj_id)); obj_it != content.end()) + increase_instances(1, int(obj_id), *obj_it->second.rbegin()); + } } + return; } - return; } + assert(obj_idx >= 0); ModelObject* model_object = p->model.objects[obj_idx]; - int inst_idx = -1; - if (selection_map.has_value()) { - auto obj_it = selection_map->find(obj_idx); - if (obj_it != selection_map->end() && obj_it->second.size() == 1) - inst_idx = *obj_it->second.begin(); - } - else - inst_idx = p->get_selected_instance_idx(); + if (inst_idx < 0 && get_selected_object_idx() >= 0) { + inst_idx = get_selection().get_instance_idx(); + if (0 > inst_idx || inst_idx >= int(model_object->instances.size())) + inst_idx = -1; + } ModelInstance* model_instance = (inst_idx >= 0) ? model_object->instances[inst_idx] : model_object->instances.back(); bool was_one_instance = model_object->instances.size()==1; @@ -6098,7 +6098,6 @@ void Plater::increase_instances(size_t num, int obj_idx, std::optionalget_transformation(); trafo.set_offset(offset_vec); model_object->add_instance(trafo); -// p->print.get_object(obj_idx)->add_copy(Slic3r::to_2d(offset_vec)); } if (p->get_config_bool("autocenter")) @@ -6182,11 +6181,16 @@ void Plater::set_number_of_copies() return; TakeSnapshot snapshot(this, wxString::Format(_L("Set numbers of copies to %d"), num)); - for (const auto obj_idx : obj_idxs) { + // we need a copy made here because the selection changes at every call of increase_instances() + Selection::ObjectIdxsToInstanceIdxsMap content = p->get_selection().get_content(); + + for (const auto& obj_idx : obj_idxs) { ModelObject* model_object = p->model.objects[obj_idx]; const int diff = num - (int)model_object->instances.size(); - if (diff > 0) - increase_instances(diff, int(obj_idx)); + if (diff > 0) { + if (auto obj_it = content.find(int(obj_idx)); obj_it != content.end()) + increase_instances(diff, int(obj_idx), *obj_it->second.rbegin()); + } else if (diff < 0) decrease_instances(-diff, int(obj_idx)); } diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 0359328699..19152a7a56 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -250,7 +250,7 @@ public: void reset_with_confirm(); bool delete_object_from_model(size_t obj_idx); void remove_selected(); - void increase_instances(size_t num = 1, int obj_idx = -1, std::optional selection_map = std::nullopt); + void increase_instances(size_t num = 1, int obj_idx = -1, int inst_idx = -1); void decrease_instances(size_t num = 1, int obj_idx = -1); void set_number_of_copies(); void fill_bed_with_instances(); diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index cbd61a1dde..e9d131c433 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -1593,6 +1593,7 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field) shader->start_using(); glsafe(::glEnable(GL_DEPTH_TEST)); + glsafe(::glDisable(GL_CULL_FACE)); const Transform3d base_matrix = Geometry::translation_transform(get_bounding_box().center()); Transform3d orient_matrix = Transform3d::Identity(); @@ -1603,15 +1604,15 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field) if (!boost::starts_with(sidebar_field, "layer")) { shader->set_uniform("emission_factor", 0.05f); if (is_single_full_instance() && !wxGetApp().obj_manipul()->is_world_coordinates()) { - orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_rotation_matrix(); - axes_center = (*m_volumes)[*m_list.begin()]->get_instance_offset(); + orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_rotation_matrix(); + axes_center = (*m_volumes)[*m_list.begin()]->get_instance_offset(); } else if (is_single_volume_or_modifier()) { if (!wxGetApp().obj_manipul()->is_world_coordinates()) { if (wxGetApp().obj_manipul()->is_local_coordinates()) { const GLVolume* v = (*m_volumes)[*m_list.begin()]; - orient_matrix = v->get_instance_transformation().get_rotation_matrix() * v->get_volume_transformation().get_rotation_matrix(); - axes_center = (*m_volumes)[*m_list.begin()]->world_matrix().translation(); + orient_matrix = get_bounding_box_in_current_reference_system().second; + orient_matrix.translation() = Vec3d::Zero(); } else { orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_rotation_matrix(); @@ -1645,6 +1646,7 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field) m_axes.render(Geometry::translation_transform(axes_center) * orient_matrix, 0.25f); } + glsafe(::glEnable(GL_CULL_FACE)); shader->stop_using(); }