Merge remote-tracking branch 'origin/ys_undo_redo' into vb_undo_redo

This commit is contained in:
bubnikv 2019-07-04 20:15:50 +02:00
commit 1070991149
8 changed files with 89 additions and 19 deletions

View file

@ -508,8 +508,8 @@ private:
ModelVolume(ModelObject *object, const ModelVolume &other, const TriangleMesh &&mesh) : ModelVolume(ModelObject *object, const ModelVolume &other, const TriangleMesh &&mesh) :
name(other.name), m_mesh(new TriangleMesh(std::move(mesh))), config(other.config), m_type(other.m_type), object(object), m_transformation(other.m_transformation) name(other.name), m_mesh(new TriangleMesh(std::move(mesh))), config(other.config), m_type(other.m_type), object(object), m_transformation(other.m_transformation)
{ {
assert(this->id().valid()); assert(this->config.id().valid()); assert(this->id() != this->config.id()); // assert(this->id().valid()); assert(this->config.id().valid()); assert(this->id() != this->config.id());
assert(this->id() == other.id() && this->config.id() == other.config.id()); // assert(this->id() == other.id() && this->config.id() == other.config.id());
this->set_material_id(other.material_id()); this->set_material_id(other.material_id());
this->config.set_new_unique_id(); this->config.set_new_unique_id();
if (mesh.stl.stats.number_of_facets > 1) if (mesh.stl.stats.number_of_facets > 1)

View file

@ -65,6 +65,11 @@ static int extruders_count()
return wxGetApp().extruders_cnt(); return wxGetApp().extruders_cnt();
} }
static void take_snapshot(const wxString& snapshot_name)
{
wxGetApp().plater()->take_snapshot(snapshot_name);
}
ObjectList::ObjectList(wxWindow* parent) : ObjectList::ObjectList(wxWindow* parent) :
wxDataViewCtrl(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxDV_MULTIPLE), wxDataViewCtrl(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxDV_MULTIPLE),
m_parent(parent) m_parent(parent)
@ -580,7 +585,6 @@ void ObjectList::paste_volumes_into_list(int obj_idx, const ModelVolumePtrs& vol
if (volumes.empty()) if (volumes.empty())
return; return;
ModelObject& model_object = *(*m_objects)[obj_idx];
const auto object_item = m_objects_model->GetItemById(obj_idx); const auto object_item = m_objects_model->GetItemById(obj_idx);
wxDataViewItemArray items; wxDataViewItemArray items;
@ -816,6 +820,7 @@ void ObjectList::OnDrop(wxDataViewEvent &event)
if (m_dragged_data.type() == itInstance) if (m_dragged_data.type() == itInstance)
{ {
take_snapshot(_(L("Instances to Separated Objects")));
instances_to_separated_object(m_dragged_data.obj_idx(), m_dragged_data.inst_idxs()); instances_to_separated_object(m_dragged_data.obj_idx(), m_dragged_data.inst_idxs());
m_dragged_data.clear(); m_dragged_data.clear();
return; return;
@ -833,6 +838,8 @@ void ObjectList::OnDrop(wxDataViewEvent &event)
// if (to_volume_id > from_volume_id) to_volume_id--; // if (to_volume_id > from_volume_id) to_volume_id--;
// #endif // __WXGTK__ // #endif // __WXGTK__
take_snapshot(_(L("Remov Volume(s)")));
auto& volumes = (*m_objects)[m_dragged_data.obj_idx()]->volumes; auto& volumes = (*m_objects)[m_dragged_data.obj_idx()]->volumes;
auto delta = to_volume_id < from_volume_id ? -1 : 1; auto delta = to_volume_id < from_volume_id ? -1 : 1;
int cnt = 0; int cnt = 0;
@ -1427,6 +1434,8 @@ void ObjectList::load_subobject(ModelVolumeType type)
if (m_objects_model->GetItemType(item)&itInstance) if (m_objects_model->GetItemType(item)&itInstance)
item = m_objects_model->GetItemById(obj_idx); item = m_objects_model->GetItemById(obj_idx);
take_snapshot(_(L("Load Part")));
std::vector<std::pair<wxString, bool>> volumes_info; std::vector<std::pair<wxString, bool>> volumes_info;
load_part((*m_objects)[obj_idx], volumes_info, type); load_part((*m_objects)[obj_idx], volumes_info, type);
@ -1502,6 +1511,8 @@ void ObjectList::load_generic_subobject(const std::string& type_name, const Mode
if (instance_idx == -1) if (instance_idx == -1)
return; return;
take_snapshot(_(L("Add Generic Subobject")));
// Selected object // Selected object
ModelObject &model_object = *(*m_objects)[obj_idx]; ModelObject &model_object = *(*m_objects)[obj_idx];
// Bounding box of the selected instance in world coordinate system including the translation, without modifiers. // Bounding box of the selected instance in world coordinate system including the translation, without modifiers.
@ -1616,6 +1627,8 @@ void ObjectList::del_instances_from_object(const int obj_idx)
if (instances.size() <= 1) if (instances.size() <= 1)
return; return;
take_snapshot(_(L("Delete All Instances from Object")));
while ( instances.size()> 1) while ( instances.size()> 1)
instances.pop_back(); instances.pop_back();
@ -1645,6 +1658,8 @@ bool ObjectList::del_subobject_from_object(const int obj_idx, const int idx, con
return false; return false;
} }
take_snapshot(_(L("Delete Subobject")));
object->delete_volume(idx); object->delete_volume(idx);
if (object->volumes.size() == 1) if (object->volumes.size() == 1)
@ -1661,6 +1676,8 @@ bool ObjectList::del_subobject_from_object(const int obj_idx, const int idx, con
Slic3r::GUI::show_error(nullptr, _(L("You can't delete the last intance from object."))); Slic3r::GUI::show_error(nullptr, _(L("You can't delete the last intance from object.")));
return false; return false;
} }
take_snapshot(_(L("Delete Instance")));
object->delete_instance(idx); object->delete_instance(idx);
} }
else else
@ -1688,6 +1705,8 @@ void ObjectList::split()
return; return;
} }
take_snapshot(_(L("Split to Parts")));
wxBusyCursor wait; wxBusyCursor wait;
auto model_object = (*m_objects)[obj_idx]; auto model_object = (*m_objects)[obj_idx];
@ -1945,6 +1964,8 @@ void ObjectList::delete_from_model_and_list(const ItemType type, const int obj_i
if ( !(type&(itObject|itVolume|itInstance)) ) if ( !(type&(itObject|itVolume|itInstance)) )
return; return;
take_snapshot(_(L("Delete Selected Item")));
if (type&itObject) { if (type&itObject) {
del_object(obj_idx); del_object(obj_idx);
delete_object_from_list(obj_idx); delete_object_from_list(obj_idx);
@ -2502,6 +2523,8 @@ void ObjectList::change_part_type()
if (new_type == type || new_type == ModelVolumeType::INVALID) if (new_type == type || new_type == ModelVolumeType::INVALID)
return; return;
take_snapshot(_(L("Paste from Clipboard")));
const auto item = GetSelection(); const auto item = GetSelection();
volume->set_type(new_type); volume->set_type(new_type);
m_objects_model->SetVolumeType(item, new_type); m_objects_model->SetVolumeType(item, new_type);
@ -2862,5 +2885,22 @@ void ObjectList::set_extruder_for_selected_items(const int extruder) const
wxGetApp().plater()->update(); wxGetApp().plater()->update();
} }
void ObjectList::recreate_object_list()
{
m_prevent_list_events = true;
m_prevent_canvas_selection_update = true;
m_objects_model->DeleteAll();
size_t obj_idx = 0;
while (obj_idx < m_objects->size()) {
add_object_to_list(obj_idx);
++obj_idx;
}
m_prevent_canvas_selection_update = false;
m_prevent_list_events = false;
}
} //namespace GUI } //namespace GUI
} //namespace Slic3r } //namespace Slic3r

View file

@ -300,6 +300,8 @@ public:
void msw_rescale(); void msw_rescale();
void recreate_object_list();
private: private:
#ifdef __WXOSX__ #ifdef __WXOSX__
// void OnChar(wxKeyEvent& event); // void OnChar(wxKeyEvent& event);

View file

@ -1738,7 +1738,9 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
view3D_canvas->Bind(EVT_GLCANVAS_QUESTION_MARK, [this](SimpleEvent&) { wxGetApp().keyboard_shortcuts(); }); view3D_canvas->Bind(EVT_GLCANVAS_QUESTION_MARK, [this](SimpleEvent&) { wxGetApp().keyboard_shortcuts(); });
view3D_canvas->Bind(EVT_GLCANVAS_INCREASE_INSTANCES, [this](Event<int> &evt) view3D_canvas->Bind(EVT_GLCANVAS_INCREASE_INSTANCES, [this](Event<int> &evt)
{ if (evt.data == 1) this->q->increase_instances(); else if (this->can_decrease_instances()) this->q->decrease_instances(); }); { if (evt.data == 1) this->q->increase_instances(); else if (this->can_decrease_instances()) this->q->decrease_instances(); });
view3D_canvas->Bind(EVT_GLCANVAS_INSTANCE_MOVED, [this](SimpleEvent&) { update(); }); view3D_canvas->Bind(EVT_GLCANVAS_INSTANCE_MOVED, [this](SimpleEvent&) {
this->take_snapshot(_(L("Instance Moved")));
update(); });
view3D_canvas->Bind(EVT_GLCANVAS_WIPETOWER_MOVED, &priv::on_wipetower_moved, this); view3D_canvas->Bind(EVT_GLCANVAS_WIPETOWER_MOVED, &priv::on_wipetower_moved, this);
view3D_canvas->Bind(EVT_GLCANVAS_WIPETOWER_ROTATED, &priv::on_wipetower_rotated, this); view3D_canvas->Bind(EVT_GLCANVAS_WIPETOWER_ROTATED, &priv::on_wipetower_rotated, this);
view3D_canvas->Bind(EVT_GLCANVAS_INSTANCE_ROTATED, [this](SimpleEvent&) { update(); }); view3D_canvas->Bind(EVT_GLCANVAS_INSTANCE_ROTATED, [this](SimpleEvent&) { update(); });
@ -2337,17 +2339,21 @@ void Plater::priv::object_list_changed()
void Plater::priv::select_all() void Plater::priv::select_all()
{ {
// this->take_snapshot(_(L("Select All")));
view3D->select_all(); view3D->select_all();
this->sidebar->obj_list()->update_selections(); this->sidebar->obj_list()->update_selections();
} }
void Plater::priv::deselect_all() void Plater::priv::deselect_all()
{ {
// this->take_snapshot(_(L("Deselect All")));
view3D->deselect_all(); view3D->deselect_all();
} }
void Plater::priv::remove(size_t obj_idx) void Plater::priv::remove(size_t obj_idx)
{ {
this->take_snapshot(_(L("Remove Object")));
// Prevent toolpaths preview from rendering while we modify the Print object // Prevent toolpaths preview from rendering while we modify the Print object
preview->set_enabled(false); preview->set_enabled(false);
@ -2364,6 +2370,7 @@ void Plater::priv::remove(size_t obj_idx)
void Plater::priv::delete_object_from_model(size_t obj_idx) void Plater::priv::delete_object_from_model(size_t obj_idx)
{ {
// this->take_snapshot(_(L("Delete Object"))); // ys_FIXME What is the difference with "Remove Object"?
model.delete_object(obj_idx); model.delete_object(obj_idx);
update(); update();
object_list_changed(); object_list_changed();
@ -2398,17 +2405,20 @@ void Plater::priv::reset()
void Plater::priv::mirror(Axis axis) void Plater::priv::mirror(Axis axis)
{ {
this->take_snapshot(_(L("Mirror")));
view3D->mirror_selection(axis); view3D->mirror_selection(axis);
} }
void Plater::priv::arrange() void Plater::priv::arrange()
{ {
this->take_snapshot(_(L("Arrange")));
m_ui_jobs.start(Jobs::Arrange); m_ui_jobs.start(Jobs::Arrange);
} }
// This method will find an optimal orientation for the currently selected item // This method will find an optimal orientation for the currently selected item
// Very similar in nature to the arrange method above... // Very similar in nature to the arrange method above...
void Plater::priv::sla_optimize_rotation() { void Plater::priv::sla_optimize_rotation() {
this->take_snapshot(_(L("Optimize Rotation")));
m_ui_jobs.start(Jobs::Rotoptimize); m_ui_jobs.start(Jobs::Rotoptimize);
} }
@ -2564,6 +2574,8 @@ void Plater::priv::split_object()
Slic3r::GUI::warning_catcher(q, _(L("The selected object couldn't be split because it contains only one part."))); Slic3r::GUI::warning_catcher(q, _(L("The selected object couldn't be split because it contains only one part.")));
else else
{ {
this->take_snapshot(_(L("Split to Objects")));
unsigned int counter = 1; unsigned int counter = 1;
for (ModelObject* m : new_objects) for (ModelObject* m : new_objects)
m->name = current_model_object->name + "_" + std::to_string(counter++); m->name = current_model_object->name + "_" + std::to_string(counter++);
@ -2835,6 +2847,9 @@ void Plater::priv::fix_through_netfabb(const int obj_idx, const int vol_idx/* =
{ {
if (obj_idx < 0) if (obj_idx < 0)
return; return;
this->take_snapshot(_(L("Fix Throught NetFabb")));
fix_model_by_win10_sdk_gui(*model.objects[obj_idx], vol_idx); fix_model_by_win10_sdk_gui(*model.objects[obj_idx], vol_idx);
this->update(); this->update();
this->object_list_changed(); this->object_list_changed();
@ -3074,6 +3089,8 @@ void Plater::priv::on_action_layersediting(SimpleEvent&)
void Plater::priv::on_object_select(SimpleEvent& evt) void Plater::priv::on_object_select(SimpleEvent& evt)
{ {
// this->take_snapshot(_(L("Object Selection")));
wxGetApp().obj_list()->update_selections(); wxGetApp().obj_list()->update_selections();
selection_changed(); selection_changed();
} }
@ -3135,6 +3152,8 @@ void Plater::priv::on_right_click(Vec2dEvent& evt)
void Plater::priv::on_wipetower_moved(Vec3dEvent &evt) void Plater::priv::on_wipetower_moved(Vec3dEvent &evt)
{ {
this->take_snapshot(_(L("Wipe Tower Moved")));
DynamicPrintConfig cfg; DynamicPrintConfig cfg;
cfg.opt<ConfigOptionFloat>("wipe_tower_x", true)->value = evt.data(0); cfg.opt<ConfigOptionFloat>("wipe_tower_x", true)->value = evt.data(0);
cfg.opt<ConfigOptionFloat>("wipe_tower_y", true)->value = evt.data(1); cfg.opt<ConfigOptionFloat>("wipe_tower_y", true)->value = evt.data(1);
@ -3143,6 +3162,8 @@ void Plater::priv::on_wipetower_moved(Vec3dEvent &evt)
void Plater::priv::on_wipetower_rotated(Vec3dEvent& evt) void Plater::priv::on_wipetower_rotated(Vec3dEvent& evt)
{ {
this->take_snapshot(_(L("Wipe Tower Rotated")));
DynamicPrintConfig cfg; DynamicPrintConfig cfg;
cfg.opt<ConfigOptionFloat>("wipe_tower_x", true)->value = evt.data(0); cfg.opt<ConfigOptionFloat>("wipe_tower_x", true)->value = evt.data(0);
cfg.opt<ConfigOptionFloat>("wipe_tower_y", true)->value = evt.data(1); cfg.opt<ConfigOptionFloat>("wipe_tower_y", true)->value = evt.data(1);
@ -3514,7 +3535,9 @@ void Plater::priv::update_after_undo_redo()
this->update(false); // update volumes from the deserializd model this->update(false); // update volumes from the deserializd model
//YS_FIXME update obj_list from the deserialized model (maybe store ObjectIDs into the tree?) (no selections at this point of time) //YS_FIXME update obj_list from the deserialized model (maybe store ObjectIDs into the tree?) (no selections at this point of time)
this->view3D->get_canvas3d()->get_selection().set_deserialized(GUI::Selection::EMode(this->undo_redo_stack.selection_deserialized().mode), this->undo_redo_stack.selection_deserialized().volumes_and_instances); this->view3D->get_canvas3d()->get_selection().set_deserialized(GUI::Selection::EMode(this->undo_redo_stack.selection_deserialized().mode), this->undo_redo_stack.selection_deserialized().volumes_and_instances);
// wxGetApp().obj_list()->update_selections();
wxGetApp().obj_list()->recreate_object_list();
wxGetApp().obj_list()->update_selections();
// selection_changed(); // selection_changed();
//FIXME what about the state of the manipulators? //FIXME what about the state of the manipulators?
//FIXME what about the focus? Cursor in the side panel? //FIXME what about the focus? Cursor in the side panel?
@ -3580,6 +3603,8 @@ void Plater::add_model()
if (input_files.empty()) if (input_files.empty())
return; return;
this->take_snapshot(_(L("Add object(s)")));
std::vector<fs::path> input_paths; std::vector<fs::path> input_paths;
for (const auto &file : input_files) { for (const auto &file : input_files) {
input_paths.push_back(into_path(file)); input_paths.push_back(into_path(file));
@ -3717,6 +3742,8 @@ void Plater::set_number_of_copies(/*size_t num*/)
if (num < 0) if (num < 0)
return; return;
this->take_snapshot(wxString::Format(_(L("Set numbers of copies to %d")), num));
int diff = (int)num - (int)model_object->instances.size(); int diff = (int)num - (int)model_object->instances.size();
if (diff > 0) if (diff > 0)
increase_instances(diff); increase_instances(diff);
@ -3745,6 +3772,8 @@ void Plater::cut(size_t obj_idx, size_t instance_idx, coordf_t z, bool keep_uppe
return; return;
} }
this->take_snapshot(_(L("Cut")));
wxBusyCursor wait; wxBusyCursor wait;
const auto new_objects = object->cut(instance_idx, z, keep_upper, keep_lower, rotate_lower); const auto new_objects = object->cut(instance_idx, z, keep_upper, keep_lower, rotate_lower);
@ -4245,8 +4274,11 @@ void Plater::copy_selection_to_clipboard()
void Plater::paste_from_clipboard() void Plater::paste_from_clipboard()
{ {
if (can_paste_from_clipboard()) if (!can_paste_from_clipboard())
p->view3D->get_canvas3d()->get_selection().paste_from_clipboard(); return;
this->take_snapshot(_(L("Paste From Clipboard")));
p->view3D->get_canvas3d()->get_selection().paste_from_clipboard();
} }
void Plater::msw_rescale() void Plater::msw_rescale()

View file

@ -311,7 +311,7 @@ void Selection::add_all()
this->set_bounding_boxes_dirty(); this->set_bounding_boxes_dirty();
} }
void Selection::set_deserialized(EMode mode, const std::vector<std::pair<ObjectID, ObjectID>> &volumes_and_instances) void Selection::set_deserialized(EMode mode, const std::vector<std::pair<size_t, size_t>> &volumes_and_instances)
{ {
if (! m_valid) if (! m_valid)
return; return;
@ -320,11 +320,9 @@ void Selection::set_deserialized(EMode mode, const std::vector<std::pair<ObjectI
for (unsigned int i : m_list) for (unsigned int i : m_list)
(*m_volumes)[i]->selected = false; (*m_volumes)[i]->selected = false;
m_list.clear(); m_list.clear();
for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++ i) { for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++ i)
const GLVolume::CompositeID &id = (*m_volumes)[i]->composite_id; if (std::binary_search(volumes_and_instances.begin(), volumes_and_instances.end(), (*m_volumes)[i]->geometry_id))
if (std::binary_search(volumes_and_instances.begin(), volumes_and_instances.end(), std::make_pair<ObjectID, ObjectID>(id.volume_id, id.instance_id)))
this->do_add_volume(i); this->do_add_volume(i);
}
update_type(); update_type();
this->set_bounding_boxes_dirty(); this->set_bounding_boxes_dirty();
} }

View file

@ -238,7 +238,7 @@ public:
void add_all(); void add_all();
// To be called after Undo or Redo once the volumes are updated. // To be called after Undo or Redo once the volumes are updated.
void set_deserialized(EMode mode, const std::vector<std::pair<ObjectID, ObjectID>> &volumes_and_instances); void set_deserialized(EMode mode, const std::vector<std::pair<size_t, size_t>> &volumes_and_instances);
// Update the selection based on the new instance IDs. // Update the selection based on the new instance IDs.
void instances_changed(const std::vector<size_t> &instance_ids_selected); void instances_changed(const std::vector<size_t> &instance_ids_selected);

View file

@ -652,10 +652,8 @@ void StackImpl::take_snapshot(const std::string &snapshot_name, const Slic3r::Mo
m_selection.volumes_and_instances.clear(); m_selection.volumes_and_instances.clear();
m_selection.volumes_and_instances.reserve(selection.get_volume_idxs().size()); m_selection.volumes_and_instances.reserve(selection.get_volume_idxs().size());
m_selection.mode = selection.get_mode(); m_selection.mode = selection.get_mode();
for (unsigned int volume_idx : selection.get_volume_idxs()) { for (unsigned int volume_idx : selection.get_volume_idxs())
const Slic3r::GLVolume::CompositeID &id = selection.get_volume(volume_idx)->composite_id; m_selection.volumes_and_instances.emplace_back(selection.get_volume(volume_idx)->geometry_id);
m_selection.volumes_and_instances.emplace_back(id.volume_id, id.instance_id);
}
this->save_mutable_object<Selection, Selection>(m_selection); this->save_mutable_object<Selection, Selection>(m_selection);
// Save the snapshot info. // Save the snapshot info.
m_snapshots.emplace_back(snapshot_name, m_current_time ++, model.id().id); m_snapshots.emplace_back(snapshot_name, m_current_time ++, model.id().id);

View file

@ -31,8 +31,8 @@ struct Snapshot
// Excerpt of Slic3r::GUI::Selection for serialization onto the Undo / Redo stack. // Excerpt of Slic3r::GUI::Selection for serialization onto the Undo / Redo stack.
struct Selection : public Slic3r::ObjectBase { struct Selection : public Slic3r::ObjectBase {
unsigned char mode; unsigned char mode;
std::vector<std::pair<ObjectID, ObjectID>> volumes_and_instances; std::vector<std::pair<size_t, size_t>> volumes_and_instances;
template<class Archive> void serialize(Archive &ar) { ar(mode, volumes_and_instances); } template<class Archive> void serialize(Archive &ar) { ar(mode, volumes_and_instances); }
}; };