mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-30 12:11:15 -06:00 
			
		
		
		
	Update object list after undo/redo
This commit is contained in:
		
							parent
							
								
									1798e2a84c
								
							
						
					
					
						commit
						a29cc9e242
					
				
					 8 changed files with 89 additions and 19 deletions
				
			
		|  | @ -65,6 +65,11 @@ static int extruders_count() | |||
|     return wxGetApp().extruders_cnt(); | ||||
| } | ||||
| 
 | ||||
| static void take_snapshot(const wxString& snapshot_name) | ||||
| { | ||||
|     wxGetApp().plater()->take_snapshot(snapshot_name); | ||||
| } | ||||
| 
 | ||||
| ObjectList::ObjectList(wxWindow* parent) : | ||||
|     wxDataViewCtrl(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxDV_MULTIPLE), | ||||
|     m_parent(parent) | ||||
|  | @ -580,7 +585,6 @@ void ObjectList::paste_volumes_into_list(int obj_idx, const ModelVolumePtrs& vol | |||
|     if (volumes.empty()) | ||||
|         return; | ||||
| 
 | ||||
|     ModelObject& model_object = *(*m_objects)[obj_idx]; | ||||
|     const auto object_item = m_objects_model->GetItemById(obj_idx); | ||||
| 
 | ||||
|     wxDataViewItemArray items; | ||||
|  | @ -816,6 +820,7 @@ void ObjectList::OnDrop(wxDataViewEvent &event) | |||
| 
 | ||||
|     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()); | ||||
|         m_dragged_data.clear(); | ||||
|         return; | ||||
|  | @ -833,6 +838,8 @@ void ObjectList::OnDrop(wxDataViewEvent &event) | |||
| //     if (to_volume_id > from_volume_id) to_volume_id--;
 | ||||
| // #endif // __WXGTK__
 | ||||
| 
 | ||||
|     take_snapshot(_(L("Remov Volume(s)"))); | ||||
| 
 | ||||
|     auto& volumes = (*m_objects)[m_dragged_data.obj_idx()]->volumes; | ||||
|     auto delta = to_volume_id < from_volume_id ? -1 : 1; | ||||
|     int cnt = 0; | ||||
|  | @ -1427,6 +1434,8 @@ void ObjectList::load_subobject(ModelVolumeType type) | |||
|     if (m_objects_model->GetItemType(item)&itInstance) | ||||
|         item = m_objects_model->GetItemById(obj_idx); | ||||
| 
 | ||||
|     take_snapshot(_(L("Load Part"))); | ||||
| 
 | ||||
|     std::vector<std::pair<wxString, bool>> volumes_info; | ||||
|     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) | ||||
|         return; | ||||
| 
 | ||||
|     take_snapshot(_(L("Add Generic Subobject"))); | ||||
| 
 | ||||
|     // Selected object
 | ||||
|     ModelObject  &model_object = *(*m_objects)[obj_idx]; | ||||
|     // 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) | ||||
|         return; | ||||
| 
 | ||||
|     take_snapshot(_(L("Delete All Instances from Object"))); | ||||
| 
 | ||||
|     while ( instances.size()> 1) | ||||
|         instances.pop_back(); | ||||
| 
 | ||||
|  | @ -1645,6 +1658,8 @@ bool ObjectList::del_subobject_from_object(const int obj_idx, const int idx, con | |||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         take_snapshot(_(L("Delete Subobject"))); | ||||
| 
 | ||||
|         object->delete_volume(idx); | ||||
| 
 | ||||
|         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."))); | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         take_snapshot(_(L("Delete Instance"))); | ||||
|         object->delete_instance(idx); | ||||
|     } | ||||
|     else | ||||
|  | @ -1688,6 +1705,8 @@ void ObjectList::split() | |||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     take_snapshot(_(L("Split to Parts"))); | ||||
| 
 | ||||
|     wxBusyCursor wait; | ||||
| 
 | ||||
|     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)) ) | ||||
|         return; | ||||
| 
 | ||||
|     take_snapshot(_(L("Delete Selected Item"))); | ||||
| 
 | ||||
|     if (type&itObject) { | ||||
|         del_object(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) | ||||
|         return; | ||||
| 
 | ||||
|     take_snapshot(_(L("Paste from Clipboard"))); | ||||
| 
 | ||||
|     const auto item = GetSelection(); | ||||
|     volume->set_type(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(); | ||||
| } | ||||
| 
 | ||||
| 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 Slic3r 
 | ||||
|  | @ -300,6 +300,8 @@ public: | |||
| 
 | ||||
|     void msw_rescale(); | ||||
| 
 | ||||
|     void recreate_object_list(); | ||||
| 
 | ||||
| private: | ||||
| #ifdef __WXOSX__ | ||||
| //    void OnChar(wxKeyEvent& event);
 | ||||
|  |  | |||
|  | @ -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_INCREASE_INSTANCES, [this](Event<int> &evt)  | ||||
|         { 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_ROTATED, &priv::on_wipetower_rotated, this); | ||||
|     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() | ||||
| { | ||||
| //    this->take_snapshot(_(L("Select All")));
 | ||||
| 
 | ||||
|     view3D->select_all(); | ||||
|     this->sidebar->obj_list()->update_selections(); | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::deselect_all() | ||||
| { | ||||
| //    this->take_snapshot(_(L("Deselect All")));
 | ||||
|     view3D->deselect_all(); | ||||
| } | ||||
| 
 | ||||
| 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
 | ||||
|     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) | ||||
| { | ||||
| //    this->take_snapshot(_(L("Delete Object"))); // ys_FIXME What is the difference with "Remove Object"? 
 | ||||
|     model.delete_object(obj_idx); | ||||
|     update(); | ||||
|     object_list_changed(); | ||||
|  | @ -2398,17 +2405,20 @@ void Plater::priv::reset() | |||
| 
 | ||||
| void Plater::priv::mirror(Axis axis) | ||||
| { | ||||
|     this->take_snapshot(_(L("Mirror"))); | ||||
|     view3D->mirror_selection(axis); | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::arrange() | ||||
| { | ||||
|     this->take_snapshot(_(L("Arrange"))); | ||||
|     m_ui_jobs.start(Jobs::Arrange); | ||||
| } | ||||
| 
 | ||||
| // This method will find an optimal orientation for the currently selected item
 | ||||
| // Very similar in nature to the arrange method above...
 | ||||
| void Plater::priv::sla_optimize_rotation() { | ||||
|     this->take_snapshot(_(L("Optimize Rotation"))); | ||||
|     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."))); | ||||
|     else | ||||
|     { | ||||
|         this->take_snapshot(_(L("Split to Objects"))); | ||||
| 
 | ||||
|         unsigned int counter = 1; | ||||
|         for (ModelObject* m : new_objects) | ||||
|             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) | ||||
|         return; | ||||
| 
 | ||||
|     this->take_snapshot(_(L("Fix Throught NetFabb"))); | ||||
| 
 | ||||
|     fix_model_by_win10_sdk_gui(*model.objects[obj_idx], vol_idx); | ||||
|     this->update(); | ||||
|     this->object_list_changed(); | ||||
|  | @ -3074,6 +3089,8 @@ void Plater::priv::on_action_layersediting(SimpleEvent&) | |||
| 
 | ||||
| void Plater::priv::on_object_select(SimpleEvent& evt) | ||||
| { | ||||
| //    this->take_snapshot(_(L("Object Selection")));
 | ||||
| 
 | ||||
|     wxGetApp().obj_list()->update_selections(); | ||||
|     selection_changed(); | ||||
| } | ||||
|  | @ -3135,6 +3152,8 @@ void Plater::priv::on_right_click(Vec2dEvent& evt) | |||
| 
 | ||||
| void Plater::priv::on_wipetower_moved(Vec3dEvent &evt) | ||||
| { | ||||
|     this->take_snapshot(_(L("Wipe Tower Moved"))); | ||||
| 
 | ||||
|     DynamicPrintConfig cfg; | ||||
|     cfg.opt<ConfigOptionFloat>("wipe_tower_x", true)->value = evt.data(0); | ||||
|     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) | ||||
| { | ||||
|     this->take_snapshot(_(L("Wipe Tower Rotated"))); | ||||
| 
 | ||||
|     DynamicPrintConfig cfg; | ||||
|     cfg.opt<ConfigOptionFloat>("wipe_tower_x", true)->value = evt.data(0); | ||||
|     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
 | ||||
| 	//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); | ||||
| //	    wxGetApp().obj_list()->update_selections();
 | ||||
| 
 | ||||
|     wxGetApp().obj_list()->recreate_object_list(); | ||||
|     wxGetApp().obj_list()->update_selections(); | ||||
| //	    selection_changed();
 | ||||
| 	//FIXME what about the state of the manipulators?
 | ||||
| 	//FIXME what about the focus? Cursor in the side panel?
 | ||||
|  | @ -3580,6 +3603,8 @@ void Plater::add_model() | |||
|     if (input_files.empty()) | ||||
|         return; | ||||
| 
 | ||||
|     this->take_snapshot(_(L("Add object(s)"))); | ||||
| 
 | ||||
|     std::vector<fs::path> input_paths; | ||||
|     for (const auto &file : input_files) { | ||||
|         input_paths.push_back(into_path(file)); | ||||
|  | @ -3717,6 +3742,8 @@ void Plater::set_number_of_copies(/*size_t num*/) | |||
|     if (num < 0) | ||||
|         return; | ||||
| 
 | ||||
|     this->take_snapshot(wxString::Format(_(L("Set numbers of copies to %d")), num)); | ||||
| 
 | ||||
|     int diff = (int)num - (int)model_object->instances.size(); | ||||
|     if (diff > 0) | ||||
|         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; | ||||
|     } | ||||
| 
 | ||||
|     this->take_snapshot(_(L("Cut"))); | ||||
| 
 | ||||
|     wxBusyCursor wait; | ||||
|     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() | ||||
| { | ||||
|     if (can_paste_from_clipboard()) | ||||
|         p->view3D->get_canvas3d()->get_selection().paste_from_clipboard(); | ||||
|     if (!can_paste_from_clipboard()) | ||||
|         return; | ||||
| 
 | ||||
|     this->take_snapshot(_(L("Paste From Clipboard"))); | ||||
|     p->view3D->get_canvas3d()->get_selection().paste_from_clipboard(); | ||||
| } | ||||
| 
 | ||||
| void Plater::msw_rescale() | ||||
|  |  | |||
|  | @ -311,7 +311,7 @@ void Selection::add_all() | |||
|     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) | ||||
|         return; | ||||
|  | @ -320,11 +320,9 @@ void Selection::set_deserialized(EMode mode, const std::vector<std::pair<ObjectI | |||
|     for (unsigned int i : m_list) | ||||
|         (*m_volumes)[i]->selected = false; | ||||
|     m_list.clear(); | ||||
|     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(), std::make_pair<ObjectID, ObjectID>(id.volume_id, id.instance_id))) | ||||
|     for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++ i) | ||||
| 		if (std::binary_search(volumes_and_instances.begin(), volumes_and_instances.end(), (*m_volumes)[i]->geometry_id)) | ||||
| 			this->do_add_volume(i); | ||||
|     } | ||||
|     update_type(); | ||||
|     this->set_bounding_boxes_dirty(); | ||||
| } | ||||
|  |  | |||
|  | @ -238,7 +238,7 @@ public: | |||
|     void add_all(); | ||||
| 
 | ||||
|     // 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.
 | ||||
| 	void instances_changed(const std::vector<size_t> &instance_ids_selected); | ||||
|  |  | |||
|  | @ -566,10 +566,8 @@ void StackImpl::take_snapshot(const std::string &snapshot_name, const Slic3r::Mo | |||
| 	m_selection.volumes_and_instances.clear(); | ||||
| 	m_selection.volumes_and_instances.reserve(selection.get_volume_idxs().size()); | ||||
| 	m_selection.mode = selection.get_mode(); | ||||
| 	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(id.volume_id, id.instance_id); | ||||
| 	} | ||||
| 	for (unsigned int volume_idx : selection.get_volume_idxs()) | ||||
| 		m_selection.volumes_and_instances.emplace_back(selection.get_volume(volume_idx)->geometry_id); | ||||
| 	this->save_mutable_object<Selection, Selection>(m_selection); | ||||
| 	// Save the snapshot info.
 | ||||
| 	m_active_snapshot_time = m_current_time ++; | ||||
|  |  | |||
|  | @ -31,8 +31,8 @@ struct Snapshot | |||
| 
 | ||||
| // Excerpt of Slic3r::GUI::Selection for serialization onto the Undo / Redo stack.
 | ||||
| struct Selection : public Slic3r::ObjectBase { | ||||
| 	unsigned char								mode; | ||||
| 	std::vector<std::pair<ObjectID, ObjectID>>	volumes_and_instances; | ||||
| 	unsigned char							mode; | ||||
| 	std::vector<std::pair<size_t, size_t>>	volumes_and_instances; | ||||
| 	template<class Archive> void serialize(Archive &ar) { ar(mode, volumes_and_instances); } | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 YuSanka
						YuSanka