mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-30 12:11:15 -06:00 
			
		
		
		
	Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer into et_custom_bed
This commit is contained in:
		
						commit
						1b5ba6c823
					
				
					 18 changed files with 148 additions and 75 deletions
				
			
		|  | @ -157,7 +157,7 @@ public: | |||
|             change_analyzer_mm3_per_mm(len, e); | ||||
| 			// Width of a squished extrusion, corrected for the roundings of the squished extrusions.
 | ||||
| 			// This is left zero if it is a travel move.
 | ||||
| 			float width = float(double(e) * /*Filament_Area*/2.40528 / (len * m_layer_height)); | ||||
| 			float width = float(double(e) * m_filpar[0].filament_area / (len * m_layer_height)); | ||||
| 			// Correct for the roundings of a squished extrusion.
 | ||||
| 			width += m_layer_height * float(1. - M_PI / 4.); | ||||
| 			if (m_extrusions.empty() || m_extrusions.back().pos != rotated_current_pos) | ||||
|  | @ -822,7 +822,7 @@ void WipeTower::toolchange_Unload( | |||
|     while (i < m_filpar[m_current_tool].ramming_speed.size()) | ||||
|     { | ||||
|         const float x = volume_to_length(m_filpar[m_current_tool].ramming_speed[i] * 0.25f, line_width, m_layer_height); | ||||
|         const float e = m_filpar[m_current_tool].ramming_speed[i] * 0.25f / Filament_Area; // transform volume per sec to E move;
 | ||||
|         const float e = m_filpar[m_current_tool].ramming_speed[i] * 0.25f / filament_area(); // transform volume per sec to E move;
 | ||||
|         const float dist = std::min(x - e_done, remaining);		  // distance to travel for either the next 0.25s, or to the next turnaround
 | ||||
|         const float actual_time = dist/x * 0.25; | ||||
|         writer.ram(writer.x(), writer.x() + (m_left_to_right ? 1.f : -1.f) * dist, 0, 0, e * (dist / x), dist / (actual_time / 60.)); | ||||
|  |  | |||
|  | @ -111,7 +111,8 @@ public: | |||
| 	// Set the extruder properties.
 | ||||
| 	void set_extruder(size_t idx, std::string material, int temp, int first_layer_temp, float loading_speed, float loading_speed_start, | ||||
|                       float unloading_speed, float unloading_speed_start, float delay, int cooling_moves, | ||||
|                       float cooling_initial_speed, float cooling_final_speed, std::string ramming_parameters, float max_volumetric_speed, float nozzle_diameter) | ||||
|                       float cooling_initial_speed, float cooling_final_speed, std::string ramming_parameters, float max_volumetric_speed, | ||||
|                       float nozzle_diameter, float filament_diameter) | ||||
| 	{ | ||||
|         //while (m_filpar.size() < idx+1)   // makes sure the required element is in the vector
 | ||||
|         m_filpar.push_back(FilamentParameters()); | ||||
|  | @ -133,10 +134,12 @@ public: | |||
|             m_filpar[idx].cooling_final_speed     = cooling_final_speed; | ||||
|         } | ||||
| 
 | ||||
|         if (max_volumetric_speed != 0.f) | ||||
|             m_filpar[idx].max_e_speed = (max_volumetric_speed / Filament_Area); | ||||
|         m_filpar[idx].filament_area = (M_PI/4.f) * pow(filament_diameter, 2); // all extruders are assumed to have the same filament diameter at this point
 | ||||
|         m_filpar[idx].nozzle_diameter = nozzle_diameter; // to be used in future with (non-single) multiextruder MM
 | ||||
| 
 | ||||
|         if (max_volumetric_speed != 0.f) | ||||
|             m_filpar[idx].max_e_speed = (max_volumetric_speed / filament_area()); | ||||
| 
 | ||||
|         m_perimeter_width = nozzle_diameter * Width_To_Nozzle_Ratio; // all extruders are now assumed to have the same diameter
 | ||||
| 
 | ||||
|         if (m_semm) { | ||||
|  | @ -248,6 +251,7 @@ public: | |||
|         float               max_e_speed = std::numeric_limits<float>::max(); | ||||
|         std::vector<float>  ramming_speed; | ||||
|         float               nozzle_diameter; | ||||
|         float               filament_area; | ||||
|     }; | ||||
| 
 | ||||
| private: | ||||
|  | @ -261,9 +265,11 @@ private: | |||
| 
 | ||||
| 
 | ||||
|     const bool  m_peters_wipe_tower   = false; // sparse wipe tower inspired by Peter's post processor - not finished yet
 | ||||
|     const float Filament_Area         = float(M_PI * 1.75f * 1.75f / 4.f); // filament area in mm^2
 | ||||
|     const float Width_To_Nozzle_Ratio = 1.25f; // desired line width (oval) in multiples of nozzle diameter - may not be actually neccessary to adjust
 | ||||
|     const float WT_EPSILON            = 1e-3f; | ||||
|     const float filament_area() const { | ||||
|         return m_filpar[0].filament_area; // all extruders are assumed to have the same filament diameter at this point
 | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| 	bool   m_semm               = true; // Are we using a single extruder multimaterial printer?
 | ||||
|  | @ -315,7 +321,7 @@ private: | |||
| 	{ | ||||
| 		if ( layer_height < 0 ) | ||||
| 			return m_extrusion_flow; | ||||
| 		return layer_height * ( m_perimeter_width - layer_height * (1.f-float(M_PI)/4.f)) / Filament_Area; | ||||
| 		return layer_height * ( m_perimeter_width - layer_height * (1.f-float(M_PI)/4.f)) / filament_area(); | ||||
| 	} | ||||
| 
 | ||||
| 	// Calculates length of extrusion line to extrude given volume
 | ||||
|  |  | |||
|  | @ -1092,6 +1092,13 @@ std::string Print::validate() const | |||
|     } | ||||
| 
 | ||||
|     if (this->has_wipe_tower() && ! m_objects.empty()) { | ||||
|         // make sure all extruders use same diameter filament and have the same nozzle diameter
 | ||||
|         for (const auto& extruder_idx : extruders()) { | ||||
|             if (m_config.nozzle_diameter.get_at(extruder_idx) != m_config.nozzle_diameter.get_at(extruders().front()) | ||||
|              || m_config.filament_diameter.get_at(extruder_idx) != m_config.filament_diameter.get_at(extruders().front())) | ||||
|                  return L("The wipe tower is only supported if all extruders have the same nozzle diameter and use filaments of the same diameter."); | ||||
|         } | ||||
| 
 | ||||
|         if (m_config.gcode_flavor != gcfRepRap && m_config.gcode_flavor != gcfRepetier && m_config.gcode_flavor != gcfMarlin) | ||||
|             return L("The Wipe Tower is currently only supported for the Marlin, RepRap/Sprinter and Repetier G-code flavors."); | ||||
|         if (! m_config.use_relative_e_distances) | ||||
|  | @ -1701,7 +1708,8 @@ void Print::_make_wipe_tower() | |||
| 			(float)m_config.filament_cooling_final_speed.get_at(i), | ||||
|             m_config.filament_ramming_parameters.get_at(i), | ||||
|             m_config.filament_max_volumetric_speed.get_at(i), | ||||
|             m_config.nozzle_diameter.get_at(i)); | ||||
|             m_config.nozzle_diameter.get_at(i), | ||||
|             m_config.filament_diameter.get_at(i)); | ||||
| 
 | ||||
|     m_wipe_tower_data.priming = Slic3r::make_unique<std::vector<WipeTower::ToolChangeResult>>( | ||||
|         wipe_tower.prime((float)this->skirt_first_layer_height(), m_wipe_tower_data.tool_ordering.all_extruders(), false)); | ||||
|  |  | |||
|  | @ -172,7 +172,7 @@ extern std::string xml_escape(std::string text); | |||
| #if defined __GNUC__ && __GNUC__ < 5 && !defined __clang__ | ||||
| // Older GCCs don't have std::is_trivially_copyable
 | ||||
| // cf. https://gcc.gnu.org/onlinedocs/gcc-4.9.4/libstdc++/manual/manual/status.html#status.iso.2011
 | ||||
| #warning "GCC version < 5, faking std::is_trivially_copyable" | ||||
| // #warning "GCC version < 5, faking std::is_trivially_copyable"
 | ||||
| template<typename T> struct IsTriviallyCopyable { static constexpr bool value = true; }; | ||||
| #else | ||||
| template<typename T> struct IsTriviallyCopyable : public std::is_trivially_copyable<T> {}; | ||||
|  |  | |||
|  | @ -487,13 +487,15 @@ void ObjectList::update_name_in_model(const wxDataViewItem& item) const | |||
| { | ||||
|     const int obj_idx = m_objects_model->GetObjectIdByItem(item); | ||||
|     if (obj_idx < 0) return; | ||||
|     const int volume_id = m_objects_model->GetVolumeIdByItem(item); | ||||
| 
 | ||||
|     if (m_objects_model->GetParent(item) == wxDataViewItem(0)) { | ||||
|     take_snapshot(wxString::Format(_(L("Rename %s")), volume_id < 0 ? _(L("Object")) : _(L("Sub-object")))); | ||||
| 
 | ||||
|     if (m_objects_model->GetItemType(item) & itObject) { | ||||
|         (*m_objects)[obj_idx]->name = m_objects_model->GetName(item).ToUTF8().data(); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     const int volume_id = m_objects_model->GetVolumeIdByItem(item); | ||||
|     if (volume_id < 0) return; | ||||
|     (*m_objects)[obj_idx]->volumes[volume_id]->name = m_objects_model->GetName(item).ToUTF8().data(); | ||||
| } | ||||
|  | @ -925,7 +927,7 @@ void ObjectList::OnDrop(wxDataViewEvent &event) | |||
| 
 | ||||
|     if (m_dragged_data.type() == itInstance) | ||||
|     { | ||||
|         take_snapshot(_(L("Instances to Separated Objects"))); | ||||
|         Plater::TakeSnapshot snapshot(wxGetApp().plater(),_(L("Instances to Separated Objects"))); | ||||
|         instances_to_separated_object(m_dragged_data.obj_idx(), m_dragged_data.inst_idxs()); | ||||
|         m_dragged_data.clear(); | ||||
|         return; | ||||
|  | @ -943,7 +945,7 @@ void ObjectList::OnDrop(wxDataViewEvent &event) | |||
| //     if (to_volume_id > from_volume_id) to_volume_id--;
 | ||||
| // #endif // __WXGTK__
 | ||||
| 
 | ||||
|     take_snapshot(_(L("Remov Volume(s)"))); | ||||
|     take_snapshot(_(L("Remove Volume(s)"))); | ||||
| 
 | ||||
|     auto& volumes = (*m_objects)[m_dragged_data.obj_idx()]->volumes; | ||||
|     auto delta = to_volume_id < from_volume_id ? -1 : 1; | ||||
|  | @ -3055,7 +3057,7 @@ void ObjectList::change_part_type() | |||
| 	if (new_type == type || new_type == ModelVolumeType::INVALID) | ||||
|         return; | ||||
| 
 | ||||
|     take_snapshot(_(L("Paste from Clipboard"))); | ||||
|     take_snapshot(_(L("Change Part Type"))); | ||||
| 
 | ||||
|     const auto item = GetSelection(); | ||||
|     volume->set_type(new_type); | ||||
|  | @ -3294,6 +3296,8 @@ void ObjectList::split_instances() | |||
|     if (obj_idx == -1) | ||||
|         return; | ||||
| 
 | ||||
|     Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Instances to Separated Objects"))); | ||||
| 
 | ||||
|     if (selection.is_single_full_object()) | ||||
|     { | ||||
|         instances_to_separated_objects(obj_idx); | ||||
|  |  | |||
|  | @ -93,6 +93,7 @@ bool ObjectSettings::update_settings_list() | |||
|             btn->SetToolTip(_(L("Remove parameter"))); | ||||
| 
 | ||||
| 			btn->Bind(wxEVT_BUTTON, [opt_key, config, this](wxEvent &event) { | ||||
|                 wxGetApp().plater()->take_snapshot(wxString::Format(_(L("Delete Option %s")), opt_key)); | ||||
| 				config->erase(opt_key); | ||||
|                 wxGetApp().obj_list()->changed_object(); | ||||
|                 wxTheApp->CallAfter([this]() { | ||||
|  | @ -137,6 +138,13 @@ bool ObjectSettings::update_settings_list() | |||
|                 if (is_extruders_cat) | ||||
|                     option.opt.max = wxGetApp().extruders_edited_cnt(); | ||||
|                 optgroup->append_single_option_line(option); | ||||
| 
 | ||||
|                 optgroup->get_field(opt)->m_on_change = [optgroup](const std::string& opt_id, const boost::any& value) { | ||||
|                     // first of all take a snapshot and then change value in configuration
 | ||||
|                     wxGetApp().plater()->take_snapshot(wxString::Format(_(L("Change Option %s")), opt_id)); | ||||
|                     optgroup->on_change_OG(opt_id, value); | ||||
|                 }; | ||||
| 
 | ||||
|             } | ||||
|             optgroup->reload_config(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -166,7 +166,7 @@ void GLGizmoBase::set_highlight_color(const float* color) | |||
| 
 | ||||
| void GLGizmoBase::enable_grabber(unsigned int id) | ||||
| { | ||||
|     if ((0 <= id) && (id < (unsigned int)m_grabbers.size())) | ||||
|     if (id < m_grabbers.size()) | ||||
|         m_grabbers[id].enabled = true; | ||||
| 
 | ||||
|     on_enable_grabber(id); | ||||
|  | @ -174,7 +174,7 @@ void GLGizmoBase::enable_grabber(unsigned int id) | |||
| 
 | ||||
| void GLGizmoBase::disable_grabber(unsigned int id) | ||||
| { | ||||
|     if ((0 <= id) && (id < (unsigned int)m_grabbers.size())) | ||||
|     if (id < m_grabbers.size()) | ||||
|         m_grabbers[id].enabled = false; | ||||
| 
 | ||||
|     on_disable_grabber(id); | ||||
|  |  | |||
|  | @ -93,19 +93,19 @@ protected: | |||
|     } | ||||
|     virtual void on_set_hover_id() | ||||
|     { | ||||
|         for (unsigned int i = 0; i < 3; ++i) | ||||
|         for (int i = 0; i < 3; ++i) | ||||
|         { | ||||
|             m_gizmos[i].set_hover_id((m_hover_id == i) ? 0 : -1); | ||||
|         } | ||||
|     } | ||||
|     virtual void on_enable_grabber(unsigned int id) | ||||
|     { | ||||
|         if ((0 <= id) && (id < 3)) | ||||
|         if (id < 3) | ||||
|             m_gizmos[id].enable_grabber(0); | ||||
|     } | ||||
|     virtual void on_disable_grabber(unsigned int id) | ||||
|     { | ||||
|         if ((0 <= id) && (id < 3)) | ||||
|         if (id < 3) | ||||
|             m_gizmos[id].disable_grabber(0); | ||||
|     } | ||||
|     virtual void on_start_dragging(); | ||||
|  |  | |||
|  | @ -82,7 +82,9 @@ void GLGizmoSlaSupports::set_sla_support_data(ModelObject* model_object, const S | |||
|             editing_mode_reload_cache(); | ||||
|         } | ||||
| 
 | ||||
|         if (m_editing_mode_cache.empty() && m_model_object->sla_points_status != sla::PointsStatus::UserModified) | ||||
|         if (m_editing_mode_cache.empty() | ||||
|          && m_model_object->sla_points_status != sla::PointsStatus::UserModified | ||||
|          && m_model_object->sla_points_status != sla::PointsStatus::None) | ||||
|             get_data_from_backend(); | ||||
| 
 | ||||
|         if (m_state == On) { | ||||
|  | @ -1122,9 +1124,13 @@ void GLGizmoSlaSupports::on_start_dragging() | |||
| 
 | ||||
| void GLGizmoSlaSupports::on_load(cereal::BinaryInputArchive& ar) | ||||
| { | ||||
|     if (m_editing_mode) | ||||
|         editing_mode_discard_changes(); | ||||
| 
 | ||||
|     ar(m_clipping_plane_distance, | ||||
|        m_clipping_plane_normal, | ||||
|        m_current_mesh_object_id | ||||
|        m_current_mesh_object_id, | ||||
|        m_editing_mode_cache | ||||
|     ); | ||||
| } | ||||
| 
 | ||||
|  | @ -1134,7 +1140,8 @@ void GLGizmoSlaSupports::on_save(cereal::BinaryOutputArchive& ar) const | |||
| { | ||||
|     ar(m_clipping_plane_distance, | ||||
|        m_clipping_plane_normal, | ||||
|        m_current_mesh_object_id | ||||
|        m_current_mesh_object_id, | ||||
|        m_editing_mode_cache | ||||
|     ); | ||||
| } | ||||
| 
 | ||||
|  | @ -1177,16 +1184,16 @@ void GLGizmoSlaSupports::editing_mode_discard_changes() | |||
|     // If the points were autogenerated, they may not be on the ModelObject yet.
 | ||||
|     // Because the user probably messed with the cache, we will get the data
 | ||||
|     // from the backend again.
 | ||||
| 
 | ||||
|     if (m_model_object->sla_points_status == sla::PointsStatus::AutoGenerated) | ||||
|     /*if (m_model_object->sla_points_status == sla::PointsStatus::AutoGenerated) {
 | ||||
|         get_data_from_backend(); | ||||
|     else { | ||||
|         m_editing_mode_cache.clear(); | ||||
|         for (const sla::SupportPoint& point : m_model_object->sla_support_points) | ||||
|             m_editing_mode_cache.emplace_back(point, false); | ||||
|     } | ||||
|         m_editing_mode = false; | ||||
|         m_unsaved_changes = false; | ||||
|         } | ||||
|     else | ||||
|         editing_mode_reload_cache();*/ | ||||
| 
 | ||||
|     m_editing_mode_cache = m_old_cache; | ||||
| 
 | ||||
|     m_editing_mode = false; | ||||
|     m_unsaved_changes = false; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -1196,7 +1203,13 @@ void GLGizmoSlaSupports::editing_mode_apply_changes() | |||
|     // If there are no changes, don't touch the front-end. The data in the cache could have been
 | ||||
|     // taken from the backend and copying them to ModelObject would needlessly invalidate them.
 | ||||
|     if (m_unsaved_changes) { | ||||
|         // In order to make the undo/redo snapshot, we must first temporarily restore
 | ||||
|         // the editing cache to the state before the edits were made.
 | ||||
|         std::vector<CacheEntry> backup = m_editing_mode_cache; | ||||
|         m_editing_mode_cache = m_old_cache; | ||||
|         wxGetApp().plater()->take_snapshot(_(L("Support points edit"))); | ||||
|         m_editing_mode_cache = std::move(backup); | ||||
| 
 | ||||
|         m_model_object->sla_points_status = sla::PointsStatus::UserModified; | ||||
|         m_model_object->sla_support_points.clear(); | ||||
|         for (const CacheEntry& cache_entry : m_editing_mode_cache) | ||||
|  | @ -1216,6 +1229,7 @@ void GLGizmoSlaSupports::editing_mode_apply_changes() | |||
| void GLGizmoSlaSupports::editing_mode_reload_cache() | ||||
| { | ||||
|     m_editing_mode_cache.clear(); | ||||
| 
 | ||||
|     for (const sla::SupportPoint& point : m_model_object->sla_support_points) | ||||
|         m_editing_mode_cache.emplace_back(point, false); | ||||
| 
 | ||||
|  | @ -1271,6 +1285,8 @@ void GLGizmoSlaSupports::switch_to_editing_mode() | |||
|         editing_mode_reload_cache(); | ||||
|     m_unsaved_changes = false; | ||||
|     m_editing_mode = true; | ||||
|     m_old_cache = m_editing_mode_cache; | ||||
|     select_point(NoPoints); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -98,6 +98,8 @@ private: | |||
|     float m_new_point_head_diameter;        // Size of a new point.
 | ||||
|     float m_minimal_point_distance = 20.f; | ||||
|     mutable std::vector<CacheEntry> m_editing_mode_cache; // a support point and whether it is currently selected
 | ||||
|     std::vector<CacheEntry> m_old_cache; // to restore after discarding changes or undo/redo
 | ||||
| 
 | ||||
|     float m_clipping_plane_distance = 0.f; | ||||
|     mutable float m_old_clipping_plane_distance = 0.f; | ||||
|     mutable Vec3d m_old_clipping_plane_normal; | ||||
|  |  | |||
|  | @ -223,7 +223,7 @@ void GLGizmosManager::update_data() | |||
|     enable_grabber(Rotate, 1, !is_wipe_tower); | ||||
| 
 | ||||
|     bool enable_scale_xyz = selection.is_single_full_instance() || selection.is_single_volume() || selection.is_single_modifier(); | ||||
|     for (int i = 0; i < 6; ++i) | ||||
|     for (unsigned int i = 0; i < 6; ++i) | ||||
|     { | ||||
|         enable_grabber(Scale, i, enable_scale_xyz); | ||||
|     } | ||||
|  |  | |||
|  | @ -3733,9 +3733,10 @@ void Plater::priv::take_snapshot(const std::string& snapshot_name) | |||
|     if (this->m_prevent_snapshots > 0)  | ||||
|         return; | ||||
|     assert(this->m_prevent_snapshots >= 0); | ||||
|     unsigned int flags = 0; | ||||
|     UndoRedo::SnapshotData snapshot_data; | ||||
|     snapshot_data.printer_technology = this->printer_technology; | ||||
|     if (this->view3D->is_layers_editing_enabled()) | ||||
|     	flags |= UndoRedo::Snapshot::VARIABLE_LAYER_EDITING_ACTIVE; | ||||
|     	snapshot_data.flags |= UndoRedo::SnapshotData::VARIABLE_LAYER_EDITING_ACTIVE; | ||||
|     //FIXME updating the Wipe tower config values at the ModelWipeTower from the Print config.
 | ||||
|     // This is a workaround until we refactor the Wipe Tower position / orientation to live solely inside the Model, not in the Print config.
 | ||||
|     if (this->printer_technology == ptFFF) { | ||||
|  | @ -3743,7 +3744,7 @@ 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(), this->printer_technology, flags); | ||||
|     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(); | ||||
|  | @ -3777,11 +3778,11 @@ 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(); | ||||
| 	PrinterTechnology 	new_printer_technology 		= it_snapshot->printer_technology; | ||||
| 	PrinterTechnology 	new_printer_technology 		= it_snapshot->snapshot_data.printer_technology; | ||||
| 	bool 				printer_technology_changed 	= this->printer_technology != new_printer_technology; | ||||
| 	if (printer_technology_changed) { | ||||
| 		// Switching the printer technology when jumping forwards / backwards in time. Switch to the last active printer profile of the other type.
 | ||||
| 		std::string s_pt = (it_snapshot->printer_technology == ptFFF) ? "FFF" : "SLA"; | ||||
| 		std::string s_pt = (it_snapshot->snapshot_data.printer_technology == ptFFF) ? "FFF" : "SLA"; | ||||
| 		if (! wxGetApp().check_unsaved_changes(from_u8((boost::format(_utf8( | ||||
| 			L("%1% printer was active at the time the target Undo / Redo snapshot was taken. Switching to %1% printer requires reloading of %1% presets."))) % s_pt).str()))) | ||||
| 			// Don't switch the profiles.
 | ||||
|  | @ -3797,17 +3798,18 @@ void Plater::priv::undo_redo_to(std::vector<UndoRedo::Snapshot>::const_iterator | |||
|                 model.wipe_tower.rotation = config.opt_float("wipe_tower_rotation_angle"); | ||||
|     } | ||||
|     // Flags made of Snapshot::Flags enum values.
 | ||||
|     unsigned int new_flags = it_snapshot->flags; | ||||
| 	unsigned int top_snapshot_flags = 0; | ||||
|     unsigned int new_flags = it_snapshot->snapshot_data.flags; | ||||
| 	UndoRedo::SnapshotData top_snapshot_data; | ||||
|     top_snapshot_data.printer_technology = this->printer_technology; | ||||
|     if (this->view3D->is_layers_editing_enabled()) | ||||
|     	top_snapshot_flags |= UndoRedo::Snapshot::VARIABLE_LAYER_EDITING_ACTIVE; | ||||
| 	bool   		 new_variable_layer_editing_active = (new_flags & UndoRedo::Snapshot::VARIABLE_LAYER_EDITING_ACTIVE) != 0; | ||||
|     	top_snapshot_data.flags |= UndoRedo::SnapshotData::VARIABLE_LAYER_EDITING_ACTIVE; | ||||
| 	bool   		 new_variable_layer_editing_active = (new_flags & UndoRedo::SnapshotData::VARIABLE_LAYER_EDITING_ACTIVE) != 0; | ||||
| 	// Disable layer editing before the Undo / Redo jump.
 | ||||
|     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(), this->printer_technology, top_snapshot_flags, it_snapshot->timestamp) : | ||||
| 		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.
 | ||||
|  | @ -3910,8 +3912,6 @@ void Plater::load_project() | |||
|     // Ask user for a project file name.
 | ||||
|     wxString input_file; | ||||
|     wxGetApp().load_project(this, input_file); | ||||
|     // Take the Undo / Redo snapshot.
 | ||||
| 	Plater::TakeSnapshot snapshot(this, _(L("Load Project")) + ": " + wxString::FromUTF8(into_path(input_file).stem().string().c_str())); | ||||
|     // And finally load the new project.
 | ||||
|     load_project(input_file); | ||||
| } | ||||
|  | @ -3921,6 +3921,9 @@ void Plater::load_project(const wxString& filename) | |||
|     if (filename.empty()) | ||||
|         return; | ||||
| 
 | ||||
|     // Take the Undo / Redo snapshot.
 | ||||
|     Plater::TakeSnapshot snapshot(this, _(L("Load Project")) + ": " + wxString::FromUTF8(into_path(filename).stem().string().c_str())); | ||||
| 
 | ||||
|     p->reset(); | ||||
|     p->set_project_filename(filename); | ||||
| 
 | ||||
|  |  | |||
|  | @ -323,9 +323,9 @@ public: | |||
| 	} | ||||
| 
 | ||||
| 	bool SwapChildrens(int frst_id, int scnd_id) { | ||||
| 		if (GetChildCount() < 2 ||  | ||||
| 			frst_id < 0 || frst_id >= GetChildCount() ||  | ||||
| 			scnd_id < 0 || scnd_id >= GetChildCount()) | ||||
| 		if (GetChildCount() < 2 || | ||||
| 			frst_id < 0 || (size_t)frst_id >= GetChildCount() || | ||||
| 			scnd_id < 0 || (size_t)scnd_id >= GetChildCount()) | ||||
| 			return false; | ||||
| 
 | ||||
| 		ObjectDataViewModelNode new_scnd = *GetNthChild(frst_id); | ||||
|  |  | |||
|  | @ -17,6 +17,7 @@ | |||
| #define CEREAL_FUTURE_EXPERIMENTAL | ||||
| #include <cereal/archives/adapters.hpp> | ||||
| 
 | ||||
| #include <libslic3r/Config.hpp> | ||||
| #include <libslic3r/ObjectID.hpp> | ||||
| #include <libslic3r/Utils.hpp> | ||||
| 
 | ||||
|  | @ -35,6 +36,10 @@ | |||
| namespace Slic3r { | ||||
| namespace UndoRedo { | ||||
| 
 | ||||
| SnapshotData::SnapshotData() : printer_technology(ptUnknown), flags(0) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| static std::string topmost_snapshot_name = "@@@ Topmost @@@"; | ||||
| 
 | ||||
| bool Snapshot::is_topmost() const | ||||
|  | @ -496,12 +501,12 @@ public: | |||
| 	} | ||||
| 
 | ||||
|     // Store the current application state onto the Undo / Redo stack, remove all snapshots after m_active_snapshot_time.
 | ||||
|     void take_snapshot(const std::string& snapshot_name, const Slic3r::Model& model, const Slic3r::GUI::Selection& selection, const Slic3r::GUI::GLGizmosManager& gizmos, Slic3r::PrinterTechnology printer_technology, unsigned int flags); | ||||
|     void take_snapshot(const std::string& snapshot_name, const Slic3r::Model& model, const Slic3r::GUI::Selection& selection, const Slic3r::GUI::GLGizmosManager& gizmos, const SnapshotData &snapshot_data); | ||||
|     void load_snapshot(size_t timestamp, Slic3r::Model& model, Slic3r::GUI::GLGizmosManager& gizmos); | ||||
| 
 | ||||
| 	bool has_undo_snapshot() const; | ||||
| 	bool has_redo_snapshot() const; | ||||
|     bool undo(Slic3r::Model &model, const Slic3r::GUI::Selection &selection, Slic3r::GUI::GLGizmosManager &gizmos, PrinterTechnology printer_technology, unsigned int flags, size_t jump_to_time); | ||||
|     bool undo(Slic3r::Model &model, const Slic3r::GUI::Selection &selection, Slic3r::GUI::GLGizmosManager &gizmos, const SnapshotData &snapshot_data, size_t jump_to_time); | ||||
|     bool redo(Slic3r::Model &model, Slic3r::GUI::GLGizmosManager &gizmos, size_t jump_to_time); | ||||
| 	void release_least_recently_used(); | ||||
| 
 | ||||
|  | @ -786,7 +791,7 @@ template<typename T> void StackImpl::load_mutable_object(const Slic3r::ObjectID | |||
| } | ||||
| 
 | ||||
| // Store the current application state onto the Undo / Redo stack, remove all snapshots after m_active_snapshot_time.
 | ||||
| void StackImpl::take_snapshot(const std::string& snapshot_name, const Slic3r::Model& model, const Slic3r::GUI::Selection& selection, const Slic3r::GUI::GLGizmosManager& gizmos, Slic3r::PrinterTechnology printer_technology, unsigned int flags) | ||||
| void StackImpl::take_snapshot(const std::string& snapshot_name, const Slic3r::Model& model, const Slic3r::GUI::Selection& selection, const Slic3r::GUI::GLGizmosManager& gizmos, const SnapshotData &snapshot_data) | ||||
| { | ||||
| 	// Release old snapshot data.
 | ||||
| 	assert(m_active_snapshot_time <= m_current_time); | ||||
|  | @ -806,11 +811,11 @@ void StackImpl::take_snapshot(const std::string& snapshot_name, const Slic3r::Mo | |||
| 	this->save_mutable_object<Selection>(m_selection); | ||||
|     this->save_mutable_object<Slic3r::GUI::GLGizmosManager>(gizmos); | ||||
|     // Save the snapshot info.
 | ||||
| 	m_snapshots.emplace_back(snapshot_name, m_current_time ++, model.id().id, printer_technology, flags); | ||||
| 	m_snapshots.emplace_back(snapshot_name, m_current_time ++, model.id().id, snapshot_data); | ||||
| 	m_active_snapshot_time = m_current_time; | ||||
| 	// Save snapshot info of the last "current" aka "top most" state, that is only being serialized
 | ||||
| 	// if undoing an action. Such a snapshot has an invalid Model ID assigned if it was not taken yet.
 | ||||
| 	m_snapshots.emplace_back(topmost_snapshot_name, m_active_snapshot_time, 0, printer_technology, flags); | ||||
| 	m_snapshots.emplace_back(topmost_snapshot_name, m_active_snapshot_time, 0, snapshot_data); | ||||
| 	// Release empty objects from the history.
 | ||||
| 	this->collect_garbage(); | ||||
| 	assert(this->valid()); | ||||
|  | @ -856,7 +861,7 @@ bool StackImpl::has_redo_snapshot() const | |||
| 	return ++ it != m_snapshots.end(); | ||||
| } | ||||
| 
 | ||||
| bool StackImpl::undo(Slic3r::Model &model, const Slic3r::GUI::Selection &selection, Slic3r::GUI::GLGizmosManager &gizmos, PrinterTechnology printer_technology, unsigned int flags, size_t time_to_load) | ||||
| bool StackImpl::undo(Slic3r::Model &model, const Slic3r::GUI::Selection &selection, Slic3r::GUI::GLGizmosManager &gizmos, const SnapshotData &snapshot_data, size_t time_to_load) | ||||
| { | ||||
| 	assert(this->valid()); | ||||
| 	if (time_to_load == SIZE_MAX) { | ||||
|  | @ -870,7 +875,7 @@ bool StackImpl::undo(Slic3r::Model &model, const Slic3r::GUI::Selection &selecti | |||
| 	bool new_snapshot_taken = false; | ||||
| 	if (m_active_snapshot_time == m_snapshots.back().timestamp && ! m_snapshots.back().is_topmost_captured()) { | ||||
| 		// The current state is temporary. The current state needs to be captured to be redoable.
 | ||||
|         this->take_snapshot(topmost_snapshot_name, model, selection, gizmos, printer_technology, flags); | ||||
|         this->take_snapshot(topmost_snapshot_name, model, selection, gizmos, snapshot_data); | ||||
|         // The line above entered another topmost_snapshot_name.
 | ||||
| 		assert(m_snapshots.back().is_topmost()); | ||||
| 		assert(! m_snapshots.back().is_topmost_captured()); | ||||
|  | @ -1019,12 +1024,12 @@ 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(); } | ||||
| void Stack::release_least_recently_used() { pimpl->release_least_recently_used(); } | ||||
| void Stack::take_snapshot(const std::string& snapshot_name, const Slic3r::Model& model, const Slic3r::GUI::Selection& selection, const Slic3r::GUI::GLGizmosManager& gizmos, Slic3r::PrinterTechnology printer_technology, unsigned int flags) | ||||
| 	{ pimpl->take_snapshot(snapshot_name, model, selection, gizmos, printer_technology, flags); } | ||||
| void Stack::take_snapshot(const std::string& snapshot_name, const Slic3r::Model& model, const Slic3r::GUI::Selection& selection, const Slic3r::GUI::GLGizmosManager& gizmos, const SnapshotData &snapshot_data) | ||||
| 	{ pimpl->take_snapshot(snapshot_name, model, selection, gizmos, snapshot_data); } | ||||
| bool Stack::has_undo_snapshot() const { return pimpl->has_undo_snapshot(); } | ||||
| bool Stack::has_redo_snapshot() const { return pimpl->has_redo_snapshot(); } | ||||
| bool Stack::undo(Slic3r::Model& model, const Slic3r::GUI::Selection& selection, Slic3r::GUI::GLGizmosManager& gizmos, PrinterTechnology printer_technology, unsigned int flags, size_t time_to_load) | ||||
| 	{ return pimpl->undo(model, selection, gizmos, printer_technology, flags, time_to_load); } | ||||
| bool Stack::undo(Slic3r::Model& model, const Slic3r::GUI::Selection& selection, Slic3r::GUI::GLGizmosManager& gizmos, const SnapshotData &snapshot_data, size_t time_to_load) | ||||
| 	{ return pimpl->undo(model, selection, gizmos, snapshot_data, time_to_load); } | ||||
| bool Stack::redo(Slic3r::Model& model, Slic3r::GUI::GLGizmosManager& gizmos, size_t time_to_load) { return pimpl->redo(model, gizmos, time_to_load); } | ||||
| const Selection& Stack::selection_deserialized() const { return pimpl->selection_deserialized(); } | ||||
| 
 | ||||
|  |  | |||
|  | @ -21,23 +21,36 @@ namespace GUI { | |||
| 
 | ||||
| namespace UndoRedo { | ||||
| 
 | ||||
| struct Snapshot | ||||
| // Data structure to be stored with each snapshot.
 | ||||
| // Storing short data (bit masks, ints) with each snapshot instead of being serialized into the Undo / Redo stack
 | ||||
| // is likely cheaper in term of both the runtime and memory allocation.
 | ||||
| // Also the SnapshotData is available without having to deserialize the snapshot from the Undo / Redo stack,
 | ||||
| // which may be handy sometimes.
 | ||||
| struct SnapshotData | ||||
| { | ||||
| 	Snapshot(size_t timestamp) : timestamp(timestamp) {} | ||||
| 	Snapshot(const std::string &name, size_t timestamp, size_t model_id, Slic3r::PrinterTechnology printer_technology, unsigned int flags) : | ||||
| 		name(name), timestamp(timestamp), model_id(model_id), printer_technology(printer_technology), flags(flags) {} | ||||
| 	// Constructor is defined in .cpp due to the forward declaration of enum PrinterTechnology.
 | ||||
| 	SnapshotData(); | ||||
| 
 | ||||
| 	PrinterTechnology 	printer_technology; | ||||
| 	// Bitmap of Flags (see the Flags enum).
 | ||||
| 	unsigned int        flags; | ||||
| 
 | ||||
| 	// Bitmask of various binary flags to be stored with the snapshot.
 | ||||
| 	enum Flags { | ||||
| 		VARIABLE_LAYER_EDITING_ACTIVE = 1, | ||||
| 	}; | ||||
| }; | ||||
| 
 | ||||
| struct Snapshot | ||||
| { | ||||
| 	Snapshot(size_t timestamp) : timestamp(timestamp) {} | ||||
| 	Snapshot(const std::string &name, size_t timestamp, size_t model_id, const SnapshotData &snapshot_data) : | ||||
| 		name(name), timestamp(timestamp), model_id(model_id), snapshot_data(snapshot_data) {} | ||||
| 	 | ||||
| 	std::string 		name; | ||||
| 	size_t 				timestamp; | ||||
| 	size_t 				model_id; | ||||
| 	PrinterTechnology 	printer_technology; | ||||
| 	// Bitmap of Flags (see the Flags enum).
 | ||||
| 	unsigned int        flags; | ||||
| 	SnapshotData  		snapshot_data; | ||||
| 
 | ||||
| 	bool		operator< (const Snapshot &rhs) const { return this->timestamp < rhs.timestamp; } | ||||
| 	bool		operator==(const Snapshot &rhs) const { return this->timestamp == rhs.timestamp; } | ||||
|  | @ -77,7 +90,7 @@ public: | |||
| 	void release_least_recently_used(); | ||||
| 
 | ||||
| 	// Store the current application state onto the Undo / Redo stack, remove all snapshots after m_active_snapshot_time.
 | ||||
|     void take_snapshot(const std::string& snapshot_name, const Slic3r::Model& model, const Slic3r::GUI::Selection& selection, const Slic3r::GUI::GLGizmosManager& gizmos, Slic3r::PrinterTechnology printer_technology, unsigned int flags); | ||||
|     void take_snapshot(const std::string& snapshot_name, const Slic3r::Model& model, const Slic3r::GUI::Selection& selection, const Slic3r::GUI::GLGizmosManager& gizmos, const SnapshotData &snapshot_data); | ||||
| 
 | ||||
| 	// To be queried to enable / disable the Undo / Redo buttons at the UI.
 | ||||
| 	bool has_undo_snapshot() const; | ||||
|  | @ -85,7 +98,7 @@ public: | |||
| 
 | ||||
| 	// Roll back the time. If time_to_load is SIZE_MAX, the previous snapshot is activated.
 | ||||
| 	// Undoing an action may need to take a snapshot of the current application state, so that redo to the current state is possible.
 | ||||
|     bool undo(Slic3r::Model& model, const Slic3r::GUI::Selection& selection, Slic3r::GUI::GLGizmosManager& gizmos, PrinterTechnology printer_technology, unsigned int flags, size_t time_to_load = SIZE_MAX); | ||||
|     bool undo(Slic3r::Model& model, const Slic3r::GUI::Selection& selection, Slic3r::GUI::GLGizmosManager& gizmos, const SnapshotData &snapshot_data, size_t time_to_load = SIZE_MAX); | ||||
| 
 | ||||
| 	// Jump forward in time. If time_to_load is SIZE_MAX, the next snapshot is activated.
 | ||||
|     bool redo(Slic3r::Model& model, Slic3r::GUI::GLGizmosManager& gizmos, size_t time_to_load = SIZE_MAX); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Enrico Turri
						Enrico Turri