mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-11 00:37:51 -06:00
Export to STL of SLA supports and pad
This commit is contained in:
parent
4a5992ba6e
commit
a3385278e5
5 changed files with 95 additions and 15 deletions
|
@ -1147,7 +1147,7 @@ void ObjectList::append_menu_item_fix_through_netfabb(wxMenu* menu)
|
||||||
void ObjectList::append_menu_item_export_stl(wxMenu* menu) const
|
void ObjectList::append_menu_item_export_stl(wxMenu* menu) const
|
||||||
{
|
{
|
||||||
append_menu_item(menu, wxID_ANY, _(L("Export as STL")) + dots, "",
|
append_menu_item(menu, wxID_ANY, _(L("Export as STL")) + dots, "",
|
||||||
[](wxCommandEvent&) { wxGetApp().plater()->export_stl(true); }, "", menu);
|
[](wxCommandEvent&) { wxGetApp().plater()->export_stl(false, true); }, "", menu);
|
||||||
menu->AppendSeparator();
|
menu->AppendSeparator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#include "libslic3r/Print.hpp"
|
#include "libslic3r/Print.hpp"
|
||||||
#include "libslic3r/Polygon.hpp"
|
#include "libslic3r/Polygon.hpp"
|
||||||
|
#include "libslic3r/SLAPrint.hpp"
|
||||||
|
|
||||||
#include "Tab.hpp"
|
#include "Tab.hpp"
|
||||||
#include "PresetBundle.hpp"
|
#include "PresetBundle.hpp"
|
||||||
|
@ -205,12 +206,30 @@ void MainFrame::add_created_tab(Tab* panel)
|
||||||
|
|
||||||
bool MainFrame::can_save() const
|
bool MainFrame::can_save() const
|
||||||
{
|
{
|
||||||
return (m_plater != nullptr) ? !m_plater->model().objects.empty() : false;
|
return (m_plater != nullptr) && !m_plater->model().objects.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MainFrame::can_export_model() const
|
bool MainFrame::can_export_model() const
|
||||||
{
|
{
|
||||||
return (m_plater != nullptr) ? !m_plater->model().objects.empty() : false;
|
return (m_plater != nullptr) && !m_plater->model().objects.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MainFrame::can_export_supports() const
|
||||||
|
{
|
||||||
|
if ((m_plater == nullptr) || (m_plater->printer_technology() != ptSLA) || m_plater->model().objects.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool can_export = false;
|
||||||
|
const PrintObjects& objects = m_plater->sla_print().objects();
|
||||||
|
for (const SLAPrintObject* object : objects)
|
||||||
|
{
|
||||||
|
if (object->has_mesh(slaposBasePool) || object->has_mesh(slaposSupportTree))
|
||||||
|
{
|
||||||
|
can_export = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return can_export;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MainFrame::can_export_gcode() const
|
bool MainFrame::can_export_gcode() const
|
||||||
|
@ -243,17 +262,17 @@ bool MainFrame::can_change_view() const
|
||||||
|
|
||||||
bool MainFrame::can_select() const
|
bool MainFrame::can_select() const
|
||||||
{
|
{
|
||||||
return (m_plater != nullptr) ? !m_plater->model().objects.empty() : false;
|
return (m_plater != nullptr) && !m_plater->model().objects.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MainFrame::can_delete() const
|
bool MainFrame::can_delete() const
|
||||||
{
|
{
|
||||||
return (m_plater != nullptr) ? !m_plater->is_selection_empty() : false;
|
return (m_plater != nullptr) && !m_plater->is_selection_empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MainFrame::can_delete_all() const
|
bool MainFrame::can_delete_all() const
|
||||||
{
|
{
|
||||||
return (m_plater != nullptr) ? !m_plater->model().objects.empty() : false;
|
return (m_plater != nullptr) && !m_plater->model().objects.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainFrame::on_dpi_changed(const wxRect &suggested_rect)
|
void MainFrame::on_dpi_changed(const wxRect &suggested_rect)
|
||||||
|
@ -346,6 +365,8 @@ void MainFrame::init_menubar()
|
||||||
export_menu->AppendSeparator();
|
export_menu->AppendSeparator();
|
||||||
wxMenuItem* item_export_stl = append_menu_item(export_menu, wxID_ANY, _(L("Export plate as &STL")) + dots, _(L("Export current plate as STL")),
|
wxMenuItem* item_export_stl = append_menu_item(export_menu, wxID_ANY, _(L("Export plate as &STL")) + dots, _(L("Export current plate as STL")),
|
||||||
[this](wxCommandEvent&) { if (m_plater) m_plater->export_stl(); }, menu_icon("export_plater"));
|
[this](wxCommandEvent&) { if (m_plater) m_plater->export_stl(); }, menu_icon("export_plater"));
|
||||||
|
wxMenuItem* item_export_stl_sla = append_menu_item(export_menu, wxID_ANY, _(L("Export plate as STL including supports")) + dots, _(L("Export current plate as STL including supports")),
|
||||||
|
[this](wxCommandEvent&) { if (m_plater) m_plater->export_stl(true); }, menu_icon("export_plater"));
|
||||||
wxMenuItem* item_export_amf = append_menu_item(export_menu, wxID_ANY, _(L("Export plate as &AMF")) + dots, _(L("Export current plate as AMF")),
|
wxMenuItem* item_export_amf = append_menu_item(export_menu, wxID_ANY, _(L("Export plate as &AMF")) + dots, _(L("Export current plate as AMF")),
|
||||||
[this](wxCommandEvent&) { if (m_plater) m_plater->export_amf(); }, menu_icon("export_plater"));
|
[this](wxCommandEvent&) { if (m_plater) m_plater->export_amf(); }, menu_icon("export_plater"));
|
||||||
export_menu->AppendSeparator();
|
export_menu->AppendSeparator();
|
||||||
|
@ -389,13 +410,14 @@ void MainFrame::init_menubar()
|
||||||
[this](wxCommandEvent&) { Close(false); });
|
[this](wxCommandEvent&) { Close(false); });
|
||||||
|
|
||||||
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(m_plater != nullptr); }, item_open->GetId());
|
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(m_plater != nullptr); }, item_open->GetId());
|
||||||
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable((m_plater != nullptr) && can_save()); }, item_save->GetId());
|
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_save()); }, item_save->GetId());
|
||||||
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable((m_plater != nullptr) && can_save()); }, item_save_as->GetId());
|
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_save()); }, item_save_as->GetId());
|
||||||
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(m_plater != nullptr); }, item_import_model->GetId());
|
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(m_plater != nullptr); }, item_import_model->GetId());
|
||||||
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable((m_plater != nullptr) && can_export_gcode()); }, item_export_gcode->GetId());
|
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_export_gcode()); }, item_export_gcode->GetId());
|
||||||
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable((m_plater != nullptr) && can_export_model()); }, item_export_stl->GetId());
|
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_export_model()); }, item_export_stl->GetId());
|
||||||
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable((m_plater != nullptr) && can_export_model()); }, item_export_amf->GetId());
|
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_export_supports()); }, item_export_stl_sla->GetId());
|
||||||
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable((m_plater != nullptr) && can_slice()); }, m_menu_item_reslice_now->GetId());
|
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_export_model()); }, item_export_amf->GetId());
|
||||||
|
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_slice()); }, m_menu_item_reslice_now->GetId());
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
|
|
@ -63,6 +63,7 @@ class MainFrame : public DPIFrame
|
||||||
|
|
||||||
bool can_save() const;
|
bool can_save() const;
|
||||||
bool can_export_model() const;
|
bool can_export_model() const;
|
||||||
|
bool can_export_supports() const;
|
||||||
bool can_export_gcode() const;
|
bool can_export_gcode() const;
|
||||||
bool can_slice() const;
|
bool can_slice() const;
|
||||||
bool can_change_view() const;
|
bool can_change_view() const;
|
||||||
|
|
|
@ -2925,7 +2925,7 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/
|
||||||
[this](wxCommandEvent&) { reload_from_disk(); });
|
[this](wxCommandEvent&) { reload_from_disk(); });
|
||||||
|
|
||||||
append_menu_item(menu, wxID_ANY, _(L("Export as STL")) + dots, _(L("Export the selected object as STL file")),
|
append_menu_item(menu, wxID_ANY, _(L("Export as STL")) + dots, _(L("Export the selected object as STL file")),
|
||||||
[this](wxCommandEvent&) { q->export_stl(true); });
|
[this](wxCommandEvent&) { q->export_stl(false, true); });
|
||||||
|
|
||||||
menu->AppendSeparator();
|
menu->AppendSeparator();
|
||||||
}
|
}
|
||||||
|
@ -3431,7 +3431,7 @@ void Plater::export_gcode()
|
||||||
p->export_gcode(std::move(output_path), PrintHostJob());
|
p->export_gcode(std::move(output_path), PrintHostJob());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Plater::export_stl(bool selection_only)
|
void Plater::export_stl(bool extended, bool selection_only)
|
||||||
{
|
{
|
||||||
if (p->model.objects.empty()) { return; }
|
if (p->model.objects.empty()) { return; }
|
||||||
|
|
||||||
|
@ -3466,8 +3466,65 @@ void Plater::export_stl(bool selection_only)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
mesh = p->model.mesh();
|
mesh = p->model.mesh();
|
||||||
|
|
||||||
|
if (extended && (p->printer_technology == ptSLA))
|
||||||
|
{
|
||||||
|
const PrintObjects& objects = p->sla_print.objects();
|
||||||
|
for (const SLAPrintObject* object : objects)
|
||||||
|
{
|
||||||
|
const ModelObject* model_object = object->model_object();
|
||||||
|
Transform3d mesh_trafo_inv = object->trafo().inverse();
|
||||||
|
bool is_left_handed = object->is_left_handed();
|
||||||
|
|
||||||
|
TriangleMesh pad_mesh;
|
||||||
|
bool has_pad_mesh = object->has_mesh(slaposBasePool);
|
||||||
|
if (has_pad_mesh)
|
||||||
|
{
|
||||||
|
pad_mesh = object->get_mesh(slaposBasePool);
|
||||||
|
pad_mesh.transform(mesh_trafo_inv);
|
||||||
|
}
|
||||||
|
|
||||||
|
TriangleMesh supports_mesh;
|
||||||
|
bool has_supports_mesh = object->has_mesh(slaposSupportTree);
|
||||||
|
if (has_supports_mesh)
|
||||||
|
{
|
||||||
|
supports_mesh = object->get_mesh(slaposSupportTree);
|
||||||
|
supports_mesh.transform(mesh_trafo_inv);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<SLAPrintObject::Instance>& obj_instances = object->instances();
|
||||||
|
for (const SLAPrintObject::Instance& obj_instance : obj_instances)
|
||||||
|
{
|
||||||
|
auto it = std::find_if(model_object->instances.begin(), model_object->instances.end(),
|
||||||
|
[&obj_instance](const ModelInstance *mi) { return mi->id() == obj_instance.instance_id; });
|
||||||
|
assert(it != model_object->instances.end());
|
||||||
|
|
||||||
|
if (it != model_object->instances.end())
|
||||||
|
{
|
||||||
|
int instance_idx = it - model_object->instances.begin();
|
||||||
|
const Transform3d& inst_transform = object->model_object()->instances[instance_idx]->get_transformation().get_matrix();
|
||||||
|
|
||||||
|
if (has_pad_mesh)
|
||||||
|
{
|
||||||
|
TriangleMesh inst_pad_mesh = pad_mesh;
|
||||||
|
inst_pad_mesh.transform(inst_transform, is_left_handed);
|
||||||
|
mesh.merge(inst_pad_mesh);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_supports_mesh)
|
||||||
|
{
|
||||||
|
TriangleMesh inst_supports_mesh = supports_mesh;
|
||||||
|
inst_supports_mesh.transform(inst_transform, is_left_handed);
|
||||||
|
mesh.merge(inst_supports_mesh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Slic3r::store_stl(path_u8.c_str(), &mesh, true);
|
Slic3r::store_stl(path_u8.c_str(), &mesh, true);
|
||||||
p->statusbar()->set_status_text(wxString::Format(_(L("STL file exported to %s")), path));
|
p->statusbar()->set_status_text(wxString::Format(_(L("STL file exported to %s")), path));
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,7 +163,7 @@ public:
|
||||||
void cut(size_t obj_idx, size_t instance_idx, coordf_t z, bool keep_upper = true, bool keep_lower = true, bool rotate_lower = false);
|
void cut(size_t obj_idx, size_t instance_idx, coordf_t z, bool keep_upper = true, bool keep_lower = true, bool rotate_lower = false);
|
||||||
|
|
||||||
void export_gcode();
|
void export_gcode();
|
||||||
void export_stl(bool selection_only = false);
|
void export_stl(bool extended = false, bool selection_only = false);
|
||||||
void export_amf();
|
void export_amf();
|
||||||
void export_3mf(const boost::filesystem::path& output_path = boost::filesystem::path());
|
void export_3mf(const boost::filesystem::path& output_path = boost::filesystem::path());
|
||||||
void reslice();
|
void reslice();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue