mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-12-11 16:00:17 -07:00
Merge branch 'main' into enh-update-wxwidgets
# Conflicts: # src/nanosvg/README.txt # src/nanosvg/nanosvg.h # src/nanosvg/nanosvgrast.h # src/slic3r/GUI/BitmapCache.cpp # src/slic3r/GUI/BitmapCache.hpp # src/slic3r/GUI/ImGuiWrapper.cpp
This commit is contained in:
commit
53bc949580
467 changed files with 29654 additions and 17853 deletions
|
|
@ -1,3 +1,9 @@
|
|||
///|/ Copyright (c) Prusa Research 2018 - 2023 Oleksandra Iushchenko @YuSanka, Enrico Turri @enricoturri1966, Lukáš Matěna @lukasmatena, Lukáš Hejl @hejllukas, Tomáš Mészáros @tamasmeszaros, Vojtěch Bubník @bubnikv, Pavel Mikuš @Godrak, David Kocík @kocikdav, Filip Sykala @Jony01, Vojtěch Král @vojtechkral
|
||||
///|/ Copyright (c) 2021 Mathias Rasmussen
|
||||
///|/ Copyright (c) 2020 rongith
|
||||
///|/
|
||||
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
|
||||
///|/
|
||||
#include "libslic3r/libslic3r.h"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
#include "GUI_ObjectList.hpp"
|
||||
|
|
@ -304,6 +310,7 @@ ObjectList::ObjectList(wxWindow* parent) :
|
|||
|
||||
ObjectList::~ObjectList()
|
||||
{
|
||||
delete m_objects_model;
|
||||
}
|
||||
|
||||
void ObjectList::set_min_height()
|
||||
|
|
@ -1949,7 +1956,7 @@ void ObjectList::load_modifier(const wxArrayString& input_files, ModelObject& mo
|
|||
const BoundingBoxf3 instance_bb = model_object.instance_bounding_box(instance_idx);
|
||||
|
||||
// First (any) GLVolume of the selected instance. They all share the same instance matrix.
|
||||
const GLVolume* v = selection.get_volume(*selection.get_volume_idxs().begin());
|
||||
const GLVolume* v = selection.get_first_volume();
|
||||
const Geometry::Transformation inst_transform = v->get_instance_transformation();
|
||||
const Transform3d inv_inst_transform = inst_transform.get_matrix(true).inverse();
|
||||
const Vec3d instance_offset = v->get_instance_offset();
|
||||
|
|
@ -2085,7 +2092,7 @@ void ObjectList::load_generic_subobject(const std::string& type_name, const Mode
|
|||
ModelVolume *new_volume = model_object.add_volume(std::move(mesh), type);
|
||||
|
||||
// First (any) GLVolume of the selected instance. They all share the same instance matrix.
|
||||
const GLVolume* v = selection.get_volume(*selection.get_volume_idxs().begin());
|
||||
const GLVolume* v = selection.get_first_volume();
|
||||
// Transform the new modifier to be aligned with the print bed.
|
||||
const BoundingBoxf3 mesh_bb = new_volume->mesh().bounding_box();
|
||||
new_volume->set_transformation(Geometry::Transformation::volume_to_bed_transformation(v->get_instance_transformation(), mesh_bb));
|
||||
|
|
@ -2810,7 +2817,7 @@ void ObjectList::merge(bool to_multipart_object)
|
|||
}
|
||||
}
|
||||
|
||||
void ObjectList::merge_volumes()
|
||||
/*void ObjectList::merge_volumes()
|
||||
{
|
||||
std::vector<int> obj_idxs, vol_idxs;
|
||||
get_selection_indexes(obj_idxs, vol_idxs);
|
||||
|
|
@ -2838,11 +2845,11 @@ void ObjectList::merge_volumes()
|
|||
else {
|
||||
for (int vol_idx : vol_idxs)
|
||||
selection.add_volume(last_obj_idx, vol_idx, 0, false);
|
||||
}*/
|
||||
}#1#
|
||||
#else
|
||||
wxGetApp().plater()->merge(obj_idxs[0], vol_idxs);
|
||||
#endif
|
||||
}
|
||||
}*/
|
||||
|
||||
void ObjectList::layers_editing()
|
||||
{
|
||||
|
|
@ -3029,6 +3036,93 @@ bool ObjectList::can_split_instances()
|
|||
return selection.is_multiple_full_instance() || selection.is_single_full_instance();
|
||||
}
|
||||
|
||||
bool ObjectList::has_selected_cut_object() const
|
||||
{
|
||||
wxDataViewItemArray sels;
|
||||
GetSelections(sels);
|
||||
if (sels.IsEmpty())
|
||||
return false;
|
||||
|
||||
for (wxDataViewItem item : sels) {
|
||||
const int obj_idx = m_objects_model->GetObjectIdByItem(item);
|
||||
// ys_FIXME: The obj_idx<size condition is a workaround for https://github.com/prusa3d/PrusaSlicer/issues/11186,
|
||||
// but not the correct fix. The deleted item probably should not be in sels in the first place.
|
||||
if (obj_idx >= 0 && obj_idx < int(m_objects->size()) && object(obj_idx)->is_cut())
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ObjectList::invalidate_cut_info_for_selection()
|
||||
{
|
||||
const wxDataViewItem item = GetSelection();
|
||||
if (item) {
|
||||
const int obj_idx = m_objects_model->GetObjectIdByItem(item);
|
||||
if (obj_idx >= 0)
|
||||
invalidate_cut_info_for_object(size_t(obj_idx));
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectList::invalidate_cut_info_for_object(int obj_idx)
|
||||
{
|
||||
ModelObject* init_obj = object(obj_idx);
|
||||
if (!init_obj->is_cut())
|
||||
return;
|
||||
|
||||
take_snapshot(_u8L("Invalidate cut info"));
|
||||
|
||||
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(int(idx)); obj->cut_id.is_equal(cut_id)) {
|
||||
obj->invalidate_cut();
|
||||
update_info_items(idx);
|
||||
add_volumes_to_object_in_list(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(_u8L("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();
|
||||
}
|
||||
|
||||
bool ObjectList::can_merge_to_multipart_object() const
|
||||
{
|
||||
if (has_selected_cut_object())
|
||||
|
|
@ -3043,10 +3137,9 @@ bool ObjectList::can_merge_to_multipart_object() const
|
|||
return false;
|
||||
|
||||
// should be selected just objects
|
||||
for (wxDataViewItem item : sels) {
|
||||
for (wxDataViewItem item : sels)
|
||||
if (!(m_objects_model->GetItemType(item) & (itObject | itInstance)))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -3071,97 +3164,6 @@ bool ObjectList::can_mesh_boolean() const
|
|||
return (*m_objects)[obj_idx]->volumes.size() > 1 || ((*m_objects)[obj_idx]->volumes.size() == 1 && (*m_objects)[obj_idx]->volumes[0]->is_splittable());
|
||||
}
|
||||
|
||||
bool ObjectList::has_selected_cut_object() const
|
||||
{
|
||||
wxDataViewItemArray sels;
|
||||
GetSelections(sels);
|
||||
if (sels.IsEmpty())
|
||||
return false;
|
||||
|
||||
for (wxDataViewItem item : sels) {
|
||||
const int obj_idx = m_objects_model->GetObjectIdByItem(item);
|
||||
if (obj_idx >= 0 && object(obj_idx)->is_cut())
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ObjectList::invalidate_cut_info_for_selection()
|
||||
{
|
||||
const wxDataViewItem item = GetSelection();
|
||||
if (item) {
|
||||
const int obj_idx = m_objects_model->GetObjectIdByItem(item);
|
||||
if (obj_idx >= 0)
|
||||
invalidate_cut_info_for_object(size_t(obj_idx));
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectList::invalidate_cut_info_for_object(int obj_idx)
|
||||
{
|
||||
ModelObject *init_obj = object(obj_idx);
|
||||
if (!init_obj->is_cut()) return;
|
||||
|
||||
take_snapshot("Invalidate cut info");
|
||||
|
||||
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(int(idx)); obj->cut_id.is_equal(cut_id)) {
|
||||
obj->invalidate_cut();
|
||||
update_info_items(idx);
|
||||
add_volumes_to_object_in_list(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("Delete all connectors");
|
||||
|
||||
auto has_solid_mesh = [](ModelObject* obj) {
|
||||
for (const ModelVolume *volume : obj->volumes)
|
||||
if (volume->is_model_part()) return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
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() || !has_solid_mesh(obj)) {
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
// NO_PARAMETERS function call means that changed object index will be determine from Selection()
|
||||
void ObjectList::changed_object(const int obj_idx/* = -1*/) const
|
||||
{
|
||||
|
|
@ -4349,7 +4351,7 @@ void ObjectList::update_selections()
|
|||
sels.Add(m_objects_model->GetItemById(selection.get_object_idx()));
|
||||
}
|
||||
else if (selection.is_single_volume() || selection.is_any_modifier()) {
|
||||
const auto gl_vol = selection.get_volume(*selection.get_volume_idxs().begin());
|
||||
const auto gl_vol = selection.get_first_volume();
|
||||
if (m_objects_model->GetVolumeIdByItem(m_objects_model->GetParent(item)) == gl_vol->volume_idx())
|
||||
return;
|
||||
}
|
||||
|
|
@ -4425,8 +4427,7 @@ void ObjectList::update_selections()
|
|||
{
|
||||
if (m_selection_mode & smSettings)
|
||||
{
|
||||
const auto idx = *selection.get_volume_idxs().begin();
|
||||
const auto gl_vol = selection.get_volume(idx);
|
||||
const auto gl_vol = selection.get_first_volume();
|
||||
if (gl_vol->volume_idx() >= 0) {
|
||||
// Only add GLVolumes with non-negative volume_ids. GLVolumes with negative volume ids
|
||||
// are not associated with ModelVolumes, but they are temporarily generated by the backend
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue