mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-26 10:11:10 -06:00
Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer into et_imgui_slider
This commit is contained in:
commit
67533da405
24 changed files with 523 additions and 255 deletions
|
|
@ -1131,29 +1131,45 @@ void GLVolumeCollection::update_colors_by_extruder(const DynamicPrintConfig* con
|
|||
if (config == nullptr)
|
||||
return;
|
||||
|
||||
const ConfigOptionStrings* extruders_opt = dynamic_cast<const ConfigOptionStrings*>(config->option("extruder_colour"));
|
||||
if (extruders_opt == nullptr)
|
||||
return;
|
||||
|
||||
const ConfigOptionStrings* filamemts_opt = dynamic_cast<const ConfigOptionStrings*>(config->option("filament_colour"));
|
||||
if (filamemts_opt == nullptr)
|
||||
return;
|
||||
|
||||
unsigned int colors_count = std::max((unsigned int)extruders_opt->values.size(), (unsigned int)filamemts_opt->values.size());
|
||||
if (colors_count == 0)
|
||||
return;
|
||||
|
||||
std::vector<Color> colors(colors_count);
|
||||
|
||||
unsigned char rgb[3];
|
||||
for (unsigned int i = 0; i < colors_count; ++i) {
|
||||
const std::string& txt_color = config->opt_string("extruder_colour", i);
|
||||
std::vector<Color> colors;
|
||||
|
||||
if (static_cast<PrinterTechnology>(config->opt_int("printer_technology")) == ptSLA)
|
||||
{
|
||||
const ConfigOptionStrings* resin_clr = dynamic_cast<const ConfigOptionStrings*>(config->option("material_colour"));
|
||||
if (resin_clr == nullptr)
|
||||
return;
|
||||
assert(resin_clr->values.size() == 1);
|
||||
colors.resize(1);
|
||||
|
||||
const std::string& txt_color = config->opt_string("material_colour", 0);
|
||||
if (Slic3r::GUI::BitmapCache::parse_color(txt_color, rgb))
|
||||
colors[i].set(txt_color, rgb);
|
||||
else {
|
||||
const std::string& txt_color = config->opt_string("filament_colour", i);
|
||||
colors[0].set(txt_color, rgb);
|
||||
}
|
||||
else
|
||||
{
|
||||
const ConfigOptionStrings* extruders_opt = dynamic_cast<const ConfigOptionStrings*>(config->option("extruder_colour"));
|
||||
if (extruders_opt == nullptr)
|
||||
return;
|
||||
|
||||
const ConfigOptionStrings* filamemts_opt = dynamic_cast<const ConfigOptionStrings*>(config->option("filament_colour"));
|
||||
if (filamemts_opt == nullptr)
|
||||
return;
|
||||
|
||||
unsigned int colors_count = std::max((unsigned int)extruders_opt->values.size(), (unsigned int)filamemts_opt->values.size());
|
||||
if (colors_count == 0)
|
||||
return;
|
||||
colors.resize(colors_count);
|
||||
|
||||
for (unsigned int i = 0; i < colors_count; ++i) {
|
||||
const std::string& txt_color = config->opt_string("extruder_colour", i);
|
||||
if (Slic3r::GUI::BitmapCache::parse_color(txt_color, rgb))
|
||||
colors[i].set(txt_color, rgb);
|
||||
else {
|
||||
const std::string& txt_color = config->opt_string("filament_colour", i);
|
||||
if (Slic3r::GUI::BitmapCache::parse_color(txt_color, rgb))
|
||||
colors[i].set(txt_color, rgb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -555,7 +555,7 @@ PagePrinters::PagePrinters(ConfigWizard *parent,
|
|||
wizard_p()->on_printer_pick(this, evt);
|
||||
});
|
||||
|
||||
append(new wxStaticLine(this));
|
||||
append(new StaticLine(this));
|
||||
|
||||
append(picker);
|
||||
printer_pickers.push_back(picker);
|
||||
|
|
@ -2800,11 +2800,7 @@ ConfigWizard::ConfigWizard(wxWindow *parent)
|
|||
|
||||
auto *vsizer = new wxBoxSizer(wxVERTICAL);
|
||||
auto *topsizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
wxStaticLine* hline = nullptr;
|
||||
#ifdef _MSW_DARK_MODE
|
||||
if (!NppDarkMode::IsEnabled())
|
||||
#endif //_MSW_DARK_MODE
|
||||
hline = new wxStaticLine(this);
|
||||
auto* hline = new StaticLine(this);
|
||||
p->btnsizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
// Initially we _do not_ SetScrollRate in order to figure out the overall width of the Wizard without scrolling.
|
||||
|
|
@ -2880,8 +2876,7 @@ ConfigWizard::ConfigWizard(wxWindow *parent)
|
|||
p->index->go_to(size_t{0});
|
||||
|
||||
vsizer->Add(topsizer, 1, wxEXPAND | wxALL, DIALOG_MARGIN);
|
||||
if (hline)
|
||||
vsizer->Add(hline, 0, wxEXPAND);
|
||||
vsizer->Add(hline, 0, wxEXPAND | wxLEFT | wxRIGHT, VERTICAL_SPACING);
|
||||
vsizer->Add(p->btnsizer, 0, wxEXPAND | wxALL, DIALOG_MARGIN);
|
||||
|
||||
SetSizer(vsizer);
|
||||
|
|
|
|||
|
|
@ -79,7 +79,9 @@ std::pair<bool, std::string> GLShadersManager::init()
|
|||
// For Apple's on Arm CPU computed triangle normals inside fragment shader using dFdx and dFdy has the opposite direction.
|
||||
// Because of this, objects had darker colors inside the multi-material gizmo.
|
||||
// Based on https://stackoverflow.com/a/66206648, the similar behavior was also spotted on some other devices with Arm CPU.
|
||||
if (platform_flavor() == PlatformFlavor::OSXOnArm)
|
||||
// Since macOS 12 (Monterey), this issue with the opposite direction on Apple's Arm CPU seems to be fixed, and computed
|
||||
// triangle normals inside fragment shader have the right direction.
|
||||
if (platform_flavor() == PlatformFlavor::OSXOnArm && wxPlatformInfo::Get().GetOSMajorVersion() < 12)
|
||||
valid &= append_shader("mm_gouraud", {"mm_gouraud.vs", "mm_gouraud.fs"}, {"FLIP_TRIANGLE_NORMALS"sv});
|
||||
else
|
||||
valid &= append_shader("mm_gouraud", {"mm_gouraud.vs", "mm_gouraud.fs"});
|
||||
|
|
|
|||
|
|
@ -411,7 +411,7 @@ bool static check_old_linux_datadir(const wxString& app_name) {
|
|||
"location again.\n\n"
|
||||
"What do you want to do now?")) % SLIC3R_APP_NAME % new_path % old_path).str());
|
||||
wxString caption = from_u8((boost::format(_u8L("%s - BREAKING CHANGE")) % SLIC3R_APP_NAME).str());
|
||||
wxRichMessageDialog dlg(nullptr, msg, caption, wxYES_NO);
|
||||
RichMessageDialog dlg(nullptr, msg, caption, wxYES_NO);
|
||||
dlg.SetYesNoLabels(_L("Quit, I will move my data now"), _L("Start the application"));
|
||||
if (dlg.ShowModal() != wxID_NO)
|
||||
return false;
|
||||
|
|
@ -846,7 +846,7 @@ bool GUI_App::check_older_app_config(Semver current_version, bool backup)
|
|||
return false;
|
||||
BOOST_LOG_TRIVIAL(info) << "last app config file used: " << m_older_data_dir_path;
|
||||
// ask about using older data folder
|
||||
wxRichMessageDialog msg(nullptr, backup ?
|
||||
RichMessageDialog msg(nullptr, backup ?
|
||||
wxString::Format(_L("PrusaSlicer detected another configuration folder at %s."
|
||||
"\nIts version is %s."
|
||||
"\nLast version you used in current configuration folder is %s."
|
||||
|
|
@ -936,7 +936,7 @@ bool GUI_App::on_init_inner()
|
|||
// win32 build on win64 and viceversa
|
||||
#ifdef _WIN64
|
||||
if (wxPlatformInfo::Get().GetArchName().substr(0, 2) == "") {
|
||||
wxRichMessageDialog dlg(nullptr,
|
||||
RichMessageDialog dlg(nullptr,
|
||||
_L("You have started PrusaSlicer for 64-bit architecture on 32-bit system."
|
||||
"\nPlease download and install correct version at https://www.prusa3d.cz/prusaslicer/."
|
||||
"\nDo you wish to continue?"),
|
||||
|
|
@ -946,7 +946,7 @@ bool GUI_App::on_init_inner()
|
|||
}
|
||||
#elif _WIN32
|
||||
if (wxPlatformInfo::Get().GetArchName().substr(0, 2) == "64") {
|
||||
wxRichMessageDialog dlg(nullptr,
|
||||
RichMessageDialog dlg(nullptr,
|
||||
_L("You have started PrusaSlicer for 32-bit architecture on 64-bit system."
|
||||
"\nPlease download and install correct version at https://www.prusa3d.cz/prusaslicer/."
|
||||
"\nDo you wish to continue?"),
|
||||
|
|
@ -991,7 +991,7 @@ bool GUI_App::on_init_inner()
|
|||
bool ssl_accept = app_config->get("tls_cert_store_accepted") == "yes" && ssl_cert_store == Http::tls_system_cert_store();
|
||||
|
||||
if (!msg.empty() && !ssl_accept) {
|
||||
wxRichMessageDialog
|
||||
RichMessageDialog
|
||||
dlg(nullptr,
|
||||
wxString::Format(_L("%s\nDo you want to continue?"), msg),
|
||||
"PrusaSlicer", wxICON_QUESTION | wxYES_NO);
|
||||
|
|
@ -1620,6 +1620,7 @@ void GUI_App::update_ui_from_settings()
|
|||
m_force_colors_update = false;
|
||||
mainframe->force_color_changed();
|
||||
mainframe->diff_dialog.force_color_changed();
|
||||
mainframe->printhost_queue_dlg()->force_color_changed();
|
||||
#ifdef _MSW_DARK_MODE
|
||||
update_scrolls(mainframe);
|
||||
#endif //_MSW_DARK_MODE
|
||||
|
|
@ -2855,7 +2856,7 @@ bool GUI_App::open_browser_with_warning_dialog(const wxString& url, int flags/*
|
|||
bool launch = true;
|
||||
|
||||
if (get_app_config()->get("suppress_hyperlinks").empty()) {
|
||||
wxRichMessageDialog dialog(nullptr, _L("Should we open this hyperlink in your default browser?"), _L("PrusaSlicer: Open hyperlink"), wxICON_QUESTION | wxYES_NO);
|
||||
RichMessageDialog dialog(nullptr, _L("Should we open this hyperlink in your default browser?"), _L("PrusaSlicer: Open hyperlink"), wxICON_QUESTION | wxYES_NO);
|
||||
dialog.ShowCheckBox(_L("Remember my choice"));
|
||||
int answer = dialog.ShowModal();
|
||||
launch = answer == wxID_YES;
|
||||
|
|
|
|||
|
|
@ -2044,8 +2044,7 @@ void ObjectList::split()
|
|||
void ObjectList::merge(bool to_multipart_object)
|
||||
{
|
||||
// merge selected objects to the multipart object
|
||||
if (to_multipart_object)
|
||||
{
|
||||
if (to_multipart_object) {
|
||||
auto get_object_idxs = [this](std::vector<int>& obj_idxs, wxDataViewItemArray& sels)
|
||||
{
|
||||
// check selections and split instances to the separated objects...
|
||||
|
|
@ -2056,8 +2055,7 @@ void ObjectList::merge(bool to_multipart_object)
|
|||
break;
|
||||
}
|
||||
|
||||
if (!instance_selection)
|
||||
{
|
||||
if (!instance_selection) {
|
||||
for (wxDataViewItem item : sels) {
|
||||
assert(m_objects_model->GetItemType(item) & itObject);
|
||||
obj_idxs.emplace_back(m_objects_model->GetIdByItem(item));
|
||||
|
|
@ -2069,8 +2067,7 @@ void ObjectList::merge(bool to_multipart_object)
|
|||
std::map<int, std::set<int>> sel_map;
|
||||
std::set<int> empty_set;
|
||||
for (wxDataViewItem item : sels) {
|
||||
if (m_objects_model->GetItemType(item) & itObject)
|
||||
{
|
||||
if (m_objects_model->GetItemType(item) & itObject) {
|
||||
int obj_idx = m_objects_model->GetIdByItem(item);
|
||||
int inst_cnt = (*m_objects)[obj_idx]->instances.size();
|
||||
if (inst_cnt == 1)
|
||||
|
|
@ -2087,8 +2084,7 @@ void ObjectList::merge(bool to_multipart_object)
|
|||
// all objects, created from the instances will be added to the end of list
|
||||
int new_objects_cnt = 0; // count of this new objects
|
||||
|
||||
for (auto map_item : sel_map)
|
||||
{
|
||||
for (auto map_item : sel_map) {
|
||||
int obj_idx = map_item.first;
|
||||
// object with just 1 instance
|
||||
if (map_item.second.empty()) {
|
||||
|
|
@ -2148,37 +2144,36 @@ void ObjectList::merge(bool to_multipart_object)
|
|||
new_object->name = _u8L("Merged");
|
||||
ModelConfig &config = new_object->config;
|
||||
|
||||
for (int obj_idx : obj_idxs)
|
||||
{
|
||||
for (int obj_idx : obj_idxs) {
|
||||
ModelObject* object = (*m_objects)[obj_idx];
|
||||
|
||||
const Geometry::Transformation& transformation = object->instances[0]->get_transformation();
|
||||
Vec3d scale = transformation.get_scaling_factor();
|
||||
Vec3d mirror = transformation.get_mirror();
|
||||
Vec3d rotation = transformation.get_rotation();
|
||||
const Vec3d scale = transformation.get_scaling_factor();
|
||||
const Vec3d mirror = transformation.get_mirror();
|
||||
const Vec3d rotation = transformation.get_rotation();
|
||||
|
||||
if (object->id() == (*m_objects)[obj_idxs.front()]->id())
|
||||
new_object->add_instance();
|
||||
Transform3d volume_offset_correction = new_object->instances[0]->get_transformation().get_matrix().inverse() * transformation.get_matrix();
|
||||
const Transform3d& volume_offset_correction = transformation.get_matrix();
|
||||
|
||||
// merge volumes
|
||||
for (const ModelVolume* volume : object->volumes) {
|
||||
ModelVolume* new_volume = new_object->add_volume(*volume);
|
||||
|
||||
//set rotation
|
||||
Vec3d vol_rot = new_volume->get_rotation() + rotation;
|
||||
const Vec3d vol_rot = new_volume->get_rotation() + rotation;
|
||||
new_volume->set_rotation(vol_rot);
|
||||
|
||||
// set scale
|
||||
Vec3d vol_sc_fact = new_volume->get_scaling_factor().cwiseProduct(scale);
|
||||
const Vec3d vol_sc_fact = new_volume->get_scaling_factor().cwiseProduct(scale);
|
||||
new_volume->set_scaling_factor(vol_sc_fact);
|
||||
|
||||
// set mirror
|
||||
Vec3d vol_mirror = new_volume->get_mirror().cwiseProduct(mirror);
|
||||
const Vec3d vol_mirror = new_volume->get_mirror().cwiseProduct(mirror);
|
||||
new_volume->set_mirror(vol_mirror);
|
||||
|
||||
// set offset
|
||||
Vec3d vol_offset = volume_offset_correction* new_volume->get_offset();
|
||||
const Vec3d vol_offset = volume_offset_correction* new_volume->get_offset();
|
||||
new_volume->set_offset(vol_offset);
|
||||
}
|
||||
new_object->sort_volumes(wxGetApp().app_config->get("order_volumes") == "1");
|
||||
|
|
@ -2211,6 +2206,11 @@ void ObjectList::merge(bool to_multipart_object)
|
|||
for (const auto& range : object->layer_config_ranges)
|
||||
new_object->layer_config_ranges.emplace(range);
|
||||
}
|
||||
|
||||
new_object->center_around_origin();
|
||||
new_object->translate_instances(-new_object->origin_translation);
|
||||
new_object->origin_translation = Vec3d::Zero();
|
||||
|
||||
// remove selected objects
|
||||
remove();
|
||||
|
||||
|
|
@ -2221,8 +2221,7 @@ void ObjectList::merge(bool to_multipart_object)
|
|||
}
|
||||
// merge all parts to the one single object
|
||||
// all part's settings will be lost
|
||||
else
|
||||
{
|
||||
else {
|
||||
wxDataViewItem item = GetSelection();
|
||||
if (!item)
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -866,6 +866,9 @@ void ObjectManipulation::change_rotation_value(int axis, double value)
|
|||
|
||||
void ObjectManipulation::change_scale_value(int axis, double value)
|
||||
{
|
||||
if (value <= 0.0)
|
||||
return;
|
||||
|
||||
if (std::abs(m_cache.scale_rounded(axis) - value) < EPSILON)
|
||||
return;
|
||||
|
||||
|
|
@ -882,6 +885,9 @@ void ObjectManipulation::change_scale_value(int axis, double value)
|
|||
|
||||
void ObjectManipulation::change_size_value(int axis, double value)
|
||||
{
|
||||
if (value <= 0.0)
|
||||
return;
|
||||
|
||||
if (std::abs(m_cache.size_rounded(axis) - value) < EPSILON)
|
||||
return;
|
||||
|
||||
|
|
@ -947,10 +953,26 @@ void ObjectManipulation::on_change(const std::string& opt_key, int axis, double
|
|||
change_position_value(axis, new_value);
|
||||
else if (opt_key == "rotation")
|
||||
change_rotation_value(axis, new_value);
|
||||
else if (opt_key == "scale")
|
||||
change_scale_value(axis, new_value);
|
||||
else if (opt_key == "size")
|
||||
change_size_value(axis, new_value);
|
||||
else if (opt_key == "scale") {
|
||||
if (new_value > 0.0)
|
||||
change_scale_value(axis, new_value);
|
||||
else {
|
||||
new_value = m_cache.scale(axis);
|
||||
m_cache.scale(axis) = 0.0;
|
||||
m_cache.scale_rounded(axis) = DBL_MAX;
|
||||
change_scale_value(axis, new_value);
|
||||
}
|
||||
}
|
||||
else if (opt_key == "size") {
|
||||
if (new_value > 0.0)
|
||||
change_size_value(axis, new_value);
|
||||
else {
|
||||
new_value = m_cache.size(axis);
|
||||
m_cache.size(axis) = 0.0;
|
||||
m_cache.size_rounded(axis) = DBL_MAX;
|
||||
change_size_value(axis, new_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectManipulation::set_uniform_scaling(const bool new_value)
|
||||
|
|
|
|||
|
|
@ -122,7 +122,9 @@ public:
|
|||
std::string err;
|
||||
ConfigSubstitutions config_substitutions;
|
||||
|
||||
priv(Plater *plt) : plater{plt} {}
|
||||
ImportDlg import_dlg;
|
||||
|
||||
priv(Plater *plt) : plater{plt}, import_dlg{plt} {}
|
||||
};
|
||||
|
||||
SLAImportJob::SLAImportJob(std::shared_ptr<ProgressIndicator> pri, Plater *plater)
|
||||
|
|
@ -176,14 +178,12 @@ void SLAImportJob::prepare()
|
|||
{
|
||||
reset();
|
||||
|
||||
ImportDlg dlg{p->plater};
|
||||
|
||||
if (dlg.ShowModal() == wxID_OK) {
|
||||
auto path = dlg.get_path();
|
||||
if (p->import_dlg.ShowModal() == wxID_OK) {
|
||||
auto path = p->import_dlg.get_path();
|
||||
auto nm = wxFileName(path);
|
||||
p->path = !nm.Exists(wxFILE_EXISTS_REGULAR) ? "" : nm.GetFullPath();
|
||||
p->sel = dlg.get_selection();
|
||||
p->win = dlg.get_marchsq_windowsize();
|
||||
p->sel = p->import_dlg.get_selection();
|
||||
p->win = p->import_dlg.get_marchsq_windowsize();
|
||||
p->config_substitutions.clear();
|
||||
} else {
|
||||
p->path = "";
|
||||
|
|
@ -236,7 +236,7 @@ void SLAImportJob::finalize()
|
|||
|
||||
if (!p->mesh.empty()) {
|
||||
bool is_centered = false;
|
||||
p->plater->sidebar().obj_list()->load_mesh_object(TriangleMesh{p->mesh},
|
||||
p->plater->sidebar().obj_list()->load_mesh_object(TriangleMesh{std::move(p->mesh)},
|
||||
name, is_centered);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ namespace GUI {
|
|||
|
||||
MsgDialog::MsgDialog(wxWindow *parent, const wxString &title, const wxString &headline, wxWindowID button_id, wxBitmap bitmap)
|
||||
: wxDialog(parent ? parent : dynamic_cast<wxWindow*>(wxGetApp().mainframe), wxID_ANY, title, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
||||
, boldfont(wxGetApp().normal_font()/*wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)*/)
|
||||
, boldfont(wxGetApp().normal_font())
|
||||
, content_sizer(new wxBoxSizer(wxVERTICAL))
|
||||
, btn_sizer(new wxBoxSizer(wxHORIZONTAL))
|
||||
{
|
||||
|
|
@ -36,6 +36,7 @@ MsgDialog::MsgDialog(wxWindow *parent, const wxString &title, const wxString &he
|
|||
this->SetFont(wxGetApp().normal_font());
|
||||
this->CenterOnParent();
|
||||
|
||||
auto *main_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
auto *topsizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
auto *rightsizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
|
|
@ -46,6 +47,7 @@ MsgDialog::MsgDialog(wxWindow *parent, const wxString &title, const wxString &he
|
|||
rightsizer->AddSpacer(VERT_SPACING);
|
||||
|
||||
rightsizer->Add(content_sizer, 1, wxEXPAND);
|
||||
btn_sizer->AddStretchSpacer();
|
||||
|
||||
if (button_id != wxID_NONE) {
|
||||
auto *button = new wxButton(this, button_id);
|
||||
|
|
@ -53,8 +55,6 @@ MsgDialog::MsgDialog(wxWindow *parent, const wxString &title, const wxString &he
|
|||
btn_sizer->Add(button);
|
||||
}
|
||||
|
||||
rightsizer->Add(btn_sizer, 0, wxALIGN_RIGHT);
|
||||
|
||||
if (! bitmap.IsOk()) {
|
||||
bitmap = create_scaled_bitmap("PrusaSlicer_192px.png", this, 192);
|
||||
}
|
||||
|
|
@ -64,7 +64,11 @@ MsgDialog::MsgDialog(wxWindow *parent, const wxString &title, const wxString &he
|
|||
topsizer->Add(logo, 0, wxALL, BORDER);
|
||||
topsizer->Add(rightsizer, 1, wxTOP | wxBOTTOM | wxRIGHT | wxEXPAND, BORDER);
|
||||
|
||||
SetSizerAndFit(topsizer);
|
||||
main_sizer->Add(topsizer, 1, wxEXPAND);
|
||||
main_sizer->Add(new StaticLine(this), 0, wxEXPAND | wxLEFT | wxRIGHT, HORIZ_SPACING);
|
||||
main_sizer->Add(btn_sizer, 0, wxALL | wxEXPAND, VERT_SPACING);
|
||||
|
||||
SetSizerAndFit(main_sizer);
|
||||
}
|
||||
|
||||
void MsgDialog::add_btn(wxWindowID btn_id, bool set_focus /*= false*/)
|
||||
|
|
@ -72,7 +76,7 @@ void MsgDialog::add_btn(wxWindowID btn_id, bool set_focus /*= false*/)
|
|||
wxButton* btn = new wxButton(this, btn_id);
|
||||
if (set_focus)
|
||||
btn->SetFocus();
|
||||
btn_sizer->Add(btn, 0, wxRIGHT, HORIZ_SPACING);
|
||||
btn_sizer->Add(btn, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, HORIZ_SPACING);
|
||||
btn->Bind(wxEVT_BUTTON, [this, btn_id](wxCommandEvent&) { this->EndModal(btn_id); });
|
||||
};
|
||||
|
||||
|
|
@ -209,33 +213,38 @@ MessageDialog::MessageDialog(wxWindow* parent,
|
|||
apply_style(style);
|
||||
finalize();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// MessageWithCheckDialog
|
||||
// RichMessageDialog
|
||||
|
||||
MessageWithCheckDialog::MessageWithCheckDialog( wxWindow* parent,
|
||||
const wxString& message,
|
||||
const wxString& checkbox_label,
|
||||
const wxString& caption/* = wxEmptyString*/,
|
||||
long style/* = wxOK*/)
|
||||
RichMessageDialog::RichMessageDialog(wxWindow* parent,
|
||||
const wxString& message,
|
||||
const wxString& caption/* = wxEmptyString*/,
|
||||
long style/* = wxOK*/)
|
||||
: MsgDialog(parent, caption.IsEmpty() ? wxString::Format(_L("%s info"), SLIC3R_APP_NAME) : caption, wxEmptyString, wxID_NONE)
|
||||
{
|
||||
add_msg_content(this, content_sizer, message);
|
||||
|
||||
m_check = new wxCheckBox(this, wxID_ANY, checkbox_label);
|
||||
content_sizer->Add(m_check, 0, wxTOP, 10);
|
||||
m_checkBox = new wxCheckBox(this, wxID_ANY, m_checkBoxText);
|
||||
m_checkBox->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent&) { m_checkBoxValue = m_checkBox->GetValue(); });
|
||||
|
||||
btn_sizer->Insert(0, m_checkBox, wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
apply_style(style);
|
||||
finalize();
|
||||
}
|
||||
|
||||
bool MessageWithCheckDialog::GetCheckVal()
|
||||
int RichMessageDialog::ShowModal()
|
||||
{
|
||||
if (m_check)
|
||||
return m_check->GetValue();
|
||||
return false;
|
||||
if (m_checkBoxText.IsEmpty())
|
||||
m_checkBox->Hide();
|
||||
else
|
||||
m_checkBox->SetLabelText(m_checkBoxText);
|
||||
Layout();
|
||||
|
||||
return wxDialog::ShowModal();
|
||||
}
|
||||
#endif
|
||||
|
||||
// InfoDialog
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@
|
|||
#include <wx/font.h>
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/msgdlg.h>
|
||||
#include <wx/richmsgdlg.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/statline.h>
|
||||
|
||||
class wxBoxSizer;
|
||||
class wxCheckBox;
|
||||
|
|
@ -17,7 +20,6 @@ namespace Slic3r {
|
|||
|
||||
namespace GUI {
|
||||
|
||||
|
||||
// A message / query dialog with a bitmap on the left and any content on the right
|
||||
// with buttons underneath.
|
||||
struct MsgDialog : wxDialog
|
||||
|
|
@ -87,6 +89,23 @@ public:
|
|||
};
|
||||
|
||||
#ifdef _WIN32
|
||||
// Generic static line, used intead of wxStaticLine
|
||||
class StaticLine: public wxTextCtrl
|
||||
{
|
||||
public:
|
||||
StaticLine( wxWindow* parent,
|
||||
wxWindowID id = wxID_ANY,
|
||||
const wxPoint& pos = wxDefaultPosition,
|
||||
const wxSize& size = wxDefaultSize,
|
||||
long style = wxLI_HORIZONTAL,
|
||||
const wxString& name = wxString::FromAscii(wxTextCtrlNameStr))
|
||||
: wxTextCtrl(parent, id, wxEmptyString, pos, size!=wxDefaultSize ? size : (style == wxLI_HORIZONTAL ? wxSize(10, 1) : wxSize(1, 10)), wxSIMPLE_BORDER, wxDefaultValidator, name)
|
||||
{
|
||||
this->Enable(false);
|
||||
}
|
||||
~StaticLine() {}
|
||||
};
|
||||
|
||||
// Generic message dialog, used intead of wxMessageDialog
|
||||
class MessageDialog : public MsgDialog
|
||||
{
|
||||
|
|
@ -101,7 +120,158 @@ public:
|
|||
MessageDialog &operator=(const MessageDialog&) = delete;
|
||||
virtual ~MessageDialog() = default;
|
||||
};
|
||||
|
||||
// Generic rich message dialog, used intead of wxRichMessageDialog
|
||||
class RichMessageDialog : public MsgDialog
|
||||
{
|
||||
wxCheckBox* m_checkBox{ nullptr };
|
||||
wxString m_checkBoxText;
|
||||
bool m_checkBoxValue{ false };
|
||||
|
||||
public:
|
||||
RichMessageDialog( wxWindow *parent,
|
||||
const wxString& message,
|
||||
const wxString& caption = wxEmptyString,
|
||||
long style = wxOK);
|
||||
RichMessageDialog(RichMessageDialog&&) = delete;
|
||||
RichMessageDialog(const RichMessageDialog&) = delete;
|
||||
RichMessageDialog &operator=(RichMessageDialog&&) = delete;
|
||||
RichMessageDialog &operator=(const RichMessageDialog&) = delete;
|
||||
virtual ~RichMessageDialog() = default;
|
||||
|
||||
int ShowModal() override;
|
||||
|
||||
void ShowCheckBox(const wxString& checkBoxText, bool checked = false)
|
||||
{
|
||||
m_checkBoxText = checkBoxText;
|
||||
m_checkBoxValue = checked;
|
||||
}
|
||||
|
||||
wxString GetCheckBoxText() const { return m_checkBoxText; }
|
||||
bool IsCheckBoxChecked() const { return m_checkBoxValue; }
|
||||
|
||||
// This part o fcode isported from the "wx\msgdlg.h"
|
||||
using wxMD = wxMessageDialogBase;
|
||||
// customization of the message box buttons
|
||||
virtual bool SetYesNoLabels(const wxMD::ButtonLabel& yes, const wxMD::ButtonLabel& no)
|
||||
{
|
||||
DoSetCustomLabel(m_yes, yes);
|
||||
DoSetCustomLabel(m_no, no);
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool SetYesNoCancelLabels(const wxMD::ButtonLabel& yes,
|
||||
const wxMD::ButtonLabel& no,
|
||||
const wxMD::ButtonLabel& cancel)
|
||||
{
|
||||
DoSetCustomLabel(m_yes, yes);
|
||||
DoSetCustomLabel(m_no, no);
|
||||
DoSetCustomLabel(m_cancel, cancel);
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool SetOKLabel(const wxMD::ButtonLabel& ok)
|
||||
{
|
||||
DoSetCustomLabel(m_ok, ok);
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool SetOKCancelLabels(const wxMD::ButtonLabel& ok,
|
||||
const wxMD::ButtonLabel& cancel)
|
||||
{
|
||||
DoSetCustomLabel(m_ok, ok);
|
||||
DoSetCustomLabel(m_cancel, cancel);
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool SetHelpLabel(const wxMD::ButtonLabel& help)
|
||||
{
|
||||
DoSetCustomLabel(m_help, help);
|
||||
return true;
|
||||
}
|
||||
// test if any custom labels were set
|
||||
bool HasCustomLabels() const
|
||||
{
|
||||
return !(m_ok.empty() && m_cancel.empty() && m_help.empty() &&
|
||||
m_yes.empty() && m_no.empty());
|
||||
}
|
||||
|
||||
// these functions return the label to be used for the button which is
|
||||
// either a custom label explicitly set by the user or the default label,
|
||||
// i.e. they always return a valid string
|
||||
wxString GetYesLabel() const
|
||||
{
|
||||
return m_yes.empty() ? GetDefaultYesLabel() : m_yes;
|
||||
}
|
||||
wxString GetNoLabel() const
|
||||
{
|
||||
return m_no.empty() ? GetDefaultNoLabel() : m_no;
|
||||
}
|
||||
wxString GetOKLabel() const
|
||||
{
|
||||
return m_ok.empty() ? GetDefaultOKLabel() : m_ok;
|
||||
}
|
||||
wxString GetCancelLabel() const
|
||||
{
|
||||
return m_cancel.empty() ? GetDefaultCancelLabel() : m_cancel;
|
||||
}
|
||||
wxString GetHelpLabel() const
|
||||
{
|
||||
return m_help.empty() ? GetDefaultHelpLabel() : m_help;
|
||||
}
|
||||
|
||||
protected:
|
||||
// this function is called by our public SetXXXLabels() and should assign
|
||||
// the value to var with possibly some transformation (e.g. Cocoa version
|
||||
// currently uses this to remove any accelerators from the button strings
|
||||
// while GTK+ one handles stock items specifically here)
|
||||
void DoSetCustomLabel(wxString& var, const wxMD::ButtonLabel& label)
|
||||
{
|
||||
var = label.GetAsString();
|
||||
}
|
||||
|
||||
// these functions return the custom label or empty string and should be
|
||||
// used only in specific circumstances such as creating the buttons with
|
||||
// these labels (in which case it makes sense to only use a custom label if
|
||||
// it was really given and fall back on stock label otherwise), use the
|
||||
// Get{Yes,No,OK,Cancel}Label() methods above otherwise
|
||||
const wxString& GetCustomYesLabel() const { return m_yes; }
|
||||
const wxString& GetCustomNoLabel() const { return m_no; }
|
||||
const wxString& GetCustomOKLabel() const { return m_ok; }
|
||||
const wxString& GetCustomHelpLabel() const { return m_help; }
|
||||
const wxString& GetCustomCancelLabel() const { return m_cancel; }
|
||||
|
||||
private:
|
||||
// these functions may be overridden to provide different defaults for the
|
||||
// default button labels (this is used by wxGTK)
|
||||
virtual wxString GetDefaultYesLabel() const { return wxGetTranslation("Yes"); }
|
||||
virtual wxString GetDefaultNoLabel() const { return wxGetTranslation("No"); }
|
||||
virtual wxString GetDefaultOKLabel() const { return wxGetTranslation("OK"); }
|
||||
virtual wxString GetDefaultCancelLabel() const { return wxGetTranslation("Cancel"); }
|
||||
virtual wxString GetDefaultHelpLabel() const { return wxGetTranslation("Help"); }
|
||||
|
||||
// labels for the buttons, initially empty meaning that the defaults should
|
||||
// be used, use GetYes/No/OK/CancelLabel() to access them
|
||||
wxString m_yes,
|
||||
m_no,
|
||||
m_ok,
|
||||
m_cancel,
|
||||
m_help;
|
||||
};
|
||||
#else
|
||||
// just a wrapper for wxStaticLine to use the same code on all platforms
|
||||
class StaticLine : public wxStaticLine
|
||||
{
|
||||
public:
|
||||
StaticLine(wxWindow* parent,
|
||||
wxWindowID id = wxID_ANY,
|
||||
const wxPoint& pos = wxDefaultPosition,
|
||||
const wxSize& size = wxDefaultSize,
|
||||
long style = wxLI_HORIZONTAL,
|
||||
const wxString& name = wxString::FromAscii(wxStaticLineNameStr))
|
||||
: wxStaticLine(parent, id, pos, size, style, name) {}
|
||||
~StaticLine() {}
|
||||
};
|
||||
// just a wrapper to wxMessageBox to use the same code on all platforms
|
||||
class MessageDialog : public wxMessageDialog
|
||||
{
|
||||
|
|
@ -113,25 +283,19 @@ public:
|
|||
: wxMessageDialog(parent, message, caption, style) {}
|
||||
~MessageDialog() {}
|
||||
};
|
||||
#endif
|
||||
|
||||
class MessageWithCheckDialog : public MsgDialog
|
||||
// just a wrapper to wxRichMessageBox to use the same code on all platforms
|
||||
class RichMessageDialog : public wxRichMessageDialog
|
||||
{
|
||||
wxCheckBox* m_check{ nullptr };
|
||||
public:
|
||||
MessageWithCheckDialog(wxWindow* parent,
|
||||
RichMessageDialog(wxWindow* parent,
|
||||
const wxString& message,
|
||||
const wxString& checkbox_label,
|
||||
const wxString& caption = wxEmptyString,
|
||||
long style = wxOK);
|
||||
MessageWithCheckDialog(MessageWithCheckDialog&&) = delete;
|
||||
MessageWithCheckDialog(const MessageWithCheckDialog&) = delete;
|
||||
MessageWithCheckDialog& operator=(MessageWithCheckDialog&&) = delete;
|
||||
MessageWithCheckDialog& operator=(const MessageWithCheckDialog&) = delete;
|
||||
virtual ~MessageWithCheckDialog() = default;
|
||||
|
||||
bool GetCheckVal();
|
||||
long style = wxOK)
|
||||
: wxRichMessageDialog(parent, message, caption, style) {}
|
||||
~RichMessageDialog() {}
|
||||
};
|
||||
#endif
|
||||
|
||||
// Generic info dialog, used for displaying exceptions
|
||||
class InfoDialog : public MsgDialog
|
||||
|
|
|
|||
|
|
@ -1920,7 +1920,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
|||
"bed_shape", "bed_custom_texture", "bed_custom_model", "complete_objects", "duplicate_distance", "extruder_clearance_radius", "skirts", "skirt_distance",
|
||||
"brim_width", "brim_separation", "brim_type", "variable_layer_height", "nozzle_diameter", "single_extruder_multi_material",
|
||||
"wipe_tower", "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_brim_width",
|
||||
"extruder_colour", "filament_colour", "max_print_height", "printer_model", "printer_technology",
|
||||
"extruder_colour", "filament_colour", "material_colour", "max_print_height", "printer_model", "printer_technology",
|
||||
// These values are necessary to construct SlicingParameters by the Canvas3D variable layer height editor.
|
||||
"layer_height", "first_layer_height", "min_layer_height", "max_layer_height",
|
||||
"brim_width", "perimeters", "perimeter_extruder", "fill_density", "infill_extruder", "top_solid_layers",
|
||||
|
|
@ -2482,15 +2482,15 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
|||
model.convert_from_meters(true);
|
||||
};
|
||||
if (answer_convert_from_meters == wxOK_DEFAULT) {
|
||||
MessageWithCheckDialog dlg(q, format_wxstr(_L_PLURAL(
|
||||
RichMessageDialog dlg(q, format_wxstr(_L_PLURAL(
|
||||
"The dimensions of the object from file %s seem to be defined in meters.\n"
|
||||
"The internal unit of PrusaSlicer are millimeters. Do you want to recalculate the dimensions of the object?",
|
||||
"The dimensions of some objects from file %s seem to be defined in meters.\n"
|
||||
"The internal unit of PrusaSlicer are millimeters. Do you want to recalculate the dimensions of these objects?", model.objects.size()), from_path(filename)) + "\n",
|
||||
_L("Apply to all the remaining small objects being loaded."),
|
||||
_L("The object is too small"), wxICON_WARNING | wxYES | wxNO);
|
||||
dlg.ShowCheckBox(_L("Apply to all the remaining small objects being loaded."));
|
||||
int answer = dlg.ShowModal();
|
||||
if (dlg.GetCheckVal())
|
||||
if (dlg.IsCheckBoxChecked())
|
||||
answer_convert_from_meters = answer;
|
||||
else
|
||||
convert_model_if(model, answer == wxID_YES);
|
||||
|
|
@ -2504,15 +2504,15 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
|||
convert_from_imperial_units(model, true);
|
||||
};
|
||||
if (answer_convert_from_imperial_units == wxOK_DEFAULT) {
|
||||
MessageWithCheckDialog dlg(q, format_wxstr(_L_PLURAL(
|
||||
RichMessageDialog dlg(q, format_wxstr(_L_PLURAL(
|
||||
"The dimensions of the object from file %s seem to be defined in inches.\n"
|
||||
"The internal unit of PrusaSlicer are millimeters. Do you want to recalculate the dimensions of the object?",
|
||||
"The dimensions of some objects from file %s seem to be defined in inches.\n"
|
||||
"The internal unit of PrusaSlicer are millimeters. Do you want to recalculate the dimensions of these objects?", model.objects.size()), from_path(filename)) + "\n",
|
||||
_L("Apply to all the remaining small objects being loaded."),
|
||||
_L("The object is too small"), wxICON_WARNING | wxYES | wxNO);
|
||||
dlg.ShowCheckBox(_L("Apply to all the remaining small objects being loaded."));
|
||||
int answer = dlg.ShowModal();
|
||||
if (dlg.GetCheckVal())
|
||||
if (dlg.IsCheckBoxChecked())
|
||||
answer_convert_from_imperial_units = answer;
|
||||
else
|
||||
convert_model_if(model, answer == wxID_YES);
|
||||
|
|
@ -6222,6 +6222,15 @@ void Plater::on_config_change(const DynamicPrintConfig &config)
|
|||
}
|
||||
}
|
||||
|
||||
if (opt_key == "material_colour") {
|
||||
update_scheduled = true; // update should be scheduled (for update 3DScene)
|
||||
|
||||
// update material color in full config
|
||||
std::vector<std::string> material_colors = { config.opt_string("material_colour", (unsigned)0) };
|
||||
p->config->option<ConfigOptionStrings>("material_colour")->values = material_colors;
|
||||
continue;
|
||||
}
|
||||
|
||||
p->config->set_key_value(opt_key, config.option(opt_key)->clone());
|
||||
if (opt_key == "printer_technology") {
|
||||
this->set_printer_technology(config.opt_enum<PrinterTechnology>(opt_key));
|
||||
|
|
|
|||
|
|
@ -101,6 +101,8 @@ PrintHostSendDialog::PrintHostSendDialog(const fs::path &path, bool can_start_pr
|
|||
EndDialog(wxID_OK);
|
||||
});
|
||||
|
||||
wxGetApp().UpdateDlgDarkUI(this);
|
||||
|
||||
Fit();
|
||||
CenterOnParent();
|
||||
|
||||
|
|
@ -331,6 +333,14 @@ void PrintHostQueueDialog::on_dpi_changed(const wxRect &suggested_rect)
|
|||
save_user_data(UDT_SIZE | UDT_POSITION | UDT_COLS);
|
||||
}
|
||||
|
||||
void PrintHostQueueDialog::on_sys_color_changed()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
wxGetApp().UpdateDlgDarkUI(this);
|
||||
wxGetApp().UpdateDVCDarkUI(job_list);
|
||||
#endif
|
||||
}
|
||||
|
||||
PrintHostQueueDialog::JobState PrintHostQueueDialog::get_state(int idx)
|
||||
{
|
||||
wxCHECK_MSG(idx >= 0 && idx < job_list->GetItemCount(), ST_ERROR, "Out of bounds access to job list");
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ public:
|
|||
}
|
||||
protected:
|
||||
void on_dpi_changed(const wxRect &suggested_rect) override;
|
||||
void on_sys_color_changed() override;
|
||||
|
||||
private:
|
||||
enum Column {
|
||||
|
|
|
|||
|
|
@ -4157,6 +4157,7 @@ void TabSLAMaterial::build()
|
|||
auto page = add_options_page(L("Material"), "resin");
|
||||
|
||||
auto optgroup = page->new_optgroup(L("Material"));
|
||||
optgroup->append_single_option_line("material_colour");
|
||||
optgroup->append_single_option_line("bottle_cost");
|
||||
optgroup->append_single_option_line("bottle_volume");
|
||||
optgroup->append_single_option_line("bottle_weight");
|
||||
|
|
@ -4164,6 +4165,12 @@ void TabSLAMaterial::build()
|
|||
|
||||
optgroup->m_on_change = [this, optgroup](t_config_option_key opt_key, boost::any value)
|
||||
{
|
||||
if (opt_key == "material_colour") {
|
||||
update_dirty();
|
||||
on_value_change(opt_key, value);
|
||||
return;
|
||||
}
|
||||
|
||||
DynamicPrintConfig new_conf = *m_config;
|
||||
|
||||
if (opt_key == "bottle_volume") {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue