diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 94f01e25d..d2a7a23b1 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -594,7 +594,7 @@ sub new { $self->on_process_completed($event->GetInt ? undef : $event->GetString); }); -# XXX: ??? +# XXX: not done { my $timer_id = Wx::NewId(); $self->{apply_config_timer} = Wx::Timer->new($self, $timer_id); @@ -1179,7 +1179,7 @@ sub reset { $self->update; } -# XXX: not done +# XXX: VK: done sub increase { my ($self, $copies) = @_; $copies //= 1; @@ -1211,7 +1211,7 @@ sub increase { $self->schedule_background_process; } -# XXX: not done +# XXX: VK: done sub decrease { my ($self, $copies_asked) = @_; my $copies = $copies_asked // 1; @@ -1239,7 +1239,7 @@ sub decrease { $self->update; } -# XXX: not done +# XXX: VK: done sub set_number_of_copies { my ($self) = @_; # get current number of copies @@ -1258,8 +1258,8 @@ sub set_number_of_copies { } } -# XXX: not done (?) -sub _get_number_from_user { # XXX: Enrico +# XXX: VK: removed +sub _get_number_from_user { my ($self, $title, $prompt_message, $error_message, $default, $only_positive) = @_; for (;;) { my $value = Wx::GetTextFromUser($prompt_message, $title, $default, $self); @@ -1457,7 +1457,7 @@ sub changescale { $self->update; } -# XXX: not done +# XXX: VK: WIP sub arrange { my ($self) = @_; @@ -2057,7 +2057,7 @@ sub update { $self->Thaw; } -# XXX: done in sidebar? +# XXX: YS: done # When a printer technology is changed, the UI needs to be updated to show/hide needed preset combo boxes. sub show_preset_comboboxes{ my ($self, $showSLA) = @_; #if showSLA is oposite value to "ptFFF" @@ -2076,7 +2076,7 @@ sub show_preset_comboboxes{ $self->Layout; } -# XXX: not done +# XXX: YS: done # When a number of extruders changes, the UI needs to be updated to show a single filament selection combo box per extruder. # Also the wxTheApp->{preset_bundle}->filament_presets needs to be resized accordingly # and some reasonable default has to be selected for the additional extruders. @@ -2188,7 +2188,7 @@ sub on_config_change { $self->schedule_background_process; } -# XXX: not done +# XXX: YS: WIP sub item_changed_selection { my ($self, $obj_idx) = @_; @@ -2214,7 +2214,7 @@ sub collect_selections { return $selections; } -# XXX: not done +# XXX: YS: done, lambda on LEFT_DOWN # Called when clicked on the filament preset combo box. # When clicked on the icon, show the color picker. sub filament_color_box_lmouse_down @@ -2268,7 +2268,7 @@ sub filament_color_box_lmouse_down # } #} -# XXX: not done +# XXX: YS: done sub changed_object_settings { my ($self, $obj_idx, $parts_changed, $part_settings_changed) = @_; @@ -2464,7 +2464,7 @@ sub select_object { $self->selection_changed(1); } -# XXX: not done +# XXX: YS: WIP sub select_object_from_cpp { my ($self, $obj_idx, $vol_idx) = @_; diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 88e4c551a..e0cf14a57 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -609,6 +609,15 @@ ModelInstance* ModelObject::add_instance(const ModelInstance &other) return i; } +ModelInstance* ModelObject::add_instance(const Vec3d &offset, const Vec3d &scaling_factor, const Vec3d &rotation) +{ + auto *instance = add_instance(); + instance->set_offset(offset); + instance->set_scaling_factor(scaling_factor); + instance->set_rotation(rotation); + return instance; +} + void ModelObject::delete_instance(size_t idx) { ModelInstancePtrs::iterator i = this->instances.begin() + idx; diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index d9abc109a..695de6127 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -96,6 +96,7 @@ public: ModelInstance* add_instance(); ModelInstance* add_instance(const ModelInstance &instance); + ModelInstance* add_instance(const Vec3d &offset, const Vec3d &scaling_factor, const Vec3d &rotation); void delete_instance(size_t idx); void delete_last_instance(); void clear_instances(); diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index a646ab8fd..5bbeb3f6a 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -416,7 +416,8 @@ public: const PrintObjectConfig& default_object_config() const { return m_default_object_config; } const PrintRegionConfig& default_region_config() const { return m_default_region_config; } const PrintObjectPtrs& objects() const { return m_objects; } - const PrintObject* get_object(int idx) const { return m_objects[idx]; } + PrintObject* get_object(size_t idx) { return m_objects[idx]; } + const PrintObject* get_object(size_t idx) const { return m_objects[idx]; } const PrintRegionPtrs& regions() const { return m_regions; } const PlaceholderParser& placeholder_parser() const { return m_placeholder_parser; } PlaceholderParser& placeholder_parser() { return m_placeholder_parser; } diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index 68d4dac67..92e903911 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -572,7 +572,7 @@ void GLVolume::render_VBOs(int color_id, int detection_id, int worldmatrix_id) c ::glUniform4fv(color_id, 1, (const GLfloat*)color); } else - ::glColor4f(render_color[0], render_color[1], render_color[2], render_color[3]); + ::glColor4fv(render_color); if (detection_id != -1) ::glUniform1i(detection_id, shader_outside_printer_detection_enabled ? 1 : 0); @@ -591,7 +591,7 @@ void GLVolume::render_VBOs(int color_id, int detection_id, int worldmatrix_id) c if (color_id >= 0) ::glUniform4fv(color_id, 1, (const GLfloat*)render_color); else - ::glColor4f(render_color[0], render_color[1], render_color[2], render_color[3]); + ::glColor4fv(render_color); if (detection_id != -1) ::glUniform1i(detection_id, shader_outside_printer_detection_enabled ? 1 : 0); @@ -640,7 +640,7 @@ void GLVolume::render_legacy() const ::glDisableClientState(GL_VERTEX_ARRAY); ::glDisableClientState(GL_NORMAL_ARRAY); - ::glColor4f(render_color[0], render_color[1], render_color[2], render_color[3]); + ::glColor4fv(render_color); render(); ::glEnableClientState(GL_VERTEX_ARRAY); @@ -649,7 +649,7 @@ void GLVolume::render_legacy() const return; } - ::glColor4f(render_color[0], render_color[1], render_color[2], render_color[3]); + ::glColor4fv(render_color); ::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), indexed_vertex_array.vertices_and_normals_interleaved.data() + 3); ::glNormalPointer(GL_FLOAT, 6 * sizeof(float), indexed_vertex_array.vertices_and_normals_interleaved.data()); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index f3fb9b0be..a2067bbf3 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -600,7 +600,8 @@ bool GLCanvas3D::Bed::_are_equal(const Pointfs& bed_1, const Pointfs& bed_2) } GLCanvas3D::Axes::Axes() - : origin(0, 0, 0), length(0.0f) + : origin(Vec3d::Zero()) + , length(0.0f) { } @@ -615,11 +616,11 @@ void GLCanvas3D::Axes::render(bool depth_test) const ::glBegin(GL_LINES); // draw line for x axis ::glColor3f(1.0f, 0.0f, 0.0f); - ::glVertex3f((GLfloat)origin(0), (GLfloat)origin(1), (GLfloat)origin(2)); + ::glVertex3dv(origin.data()); ::glVertex3f((GLfloat)origin(0) + length, (GLfloat)origin(1), (GLfloat)origin(2)); // draw line for y axis ::glColor3f(0.0f, 1.0f, 0.0f); - ::glVertex3f((GLfloat)origin(0), (GLfloat)origin(1), (GLfloat)origin(2)); + ::glVertex3dv(origin.data()); ::glVertex3f((GLfloat)origin(0), (GLfloat)origin(1) + length, (GLfloat)origin(2)); ::glEnd(); // draw line for Z axis @@ -629,7 +630,7 @@ void GLCanvas3D::Axes::render(bool depth_test) const ::glBegin(GL_LINES); ::glColor3f(0.0f, 0.0f, 1.0f); - ::glVertex3f((GLfloat)origin(0), (GLfloat)origin(1), (GLfloat)origin(2)); + ::glVertex3dv(origin.data()); ::glVertex3f((GLfloat)origin(0), (GLfloat)origin(1), (GLfloat)origin(2) + length); ::glEnd(); } @@ -3234,13 +3235,7 @@ void GLCanvas3D::update_gizmos_data() #if ENABLE_EXTENDED_SELECTION bool enable_move_z = !m_selection.is_wipe_tower(); - bool enable_rotate_xy = m_selection.is_single_full_object() || m_selection.is_mixed(); - m_gizmos.enable_grabber(Gizmos::Move, 2, enable_move_z); - for (int i = 0; i < 2; ++i) - { - m_gizmos.enable_grabber(Gizmos::Rotate, i, enable_rotate_xy); - } if (m_selection.is_single_full_instance()) { @@ -4894,7 +4889,7 @@ void GLCanvas3D::_camera_tranform() const ::glRotatef(m_camera.phi, 0.0f, 0.0f, 1.0f); // yaw Vec3d neg_target = - m_camera.target; - ::glTranslatef((GLfloat)neg_target(0), (GLfloat)neg_target(1), (GLfloat)neg_target(2)); + ::glTranslated(neg_target(0), neg_target(1), neg_target(2)); } void GLCanvas3D::_picking_pass() const @@ -5003,9 +4998,9 @@ void GLCanvas3D::_render_background() const ::glVertex2f(1.0f, -1.0f); if (m_dynamic_background_enabled && _is_any_volume_outside()) - ::glColor3f(ERROR_BG_COLOR[0], ERROR_BG_COLOR[1], ERROR_BG_COLOR[2]); + ::glColor3fv(ERROR_BG_COLOR); else - ::glColor3f(DEFAULT_BG_COLOR[0], DEFAULT_BG_COLOR[1], DEFAULT_BG_COLOR[2]); + ::glColor3fv(DEFAULT_BG_COLOR); ::glVertex2f(1.0f, 1.0f); ::glVertex2f(-1.0f, 1.0f); @@ -5172,7 +5167,7 @@ void GLCanvas3D::_render_volumes(bool fake_colors) const else { vol->set_render_color(); - ::glColor4f(vol->render_color[0], vol->render_color[1], vol->render_color[2], vol->render_color[3]); + ::glColor4fv(vol->render_color); } vol->render(); diff --git a/src/slic3r/GUI/GLGizmo.cpp b/src/slic3r/GUI/GLGizmo.cpp index 72bf18de9..ced0ca85b 100644 --- a/src/slic3r/GUI/GLGizmo.cpp +++ b/src/slic3r/GUI/GLGizmo.cpp @@ -142,15 +142,15 @@ void GLGizmoBase::Grabber::render(const BoundingBoxf3& box, const float* render_ if (use_lighting) ::glEnable(GL_LIGHTING); - ::glColor3f((GLfloat)render_color[0], (GLfloat)render_color[1], (GLfloat)render_color[2]); + ::glColor3fv(render_color); ::glPushMatrix(); - ::glTranslatef((GLfloat)center(0), (GLfloat)center(1), (GLfloat)center(2)); + ::glTranslated(center(0), center(1), center(2)); - float rad_to_deg = 180.0f / (GLfloat)PI; - ::glRotatef((GLfloat)angles(0) * rad_to_deg, 1.0f, 0.0f, 0.0f); - ::glRotatef((GLfloat)angles(1) * rad_to_deg, 0.0f, 1.0f, 0.0f); - ::glRotatef((GLfloat)angles(2) * rad_to_deg, 0.0f, 0.0f, 1.0f); + double rad_to_deg = 180.0 / (double)PI; + ::glRotated(angles(0) * rad_to_deg, 1.0, 0.0, 0.0); + ::glRotated(angles(1) * rad_to_deg, 0.0, 1.0, 0.0); + ::glRotated(angles(2) * rad_to_deg, 0.0, 0.0, 1.0); // face min x ::glPushMatrix(); @@ -568,7 +568,7 @@ void GLGizmoRotate::render_grabber(const BoundingBoxf3& box) const ::glBegin(GL_LINES); ::glVertex3f(0.0f, 0.0f, 0.0f); - ::glVertex3f((GLfloat)m_grabbers[0].center(0), (GLfloat)m_grabbers[0].center(1), (GLfloat)m_grabbers[0].center(2)); + ::glVertex3dv(m_grabbers[0].center.data()); ::glEnd(); ::memcpy((void*)m_grabbers[0].color, (const void*)m_highlight_color, 3 * sizeof(float)); @@ -577,7 +577,7 @@ void GLGizmoRotate::render_grabber(const BoundingBoxf3& box) const void GLGizmoRotate::transform_to_local() const { - ::glTranslatef((GLfloat)m_center(0), (GLfloat)m_center(1), (GLfloat)m_center(2)); + ::glTranslated(m_center(0), m_center(1), m_center(2)); switch (m_axis) { @@ -965,8 +965,8 @@ void GLGizmoScale3D::render_grabbers_connection(unsigned int id_1, unsigned int if ((id_1 < grabbers_count) && (id_2 < grabbers_count)) { ::glBegin(GL_LINES); - ::glVertex3f((GLfloat)m_grabbers[id_1].center(0), (GLfloat)m_grabbers[id_1].center(1), (GLfloat)m_grabbers[id_1].center(2)); - ::glVertex3f((GLfloat)m_grabbers[id_2].center(0), (GLfloat)m_grabbers[id_2].center(1), (GLfloat)m_grabbers[id_2].center(2)); + ::glVertex3dv(m_grabbers[id_1].center.data()); + ::glVertex3dv(m_grabbers[id_2].center.data()); ::glEnd(); } } @@ -1170,8 +1170,8 @@ void GLGizmoMove3D::on_render(const BoundingBoxf3& box) const { ::glColor3fv(AXES_COLOR[i]); ::glBegin(GL_LINES); - ::glVertex3f(center(0), center(1), center(2)); - ::glVertex3f((GLfloat)m_grabbers[i].center(0), (GLfloat)m_grabbers[i].center(1), (GLfloat)m_grabbers[i].center(2)); + ::glVertex3dv(center.data()); + ::glVertex3dv(m_grabbers[i].center.data()); ::glEnd(); } } @@ -1184,8 +1184,8 @@ void GLGizmoMove3D::on_render(const BoundingBoxf3& box) const // draw axis ::glColor3fv(AXES_COLOR[m_hover_id]); ::glBegin(GL_LINES); - ::glVertex3f(center(0), center(1), center(2)); - ::glVertex3f((GLfloat)m_grabbers[m_hover_id].center(0), (GLfloat)m_grabbers[m_hover_id].center(1), (GLfloat)m_grabbers[m_hover_id].center(2)); + ::glVertex3dv(center.data()); + ::glVertex3dv(m_grabbers[m_hover_id].center.data()); ::glEnd(); // draw grabber @@ -1303,7 +1303,7 @@ void GLGizmoFlatten::on_render(const BoundingBoxf3& box) const #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM ::glBegin(GL_POLYGON); for (const Vec3d& vertex : m_planes[i].vertices) - ::glVertex3f((GLfloat)vertex(0), (GLfloat)vertex(1), (GLfloat)vertex(2)); + ::glVertex3dv(vertex.data()); ::glEnd(); ::glPopMatrix(); } @@ -1330,7 +1330,7 @@ void GLGizmoFlatten::on_render_for_picking(const BoundingBoxf3& box) const #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM ::glBegin(GL_POLYGON); for (const Vec3d& vertex : m_planes[i].vertices) - ::glVertex3f((GLfloat)vertex(0), (GLfloat)vertex(1), (GLfloat)vertex(2)); + ::glVertex3dv(vertex.data()); ::glEnd(); ::glPopMatrix(); } diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index ecd1ddea2..505a45125 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -58,9 +58,9 @@ wxFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAUL SLIC3R_VERSION + _(L(" - Remember to check for updates at http://github.com/prusa3d/slic3r/releases"))); - // m_appController->set_model(m_plater->model); - // m_appController->set_print(m_plater->print); - // m_plater->appController = m_appController; + m_appController->set_model(&m_plater->model()); + m_appController->set_print(&m_plater->print()); + GUI::set_gui_appctl(); // Make the global status bar and its progress indicator available in C++ diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp index aa2041a36..ed2646b69 100644 --- a/src/slic3r/GUI/MainFrame.hpp +++ b/src/slic3r/GUI/MainFrame.hpp @@ -106,6 +106,8 @@ public: void select_tab(size_t tab) const; void select_view(const std::string& direction); + AppController* app_controller() { return m_appController; } + std::vector<PresetTab>& get_preset_tabs(); Plater* m_plater { nullptr }; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index f130ef449..72ef47670 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -31,6 +31,7 @@ #include "libslic3r/Format/STL.hpp" #include "libslic3r/Format/AMF.hpp" #include "libslic3r/Format/3mf.hpp" +#include "slic3r/AppController.hpp" #include "GUI.hpp" #include "GUI_App.hpp" #include "GUI_ObjectList.hpp" @@ -756,9 +757,6 @@ struct Plater::priv void remove(size_t obj_idx); void reset(); - void increase(size_t num = 1); - void decrease(size_t num = 1); - void set_number_of_copies(); void rotate(); void mirror(const Axis &axis); void scale(); @@ -781,9 +779,6 @@ struct Plater::priv void on_layer_editing_toggled(bool enable); void on_action_add(SimpleEvent&); - void on_action_arrange(SimpleEvent&); - void on_action_more(SimpleEvent&); - void on_action_fewer(SimpleEvent&); void on_action_split(SimpleEvent&); void on_action_cut(SimpleEvent&); void on_action_settings(SimpleEvent&); @@ -886,7 +881,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : canvas3D->Bind(EVT_GLCANVAS_ARRANGE, [this](SimpleEvent&) { arrange(); }); canvas3D->Bind(EVT_GLCANVAS_ROTATE_OBJECT, [this](Event<int> &evt) { /*TODO: call rotate */ }); canvas3D->Bind(EVT_GLCANVAS_SCALE_UNIFORMLY, [this](SimpleEvent&) { scale(); }); - canvas3D->Bind(EVT_GLCANVAS_INCREASE_OBJECTS, [this](Event<int> &evt) { evt.data == 1 ? increase() : decrease(); }); + canvas3D->Bind(EVT_GLCANVAS_INCREASE_OBJECTS, [q](Event<int> &evt) { evt.data == 1 ? q->increase() : q->decrease(); }); canvas3D->Bind(EVT_GLCANVAS_INSTANCE_MOVED, [this](SimpleEvent&) { update(); }); canvas3D->Bind(EVT_GLCANVAS_WIPETOWER_MOVED, &priv::on_wipetower_moved, this); canvas3D->Bind(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, &priv::on_enable_action_buttons, this); @@ -895,9 +890,9 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : canvas3D->Bind(EVT_GLTOOLBAR_ADD, &priv::on_action_add, this); canvas3D->Bind(EVT_GLTOOLBAR_DELETE, [q](SimpleEvent&) { q->remove_selected(); } ); canvas3D->Bind(EVT_GLTOOLBAR_DELETE_ALL, [this](SimpleEvent&) { reset(); }); - canvas3D->Bind(EVT_GLTOOLBAR_ARRANGE, &priv::on_action_arrange, this); - canvas3D->Bind(EVT_GLTOOLBAR_MORE, &priv::on_action_more, this); - canvas3D->Bind(EVT_GLTOOLBAR_FEWER, &priv::on_action_fewer, this); + canvas3D->Bind(EVT_GLTOOLBAR_ARRANGE, [this](SimpleEvent&) { arrange(); }); + canvas3D->Bind(EVT_GLTOOLBAR_MORE, [q](SimpleEvent&) { q->increase(); }); + canvas3D->Bind(EVT_GLTOOLBAR_FEWER, [q](SimpleEvent&) { q->decrease(); }); canvas3D->Bind(EVT_GLTOOLBAR_SPLIT, &priv::on_action_split, this); canvas3D->Bind(EVT_GLTOOLBAR_CUT, &priv::on_action_cut, this); canvas3D->Bind(EVT_GLTOOLBAR_SETTINGS, &priv::on_action_settings, this); @@ -1161,8 +1156,8 @@ std::vector<size_t> Plater::priv::load_model_objects(const ModelObjectPtrs &mode update(); _3DScene::zoom_to_volumes(canvas3D); - // TODO - // $self->object_list_changed; + object_list_changed(); + // $self->schedule_background_process; return obj_idxs; @@ -1388,21 +1383,6 @@ void Plater::priv::reset() update(); } -void Plater::priv::increase(size_t num) -{ - // TODO -} - -void Plater::priv::decrease(size_t num) -{ - // TODO -} - -void Plater::priv::set_number_of_copies() -{ - // TODO -} - void Plater::priv::rotate() { // TODO @@ -1438,7 +1418,14 @@ void Plater::priv::scale() void Plater::priv::arrange() { - // TODO + // $self->stop_background_process; + + main_frame->app_controller()->arrange_model(); + + // ignore arrange failures on purpose: user has visual feedback and we don't need to warn him + // when parts don't fit in print bed + + update(); } void Plater::priv::split_object() @@ -1574,21 +1561,6 @@ void Plater::priv::on_action_add(SimpleEvent&) load_files(input_paths); } -void Plater::priv::on_action_arrange(SimpleEvent&) -{ - // TODO -} - -void Plater::priv::on_action_more(SimpleEvent&) -{ - // TODO -} - -void Plater::priv::on_action_fewer(SimpleEvent&) -{ - // TODO -} - void Plater::priv::on_action_split(SimpleEvent&) { // TODO @@ -1718,7 +1690,10 @@ Plater::~Plater() } Sidebar& Plater::sidebar() { return *p->sidebar; } -Model& Plater::model() { return p->model; } +Model& Plater::model() { return p->model; } +Print& Plater::print() { return p->print; } + +void Plater::load_files(const std::vector<fs::path> &input_files) { p->load_files(input_files); } void Plater::update(bool force_autocenter) { p->update(force_autocenter); } void Plater::remove(size_t obj_idx) { p->remove(obj_idx); } @@ -1731,7 +1706,69 @@ void Plater::remove_selected() } } -void Plater::load_files(const std::vector<fs::path> &input_files) { p->load_files(input_files); } +void Plater::increase(size_t num) +{ + const auto obj_idx = p->selected_object(); + if (! obj_idx) { return; } + + auto *model_object = p->model.objects[*obj_idx]; + auto *model_instance = model_object->instances[model_object->instances.size() - 1]; + + // $self->stop_background_process; + + float offset = 10.0; + for (size_t i = 0; i < num; i++, offset += 10.0) { + Vec3d offset_vec = model_instance->get_offset() + Vec3d(offset, offset, 0.0); + auto *new_instance = model_object->add_instance(offset_vec, model_instance->get_scaling_factor(), model_instance->get_rotation()); + p->print.get_object(*obj_idx)->add_copy(Slic3r::to_2d(offset_vec)); + } + + sidebar().obj_list()->set_object_count(*obj_idx, model_object->instances.size()); + + if (p->get_config("autocenter") == "1") { + p->arrange(); + } else { + p->update(); + } + + p->selection_changed(); + + // $self->schedule_background_process; +} + +void Plater::decrease(size_t num) +{ + const auto obj_idx = p->selected_object(); + if (! obj_idx) { return; } + + auto *model_object = p->model.objects[*obj_idx]; + if (model_object->instances.size() > num) { + for (size_t i = 0; i < num; i++) { + model_object->delete_last_instance(); + p->print.get_object(*obj_idx)->delete_last_copy(); + } + sidebar().obj_list()->set_object_count(*obj_idx, model_object->instances.size()); + } else { + remove(*obj_idx); + } + + p->update(); +} + +void Plater::set_number_of_copies(size_t num) +{ + const auto obj_idx = p->selected_object(); + if (! obj_idx) { return; } + + auto *model_object = p->model.objects[*obj_idx]; + + auto diff = (ptrdiff_t)num - (ptrdiff_t)model_object->instances.size(); + if (diff > 0) { + increase(diff); + } else if (diff < 0) { + decrease(-diff); + } +} fs::path Plater::export_gcode(const fs::path &output_path) { diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index bcc295043..b25b43b7d 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -17,6 +17,7 @@ class wxGLCanvas; namespace Slic3r { class Model; +class Print; namespace GUI { @@ -92,13 +93,17 @@ public: ~Plater(); Sidebar& sidebar(); - Model& model(); + Model& model(); + Print& print(); + + void load_files(const std::vector<boost::filesystem::path> &input_files); void update(bool force_autocenter = false); void remove(size_t obj_idx); void remove_selected(); - - void load_files(const std::vector<boost::filesystem::path> &input_files); + void increase(size_t num = 1); + void decrease(size_t num = 1); + void set_number_of_copies(size_t num); // Note: empty path means "use the default" boost::filesystem::path export_gcode(const boost::filesystem::path &output_path = boost::filesystem::path());