diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 18cb49b8e..10f520ffd 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -452,6 +452,21 @@ ModelObject* Model::add_object(const ModelObject &other) return new_object; } +void Model::set_assembly_pos(ModelObject *model_object) +{ + if (!model_object) {return;} + auto cur_assemble_scene_box = bounding_box_in_assembly_view(); + if (cur_assemble_scene_box.defined) { + auto offset = cur_assemble_scene_box.center(); + auto mo_box = model_object->bounding_box_in_assembly_view(); + offset[0] += ((cur_assemble_scene_box.size()[0] / 2.0f + mo_box.size()[0] / 2.0f) * 1.2); + offset[2] = cur_assemble_scene_box.min[2] + mo_box.size()[2]; + model_object->instances[0]->set_assemble_offset(offset); + offset[1] += cur_assemble_scene_box.center().y() - model_object->bounding_box_in_assembly_view().center().y(); + model_object->instances[0]->set_assemble_offset(offset); + } +} + void Model::delete_object(size_t idx) { ModelObjectPtrs::iterator i = this->objects.begin() + idx; @@ -603,6 +618,13 @@ BoundingBoxf3 Model::bounding_box() const return bb; } +BoundingBoxf3 Model::bounding_box_in_assembly_view() const { + BoundingBoxf3 bb; + for (ModelObject *o : this->objects) + bb.merge(o->bounding_box_in_assembly_view()); + return bb; +} + unsigned int Model::update_print_volume_state(const BuildVolume &build_volume) { unsigned int num_printable = 0; @@ -1353,6 +1375,15 @@ const BoundingBoxf3& ModelObject::bounding_box() const return m_bounding_box; } +const BoundingBoxf3 &ModelObject::bounding_box_in_assembly_view() const +{ + m_bounding_box_in_assembly_view.reset(); + BoundingBoxf3 raw_bbox = this->raw_mesh_bounding_box(); + for (const ModelInstance *i : this->instances) + m_bounding_box_in_assembly_view.merge(i->transform_bounding_box_in_assembly_view(raw_bbox)); + return m_bounding_box_in_assembly_view; +} + // A mesh containing all transformed instances of this object. TriangleMesh ModelObject::mesh() const { @@ -3337,6 +3368,10 @@ BoundingBoxf3 ModelInstance::transform_bounding_box(const BoundingBoxf3 &bbox, b return bbox.transformed(get_matrix(dont_translate)); } +BoundingBoxf3 ModelInstance::transform_bounding_box_in_assembly_view(const BoundingBoxf3 &bbox, bool dont_translate) const { + return bbox.transformed(get_assemble_transformation().get_matrix()); +} + Vec3d ModelInstance::transform_vector(const Vec3d& v, bool dont_translate) const { return get_matrix(dont_translate) * v; diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index c24b051ef..daf3699d5 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -427,6 +427,7 @@ public: // This bounding box is approximate and not snug. // This bounding box is being cached. const BoundingBoxf3& bounding_box() const; + const BoundingBoxf3& bounding_box_in_assembly_view() const; void invalidate_bounding_box() { m_bounding_box_valid = false; m_raw_bounding_box_valid = false; m_raw_mesh_bounding_box_valid = false; } // A mesh containing all transformed instances of this object. @@ -647,6 +648,7 @@ private: // Bounding box, cached. mutable BoundingBoxf3 m_bounding_box; + mutable BoundingBoxf3 m_bounding_box_in_assembly_view; mutable bool m_bounding_box_valid; mutable BoundingBoxf3 m_raw_bounding_box; mutable bool m_raw_bounding_box_valid; @@ -1278,7 +1280,7 @@ public: m_assemble_transformation.set_from_transform(transform); } const Vec3d& get_assemble_offset() {return m_assemble_transformation.get_offset(); } - void set_assemble_offset(const Vec3d& offset) { m_assemble_transformation.set_offset(offset); } + void set_assemble_offset(const Vec3d &offset){ m_assemble_initialized = true;m_assemble_transformation.set_offset(offset);} void set_assemble_rotation(const Vec3d &rotation) { m_assemble_transformation.set_rotation(rotation); } void rotate_assemble(double angle, const Vec3d& axis) { m_assemble_transformation.set_rotation(m_assemble_transformation.get_rotation() + Geometry::extract_euler_angles(Eigen::Quaterniond(Eigen::AngleAxisd(angle, axis)).toRotationMatrix())); @@ -1328,6 +1330,7 @@ public: BoundingBoxf3 transform_mesh_bounding_box(const TriangleMesh& mesh, bool dont_translate = false) const; // Transform an external bounding box. BoundingBoxf3 transform_bounding_box(const BoundingBoxf3 &bbox, bool dont_translate = false) const; + BoundingBoxf3 transform_bounding_box_in_assembly_view(const BoundingBoxf3 &bbox, bool dont_translate = false) const; // Transform an external vector. Vec3d transform_vector(const Vec3d& v, bool dont_translate = false) const; // To be called on an external polygon. It does not translate the polygon, only rotates and scales. @@ -1602,6 +1605,7 @@ public: ModelObject* add_object(const char *name, const char *path, const TriangleMesh &mesh); ModelObject* add_object(const char *name, const char *path, TriangleMesh &&mesh); ModelObject* add_object(const ModelObject &other); + void set_assembly_pos(ModelObject * model_object); void delete_object(size_t idx); bool delete_object(ObjectID id); bool delete_object(ModelObject* object); @@ -1624,6 +1628,7 @@ public: bool add_default_instances(); // Returns approximate axis aligned bounding box of this model BoundingBoxf3 bounding_box() const; + BoundingBoxf3 bounding_box_in_assembly_view() const; // Set the print_volume_state of PrintObject::instances, // return total number of printable objects. unsigned int update_print_volume_state(const BuildVolume &build_volume); diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index 70517f41a..fdd43e88e 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -1349,7 +1349,7 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, const Transform3d & view_matrix, std::function filter_func, bool with_outline, - const std::array & body_color, + const std::array & body_color, bool partly_inside_enable) const { GLVolumeWithIdAndZList to_render = volumes_to_render(volumes, type, view_matrix, filter_func); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index ea6b32515..f7a00ba30 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1572,6 +1572,10 @@ void GLCanvas3D::refresh_camera_scene_box() wxGetApp().plater()->get_camera().set_scene_box(scene_bounding_box()); } +BoundingBoxf3 GLCanvas3D::assembly_view_cur_bounding_box() const { + return m_model->bounding_box_in_assembly_view(); +} + BoundingBoxf3 GLCanvas3D::volumes_bounding_box() const { BoundingBoxf3 bb; diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 316252250..99731c1ce 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -416,7 +416,7 @@ class GLCanvas3D void render(const std::vector& sorted_instances) const; }; - + class Tooltip { std::string m_text; @@ -502,6 +502,7 @@ public: }; int GetHoverId(); + void set_ignore_left_up() { m_mouse.ignore_left_up = true; } private: bool m_is_dark = false; @@ -778,6 +779,7 @@ public: void set_show_world_axes(bool flag) { m_show_world_axes = flag; } void refresh_camera_scene_box(); + BoundingBoxf3 assembly_view_cur_bounding_box() const; BoundingBoxf3 volumes_bounding_box() const; BoundingBoxf3 scene_bounding_box() const; BoundingBoxf3 plate_scene_bounding_box(int plate_idx) const; @@ -1032,7 +1034,7 @@ public: bool is_overhang_shown() const { return m_slope.is_GlobalUsed(); } void show_overhang(bool show) { m_slope.globalUse(show); } - + bool is_using_slope() const { return m_slope.is_used(); } void use_slope(bool use) { m_slope.use(use); } void set_slope_normal_angle(float angle_in_deg) { m_slope.set_normal_angle(angle_in_deg); } diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 77f42eda3..896a729d6 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -57,7 +57,7 @@ static const Selection& scene_selection() //BBS AssembleView canvas has its own selection if (wxGetApp().plater()->get_current_canvas3D()->get_canvas_type() == GLCanvas3D::ECanvasType::CanvasAssembleView) return wxGetApp().plater()->get_assmeble_canvas3D()->get_selection(); - + return wxGetApp().plater()->get_view3D_canvas3D()->get_selection(); } @@ -140,7 +140,7 @@ ObjectList::ObjectList(wxWindow* parent) : int new_selected_column = -1; #endif //__WXMSW__ GLGizmosManager &gizmos_mgr = wxGetApp().plater()->get_view3D_canvas3D()->get_gizmos_manager(); - if ((wxGetKeyState(WXK_SHIFT) || wxGetKeyState(WXK_CONTROL)) + if ((wxGetKeyState(WXK_SHIFT) || wxGetKeyState(WXK_CONTROL)) && gizmos_mgr.is_gizmo_activable_when_single_full_instance()) { // selection will not be single_full_instance after shift_pressed,Caused exe crashed UnselectAll(); @@ -2281,8 +2281,7 @@ void ObjectList::load_mesh_object(const TriangleMesh &mesh, const wxString &name new_object->ensure_on_bed(); //BBS init assmeble transformation - Geometry::Transformation t = new_object->instances[0]->get_transformation(); - new_object->instances[0]->set_assemble_transformation(t); + new_object->get_model()->set_assembly_pos(new_object); object_idxs.push_back(model.objects.size() - 1); #ifdef _DEBUG @@ -2500,7 +2499,7 @@ bool ObjectList::del_from_cut_object(bool is_cut_connector, bool is_model_part/* const wxString title = is_cut_connector ? _L("Delete connector from object which is a part of cut") : is_model_part ? _L("Delete solid part from object which is a part of cut") : is_negative_volume ? _L("Delete negative volume from object which is a part of cut") : ""; - + const wxString msg_end = is_cut_connector ? ("\n" + _L("To save cut correspondence you can delete all connectors from all related objects.")) : ""; InfoDialog dialog(wxGetApp().plater(), title, @@ -5545,7 +5544,7 @@ void ObjectList::msw_rescale() void ObjectList::sys_color_changed() { wxGetApp().UpdateDVCDarkUI(this, true); - + msw_rescale(); if (m_objects_model) { m_objects_model->sys_color_changed(); } diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 2237c406f..09f266120 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -3535,7 +3535,7 @@ std::vector Plater::priv::load_files(const std::vector& input_ const float INIT_MODEL_RATIO = 0.75; const float CENTER_AROUND_ORIGIN_RATIO = 0.8; const float LOAD_MODEL_RATIO = 0.9; - + bool import_obj_or_stl = false; for (size_t i = 0; i < input_files.size(); ++i) { int file_percent = 0; @@ -4159,7 +4159,9 @@ std::vector Plater::priv::load_files(const std::vector& input_ q->skip_thumbnail_invalid = false; return empty_result; } - + if (boost::algorithm::iends_with(path.string(), ".stl") || boost::algorithm::iends_with(path.string(), ".obj")) { + import_obj_or_stl = true; + } if (one_by_one) { // BBS: add load_old_project logic if (type_3mf && !is_project_file && !load_old_project) @@ -4174,7 +4176,11 @@ std::vector Plater::priv::load_files(const std::vector& input_ BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format(", before load_model_objects, count %1%")%model.objects.size(); auto loaded_idxs = load_model_objects(model.objects, is_project_file); obj_idxs.insert(obj_idxs.end(), loaded_idxs.begin(), loaded_idxs.end()); - + if (import_obj_or_stl) { + for (int i = 0; i < loaded_idxs.size(); i++) { + q->model().set_assembly_pos(q->model().objects[q->model().objects.size() - 1 - i]); + } + } BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format(", finished load_model_objects"); wxString msg = wxString::Format(_L("Loading file: %s"), from_path(real_filename)); dlg_cont = dlg.Update(progress_percent, msg); @@ -4209,6 +4215,11 @@ std::vector Plater::priv::load_files(const std::vector& input_ auto loaded_idxs = load_model_objects(new_model->objects); obj_idxs.insert(obj_idxs.end(), loaded_idxs.begin(), loaded_idxs.end()); + if (import_obj_or_stl) { + for (int i = 0; i < loaded_idxs.size(); i++) { + q->model().set_assembly_pos(q->model().objects[q->model().objects.size() - 1 - i]); + } + } } if (new_model) delete new_model; @@ -5828,7 +5839,7 @@ void Plater::priv::reload_from_disk() new_volume = old_model_object->add_volume(*new_model_object->volumes[new_volume_idx]); // new_volume = old_model_object->volumes.back(); } - + new_volume->set_new_unique_id(); new_volume->config.apply(old_volume->config); new_volume->set_type(old_volume->type()); @@ -6252,7 +6263,7 @@ void Plater::priv::set_current_panel(wxPanel* panel, bool no_slice) assemble_view->get_canvas3d()->bind_event_handlers(); assemble_view->reload_scene(true); - + assemble_view->get_canvas3d()->set_ignore_left_up(); if (old_panel == view3D) { GLCanvas3D* view3D_canvas = view3D->get_canvas3d(); Selection::IndicesList select_idxs = view3D_canvas->get_selection().get_volume_idxs();