diff --git a/src/GUI/Plater.cpp b/src/GUI/Plater.cpp index 2f6c2b0b6..acedd69ae 100644 --- a/src/GUI/Plater.cpp +++ b/src/GUI/Plater.cpp @@ -11,6 +11,22 @@ namespace Slic3r { namespace GUI { +const auto TB_ADD {wxNewId()}; +const auto TB_REMOVE {wxNewId()}; +const auto TB_RESET {wxNewId()}; +const auto TB_ARRANGE {wxNewId()}; +const auto TB_EXPORT_GCODE {wxNewId()}; +const auto TB_EXPORT_STL {wxNewId()}; +const auto TB_MORE {wxNewId()}; +const auto TB_FEWER {wxNewId()}; +const auto TB_45CW {wxNewId()}; +const auto TB_45CCW {wxNewId()}; +const auto TB_SCALE {wxNewId()}; +const auto TB_SPLIT {wxNewId()}; +const auto TB_CUT {wxNewId()}; +const auto TB_LAYERS {wxNewId()}; +const auto TB_SETTINGS {wxNewId()}; + const auto PROGRESS_BAR_EVENT = wxNewEventType(); Plater::Plater(wxWindow* parent, const wxString& title, std::shared_ptr _settings) : @@ -123,8 +139,12 @@ Plater::Plater(wxWindow* parent, const wxString& title, std::shared_ptrcanvas2D->update_bed_size(); + // Toolbar + this->build_toolbar(); + // Finally assemble the sizers into the display. // export/print/send/export buttons @@ -541,10 +561,162 @@ void Plater::build_toolbar() { toolbar->AddSeparator(); toolbar->AddTool(TB_SETTINGS, _(L"Settings…"), wxBitmap(var("cog.png"), wxBITMAP_TYPE_PNG), ""); toolbar->AddTool(TB_LAYERS, _(L"Layer heights…"), wxBitmap(var("variable_layer_height.png"), wxBITMAP_TYPE_PNG), ""); - + + toolbar->Bind(wxEVT_TOOL, [this](wxCommandEvent &e) { this->add(); }, TB_ADD); + toolbar->Bind(wxEVT_TOOL, [this](wxCommandEvent &e) { this->remove(); }, TB_REMOVE); + toolbar->Bind(wxEVT_TOOL, [this](wxCommandEvent &e) { this->reset(); }, TB_RESET); + toolbar->Bind(wxEVT_TOOL, [this](wxCommandEvent &e) { this->arrange(); }, TB_ARRANGE); + toolbar->Bind(wxEVT_TOOL, [this](wxCommandEvent &e) { this->increase(); }, TB_MORE); + toolbar->Bind(wxEVT_TOOL, [this](wxCommandEvent &e) { this->decrease(); }, TB_FEWER); + toolbar->Bind(wxEVT_TOOL, [this](wxCommandEvent &e) { this->rotate(-45); }, TB_45CW); + toolbar->Bind(wxEVT_TOOL, [this](wxCommandEvent &e) { this->rotate(45); }, TB_45CCW); + toolbar->Bind(wxEVT_TOOL, [this](wxCommandEvent &e) { this->changescale(); }, TB_SCALE); + toolbar->Bind(wxEVT_TOOL, [this](wxCommandEvent &e) { this->split_object(); }, TB_SPLIT); + toolbar->Bind(wxEVT_TOOL, [this](wxCommandEvent &e) { this->object_cut_dialog(); }, TB_CUT); + toolbar->Bind(wxEVT_TOOL, [this](wxCommandEvent &e) { this->object_layers_dialog(); }, TB_LAYERS); + toolbar->Bind(wxEVT_TOOL, [this](wxCommandEvent &e) { this->object_settings_dialog(); }, TB_SETTINGS); } +void Plater::remove() { + this->remove(-1, false); +} + +void Plater::remove(int obj_idx, bool dont_push) { + + // TODO: $self->stop_background_process; + + // Prevent toolpaths preview from rendering while we modify the Print object + if (this->preview2D != nullptr) + this->preview2D->enabled(false); + + if (this->preview3D != nullptr) + this->preview3D->enabled(false); + + if (this->previewDLP != nullptr) + this->previewDLP->enabled(false); + + ObjRef obj_ref; + // if no object index is supplied or an invalid one is supplied, remove the selected one + if (obj_idx < 0 || obj_idx >= this->objects.size()) { + obj_ref = this->selected_object(); + } else { // otherwise + obj_ref = this->objects.begin() + obj_idx; + } + std::vector::const_iterator const_ref = obj_ref; + + if (obj_ref >= this->objects.end()) return; // do nothing, nothing was selected. + + Slic3r::Log::info(LogChannel, "Assigned obj_ref"); + // Save the object identifier and copy the object for undo/redo operations. + auto object_id { obj_ref->identifier }; + auto new_model { Slic3r::Model() }; + new_model.add_object(*(this->model->objects.at(obj_ref->identifier))); + + Slic3r::Log::info(LogChannel, "Assigned obj_ref"); + try { + this->model->delete_object(obj_ref->identifier); + } catch (InvalidObjectException& ex) { + Slic3r::Log::error(LogChannel, LOG_WSTRING("Failed to delete object " << obj_ref->identifier << " from Model.")); + } + try { + this->print->delete_object(obj_ref->identifier); + } catch (InvalidObjectException& ex) { + Slic3r::Log::error(LogChannel, LOG_WSTRING("Failed to delete object " << obj_ref->identifier << " from Print.")); + } + + this->objects.erase(const_ref); + int i = 0; + for (auto o : this->objects) { o.identifier = i++; } // fix identifiers + this->object_identifier = this->objects.size(); + + this->object_list_changed(); + + this->select_object(); + + this->on_model_change(); + + if (!dont_push) { + Slic3r::Log::info(LogChannel, "Push to undo stack."); + this->add_undo_operation(UndoCmd::Remove, object_id, new_model); + Slic3r::Log::info(LogChannel, "Pushed to undo stack."); + } +} + +void Plater::reset(bool dont_push) { + // TODO: $self->stop_background_process; + + // Prevent toolpaths preview from rendering while we modify the Print object + if (this->preview2D != nullptr) + this->preview2D->enabled(false); + + if (this->preview3D != nullptr) + this->preview3D->enabled(false); + + if (this->previewDLP != nullptr) + this->previewDLP->enabled(false); + + if (!dont_push) { + Slic3r::Model current_model {*(this->model)}; + std::vector tmp_ids; + for (const auto& obj : this->objects) { + tmp_ids.push_back(obj.identifier); + } + this->add_undo_operation(UndoCmd::Reset, tmp_ids, current_model); + } + + this->objects.clear(); + this->object_identifier = this->objects.size(); + + this->model->clear_objects(); + this->print->clear_objects(); + + this->object_list_changed(); + this->select_object(); + + this->on_model_change(); +} + +void Plater::increase() { + //TODO +} + +void Plater::decrease() { + //TODO +} + +void Plater::rotate(double angle) { + //TODO +} + +void Plater::split_object() { + //TODO +} + +void Plater::changescale() { + //TODO +} + +void Plater::object_cut_dialog() { + //TODO +} + +void Plater::object_layers_dialog() { + //TODO +} + +void Plater::add_undo_operation(UndoCmd cmd, std::vector& obj_ids, Slic3r::Model& model) { + //TODO +} + +void Plater::add_undo_operation(UndoCmd cmd, int obj_id, Slic3r::Model& model) { + std::vector tmp {obj_id}; + add_undo_operation(cmd, tmp, model); +} + +void Plater::object_list_changed() { + //TODO +} }} // Namespace Slic3r::GUI diff --git a/src/GUI/Plater.hpp b/src/GUI/Plater.hpp index c73899b13..5170bc553 100644 --- a/src/GUI/Plater.hpp +++ b/src/GUI/Plater.hpp @@ -6,6 +6,7 @@ #endif #include +#include #include @@ -28,6 +29,11 @@ namespace Slic3r { namespace GUI { using UndoOperation = int; + +enum class UndoCmd { + Remove, Add, Reset +}; + using ObjIdx = unsigned int; using ObjRef = std::vector::iterator; @@ -45,6 +51,10 @@ public: /// User-level function called through external interface. /// Pops file dialog. void add(); + + /// Remove a selected model from the plater. + void remove(int obj_idx, bool dont_push = false); + void remove(); /// Arrange models via a simple packing mechanism based on bounding boxes. void arrange(); @@ -52,6 +62,11 @@ public: /// Ask if there are any unsaved changes. bool prompt_unsaved_changes() { return true; } + void add_undo_operation(UndoCmd cmd, int obj_id, Slic3r::Model& model); + + /// Push an undo op onto the stack. + void add_undo_operation(UndoCmd cmd, std::vector& obj_ids, Slic3r::Model& model); + private: std::shared_ptr print {std::make_shared(Slic3r::Print())}; std::shared_ptr model {std::make_shared(Slic3r::Model())}; @@ -143,6 +158,36 @@ private: /// Create and launch menu for object. wxMenu* object_menu(); + /// Instantiate the toolbar + void build_toolbar(); + + /// Clear plate. + void reset(bool dont_push = false); + + /// Make instances of the currently selected model. + void increase(); + + /// Remove instances of the currently selected model. + void decrease(); + + /// Rotate the currently selected model. + void rotate(double angle); + + /// Separate a multipart model to its component interfaces. + void split_object(); + + /// Prompt a change of scaling. + void changescale(); + + /// Open the dialog to perform a cut on the current model. + void object_cut_dialog(); + + /// Open a menu to configure the layer heights. + void object_layers_dialog(); + + /// Process a change in the object list. + void object_list_changed(); + }; diff --git a/src/GUI/Plater/PlaterObject.cpp b/src/GUI/Plater/PlaterObject.cpp index 1ecee7b49..e0d9f598a 100644 --- a/src/GUI/Plater/PlaterObject.cpp +++ b/src/GUI/Plater/PlaterObject.cpp @@ -61,5 +61,36 @@ bool PlaterObject::instance_contains(Slic3r::Point point) const { return ep.contains(point); }); } +PlaterObject& PlaterObject::operator=(const PlaterObject& other) { + if (&other == this) return *this; + this->name = std::string(other.name); + this->identifier = other.identifier; + this->input_file = std::string(other.input_file); + this->input_file_obj_idx = other.input_file_obj_idx; + this->selected = false; + this->selected_instance = -1; + + this->thumbnail = Slic3r::ExPolygonCollection(other.thumbnail); + this->transformed_thumbnail = Slic3r::ExPolygonCollection(other.transformed_thumbnail); + + this->instance_thumbnails = std::vector(other.instance_thumbnails); + return *this; +} + +PlaterObject& PlaterObject::operator=(PlaterObject&& other) { + this->name = std::string(other.name); + this->identifier = other.identifier; + this->input_file = std::string(other.input_file); + this->input_file_obj_idx = other.input_file_obj_idx; + + this->selected = std::move(other.selected); + this->selected_instance = std::move(other.selected); + + this->thumbnail = Slic3r::ExPolygonCollection(other.thumbnail); + this->transformed_thumbnail = Slic3r::ExPolygonCollection(other.transformed_thumbnail); + + this->instance_thumbnails = std::vector(other.instance_thumbnails); + return *this; +} } } // Namespace Slic3r::GUI diff --git a/src/GUI/Plater/PlaterObject.hpp b/src/GUI/Plater/PlaterObject.hpp index d5f857583..2134d14b5 100644 --- a/src/GUI/Plater/PlaterObject.hpp +++ b/src/GUI/Plater/PlaterObject.hpp @@ -20,7 +20,6 @@ public: bool selected {false}; int selected_instance {-1}; - Slic3r::ExPolygonCollection thumbnail; Slic3r::ExPolygonCollection transformed_thumbnail; @@ -35,6 +34,12 @@ public: bool instance_contains(Slic3r::Point point) const; + PlaterObject& operator=(const PlaterObject& other); + PlaterObject& operator=(PlaterObject&& other); + + PlaterObject(const PlaterObject& other) = default; + PlaterObject() = default; + protected: const std::string LogChannel {"PlaterObject"}; diff --git a/src/GUI/Plater/Preview2D.hpp b/src/GUI/Plater/Preview2D.hpp index 9aa4c37f7..2a17b68da 100644 --- a/src/GUI/Plater/Preview2D.hpp +++ b/src/GUI/Plater/Preview2D.hpp @@ -17,6 +17,8 @@ public: Preview2D(wxWindow* parent, const wxSize& size, std::vector& _objects, std::shared_ptr _model, std::shared_ptr _config, std::shared_ptr _settings) : wxPanel(parent, wxID_ANY, wxDefaultPosition, size, wxTAB_TRAVERSAL), objects(_objects), model(_model), config(_config), settings(_settings) {} + + void enabled(bool enable = true) {} private: std::vector& objects; //< reference to parent vector std::shared_ptr model; diff --git a/src/GUI/Plater/Preview3D.hpp b/src/GUI/Plater/Preview3D.hpp index 2baa63900..49aa98c2d 100644 --- a/src/GUI/Plater/Preview3D.hpp +++ b/src/GUI/Plater/Preview3D.hpp @@ -17,6 +17,8 @@ public: Preview3D(wxWindow* parent, const wxSize& size, std::vector& _objects, std::shared_ptr _model, std::shared_ptr _config, std::shared_ptr _settings) : wxPanel(parent, wxID_ANY, wxDefaultPosition, size, wxTAB_TRAVERSAL), objects(_objects), model(_model), config(_config), settings(_settings) {} + + void enabled(bool enable = true) {} private: std::vector& objects; //< reference to parent vector std::shared_ptr model; diff --git a/src/GUI/Plater/PreviewDLP.hpp b/src/GUI/Plater/PreviewDLP.hpp index 090483cc1..17b52cae5 100644 --- a/src/GUI/Plater/PreviewDLP.hpp +++ b/src/GUI/Plater/PreviewDLP.hpp @@ -17,6 +17,8 @@ public: PreviewDLP(wxWindow* parent, const wxSize& size, std::vector& _objects, std::shared_ptr _model, std::shared_ptr _config, std::shared_ptr _settings) : wxPanel(parent, wxID_ANY, wxDefaultPosition, size, wxTAB_TRAVERSAL), objects(_objects), model(_model), config(_config), settings(_settings) {} + + void enabled(bool enable = true) {} private: std::vector& objects; //< reference to parent vector std::shared_ptr model;