Merge remote-tracking branch 'remotes/origin/lm_sla_gizmo_snapshots_supports'

This commit is contained in:
bubnikv 2019-08-23 12:56:47 +02:00
commit 007a5301eb
6 changed files with 158 additions and 59 deletions

View file

@ -528,7 +528,7 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
if (m_selection_empty) { if (m_selection_empty) {
std::pair<Vec3f, Vec3f> pos_and_normal; std::pair<Vec3f, Vec3f> pos_and_normal;
if (unproject_on_mesh(mouse_position, pos_and_normal)) { // we got an intersection if (unproject_on_mesh(mouse_position, pos_and_normal)) { // we got an intersection
wxGetApp().plater()->take_snapshot(_(L("Add support point"))); Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Add support point")));
m_editing_cache.emplace_back(sla::SupportPoint(pos_and_normal.first, m_new_point_head_diameter/2.f, false), false, pos_and_normal.second); m_editing_cache.emplace_back(sla::SupportPoint(pos_and_normal.first, m_new_point_head_diameter/2.f, false), false, pos_and_normal.second);
m_parent.set_as_dirty(); m_parent.set_as_dirty();
m_wait_for_up_event = true; m_wait_for_up_event = true;
@ -716,14 +716,12 @@ void GLGizmoSlaSupports::delete_selected_points(bool force)
std::abort(); std::abort();
} }
wxGetApp().plater()->take_snapshot(_(L("Delete support point"))); Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Delete support point")));
for (unsigned int idx=0; idx<m_editing_cache.size(); ++idx) { for (unsigned int idx=0; idx<m_editing_cache.size(); ++idx) {
if (m_editing_cache[idx].selected && (!m_editing_cache[idx].support_point.is_new_island || !m_lock_unique_islands || force)) { if (m_editing_cache[idx].selected && (!m_editing_cache[idx].support_point.is_new_island || !m_lock_unique_islands || force)) {
m_editing_cache.erase(m_editing_cache.begin() + (idx--)); m_editing_cache.erase(m_editing_cache.begin() + (idx--));
} }
// This should trigger the support generation
// wxGetApp().plater()->reslice_SLA_supports(*m_model_object);
} }
select_point(NoPoints); select_point(NoPoints);
@ -919,7 +917,7 @@ RENDER_AGAIN:
cache_entry.support_point.head_front_radius = m_old_point_head_diameter / 2.f; cache_entry.support_point.head_front_radius = m_old_point_head_diameter / 2.f;
float backup = m_new_point_head_diameter; float backup = m_new_point_head_diameter;
m_new_point_head_diameter = m_old_point_head_diameter; m_new_point_head_diameter = m_old_point_head_diameter;
wxGetApp().plater()->take_snapshot(_(L("Change point head diameter"))); Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Change point head diameter")));
m_new_point_head_diameter = backup; m_new_point_head_diameter = backup;
for (auto& cache_entry : m_editing_cache) for (auto& cache_entry : m_editing_cache)
if (cache_entry.selected) if (cache_entry.selected)
@ -985,7 +983,7 @@ RENDER_AGAIN:
if (slider_released) { if (slider_released) {
m_model_object->config.opt<ConfigOptionFloat>("support_points_minimal_distance", true)->value = m_minimal_point_distance_stash; m_model_object->config.opt<ConfigOptionFloat>("support_points_minimal_distance", true)->value = m_minimal_point_distance_stash;
m_model_object->config.opt<ConfigOptionInt>("support_points_density_relative", true)->value = (int)m_density_stash; m_model_object->config.opt<ConfigOptionInt>("support_points_density_relative", true)->value = (int)m_density_stash;
wxGetApp().plater()->take_snapshot(_(L("Support parameter change"))); Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Support parameter change")));
m_model_object->config.opt<ConfigOptionFloat>("support_points_minimal_distance", true)->value = minimal_point_distance; m_model_object->config.opt<ConfigOptionFloat>("support_points_minimal_distance", true)->value = minimal_point_distance;
m_model_object->config.opt<ConfigOptionInt>("support_points_density_relative", true)->value = (int)density; m_model_object->config.opt<ConfigOptionInt>("support_points_density_relative", true)->value = (int)density;
wxGetApp().obj_list()->update_and_show_object_settings_item(); wxGetApp().obj_list()->update_and_show_object_settings_item();
@ -1100,6 +1098,9 @@ std::string GLGizmoSlaSupports::on_get_name() const
void GLGizmoSlaSupports::on_set_state() void GLGizmoSlaSupports::on_set_state()
{ {
if (m_state == Hover)
return;
// m_model_object pointer can be invalid (for instance because of undo/redo action), // m_model_object pointer can be invalid (for instance because of undo/redo action),
// we should recover it from the object id // we should recover it from the object id
m_model_object = nullptr; m_model_object = nullptr;
@ -1111,6 +1112,7 @@ void GLGizmoSlaSupports::on_set_state()
} }
if (m_state == On && m_old_state != On) { // the gizmo was just turned on if (m_state == On && m_old_state != On) { // the gizmo was just turned on
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("SLA gizmo turned on")));
if (is_mesh_update_necessary()) if (is_mesh_update_necessary())
update_mesh(); update_mesh();
@ -1127,21 +1129,26 @@ void GLGizmoSlaSupports::on_set_state()
m_new_point_head_diameter = static_cast<const ConfigOptionFloat*>(cfg.option("support_head_front_diameter"))->value; m_new_point_head_diameter = static_cast<const ConfigOptionFloat*>(cfg.option("support_head_front_diameter"))->value;
} }
if (m_state == Off && m_old_state != Off) { // the gizmo was just turned Off if (m_state == Off && m_old_state != Off) { // the gizmo was just turned Off
bool will_ask = m_model_object && m_editing_mode && unsaved_changes();
if (will_ask) {
wxGetApp().CallAfter([this]() { wxGetApp().CallAfter([this]() {
// Following is called through CallAfter, because otherwise there was a problem // Following is called through CallAfter, because otherwise there was a problem
// on OSX with the wxMessageDialog being shown several times when clicked into. // on OSX with the wxMessageDialog being shown several times when clicked into.
if (m_model_object) { wxMessageDialog dlg(GUI::wxGetApp().mainframe, _(L("Do you want to save your manually "
if (m_editing_mode && unsaved_changes()) { "edited support points?")) + "\n",_(L("Save changes?")), wxICON_QUESTION | wxYES | wxNO);
wxMessageDialog dlg(GUI::wxGetApp().mainframe, _(L("Do you want to save your manually edited support points?")) + "\n",
_(L("Save changes?")), wxICON_QUESTION | wxYES | wxNO);
if (dlg.ShowModal() == wxID_YES) if (dlg.ShowModal() == wxID_YES)
editing_mode_apply_changes(); editing_mode_apply_changes();
else else
editing_mode_discard_changes(); editing_mode_discard_changes();
});
// refuse to be turned off so the gizmo is active when the CallAfter is executed
m_state = m_old_state;
} }
} else {
m_parent.toggle_model_objects_visibility(true); // we are actually shutting down
disable_editing_mode(); // so it is not active next time the gizmo opens disable_editing_mode(); // so it is not active next time the gizmo opens
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("SLA gizmo turned off")));
m_parent.toggle_model_objects_visibility(true);
m_normal_cache.clear(); m_normal_cache.clear();
m_clipping_plane_distance = 0.f; m_clipping_plane_distance = 0.f;
// Release triangle mesh slicer and the AABB spatial search structure. // Release triangle mesh slicer and the AABB spatial search structure.
@ -1149,7 +1156,7 @@ void GLGizmoSlaSupports::on_set_state()
m_its = nullptr; m_its = nullptr;
m_tms.reset(); m_tms.reset();
m_supports_tms.reset(); m_supports_tms.reset();
}); }
} }
m_old_state = m_state; m_old_state = m_state;
} }
@ -1177,7 +1184,7 @@ void GLGizmoSlaSupports::on_stop_dragging()
&& backup.support_point.pos != m_point_before_drag.support_point.pos) // and it was moved, not just selected && backup.support_point.pos != m_point_before_drag.support_point.pos) // and it was moved, not just selected
{ {
m_editing_cache[m_hover_id] = m_point_before_drag; m_editing_cache[m_hover_id] = m_point_before_drag;
wxGetApp().plater()->take_snapshot(_(L("Move support point"))); Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Move support point")));
m_editing_cache[m_hover_id] = backup; m_editing_cache[m_hover_id] = backup;
} }
} }
@ -1276,7 +1283,7 @@ void GLGizmoSlaSupports::editing_mode_apply_changes()
disable_editing_mode(); // this leaves the editing mode undo/redo stack and must be done before the snapshot is taken disable_editing_mode(); // this leaves the editing mode undo/redo stack and must be done before the snapshot is taken
if (unsaved_changes()) { if (unsaved_changes()) {
wxGetApp().plater()->take_snapshot(_(L("Support points edit"))); Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Support points edit")));
m_normal_cache.clear(); m_normal_cache.clear();
for (const CacheEntry& ce : m_editing_cache) for (const CacheEntry& ce : m_editing_cache)
@ -1286,7 +1293,7 @@ void GLGizmoSlaSupports::editing_mode_apply_changes()
m_model_object->sla_support_points.clear(); m_model_object->sla_support_points.clear();
m_model_object->sla_support_points = m_normal_cache; m_model_object->sla_support_points = m_normal_cache;
wxGetApp().CallAfter([this]() { wxGetApp().plater()->reslice_SLA_supports(*m_model_object); }); reslice_SLA_supports();
} }
} }
@ -1303,11 +1310,29 @@ void GLGizmoSlaSupports::reload_cache()
} }
bool GLGizmoSlaSupports::has_backend_supports() const
{
// find SlaPrintObject with this ID
for (const SLAPrintObject* po : m_parent.sla_print()->objects()) {
if (po->model_object()->id() == m_model_object->id() && po->is_step_done(slaposSupportPoints))
return true;
}
return false;
}
void GLGizmoSlaSupports::reslice_SLA_supports() const
{
wxGetApp().CallAfter([this]() { wxGetApp().plater()->reslice_SLA_supports(*m_model_object); });
}
void GLGizmoSlaSupports::get_data_from_backend() void GLGizmoSlaSupports::get_data_from_backend()
{ {
if (! has_backend_supports())
return;
// find the respective SLAPrintObject, we need a pointer to it
for (const SLAPrintObject* po : m_parent.sla_print()->objects()) { for (const SLAPrintObject* po : m_parent.sla_print()->objects()) {
if (po->model_object()->id() == m_model_object->id() && po->is_step_done(slaposSupportPoints)) { if (po->model_object()->id() == m_model_object->id()) {
m_normal_cache.clear(); m_normal_cache.clear();
const std::vector<sla::SupportPoint>& points = po->get_support_points(); const std::vector<sla::SupportPoint>& points = po->get_support_points();
auto mat = po->trafo().inverse().cast<float>(); auto mat = po->trafo().inverse().cast<float>();
@ -1332,8 +1357,8 @@ void GLGizmoSlaSupports::auto_generate()
)), _(L("Warning")), wxICON_WARNING | wxYES | wxNO); )), _(L("Warning")), wxICON_WARNING | wxYES | wxNO);
if (m_model_object->sla_points_status != sla::PointsStatus::UserModified || m_normal_cache.empty() || dlg.ShowModal() == wxID_YES) { if (m_model_object->sla_points_status != sla::PointsStatus::UserModified || m_normal_cache.empty() || dlg.ShowModal() == wxID_YES) {
wxGetApp().plater()->take_snapshot(_(L("Autogenerate support points"))); Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Autogenerate support points")));
wxGetApp().CallAfter([this]() { wxGetApp().plater()->reslice_SLA_supports(*m_model_object); }); wxGetApp().CallAfter([this]() { reslice_SLA_supports(); });
m_model_object->sla_points_status = sla::PointsStatus::Generating; m_model_object->sla_points_status = sla::PointsStatus::Generating;
} }
} }

View file

@ -86,6 +86,8 @@ public:
bool is_in_editing_mode() const { return m_editing_mode; } bool is_in_editing_mode() const { return m_editing_mode; }
bool is_selection_rectangle_dragging() const { return m_selection_rectangle.is_dragging(); } bool is_selection_rectangle_dragging() const { return m_selection_rectangle.is_dragging(); }
bool has_backend_supports() const;
void reslice_SLA_supports() const;
private: private:
bool on_init(); bool on_init();
@ -101,6 +103,8 @@ private:
void update_cache_entry_normal(unsigned int i) const; void update_cache_entry_normal(unsigned int i) const;
bool unsaved_changes() const; bool unsaved_changes() const;
EState m_no_hover_state = Off;
EState m_no_hover_old_state = Off;
bool m_lock_unique_islands = false; bool m_lock_unique_islands = false;
bool m_editing_mode = false; // Is editing mode active? bool m_editing_mode = false; // Is editing mode active?
bool m_old_editing_state = false; // To keep track of whether the user toggled between the modes (needed for imgui refreshes). bool m_old_editing_state = false; // To keep track of whether the user toggled between the modes (needed for imgui refreshes).

View file

@ -5,6 +5,7 @@
#include "slic3r/GUI/GUI_App.hpp" #include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/GUI_ObjectManipulation.hpp" #include "slic3r/GUI/GUI_ObjectManipulation.hpp"
#include "slic3r/GUI/PresetBundle.hpp" #include "slic3r/GUI/PresetBundle.hpp"
#include "slic3r/Utils/UndoRedo.hpp"
#include <GL/glew.h> #include <GL/glew.h>
#include <wx/glcanvas.h> #include <wx/glcanvas.h>
@ -280,8 +281,8 @@ bool GLGizmosManager::handle_shortcut(int key)
if (m_parent.get_selection().is_empty()) if (m_parent.get_selection().is_empty())
return false; return false;
EType old_current = m_current;
bool handled = false; bool handled = false;
for (GizmosMap::iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) for (GizmosMap::iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
{ {
if ((it->second == nullptr) || !it->second->is_selectable()) if ((it->second == nullptr) || !it->second->is_selectable())
@ -294,25 +295,34 @@ bool GLGizmosManager::handle_shortcut(int key)
if ((it->second->get_state() == GLGizmoBase::On)) if ((it->second->get_state() == GLGizmoBase::On))
{ {
it->second->set_state(GLGizmoBase::Off); it->second->set_state(GLGizmoBase::Off);
if (it->second->get_state() == GLGizmoBase::Off) {
m_current = Undefined; m_current = Undefined;
}
handled = true; handled = true;
} }
else if ((it->second->get_state() == GLGizmoBase::Off)) else if ((it->second->get_state() == GLGizmoBase::Off))
{ {
// Before turning anything on, turn everything else off to see if
// nobody refuses. Only then activate the gizmo.
bool can_open = true;
for (GizmosMap::iterator i = m_gizmos.begin(); i != m_gizmos.end(); ++i) {
if (i->first != it->first) {
if (m_current == i->first && i->second->get_state() != GLGizmoBase::Off ) {
i->second->set_state(GLGizmoBase::Off);
if (i->second->get_state() != GLGizmoBase::Off)
can_open = false;
}
}
}
if (can_open) {
it->second->set_state(GLGizmoBase::On); it->second->set_state(GLGizmoBase::On);
m_current = it->first; m_current = it->first;
}
handled = true; handled = true;
} }
} }
} }
if (handled && (old_current != Undefined) && (old_current != m_current))
{
GizmosMap::const_iterator it = m_gizmos.find(old_current);
if (it != m_gizmos.end())
it->second->set_state(GLGizmoBase::Off);
}
return handled; return handled;
} }
@ -455,6 +465,11 @@ ClippingPlane GLGizmosManager::get_sla_clipping_plane() const
return ClippingPlane::ClipsNothing(); return ClippingPlane::ClipsNothing();
} }
bool GLGizmosManager::wants_reslice_supports_on_undo() const
{
return (m_current == SlaSupports
&& dynamic_cast<const GLGizmoSlaSupports*>(m_gizmos.at(SlaSupports))->has_backend_supports());
}
void GLGizmosManager::render_current_gizmo() const void GLGizmosManager::render_current_gizmo() const
{ {
@ -861,10 +876,13 @@ bool GLGizmosManager::on_key(wxKeyEvent& evt)
return processed; return processed;
} }
void GLGizmosManager::update_after_undo_redo() void GLGizmosManager::update_after_undo_redo(const UndoRedo::Snapshot& snapshot)
{ {
update_data(); update_data();
m_serializing = false; m_serializing = false;
if (m_current == SlaSupports
&& snapshot.snapshot_data.flags & UndoRedo::SnapshotData::RECALCULATE_SLA_SUPPORTS)
dynamic_cast<GLGizmoSlaSupports*>(m_gizmos[SlaSupports])->reslice_SLA_supports();
} }
void GLGizmosManager::reset() void GLGizmosManager::reset()
@ -1065,35 +1083,66 @@ void GLGizmosManager::update_on_off_state(const Vec2d& mouse_pos)
float scaled_stride_y = scaled_icons_size + scaled_gap_y; float scaled_stride_y = scaled_icons_size + scaled_gap_y;
float top_y = 0.5f * (cnv_h - height) + scaled_border; float top_y = 0.5f * (cnv_h - height) + scaled_border;
for (GizmosMap::iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) auto inside = [scaled_border, scaled_icons_size, &mouse_pos](float top_y) {
return (scaled_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= scaled_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size);
};
bool could_activate = true;
for (std::pair<const GLGizmosManager::EType, GLGizmoBase*> &type_and_gizmo : m_gizmos)
{ {
if ((it->second == nullptr) || !it->second->is_selectable()) GLGizmoBase *gizmo = type_and_gizmo.second;
if ((gizmo == nullptr) || !gizmo->is_selectable())
continue; continue;
bool inside = (scaled_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= scaled_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size); if (! (gizmo->is_activable() && inside(top_y))) {
if (it->second->is_activable() && inside) gizmo->set_state(GLGizmoBase::Off);
{ if (gizmo->get_state() != GLGizmoBase::Off) {
if ((it->second->get_state() == GLGizmoBase::On)) // Gizmo refused to leave it's active state. Don't try to select
{ could_activate = false;
it->second->set_state(GLGizmoBase::Hover);
m_current = Undefined;
}
else if ((it->second->get_state() == GLGizmoBase::Hover))
{
it->second->set_state(GLGizmoBase::On);
m_current = it->first;
} }
} }
else
it->second->set_state(GLGizmoBase::Off);
top_y += scaled_stride_y; top_y += scaled_stride_y;
} }
// We may change m_current soon. If we did it during following loop, gizmos that take undo/redo snapshots
// in their on_set_state function could snapshot a state with the new gizmo already active.
// Therefore, just remember what needs to be done and actually change m_current afterwards.
EType new_current = m_current;
top_y = 0.5f * (cnv_h - height) + scaled_border;
for (std::pair<const GLGizmosManager::EType, GLGizmoBase*> &type_and_gizmo : m_gizmos)
{
GLGizmoBase *gizmo = type_and_gizmo.second;
if ((gizmo == nullptr) || !gizmo->is_selectable())
continue;
if (gizmo->is_activable() && inside(top_y))
{
if ((gizmo->get_state() == GLGizmoBase::On))
{
gizmo->set_state(GLGizmoBase::Off);
if (gizmo->get_state() == GLGizmoBase::Off) {
gizmo->set_state(GLGizmoBase::Hover);
new_current = Undefined;
}
}
else if ((gizmo->get_state() == GLGizmoBase::Hover) && could_activate)
{
gizmo->set_state(GLGizmoBase::On);
new_current = type_and_gizmo.first;
}
}
top_y += scaled_stride_y;
}
m_current = new_current;
if (could_activate) {
GizmosMap::iterator it = m_gizmos.find(m_current); GizmosMap::iterator it = m_gizmos.find(m_current);
if ((it != m_gizmos.end()) && (it->second != nullptr) && (it->second->get_state() != GLGizmoBase::On)) if ((it != m_gizmos.end()) && (it->second != nullptr) && (it->second->get_state() != GLGizmoBase::On))
it->second->set_state(GLGizmoBase::On); it->second->set_state(GLGizmoBase::On);
} }
}
std::string GLGizmosManager::update_hover_state(const Vec2d& mouse_pos) std::string GLGizmosManager::update_hover_state(const Vec2d& mouse_pos)
{ {

View file

@ -9,6 +9,11 @@
#include <map> #include <map>
namespace Slic3r { namespace Slic3r {
namespace UndoRedo {
struct Snapshot;
}
namespace GUI { namespace GUI {
class GLCanvas3D; class GLCanvas3D;
@ -173,6 +178,7 @@ public:
void set_sla_support_data(ModelObject* model_object); void set_sla_support_data(ModelObject* model_object);
bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position = Vec2d::Zero(), bool shift_down = false, bool alt_down = false, bool control_down = false); bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position = Vec2d::Zero(), bool shift_down = false, bool alt_down = false, bool control_down = false);
ClippingPlane get_sla_clipping_plane() const; ClippingPlane get_sla_clipping_plane() const;
bool wants_reslice_supports_on_undo() const;
void render_current_gizmo() const; void render_current_gizmo() const;
void render_current_gizmo_for_picking_pass() const; void render_current_gizmo_for_picking_pass() const;
@ -186,7 +192,7 @@ public:
bool on_char(wxKeyEvent& evt); bool on_char(wxKeyEvent& evt);
bool on_key(wxKeyEvent& evt); bool on_key(wxKeyEvent& evt);
void update_after_undo_redo(); void update_after_undo_redo(const UndoRedo::Snapshot& snapshot);
private: private:
void reset(); void reset();

View file

@ -1908,7 +1908,7 @@ private:
void update_fff_scene(); void update_fff_scene();
void update_sla_scene(); void update_sla_scene();
void undo_redo_to(std::vector<UndoRedo::Snapshot>::const_iterator it_snapshot); void undo_redo_to(std::vector<UndoRedo::Snapshot>::const_iterator it_snapshot);
void update_after_undo_redo(bool temp_snapshot_was_taken = false); void update_after_undo_redo(const UndoRedo::Snapshot& snapshot, bool temp_snapshot_was_taken = false);
// path to project file stored with no extension // path to project file stored with no extension
wxString m_project_filename; wxString m_project_filename;
@ -3823,6 +3823,12 @@ void Plater::priv::take_snapshot(const std::string& snapshot_name)
} }
else if (this->sidebar->obj_list()->is_selected(itLayerRoot)) else if (this->sidebar->obj_list()->is_selected(itLayerRoot))
snapshot_data.flags |= UndoRedo::SnapshotData::SELECTED_LAYERROOT_ON_SIDEBAR; snapshot_data.flags |= UndoRedo::SnapshotData::SELECTED_LAYERROOT_ON_SIDEBAR;
// If SLA gizmo is active, ask it if it wants to trigger support generation
// on loading this snapshot.
if (view3D->get_canvas3d()->get_gizmos_manager().wants_reslice_supports_on_undo())
snapshot_data.flags |= UndoRedo::SnapshotData::RECALCULATE_SLA_SUPPORTS;
//FIXME updating the Wipe tower config values at the ModelWipeTower from the Print config. //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. // 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) { if (this->printer_technology == ptFFF) {
@ -3863,6 +3869,9 @@ 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) void Plater::priv::undo_redo_to(std::vector<UndoRedo::Snapshot>::const_iterator it_snapshot)
{ {
// Make sure that no updating function calls take_snapshot until we are done.
SuppressSnapshots snapshot_supressor(q);
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; PrinterTechnology new_printer_technology = it_snapshot->snapshot_data.printer_technology;
bool printer_technology_changed = this->printer_technology != new_printer_technology; bool printer_technology_changed = this->printer_technology != new_printer_technology;
@ -3905,9 +3914,14 @@ void Plater::priv::undo_redo_to(std::vector<UndoRedo::Snapshot>::const_iterator
bool new_selected_layer_on_sidebar = (new_flags & UndoRedo::SnapshotData::SELECTED_LAYER_ON_SIDEBAR) != 0; bool new_selected_layer_on_sidebar = (new_flags & UndoRedo::SnapshotData::SELECTED_LAYER_ON_SIDEBAR) != 0;
bool new_selected_layerroot_on_sidebar = (new_flags & UndoRedo::SnapshotData::SELECTED_LAYERROOT_ON_SIDEBAR) != 0; bool new_selected_layerroot_on_sidebar = (new_flags & UndoRedo::SnapshotData::SELECTED_LAYERROOT_ON_SIDEBAR) != 0;
if (this->view3D->get_canvas3d()->get_gizmos_manager().wants_reslice_supports_on_undo())
top_snapshot_data.flags |= UndoRedo::SnapshotData::RECALCULATE_SLA_SUPPORTS;
// Disable layer editing before the Undo / Redo jump. // Disable layer editing before the Undo / Redo jump.
if (!new_variable_layer_editing_active && view3D->is_layers_editing_enabled()) 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")); view3D->get_canvas3d()->force_main_toolbar_left_action(view3D->get_canvas3d()->get_main_toolbar_item_id("layersediting"));
// Make a copy of the snapshot, undo/redo could invalidate the iterator
const UndoRedo::Snapshot snapshot_copy = *it_snapshot;
// Do the jump in time. // Do the jump in time.
if (it_snapshot->timestamp < this->undo_redo_stack().active_snapshot_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().undo(model, this->view3D->get_canvas3d()->get_selection(), this->view3D->get_canvas3d()->get_gizmos_manager(), top_snapshot_data, it_snapshot->timestamp) :
@ -3945,14 +3959,14 @@ void Plater::priv::undo_redo_to(std::vector<UndoRedo::Snapshot>::const_iterator
if (new_selected_settings_on_sidebar || new_selected_layer_on_sidebar) if (new_selected_settings_on_sidebar || new_selected_layer_on_sidebar)
this->sidebar->obj_list()->set_selected_layers_range_idx(layer_range_idx); this->sidebar->obj_list()->set_selected_layers_range_idx(layer_range_idx);
this->update_after_undo_redo(temp_snapshot_was_taken); this->update_after_undo_redo(snapshot_copy, temp_snapshot_was_taken);
// Enable layer editing after the Undo / Redo jump. // Enable layer editing after the Undo / Redo jump.
if (! view3D->is_layers_editing_enabled() && this->layers_height_allowed() && new_variable_layer_editing_active) if (! view3D->is_layers_editing_enabled() && this->layers_height_allowed() && new_variable_layer_editing_active)
view3D->get_canvas3d()->force_main_toolbar_left_action(view3D->get_canvas3d()->get_main_toolbar_item_id("layersediting")); view3D->get_canvas3d()->force_main_toolbar_left_action(view3D->get_canvas3d()->get_main_toolbar_item_id("layersediting"));
} }
} }
void Plater::priv::update_after_undo_redo(bool /* temp_snapshot_was_taken */) void Plater::priv::update_after_undo_redo(const UndoRedo::Snapshot& snapshot, bool /* temp_snapshot_was_taken */)
{ {
this->view3D->get_canvas3d()->get_selection().clear(); this->view3D->get_canvas3d()->get_selection().clear();
// Update volumes from the deserializd model, always stop / update the background processing (for both the SLA and FFF technologies). // Update volumes from the deserializd model, always stop / update the background processing (for both the SLA and FFF technologies).
@ -3964,7 +3978,7 @@ void Plater::priv::update_after_undo_redo(bool /* temp_snapshot_was_taken */)
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) //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(); this->view3D->get_canvas3d()->get_gizmos_manager().update_after_undo_redo(snapshot);
wxGetApp().obj_list()->update_after_undo_redo(); wxGetApp().obj_list()->update_after_undo_redo();

View file

@ -45,6 +45,7 @@ struct SnapshotData
SELECTED_SETTINGS_ON_SIDEBAR = 2, SELECTED_SETTINGS_ON_SIDEBAR = 2,
SELECTED_LAYERROOT_ON_SIDEBAR = 4, SELECTED_LAYERROOT_ON_SIDEBAR = 4,
SELECTED_LAYER_ON_SIDEBAR = 8, SELECTED_LAYER_ON_SIDEBAR = 8,
RECALCULATE_SLA_SUPPORTS = 16
}; };
}; };