Extended interface of project dirty state manager
This commit is contained in:
parent
144e37c274
commit
5d4b7c03b6
@ -904,6 +904,14 @@ bool GUI_App::on_init_inner()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
load_current_presets();
|
load_current_presets();
|
||||||
|
|
||||||
|
#if ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
if (plater_ != nullptr) {
|
||||||
|
// plater_->reset_project_initial_presets();
|
||||||
|
plater_->update_project_dirty_from_presets();
|
||||||
|
}
|
||||||
|
#endif // ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
|
||||||
mainframe->Show(true);
|
mainframe->Show(true);
|
||||||
|
|
||||||
obj_list()->set_min_height();
|
obj_list()->set_min_height();
|
||||||
|
@ -7,6 +7,9 @@
|
|||||||
#include "GUI_App.hpp"
|
#include "GUI_App.hpp"
|
||||||
#include "I18N.hpp"
|
#include "I18N.hpp"
|
||||||
#include "Plater.hpp"
|
#include "Plater.hpp"
|
||||||
|
#if ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
#include "MainFrame.hpp"
|
||||||
|
#endif // ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
|
||||||
#include "OptionsGroup.hpp"
|
#include "OptionsGroup.hpp"
|
||||||
#include "Tab.hpp"
|
#include "Tab.hpp"
|
||||||
@ -1457,12 +1460,15 @@ void ObjectList::load_shape_object(const std::string& type_name)
|
|||||||
if (obj_idx < 0)
|
if (obj_idx < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
take_snapshot(_(L("Add Shape")));
|
take_snapshot(_L("Add Shape"));
|
||||||
|
|
||||||
// Create mesh
|
// Create mesh
|
||||||
BoundingBoxf3 bb;
|
BoundingBoxf3 bb;
|
||||||
TriangleMesh mesh = create_mesh(type_name, bb);
|
TriangleMesh mesh = create_mesh(type_name, bb);
|
||||||
load_mesh_object(mesh, _(L("Shape")) + "-" + _(type_name));
|
load_mesh_object(mesh, _L("Shape") + "-" + _(type_name));
|
||||||
|
#if ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
wxGetApp().mainframe->update_title();
|
||||||
|
#endif // ENABLE_PROJECT_DIRTY_STATE
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjectList::load_mesh_object(const TriangleMesh &mesh, const wxString &name, bool center)
|
void ObjectList::load_mesh_object(const TriangleMesh &mesh, const wxString &name, bool center)
|
||||||
|
@ -206,6 +206,11 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S
|
|||||||
|
|
||||||
// declare events
|
// declare events
|
||||||
Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent& event) {
|
Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent& event) {
|
||||||
|
#if ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
if (m_plater != nullptr)
|
||||||
|
m_plater->save_project_if_dirty();
|
||||||
|
#endif // ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
|
||||||
if (event.CanVeto() && !wxGetApp().check_unsaved_changes()) {
|
if (event.CanVeto() && !wxGetApp().check_unsaved_changes()) {
|
||||||
event.Veto();
|
event.Veto();
|
||||||
return;
|
return;
|
||||||
@ -487,8 +492,14 @@ void MainFrame::update_title()
|
|||||||
// m_plater->get_project_filename() produces file name including path, but excluding extension.
|
// m_plater->get_project_filename() produces file name including path, but excluding extension.
|
||||||
// Don't try to remove the extension, it would remove part of the file name after the last dot!
|
// Don't try to remove the extension, it would remove part of the file name after the last dot!
|
||||||
wxString project = from_path(into_path(m_plater->get_project_filename()).filename());
|
wxString project = from_path(into_path(m_plater->get_project_filename()).filename());
|
||||||
|
#if ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
wxString dirty_marker = (!m_plater->model().objects.empty() && m_plater->is_project_dirty()) ? "*" : "";
|
||||||
|
if (!dirty_marker.empty() || !project.empty())
|
||||||
|
title = dirty_marker + project + " - ";
|
||||||
|
#else
|
||||||
if (!project.empty())
|
if (!project.empty())
|
||||||
title += (project + " - ");
|
title += (project + " - ");
|
||||||
|
#endif // ENABLE_PROJECT_DIRTY_STATE
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string build_id = wxGetApp().is_editor() ? SLIC3R_BUILD_ID : GCODEVIEWER_BUILD_ID;
|
std::string build_id = wxGetApp().is_editor() ? SLIC3R_BUILD_ID : GCODEVIEWER_BUILD_ID;
|
||||||
@ -668,10 +679,36 @@ bool MainFrame::can_start_new_project() const
|
|||||||
return (m_plater != nullptr) && (!m_plater->get_project_filename(".3mf").IsEmpty() || !m_plater->model().objects.empty());
|
return (m_plater != nullptr) && (!m_plater->get_project_filename(".3mf").IsEmpty() || !m_plater->model().objects.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
bool MainFrame::can_save() const
|
||||||
|
{
|
||||||
|
return (m_plater != nullptr) && !m_plater->model().objects.empty() && !m_plater->get_project_filename().empty() && m_plater->is_project_dirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MainFrame::can_save_as() const
|
||||||
|
{
|
||||||
|
return (m_plater != nullptr) && !m_plater->model().objects.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainFrame::save_project()
|
||||||
|
{
|
||||||
|
save_project_as(m_plater->get_project_filename(".3mf"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainFrame::save_project_as(const wxString& filename)
|
||||||
|
{
|
||||||
|
bool ret = (m_plater != nullptr) ? m_plater->export_3mf(into_path(filename)) : false;
|
||||||
|
if (ret) {
|
||||||
|
// wxGetApp().update_saved_preset_from_current_preset();
|
||||||
|
m_plater->reset_project_dirty_after_save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
bool MainFrame::can_save() const
|
bool MainFrame::can_save() const
|
||||||
{
|
{
|
||||||
return (m_plater != nullptr) && !m_plater->model().objects.empty();
|
return (m_plater != nullptr) && !m_plater->model().objects.empty();
|
||||||
}
|
}
|
||||||
|
#endif // ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
|
||||||
bool MainFrame::can_export_model() const
|
bool MainFrame::can_export_model() const
|
||||||
{
|
{
|
||||||
@ -977,16 +1014,27 @@ void MainFrame::init_menubar_as_editor()
|
|||||||
|
|
||||||
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(m_recent_projects.GetCount() > 0); }, recent_projects_submenu->GetId());
|
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(m_recent_projects.GetCount() > 0); }, recent_projects_submenu->GetId());
|
||||||
|
|
||||||
|
#if ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
append_menu_item(fileMenu, wxID_ANY, _L("&Save Project") + "\tCtrl+S", _L("Save current project file"),
|
||||||
|
[this](wxCommandEvent&) { save_project(); }, "save", nullptr,
|
||||||
|
[this](){return m_plater != nullptr && can_save(); }, this);
|
||||||
|
#else
|
||||||
append_menu_item(fileMenu, wxID_ANY, _L("&Save Project") + "\tCtrl+S", _L("Save current project file"),
|
append_menu_item(fileMenu, wxID_ANY, _L("&Save Project") + "\tCtrl+S", _L("Save current project file"),
|
||||||
[this](wxCommandEvent&) { if (m_plater) m_plater->export_3mf(into_path(m_plater->get_project_filename(".3mf"))); }, "save", nullptr,
|
[this](wxCommandEvent&) { if (m_plater) m_plater->export_3mf(into_path(m_plater->get_project_filename(".3mf"))); }, "save", nullptr,
|
||||||
[this](){return m_plater != nullptr && can_save(); }, this);
|
[this](){return m_plater != nullptr && can_save(); }, this);
|
||||||
|
#endif // ENABLE_PROJECT_DIRTY_STATE
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
append_menu_item(fileMenu, wxID_ANY, _L("Save Project &as") + dots + "\tCtrl+Shift+S", _L("Save current project file as"),
|
append_menu_item(fileMenu, wxID_ANY, _L("Save Project &as") + dots + "\tCtrl+Shift+S", _L("Save current project file as"),
|
||||||
#else
|
#else
|
||||||
append_menu_item(fileMenu, wxID_ANY, _L("Save Project &as") + dots + "\tCtrl+Alt+S", _L("Save current project file as"),
|
append_menu_item(fileMenu, wxID_ANY, _L("Save Project &as") + dots + "\tCtrl+Alt+S", _L("Save current project file as"),
|
||||||
#endif // __APPLE__
|
#endif // __APPLE__
|
||||||
|
#if ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
[this](wxCommandEvent&) { save_project_as(); }, "save", nullptr,
|
||||||
|
[this](){return m_plater != nullptr && can_save_as(); }, this);
|
||||||
|
#else
|
||||||
[this](wxCommandEvent&) { if (m_plater) m_plater->export_3mf(); }, "save", nullptr,
|
[this](wxCommandEvent&) { if (m_plater) m_plater->export_3mf(); }, "save", nullptr,
|
||||||
[this](){return m_plater != nullptr && can_save(); }, this);
|
[this](){return m_plater != nullptr && can_save(); }, this);
|
||||||
|
#endif // ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
|
||||||
fileMenu->AppendSeparator();
|
fileMenu->AppendSeparator();
|
||||||
|
|
||||||
|
@ -91,7 +91,9 @@ class MainFrame : public DPIFrame
|
|||||||
void on_value_changed(wxCommandEvent&);
|
void on_value_changed(wxCommandEvent&);
|
||||||
|
|
||||||
bool can_start_new_project() const;
|
bool can_start_new_project() const;
|
||||||
|
#if !ENABLE_PROJECT_DIRTY_STATE
|
||||||
bool can_save() const;
|
bool can_save() const;
|
||||||
|
#endif // !ENABLE_PROJECT_DIRTY_STATE
|
||||||
bool can_export_model() const;
|
bool can_export_model() const;
|
||||||
bool can_export_toolpaths() const;
|
bool can_export_toolpaths() const;
|
||||||
bool can_export_supports() const;
|
bool can_export_supports() const;
|
||||||
@ -184,6 +186,13 @@ public:
|
|||||||
// Propagate changed configuration from the Tab to the Plater and save changes to the AppConfig
|
// Propagate changed configuration from the Tab to the Plater and save changes to the AppConfig
|
||||||
void on_config_changed(DynamicPrintConfig* cfg) const ;
|
void on_config_changed(DynamicPrintConfig* cfg) const ;
|
||||||
|
|
||||||
|
#if ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
bool can_save() const;
|
||||||
|
bool can_save_as() const;
|
||||||
|
void save_project();
|
||||||
|
void save_project_as(const wxString& filename = wxString());
|
||||||
|
#endif // ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
|
||||||
void add_to_recent_projects(const wxString& filename);
|
void add_to_recent_projects(const wxString& filename);
|
||||||
|
|
||||||
PrintHostQueueDialog* printhost_queue_dlg() { return m_printhost_queue_dlg; }
|
PrintHostQueueDialog* printhost_queue_dlg() { return m_printhost_queue_dlg; }
|
||||||
|
@ -1393,7 +1393,13 @@ bool PlaterDropTarget::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString &fi
|
|||||||
this->MSWUpdateDragImageOnLeave();
|
this->MSWUpdateDragImageOnLeave();
|
||||||
#endif // WIN32
|
#endif // WIN32
|
||||||
|
|
||||||
|
#if ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
bool res = (m_plater != nullptr) ? m_plater->load_files(filenames) : false;
|
||||||
|
wxGetApp().mainframe->update_title();
|
||||||
|
return res;
|
||||||
|
#else
|
||||||
return (m_plater != nullptr) ? m_plater->load_files(filenames) : false;
|
return (m_plater != nullptr) ? m_plater->load_files(filenames) : false;
|
||||||
|
#endif // ENABLE_PROJECT_DIRTY_STATE
|
||||||
}
|
}
|
||||||
|
|
||||||
// State to manage showing after export notifications and device ejecting
|
// State to manage showing after export notifications and device ejecting
|
||||||
@ -1511,9 +1517,26 @@ struct Plater::priv
|
|||||||
priv(Plater *q, MainFrame *main_frame);
|
priv(Plater *q, MainFrame *main_frame);
|
||||||
~priv();
|
~priv();
|
||||||
|
|
||||||
|
#if ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
bool is_project_dirty() const { return dirty_state.is_dirty(); }
|
||||||
|
void update_project_dirty_from_presets() { dirty_state.update_from_presets(); }
|
||||||
|
bool save_project_if_dirty() {
|
||||||
|
if (dirty_state.is_dirty()) {
|
||||||
|
MainFrame* mainframe = wxGetApp().mainframe;
|
||||||
|
if (mainframe->can_save_as()) {
|
||||||
|
wxMessageDialog dlg(mainframe, _L("Do you want to save the changes to the current project ?"), wxString(SLIC3R_APP_NAME), wxYES_NO | wxCANCEL);
|
||||||
|
if (dlg.ShowModal() == wxID_CANCEL)
|
||||||
|
return false;
|
||||||
|
mainframe->save_project_as(wxGetApp().plater()->get_project_filename());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
void reset_project_dirty_after_save() { dirty_state.reset_after_save(); }
|
||||||
#if ENABLE_PROJECT_DIRTY_STATE_DEBUG_WINDOW
|
#if ENABLE_PROJECT_DIRTY_STATE_DEBUG_WINDOW
|
||||||
void render_project_state_debug_window() const { dirty_state.render_debug_window(); }
|
void render_project_state_debug_window() const { dirty_state.render_debug_window(); }
|
||||||
#endif // ENABLE_PROJECT_DIRTY_STATE_DEBUG_WINDOW
|
#endif // ENABLE_PROJECT_DIRTY_STATE_DEBUG_WINDOW
|
||||||
|
#endif // ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
|
||||||
enum class UpdateParams {
|
enum class UpdateParams {
|
||||||
FORCE_FULL_SCREEN_REFRESH = 1,
|
FORCE_FULL_SCREEN_REFRESH = 1,
|
||||||
@ -4216,6 +4239,11 @@ void Plater::priv::take_snapshot(const std::string& snapshot_name)
|
|||||||
}
|
}
|
||||||
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().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().release_least_recently_used();
|
||||||
|
|
||||||
|
#if ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
dirty_state.update_from_undo_redo_stack(undo_redo_stack_main(), undo_redo_stack());
|
||||||
|
#endif // ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
|
||||||
// Save the last active preset name of a particular printer technology.
|
// 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();
|
((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();
|
||||||
@ -4346,6 +4374,10 @@ void Plater::priv::undo_redo_to(std::vector<UndoRedo::Snapshot>::const_iterator
|
|||||||
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"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
dirty_state.update_from_undo_redo_stack(undo_redo_stack_main(), undo_redo_stack());
|
||||||
|
#endif // ENABLE_PROJECT_DIRTY_STATE
|
||||||
}
|
}
|
||||||
|
|
||||||
void Plater::priv::update_after_undo_redo(const UndoRedo::Snapshot& snapshot, bool /* temp_snapshot_was_taken */)
|
void Plater::priv::update_after_undo_redo(const UndoRedo::Snapshot& snapshot, bool /* temp_snapshot_was_taken */)
|
||||||
@ -4429,9 +4461,15 @@ Plater::Plater(wxWindow *parent, MainFrame *main_frame)
|
|||||||
// Initialization performed in the private c-tor
|
// Initialization performed in the private c-tor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
bool Plater::is_project_dirty() const { return p->is_project_dirty(); }
|
||||||
|
void Plater::update_project_dirty_from_presets() { p->update_project_dirty_from_presets(); }
|
||||||
|
bool Plater::save_project_if_dirty() { return p->save_project_if_dirty(); }
|
||||||
|
void Plater::reset_project_dirty_after_save() { p->reset_project_dirty_after_save(); }
|
||||||
#if ENABLE_PROJECT_DIRTY_STATE_DEBUG_WINDOW
|
#if ENABLE_PROJECT_DIRTY_STATE_DEBUG_WINDOW
|
||||||
void Plater::render_project_state_debug_window() const { p->render_project_state_debug_window(); }
|
void Plater::render_project_state_debug_window() const { p->render_project_state_debug_window(); }
|
||||||
#endif // ENABLE_PROJECT_DIRTY_STATE_DEBUG_WINDOW
|
#endif // ENABLE_PROJECT_DIRTY_STATE_DEBUG_WINDOW
|
||||||
|
#endif // ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
|
||||||
Sidebar& Plater::sidebar() { return *p->sidebar; }
|
Sidebar& Plater::sidebar() { return *p->sidebar; }
|
||||||
Model& Plater::model() { return p->model; }
|
Model& Plater::model() { return p->model; }
|
||||||
@ -4442,12 +4480,30 @@ SLAPrint& Plater::sla_print() { return p->sla_print; }
|
|||||||
|
|
||||||
void Plater::new_project()
|
void Plater::new_project()
|
||||||
{
|
{
|
||||||
|
#if ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
if (!p->save_project_if_dirty())
|
||||||
|
return;
|
||||||
|
#endif // ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
|
||||||
p->select_view_3D("3D");
|
p->select_view_3D("3D");
|
||||||
|
#if ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
take_snapshot(_L("New Project"));
|
||||||
|
Plater::SuppressSnapshots suppress(this);
|
||||||
|
reset();
|
||||||
|
// reset_project_initial_presets();
|
||||||
|
update_project_dirty_from_presets();
|
||||||
|
#else
|
||||||
wxPostEvent(p->view3D->get_wxglcanvas(), SimpleEvent(EVT_GLTOOLBAR_DELETE_ALL));
|
wxPostEvent(p->view3D->get_wxglcanvas(), SimpleEvent(EVT_GLTOOLBAR_DELETE_ALL));
|
||||||
|
#endif // ENABLE_PROJECT_DIRTY_STATE
|
||||||
}
|
}
|
||||||
|
|
||||||
void Plater::load_project()
|
void Plater::load_project()
|
||||||
{
|
{
|
||||||
|
#if ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
if (!p->save_project_if_dirty())
|
||||||
|
return;
|
||||||
|
#endif // ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
|
||||||
// Ask user for a project file name.
|
// Ask user for a project file name.
|
||||||
wxString input_file;
|
wxString input_file;
|
||||||
wxGetApp().load_project(this, input_file);
|
wxGetApp().load_project(this, input_file);
|
||||||
@ -4471,8 +4527,16 @@ void Plater::load_project(const wxString& filename)
|
|||||||
std::vector<size_t> res = load_files(input_paths);
|
std::vector<size_t> res = load_files(input_paths);
|
||||||
|
|
||||||
// if res is empty no data has been loaded
|
// if res is empty no data has been loaded
|
||||||
|
#if ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
if (!res.empty()) {
|
||||||
|
p->set_project_filename(filename);
|
||||||
|
// reset_project_initial_presets();
|
||||||
|
update_project_dirty_from_presets();
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (!res.empty())
|
if (!res.empty())
|
||||||
p->set_project_filename(filename);
|
p->set_project_filename(filename);
|
||||||
|
#endif // ENABLE_PROJECT_DIRTY_STATE
|
||||||
}
|
}
|
||||||
|
|
||||||
void Plater::add_model(bool imperial_units/* = false*/)
|
void Plater::add_model(bool imperial_units/* = false*/)
|
||||||
@ -4503,7 +4567,13 @@ void Plater::add_model(bool imperial_units/* = false*/)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Plater::TakeSnapshot snapshot(this, snapshot_label);
|
Plater::TakeSnapshot snapshot(this, snapshot_label);
|
||||||
|
#if ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
std::vector<size_t> res = load_files(paths, true, false, imperial_units);
|
||||||
|
if (!res.empty())
|
||||||
|
wxGetApp().mainframe->update_title();
|
||||||
|
#else
|
||||||
load_files(paths, true, false, imperial_units);
|
load_files(paths, true, false, imperial_units);
|
||||||
|
#endif // ENABLE_PROJECT_DIRTY_STATE
|
||||||
}
|
}
|
||||||
|
|
||||||
void Plater::import_sl1_archive()
|
void Plater::import_sl1_archive()
|
||||||
@ -5187,24 +5257,39 @@ void Plater::export_amf()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
bool Plater::export_3mf(const boost::filesystem::path& output_path)
|
||||||
|
#else
|
||||||
void Plater::export_3mf(const boost::filesystem::path& output_path)
|
void Plater::export_3mf(const boost::filesystem::path& output_path)
|
||||||
|
#endif // ENABLE_PROJECT_DIRTY_STATE
|
||||||
{
|
{
|
||||||
if (p->model.objects.empty()
|
if (p->model.objects.empty()
|
||||||
|| canvas3D()->get_gizmos_manager().is_in_editing_mode(true))
|
|| canvas3D()->get_gizmos_manager().is_in_editing_mode(true))
|
||||||
|
#if ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
return;
|
return;
|
||||||
|
#endif // ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
|
||||||
wxString path;
|
wxString path;
|
||||||
bool export_config = true;
|
bool export_config = true;
|
||||||
if (output_path.empty())
|
if (output_path.empty()) {
|
||||||
{
|
|
||||||
path = p->get_export_file(FT_3MF);
|
path = p->get_export_file(FT_3MF);
|
||||||
|
#if ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
if (path.empty()) { return false; }
|
||||||
|
#else
|
||||||
if (path.empty()) { return; }
|
if (path.empty()) { return; }
|
||||||
|
#endif // ENABLE_PROJECT_DIRTY_STATE
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
path = from_path(output_path);
|
path = from_path(output_path);
|
||||||
|
|
||||||
if (!path.Lower().EndsWith(".3mf"))
|
if (!path.Lower().EndsWith(".3mf"))
|
||||||
|
#if ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
return;
|
return;
|
||||||
|
#endif // ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
|
||||||
DynamicPrintConfig cfg = wxGetApp().preset_bundle->full_config_secure();
|
DynamicPrintConfig cfg = wxGetApp().preset_bundle->full_config_secure();
|
||||||
const std::string path_u8 = into_u8(path);
|
const std::string path_u8 = into_u8(path);
|
||||||
@ -5212,6 +5297,19 @@ void Plater::export_3mf(const boost::filesystem::path& output_path)
|
|||||||
bool full_pathnames = wxGetApp().app_config->get("export_sources_full_pathnames") == "1";
|
bool full_pathnames = wxGetApp().app_config->get("export_sources_full_pathnames") == "1";
|
||||||
ThumbnailData thumbnail_data;
|
ThumbnailData thumbnail_data;
|
||||||
p->generate_thumbnail(thumbnail_data, THUMBNAIL_SIZE_3MF.first, THUMBNAIL_SIZE_3MF.second, false, true, true, true);
|
p->generate_thumbnail(thumbnail_data, THUMBNAIL_SIZE_3MF.first, THUMBNAIL_SIZE_3MF.second, false, true, true, true);
|
||||||
|
#if ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
bool ret = Slic3r::store_3mf(path_u8.c_str(), &p->model, export_config ? &cfg : nullptr, full_pathnames, &thumbnail_data);
|
||||||
|
if (ret) {
|
||||||
|
// Success
|
||||||
|
p->statusbar()->set_status_text(format_wxstr(_L("3MF file exported to %s"), path));
|
||||||
|
p->set_project_filename(path);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Failure
|
||||||
|
p->statusbar()->set_status_text(format_wxstr(_L("Error exporting 3MF file %s"), path));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
#else
|
||||||
if (Slic3r::store_3mf(path_u8.c_str(), &p->model, export_config ? &cfg : nullptr, full_pathnames, &thumbnail_data)) {
|
if (Slic3r::store_3mf(path_u8.c_str(), &p->model, export_config ? &cfg : nullptr, full_pathnames, &thumbnail_data)) {
|
||||||
// Success
|
// Success
|
||||||
p->statusbar()->set_status_text(format_wxstr(_L("3MF file exported to %s"), path));
|
p->statusbar()->set_status_text(format_wxstr(_L("3MF file exported to %s"), path));
|
||||||
@ -5221,6 +5319,7 @@ void Plater::export_3mf(const boost::filesystem::path& output_path)
|
|||||||
// Failure
|
// Failure
|
||||||
p->statusbar()->set_status_text(format_wxstr(_L("Error exporting 3MF file %s"), path));
|
p->statusbar()->set_status_text(format_wxstr(_L("Error exporting 3MF file %s"), path));
|
||||||
}
|
}
|
||||||
|
#endif // ENABLE_PROJECT_DIRTY_STATE
|
||||||
}
|
}
|
||||||
|
|
||||||
void Plater::reload_from_disk()
|
void Plater::reload_from_disk()
|
||||||
|
@ -130,9 +130,15 @@ public:
|
|||||||
Plater &operator=(const Plater &) = delete;
|
Plater &operator=(const Plater &) = delete;
|
||||||
~Plater() = default;
|
~Plater() = default;
|
||||||
|
|
||||||
|
#if ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
bool is_project_dirty() const;
|
||||||
|
void update_project_dirty_from_presets();
|
||||||
|
bool save_project_if_dirty();
|
||||||
|
void reset_project_dirty_after_save();
|
||||||
#if ENABLE_PROJECT_DIRTY_STATE_DEBUG_WINDOW
|
#if ENABLE_PROJECT_DIRTY_STATE_DEBUG_WINDOW
|
||||||
void render_project_state_debug_window() const;
|
void render_project_state_debug_window() const;
|
||||||
#endif // ENABLE_PROJECT_DIRTY_STATE_DEBUG_WINDOW
|
#endif // ENABLE_PROJECT_DIRTY_STATE_DEBUG_WINDOW
|
||||||
|
#endif // ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
|
||||||
Sidebar& sidebar();
|
Sidebar& sidebar();
|
||||||
Model& model();
|
Model& model();
|
||||||
@ -201,7 +207,11 @@ public:
|
|||||||
void export_gcode(bool prefer_removable);
|
void export_gcode(bool prefer_removable);
|
||||||
void export_stl(bool extended = false, bool selection_only = false);
|
void export_stl(bool extended = false, bool selection_only = false);
|
||||||
void export_amf();
|
void export_amf();
|
||||||
|
#if ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
bool export_3mf(const boost::filesystem::path& output_path = boost::filesystem::path());
|
||||||
|
#else
|
||||||
void export_3mf(const boost::filesystem::path& output_path = boost::filesystem::path());
|
void export_3mf(const boost::filesystem::path& output_path = boost::filesystem::path());
|
||||||
|
#endif // ENABLE_PROJECT_DIRTY_STATE
|
||||||
void reload_from_disk();
|
void reload_from_disk();
|
||||||
void reload_all_from_disk();
|
void reload_all_from_disk();
|
||||||
bool has_toolpaths_to_export() const;
|
bool has_toolpaths_to_export() const;
|
||||||
|
@ -2,12 +2,32 @@
|
|||||||
#include "ProjectDirtyStateManager.hpp"
|
#include "ProjectDirtyStateManager.hpp"
|
||||||
#include "ImGuiWrapper.hpp"
|
#include "ImGuiWrapper.hpp"
|
||||||
#include "GUI_App.hpp"
|
#include "GUI_App.hpp"
|
||||||
|
#include "MainFrame.hpp"
|
||||||
|
|
||||||
#if ENABLE_PROJECT_DIRTY_STATE
|
#if ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
|
||||||
|
void ProjectDirtyStateManager::update_from_undo_redo_stack(const Slic3r::UndoRedo::Stack& main_stack, const Slic3r::UndoRedo::Stack& active_stack)
|
||||||
|
{
|
||||||
|
if (!wxGetApp().initialized())
|
||||||
|
return;
|
||||||
|
|
||||||
|
wxGetApp().mainframe->update_title();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProjectDirtyStateManager::update_from_presets()
|
||||||
|
{
|
||||||
|
wxGetApp().mainframe->update_title();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProjectDirtyStateManager::reset_after_save()
|
||||||
|
{
|
||||||
|
m_state.reset();
|
||||||
|
wxGetApp().mainframe->update_title();
|
||||||
|
}
|
||||||
|
|
||||||
#if ENABLE_PROJECT_DIRTY_STATE_DEBUG_WINDOW
|
#if ENABLE_PROJECT_DIRTY_STATE_DEBUG_WINDOW
|
||||||
void ProjectDirtyStateManager::render_debug_window() const
|
void ProjectDirtyStateManager::render_debug_window() const
|
||||||
{
|
{
|
||||||
|
@ -4,6 +4,9 @@
|
|||||||
#if ENABLE_PROJECT_DIRTY_STATE
|
#if ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
namespace UndoRedo {
|
||||||
|
class Stack;
|
||||||
|
} // namespace UndoRedo
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
|
||||||
class ProjectDirtyStateManager
|
class ProjectDirtyStateManager
|
||||||
@ -14,12 +17,19 @@ class ProjectDirtyStateManager
|
|||||||
bool presets{ false };
|
bool presets{ false };
|
||||||
|
|
||||||
bool is_dirty() const { return plater || presets; }
|
bool is_dirty() const { return plater || presets; }
|
||||||
|
void reset() {
|
||||||
|
plater = false;
|
||||||
|
presets = false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
DirtyState m_state;
|
DirtyState m_state;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool is_dirty() const { return m_state.is_dirty(); }
|
bool is_dirty() const { return m_state.is_dirty(); }
|
||||||
|
void update_from_undo_redo_stack(const Slic3r::UndoRedo::Stack& main_stack, const Slic3r::UndoRedo::Stack& active_stack);
|
||||||
|
void update_from_presets();
|
||||||
|
void reset_after_save();
|
||||||
|
|
||||||
#if ENABLE_PROJECT_DIRTY_STATE_DEBUG_WINDOW
|
#if ENABLE_PROJECT_DIRTY_STATE_DEBUG_WINDOW
|
||||||
void render_debug_window() const;
|
void render_debug_window() const;
|
||||||
|
@ -1215,9 +1215,8 @@ void Tab::apply_config_from_cache()
|
|||||||
// to update number of "filament" selection boxes when the number of extruders change.
|
// to update number of "filament" selection boxes when the number of extruders change.
|
||||||
void Tab::on_presets_changed()
|
void Tab::on_presets_changed()
|
||||||
{
|
{
|
||||||
if (wxGetApp().plater() == nullptr) {
|
if (wxGetApp().plater() == nullptr)
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
// Instead of PostEvent (EVT_TAB_PRESETS_CHANGED) just call update_presets
|
// Instead of PostEvent (EVT_TAB_PRESETS_CHANGED) just call update_presets
|
||||||
wxGetApp().plater()->sidebar().update_presets(m_type);
|
wxGetApp().plater()->sidebar().update_presets(m_type);
|
||||||
@ -1235,6 +1234,10 @@ void Tab::on_presets_changed()
|
|||||||
// clear m_dependent_tabs after first update from select_preset()
|
// clear m_dependent_tabs after first update from select_preset()
|
||||||
// to avoid needless preset loading from update() function
|
// to avoid needless preset loading from update() function
|
||||||
m_dependent_tabs.clear();
|
m_dependent_tabs.clear();
|
||||||
|
|
||||||
|
#if ENABLE_PROJECT_DIRTY_STATE
|
||||||
|
wxGetApp().plater()->update_project_dirty_from_presets();
|
||||||
|
#endif // ENABLE_PROJECT_DIRTY_STATE
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tab::build_preset_description_line(ConfigOptionsGroup* optgroup)
|
void Tab::build_preset_description_line(ConfigOptionsGroup* optgroup)
|
||||||
|
Loading…
Reference in New Issue
Block a user