mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-13 19:01:21 +00:00
Fix instance Z synchronization (#15465)
This commit is contained in:
@@ -987,6 +987,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
|
||||
MetadataList metadata;
|
||||
VolumeMetadataList volumes;
|
||||
bool auto_drop { true };
|
||||
};
|
||||
|
||||
struct CutObjectInfo
|
||||
@@ -1367,7 +1368,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
bool _handle_start_text_configuration(const char** attributes, unsigned int num_attributes);
|
||||
bool _handle_start_shape_configuration(const char **attributes, unsigned int num_attributes);
|
||||
|
||||
bool _create_object_instance(std::string const & path, int object_id, const Transform3d& transform, const bool printable, const bool auto_drop, unsigned int recur_counter);
|
||||
bool _create_object_instance(std::string const & path, int object_id, const Transform3d& transform, const bool printable, unsigned int recur_counter);
|
||||
|
||||
void _apply_transform(ModelInstance& instance, const Transform3d& transform);
|
||||
|
||||
@@ -2259,6 +2260,8 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
if (obj_metadata != m_objects_metadata.end()) {
|
||||
// config data has been found, this model was saved using slic3r pe
|
||||
|
||||
model_object->auto_drop = obj_metadata->second.auto_drop;
|
||||
|
||||
// apply object's name and config data
|
||||
for (const Metadata& metadata : obj_metadata->second.metadata) {
|
||||
if (metadata.key == "name")
|
||||
@@ -4117,9 +4120,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
std::string path = bbs_get_attribute_value_string(attributes, num_attributes, PPATH_ATTR);
|
||||
Transform3d transform = bbs_get_transform_from_3mf_specs_string(bbs_get_attribute_value_string(attributes, num_attributes, TRANSFORM_ATTR));
|
||||
int printable = bbs_get_attribute_value_bool(attributes, num_attributes, PRINTABLE_ATTR);
|
||||
int auto_drop = bbs_get_attribute_value_bool(attributes, num_attributes, AUTO_DROP_ATTR);
|
||||
|
||||
return !m_load_model || _create_object_instance(path, object_id, transform, printable, auto_drop, 1);
|
||||
return !m_load_model || _create_object_instance(path, object_id, transform, printable, 1);
|
||||
}
|
||||
|
||||
bool _BBS_3MF_Importer::_handle_end_item()
|
||||
@@ -4347,7 +4348,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _BBS_3MF_Importer::_create_object_instance(std::string const & path, int object_id, const Transform3d& transform, const bool printable, const bool auto_drop, unsigned int recur_counter)
|
||||
bool _BBS_3MF_Importer::_create_object_instance(std::string const & path, int object_id, const Transform3d& transform, const bool printable, unsigned int recur_counter)
|
||||
{
|
||||
static const unsigned int MAX_RECURSIONS = 10;
|
||||
|
||||
@@ -4384,7 +4385,6 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
return false;
|
||||
}
|
||||
instance->printable = printable;
|
||||
instance->auto_drop = auto_drop;
|
||||
|
||||
m_instances.emplace_back(instance, transform);
|
||||
|
||||
@@ -4417,7 +4417,6 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
return false;
|
||||
}
|
||||
instance->printable = printable;
|
||||
instance->auto_drop = auto_drop;
|
||||
|
||||
m_instances.emplace_back(instance, transform);
|
||||
}
|
||||
@@ -4488,7 +4487,9 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
// Added because of github #3435, currently not used by PrusaSlicer
|
||||
// int instances_count_id = bbs_get_attribute_value_int(attributes, num_attributes, INSTANCESCOUNT_ATTR);
|
||||
|
||||
m_objects_metadata.insert({ object_id, ObjectMetadata() });
|
||||
ObjectMetadata metadata;
|
||||
metadata.auto_drop = bbs_get_attribute_value_bool(attributes, num_attributes, AUTO_DROP_ATTR);
|
||||
m_objects_metadata.insert({ object_id, std::move(metadata) });
|
||||
m_curr_config.object_id = object_id;
|
||||
return true;
|
||||
}
|
||||
@@ -6164,14 +6165,12 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
unsigned int id;
|
||||
Transform3d transform;
|
||||
bool printable;
|
||||
bool auto_drop;
|
||||
|
||||
BuildItem(std::string const & path, unsigned int id, const Transform3d& transform, const bool printable, const bool auto_drop)
|
||||
BuildItem(std::string const & path, unsigned int id, const Transform3d& transform, const bool printable)
|
||||
: path(path)
|
||||
, id(id)
|
||||
, transform(transform)
|
||||
, printable(printable)
|
||||
, auto_drop(auto_drop)
|
||||
{
|
||||
}
|
||||
};
|
||||
@@ -7412,7 +7411,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
// instance_id is just a 1 indexed index in build_items.
|
||||
//assert(m_skip_static || curr_id == build_items.size() + 1);
|
||||
|
||||
build_items.emplace_back("", object_it->second.object_id, t, instance->printable, instance->auto_drop);
|
||||
build_items.emplace_back("", object_it->second.object_id, t, instance->printable);
|
||||
count++;
|
||||
}
|
||||
|
||||
@@ -7862,8 +7861,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
stream << "\" " << PPATH_ATTR << "=\"" << xml_escape(item.path);
|
||||
stream << "\" " << TRANSFORM_ATTR << "=\"";
|
||||
add_transformation(stream, item.transform);
|
||||
stream << "\" " << PRINTABLE_ATTR << "=\"" << item.printable;
|
||||
stream << "\" " << AUTO_DROP_ATTR << "=\"" << item.auto_drop << "\"/>\n";
|
||||
stream << "\" " << PRINTABLE_ATTR << "=\"" << item.printable << "\"/>\n";
|
||||
}
|
||||
|
||||
stream << " </" << BUILD_TAG << ">\n";
|
||||
@@ -8300,7 +8298,8 @@ bool _BBS_3MF_Exporter::_add_model_config_file_to_archive(mz_zip_archive& archiv
|
||||
if (obj != nullptr) {
|
||||
// Output of instances count added because of github #3435, currently not used by PrusaSlicer
|
||||
//stream << " <" << OBJECT_TAG << " " << ID_ATTR << "=\"" << obj_metadata.first << "\" " << INSTANCESCOUNT_ATTR << "=\"" << obj->instances.size() << "\">\n";
|
||||
stream << " <" << OBJECT_TAG << " " << ID_ATTR << "=\"" << object_data.object_id << "\">\n";
|
||||
stream << " <" << OBJECT_TAG << " " << ID_ATTR << "=\"" << object_data.object_id
|
||||
<< "\" " << AUTO_DROP_ATTR << "=\"" << obj->auto_drop << "\">\n";
|
||||
|
||||
// stores object's name
|
||||
if (!obj->name.empty())
|
||||
|
||||
@@ -1280,6 +1280,7 @@ ModelObject& ModelObject::assign_copy(const ModelObject &rhs)
|
||||
this->layer_config_ranges = rhs.layer_config_ranges;
|
||||
this->layer_height_profile = rhs.layer_height_profile;
|
||||
this->printable = rhs.printable;
|
||||
this->auto_drop = rhs.auto_drop;
|
||||
this->origin_translation = rhs.origin_translation;
|
||||
this->cut_id.copy(rhs.cut_id);
|
||||
this->copy_transformation_caches(rhs);
|
||||
@@ -1320,6 +1321,7 @@ ModelObject& ModelObject::assign_copy(ModelObject &&rhs)
|
||||
this->layer_config_ranges = std::move(rhs.layer_config_ranges);
|
||||
this->layer_height_profile = std::move(rhs.layer_height_profile);
|
||||
this->printable = std::move(rhs.printable);
|
||||
this->auto_drop = rhs.auto_drop;
|
||||
this->origin_translation = std::move(rhs.origin_translation);
|
||||
this->copy_transformation_caches(rhs);
|
||||
|
||||
@@ -1889,6 +1891,9 @@ void ModelObject::center_around_origin(bool include_modifiers)
|
||||
|
||||
void ModelObject::ensure_on_bed(bool allow_negative_z)
|
||||
{
|
||||
if (!auto_drop)
|
||||
return;
|
||||
|
||||
double z_offset = 0.0;
|
||||
|
||||
if (allow_negative_z) {
|
||||
@@ -1907,14 +1912,8 @@ void ModelObject::ensure_on_bed(bool allow_negative_z)
|
||||
else
|
||||
z_offset = -this->min_z();
|
||||
|
||||
if (z_offset != 0.0) {
|
||||
for (size_t i = 0; i < instances.size(); ++i) {
|
||||
if (!instances[i]->auto_drop)
|
||||
continue;
|
||||
|
||||
translate_instance(i, z_offset * Vec3d::UnitZ());
|
||||
}
|
||||
}
|
||||
if (z_offset != 0.0)
|
||||
translate_instances(z_offset * Vec3d::UnitZ());
|
||||
}
|
||||
|
||||
void ModelObject::translate_instances(const Vec3d& vector)
|
||||
|
||||
@@ -400,6 +400,9 @@ public:
|
||||
LayerHeightProfile layer_height_profile;
|
||||
// Whether or not this object is printable
|
||||
bool printable { true };
|
||||
// Whether this object is snapped to the build plate after transformations.
|
||||
// Instance Z offsets are shared by all instances of an object.
|
||||
bool auto_drop { true };
|
||||
|
||||
// This vector holds position of selected support points for SLA. The data are
|
||||
// saved in mesh coordinates to allow using them for several instances.
|
||||
@@ -706,7 +709,7 @@ private:
|
||||
Internal::StaticSerializationWrapper<ModelConfigObject const> config_wrapper(config);
|
||||
Internal::StaticSerializationWrapper<LayerHeightProfile const> layer_heigth_profile_wrapper(layer_height_profile);
|
||||
ar(name, module_name, input_file, instances, volumes, config_wrapper, layer_config_ranges, layer_heigth_profile_wrapper,
|
||||
sla_support_points, sla_points_status, sla_drain_holes, printable, origin_translation, brim_points,
|
||||
sla_support_points, sla_points_status, sla_drain_holes, printable, auto_drop, origin_translation, brim_points,
|
||||
m_bounding_box_approx, m_bounding_box_approx_valid,
|
||||
m_bounding_box_exact, m_bounding_box_exact_valid, m_min_max_z_valid,
|
||||
m_raw_bounding_box, m_raw_bounding_box_valid, m_raw_mesh_bounding_box, m_raw_mesh_bounding_box_valid,
|
||||
@@ -719,7 +722,7 @@ private:
|
||||
// BBS: add backup, check modify
|
||||
SaveObjectGaurd gaurd(*this);
|
||||
ar(name, module_name, input_file, instances, volumes, config_wrapper, layer_config_ranges, layer_heigth_profile_wrapper,
|
||||
sla_support_points, sla_points_status, sla_drain_holes, printable, origin_translation, brim_points,
|
||||
sla_support_points, sla_points_status, sla_drain_holes, printable, auto_drop, origin_translation, brim_points,
|
||||
m_bounding_box_approx, m_bounding_box_approx_valid,
|
||||
m_bounding_box_exact, m_bounding_box_exact_valid, m_min_max_z_valid,
|
||||
m_raw_bounding_box, m_raw_bounding_box_valid, m_raw_mesh_bounding_box, m_raw_mesh_bounding_box_valid,
|
||||
@@ -1427,7 +1430,6 @@ public:
|
||||
ModelInstanceEPrintVolumeState print_volume_state;
|
||||
// Whether or not this instance is printable
|
||||
bool printable;
|
||||
bool auto_drop;
|
||||
bool use_loaded_id_for_label {false};
|
||||
int arrange_order = 0; // BBS
|
||||
size_t loaded_id = 0; // BBS
|
||||
@@ -1557,7 +1559,7 @@ private:
|
||||
|
||||
// Constructor, which assigns a new unique ID.
|
||||
explicit ModelInstance(ModelObject* object)
|
||||
: print_volume_state(ModelInstancePVS_Inside), printable(true), auto_drop(true), object(object), m_assemble_initialized(false)
|
||||
: print_volume_state(ModelInstancePVS_Inside), printable(true), object(object), m_assemble_initialized(false)
|
||||
{
|
||||
assert(this->id().valid());
|
||||
}
|
||||
@@ -1568,7 +1570,6 @@ private:
|
||||
, m_offset_to_assembly(other.m_offset_to_assembly)
|
||||
, print_volume_state(ModelInstancePVS_Inside)
|
||||
, printable(other.printable)
|
||||
, auto_drop(other.auto_drop)
|
||||
, object(object)
|
||||
, m_assemble_initialized(false) { assert(this->id().valid() && this->id() != other.id()); }
|
||||
|
||||
@@ -1582,7 +1583,7 @@ private:
|
||||
ModelInstance() : ObjectBase(-1), object(nullptr) { assert(this->id().invalid()); }
|
||||
// BBS. Add added members to archive.
|
||||
template<class Archive> void serialize(Archive& ar) {
|
||||
ar(m_transformation, print_volume_state, printable, auto_drop, m_assemble_transformation, m_offset_to_assembly, m_assemble_initialized);
|
||||
ar(m_transformation, print_volume_state, printable, m_assemble_transformation, m_offset_to_assembly, m_assemble_initialized);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -3053,10 +3053,9 @@ void GLCanvas3D::ensure_on_bed(unsigned int object_idx, bool allow_negative_z)
|
||||
InstancesToZMap instances_min_z;
|
||||
|
||||
for (GLVolume* volume : m_volumes.volumes) {
|
||||
ModelObject* mo = m_model->objects[volume->object_idx()];
|
||||
ModelInstance* mi = mo->instances[volume->instance_idx()];
|
||||
ModelObject* mo = m_model->objects[volume->object_idx()];
|
||||
|
||||
if (!mi->auto_drop) {
|
||||
if (!mo->auto_drop) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -5604,9 +5603,8 @@ void GLCanvas3D::do_move(const std::string& snapshot_type)
|
||||
// Fixes sinking/flying instances (snaps object to buildplate)
|
||||
for (const std::pair<int, int>& i : done) {
|
||||
ModelObject* mo = m_model->objects[i.first];
|
||||
ModelInstance* mi = mo->instances[i.second];
|
||||
|
||||
if (!mi->auto_drop) {
|
||||
if (!mo->auto_drop) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -5735,9 +5733,8 @@ void GLCanvas3D::do_rotate(const std::string& snapshot_type)
|
||||
// Fixes sinking/flying instances (snaps object to buildplate)
|
||||
for (const std::pair<int, int> &i : done) {
|
||||
ModelObject *mo = m_model->objects[i.first];
|
||||
ModelInstance* mi = mo->instances[i.second];
|
||||
|
||||
if (!mi->auto_drop) {
|
||||
if (!mo->auto_drop) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -5838,9 +5835,8 @@ void GLCanvas3D::do_scale(const std::string& snapshot_type)
|
||||
// Fixes sinking/flying instances (snaps object to buildplate)
|
||||
for (const std::pair<int, int>& i : done) {
|
||||
ModelObject* mo = m_model->objects[i.first];
|
||||
ModelInstance* mi = mo->instances[i.second];
|
||||
|
||||
if (!mi->auto_drop) {
|
||||
if (!mo->auto_drop) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -5959,9 +5955,8 @@ void GLCanvas3D::do_mirror(const std::string& snapshot_type)
|
||||
// Fixes sinking/flying instances (snaps object to buildplate)
|
||||
for (const std::pair<int, int>& i : done) {
|
||||
ModelObject* mo = m_model->objects[i.first];
|
||||
ModelInstance* mi = mo->instances[i.second];
|
||||
|
||||
if (!mi->auto_drop) {
|
||||
if (!mo->auto_drop) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -3234,8 +3234,8 @@ void ObjectList::merge(bool to_multipart_object)
|
||||
new_object->printable = false;
|
||||
new_object->instances[0]->printable = false;
|
||||
}
|
||||
if (object->instances[0]->auto_drop == false) {
|
||||
new_object->instances[0]->auto_drop = false;
|
||||
if (object->auto_drop == false) {
|
||||
new_object->auto_drop = false;
|
||||
}
|
||||
|
||||
// merge layers
|
||||
@@ -7098,18 +7098,10 @@ void ObjectList::toggle_auto_drop()
|
||||
|
||||
obj_idxs.emplace_back(static_cast<size_t>(obj_idx));
|
||||
|
||||
ItemType type = m_objects_model->GetItemType(item);
|
||||
// set auto_drop value for selected instance/instances in object
|
||||
if (type == itInstance) {
|
||||
int inst_idx = m_objects_model->GetInstanceIdByItem(item);
|
||||
obj->instances[inst_idx]->auto_drop = !current_auto_drop;
|
||||
} else {
|
||||
for (auto inst : obj->instances)
|
||||
inst->auto_drop = !current_auto_drop;
|
||||
|
||||
if (current_auto_drop == false)
|
||||
// auto_drop is shared by all instances of an object.
|
||||
obj->auto_drop = !current_auto_drop;
|
||||
if (current_auto_drop == false)
|
||||
obj->ensure_on_bed();
|
||||
}
|
||||
}
|
||||
|
||||
sort(obj_idxs.begin(), obj_idxs.end());
|
||||
|
||||
@@ -10359,10 +10359,7 @@ std::vector<size_t> Plater::priv::load_model_objects(const ModelObjectPtrs& mode
|
||||
}
|
||||
|
||||
if (!auto_drop) {
|
||||
for (size_t i = 0; i < object->instances.size(); ++i) {
|
||||
ModelInstance* instance = object->instances[i];
|
||||
instance->auto_drop = auto_drop;
|
||||
}
|
||||
object->auto_drop = false;
|
||||
|
||||
// if under the bed, move over the bed
|
||||
double dist_to_bed = std::min(object->min_z(), double(0));
|
||||
@@ -10991,7 +10988,7 @@ void Plater::priv::split_object(int obj_idx, bool auto_drop /* = true */)
|
||||
return false;
|
||||
};
|
||||
bool split_auto_drop = auto_drop;
|
||||
if (current_model_object->instances[0]->auto_drop && is_atleast_one_floating()) {
|
||||
if (current_model_object->auto_drop && is_atleast_one_floating()) {
|
||||
MessageDialog dlg(q, _L("Disable Auto-Drop to preserve Z positioning?\n"),
|
||||
_L("Object with floating parts was detected"), wxICON_QUESTION | wxYES_NO);
|
||||
|
||||
|
||||
@@ -638,26 +638,21 @@ void Selection::set_printable(bool printable)
|
||||
}
|
||||
|
||||
bool Selection::get_auto_drop() const {
|
||||
// The wipe tower is not a ModelObject and has no per-instance auto_drop;
|
||||
// The wipe tower is not a ModelObject and has no auto_drop state;
|
||||
// return the default to avoid indexing m_model->objects with its synthetic id.
|
||||
if (!m_valid || is_wipe_tower())
|
||||
return true;
|
||||
|
||||
std::set<std::pair<int, int>> instances_idxs;
|
||||
std::set<int> object_idxs;
|
||||
for (const auto& [obj_idx, inst_list] : m_cache.content) {
|
||||
for (int inst_idx : inst_list) {
|
||||
instances_idxs.insert({obj_idx, inst_idx});
|
||||
}
|
||||
object_idxs.insert(obj_idx);
|
||||
}
|
||||
|
||||
// return false, if one of the instances in the selection has auto_drop disabled, otherwise return true
|
||||
for (const auto& [obj_idx, inst_idx] : instances_idxs) {
|
||||
// Return false if one selected object has auto_drop disabled.
|
||||
for (int obj_idx : object_idxs) {
|
||||
ModelObject* object = m_model->objects[obj_idx];
|
||||
for (const auto* inst : object->instances) {
|
||||
if (!inst->auto_drop) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!object->auto_drop)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -668,22 +663,18 @@ void Selection::set_auto_drop(bool enabled)
|
||||
if (!m_valid)
|
||||
return;
|
||||
|
||||
std::set<std::pair<int, int>> instances_idxs;
|
||||
std::set<int> object_idxs;
|
||||
for (const auto& [obj_idx, inst_list] : m_cache.content) {
|
||||
for (int inst_idx : inst_list) {
|
||||
instances_idxs.insert({obj_idx, inst_idx});
|
||||
}
|
||||
object_idxs.insert(obj_idx);
|
||||
}
|
||||
|
||||
std::string snapshot_text = (boost::format("%1%") % (enabled ? "Set Selection Auto-Drop Enabled" : "Set Selection Auto-Drop Disabled")).str();
|
||||
wxGetApp().plater()->take_snapshot(snapshot_text);
|
||||
|
||||
// set auto_drop value for all instances in object
|
||||
for (const auto& [obj_idx, inst_idx] : instances_idxs) {
|
||||
// auto_drop is shared by all instances of an object.
|
||||
for (int obj_idx : object_idxs) {
|
||||
ModelObject* object = m_model->objects[obj_idx];
|
||||
for (auto* inst : object->instances) {
|
||||
inst->auto_drop = enabled;
|
||||
}
|
||||
object->auto_drop = enabled;
|
||||
}
|
||||
|
||||
// update scene
|
||||
@@ -3088,8 +3079,9 @@ void Selection::synchronize_unselected_instances(SyncRotationType sync_rotation_
|
||||
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();
|
||||
|
||||
bool should_synchronize_z = m_model->objects[volume_j->object_idx()]->instances[volume_j->instance_idx()]->auto_drop == false;
|
||||
if (should_synchronize_z && wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA)
|
||||
// Instances of the same object must remain at the same height. auto_drop
|
||||
// only controls snapping after the move, not the instance transform itself.
|
||||
if (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA)
|
||||
new_inst_trafo_j.translation().z() = curr_inst_trafo_i.translation().z();
|
||||
|
||||
assert(is_rotation_xy_synchronized(curr_inst_trafo_i, new_inst_trafo_j));
|
||||
@@ -3136,9 +3128,7 @@ void Selection::ensure_on_bed()
|
||||
for (size_t i = 0; i < m_volumes->size(); ++i) {
|
||||
GLVolume* volume = (*m_volumes)[i];
|
||||
ModelObject* mo = m_model->objects[volume->object_idx()];
|
||||
ModelInstance* mi = mo->instances[volume->instance_idx()];
|
||||
|
||||
if (mi->auto_drop == false
|
||||
if (mo->auto_drop == false
|
||||
|| volume->is_wipe_tower
|
||||
|| volume->is_modifier
|
||||
|| std::find(m_cache.sinking_volumes.begin(), m_cache.sinking_volumes.end(), i) != m_cache.sinking_volumes.end())
|
||||
|
||||
Reference in New Issue
Block a user