mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-04 18:10:38 +08:00
Multiple beds (part 6):
- arrange - bed spacing in multiples of bed size - newly loaded positions are loaded on active bed TODO: Fix results after convert, split and cut
This commit is contained in:
parent
c24e9fdfed
commit
87a1fe8c65
@ -1602,7 +1602,10 @@ unsigned int ModelObject::update_instances_print_volume_state(const BuildVolume
|
||||
for (const ModelVolume* vol : this->volumes)
|
||||
if (vol->is_model_part()) {
|
||||
const Transform3d matrix = model_instance->get_matrix() * vol->get_matrix();
|
||||
BuildVolume::ObjectState state = build_volume.object_state(vol->mesh().its, matrix.cast<float>(), true /* may be below print bed */, true /*ignore_bottom*/, &bed_idx);
|
||||
int bed = -1;
|
||||
BuildVolume::ObjectState state = build_volume.object_state(vol->mesh().its, matrix.cast<float>(), true /* may be below print bed */, true /*ignore_bottom*/, &bed);
|
||||
if (bed_idx == -1) // instance will be assigned to the bed the first volume is assigned to.
|
||||
bed_idx = bed;
|
||||
if (state == BuildVolume::ObjectState::Inside)
|
||||
// Volume is completely inside.
|
||||
inside_outside |= INSIDE;
|
||||
@ -1621,7 +1624,8 @@ unsigned int ModelObject::update_instances_print_volume_state(const BuildVolume
|
||||
inside_outside == INSIDE ? ModelInstancePVS_Inside : ModelInstancePVS_Fully_Outside;
|
||||
if (inside_outside == INSIDE)
|
||||
++num_printable;
|
||||
s_multiple_beds.set_instance_bed(model_instance->id(), bed_idx);
|
||||
if (bed_idx != -1)
|
||||
s_multiple_beds.set_instance_bed(model_instance->id(), bed_idx);
|
||||
}
|
||||
return num_printable;
|
||||
}
|
||||
|
@ -14,37 +14,42 @@ bool s_reload_preview_after_switching_beds = false;
|
||||
|
||||
Vec3d MultipleBeds::get_bed_translation(int id) const
|
||||
{
|
||||
// TODO: Arrange defines this in LogicalBedGap in SceneBuilder.cpp
|
||||
// TODO: It should be defined as multiple of bed size.
|
||||
// The x value is bed gap as multiples of the actual printable area bounding box,
|
||||
// so it can be matched to how the old slicer arranged things (in SceneBuilder.cpp).
|
||||
// The y value is a multiple of the larger of printable area BB and bed model BB -
|
||||
// this is to make sure that the bed models do not overlap.
|
||||
const double bed_gap_x = 2./10;
|
||||
const double bed_gap_y = 2./10;
|
||||
|
||||
if (id == 0)
|
||||
return Vec3d::Zero();
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
#if 0
|
||||
// Linear layout
|
||||
x = id;
|
||||
#else
|
||||
// Grid layout.
|
||||
++id;
|
||||
int a = 1;
|
||||
while ((a+1)*(a+1) < id)
|
||||
++a;
|
||||
id = id - a*a;
|
||||
x=a;
|
||||
y=a;
|
||||
if (id <= a)
|
||||
y = id-1;
|
||||
else
|
||||
x=id-a-1;
|
||||
#endif
|
||||
return 300. * Vec3d(x, y, 0.);
|
||||
if (m_layout_linear)
|
||||
x = id;
|
||||
else {
|
||||
// Grid layout.
|
||||
++id;
|
||||
int a = 1;
|
||||
while ((a+1)*(a+1) < id)
|
||||
++a;
|
||||
id = id - a*a;
|
||||
x=a;
|
||||
y=a;
|
||||
if (id <= a)
|
||||
y = id-1;
|
||||
else
|
||||
x=id-a-1;
|
||||
}
|
||||
return Vec3d(x * m_build_volume_bb.size().x() * (1. + bed_gap_x), y * m_build_volume_bb.size().y() * (1. + bed_gap_y), 0.);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void MultipleBeds::clear_inst_map()
|
||||
{
|
||||
m_inst_to_bed.clear();
|
||||
@ -132,5 +137,54 @@ bool MultipleBeds::is_glvolume_on_thumbnail_bed(const Model& model, int obj_idx,
|
||||
|
||||
|
||||
|
||||
bool MultipleBeds::rearrange_linear_to_grid_if_possible(Model& model, const BuildVolume& build_volume)
|
||||
{
|
||||
m_layout_linear = true;
|
||||
int old_number_of_beds = m_number_of_beds;
|
||||
m_number_of_beds = get_max_beds();
|
||||
Slic3r::ScopeGuard guard([this]() { m_layout_linear = false; });
|
||||
model.update_print_volume_state(build_volume);
|
||||
m_number_of_beds = old_number_of_beds;
|
||||
|
||||
int max_bed = 0;
|
||||
|
||||
std::map<ObjectID, std::pair<ModelInstance*, int>> id_to_ptr_and_bed;
|
||||
for (ModelObject* mo : model.objects) {
|
||||
for (ModelInstance* mi : mo->instances) {
|
||||
auto it = m_inst_to_bed.find(mi->id());
|
||||
if (it == m_inst_to_bed.end()) {
|
||||
// An instance is outside. Do not rearrange anything,
|
||||
// that could create collisions.
|
||||
return false;
|
||||
}
|
||||
id_to_ptr_and_bed[mi->id()] = std::make_pair(mi, it->second);
|
||||
max_bed = std::max(max_bed, it->second);
|
||||
}
|
||||
}
|
||||
|
||||
if (max_bed == 0) {
|
||||
// All instances are on the first bed. No need to do anything.
|
||||
return false;
|
||||
}
|
||||
m_number_of_beds = max_bed + 1;
|
||||
assert(m_number_of_beds <= get_max_beds());
|
||||
|
||||
// All instances are on some bed, at least two are used.
|
||||
for (auto& [oid, mi_and_bed] : id_to_ptr_and_bed) {
|
||||
auto& [mi, bed_idx] = mi_and_bed;
|
||||
mi->set_offset(mi->get_offset() - get_bed_translation(bed_idx));
|
||||
}
|
||||
|
||||
m_layout_linear = false;
|
||||
for (auto& [oid, mi_and_bed] : id_to_ptr_and_bed) {
|
||||
auto& [mi, bed_idx] = mi_and_bed;
|
||||
mi->set_offset(mi->get_offset() + get_bed_translation(bed_idx));
|
||||
}
|
||||
model.update_print_volume_state(build_volume);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -39,8 +39,15 @@ public:
|
||||
int get_thumbnail_bed_idx() const { return m_bed_for_thumbnails_generation; }
|
||||
bool is_glvolume_on_thumbnail_bed(const Model& model, int obj_idx, int instance_idx) const;
|
||||
|
||||
void set_last_hovered_bed(int i) { m_last_hovered_bed = i; }
|
||||
int get_last_hovered_bed() const { return m_last_hovered_bed; }
|
||||
void set_last_hovered_bed(int i) { m_last_hovered_bed = i; }
|
||||
int get_last_hovered_bed() const { return m_last_hovered_bed; }
|
||||
|
||||
bool rearrange_linear_to_grid_if_possible(Model& model, const BuildVolume& build_volume);
|
||||
void set_loading_project_flag(bool project) { m_loading_project = project; }
|
||||
bool get_loading_project_flag() const { return m_loading_project; }
|
||||
|
||||
void update_build_volume(const BoundingBoxf& build_volume_bb) { m_build_volume_bb = build_volume_bb; }
|
||||
|
||||
|
||||
|
||||
|
||||
@ -56,6 +63,9 @@ private:
|
||||
std::map<ObjectID, int> m_inst_to_bed;
|
||||
std::map<PrintBase*, size_t> m_printbase_to_texture;
|
||||
int m_last_hovered_bed = -1;
|
||||
BoundingBoxf m_build_volume_bb;
|
||||
bool m_layout_linear = false;
|
||||
bool m_loading_project = false;
|
||||
};
|
||||
|
||||
extern MultipleBeds s_multiple_beds;
|
||||
|
@ -84,6 +84,8 @@ bool Bed3D::set_shape(const Pointfs& bed_shape, const double max_print_height, c
|
||||
m_model_filename = model_filename;
|
||||
m_extended_bounding_box = this->calc_extended_bounding_box();
|
||||
|
||||
s_multiple_beds.update_build_volume(m_build_volume.bounding_volume2d());
|
||||
|
||||
m_contour = ExPolygon(Polygon::new_scale(bed_shape));
|
||||
const BoundingBox bbox = m_contour.contour.bounding_box();
|
||||
if (!bbox.defined)
|
||||
@ -228,6 +230,13 @@ void Bed3D::init_triangles()
|
||||
|
||||
m_triangles.init_from(std::move(init_data));
|
||||
m_triangles.set_color(DEFAULT_MODEL_COLOR);
|
||||
|
||||
BoundingBoxf bb = m_build_volume.bounding_volume2d();
|
||||
double y = bb.size().y();
|
||||
double ym = m_model.model.get_bounding_box().size().y();
|
||||
double diff = std::max(0., ym - y);
|
||||
bb.max = Vec2d(bb.max.x(), bb.max.y() + diff);
|
||||
s_multiple_beds.update_build_volume(bb);
|
||||
}
|
||||
|
||||
void Bed3D::init_gridlines()
|
||||
|
@ -22,6 +22,8 @@
|
||||
#include "Gizmos/GLGizmoCut.hpp"
|
||||
#include "Gizmos/GLGizmoScale.hpp"
|
||||
|
||||
#include "libslic3r/MultipleBeds.hpp"
|
||||
|
||||
#include "OptionsGroup.hpp"
|
||||
#include "Tab.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
@ -1835,6 +1837,9 @@ void ObjectList::load_mesh_object(const TriangleMesh &mesh, const std::string &n
|
||||
|
||||
new_object->ensure_on_bed();
|
||||
|
||||
if (! s_multiple_beds.get_loading_project_flag())
|
||||
new_object->instances.front()->set_offset(new_object->instances.front()->get_offset() + s_multiple_beds.get_bed_translation(s_multiple_beds.get_active_bed()));
|
||||
|
||||
#ifdef _DEBUG
|
||||
check_model_ids_validity(model);
|
||||
#endif /* _DEBUG */
|
||||
|
@ -14,6 +14,8 @@
|
||||
#include <libslic3r/BuildVolume.hpp> // create object
|
||||
#include <libslic3r/SLA/ReprojectPointsOnMesh.hpp>
|
||||
|
||||
#include "libslic3r/MultipleBeds.hpp"
|
||||
|
||||
#include "slic3r/GUI/Plater.hpp"
|
||||
#include "slic3r/GUI/NotificationManager.hpp"
|
||||
#include "slic3r/GUI/GLCanvas3D.hpp"
|
||||
@ -373,6 +375,7 @@ void CreateObjectJob::finalize(bool canceled, std::exception_ptr &eptr)
|
||||
// set transformation
|
||||
Slic3r::Geometry::Transformation tr(m_transformation);
|
||||
new_object->instances.front()->set_transformation(tr);
|
||||
new_object->instances.front()->set_offset(new_object->instances.front()->get_offset() + s_multiple_beds.get_bed_translation(s_multiple_beds.get_active_bed()));
|
||||
new_object->ensure_on_bed();
|
||||
|
||||
// Actualize right panel and set inside of selection
|
||||
|
@ -1599,6 +1599,9 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
||||
GLGizmoSimplify::add_simplify_suggestion_notification(
|
||||
obj_idxs, model.objects, *notification_manager);
|
||||
|
||||
if (s_multiple_beds.rearrange_linear_to_grid_if_possible(model, q->build_volume()))
|
||||
update();
|
||||
|
||||
return obj_idxs;
|
||||
}
|
||||
|
||||
@ -1658,6 +1661,9 @@ std::vector<size_t> Plater::priv::load_model_objects(const ModelObjectPtrs& mode
|
||||
instance->set_scaling_factor(instance->get_scaling_factor() / max_ratio);
|
||||
scaled_down = true;
|
||||
}
|
||||
|
||||
if (! s_multiple_beds.get_loading_project_flag())
|
||||
instance->set_offset(instance->get_offset() + s_multiple_beds.get_bed_translation(s_multiple_beds.get_active_bed()));
|
||||
}
|
||||
|
||||
object->ensure_on_bed(allow_negative_z);
|
||||
@ -4159,6 +4165,9 @@ void Plater::load_project(const wxString& filename)
|
||||
// Take the Undo / Redo snapshot.
|
||||
Plater::TakeSnapshot snapshot(this, _L("Load Project") + ": " + wxString::FromUTF8(into_path(filename).stem().string().c_str()), UndoRedo::SnapshotType::ProjectSeparator);
|
||||
|
||||
s_multiple_beds.set_loading_project_flag(true);
|
||||
ScopeGuard guard([](){ s_multiple_beds.set_loading_project_flag(false);});
|
||||
|
||||
p->reset();
|
||||
|
||||
if (! load_files({ into_path(filename) }).empty()) {
|
||||
@ -6734,6 +6743,8 @@ void Plater::arrange(Worker &w, bool selected)
|
||||
concat_strings(names, "\n")));
|
||||
}
|
||||
|
||||
s_multiple_beds.rearrange_linear_to_grid_if_possible(model(), build_volume());
|
||||
|
||||
update(static_cast<unsigned int>(UpdateParams::FORCE_FULL_SCREEN_REFRESH));
|
||||
wxGetApp().obj_manipul()->set_dirty();
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user