mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-16 06:25:59 +08:00
Merge branch 'master' into fs_emboss
This commit is contained in:
commit
8a1fc4b16b
@ -1,2 +1,3 @@
|
||||
min_slic3r_version = 2.6.0-alpha1
|
||||
1.0.1 Disabled thick bridges.
|
||||
1.0.0 Initial Version
|
||||
|
@ -6,7 +6,7 @@
|
||||
name = Anker
|
||||
# Configuration version of this file. Config file will only be installed, if the config_version differs.
|
||||
# This means, the server may force the PrusaSlicer configuration to be downgraded.
|
||||
config_version = 1.0.0
|
||||
config_version = 1.0.1
|
||||
# Where to get the updates from?
|
||||
config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Anker/
|
||||
|
||||
@ -118,7 +118,7 @@ support_material_synchronize_layers = 0
|
||||
support_material_threshold = 40
|
||||
support_material_with_sheath = 0
|
||||
support_material_xy_spacing = 60%
|
||||
thick_bridges = 1
|
||||
thick_bridges = 0
|
||||
thin_walls = 0
|
||||
top_solid_infill_speed = 150
|
||||
travel_speed = 300
|
||||
|
@ -1279,6 +1279,14 @@ void ModelObject::invalidate_cut()
|
||||
volume->invalidate_cut_info();
|
||||
}
|
||||
|
||||
void ModelObject::delete_connectors()
|
||||
{
|
||||
for (int id = int(this->volumes.size()) - 1; id >= 0; id--) {
|
||||
if (volumes[id]->is_cut_connector())
|
||||
this->delete_volume(size_t(id));
|
||||
}
|
||||
}
|
||||
|
||||
void ModelObject::synchronize_model_after_cut()
|
||||
{
|
||||
for (ModelObject* obj : m_model->objects) {
|
||||
@ -1994,6 +2002,14 @@ int ModelObject::get_repaired_errors_count(const int vol_idx /*= -1*/) const
|
||||
stats.facets_reversed + stats.backwards_edges;
|
||||
}
|
||||
|
||||
bool ModelObject::has_solid_mesh() const
|
||||
{
|
||||
for (const ModelVolume* volume : volumes)
|
||||
if (volume->is_model_part())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void ModelVolume::set_material_id(t_model_material_id material_id)
|
||||
{
|
||||
m_material_id = material_id;
|
||||
|
@ -448,6 +448,8 @@ public:
|
||||
void apply_cut_connectors(const std::string& name);
|
||||
// invalidate cut state for this object and its connectors/volumes
|
||||
void invalidate_cut();
|
||||
// delete volumes which are marked as connector for this object
|
||||
void delete_connectors();
|
||||
void synchronize_model_after_cut();
|
||||
void apply_cut_attributes(ModelObjectCutAttributes attributes);
|
||||
void clone_for_cut(ModelObject **obj);
|
||||
@ -481,6 +483,8 @@ public:
|
||||
// Get count of errors in the mesh( or all object's meshes, if volume index isn't defined)
|
||||
int get_repaired_errors_count(const int vol_idx = -1) const;
|
||||
|
||||
// Detect if object has at least one solid mash
|
||||
bool has_solid_mesh() const;
|
||||
bool is_cut() const { return cut_id.id().valid(); }
|
||||
bool has_connectors() const;
|
||||
|
||||
|
@ -1880,6 +1880,7 @@ bool ObjectList::del_subobject_item(wxDataViewItem& item)
|
||||
|
||||
wxDataViewItem parent = m_objects_model->GetParent(item);
|
||||
|
||||
InfoItemType item_info_type = m_objects_model->GetInfoItemType(item);
|
||||
if (type & itSettings)
|
||||
del_settings_from_config(parent);
|
||||
else if (type & itInstanceRoot && obj_idx != -1)
|
||||
@ -1889,7 +1890,7 @@ bool ObjectList::del_subobject_item(wxDataViewItem& item)
|
||||
else if (type & itLayer && obj_idx != -1)
|
||||
del_layer_from_object(obj_idx, m_objects_model->GetLayerRangeByItem(item));
|
||||
else if (type & itInfo && obj_idx != -1)
|
||||
del_info_item(obj_idx, m_objects_model->GetInfoItemType(item));
|
||||
del_info_item(obj_idx, item_info_type);
|
||||
else if (idx == -1 || !del_subobject_from_object(obj_idx, idx, type))
|
||||
return false;
|
||||
|
||||
@ -1898,9 +1899,12 @@ bool ObjectList::del_subobject_item(wxDataViewItem& item)
|
||||
const std::string& icon_name = get_warning_icon_name(object(obj_idx)->get_object_stl_stats());
|
||||
m_objects_model->UpdateWarningIcon(parent, icon_name);
|
||||
}
|
||||
m_objects_model->Delete(item);
|
||||
|
||||
update_info_items(obj_idx);
|
||||
if (!(type & itInfo) || item_info_type != InfoItemType::CutConnectors) {
|
||||
// Connectors Item is already updated/deleted inside the del_info_item()
|
||||
m_objects_model->Delete(item);
|
||||
update_info_items(obj_idx);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1926,7 +1930,10 @@ void ObjectList::del_info_item(const int obj_idx, InfoItemType type)
|
||||
break;
|
||||
|
||||
case InfoItemType::CutConnectors:
|
||||
show_error(nullptr, _L("Connectors cannot be deleted from cut object."));
|
||||
if (!del_from_cut_object(true)) {
|
||||
// there is no need to post EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS if nothing was changed
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case InfoItemType::MmuSegmentation:
|
||||
@ -2018,6 +2025,38 @@ void ObjectList::del_layers_from_object(const int obj_idx)
|
||||
changed_object(obj_idx);
|
||||
}
|
||||
|
||||
bool ObjectList::del_from_cut_object(bool is_cut_connector, bool is_model_part/* = false*/, bool is_negative_volume/* = false*/)
|
||||
{
|
||||
const long buttons_style = is_cut_connector ? (wxYES | wxNO | wxCANCEL) : (wxYES | wxCANCEL);
|
||||
|
||||
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,
|
||||
_L("This action will break a cut correspondence.\n"
|
||||
"After that PrusaSlicer can't guarantee model consistency.\n"
|
||||
"\n"
|
||||
"To manipulate with solid parts or negative volumes you have to invalidate cut infornation first." + msg_end ),
|
||||
false, buttons_style | wxCANCEL_DEFAULT | wxICON_WARNING);
|
||||
|
||||
dialog.SetButtonLabel(wxID_YES, _L("Invalidate cut info"));
|
||||
if (is_cut_connector)
|
||||
dialog.SetButtonLabel(wxID_NO, _L("Delete all connectors"));
|
||||
|
||||
const int answer = dialog.ShowModal();
|
||||
if (answer == wxID_CANCEL)
|
||||
return false;
|
||||
|
||||
if (answer == wxID_YES)
|
||||
invalidate_cut_info_for_selection();
|
||||
else if (answer == wxID_NO)
|
||||
delete_all_connectors_for_selection();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ObjectList::del_subobject_from_object(const int obj_idx, const int idx, const int type)
|
||||
{
|
||||
assert(idx >= 0);
|
||||
@ -2039,15 +2078,10 @@ bool ObjectList::del_subobject_from_object(const int obj_idx, const int idx, con
|
||||
Slic3r::GUI::show_error(nullptr, _L("From Object List You can't delete the last solid part from object."));
|
||||
return false;
|
||||
}
|
||||
if (object->is_cut()) {
|
||||
if (volume->is_model_part()) {
|
||||
Slic3r::GUI::show_error(nullptr, _L("Solid part cannot be deleted from cut object."));
|
||||
return false;
|
||||
}
|
||||
if (volume->is_negative_volume()) {
|
||||
Slic3r::GUI::show_error(nullptr, _L("Negative volume cannot be deleted from cut object."));
|
||||
return false;
|
||||
}
|
||||
if (object->is_cut() && (volume->is_model_part() || volume->is_negative_volume())) {
|
||||
del_from_cut_object(volume->is_cut_connector(), volume->is_model_part(), volume->is_negative_volume());
|
||||
// in any case return false to break the deletion
|
||||
return false;
|
||||
}
|
||||
|
||||
take_snapshot(_L("Delete Subobject"));
|
||||
@ -2489,6 +2523,7 @@ bool ObjectList::has_selected_cut_object() const
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ObjectList::invalidate_cut_info_for_selection()
|
||||
{
|
||||
const wxDataViewItem item = GetSelection();
|
||||
@ -2499,27 +2534,61 @@ void ObjectList::invalidate_cut_info_for_selection()
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectList::invalidate_cut_info_for_object(size_t obj_idx)
|
||||
void ObjectList::invalidate_cut_info_for_object(int obj_idx)
|
||||
{
|
||||
ModelObject* init_obj = object(int(obj_idx));
|
||||
ModelObject* init_obj = object(obj_idx);
|
||||
if (!init_obj->is_cut())
|
||||
return;
|
||||
|
||||
take_snapshot(_L("Invalidate cut info"));
|
||||
|
||||
auto invalidate_cut = [this](size_t obj_idx) {
|
||||
object(int(obj_idx))->invalidate_cut();
|
||||
update_info_items(obj_idx);
|
||||
add_volumes_to_object_in_list(obj_idx);
|
||||
};
|
||||
|
||||
const CutObjectBase cut_id = init_obj->cut_id;
|
||||
// invalidate cut for related objects (which have the same cut_id)
|
||||
for (size_t idx = 0; idx < m_objects->size(); idx++)
|
||||
if (ModelObject* obj = object(idx); obj != init_obj && obj->cut_id.is_equal(init_obj->cut_id))
|
||||
invalidate_cut(idx);
|
||||
if (ModelObject* obj = object(int(idx)); obj->cut_id.is_equal(cut_id)) {
|
||||
obj->invalidate_cut();
|
||||
update_info_items(idx);
|
||||
add_volumes_to_object_in_list(idx);
|
||||
}
|
||||
|
||||
// invalidate own cut information
|
||||
invalidate_cut(size_t(obj_idx));
|
||||
update_lock_icons_for_model();
|
||||
}
|
||||
|
||||
void ObjectList::delete_all_connectors_for_selection()
|
||||
{
|
||||
const wxDataViewItem item = GetSelection();
|
||||
if (item) {
|
||||
const int obj_idx = m_objects_model->GetObjectIdByItem(item);
|
||||
if (obj_idx >= 0)
|
||||
delete_all_connectors_for_object(size_t(obj_idx));
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectList::delete_all_connectors_for_object(int obj_idx)
|
||||
{
|
||||
ModelObject* init_obj = object(obj_idx);
|
||||
if (!init_obj->is_cut())
|
||||
return;
|
||||
|
||||
take_snapshot(_L("Delete all connectors"));
|
||||
|
||||
const CutObjectBase cut_id = init_obj->cut_id;
|
||||
// Delete all connectors for related objects (which have the same cut_id)
|
||||
Model& model = wxGetApp().plater()->model();
|
||||
for (int idx = int(m_objects->size())-1; idx >= 0; idx--)
|
||||
if (ModelObject* obj = object(idx); obj->cut_id.is_equal(cut_id)) {
|
||||
obj->delete_connectors();
|
||||
|
||||
if (obj->volumes.empty() || !obj->has_solid_mesh()) {
|
||||
model.delete_object(idx);
|
||||
m_objects_model->Delete(m_objects_model->GetItemById(idx));
|
||||
continue;
|
||||
}
|
||||
|
||||
update_info_items(idx);
|
||||
add_volumes_to_object_in_list(idx);
|
||||
changed_object(int(idx));
|
||||
}
|
||||
|
||||
update_lock_icons_for_model();
|
||||
}
|
||||
@ -3044,6 +3113,7 @@ bool ObjectList::delete_from_model_and_list(const std::vector<ItemForDelete>& it
|
||||
return false;
|
||||
|
||||
m_prevent_list_events = true;
|
||||
ScopeGuard sg_prevent_list_events = ScopeGuard([this]() { m_prevent_list_events = false; });
|
||||
|
||||
std::set<size_t> modified_objects_ids;
|
||||
for (std::vector<ItemForDelete>::const_reverse_iterator item = items_for_delete.rbegin(); item != items_for_delete.rend(); ++item) {
|
||||
@ -3059,7 +3129,7 @@ bool ObjectList::delete_from_model_and_list(const std::vector<ItemForDelete>& it
|
||||
}
|
||||
else {
|
||||
if (!del_subobject_from_object(item->obj_idx, item->sub_obj_idx, item->type))
|
||||
continue;
|
||||
return false;// continue;
|
||||
if (item->type&itVolume) {
|
||||
m_objects_model->Delete(m_objects_model->GetItemByVolumeId(item->obj_idx, item->sub_obj_idx));
|
||||
ModelObject* obj = object(item->obj_idx);
|
||||
|
@ -266,6 +266,7 @@ public:
|
||||
void del_instances_from_object(const int obj_idx);
|
||||
void del_layer_from_object(const int obj_idx, const t_layer_height_range& layer_range);
|
||||
void del_layers_from_object(const int obj_idx);
|
||||
bool del_from_cut_object(bool is_connector, bool is_model_part = false, bool is_negative_volume = false);
|
||||
bool del_subobject_from_object(const int obj_idx, const int idx, const int type);
|
||||
void del_info_item(const int obj_idx, InfoItemType type);
|
||||
void split();
|
||||
@ -282,7 +283,9 @@ public:
|
||||
bool can_split_instances();
|
||||
bool has_selected_cut_object() const;
|
||||
void invalidate_cut_info_for_selection();
|
||||
void invalidate_cut_info_for_object(size_t obj_idx);
|
||||
void invalidate_cut_info_for_object(int obj_idx);
|
||||
void delete_all_connectors_for_selection();
|
||||
void delete_all_connectors_for_object(int obj_idx);
|
||||
bool can_merge_to_multipart_object() const;
|
||||
bool can_merge_to_single_object() const;
|
||||
|
||||
|
@ -165,8 +165,6 @@ void ArrangeJob::process(Ctl &ctl)
|
||||
{
|
||||
static const auto arrangestr = _u8L("Arranging");
|
||||
|
||||
ctl.update_status(0, arrangestr);
|
||||
|
||||
arrangement::ArrangeParams params;
|
||||
Points bedpts;
|
||||
ctl.call_on_main_thread([this, ¶ms, &bedpts]{
|
||||
@ -175,7 +173,12 @@ void ArrangeJob::process(Ctl &ctl)
|
||||
bedpts = get_bed_shape(*m_plater->config());
|
||||
}).wait();
|
||||
|
||||
auto count = unsigned(m_selected.size() + m_unprintable.size());
|
||||
auto count = unsigned(m_selected.size() + m_unprintable.size());
|
||||
|
||||
if (count == 0) // Should be taken care of by plater, but doesn't hurt
|
||||
return;
|
||||
|
||||
ctl.update_status(0, arrangestr);
|
||||
|
||||
params.stopcondition = [&ctl]() { return ctl.was_canceled(); };
|
||||
|
||||
|
@ -3001,7 +3001,7 @@ bool Plater::priv::delete_object_from_model(size_t obj_idx)
|
||||
InfoDialog dialog(q, _L("Delete object which is a part of cut object"),
|
||||
_L("You try to delete an object which is a part of a cut object.\n"
|
||||
"This action will break a cut correspondence.\n"
|
||||
"After that PrusaSlicer can't garantie model consistency"),
|
||||
"After that PrusaSlicer can't guarantee model consistency"),
|
||||
false, wxYES | wxCANCEL | wxCANCEL_DEFAULT | wxICON_WARNING);
|
||||
dialog.SetButtonLabel(wxID_YES, _L("Delete object"));
|
||||
if (dialog.ShowModal() == wxID_CANCEL)
|
||||
@ -4977,7 +4977,7 @@ bool Plater::priv::can_split_to_volumes() const
|
||||
|
||||
bool Plater::priv::can_arrange() const
|
||||
{
|
||||
if (model.objects.empty() && m_worker.is_idle()) return false;
|
||||
if (model.objects.empty() || !m_worker.is_idle()) return false;
|
||||
if (q->canvas3D()->get_gizmos_manager().get_current_type() == GLGizmosManager::Emboss) return false;
|
||||
return true;
|
||||
}
|
||||
@ -6821,8 +6821,8 @@ GLCanvas3D* Plater::get_current_canvas3D()
|
||||
|
||||
void Plater::arrange()
|
||||
{
|
||||
auto &w = get_ui_job_worker();
|
||||
if (w.is_idle()) {
|
||||
if (p->can_arrange()) {
|
||||
auto &w = get_ui_job_worker();
|
||||
p->take_snapshot(_L("Arrange"));
|
||||
replace_job(w, std::make_unique<ArrangeJob>());
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user