WIP: Plater, build fixes
This commit is contained in:
parent
99fe5761d8
commit
1f926964ee
@ -56,10 +56,10 @@ inline Vec2i64 to_2d(const Vec3i64 &pt3) { return Vec2i64(pt3(0), pt3(1)); }
|
|||||||
inline Vec2f to_2d(const Vec3f &pt3) { return Vec2f (pt3(0), pt3(1)); }
|
inline Vec2f to_2d(const Vec3f &pt3) { return Vec2f (pt3(0), pt3(1)); }
|
||||||
inline Vec2d to_2d(const Vec3d &pt3) { return Vec2d (pt3(0), pt3(1)); }
|
inline Vec2d to_2d(const Vec3d &pt3) { return Vec2d (pt3(0), pt3(1)); }
|
||||||
|
|
||||||
// inline Vec3crd to_3d(const Vec2crd &pt2, coord_t z) { return Vec3crd(pt2(0), pt2(1), z); }
|
inline Vec3d to_3d(const Vec2d &v, double z) { return Vec3d(v(0), v(1), z); }
|
||||||
// inline Vec3i64 to_3d(const Vec2i64 &pt2, int64_t z) { return Vec3i64(pt2(0), pt2(1), z); }
|
inline Vec3f to_3d(const Vec2f &v, float z) { return Vec3f(v(0), v(1), z); }
|
||||||
// inline Vec3f to_3d(const Vec2f &pt2, float z) { return Vec3f (pt2(0), pt2(1), z); }
|
inline Vec3i64 to_3d(const Vec2i64 &v, float z) { return Vec3i64(v(0), v(1), z); }
|
||||||
// inline Vec3d to_3d(const Vec2d &pt2, double z) { return Vec3d (pt2(0), pt2(1), z); }
|
inline Vec3crd to_3d(const Vec3crd &p, coord_t z) { return Vec3crd(p(0), p(1), z); }
|
||||||
|
|
||||||
inline Vec2d unscale(coord_t x, coord_t y) { return Vec2d(unscale<double>(x), unscale<double>(y)); }
|
inline Vec2d unscale(coord_t x, coord_t y) { return Vec2d(unscale<double>(x), unscale<double>(y)); }
|
||||||
inline Vec2d unscale(const Vec2crd &pt) { return Vec2d(unscale<double>(pt(0)), unscale<double>(pt(1))); }
|
inline Vec2d unscale(const Vec2crd &pt) { return Vec2d(unscale<double>(pt(0)), unscale<double>(pt(1))); }
|
||||||
|
@ -419,6 +419,7 @@ public:
|
|||||||
const PrintObject* get_object(int idx) const { return m_objects[idx]; }
|
const PrintObject* get_object(int idx) const { return m_objects[idx]; }
|
||||||
const PrintRegionPtrs& regions() const { return m_regions; }
|
const PrintRegionPtrs& regions() const { return m_regions; }
|
||||||
const PlaceholderParser& placeholder_parser() const { return m_placeholder_parser; }
|
const PlaceholderParser& placeholder_parser() const { return m_placeholder_parser; }
|
||||||
|
PlaceholderParser& placeholder_parser() { return m_placeholder_parser; }
|
||||||
|
|
||||||
// Returns extruder this eec should be printed with, according to PrintRegion config:
|
// Returns extruder this eec should be printed with, according to PrintRegion config:
|
||||||
static int get_extruder(const ExtrusionEntityCollection& fill, const PrintRegion ®ion);
|
static int get_extruder(const ExtrusionEntityCollection& fill, const PrintRegion ®ion);
|
||||||
|
@ -39,6 +39,8 @@ add_library(libslic3r_gui STATIC
|
|||||||
${LIBDIR}/slic3r/GUI/GUI_PreviewIface.hpp
|
${LIBDIR}/slic3r/GUI/GUI_PreviewIface.hpp
|
||||||
${LIBDIR}/slic3r/GUI/GUI_App.cpp
|
${LIBDIR}/slic3r/GUI/GUI_App.cpp
|
||||||
${LIBDIR}/slic3r/GUI/GUI_App.hpp
|
${LIBDIR}/slic3r/GUI/GUI_App.hpp
|
||||||
|
${LIBDIR}/slic3r/GUI/GUI_Utils.cpp
|
||||||
|
${LIBDIR}/slic3r/GUI/GUI_Utils.hpp
|
||||||
${LIBDIR}/slic3r/GUI/MainFrame.cpp
|
${LIBDIR}/slic3r/GUI/MainFrame.cpp
|
||||||
${LIBDIR}/slic3r/GUI/MainFrame.hpp
|
${LIBDIR}/slic3r/GUI/MainFrame.hpp
|
||||||
${LIBDIR}/slic3r/GUI/Plater.cpp
|
${LIBDIR}/slic3r/GUI/Plater.cpp
|
||||||
|
@ -292,7 +292,7 @@ void BedShapePanel::update_shape()
|
|||||||
void BedShapePanel::load_stl()
|
void BedShapePanel::load_stl()
|
||||||
{
|
{
|
||||||
auto dialog = new wxFileDialog(this, _(L("Choose a file to import bed shape from (STL/OBJ/AMF/3MF/PRUSA):")), "", "",
|
auto dialog = new wxFileDialog(this, _(L("Choose a file to import bed shape from (STL/OBJ/AMF/3MF/PRUSA):")), "", "",
|
||||||
MODEL_WILDCARD, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
file_wildcards[FT_MODEL], wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||||
if (dialog->ShowModal() != wxID_OK) {
|
if (dialog->ShowModal() != wxID_OK) {
|
||||||
dialog->Destroy();
|
dialog->Destroy();
|
||||||
return;
|
return;
|
||||||
|
@ -611,8 +611,9 @@ void ColourPicker::BUILD()
|
|||||||
if (m_opt.width >= 0) size.SetWidth(m_opt.width);
|
if (m_opt.width >= 0) size.SetWidth(m_opt.width);
|
||||||
|
|
||||||
wxString clr(static_cast<const ConfigOptionStrings*>(m_opt.default_value)->get_at(m_opt_idx));
|
wxString clr(static_cast<const ConfigOptionStrings*>(m_opt.default_value)->get_at(m_opt_idx));
|
||||||
|
// FIXME: verify clr is valid, otherwise this causes an assert
|
||||||
auto temp = new wxColourPickerCtrl(m_parent, wxID_ANY, clr, wxDefaultPosition, size);
|
auto temp = new wxColourPickerCtrl(m_parent, wxID_ANY, clr, wxDefaultPosition, size);
|
||||||
|
|
||||||
// // recast as a wxWindow to fit the calling convention
|
// // recast as a wxWindow to fit the calling convention
|
||||||
window = dynamic_cast<wxWindow*>(temp);
|
window = dynamic_cast<wxWindow*>(temp);
|
||||||
|
|
||||||
|
@ -347,53 +347,6 @@ std::string into_u8(const wxString &str)
|
|||||||
return std::string(buffer_utf8.data());
|
return std::string(buffer_utf8.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
wxWindow* export_option_creator(wxWindow* parent)
|
|
||||||
{
|
|
||||||
wxPanel* panel = new wxPanel(parent, -1);
|
|
||||||
wxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
|
|
||||||
wxCheckBox* cbox = new wxCheckBox(panel, wxID_HIGHEST + 1, L("Export print config"));
|
|
||||||
cbox->SetValue(true);
|
|
||||||
sizer->AddSpacer(5);
|
|
||||||
sizer->Add(cbox, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, 5);
|
|
||||||
panel->SetSizer(sizer);
|
|
||||||
sizer->SetSizeHints(panel);
|
|
||||||
return panel;
|
|
||||||
}
|
|
||||||
|
|
||||||
void add_export_option(wxFileDialog* dlg, const std::string& format)
|
|
||||||
{
|
|
||||||
if ((dlg != nullptr) && (format == "AMF") || (format == "3MF"))
|
|
||||||
{
|
|
||||||
if (dlg->SupportsExtraControl())
|
|
||||||
dlg->SetExtraControlCreator(export_option_creator);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int get_export_option(wxFileDialog* dlg)
|
|
||||||
{
|
|
||||||
if (dlg != nullptr)
|
|
||||||
{
|
|
||||||
wxWindow* wnd = dlg->GetExtraControl();
|
|
||||||
if (wnd != nullptr)
|
|
||||||
{
|
|
||||||
wxPanel* panel = dynamic_cast<wxPanel*>(wnd);
|
|
||||||
if (panel != nullptr)
|
|
||||||
{
|
|
||||||
wxWindow* child = panel->FindWindow(wxID_HIGHEST + 1);
|
|
||||||
if (child != nullptr)
|
|
||||||
{
|
|
||||||
wxCheckBox* cbox = dynamic_cast<wxCheckBox*>(child);
|
|
||||||
if (cbox != nullptr)
|
|
||||||
return cbox->IsChecked() ? 1 : 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool get_current_screen_size(wxWindow *window, unsigned &width, unsigned &height)
|
bool get_current_screen_size(wxWindow *window, unsigned &width, unsigned &height)
|
||||||
{
|
{
|
||||||
const auto idx = wxDisplay::GetFromWindow(window);
|
const auto idx = wxDisplay::GetFromWindow(window);
|
||||||
|
@ -102,9 +102,6 @@ std::string into_u8(const wxString &str);
|
|||||||
|
|
||||||
// Callback to trigger a configuration update timer on the Plater.
|
// Callback to trigger a configuration update timer on the Plater.
|
||||||
static PerlCallback g_on_request_update_callback;
|
static PerlCallback g_on_request_update_callback;
|
||||||
|
|
||||||
void add_export_option(wxFileDialog* dlg, const std::string& format);
|
|
||||||
int get_export_option(wxFileDialog* dlg);
|
|
||||||
|
|
||||||
// Returns the dimensions of the screen on which the main frame is displayed
|
// Returns the dimensions of the screen on which the main frame is displayed
|
||||||
bool get_current_screen_size(wxWindow *window, unsigned &width, unsigned &height);
|
bool get_current_screen_size(wxWindow *window, unsigned &width, unsigned &height);
|
||||||
|
@ -34,6 +34,21 @@
|
|||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
|
||||||
|
|
||||||
|
const wxString file_wildcards[FT_SIZE] = {
|
||||||
|
/* FT_STL */ "STL files (*.stl)|*.stl;*.STL",
|
||||||
|
/* FT_OBJ */ "OBJ files (*.obj)|*.obj;*.OBJ",
|
||||||
|
/* FT_AMF */ "AMF files (*.amf)|*.zip.amf;*.amf;*.AMF;*.xml;*.XML",
|
||||||
|
/* FT_3MF */ "3MF files (*.3mf)|*.3mf;*.3MF;",
|
||||||
|
/* FT_PRUSA */ "Prusa Control files (*.prusa)|*.prusa;*.PRUSA",
|
||||||
|
/* FT_GCODE */ "G-code files (*.gcode, *.gco, *.g, *.ngc)|*.gcode;*.GCODE;*.gco;*.GCO;*.g;*.G;*.ngc;*.NGC",
|
||||||
|
/* FT_MODEL */ "Known files (*.stl, *.obj, *.amf, *.xml, *.3mf, *.prusa)|*.stl;*.STL;*.obj;*.OBJ;*.amf;*.AMF;*.xml;*.XML;*.3mf;*.3MF;*.prusa;*.PRUSA",
|
||||||
|
|
||||||
|
/* FT_INI */ "INI files *.ini|*.ini;*.INI",
|
||||||
|
/* FT_SVG */ "SVG files *.svg|*.svg;*.SVG",
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
static std::string libslic3r_translate_callback(const char *s) { return wxGetTranslation(wxString(s, wxConvUTF8)).utf8_str().data(); }
|
static std::string libslic3r_translate_callback(const char *s) { return wxGetTranslation(wxString(s, wxConvUTF8)).utf8_str().data(); }
|
||||||
|
|
||||||
IMPLEMENT_APP(GUI_App)
|
IMPLEMENT_APP(GUI_App)
|
||||||
@ -291,7 +306,7 @@ void GUI_App::open_model(wxWindow *parent, wxArrayString& input_files)
|
|||||||
auto dialog = new wxFileDialog(parent ? parent : GetTopWindow(),
|
auto dialog = new wxFileDialog(parent ? parent : GetTopWindow(),
|
||||||
_(L("Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):")),
|
_(L("Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):")),
|
||||||
app_config->get_last_dir(), "",
|
app_config->get_last_dir(), "",
|
||||||
MODEL_WILDCARD, wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST);
|
file_wildcards[FT_MODEL], wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST);
|
||||||
if (dialog->ShowModal() != wxID_OK) {
|
if (dialog->ShowModal() != wxID_OK) {
|
||||||
dialog->Destroy();
|
dialog->Destroy();
|
||||||
return;
|
return;
|
||||||
|
@ -25,26 +25,24 @@ class ModelObject;
|
|||||||
|
|
||||||
namespace GUI
|
namespace GUI
|
||||||
{
|
{
|
||||||
// Map from an file_type name to full file wildcard name.
|
|
||||||
const std::map<const std::string, const std::string> FILE_WILDCARDS{
|
enum FileType
|
||||||
std::make_pair("known", "Known files (*.stl, *.obj, *.amf, *.xml, *.prusa)|*.stl;*.STL;*.obj;*.OBJ;*.amf;*.AMF;*.xml;*.XML;*.prusa;*.PRUSA"),
|
{
|
||||||
std::make_pair("stl", "STL files (*.stl)|*.stl;*.STL"),
|
FT_STL,
|
||||||
std::make_pair("obj", "OBJ files (*.obj)|*.obj;*.OBJ"),
|
FT_OBJ,
|
||||||
std::make_pair("amf", "AMF files (*.amf)|*.zip.amf;*.amf;*.AMF;*.xml;*.XML"),
|
FT_AMF,
|
||||||
std::make_pair("3mf", "3MF files (*.3mf)|*.3mf;*.3MF;"),
|
FT_3MF,
|
||||||
std::make_pair("prusa", "Prusa Control files (*.prusa)|*.prusa;*.PRUSA"),
|
FT_PRUSA,
|
||||||
std::make_pair("ini", "INI files *.ini|*.ini;*.INI"),
|
FT_GCODE,
|
||||||
std::make_pair("gcode", "G-code files (*.gcode, *.gco, *.g, *.ngc)|*.gcode;*.GCODE;*.gco;*.GCO;*.g;*.G;*.ngc;*.NGC"),
|
FT_MODEL,
|
||||||
std::make_pair("svg", "SVG files *.svg|*.svg;*.SVG")
|
|
||||||
|
FT_INI,
|
||||||
|
FT_SVG,
|
||||||
|
|
||||||
|
FT_SIZE,
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::string MODEL_WILDCARD{ FILE_WILDCARDS.at("known") + std::string("|") +
|
extern const wxString file_wildcards[FT_SIZE];
|
||||||
FILE_WILDCARDS.at("stl") + std::string("|") +
|
|
||||||
FILE_WILDCARDS.at("obj") + std::string("|") +
|
|
||||||
FILE_WILDCARDS.at("amf") + std::string("|") +
|
|
||||||
FILE_WILDCARDS.at("3mf") + std::string("|") +
|
|
||||||
FILE_WILDCARDS.at("prusa") };
|
|
||||||
|
|
||||||
|
|
||||||
enum ConfigMenuIDs {
|
enum ConfigMenuIDs {
|
||||||
ConfigMenuWizard,
|
ConfigMenuWizard,
|
||||||
|
@ -511,7 +511,7 @@ void ObjectList::menu_item_add_generic(wxMenuItem* &menu, int id) {
|
|||||||
sub_menu->Append(new wxMenuItem(sub_menu, ++id, _(item)));
|
sub_menu->Append(new wxMenuItem(sub_menu, ++id, _(item)));
|
||||||
|
|
||||||
#ifndef __WXMSW__
|
#ifndef __WXMSW__
|
||||||
sub_menu->Bind(wxEVT_MENU, [sub_menu](wxEvent &event) {
|
sub_menu->Bind(wxEVT_MENU, [this, sub_menu](wxEvent &event) {
|
||||||
load_lambda(sub_menu->GetLabel(event.GetId()).ToStdString());
|
load_lambda(sub_menu->GetLabel(event.GetId()).ToStdString());
|
||||||
});
|
});
|
||||||
#endif //no __WXMSW__
|
#endif //no __WXMSW__
|
||||||
@ -633,7 +633,7 @@ wxMenu* ObjectList::create_add_settings_popupmenu(bool is_part)
|
|||||||
menu->Append(menu_item);
|
menu->Append(menu_item);
|
||||||
}
|
}
|
||||||
#ifndef __WXMSW__
|
#ifndef __WXMSW__
|
||||||
menu->Bind(wxEVT_MENU, [menu, is_part](wxEvent &event) {
|
menu->Bind(wxEVT_MENU, [this, menu, is_part](wxEvent &event) {
|
||||||
get_settings_choice(menu, event.GetId(), is_part);
|
get_settings_choice(menu, event.GetId(), is_part);
|
||||||
});
|
});
|
||||||
#endif //no __WXMSW__
|
#endif //no __WXMSW__
|
||||||
|
54
src/slic3r/GUI/GUI_Utils.cpp
Normal file
54
src/slic3r/GUI/GUI_Utils.cpp
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#include "GUI_Utils.hpp"
|
||||||
|
|
||||||
|
#include <wx/sizer.h>
|
||||||
|
#include <wx/panel.h>
|
||||||
|
#include <wx/checkbox.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
namespace GUI {
|
||||||
|
|
||||||
|
|
||||||
|
CheckboxFileDialog::CheckboxFileDialog(wxWindow *parent,
|
||||||
|
const wxString &checkbox_label,
|
||||||
|
bool checkbox_value,
|
||||||
|
const wxString &message,
|
||||||
|
const wxString &default_dir,
|
||||||
|
const wxString &default_file,
|
||||||
|
const wxString &wildcard,
|
||||||
|
long style,
|
||||||
|
const wxPoint &pos,
|
||||||
|
const wxSize &size,
|
||||||
|
const wxString &name
|
||||||
|
)
|
||||||
|
: wxFileDialog(parent, message, default_dir, default_file, wildcard, style, pos, size, name)
|
||||||
|
, cbox(nullptr)
|
||||||
|
{
|
||||||
|
if (checkbox_label.IsEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
extra_control_creator = [this, checkbox_label](wxWindow *parent) -> wxWindow* {
|
||||||
|
wxPanel* panel = new wxPanel(parent, -1);
|
||||||
|
wxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
this->cbox = new wxCheckBox(panel, wxID_HIGHEST + 1, checkbox_label);
|
||||||
|
this->cbox->SetValue(true);
|
||||||
|
sizer->AddSpacer(5);
|
||||||
|
sizer->Add(this->cbox, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, 5);
|
||||||
|
panel->SetSizer(sizer);
|
||||||
|
sizer->SetSizeHints(panel);
|
||||||
|
|
||||||
|
return panel;
|
||||||
|
};
|
||||||
|
|
||||||
|
SetExtraControlCreator(*extra_control_creator.target<ExtraControlCreatorFunction>());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CheckboxFileDialog::get_checkbox_value() const
|
||||||
|
{
|
||||||
|
return this->cbox != nullptr ? cbox->IsChecked() : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
41
src/slic3r/GUI/GUI_Utils.hpp
Normal file
41
src/slic3r/GUI/GUI_Utils.hpp
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#ifndef slic3r_GUI_Utils_hpp_
|
||||||
|
#define slic3r_GUI_Utils_hpp_
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#include <wx/filedlg.h>
|
||||||
|
|
||||||
|
class wxCheckBox;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
namespace GUI {
|
||||||
|
|
||||||
|
|
||||||
|
class CheckboxFileDialog : public wxFileDialog
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CheckboxFileDialog(wxWindow *parent,
|
||||||
|
const wxString &checkbox_label,
|
||||||
|
bool checkbox_value,
|
||||||
|
const wxString &message = wxFileSelectorPromptStr,
|
||||||
|
const wxString &default_dir = wxEmptyString,
|
||||||
|
const wxString &default_file = wxEmptyString,
|
||||||
|
const wxString &wildcard = wxFileSelectorDefaultWildcardStr,
|
||||||
|
long style = wxFD_DEFAULT_STYLE,
|
||||||
|
const wxPoint &pos = wxDefaultPosition,
|
||||||
|
const wxSize &size = wxDefaultSize,
|
||||||
|
const wxString &name = wxFileDialogNameStr
|
||||||
|
);
|
||||||
|
|
||||||
|
bool get_checkbox_value() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::function<wxWindow*(wxWindow*)> extra_control_creator;
|
||||||
|
wxCheckBox *cbox;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}}
|
||||||
|
|
||||||
|
#endif
|
@ -460,7 +460,7 @@ void MainFrame::quick_slice(const int qs){
|
|||||||
if (!(qs & qsReslice)) {
|
if (!(qs & qsReslice)) {
|
||||||
auto dlg = new wxFileDialog(this, _(L("Choose a file to slice (STL/OBJ/AMF/3MF/PRUSA):")),
|
auto dlg = new wxFileDialog(this, _(L("Choose a file to slice (STL/OBJ/AMF/3MF/PRUSA):")),
|
||||||
wxGetApp().app_config->get_last_dir(), "",
|
wxGetApp().app_config->get_last_dir(), "",
|
||||||
MODEL_WILDCARD, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
file_wildcards[FT_MODEL], wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||||
if (dlg->ShowModal() != wxID_OK) {
|
if (dlg->ShowModal() != wxID_OK) {
|
||||||
dlg->Destroy();
|
dlg->Destroy();
|
||||||
return;
|
return;
|
||||||
@ -519,7 +519,7 @@ void MainFrame::quick_slice(const int qs){
|
|||||||
// output_file = ~s / \.[gG][cC][oO][dD][eE]$ / .svg /;
|
// output_file = ~s / \.[gG][cC][oO][dD][eE]$ / .svg /;
|
||||||
auto dlg = new wxFileDialog(this, _(L("Save ")) + (qs & qsExportSVG ? _(L("SVG")) : _(L("G-code"))) + _(L(" file as:")),
|
auto dlg = new wxFileDialog(this, _(L("Save ")) + (qs & qsExportSVG ? _(L("SVG")) : _(L("G-code"))) + _(L(" file as:")),
|
||||||
wxGetApp().app_config->get_last_output_dir(get_dir_name(output_file)), get_base_name(input_file),
|
wxGetApp().app_config->get_last_output_dir(get_dir_name(output_file)), get_base_name(input_file),
|
||||||
qs & qsExportSVG ? FILE_WILDCARDS.at("svg") : FILE_WILDCARDS.at("gcode"),
|
qs & qsExportSVG ? file_wildcards[FT_SVG] : file_wildcards[FT_GCODE],
|
||||||
wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
||||||
if (dlg->ShowModal() != wxID_OK) {
|
if (dlg->ShowModal() != wxID_OK) {
|
||||||
dlg->Destroy();
|
dlg->Destroy();
|
||||||
@ -587,7 +587,7 @@ void MainFrame::repair_stl()
|
|||||||
{
|
{
|
||||||
auto dlg = new wxFileDialog(this, _(L("Select the STL file to repair:")),
|
auto dlg = new wxFileDialog(this, _(L("Select the STL file to repair:")),
|
||||||
wxGetApp().app_config->get_last_dir(), "",
|
wxGetApp().app_config->get_last_dir(), "",
|
||||||
FILE_WILDCARDS.at("stl"), wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
file_wildcards[FT_STL], wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||||
if (dlg->ShowModal() != wxID_OK) {
|
if (dlg->ShowModal() != wxID_OK) {
|
||||||
dlg->Destroy();
|
dlg->Destroy();
|
||||||
return;
|
return;
|
||||||
@ -601,7 +601,7 @@ void MainFrame::repair_stl()
|
|||||||
// output_file = ~s / \.[sS][tT][lL]$ / _fixed.obj / ;
|
// output_file = ~s / \.[sS][tT][lL]$ / _fixed.obj / ;
|
||||||
auto dlg = new wxFileDialog( this, L("Save OBJ file (less prone to coordinate errors than STL) as:"),
|
auto dlg = new wxFileDialog( this, L("Save OBJ file (less prone to coordinate errors than STL) as:"),
|
||||||
get_dir_name(output_file), get_base_name(output_file),
|
get_dir_name(output_file), get_base_name(output_file),
|
||||||
FILE_WILDCARDS.at("obj"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
file_wildcards[FT_OBJ], wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
||||||
if (dlg->ShowModal() != wxID_OK) {
|
if (dlg->ShowModal() != wxID_OK) {
|
||||||
dlg->Destroy();
|
dlg->Destroy();
|
||||||
return /*undef*/;
|
return /*undef*/;
|
||||||
@ -631,7 +631,7 @@ void MainFrame::export_config()
|
|||||||
auto dlg = new wxFileDialog(this, _(L("Save configuration as:")),
|
auto dlg = new wxFileDialog(this, _(L("Save configuration as:")),
|
||||||
!m_last_config.IsEmpty() ? get_dir_name(m_last_config) : wxGetApp().app_config->get_last_dir(),
|
!m_last_config.IsEmpty() ? get_dir_name(m_last_config) : wxGetApp().app_config->get_last_dir(),
|
||||||
!m_last_config.IsEmpty() ? get_base_name(m_last_config) : "config.ini",
|
!m_last_config.IsEmpty() ? get_base_name(m_last_config) : "config.ini",
|
||||||
FILE_WILDCARDS.at("ini"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
file_wildcards[FT_INI], wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
||||||
wxString file;
|
wxString file;
|
||||||
if (dlg->ShowModal() == wxID_OK)
|
if (dlg->ShowModal() == wxID_OK)
|
||||||
file = dlg->GetPath();
|
file = dlg->GetPath();
|
||||||
@ -683,7 +683,7 @@ void MainFrame::export_configbundle()
|
|||||||
auto dlg = new wxFileDialog(this, _(L("Save presets bundle as:")),
|
auto dlg = new wxFileDialog(this, _(L("Save presets bundle as:")),
|
||||||
!m_last_config.IsEmpty() ? get_dir_name(m_last_config) : wxGetApp().app_config->get_last_dir(),
|
!m_last_config.IsEmpty() ? get_dir_name(m_last_config) : wxGetApp().app_config->get_last_dir(),
|
||||||
"Slic3r_config_bundle.ini",
|
"Slic3r_config_bundle.ini",
|
||||||
FILE_WILDCARDS.at("ini"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
file_wildcards[FT_INI], wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
||||||
wxString file;
|
wxString file;
|
||||||
if (dlg->ShowModal() == wxID_OK)
|
if (dlg->ShowModal() == wxID_OK)
|
||||||
file = dlg->GetPath();
|
file = dlg->GetPath();
|
||||||
@ -707,7 +707,7 @@ void MainFrame::load_configbundle(wxString file/* = wxEmptyString, const bool re
|
|||||||
if (file.IsEmpty()) {
|
if (file.IsEmpty()) {
|
||||||
auto dlg = new wxFileDialog(this, _(L("Select configuration to load:")),
|
auto dlg = new wxFileDialog(this, _(L("Select configuration to load:")),
|
||||||
!m_last_config.IsEmpty() ? get_dir_name(m_last_config) : wxGetApp().app_config->get_last_dir(),
|
!m_last_config.IsEmpty() ? get_dir_name(m_last_config) : wxGetApp().app_config->get_last_dir(),
|
||||||
"config.ini", FILE_WILDCARDS.at("ini"), wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
"config.ini", file_wildcards[FT_INI], wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||||
if (dlg->ShowModal() != wxID_OK)
|
if (dlg->ShowModal() != wxID_OK)
|
||||||
return;
|
return;
|
||||||
file = dlg->GetPath();
|
file = dlg->GetPath();
|
||||||
@ -774,7 +774,7 @@ void MainFrame::on_presets_changed(SimpleEvent &event)
|
|||||||
|
|
||||||
// Update preset combo boxes(Print settings, Filament, Material, Printer) from their respective tabs.
|
// Update preset combo boxes(Print settings, Filament, Material, Printer) from their respective tabs.
|
||||||
auto presets = tab->get_presets();
|
auto presets = tab->get_presets();
|
||||||
if (presets) {
|
if (m_plater != nullptr && presets != nullptr) {
|
||||||
auto reload_dependent_tabs = tab->get_dependent_tabs();
|
auto reload_dependent_tabs = tab->get_dependent_tabs();
|
||||||
|
|
||||||
// FIXME: The preset type really should be a property of Tab instead
|
// FIXME: The preset type really should be a property of Tab instead
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
|
#include <boost/optional.hpp>
|
||||||
#include <boost/filesystem/path.hpp>
|
#include <boost/filesystem/path.hpp>
|
||||||
|
|
||||||
#include <wx/sizer.h>
|
#include <wx/sizer.h>
|
||||||
@ -25,10 +26,12 @@
|
|||||||
#include "libslic3r/GCode/PreviewData.hpp"
|
#include "libslic3r/GCode/PreviewData.hpp"
|
||||||
#include "libslic3r/Utils.hpp"
|
#include "libslic3r/Utils.hpp"
|
||||||
#include "libslic3r/Polygon.hpp"
|
#include "libslic3r/Polygon.hpp"
|
||||||
|
#include "libslic3r/Format/STL.hpp"
|
||||||
#include "GUI.hpp"
|
#include "GUI.hpp"
|
||||||
#include "GUI_App.hpp"
|
#include "GUI_App.hpp"
|
||||||
#include "GUI_ObjectList.hpp"
|
#include "GUI_ObjectList.hpp"
|
||||||
#include "GUI_ObjectManipulation.hpp"
|
#include "GUI_ObjectManipulation.hpp"
|
||||||
|
#include "GUI_Utils.hpp"
|
||||||
#include "MainFrame.hpp"
|
#include "MainFrame.hpp"
|
||||||
#include "3DScene.hpp"
|
#include "3DScene.hpp"
|
||||||
#include "GLCanvas3D.hpp"
|
#include "GLCanvas3D.hpp"
|
||||||
@ -43,6 +46,7 @@
|
|||||||
#include <wx/glcanvas.h> // Needs to be last because reasons :-/
|
#include <wx/glcanvas.h> // Needs to be last because reasons :-/
|
||||||
#include "WipeTowerDialog.hpp"
|
#include "WipeTowerDialog.hpp"
|
||||||
|
|
||||||
|
using boost::optional;
|
||||||
namespace fs = boost::filesystem;
|
namespace fs = boost::filesystem;
|
||||||
using Slic3r::_3DScene;
|
using Slic3r::_3DScene;
|
||||||
using Slic3r::Preset;
|
using Slic3r::Preset;
|
||||||
@ -340,7 +344,7 @@ FreqChangedParams::FreqChangedParams(wxWindow* parent, const int label_width) :
|
|||||||
|
|
||||||
struct Sidebar::priv
|
struct Sidebar::priv
|
||||||
{
|
{
|
||||||
// Sidebar *q; // PIMPL back pointer ("Q-Pointer")
|
Plater *plater;
|
||||||
|
|
||||||
wxScrolledWindow *scrolled;
|
wxScrolledWindow *scrolled;
|
||||||
|
|
||||||
@ -362,13 +366,15 @@ struct Sidebar::priv
|
|||||||
wxButton *btn_reslice;
|
wxButton *btn_reslice;
|
||||||
// wxButton *btn_print; // XXX: remove
|
// wxButton *btn_print; // XXX: remove
|
||||||
wxButton *btn_send_gcode;
|
wxButton *btn_send_gcode;
|
||||||
|
|
||||||
|
priv(Plater *plater) : plater(plater) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Sidebar / public
|
// Sidebar / public
|
||||||
|
|
||||||
Sidebar::Sidebar(wxWindow *parent)
|
Sidebar::Sidebar(Plater *parent)
|
||||||
: wxPanel(parent), p(new priv)
|
: wxPanel(parent), p(new priv(parent))
|
||||||
{
|
{
|
||||||
p->scrolled = new wxScrolledWindow(this);
|
p->scrolled = new wxScrolledWindow(this);
|
||||||
|
|
||||||
@ -457,6 +463,11 @@ Sidebar::Sidebar(wxWindow *parent)
|
|||||||
sizer->Add(p->scrolled, 1, wxEXPAND | wxTOP, 5);
|
sizer->Add(p->scrolled, 1, wxEXPAND | wxTOP, 5);
|
||||||
sizer->Add(btns_sizer, 0, wxEXPAND | wxLEFT, 20);
|
sizer->Add(btns_sizer, 0, wxEXPAND | wxLEFT, 20);
|
||||||
SetSizer(sizer);
|
SetSizer(sizer);
|
||||||
|
|
||||||
|
// Events
|
||||||
|
p->btn_export_gcode->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { p->plater->export_gcode(); });
|
||||||
|
p->btn_reslice->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { p->plater->reslice(); });
|
||||||
|
p->btn_send_gcode->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { p->plater->send_gcode(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
Sidebar::~Sidebar() {}
|
Sidebar::~Sidebar() {}
|
||||||
@ -600,8 +611,8 @@ struct Plater::priv
|
|||||||
Slic3r::GCodePreviewData gcode_preview_data;
|
Slic3r::GCodePreviewData gcode_preview_data;
|
||||||
std::vector<PlaterObject> objects;
|
std::vector<PlaterObject> objects;
|
||||||
|
|
||||||
std::string export_gcode_output_file;
|
fs::path export_gcode_output_file;
|
||||||
std::string send_gcode_file;
|
fs::path send_gcode_file;
|
||||||
|
|
||||||
// GUI elements
|
// GUI elements
|
||||||
wxNotebook *notebook;
|
wxNotebook *notebook;
|
||||||
@ -610,7 +621,6 @@ struct Plater::priv
|
|||||||
Preview *preview;
|
Preview *preview;
|
||||||
BackgroundSlicingProcess background_process;
|
BackgroundSlicingProcess background_process;
|
||||||
|
|
||||||
static const int gl_attrs[];
|
|
||||||
static const std::regex pattern_bundle;
|
static const std::regex pattern_bundle;
|
||||||
static const std::regex pattern_3mf;
|
static const std::regex pattern_3mf;
|
||||||
static const std::regex pattern_zip_amf;
|
static const std::regex pattern_zip_amf;
|
||||||
@ -628,19 +638,33 @@ struct Plater::priv
|
|||||||
BoundingBox scaled_bed_shape_bb() const;
|
BoundingBox scaled_bed_shape_bb() const;
|
||||||
std::vector<size_t> load_files(const std::vector<fs::path> &input_files);
|
std::vector<size_t> load_files(const std::vector<fs::path> &input_files);
|
||||||
std::vector<size_t> load_model_objects(const ModelObjectPtrs &model_objects);
|
std::vector<size_t> load_model_objects(const ModelObjectPtrs &model_objects);
|
||||||
|
std::unique_ptr<CheckboxFileDialog> get_export_file(GUI::FileType file_type);
|
||||||
|
|
||||||
|
void select_object(optional<size_t> obj_idx);
|
||||||
|
optional<size_t> selected_object() const;
|
||||||
|
void selection_changed();
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
|
||||||
void on_notebook_changed(wxBookCtrlEvent &);
|
void on_notebook_changed(wxBookCtrlEvent &);
|
||||||
void on_select_preset(wxCommandEvent &);
|
void on_select_preset(wxCommandEvent &);
|
||||||
void on_update_print_preview(wxCommandEvent &);
|
void on_update_print_preview(wxCommandEvent &);
|
||||||
void on_process_completed(wxCommandEvent &);
|
void on_process_completed(wxCommandEvent &);
|
||||||
void on_layer_editing_toggled(bool enable);
|
void on_layer_editing_toggled(bool enable);
|
||||||
|
|
||||||
void on_action_add(SimpleEvent&);
|
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&);
|
||||||
|
void on_action_layersediting(SimpleEvent&);
|
||||||
|
void on_action_selectbyparts(SimpleEvent&);
|
||||||
|
|
||||||
void on_viewport_changed(SimpleEvent& evt);
|
void on_viewport_changed(SimpleEvent& evt);
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: multisample, see 3DScene.pm
|
|
||||||
const int Plater::priv::gl_attrs[] = {WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE, 24, 0};
|
|
||||||
const std::regex Plater::priv::pattern_bundle("[.](amf|amf[.]xml|zip[.]amf|3mf|prusa)$", std::regex::icase);
|
const std::regex Plater::priv::pattern_bundle("[.](amf|amf[.]xml|zip[.]amf|3mf|prusa)$", std::regex::icase);
|
||||||
const std::regex Plater::priv::pattern_3mf("[.]3mf$", std::regex::icase);
|
const std::regex Plater::priv::pattern_3mf("[.]3mf$", std::regex::icase);
|
||||||
const std::regex Plater::priv::pattern_zip_amf("[.]zip[.]amf$", std::regex::icase);
|
const std::regex Plater::priv::pattern_zip_amf("[.]zip[.]amf$", std::regex::icase);
|
||||||
@ -716,15 +740,26 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) :
|
|||||||
sidebar->Bind(wxEVT_COMBOBOX, &priv::on_select_preset, this);
|
sidebar->Bind(wxEVT_COMBOBOX, &priv::on_select_preset, this);
|
||||||
|
|
||||||
// Sidebar button events
|
// Sidebar button events
|
||||||
sidebar->p->btn_export_gcode->Bind(wxEVT_BUTTON, [q](wxCommandEvent&) { q->export_gcode(""); });
|
// sidebar->p->btn_export_gcode->Bind(wxEVT_BUTTON, [q](wxCommandEvent&) { q->export_gcode(); });
|
||||||
sidebar->p->btn_reslice->Bind(wxEVT_BUTTON, [q](wxCommandEvent&) { q->reslice(); });
|
// sidebar->p->btn_reslice->Bind(wxEVT_BUTTON, [q](wxCommandEvent&) { q->reslice(); });
|
||||||
sidebar->p->btn_send_gcode->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) {
|
// sidebar->p->btn_send_gcode->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) {
|
||||||
this->send_gcode_file = this->q->export_gcode("");
|
// this->send_gcode_file = this->q->export_gcode();
|
||||||
});
|
// });
|
||||||
|
|
||||||
// 3DScene events:
|
// 3DScene events:
|
||||||
// TODO: more
|
// TODO: more
|
||||||
canvas3D->Bind(EVT_GLTOOLBAR_ADD, &priv::on_action_add, this);
|
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_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);
|
||||||
|
canvas3D->Bind(EVT_GLTOOLBAR_LAYERSEDITING, &priv::on_action_layersediting, this);
|
||||||
|
canvas3D->Bind(EVT_GLTOOLBAR_SELECTBYPARTS, &priv::on_action_selectbyparts, this);
|
||||||
|
|
||||||
canvas3D->Bind(EVT_GLCANVAS_VIEWPORT_CHANGED, &priv::on_viewport_changed, this);
|
canvas3D->Bind(EVT_GLCANVAS_VIEWPORT_CHANGED, &priv::on_viewport_changed, this);
|
||||||
|
|
||||||
preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_VIEWPORT_CHANGED, &priv::on_viewport_changed, this);
|
preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_VIEWPORT_CHANGED, &priv::on_viewport_changed, this);
|
||||||
@ -810,7 +845,7 @@ BoundingBox Plater::priv::scaled_bed_shape_bb() const
|
|||||||
|
|
||||||
std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path> &input_files)
|
std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path> &input_files)
|
||||||
{
|
{
|
||||||
if (input_files.size() < 1) { return std::vector<size_t>(); }
|
if (input_files.empty()) { return std::vector<size_t>(); }
|
||||||
|
|
||||||
auto *nozzle_dmrs = config->opt<ConfigOptionFloats>("nozzle_diameter");
|
auto *nozzle_dmrs = config->opt<ConfigOptionFloats>("nozzle_diameter");
|
||||||
|
|
||||||
@ -883,9 +918,6 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path> &input_
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (one_by_one) {
|
if (one_by_one) {
|
||||||
// TODO:
|
|
||||||
// push @obj_idx, $self->load_model_objects(@{$model->objects});
|
|
||||||
// obj_idx.push_back(load_model_objects(model.objects);
|
|
||||||
auto loaded_idxs = load_model_objects(model.objects);
|
auto loaded_idxs = load_model_objects(model.objects);
|
||||||
obj_idxs.insert(obj_idxs.end(), loaded_idxs.begin(), loaded_idxs.end());
|
obj_idxs.insert(obj_idxs.end(), loaded_idxs.begin(), loaded_idxs.end());
|
||||||
} else {
|
} else {
|
||||||
@ -906,9 +938,6 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path> &input_
|
|||||||
new_model->convert_multipart_object(nozzle_dmrs->values.size());
|
new_model->convert_multipart_object(nozzle_dmrs->values.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO:
|
|
||||||
// push @obj_idx, $self->load_model_objects(@{$new_model->objects});
|
|
||||||
// obj_idx.push_back(load_model_objects(new_model->objects);
|
|
||||||
auto loaded_idxs = load_model_objects(model.objects);
|
auto loaded_idxs = load_model_objects(model.objects);
|
||||||
obj_idxs.insert(obj_idxs.end(), loaded_idxs.begin(), loaded_idxs.end());
|
obj_idxs.insert(obj_idxs.end(), loaded_idxs.begin(), loaded_idxs.end());
|
||||||
}
|
}
|
||||||
@ -919,18 +948,11 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path> &input_
|
|||||||
return obj_idxs;
|
return obj_idxs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<size_t> Plater::priv::load_model_objects(const ModelObjectPtrs &model_objects)
|
||||||
// TODO: move to Point.hpp
|
|
||||||
Vec3d to_3d(const Vec2d &v, double z) { return Vec3d(v(0), v(1), z); }
|
|
||||||
Vec3f to_3d(const Vec2f &v, float z) { return Vec3f(v(0), v(1), z); }
|
|
||||||
Vec3i64 to_3d(const Vec2i64 &v, float z) { return Vec3i64(v(0), v(1), z); }
|
|
||||||
Vec3crd to_3d(const Point &p, coord_t z) { return Vec3crd(p(0), p(1), z); }
|
|
||||||
|
|
||||||
std::vector<size_t> Plater::priv::load_model_objects(const ModelObjectPtrs &model_objects)
|
|
||||||
{
|
{
|
||||||
const BoundingBoxf bed_shape = bed_shape_bb();
|
const BoundingBoxf bed_shape = bed_shape_bb();
|
||||||
const Vec3d bed_center = to_3d(bed_shape.center().cast<double>(), 0.0);
|
const Vec3d bed_center = Slic3r::to_3d(bed_shape.center().cast<double>(), 0.0);
|
||||||
const Vec3d bed_size = to_3d(bed_shape.size().cast<double>(), 1.0);
|
const Vec3d bed_size = Slic3r::to_3d(bed_shape.size().cast<double>(), 1.0);
|
||||||
|
|
||||||
bool need_arrange = false;
|
bool need_arrange = false;
|
||||||
bool scaled_down = false;
|
bool scaled_down = false;
|
||||||
@ -942,7 +964,7 @@ std::vector<size_t> Plater::priv::load_model_objects(const ModelObjectPtrs &mod
|
|||||||
objects.emplace_back(std::move(object_name));
|
objects.emplace_back(std::move(object_name));
|
||||||
obj_idxs.push_back(objects.size() - 1);
|
obj_idxs.push_back(objects.size() - 1);
|
||||||
|
|
||||||
if (model_object->instances.size() == 0) {
|
if (model_object->instances.empty()) {
|
||||||
// if object has no defined position(s) we need to rearrange everything after loading
|
// if object has no defined position(s) we need to rearrange everything after loading
|
||||||
need_arrange = true;
|
need_arrange = true;
|
||||||
|
|
||||||
@ -1002,6 +1024,186 @@ std::vector<size_t> Plater::priv::load_model_objects(const ModelObjectPtrs &mod
|
|||||||
return obj_idxs;
|
return obj_idxs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<CheckboxFileDialog> Plater::priv::get_export_file(GUI::FileType file_type)
|
||||||
|
{
|
||||||
|
wxString wildcard;
|
||||||
|
switch (file_type) {
|
||||||
|
case FT_STL:
|
||||||
|
case FT_AMF:
|
||||||
|
case FT_3MF:
|
||||||
|
wildcard = file_wildcards[FT_STL];
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
wildcard = file_wildcards[FT_MODEL];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fs::path output_file(print.output_filepath(std::string()));
|
||||||
|
|
||||||
|
switch (file_type) {
|
||||||
|
case FT_STL: output_file.replace_extension("stl"); break;
|
||||||
|
case FT_AMF: output_file.replace_extension("zip.amf"); break; // XXX: Problem on OS X with double extension?
|
||||||
|
case FT_3MF: output_file.replace_extension("3mf"); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxGetApp().preset_bundle->export_selections(print.placeholder_parser());
|
||||||
|
|
||||||
|
auto dlg = Slic3r::make_unique<CheckboxFileDialog>(q,
|
||||||
|
_(L("Export print config")),
|
||||||
|
true,
|
||||||
|
_(L("Save file as:")),
|
||||||
|
output_file.parent_path().string(),
|
||||||
|
output_file.filename().string(),
|
||||||
|
wildcard,
|
||||||
|
wxFD_SAVE | wxFD_OVERWRITE_PROMPT
|
||||||
|
);
|
||||||
|
|
||||||
|
if (dlg->ShowModal() != wxID_OK) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
fs::path path(dlg->GetPath());
|
||||||
|
wxGetApp().app_config->update_last_output_dir(path.parent_path().string());
|
||||||
|
export_gcode_output_file = path;
|
||||||
|
|
||||||
|
return dlg;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Plater::priv::select_object(optional<size_t> obj_idx)
|
||||||
|
{
|
||||||
|
for (auto &obj : objects) {
|
||||||
|
obj.selected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj_idx) {
|
||||||
|
objects[*obj_idx].selected = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
// $self->selection_changed(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Plater::priv::selection_changed()
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
const auto obj_idx = selected_object();
|
||||||
|
const bool have_sel = !!obj_idx;
|
||||||
|
const bool layers_height_allowed = config->opt<ConfigOptionBool>("variable_layer_height")->value;
|
||||||
|
|
||||||
|
wxWindowUpdateLocker freeze_guard(sidebar);
|
||||||
|
|
||||||
|
_3DScene::enable_toolbar_item(canvas3D, "delete", have_sel);
|
||||||
|
_3DScene::enable_toolbar_item(canvas3D, "more", have_sel);
|
||||||
|
_3DScene::enable_toolbar_item(canvas3D, "fewer", have_sel);
|
||||||
|
_3DScene::enable_toolbar_item(canvas3D, "split", have_sel);
|
||||||
|
_3DScene::enable_toolbar_item(canvas3D, "cut", have_sel);
|
||||||
|
_3DScene::enable_toolbar_item(canvas3D, "settings", have_sel);
|
||||||
|
|
||||||
|
_3DScene::enable_toolbar_item(canvas3D, "layersediting", layers_height_allowed);
|
||||||
|
|
||||||
|
bool can_select_by_parts = false;
|
||||||
|
|
||||||
|
if (have_sel) {
|
||||||
|
// my $model_object = $self->{model}->objects->[$obj_idx];
|
||||||
|
const auto *model_object = model.objects[*obj_idx];
|
||||||
|
// $can_select_by_parts = ($obj_idx >= 0) && ($obj_idx < 1000) && ($model_object->volumes_count > 1);
|
||||||
|
// XXX: ?
|
||||||
|
can_select_by_parts = *obj_idx < 1000 && model_object->volumes.size() > 1;
|
||||||
|
// Slic3r::GUI::_3DScene::enable_toolbar_item($self->{canvas3D}, "fewer", $model_object->instances_count > 1);
|
||||||
|
_3DScene::enable_toolbar_item(canvas3D, "fewer", model_object->instances.size() > 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (can_select_by_parts) {
|
||||||
|
// first disable to let the item in the toolbar to switch to the unpressed state // XXX: ?
|
||||||
|
_3DScene::enable_toolbar_item(canvas3D, "selectbyparts", false);
|
||||||
|
_3DScene::enable_toolbar_item(canvas3D, "selectbyparts", true);
|
||||||
|
} else {
|
||||||
|
_3DScene::enable_toolbar_item(canvas3D, "selectbyparts", false);
|
||||||
|
_3DScene::set_select_by(canvas3D, "object");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (have_sel) {
|
||||||
|
const auto *model_object = model.objects[*obj_idx];
|
||||||
|
// FIXME print_info runs model fixing in two rounds, it is very slow, it should not be performed here!
|
||||||
|
// # $model_object->print_info;
|
||||||
|
|
||||||
|
// my $model_instance = $model_object->instances->[0];
|
||||||
|
const auto *model_instance = model_object->instances[0];
|
||||||
|
// TODO
|
||||||
|
// $self->{object_info_size}->SetLabel(sprintf("%.2f x %.2f x %.2f", @{$model_object->instance_bounding_box(0)->size}));
|
||||||
|
// $self->{object_info_materials}->SetLabel($model_object->materials_count);
|
||||||
|
|
||||||
|
// if (my $stats = $model_object->mesh_stats) {
|
||||||
|
// $self->{object_info_volume}->SetLabel(sprintf('%.2f', $stats->{volume} * ($model_instance->scaling_factor**3)));
|
||||||
|
// $self->{object_info_facets}->SetLabel(sprintf(L('%d (%d shells)'), $model_object->facets_count, $stats->{number_of_parts}));
|
||||||
|
// if (my $errors = sum(@$stats{qw(degenerate_facets edges_fixed facets_removed facets_added facets_reversed backwards_edges)})) {
|
||||||
|
// $self->{object_info_manifold}->SetLabel(sprintf(L("Auto-repaired (%d errors)"), $errors));
|
||||||
|
// #$self->{object_info_manifold_warning_icon}->Show;
|
||||||
|
// $self->{"object_info_manifold_warning_icon_show"}->(1);
|
||||||
|
|
||||||
|
// # we don't show normals_fixed because we never provide normals
|
||||||
|
// # to admesh, so it generates normals for all facets
|
||||||
|
// my $message = sprintf L('%d degenerate facets, %d edges fixed, %d facets removed, %d facets added, %d facets reversed, %d backwards edges'),
|
||||||
|
// @$stats{qw(degenerate_facets edges_fixed facets_removed facets_added facets_reversed backwards_edges)};
|
||||||
|
// $self->{object_info_manifold}->SetToolTipString($message);
|
||||||
|
// $self->{object_info_manifold_warning_icon}->SetToolTipString($message);
|
||||||
|
// } else {
|
||||||
|
// $self->{object_info_manifold}->SetLabel(L("Yes"));
|
||||||
|
// #$self->{object_info_manifold_warning_icon}->Hide;
|
||||||
|
// $self->{"object_info_manifold_warning_icon_show"}->(0);
|
||||||
|
// $self->{object_info_manifold}->SetToolTipString("");
|
||||||
|
// $self->{object_info_manifold_warning_icon}->SetToolTipString("");
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// $self->{object_info_facets}->SetLabel($object->facets);
|
||||||
|
// }
|
||||||
|
} else {
|
||||||
|
// $self->{"object_info_$_"}->SetLabel("") for qw(size volume facets materials manifold);
|
||||||
|
// $self->{"object_info_manifold_warning_icon_show"}->(0);
|
||||||
|
// $self->{object_info_manifold}->SetToolTipString("");
|
||||||
|
// $self->{object_info_manifold_warning_icon}->SetToolTipString("");
|
||||||
|
}
|
||||||
|
|
||||||
|
q->Layout();
|
||||||
|
}
|
||||||
|
|
||||||
|
optional<size_t> Plater::priv::selected_object() const
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < objects.size(); i++) {
|
||||||
|
if (objects[i].selected) { return i; }
|
||||||
|
}
|
||||||
|
|
||||||
|
return boost::none;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Plater::priv::reset()
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
// $self->stop_background_process;
|
||||||
|
|
||||||
|
// Prevent toolpaths preview from rendering while we modify the Print object
|
||||||
|
preview->set_enabled(false);
|
||||||
|
|
||||||
|
objects.clear();
|
||||||
|
model.clear_objects();
|
||||||
|
print.clear_objects();
|
||||||
|
|
||||||
|
// Delete all objects from list on c++ side
|
||||||
|
// TODO
|
||||||
|
// Slic3r::GUI::delete_all_objects_from_list();
|
||||||
|
sidebar->obj_list()->delete_all_objects_from_list();
|
||||||
|
// $self->object_list_changed;
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// $self->select_object(undef);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Plater::priv::on_notebook_changed(wxBookCtrlEvent&)
|
void Plater::priv::on_notebook_changed(wxBookCtrlEvent&)
|
||||||
{
|
{
|
||||||
const auto current_id = notebook->GetCurrentPage()->GetId();
|
const auto current_id = notebook->GetCurrentPage()->GetId();
|
||||||
@ -1082,6 +1284,47 @@ void Plater::priv::on_action_add(SimpleEvent&)
|
|||||||
load_files(input_paths);
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
void Plater::priv::on_action_cut(SimpleEvent&)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void Plater::priv::on_action_settings(SimpleEvent&)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void Plater::priv::on_action_layersediting(SimpleEvent&)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void Plater::priv::on_action_selectbyparts(SimpleEvent&)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Plater::priv::on_viewport_changed(SimpleEvent& evt)
|
void Plater::priv::on_viewport_changed(SimpleEvent& evt)
|
||||||
{
|
{
|
||||||
wxObject* o = evt.GetEventObject();
|
wxObject* o = evt.GetEventObject();
|
||||||
@ -1107,63 +1350,115 @@ Plater::~Plater()
|
|||||||
Sidebar& Plater::sidebar() { return *p->sidebar; }
|
Sidebar& Plater::sidebar() { return *p->sidebar; }
|
||||||
Model& Plater::model() { return p->model; }
|
Model& Plater::model() { return p->model; }
|
||||||
|
|
||||||
std::string Plater::export_gcode(const std::string &output_path)
|
void Plater::update(bool force_autocenter)
|
||||||
{
|
{
|
||||||
if (p->objects.size() == 0) { return ""; }
|
p->update(force_autocenter);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Plater::remove(size_t obj_idx)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void Plater::remove_selected()
|
||||||
|
{
|
||||||
|
const auto selected = p->selected_object();
|
||||||
|
if (selected) {
|
||||||
|
remove(*selected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fs::path Plater::export_gcode(const fs::path &output_path)
|
||||||
|
{
|
||||||
|
if (p->objects.empty()) { return ""; }
|
||||||
|
|
||||||
if (! p->export_gcode_output_file.empty()) {
|
if (! p->export_gcode_output_file.empty()) {
|
||||||
GUI::show_error(this, _(L("Another export job is currently running.")));
|
GUI::show_error(this, _(L("Another export job is currently running.")));
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
// wxTheApp->{preset_bundle}->full_config->validate; // FIXME
|
std::string err = wxGetApp().preset_bundle->full_config().validate();
|
||||||
const std::string err = p->print.validate();
|
if (err.empty()) {
|
||||||
|
err = p->print.validate();
|
||||||
|
}
|
||||||
if (! err.empty()) {
|
if (! err.empty()) {
|
||||||
// The config is not valid
|
// The config is not valid
|
||||||
GUI::show_error(this, _(err));
|
GUI::show_error(this, _(err));
|
||||||
return "";
|
return fs::path();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy the names of active presets into the placeholder parser.
|
// Copy the names of active presets into the placeholder parser.
|
||||||
// wxTheApp->{preset_bundle}->export_selections_pp($self->{print}->placeholder_parser); // FIXME
|
wxGetApp().preset_bundle->export_selections(p->print.placeholder_parser());
|
||||||
|
|
||||||
// select output file
|
// select output file
|
||||||
if (! output_path.empty()) {
|
if (! output_path.empty()) {
|
||||||
p->export_gcode_output_file = p->print.output_filepath(output_path);
|
p->export_gcode_output_file = fs::path(p->print.output_filepath(output_path.string()));
|
||||||
// FIXME: ^ errors to handle?
|
// FIXME: ^ errors to handle?
|
||||||
} else {
|
} else {
|
||||||
// FIXME:
|
|
||||||
std::string default_output_file; // FIXME: tmp
|
// XXX: take output path from CLI opts? Ancient Slic3r versions used to do that...
|
||||||
// my $default_output_file = eval { $self->{print}->output_filepath($main::opt{output} // '') };
|
|
||||||
// Slic3r::GUI::catch_error($self) and return;
|
|
||||||
|
|
||||||
// If possible, remove accents from accented latin characters.
|
// If possible, remove accents from accented latin characters.
|
||||||
// This function is useful for generating file names to be processed by legacy firmwares.
|
// This function is useful for generating file names to be processed by legacy firmwares.
|
||||||
default_output_file = Slic3r::fold_utf8_to_ascii(default_output_file);
|
auto default_output_file = fs::path(Slic3r::fold_utf8_to_ascii(
|
||||||
|
p->print.output_filepath(output_path.string())
|
||||||
|
// FIXME: ^ errors to handle?
|
||||||
|
));
|
||||||
|
auto start_dir = wxGetApp().app_config->get_last_output_dir(default_output_file.parent_path().string());
|
||||||
wxFileDialog dlg(this, _(L("Save G-code file as:")),
|
wxFileDialog dlg(this, _(L("Save G-code file as:")),
|
||||||
wxEmptyString,
|
start_dir,
|
||||||
wxEmptyString,
|
default_output_file.filename().string(),
|
||||||
Slic3r::GUI::FILE_WILDCARDS.at("gcode"),
|
GUI::file_wildcards[FT_GCODE],
|
||||||
wxFD_SAVE | wxFD_OVERWRITE_PROMPT
|
wxFD_SAVE | wxFD_OVERWRITE_PROMPT
|
||||||
);
|
);
|
||||||
// FIXME: ^ defaultDir:
|
|
||||||
// wxTheApp->{app_config}->get_last_output_dir(dirname($default_output_file)),
|
|
||||||
// FIXME: ^ defaultFile:
|
|
||||||
// basename($default_output_file), &Slic3r::GUI::FILE_WILDCARDS->{gcode}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
|
||||||
|
|
||||||
if (dlg.ShowModal() != wxID_OK) { return ""; }
|
if (dlg.ShowModal() != wxID_OK) { return ""; }
|
||||||
auto path = dlg.GetPath();
|
fs::path path(dlg.GetPath());
|
||||||
// wxTheApp->{app_config}->update_last_output_dir(dirname($path)); // FIXME
|
wxGetApp().app_config->update_last_output_dir(path.parent_path().string());
|
||||||
p->export_gcode_output_file = path;
|
p->export_gcode_output_file = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
return p->export_gcode_output_file;
|
return p->export_gcode_output_file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Plater::export_stl()
|
||||||
|
{
|
||||||
|
if (p->objects.empty()) { return; }
|
||||||
|
|
||||||
|
auto dialog = p->get_export_file(FT_STL);
|
||||||
|
if (! dialog) { return; }
|
||||||
|
|
||||||
|
// Store a binary STL
|
||||||
|
wxString path = dialog->GetPath();
|
||||||
|
auto path_cstr = path.c_str();
|
||||||
|
auto mesh = p->model.mesh();
|
||||||
|
Slic3r::store_stl(path_cstr, &mesh, true);
|
||||||
|
p->statusbar()->set_status_text(wxString::Format(_(L("STL file exported to %s")), path));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Plater::export_amf()
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
throw 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Plater::export_3mf()
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
throw 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Plater::reslice()
|
void Plater::reslice()
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Plater::send_gcode()
|
||||||
|
{
|
||||||
|
p->send_gcode_file = export_gcode();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}} // namespace Slic3r::GUI
|
}} // namespace Slic3r::GUI
|
||||||
|
@ -2,11 +2,15 @@
|
|||||||
#define slic3r_Plater_hpp_
|
#define slic3r_Plater_hpp_
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <boost/filesystem/path.hpp>
|
||||||
|
|
||||||
#include <wx/panel.h>
|
#include <wx/panel.h>
|
||||||
|
|
||||||
#include "Preset.hpp"
|
#include "Preset.hpp"
|
||||||
|
|
||||||
|
class wxButton;
|
||||||
|
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
class Model;
|
class Model;
|
||||||
@ -20,10 +24,12 @@ class ObjectList;
|
|||||||
|
|
||||||
using t_optgroups = std::vector <std::shared_ptr<ConfigOptionsGroup>>;
|
using t_optgroups = std::vector <std::shared_ptr<ConfigOptionsGroup>>;
|
||||||
|
|
||||||
|
class Plater;
|
||||||
|
|
||||||
class Sidebar : public wxPanel
|
class Sidebar : public wxPanel
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Sidebar(wxWindow *parent);
|
Sidebar(Plater *parent);
|
||||||
Sidebar(Sidebar &&) = delete;
|
Sidebar(Sidebar &&) = delete;
|
||||||
Sidebar(const Sidebar &) = delete;
|
Sidebar(const Sidebar &) = delete;
|
||||||
Sidebar &operator=(Sidebar &&) = delete;
|
Sidebar &operator=(Sidebar &&) = delete;
|
||||||
@ -45,8 +51,6 @@ public:
|
|||||||
private:
|
private:
|
||||||
struct priv;
|
struct priv;
|
||||||
std::unique_ptr<priv> p;
|
std::unique_ptr<priv> p;
|
||||||
|
|
||||||
friend class Plater; // XXX: better encapsulation?
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -63,10 +67,17 @@ public:
|
|||||||
Sidebar& sidebar();
|
Sidebar& sidebar();
|
||||||
Model& model();
|
Model& model();
|
||||||
|
|
||||||
// TODO: use fs::path
|
void update(bool force_autocenter = false);
|
||||||
// Note: empty string means request default path
|
void remove(size_t obj_idx);
|
||||||
std::string export_gcode(const std::string &output_path);
|
void remove_selected();
|
||||||
|
|
||||||
|
// Note: empty path means "use the default"
|
||||||
|
boost::filesystem::path export_gcode(const boost::filesystem::path &output_path = boost::filesystem::path());
|
||||||
|
void export_stl();
|
||||||
|
void export_amf();
|
||||||
|
void export_3mf();
|
||||||
void reslice();
|
void reslice();
|
||||||
|
void send_gcode();
|
||||||
private:
|
private:
|
||||||
struct priv;
|
struct priv;
|
||||||
std::unique_ptr<priv> p;
|
std::unique_ptr<priv> p;
|
||||||
|
Loading…
Reference in New Issue
Block a user