diff --git a/src/libslic3r/Format/AMF.cpp b/src/libslic3r/Format/AMF.cpp index 00ed0d9373..be02616346 100644 --- a/src/libslic3r/Format/AMF.cpp +++ b/src/libslic3r/Format/AMF.cpp @@ -32,6 +32,9 @@ // 2 : Added z component of offset // Added x and y components of rotation // Added x, y and z components of scale +#if ENABLE_MIRROR +// Added x, y and z components of mirror +#endif // ENABLE_MIRROR const unsigned int VERSION_AMF = 2; const char* SLIC3RPE_AMF_VERSION = "slic3rpe_amf_version"; @@ -126,14 +129,27 @@ struct AMFParserContext NODE_TYPE_RY, // amf/constellation/instance/ry NODE_TYPE_RZ, // amf/constellation/instance/rz NODE_TYPE_SCALE, // amf/constellation/instance/scale - NODE_TYPE_SCALEX, // amf/constellation/instance/scalex - NODE_TYPE_SCALEY, // amf/constellation/instance/scaley - NODE_TYPE_SCALEZ, // amf/constellation/instance/scalez + NODE_TYPE_SCALEX, // amf/constellation/instance/scalex + NODE_TYPE_SCALEY, // amf/constellation/instance/scaley + NODE_TYPE_SCALEZ, // amf/constellation/instance/scalez +#if ENABLE_MIRROR + NODE_TYPE_MIRRORX, // amf/constellation/instance/mirrorx + NODE_TYPE_MIRRORY, // amf/constellation/instance/mirrory + NODE_TYPE_MIRRORZ, // amf/constellation/instance/mirrorz +#endif // ENABLE_MIRROR NODE_TYPE_METADATA, // anywhere under amf/*/metadata }; struct Instance { +#if ENABLE_MIRROR + Instance() + : deltax_set(false), deltay_set(false), deltaz_set(false) + , rx_set(false), ry_set(false), rz_set(false) + , scalex_set(false), scaley_set(false), scalez_set(false) + , mirrorx_set(false), mirrory_set(false), mirrorz_set(false) {} +#else Instance() : deltax_set(false), deltay_set(false), deltaz_set(false), rx_set(false), ry_set(false), rz_set(false), scalex_set(false), scaley_set(false), scalez_set(false) {} +#endif // ENABLE_MIRROR // Shift in the X axis. float deltax; bool deltax_set; @@ -159,6 +175,15 @@ struct AMFParserContext bool scaley_set; float scalez; bool scalez_set; +#if ENABLE_MIRROR + // Mirroring factors + float mirrorx; + bool mirrorx_set; + float mirrory; + bool mirrory_set; + float mirrorz; + bool mirrorz_set; +#endif // ENABLE_MIRROR }; struct Object { @@ -289,6 +314,14 @@ void AMFParserContext::startElement(const char *name, const char **atts) node_type_new = NODE_TYPE_SCALEZ; else if (strcmp(name, "scale") == 0) node_type_new = NODE_TYPE_SCALE; +#if ENABLE_MIRROR + else if (strcmp(name, "mirrorx") == 0) + node_type_new = NODE_TYPE_MIRRORX; + else if (strcmp(name, "mirrory") == 0) + node_type_new = NODE_TYPE_MIRRORY; + else if (strcmp(name, "mirrorz") == 0) + node_type_new = NODE_TYPE_MIRRORZ; +#endif // ENABLE_MIRROR } break; case 4: @@ -345,16 +378,23 @@ void AMFParserContext::characters(const XML_Char *s, int len) { switch (m_path.size()) { case 4: - if (m_path.back() == NODE_TYPE_DELTAX || - m_path.back() == NODE_TYPE_DELTAY || - m_path.back() == NODE_TYPE_DELTAZ || + if (m_path.back() == NODE_TYPE_DELTAX || + m_path.back() == NODE_TYPE_DELTAY || + m_path.back() == NODE_TYPE_DELTAZ || m_path.back() == NODE_TYPE_RX || m_path.back() == NODE_TYPE_RY || m_path.back() == NODE_TYPE_RZ || m_path.back() == NODE_TYPE_SCALEX || m_path.back() == NODE_TYPE_SCALEY || m_path.back() == NODE_TYPE_SCALEZ || +#if ENABLE_MIRROR + m_path.back() == NODE_TYPE_SCALE || + m_path.back() == NODE_TYPE_MIRRORX || + m_path.back() == NODE_TYPE_MIRRORY || + m_path.back() == NODE_TYPE_MIRRORZ) +#else m_path.back() == NODE_TYPE_SCALE) +#endif // ENABLE_MIRROR m_value[0].append(s, len); break; case 6: @@ -446,6 +486,26 @@ void AMFParserContext::endElement(const char * /* name */) m_instance->scalez_set = true; m_value[0].clear(); break; +#if ENABLE_MIRROR + case NODE_TYPE_MIRRORX: + assert(m_instance); + m_instance->mirrorx = float(atof(m_value[0].c_str())); + m_instance->mirrorx_set = true; + m_value[0].clear(); + break; + case NODE_TYPE_MIRRORY: + assert(m_instance); + m_instance->mirrory = float(atof(m_value[0].c_str())); + m_instance->mirrory_set = true; + m_value[0].clear(); + break; + case NODE_TYPE_MIRRORZ: + assert(m_instance); + m_instance->mirrorz = float(atof(m_value[0].c_str())); + m_instance->mirrorz_set = true; + m_value[0].clear(); + break; +#endif // ENABLE_MIRROR // Object vertices: case NODE_TYPE_VERTEX: @@ -585,6 +645,9 @@ void AMFParserContext::endDocument() mi->set_offset(Vec3d(instance.deltax_set ? (double)instance.deltax : 0.0, instance.deltay_set ? (double)instance.deltay : 0.0, instance.deltaz_set ? (double)instance.deltaz : 0.0)); mi->set_rotation(Vec3d(instance.rx_set ? (double)instance.rx : 0.0, instance.ry_set ? (double)instance.ry : 0.0, instance.rz_set ? (double)instance.rz : 0.0)); mi->set_scaling_factor(Vec3d(instance.scalex_set ? (double)instance.scalex : 1.0, instance.scaley_set ? (double)instance.scaley : 1.0, instance.scalez_set ? (double)instance.scalez : 1.0)); +#if ENABLE_MIRROR + mi->set_mirror(Vec3d(instance.mirrorx_set ? (double)instance.mirrorx : 1.0, instance.mirrory_set ? (double)instance.mirrory : 1.0, instance.mirrorz_set ? (double)instance.mirrorz : 1.0)); +#endif // ENABLE_MIRROR } } } @@ -891,6 +954,11 @@ bool store_amf(const char *path, Model *model, Print* print, bool export_print_c " %lf\n" " %lf\n" " %lf\n" +#if ENABLE_MIRROR + " %lf\n" + " %lf\n" + " %lf\n" +#endif // ENABLE_MIRROR " \n", object_id, instance->get_offset(X), @@ -901,7 +969,14 @@ bool store_amf(const char *path, Model *model, Print* print, bool export_print_c instance->get_rotation(Z), instance->get_scaling_factor(X), instance->get_scaling_factor(Y), +#if ENABLE_MIRROR + instance->get_scaling_factor(Z), + instance->get_mirror(X), + instance->get_mirror(Y), + instance->get_mirror(Z)); +#else instance->get_scaling_factor(Z)); +#endif // ENABLE_MIRROR //FIXME missing instance->scaling_factor instances.append(buf); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 4bb0f499f4..7d47ff8f6c 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3432,7 +3432,6 @@ int GLCanvas3D::get_in_object_volume_id(int scene_vol_idx) const #if ENABLE_EXTENDED_SELECTION void GLCanvas3D::mirror_selection(Axis axis) { - m_regenerate_volumes = false; m_selection.mirror(axis); _on_mirror(); wxGetApp().obj_manipul()->update_settings_value(m_selection); @@ -3457,7 +3456,12 @@ void GLCanvas3D::reload_scene(bool force) #if ENABLE_EXTENDED_SELECTION if (m_regenerate_volumes) + { reset_volumes(); + + // to update the toolbar + post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT)); + } #endif // ENABLE_EXTENDED_SELECTION set_bed_shape(dynamic_cast(m_config->option("bed_shape"))->values); @@ -3477,9 +3481,6 @@ void GLCanvas3D::reload_scene(bool force) { load_object(*m_model, obj_idx); } - - // to update the toolbar - post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT)); } update_gizmos_data(); @@ -3858,7 +3859,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) case Gizmos::Scale: { #if ENABLE_EXTENDED_SELECTION - m_regenerate_volumes = false; m_selection.scale(m_gizmos.get_scale()); _on_scale(); #else @@ -3875,7 +3875,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) case Gizmos::Rotate: { #if ENABLE_EXTENDED_SELECTION - m_regenerate_volumes = false; m_selection.rotate(m_gizmos.get_rotation()); _on_rotate(); #else @@ -3958,7 +3957,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) if (m_gizmos.get_current_type() == Gizmos::Flatten) { // Rotate the object so the normal points downward: #if ENABLE_EXTENDED_SELECTION - m_regenerate_volumes = false; m_selection.rotate(m_gizmos.get_flattening_rotation()); _on_flatten(); wxGetApp().obj_manipul()->update_settings_value(m_selection); @@ -4397,7 +4395,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) case Gizmos::Scale: { #if ENABLE_EXTENDED_SELECTION - m_regenerate_volumes = false; _on_scale(); #endif // ENABLE_EXTENDED_SELECTION break; @@ -4405,7 +4402,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) case Gizmos::Rotate: { #if ENABLE_EXTENDED_SELECTION - m_regenerate_volumes = false; _on_rotate(); #else post_event(Vec3dEvent(EVT_GIZMO_ROTATE, m_gizmos.get_rotation())); diff --git a/src/slic3r/GUI/GUI_Utils.cpp b/src/slic3r/GUI/GUI_Utils.cpp index fb494ed232..5a7ece5865 100644 --- a/src/slic3r/GUI/GUI_Utils.cpp +++ b/src/slic3r/GUI/GUI_Utils.cpp @@ -28,6 +28,7 @@ CheckboxFileDialog::ExtraPanel::ExtraPanel(wxWindow *parent) auto* sizer = new wxBoxSizer(wxHORIZONTAL); cbox = new wxCheckBox(this, wxID_ANY, checkbox_label); + cbox->SetValue(true); sizer->AddSpacer(5); sizer->Add(this->cbox, 0, wxEXPAND | wxALL, 5); SetSizer(sizer); diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 6a202ad4ce..f1e6595f78 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -300,7 +300,7 @@ void MainFrame::init_menubar() append_menu_item(m_plater_menu, wxID_ANY, _(L("Export plate as STL...")), _(L("Export current plate as STL")), [this](wxCommandEvent&){ /*m_plater->export_stl(); */}, "brick_go.png"); append_menu_item(m_plater_menu, wxID_ANY, _(L("Export plate as AMF...")), _(L("Export current plate as AMF")), - [this](wxCommandEvent&){ /*m_plater->export_amf();*/ }, "brick_go.png"); + [this](wxCommandEvent&){ m_plater->export_amf(); }, "brick_go.png"); append_menu_item(m_plater_menu, wxID_ANY, _(L("Export plate as 3MF...")), _(L("Export current plate as 3MF")), [this](wxCommandEvent&){ m_plater->export_3mf(); }, "brick_go.png"); } diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index b5cb216256..bef4d5a868 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -850,7 +850,9 @@ private: bool layers_height_allowed() const; bool can_delete_all() const; bool can_arrange() const; +#if ENABLE_MIRROR bool can_mirror() const; +#endif // ENABLE_MIRROR #endif // ENABLE_EXTENDED_SELECTION }; @@ -1256,14 +1258,17 @@ std::unique_ptr Plater::priv::get_export_file(GUI::FileType wxString wildcard; switch (file_type) { case FT_STL: - case FT_AMF: - case FT_3MF: wildcard = file_wildcards[FT_STL]; - break; - + break; + case FT_AMF: + wildcard = file_wildcards[FT_AMF]; + break; + case FT_3MF: + wildcard = file_wildcards[FT_3MF]; + break; default: wildcard = file_wildcards[FT_MODEL]; - break; + break; } fs::path output_file(print.output_filepath(std::string())); @@ -1899,6 +1904,7 @@ bool Plater::priv::init_object_menu() object_menu.AppendSeparator(); +#if ENABLE_MIRROR wxMenu* mirror_menu = new wxMenu(); if (mirror_menu == nullptr) return false; @@ -1911,6 +1917,7 @@ bool Plater::priv::init_object_menu() [this](wxCommandEvent&){ mirror(Z); }, "bullet_blue.png", &object_menu); wxMenuItem* item_mirror = append_submenu(&object_menu, mirror_menu, wxID_ANY, _(L("Mirror")), _(L("Mirror the selected object"))); +#endif // ENABLE_MIRROR wxMenuItem* item_split = append_menu_item(&object_menu, wxID_ANY, _(L("Split")), _(L("Split the selected object into individual parts")), [this](wxCommandEvent&){ split_object(); }, "shape_ungroup.png"); @@ -1919,7 +1926,9 @@ bool Plater::priv::init_object_menu() // ui updates needs to be binded to the parent panel if (q != nullptr) { +#if ENABLE_MIRROR q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_mirror()); }, item_mirror->GetId()); +#endif // ENABLE_MIRROR q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_delete_object()); }, item_delete->GetId()); q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_increase_instances()); }, item_increase->GetId()); q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_decrease_instances()); }, item_decrease->GetId()); @@ -1976,10 +1985,12 @@ bool Plater::priv::can_arrange() const return !model.objects.empty(); } +#if ENABLE_MIRROR bool Plater::priv::can_mirror() const { return get_selection().is_from_single_instance(); } +#endif // ENABLE_MIRROR #endif // ENABLE_EXTENDED_SELECTION // Plater / Public