mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 12:41:20 -06:00 
			
		
		
		
	New Undo / Redo stack for the gizmos. The Gizmo specific stack is
entered with Plater::enter_gizmos_stack(), and left with Plater::enter_gizmos_stack(). Other than that, the 2nd Undo / Redo stack is transparent to the user of the Plater. WIP: Currently the Gizmo stack takes a snapshot of the whole scene on Plater::enter_gizmos_stack(). While it should work, it may be cheaper to modify the Undo/Redo stack to only take a snapshot of the gizmos in the Gizmo mode.
This commit is contained in:
		
							parent
							
								
									eefd950e16
								
							
						
					
					
						commit
						30d4bfd410
					
				
					 5 changed files with 94 additions and 34 deletions
				
			
		|  | @ -1335,12 +1335,7 @@ struct Plater::priv | |||
|     Slic3r::Model               model; | ||||
|     PrinterTechnology           printer_technology = ptFFF; | ||||
|     Slic3r::GCodePreviewData    gcode_preview_data; | ||||
|     Slic3r::UndoRedo::Stack 	undo_redo_stack; | ||||
|     int                         m_prevent_snapshots = 0;     /* Used for avoid of excess "snapshoting". 
 | ||||
|                                                               * Like for "delete selected" or "set numbers of copies" | ||||
|                                                               * we should call tack_snapshot just ones  | ||||
|                                                               * instead of calls for each action separately | ||||
|                                                               * */ | ||||
| 
 | ||||
|     // GUI elements
 | ||||
|     wxSizer* panel_sizer{ nullptr }; | ||||
|     wxPanel* current_panel{ nullptr }; | ||||
|  | @ -1785,9 +1780,16 @@ struct Plater::priv | |||
|     void split_volume(); | ||||
|     void scale_selection_to_fit_print_volume(); | ||||
| 
 | ||||
|     // Return the active Undo/Redo stack. It may be either the main stack or the Gimzo stack.
 | ||||
|     Slic3r::UndoRedo::Stack& undo_redo_stack() { assert(m_undo_redo_stack_active != nullptr); return *m_undo_redo_stack_active; } | ||||
|     Slic3r::UndoRedo::Stack& undo_redo_stack_main() { return m_undo_redo_stack_main; } | ||||
|     void enter_gizmos_stack(); | ||||
|     void leave_gizmos_stack(); | ||||
| 
 | ||||
| 	void take_snapshot(const std::string& snapshot_name); | ||||
| 	void take_snapshot(const wxString& snapshot_name) { this->take_snapshot(std::string(snapshot_name.ToUTF8().data())); } | ||||
|     int  get_active_snapshot_index(); | ||||
| 
 | ||||
|     void undo(); | ||||
|     void redo(); | ||||
|     void undo_redo_to(size_t time_to_load); | ||||
|  | @ -1889,7 +1891,15 @@ private: | |||
|     void update_after_undo_redo(bool temp_snapshot_was_taken = false); | ||||
| 
 | ||||
|     // path to project file stored with no extension
 | ||||
|     wxString m_project_filename; | ||||
|     wxString 					m_project_filename; | ||||
|     Slic3r::UndoRedo::Stack 	m_undo_redo_stack_main; | ||||
|     Slic3r::UndoRedo::Stack 	m_undo_redo_stack_gizmos; | ||||
|     Slic3r::UndoRedo::Stack    *m_undo_redo_stack_active = &m_undo_redo_stack_main; | ||||
|     int                         m_prevent_snapshots = 0;     /* Used for avoid of excess "snapshoting". 
 | ||||
|                                                               * Like for "delete selected" or "set numbers of copies" | ||||
|                                                               * we should call tack_snapshot just ones  | ||||
|                                                               * instead of calls for each action separately | ||||
|                                                               * */ | ||||
|     std::string m_last_fff_printer_profile_name; | ||||
|     std::string m_last_sla_printer_profile_name; | ||||
| }; | ||||
|  | @ -3712,10 +3722,32 @@ void Plater::priv::show_action_buttons(const bool is_ready_to_slice) const | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::enter_gizmos_stack() | ||||
| { | ||||
| 	assert(m_undo_redo_stack_active == &m_undo_redo_stack_main); | ||||
| 	if (m_undo_redo_stack_active == &m_undo_redo_stack_main) { | ||||
| 		m_undo_redo_stack_active = &m_undo_redo_stack_gizmos; | ||||
| 		assert(m_undo_redo_stack_active->empty()); | ||||
| 		// Take the initial snapshot of the gizmos.
 | ||||
| 		// Not localized on purpose, the text will never be shown to the user.
 | ||||
| 		this->take_snapshot(std::string("Gizmos-Initial")); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::leave_gizmos_stack() | ||||
| { | ||||
| 	assert(m_undo_redo_stack_active == &m_undo_redo_stack_gizmos); | ||||
| 	if (m_undo_redo_stack_active == &m_undo_redo_stack_gizmos) { | ||||
| 		assert(! m_undo_redo_stack_active->empty()); | ||||
| 		m_undo_redo_stack_active->clear(); | ||||
| 		m_undo_redo_stack_active = &m_undo_redo_stack_main; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| int Plater::priv::get_active_snapshot_index() | ||||
| { | ||||
|     const size_t active_snapshot_time = this->undo_redo_stack.active_snapshot_time(); | ||||
|     const std::vector<UndoRedo::Snapshot>& ss_stack = this->undo_redo_stack.snapshots(); | ||||
|     const size_t active_snapshot_time = this->undo_redo_stack().active_snapshot_time(); | ||||
|     const std::vector<UndoRedo::Snapshot>& ss_stack = this->undo_redo_stack().snapshots(); | ||||
|     const auto it = std::lower_bound(ss_stack.begin(), ss_stack.end(), UndoRedo::Snapshot(active_snapshot_time)); | ||||
|     return it - ss_stack.begin(); | ||||
| } | ||||
|  | @ -3746,32 +3778,32 @@ void Plater::priv::take_snapshot(const std::string& snapshot_name) | |||
|         model.wipe_tower.position = Vec2d(config.opt_float("wipe_tower_x"), config.opt_float("wipe_tower_y")); | ||||
|         model.wipe_tower.rotation = config.opt_float("wipe_tower_rotation_angle"); | ||||
|     } | ||||
|     this->undo_redo_stack.take_snapshot(snapshot_name, model, view3D->get_canvas3d()->get_selection(), view3D->get_canvas3d()->get_gizmos_manager(), snapshot_data); | ||||
|     this->undo_redo_stack.release_least_recently_used(); | ||||
|     this->undo_redo_stack().take_snapshot(snapshot_name, model, view3D->get_canvas3d()->get_selection(), view3D->get_canvas3d()->get_gizmos_manager(), snapshot_data); | ||||
|     this->undo_redo_stack().release_least_recently_used(); | ||||
|     // Save the last active preset name of a particular printer technology.
 | ||||
|     ((this->printer_technology == ptFFF) ? m_last_fff_printer_profile_name : m_last_sla_printer_profile_name) = wxGetApp().preset_bundle->printers.get_selected_preset_name(); | ||||
| 	BOOST_LOG_TRIVIAL(info) << "Undo / Redo snapshot taken: " << snapshot_name << ", Undo / Redo stack memory: " << Slic3r::format_memsize_MB(this->undo_redo_stack.memsize()) << log_memory_info(); | ||||
| 	BOOST_LOG_TRIVIAL(info) << "Undo / Redo snapshot taken: " << snapshot_name << ", Undo / Redo stack memory: " << Slic3r::format_memsize_MB(this->undo_redo_stack().memsize()) << log_memory_info(); | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::undo() | ||||
| { | ||||
| 	const std::vector<UndoRedo::Snapshot> &snapshots = this->undo_redo_stack.snapshots(); | ||||
| 	auto it_current = std::lower_bound(snapshots.begin(), snapshots.end(), UndoRedo::Snapshot(this->undo_redo_stack.active_snapshot_time())); | ||||
| 	const std::vector<UndoRedo::Snapshot> &snapshots = this->undo_redo_stack().snapshots(); | ||||
| 	auto it_current = std::lower_bound(snapshots.begin(), snapshots.end(), UndoRedo::Snapshot(this->undo_redo_stack().active_snapshot_time())); | ||||
| 	if (-- it_current != snapshots.begin()) | ||||
| 		this->undo_redo_to(it_current); | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::redo() | ||||
| {  | ||||
| 	const std::vector<UndoRedo::Snapshot> &snapshots = this->undo_redo_stack.snapshots(); | ||||
| 	auto it_current = std::lower_bound(snapshots.begin(), snapshots.end(), UndoRedo::Snapshot(this->undo_redo_stack.active_snapshot_time())); | ||||
| 	const std::vector<UndoRedo::Snapshot> &snapshots = this->undo_redo_stack().snapshots(); | ||||
| 	auto it_current = std::lower_bound(snapshots.begin(), snapshots.end(), UndoRedo::Snapshot(this->undo_redo_stack().active_snapshot_time())); | ||||
| 	if (++ it_current != snapshots.end()) | ||||
| 		this->undo_redo_to(it_current); | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::undo_redo_to(size_t time_to_load) | ||||
| { | ||||
| 	const std::vector<UndoRedo::Snapshot> &snapshots = this->undo_redo_stack.snapshots(); | ||||
| 	const std::vector<UndoRedo::Snapshot> &snapshots = this->undo_redo_stack().snapshots(); | ||||
| 	auto it_current = std::lower_bound(snapshots.begin(), snapshots.end(), UndoRedo::Snapshot(time_to_load)); | ||||
| 	assert(it_current != snapshots.end()); | ||||
| 	this->undo_redo_to(it_current); | ||||
|  | @ -3779,7 +3811,7 @@ void Plater::priv::undo_redo_to(size_t time_to_load) | |||
| 
 | ||||
| void Plater::priv::undo_redo_to(std::vector<UndoRedo::Snapshot>::const_iterator it_snapshot) | ||||
| { | ||||
| 	bool 				temp_snapshot_was_taken 	= this->undo_redo_stack.temp_snapshot_active(); | ||||
| 	bool 				temp_snapshot_was_taken 	= this->undo_redo_stack().temp_snapshot_active(); | ||||
| 	PrinterTechnology 	new_printer_technology 		= it_snapshot->snapshot_data.printer_technology; | ||||
| 	bool 				printer_technology_changed 	= this->printer_technology != new_printer_technology; | ||||
| 	if (printer_technology_changed) { | ||||
|  | @ -3825,9 +3857,9 @@ void Plater::priv::undo_redo_to(std::vector<UndoRedo::Snapshot>::const_iterator | |||
|     if (!new_variable_layer_editing_active && view3D->is_layers_editing_enabled()) | ||||
|         view3D->get_canvas3d()->force_main_toolbar_left_action(view3D->get_canvas3d()->get_main_toolbar_item_id("layersediting")); | ||||
|     // Do the jump in time.
 | ||||
|     if (it_snapshot->timestamp < this->undo_redo_stack.active_snapshot_time() ? | ||||
| 		this->undo_redo_stack.undo(model, this->view3D->get_canvas3d()->get_selection(), this->view3D->get_canvas3d()->get_gizmos_manager(), top_snapshot_data, it_snapshot->timestamp) : | ||||
| 		this->undo_redo_stack.redo(model, this->view3D->get_canvas3d()->get_gizmos_manager(), it_snapshot->timestamp)) { | ||||
|     if (it_snapshot->timestamp < this->undo_redo_stack().active_snapshot_time() ? | ||||
| 		this->undo_redo_stack().undo(model, this->view3D->get_canvas3d()->get_selection(), this->view3D->get_canvas3d()->get_gizmos_manager(), top_snapshot_data, it_snapshot->timestamp) : | ||||
| 		this->undo_redo_stack().redo(model, this->view3D->get_canvas3d()->get_gizmos_manager(), it_snapshot->timestamp)) { | ||||
| 		if (printer_technology_changed) { | ||||
| 			// Switch to the other printer technology. Switch to the last printer active for that particular technology.
 | ||||
| 		    AppConfig *app_config = wxGetApp().app_config; | ||||
|  | @ -3877,9 +3909,9 @@ void Plater::priv::update_after_undo_redo(bool /* temp_snapshot_was_taken */) | |||
| 	//if (temp_snapshot_was_taken)
 | ||||
| 	// Release the old snapshots always, as it may have happened, that some of the triangle meshes got deserialized from the snapshot, while some
 | ||||
| 	// triangle meshes may have gotten released from the scene or the background processing, therefore now being calculated into the Undo / Redo stack size.
 | ||||
| 		this->undo_redo_stack.release_least_recently_used(); | ||||
| 		this->undo_redo_stack().release_least_recently_used(); | ||||
| 	//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); | ||||
|     this->view3D->get_canvas3d()->get_gizmos_manager().update_after_undo_redo(); | ||||
| 
 | ||||
|     wxGetApp().obj_list()->update_after_undo_redo(); | ||||
|  | @ -3894,7 +3926,7 @@ void Plater::priv::update_after_undo_redo(bool /* temp_snapshot_was_taken */) | |||
| 	//FIXME what about the state of the manipulators?
 | ||||
| 	//FIXME what about the focus? Cursor in the side panel?
 | ||||
| 
 | ||||
|     BOOST_LOG_TRIVIAL(info) << "Undo / Redo snapshot reloaded. Undo / Redo stack memory: " << Slic3r::format_memsize_MB(this->undo_redo_stack.memsize()) << log_memory_info(); | ||||
|     BOOST_LOG_TRIVIAL(info) << "Undo / Redo snapshot reloaded. Undo / Redo stack memory: " << Slic3r::format_memsize_MB(this->undo_redo_stack().memsize()) << log_memory_info(); | ||||
| } | ||||
| 
 | ||||
| void Sidebar::set_btn_label(const ActionButtonType btn_type, const wxString& label) const | ||||
|  | @ -4453,7 +4485,7 @@ void Plater::undo_to(int selection) | |||
|     } | ||||
|      | ||||
|     const int idx = p->get_active_snapshot_index() - selection - 1; | ||||
|     p->undo_redo_to(p->undo_redo_stack.snapshots()[idx].timestamp); | ||||
|     p->undo_redo_to(p->undo_redo_stack().snapshots()[idx].timestamp); | ||||
| } | ||||
| void Plater::redo_to(int selection) | ||||
| { | ||||
|  | @ -4463,11 +4495,11 @@ void Plater::redo_to(int selection) | |||
|     } | ||||
|      | ||||
|     const int idx = p->get_active_snapshot_index() + selection + 1; | ||||
|     p->undo_redo_to(p->undo_redo_stack.snapshots()[idx].timestamp); | ||||
|     p->undo_redo_to(p->undo_redo_stack().snapshots()[idx].timestamp); | ||||
| } | ||||
| bool Plater::undo_redo_string_getter(const bool is_undo, int idx, const char** out_text) | ||||
| { | ||||
|     const std::vector<UndoRedo::Snapshot>& ss_stack = p->undo_redo_stack.snapshots(); | ||||
|     const std::vector<UndoRedo::Snapshot>& ss_stack = p->undo_redo_stack().snapshots(); | ||||
|     const int idx_in_ss_stack = p->get_active_snapshot_index() + (is_undo ? -(++idx) : idx); | ||||
| 
 | ||||
|     if (0 < idx_in_ss_stack && idx_in_ss_stack < ss_stack.size() - 1) { | ||||
|  | @ -4480,7 +4512,7 @@ bool Plater::undo_redo_string_getter(const bool is_undo, int idx, const char** o | |||
| 
 | ||||
| void Plater::undo_redo_topmost_string_getter(const bool is_undo, std::string& out_text) | ||||
| { | ||||
|     const std::vector<UndoRedo::Snapshot>& ss_stack = p->undo_redo_stack.snapshots(); | ||||
|     const std::vector<UndoRedo::Snapshot>& ss_stack = p->undo_redo_stack().snapshots(); | ||||
|     const int idx_in_ss_stack = p->get_active_snapshot_index() + (is_undo ? -1 : 0); | ||||
| 
 | ||||
|     if (0 < idx_in_ss_stack && idx_in_ss_stack < ss_stack.size() - 1) { | ||||
|  | @ -4785,9 +4817,11 @@ bool Plater::can_copy_to_clipboard() const | |||
|     return true; | ||||
| } | ||||
| 
 | ||||
| bool Plater::can_undo() const { return p->undo_redo_stack.has_undo_snapshot(); } | ||||
| bool Plater::can_redo() const { return p->undo_redo_stack.has_redo_snapshot(); } | ||||
| const UndoRedo::Stack& Plater::undo_redo_stack() const { return p->undo_redo_stack; } | ||||
| bool Plater::can_undo() const { return p->undo_redo_stack().has_undo_snapshot(); } | ||||
| bool Plater::can_redo() const { return p->undo_redo_stack().has_redo_snapshot(); } | ||||
| const UndoRedo::Stack& Plater::undo_redo_stack_main() const { return p->undo_redo_stack_main(); } | ||||
| void Plater::enter_gizmos_stack() { p->enter_gizmos_stack(); } | ||||
| void Plater::leave_gizmos_stack() { p->leave_gizmos_stack(); } | ||||
| 
 | ||||
| SuppressBackgroundProcessingUpdate::SuppressBackgroundProcessingUpdate() : | ||||
|     m_was_running(wxGetApp().plater()->is_background_process_running()) | ||||
|  |  | |||
|  | @ -197,7 +197,11 @@ public: | |||
|     void redo_to(int selection); | ||||
|     bool undo_redo_string_getter(const bool is_undo, int idx, const char** out_text); | ||||
|     void undo_redo_topmost_string_getter(const bool is_undo, std::string& out_text); | ||||
|     const Slic3r::UndoRedo::Stack& undo_redo_stack() const; | ||||
|     // For the memory statistics. 
 | ||||
|     const Slic3r::UndoRedo::Stack& undo_redo_stack_main() const; | ||||
|     // Enter / leave the Gizmos specific Undo / Redo stack. To be used by the SLA support point editing gizmo.
 | ||||
|     void enter_gizmos_stack(); | ||||
|     void leave_gizmos_stack(); | ||||
| 
 | ||||
|     void on_extruders_change(int extruders_count); | ||||
|     void on_config_change(const DynamicPrintConfig &config); | ||||
|  |  | |||
|  | @ -58,7 +58,7 @@ std::string get_mem_info(bool format_as_html) | |||
|     std::string b_end    = format_as_html ? "</b>" : ""; | ||||
|     std::string line_end = format_as_html ? "<br>" : "\n"; | ||||
| 
 | ||||
|     const Slic3r::UndoRedo::Stack &stack = wxGetApp().plater()->undo_redo_stack(); | ||||
|     const Slic3r::UndoRedo::Stack &stack = wxGetApp().plater()->undo_redo_stack_main(); | ||||
|     out << b_start << "RAM size reserved for the Undo / Redo stack [MB]: "  << b_end << Slic3r::format_memsize_MB(stack.get_memory_limit()) << line_end; | ||||
|     out << b_start << "RAM size occupied by the Undo / Redo stack  [MB]: "  << b_end << Slic3r::format_memsize_MB(stack.memsize()) << line_end << line_end; | ||||
| 
 | ||||
|  |  | |||
|  | @ -490,6 +490,21 @@ public: | |||
| 	// Initially enable Undo / Redo stack to occupy maximum 10% of the total system physical memory.
 | ||||
| 	StackImpl() : m_memory_limit(std::min(Slic3r::total_physical_memory() / 10, size_t(1 * 16384 * 65536 / UNDO_REDO_DEBUG_LOW_MEM_FACTOR))), m_active_snapshot_time(0), m_current_time(0) {} | ||||
| 
 | ||||
| 	void clear() { | ||||
| 		m_objects.clear(); | ||||
| 		m_shared_ptr_to_object_id.clear(); | ||||
| 		m_snapshots.clear(); | ||||
| 		m_active_snapshot_time = 0; | ||||
| 		m_current_time = 0; | ||||
| 		m_selection.clear(); | ||||
| 	} | ||||
| 
 | ||||
| 	bool empty() const { | ||||
| 		assert(m_objects.empty() == m_snapshots.empty()); | ||||
| 		assert(! m_objects.empty() || (m_current_time == 0 && m_active_snapshot_time == 0)); | ||||
| 		return m_snapshots.empty(); | ||||
| 	} | ||||
| 
 | ||||
| 	void set_memory_limit(size_t memsize) { m_memory_limit = memsize; } | ||||
| 	size_t get_memory_limit() const { return m_memory_limit; } | ||||
| 
 | ||||
|  | @ -1020,6 +1035,9 @@ void StackImpl::release_least_recently_used() | |||
| // Wrappers of the private implementation.
 | ||||
| Stack::Stack() : pimpl(new StackImpl()) {} | ||||
| Stack::~Stack() {} | ||||
| void Stack::clear() { pimpl->clear(); } | ||||
| bool Stack::empty() const { return pimpl->empty(); } | ||||
| 
 | ||||
| void Stack::set_memory_limit(size_t memsize) { pimpl->set_memory_limit(memsize); } | ||||
| size_t Stack::get_memory_limit() const { return pimpl->get_memory_limit(); } | ||||
| size_t Stack::memsize() const { return pimpl->memsize(); } | ||||
|  |  | |||
|  | @ -71,7 +71,8 @@ struct Snapshot | |||
| 
 | ||||
| // Excerpt of Slic3r::GUI::Selection for serialization onto the Undo / Redo stack.
 | ||||
| struct Selection : public Slic3r::ObjectBase { | ||||
| 	unsigned char							mode; | ||||
| 	void clear() { mode = 0; volumes_and_instances.clear(); } | ||||
| 	unsigned char							mode = 0; | ||||
| 	std::vector<std::pair<size_t, size_t>>	volumes_and_instances; | ||||
| 	template<class Archive> void serialize(Archive &ar) { ar(mode, volumes_and_instances); } | ||||
| }; | ||||
|  | @ -86,6 +87,9 @@ public: | |||
| 	Stack(); | ||||
| 	~Stack(); | ||||
| 
 | ||||
| 	void clear(); | ||||
| 	bool empty() const; | ||||
| 
 | ||||
| 	// Set maximum memory threshold. If the threshold is exceeded, least recently used snapshots are released.
 | ||||
| 	void set_memory_limit(size_t memsize); | ||||
| 	size_t get_memory_limit() const; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 bubnikv
						bubnikv