diff options
Diffstat (limited to 'src/slic3r/GUI/Selection.cpp')
-rw-r--r-- | src/slic3r/GUI/Selection.cpp | 267 |
1 files changed, 135 insertions, 132 deletions
diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index 146111f49..cdd3ebe85 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -1,20 +1,24 @@ #include "libslic3r/libslic3r.h" #include "Selection.hpp" +#include "3DScene.hpp" #include "GLCanvas3D.hpp" #include "GUI_App.hpp" #include "GUI.hpp" #include "GUI_ObjectManipulation.hpp" #include "GUI_ObjectList.hpp" #include "Gizmos/GLGizmoBase.hpp" -#include "3DScene.hpp" #include "Camera.hpp" +#include "Plater.hpp" + +#include "libslic3r/Model.hpp" #include <GL/glew.h> #include <boost/algorithm/string/predicate.hpp> +#include <boost/log/trivial.hpp> -static const float UNIFORM_SCALE_COLOR[3] = { 1.0f, 0.38f, 0.0f }; +static const float UNIFORM_SCALE_COLOR[4] = { 0.923f, 0.504f, 0.264f, 1.0f }; namespace Slic3r { namespace GUI { @@ -54,7 +58,7 @@ bool Selection::Clipboard::is_sla_compliant() const if (m_mode == Selection::Volume) return false; - for (const ModelObject* o : m_model.objects) + for (const ModelObject* o : m_model->objects) { if (o->is_multiparts()) return false; @@ -69,6 +73,35 @@ bool Selection::Clipboard::is_sla_compliant() const return true; } +Selection::Clipboard::Clipboard() +{ + m_model.reset(new Model); +} + +void Selection::Clipboard::reset() { + m_model->clear_objects(); +} + +bool Selection::Clipboard::is_empty() const +{ + return m_model->objects.empty(); +} + +ModelObject* Selection::Clipboard::add_object() +{ + return m_model->add_object(); +} + +ModelObject* Selection::Clipboard::get_object(unsigned int id) +{ + return (id < (unsigned int)m_model->objects.size()) ? m_model->objects[id] : nullptr; +} + +const ModelObjectPtrs& Selection::Clipboard::get_objects() const +{ + return m_model->objects; +} + Selection::Selection() : m_volumes(nullptr) , m_model(nullptr) @@ -76,7 +109,6 @@ Selection::Selection() , m_mode(Instance) , m_type(Empty) , m_valid(false) - , m_curved_arrow(16) , m_scale_factor(1.0f) { this->set_bounding_boxes_dirty(); @@ -104,15 +136,8 @@ void Selection::set_volumes(GLVolumePtrs* volumes) // Init shall be called from the OpenGL render function, so that the OpenGL context is initialized! bool Selection::init() { - if (!m_arrow.init()) - return false; - - m_arrow.set_scale(5.0 * Vec3d::Ones()); - - if (!m_curved_arrow.init()) - return false; - - m_curved_arrow.set_scale(5.0 * Vec3d::Ones()); + m_arrow.init_from(straight_arrow(10.0f, 5.0f, 5.0f, 10.0f, 1.0f)); + m_curved_arrow.init_from(circular_arrow(16, 10.0f, 5.0f, 10.0f, 5.0f, 1.0f)); return true; } @@ -440,6 +465,10 @@ void Selection::clear() update_type(); this->set_bounding_boxes_dirty(); + // this happens while the application is closing + if (wxGetApp().obj_manipul() == nullptr) + return; + // resets the cache in the sidebar wxGetApp().obj_manipul()->reset_cache(); @@ -805,30 +834,21 @@ void Selection::flattening_rotate(const Vec3d& normal) // We get the normal in untransformed coordinates. We must transform it using the instance matrix, find out // how to rotate the instance so it faces downwards and do the rotation. All that for all selected instances. // The function assumes that is_from_single_object() holds. + assert(Slic3r::is_approx(normal.norm(), 1.)); if (!m_valid) return; for (unsigned int i : m_list) { - Transform3d wst = m_cache.volumes_data[i].get_instance_scale_matrix(); - Vec3d scaling_factor = Vec3d(1. / wst(0, 0), 1. / wst(1, 1), 1. / wst(2, 2)); - - Transform3d wmt = m_cache.volumes_data[i].get_instance_mirror_matrix(); - Vec3d mirror(wmt(0, 0), wmt(1, 1), wmt(2, 2)); - - Vec3d rotation = Geometry::extract_euler_angles(m_cache.volumes_data[i].get_instance_rotation_matrix()); - Vec3d transformed_normal = Geometry::assemble_transform(Vec3d::Zero(), rotation, scaling_factor, mirror) * normal; - transformed_normal.normalize(); - - Vec3d axis = transformed_normal(2) > 0.999f ? Vec3d(1., 0., 0.) : Vec3d(transformed_normal.cross(Vec3d(0., 0., -1.))); - axis.normalize(); - - Transform3d extra_rotation = Transform3d::Identity(); - extra_rotation.rotate(Eigen::AngleAxisd(acos(-transformed_normal(2)), axis)); - - Vec3d new_rotation = Geometry::extract_euler_angles(extra_rotation * m_cache.volumes_data[i].get_instance_rotation_matrix()); - (*m_volumes)[i]->set_instance_rotation(new_rotation); + // Normal transformed from the object coordinate space to the world coordinate space. + const auto &voldata = m_cache.volumes_data[i]; + Vec3d tnormal = (Geometry::assemble_transform( + Vec3d::Zero(), voldata.get_instance_rotation(), + voldata.get_instance_scaling_factor().cwiseInverse(), voldata.get_instance_mirror()) * normal).normalized(); + // Additional rotation to align tnormal with the down vector in the world coordinate space. + auto extra_rotation = Eigen::Quaterniond().setFromTwoVectors(tnormal, - Vec3d::UnitZ()); + (*m_volumes)[i]->set_instance_rotation(Geometry::extract_euler_angles(extra_rotation.toRotationMatrix() * m_cache.volumes_data[i].get_instance_rotation_matrix())); } #if !DISABLE_INSTANCES_SYNCH @@ -1223,40 +1243,40 @@ void Selection::render_center(bool gizmo_is_dragging) const } #endif // ENABLE_RENDER_SELECTION_CENTER -void Selection::render_sidebar_hints(const std::string& sidebar_field, const Shader& shader) const +void Selection::render_sidebar_hints(const std::string& sidebar_field) const { if (sidebar_field.empty()) return; + GLShaderProgram* shader = nullptr; + if (!boost::starts_with(sidebar_field, "layer")) { - shader.start_using(); + shader = wxGetApp().get_shader("gouraud_light"); + if (shader == nullptr) + return; + + shader->start_using(); glsafe(::glClear(GL_DEPTH_BUFFER_BIT)); - glsafe(::glEnable(GL_LIGHTING)); } glsafe(::glEnable(GL_DEPTH_TEST)); glsafe(::glPushMatrix()); - if (!boost::starts_with(sidebar_field, "layer")) - { + if (!boost::starts_with(sidebar_field, "layer")) { const Vec3d& center = get_bounding_box().center(); - if (is_single_full_instance() && !wxGetApp().obj_manipul()->get_world_coordinates()) - { + if (is_single_full_instance() && !wxGetApp().obj_manipul()->get_world_coordinates()) { glsafe(::glTranslated(center(0), center(1), center(2))); - if (!boost::starts_with(sidebar_field, "position")) - { + if (!boost::starts_with(sidebar_field, "position")) { Transform3d orient_matrix = Transform3d::Identity(); if (boost::starts_with(sidebar_field, "scale")) orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true); - else if (boost::starts_with(sidebar_field, "rotation")) - { + else if (boost::starts_with(sidebar_field, "rotation")) { if (boost::ends_with(sidebar_field, "x")) orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true); - else if (boost::ends_with(sidebar_field, "y")) - { + else if (boost::ends_with(sidebar_field, "y")) { const Vec3d& rotation = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_rotation(); if (rotation(0) == 0.0) orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true); @@ -1267,21 +1287,16 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field, const Sha glsafe(::glMultMatrixd(orient_matrix.data())); } - } - else if (is_single_volume() || is_single_modifier()) - { + } else if (is_single_volume() || is_single_modifier()) { glsafe(::glTranslated(center(0), center(1), center(2))); Transform3d orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true); if (!boost::starts_with(sidebar_field, "position")) orient_matrix = orient_matrix * (*m_volumes)[*m_list.begin()]->get_volume_transformation().get_matrix(true, false, true, true); glsafe(::glMultMatrixd(orient_matrix.data())); - } - else - { + } else { glsafe(::glTranslated(center(0), center(1), center(2))); - if (requires_local_axes()) - { + if (requires_local_axes()) { Transform3d orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true); glsafe(::glMultMatrixd(orient_matrix.data())); } @@ -1292,20 +1307,15 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field, const Sha render_sidebar_position_hints(sidebar_field); else if (boost::starts_with(sidebar_field, "rotation")) render_sidebar_rotation_hints(sidebar_field); - else if (boost::starts_with(sidebar_field, "scale")) + else if (boost::starts_with(sidebar_field, "scale") || boost::starts_with(sidebar_field, "size")) render_sidebar_scale_hints(sidebar_field); - else if (boost::starts_with(sidebar_field, "size")) - render_sidebar_size_hints(sidebar_field); else if (boost::starts_with(sidebar_field, "layer")) render_sidebar_layers_hints(sidebar_field); glsafe(::glPopMatrix()); if (!boost::starts_with(sidebar_field, "layer")) - { - glsafe(::glDisable(GL_LIGHTING)); - shader.stop_using(); - } + shader->stop_using(); } bool Selection::requires_local_axes() const @@ -1326,12 +1336,12 @@ void Selection::copy_to_clipboard() ModelObject* dst_object = m_clipboard.add_object(); dst_object->name = src_object->name; dst_object->input_file = src_object->input_file; - static_cast<DynamicPrintConfig&>(dst_object->config) = static_cast<const DynamicPrintConfig&>(src_object->config); + dst_object->config.assign_config(src_object->config); dst_object->sla_support_points = src_object->sla_support_points; dst_object->sla_points_status = src_object->sla_points_status; dst_object->sla_drain_holes = src_object->sla_drain_holes; dst_object->layer_config_ranges = src_object->layer_config_ranges; // #ys_FIXME_experiment - dst_object->layer_height_profile = src_object->layer_height_profile; + dst_object->layer_height_profile.assign(src_object->layer_height_profile); dst_object->origin_translation = src_object->origin_translation; for (int i : object.second) @@ -1557,20 +1567,21 @@ void Selection::update_type() } else { + unsigned int sla_volumes_count = 0; + // Note: sla_volumes_count is a count of the selected sla_volumes per object instead of per instance, like a model_volumes_count is + for (unsigned int i : m_list) { + if ((*m_volumes)[i]->volume_idx() < 0) + ++sla_volumes_count; + } + if (m_cache.content.size() == 1) // single object { const ModelObject* model_object = m_model->objects[m_cache.content.begin()->first]; unsigned int model_volumes_count = (unsigned int)model_object->volumes.size(); - unsigned int sla_volumes_count = 0; - for (unsigned int i : m_list) - { - if ((*m_volumes)[i]->volume_idx() < 0) - ++sla_volumes_count; - } - unsigned int volumes_count = model_volumes_count + sla_volumes_count; + unsigned int instances_count = (unsigned int)model_object->instances.size(); unsigned int selected_instances_count = (unsigned int)m_cache.content.begin()->second.size(); - if (volumes_count * instances_count == (unsigned int)m_list.size()) + if (model_volumes_count * instances_count + sla_volumes_count == (unsigned int)m_list.size()) { m_type = SingleFullObject; // ensures the correct mode is selected @@ -1578,7 +1589,7 @@ void Selection::update_type() } else if (selected_instances_count == 1) { - if (volumes_count == (unsigned int)m_list.size()) + if (model_volumes_count + sla_volumes_count == (unsigned int)m_list.size()) { m_type = SingleFullInstance; // ensures the correct mode is selected @@ -1601,7 +1612,7 @@ void Selection::update_type() requires_disable = true; } } - else if ((selected_instances_count > 1) && (selected_instances_count * volumes_count == (unsigned int)m_list.size())) + else if ((selected_instances_count > 1) && (selected_instances_count * model_volumes_count + sla_volumes_count == (unsigned int)m_list.size())) { m_type = MultipleFullInstance; // ensures the correct mode is selected @@ -1618,7 +1629,7 @@ void Selection::update_type() unsigned int instances_count = (unsigned int)model_object->instances.size(); sels_cntr += volumes_count * instances_count; } - if (sels_cntr == (unsigned int)m_list.size()) + if (sels_cntr + sla_volumes_count == (unsigned int)m_list.size()) { m_type = MultipleFullObject; // ensures the correct mode is selected @@ -1907,57 +1918,85 @@ void Selection::render_bounding_box(const BoundingBoxf3& box, float* color) cons void Selection::render_sidebar_position_hints(const std::string& sidebar_field) const { - if (boost::ends_with(sidebar_field, "x")) - { + auto set_color = [](Axis axis) { + GLShaderProgram* shader = wxGetApp().get_current_shader(); + if (shader != nullptr) + shader->set_uniform("uniform_color", AXES_COLOR[axis], 4); + }; + + if (boost::ends_with(sidebar_field, "x")) { + set_color(X); glsafe(::glRotated(-90.0, 0.0, 0.0, 1.0)); - render_sidebar_position_hint(X); - } - else if (boost::ends_with(sidebar_field, "y")) - render_sidebar_position_hint(Y); - else if (boost::ends_with(sidebar_field, "z")) - { + m_arrow.render(); + } else if (boost::ends_with(sidebar_field, "y")) { + set_color(Y); + m_arrow.render(); + } else if (boost::ends_with(sidebar_field, "z")) { + set_color(Z); glsafe(::glRotated(90.0, 1.0, 0.0, 0.0)); - render_sidebar_position_hint(Z); + m_arrow.render(); } } void Selection::render_sidebar_rotation_hints(const std::string& sidebar_field) const { - if (boost::ends_with(sidebar_field, "x")) - { + auto set_color = [](Axis axis) { + GLShaderProgram* shader = wxGetApp().get_current_shader(); + if (shader != nullptr) + shader->set_uniform("uniform_color", AXES_COLOR[axis], 4); + }; + + auto render_sidebar_rotation_hint = [this]() { + m_curved_arrow.render(); + glsafe(::glRotated(180.0, 0.0, 0.0, 1.0)); + m_curved_arrow.render(); + }; + + if (boost::ends_with(sidebar_field, "x")) { + set_color(X); glsafe(::glRotated(90.0, 0.0, 1.0, 0.0)); - render_sidebar_rotation_hint(X); - } - else if (boost::ends_with(sidebar_field, "y")) - { + render_sidebar_rotation_hint(); + } else if (boost::ends_with(sidebar_field, "y")) { + set_color(Y); glsafe(::glRotated(-90.0, 1.0, 0.0, 0.0)); - render_sidebar_rotation_hint(Y); + render_sidebar_rotation_hint(); + } else if (boost::ends_with(sidebar_field, "z")) { + set_color(Z); + render_sidebar_rotation_hint(); } - else if (boost::ends_with(sidebar_field, "z")) - render_sidebar_rotation_hint(Z); } void Selection::render_sidebar_scale_hints(const std::string& sidebar_field) const { bool uniform_scale = requires_uniform_scale() || wxGetApp().obj_manipul()->get_uniform_scaling(); - if (boost::ends_with(sidebar_field, "x") || uniform_scale) - { + auto render_sidebar_scale_hint = [this, uniform_scale](Axis axis) { + GLShaderProgram* shader = wxGetApp().get_current_shader(); + if (shader != nullptr) + shader->set_uniform("uniform_color", uniform_scale ? UNIFORM_SCALE_COLOR : AXES_COLOR[axis], 4); + + glsafe(::glTranslated(0.0, 5.0, 0.0)); + m_arrow.render(); + + glsafe(::glTranslated(0.0, -10.0, 0.0)); + glsafe(::glRotated(180.0, 0.0, 0.0, 1.0)); + m_arrow.render(); + }; + + if (boost::ends_with(sidebar_field, "x") || uniform_scale) { glsafe(::glPushMatrix()); glsafe(::glRotated(-90.0, 0.0, 0.0, 1.0)); render_sidebar_scale_hint(X); glsafe(::glPopMatrix()); } - if (boost::ends_with(sidebar_field, "y") || uniform_scale) - { + if (boost::ends_with(sidebar_field, "y") || uniform_scale) { glsafe(::glPushMatrix()); render_sidebar_scale_hint(Y); glsafe(::glPopMatrix()); } - if (boost::ends_with(sidebar_field, "z") || uniform_scale) - { + if (boost::ends_with(sidebar_field, "z") || uniform_scale) { glsafe(::glPushMatrix()); glsafe(::glRotated(90.0, 1.0, 0.0, 0.0)); render_sidebar_scale_hint(Z); @@ -1965,11 +2004,6 @@ void Selection::render_sidebar_scale_hints(const std::string& sidebar_field) con } } -void Selection::render_sidebar_size_hints(const std::string& sidebar_field) const -{ - render_sidebar_scale_hints(sidebar_field); -} - void Selection::render_sidebar_layers_hints(const std::string& sidebar_field) const { static const double Margin = 10.0; @@ -2042,37 +2076,6 @@ void Selection::render_sidebar_layers_hints(const std::string& sidebar_field) co glsafe(::glDisable(GL_BLEND)); } -void Selection::render_sidebar_position_hint(Axis axis) const -{ - m_arrow.set_color(AXES_COLOR[axis], 3); - m_arrow.render(); -} - -void Selection::render_sidebar_rotation_hint(Axis axis) const -{ - m_curved_arrow.set_color(AXES_COLOR[axis], 3); - m_curved_arrow.render(); - - glsafe(::glRotated(180.0, 0.0, 0.0, 1.0)); - m_curved_arrow.render(); -} - -void Selection::render_sidebar_scale_hint(Axis axis) const -{ - m_arrow.set_color(((requires_uniform_scale() || wxGetApp().obj_manipul()->get_uniform_scaling()) ? UNIFORM_SCALE_COLOR : AXES_COLOR[axis]), 3); - - glsafe(::glTranslated(0.0, 5.0, 0.0)); - m_arrow.render(); - - glsafe(::glTranslated(0.0, -10.0, 0.0)); - glsafe(::glRotated(180.0, 0.0, 0.0, 1.0)); - m_arrow.render(); -} - -void Selection::render_sidebar_size_hint(Axis axis, double length) const -{ -} - #ifndef NDEBUG static bool is_rotation_xy_synchronized(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to) { |