mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-25 07:34:03 -06:00
Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer
This commit is contained in:
commit
b7ac74bc42
53 changed files with 1789 additions and 915 deletions
|
@ -7,6 +7,8 @@
|
|||
#include "MainFrame.hpp"
|
||||
#include "format.hpp"
|
||||
|
||||
#include <wx/clipbrd.h>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
|
@ -297,6 +299,11 @@ AboutDialog::AboutDialog()
|
|||
auto copy_rights_btn = new wxButton(this, m_copy_rights_btn_id, _L("Portions copyright")+dots);
|
||||
buttons->Insert(0, copy_rights_btn, 0, wxLEFT, 5);
|
||||
copy_rights_btn->Bind(wxEVT_BUTTON, &AboutDialog::onCopyrightBtn, this);
|
||||
|
||||
m_copy_version_btn_id = NewControlId();
|
||||
auto copy_version_btn = new wxButton(this, m_copy_version_btn_id, _L("Copy Version Info"));
|
||||
buttons->Insert(1, copy_version_btn, 0, wxLEFT, 5);
|
||||
copy_version_btn->Bind(wxEVT_BUTTON, &AboutDialog::onCopyToClipboard, this);
|
||||
|
||||
this->SetEscapeId(wxID_CLOSE);
|
||||
this->Bind(wxEVT_BUTTON, &AboutDialog::onCloseDialog, this, wxID_CLOSE);
|
||||
|
@ -348,5 +355,12 @@ void AboutDialog::onCopyrightBtn(wxEvent &)
|
|||
dlg.ShowModal();
|
||||
}
|
||||
|
||||
void AboutDialog::onCopyToClipboard(wxEvent&)
|
||||
{
|
||||
wxTheClipboard->Open();
|
||||
wxTheClipboard->SetData(new wxTextDataObject(_L("Version") + " " + std::string(SLIC3R_VERSION)));
|
||||
wxTheClipboard->Close();
|
||||
}
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
|
|
@ -60,6 +60,7 @@ class AboutDialog : public DPIDialog
|
|||
wxHtmlWindow* m_html;
|
||||
wxStaticBitmap* m_logo;
|
||||
int m_copy_rights_btn_id { wxID_ANY };
|
||||
int m_copy_version_btn_id { wxID_ANY };
|
||||
public:
|
||||
AboutDialog();
|
||||
|
||||
|
@ -70,6 +71,7 @@ private:
|
|||
void onLinkClicked(wxHtmlLinkEvent &event);
|
||||
void onCloseDialog(wxEvent &);
|
||||
void onCopyrightBtn(wxEvent &);
|
||||
void onCopyToClipboard(wxEvent&);
|
||||
};
|
||||
|
||||
} // namespace GUI
|
||||
|
|
|
@ -185,7 +185,7 @@ void BackgroundSlicingProcess::process_fff()
|
|||
break;
|
||||
}
|
||||
m_print->set_status(95, _utf8(L("Running post-processing scripts")));
|
||||
run_post_process_scripts(export_path, m_fff_print->config());
|
||||
run_post_process_scripts(export_path, m_fff_print->full_print_config());
|
||||
m_print->set_status(100, (boost::format(_utf8(L("G-code file exported to %1%"))) % export_path).str());
|
||||
} else if (! m_upload_job.empty()) {
|
||||
wxQueueEvent(GUI::wxGetApp().mainframe->m_plater, new wxCommandEvent(m_event_export_began_id));
|
||||
|
@ -538,7 +538,7 @@ void BackgroundSlicingProcess::prepare_upload()
|
|||
if (copy_file(m_temp_output_path, source_path.string(), error_message) != SUCCESS) {
|
||||
throw Slic3r::RuntimeError(_utf8(L("Copying of the temporary G-code to the output G-code failed")));
|
||||
}
|
||||
run_post_process_scripts(source_path.string(), m_fff_print->config());
|
||||
run_post_process_scripts(source_path.string(), m_fff_print->full_print_config());
|
||||
m_upload_job.upload_data.upload_path = m_fff_print->print_statistics().finalize_output_path(m_upload_job.upload_data.upload_path.string());
|
||||
} else {
|
||||
m_upload_job.upload_data.upload_path = m_sla_print->print_statistics().finalize_output_path(m_upload_job.upload_data.upload_path.string());
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "ConfigManipulation.hpp"
|
||||
#include "I18N.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "format.hpp"
|
||||
#include "libslic3r/Model.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
|
||||
|
@ -184,30 +185,21 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
|
|||
}
|
||||
|
||||
if (config->option<ConfigOptionPercent>("fill_density")->value == 100) {
|
||||
auto fill_pattern = config->option<ConfigOptionEnum<InfillPattern>>("fill_pattern")->value;
|
||||
std::string str_fill_pattern = "";
|
||||
t_config_enum_values map_names = config->option<ConfigOptionEnum<InfillPattern>>("fill_pattern")->get_enum_values();
|
||||
for (auto it : map_names) {
|
||||
if (fill_pattern == it.second) {
|
||||
str_fill_pattern = it.first;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!str_fill_pattern.empty()) {
|
||||
const std::vector<std::string>& external_fill_pattern = config->def()->get("top_fill_pattern")->enum_values;
|
||||
bool correct_100p_fill = false;
|
||||
for (const std::string& fill : external_fill_pattern)
|
||||
{
|
||||
if (str_fill_pattern == fill)
|
||||
correct_100p_fill = true;
|
||||
}
|
||||
std::string fill_pattern = config->option<ConfigOptionEnum<InfillPattern>>("fill_pattern")->serialize();
|
||||
const auto &top_fill_pattern_values = config->def()->get("top_fill_pattern")->enum_values;
|
||||
bool correct_100p_fill = std::find(top_fill_pattern_values.begin(), top_fill_pattern_values.end(), fill_pattern) != top_fill_pattern_values.end();
|
||||
if (!correct_100p_fill) {
|
||||
// get fill_pattern name from enum_labels for using this one at dialog_msg
|
||||
str_fill_pattern = _utf8(config->def()->get("fill_pattern")->enum_labels[fill_pattern]);
|
||||
if (!correct_100p_fill) {
|
||||
wxString msg_text = GUI::from_u8((boost::format(_utf8(L("The %1% infill pattern is not supposed to work at 100%% density."))) % str_fill_pattern).str());
|
||||
const ConfigOptionDef *fill_pattern_def = config->def()->get("fill_pattern");
|
||||
assert(fill_pattern_def != nullptr);
|
||||
auto it_pattern = std::find(fill_pattern_def->enum_values.begin(), fill_pattern_def->enum_values.end(), fill_pattern);
|
||||
assert(it_pattern != fill_pattern_def->enum_values.end());
|
||||
if (it_pattern != fill_pattern_def->enum_values.end()) {
|
||||
wxString msg_text = GUI::format_wxstr(_L("The %1% infill pattern is not supposed to work at 100%% density."),
|
||||
_(fill_pattern_def->enum_labels[it_pattern - fill_pattern_def->enum_values.begin()]));
|
||||
if (is_global_config)
|
||||
msg_text += "\n\n" + _(L("Shall I switch to rectilinear fill pattern?"));
|
||||
wxMessageDialog dialog(nullptr, msg_text, _(L("Infill")),
|
||||
msg_text += "\n\n" + _L("Shall I switch to rectilinear fill pattern?");
|
||||
wxMessageDialog dialog(nullptr, msg_text, _L("Infill"),
|
||||
wxICON_WARNING | (is_global_config ? wxYES | wxNO : wxOK) );
|
||||
DynamicPrintConfig new_conf = *config;
|
||||
auto answer = dialog.ShowModal();
|
||||
|
@ -315,6 +307,9 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config)
|
|||
for (auto el : { "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle",
|
||||
"wipe_tower_bridging", "wipe_tower_no_sparse_layers", "single_extruder_multi_material_priming" })
|
||||
toggle_field(el, have_wipe_tower);
|
||||
|
||||
bool have_avoid_crossing_perimeters = config->opt_bool("avoid_crossing_perimeters");
|
||||
toggle_field("avoid_crossing_perimeters_max_detour", have_avoid_crossing_perimeters);
|
||||
}
|
||||
|
||||
void ConfigManipulation::update_print_sla_config(DynamicPrintConfig* config, const bool is_global_config/* = false*/)
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "wxExtensions.hpp"
|
||||
#include "Plater.hpp"
|
||||
#include "MainFrame.hpp"
|
||||
#include "format.hpp"
|
||||
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
|
||||
|
@ -12,6 +13,7 @@
|
|||
#include <wx/numformatter.h>
|
||||
#include <wx/tooltip.h>
|
||||
#include <wx/notebook.h>
|
||||
#include <wx/tokenzr.h>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include "OG_CustomCtrl.hpp"
|
||||
|
||||
|
@ -52,6 +54,16 @@ wxString double_to_string(double const value, const int max_precision /*= 4*/)
|
|||
return s;
|
||||
}
|
||||
|
||||
wxString get_thumbnails_string(const std::vector<Vec2d>& values)
|
||||
{
|
||||
wxString ret_str;
|
||||
if (!values.empty())
|
||||
for (auto el : values)
|
||||
ret_str += wxString::Format("%ix%i, ", int(el[0]), int(el[1]));
|
||||
return ret_str;
|
||||
}
|
||||
|
||||
|
||||
Field::~Field()
|
||||
{
|
||||
if (m_on_kill_focus)
|
||||
|
@ -304,6 +316,56 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true
|
|||
|
||||
m_value = std::string(str.ToUTF8().data());
|
||||
break; }
|
||||
|
||||
case coPoints: {
|
||||
std::vector<Vec2d> out_values;
|
||||
str.Replace(" ", wxEmptyString, true);
|
||||
if (!str.IsEmpty()) {
|
||||
bool invalid_val = false;
|
||||
bool out_of_range_val = false;
|
||||
wxStringTokenizer thumbnails(str, ",");
|
||||
while (thumbnails.HasMoreTokens()) {
|
||||
wxString token = thumbnails.GetNextToken();
|
||||
double x, y;
|
||||
wxStringTokenizer thumbnail(token, "x");
|
||||
if (thumbnail.HasMoreTokens()) {
|
||||
wxString x_str = thumbnail.GetNextToken();
|
||||
if (x_str.ToDouble(&x) && thumbnail.HasMoreTokens()) {
|
||||
wxString y_str = thumbnail.GetNextToken();
|
||||
if (y_str.ToDouble(&y) && !thumbnail.HasMoreTokens()) {
|
||||
if (0 < x && x < 1000 && 0 < y && y < 1000) {
|
||||
out_values.push_back(Vec2d(x, y));
|
||||
continue;
|
||||
}
|
||||
out_of_range_val = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
invalid_val = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (out_of_range_val) {
|
||||
wxString text_value;
|
||||
if (!m_value.empty())
|
||||
text_value = get_thumbnails_string(boost::any_cast<std::vector<Vec2d>>(m_value));
|
||||
set_value(text_value, true);
|
||||
show_error(m_parent, _L("Input value is out of range")
|
||||
);
|
||||
}
|
||||
else if (invalid_val) {
|
||||
wxString text_value;
|
||||
if (!m_value.empty())
|
||||
text_value = get_thumbnails_string(boost::any_cast<std::vector<Vec2d>>(m_value));
|
||||
set_value(text_value, true);
|
||||
show_error(m_parent, format_wxstr(_L("Invalid input format. It must be represented like \"%1%\""),"XxY, XxY, ..." ));
|
||||
}
|
||||
}
|
||||
|
||||
m_value = out_values;
|
||||
break; }
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -371,6 +433,9 @@ void TextCtrl::BUILD() {
|
|||
text_value = vec->get_at(m_opt_idx);
|
||||
break;
|
||||
}
|
||||
case coPoints:
|
||||
text_value = get_thumbnails_string(m_opt.get_default_value<ConfigOptionPoints>()->values);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ using t_change = std::function<void(const t_config_option_key&, const boost::any
|
|||
using t_back_to_init = std::function<void(const std::string&)>;
|
||||
|
||||
wxString double_to_string(double const value, const int max_precision = 4);
|
||||
wxString get_thumbnails_string(const std::vector<Vec2d>& values);
|
||||
|
||||
class Field {
|
||||
protected:
|
||||
|
|
|
@ -1679,22 +1679,20 @@ void GLCanvas3D::render()
|
|||
if (wxGetApp().plater()->is_render_statistic_dialog_visible()) {
|
||||
ImGuiWrapper& imgui = *wxGetApp().imgui();
|
||||
imgui.begin(std::string("Render statistics"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
|
||||
imgui.text("Last frame: ");
|
||||
imgui.text("Last frame:");
|
||||
ImGui::SameLine();
|
||||
imgui.text(std::to_string(m_render_stats.last_frame));
|
||||
long long average = m_render_stats.get_average();
|
||||
imgui.text(std::to_string(average));
|
||||
ImGui::SameLine();
|
||||
imgui.text(" ms");
|
||||
imgui.text("FPS: ");
|
||||
imgui.text("ms");
|
||||
imgui.text("FPS:");
|
||||
ImGui::SameLine();
|
||||
imgui.text(std::to_string(static_cast<int>(1000.0f / static_cast<float>(m_render_stats.last_frame))));
|
||||
// imgui.text("Imgui FPS: ");
|
||||
// ImGui::SameLine();
|
||||
// imgui.text(std::to_string(static_cast<int>(ImGui::GetIO().Framerate)));
|
||||
imgui.text(std::to_string((average == 0) ? 0 : static_cast<int>(1000.0f / static_cast<float>(average))));
|
||||
ImGui::Separator();
|
||||
imgui.text("Compressed textures: ");
|
||||
imgui.text("Compressed textures:");
|
||||
ImGui::SameLine();
|
||||
imgui.text(OpenGLManager::are_compressed_textures_supported() ? "supported" : "not supported");
|
||||
imgui.text("Max texture size: ");
|
||||
imgui.text("Max texture size:");
|
||||
ImGui::SameLine();
|
||||
imgui.text(std::to_string(OpenGLManager::get_gl_info().get_max_tex_size()));
|
||||
imgui.end();
|
||||
|
@ -1707,8 +1705,6 @@ void GLCanvas3D::render()
|
|||
|
||||
std::string tooltip;
|
||||
|
||||
|
||||
|
||||
// Negative coordinate means out of the window, likely because the window was deactivated.
|
||||
// In that case the tooltip should be hidden.
|
||||
if (m_mouse.position.x() >= 0. && m_mouse.position.y() >= 0.) {
|
||||
|
@ -1745,7 +1741,7 @@ void GLCanvas3D::render()
|
|||
|
||||
#if ENABLE_RENDER_STATISTICS
|
||||
auto end_time = std::chrono::high_resolution_clock::now();
|
||||
m_render_stats.last_frame = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time).count();
|
||||
m_render_stats.add_frame(std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time).count());
|
||||
#endif // ENABLE_RENDER_STATISTICS
|
||||
}
|
||||
|
||||
|
@ -2491,7 +2487,12 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
|
|||
break;
|
||||
|
||||
#if ENABLE_CTRL_M_ON_WINDOWS
|
||||
#ifdef __APPLE__
|
||||
case 'm':
|
||||
case 'M':
|
||||
#else /* __APPLE__ */
|
||||
case WXK_CONTROL_M:
|
||||
#endif /* __APPLE__ */
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (wxGetApp().app_config->get("use_legacy_3DConnexion") == "1") {
|
||||
|
@ -3779,7 +3780,7 @@ GLCanvas3D::WipeTowerInfo GLCanvas3D::get_wipe_tower_info() const
|
|||
m_config->opt_float("wipe_tower_y"));
|
||||
wti.m_rotation = (M_PI/180.) * m_config->opt_float("wipe_tower_rotation_angle");
|
||||
const BoundingBoxf3& bb = vol->bounding_box();
|
||||
wti.m_bb_size = Vec2d(bb.size().x(), bb.size().y());
|
||||
wti.m_bb = BoundingBoxf{to_2d(bb.min), to_2d(bb.max)};
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -320,11 +320,22 @@ class GLCanvas3D
|
|||
};
|
||||
|
||||
#if ENABLE_RENDER_STATISTICS
|
||||
struct RenderStats
|
||||
class RenderStats
|
||||
{
|
||||
long long last_frame;
|
||||
std::queue<std::pair<long long, long long>> m_frames;
|
||||
long long m_curr_total{ 0 };
|
||||
|
||||
RenderStats() : last_frame(0) {}
|
||||
public:
|
||||
void add_frame(long long frame) {
|
||||
long long now = wxGetLocalTimeMillis().GetValue();
|
||||
if (!m_frames.empty() && now - m_frames.front().first > 1000) {
|
||||
m_curr_total -= m_frames.front().second;
|
||||
m_frames.pop();
|
||||
}
|
||||
m_curr_total += frame;
|
||||
m_frames.push({ now, frame });
|
||||
}
|
||||
long long get_average() const { return m_frames.empty() ? 0 : m_curr_total / m_frames.size(); }
|
||||
};
|
||||
#endif // ENABLE_RENDER_STATISTICS
|
||||
|
||||
|
@ -665,8 +676,8 @@ public:
|
|||
class WipeTowerInfo {
|
||||
protected:
|
||||
Vec2d m_pos = {std::nan(""), std::nan("")};
|
||||
Vec2d m_bb_size = {0., 0.};
|
||||
double m_rotation = 0.;
|
||||
BoundingBoxf m_bb;
|
||||
friend class GLCanvas3D;
|
||||
public:
|
||||
|
||||
|
@ -677,7 +688,7 @@ public:
|
|||
|
||||
inline const Vec2d& pos() const { return m_pos; }
|
||||
inline double rotation() const { return m_rotation; }
|
||||
inline const Vec2d bb_size() const { return m_bb_size; }
|
||||
inline const Vec2d bb_size() const { return m_bb.size(); }
|
||||
|
||||
void apply_wipe_tower() const;
|
||||
};
|
||||
|
|
|
@ -201,7 +201,7 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt
|
|||
}
|
||||
break;
|
||||
case coPoints:{
|
||||
if (opt_key.compare("bed_shape") == 0) {
|
||||
if (opt_key == "bed_shape" || opt_key == "thumbnails") {
|
||||
config.option<ConfigOptionPoints>(opt_key)->values = boost::any_cast<std::vector<Vec2d>>(value);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -933,13 +933,7 @@ bool GUI_App::on_init_inner()
|
|||
load_current_presets();
|
||||
mainframe->Show(true);
|
||||
|
||||
/* Temporary workaround for the correct behavior of the Scrolled sidebar panel:
|
||||
* change min hight of object list to the normal min value (15 * wxGetApp().em_unit())
|
||||
* after first whole Mainframe updating/layouting
|
||||
*/
|
||||
const int list_min_height = 15 * em_unit();
|
||||
if (obj_list()->GetMinSize().GetY() > list_min_height)
|
||||
obj_list()->SetMinSize(wxSize(-1, list_min_height));
|
||||
obj_list()->set_min_height();
|
||||
|
||||
update_mode(); // update view mode after fix of the object_list size
|
||||
|
||||
|
@ -1150,13 +1144,8 @@ void GUI_App::recreate_GUI(const wxString& msg_name)
|
|||
mainframe->Show(true);
|
||||
|
||||
dlg.Update(90, _L("Loading of a mode view") + dots);
|
||||
/* Temporary workaround for the correct behavior of the Scrolled sidebar panel:
|
||||
* change min hight of object list to the normal min value (15 * wxGetApp().em_unit())
|
||||
* after first whole Mainframe updating/layouting
|
||||
*/
|
||||
const int list_min_height = 15 * em_unit();
|
||||
if (obj_list()->GetMinSize().GetY() > list_min_height)
|
||||
obj_list()->SetMinSize(wxSize(-1, list_min_height));
|
||||
|
||||
obj_list()->set_min_height();
|
||||
update_mode();
|
||||
|
||||
// #ys_FIXME_delete_after_testing Do we still need this ?
|
||||
|
@ -1582,13 +1571,16 @@ void GUI_App::add_config_menu(wxMenuBar *menu)
|
|||
ConfigSnapshotDialog dlg(Slic3r::GUI::Config::SnapshotDB::singleton(), on_snapshot);
|
||||
dlg.ShowModal();
|
||||
if (!dlg.snapshot_to_activate().empty()) {
|
||||
if (!Config::SnapshotDB::singleton().is_on_snapshot(*app_config))
|
||||
if (! Config::SnapshotDB::singleton().is_on_snapshot(*app_config))
|
||||
Config::SnapshotDB::singleton().take_snapshot(*app_config, Config::Snapshot::SNAPSHOT_BEFORE_ROLLBACK);
|
||||
app_config->set("on_snapshot",
|
||||
Config::SnapshotDB::singleton().restore_snapshot(dlg.snapshot_to_activate(), *app_config).id);
|
||||
preset_bundle->load_presets(*app_config);
|
||||
// Load the currently selected preset into the GUI, update the preset selection box.
|
||||
load_current_presets();
|
||||
try {
|
||||
app_config->set("on_snapshot", Config::SnapshotDB::singleton().restore_snapshot(dlg.snapshot_to_activate(), *app_config).id);
|
||||
preset_bundle->load_presets(*app_config);
|
||||
// Load the currently selected preset into the GUI, update the preset selection box.
|
||||
load_current_presets();
|
||||
} catch (std::exception &ex) {
|
||||
GUI::show_error(nullptr, _L("Failed to activate configuration snapshot.") + "\n" + into_u8(ex.what()));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -191,7 +191,7 @@ ObjectList::ObjectList(wxWindow* parent) :
|
|||
// Bind(wxEVT_KEY_DOWN, &ObjectList::OnChar, this);
|
||||
{
|
||||
// Accelerators
|
||||
wxAcceleratorEntry entries[8];
|
||||
wxAcceleratorEntry entries[10];
|
||||
entries[0].Set(wxACCEL_CTRL, (int) 'C', wxID_COPY);
|
||||
entries[1].Set(wxACCEL_CTRL, (int) 'X', wxID_CUT);
|
||||
entries[2].Set(wxACCEL_CTRL, (int) 'V', wxID_PASTE);
|
||||
|
@ -200,7 +200,9 @@ ObjectList::ObjectList(wxWindow* parent) :
|
|||
entries[5].Set(wxACCEL_CTRL, (int) 'Y', wxID_REDO);
|
||||
entries[6].Set(wxACCEL_NORMAL, WXK_DELETE, wxID_DELETE);
|
||||
entries[7].Set(wxACCEL_NORMAL, WXK_BACK, wxID_DELETE);
|
||||
wxAcceleratorTable accel(8, entries);
|
||||
entries[8].Set(wxACCEL_NORMAL, int('+'), wxID_ADD);
|
||||
entries[9].Set(wxACCEL_NORMAL, int('-'), wxID_REMOVE);
|
||||
wxAcceleratorTable accel(10, entries);
|
||||
SetAcceleratorTable(accel);
|
||||
|
||||
this->Bind(wxEVT_MENU, [this](wxCommandEvent &evt) { this->copy(); }, wxID_COPY);
|
||||
|
@ -209,6 +211,8 @@ ObjectList::ObjectList(wxWindow* parent) :
|
|||
this->Bind(wxEVT_MENU, [this](wxCommandEvent &evt) { this->remove(); }, wxID_DELETE);
|
||||
this->Bind(wxEVT_MENU, [this](wxCommandEvent &evt) { this->undo(); }, wxID_UNDO);
|
||||
this->Bind(wxEVT_MENU, [this](wxCommandEvent &evt) { this->redo(); }, wxID_REDO);
|
||||
this->Bind(wxEVT_MENU, [this](wxCommandEvent &evt) { this->increase_instances(); }, wxID_ADD);
|
||||
this->Bind(wxEVT_MENU, [this](wxCommandEvent &evt) { this->decrease_instances(); }, wxID_REMOVE);
|
||||
}
|
||||
#else //__WXOSX__
|
||||
Bind(wxEVT_CHAR, [this](wxKeyEvent& event) { key_event(event); }); // doesn't work on OSX
|
||||
|
@ -254,6 +258,18 @@ ObjectList::~ObjectList()
|
|||
{
|
||||
}
|
||||
|
||||
void ObjectList::set_min_height()
|
||||
{
|
||||
/* Temporary workaround for the correct behavior of the Scrolled sidebar panel:
|
||||
* change min hight of object list to the normal min value (35 * wxGetApp().em_unit())
|
||||
* after first whole Mainframe updating/layouting
|
||||
*/
|
||||
const int list_min_height = 35 * wxGetApp().em_unit();
|
||||
if (this->GetMinSize().GetY() > list_min_height)
|
||||
this->SetMinSize(wxSize(-1, list_min_height));
|
||||
}
|
||||
|
||||
|
||||
void ObjectList::create_objects_ctrl()
|
||||
{
|
||||
/* Temporary workaround for the correct behavior of the Scrolled sidebar panel:
|
||||
|
@ -1092,6 +1108,16 @@ void ObjectList::redo()
|
|||
wxGetApp().plater()->redo();
|
||||
}
|
||||
|
||||
void ObjectList::increase_instances()
|
||||
{
|
||||
wxGetApp().plater()->increase_instances(1);
|
||||
}
|
||||
|
||||
void ObjectList::decrease_instances()
|
||||
{
|
||||
wxGetApp().plater()->decrease_instances(1);
|
||||
}
|
||||
|
||||
#ifndef __WXOSX__
|
||||
void ObjectList::key_event(wxKeyEvent& event)
|
||||
{
|
||||
|
@ -1116,6 +1142,10 @@ void ObjectList::key_event(wxKeyEvent& event)
|
|||
redo();
|
||||
else if (wxGetKeyState(wxKeyCode('Z')) && wxGetKeyState(WXK_CONTROL))
|
||||
undo();
|
||||
else if (event.GetUnicodeKey() == '+')
|
||||
increase_instances();
|
||||
else if (event.GetUnicodeKey() == '-')
|
||||
decrease_instances();
|
||||
else
|
||||
event.Skip();
|
||||
}
|
||||
|
|
|
@ -207,6 +207,7 @@ public:
|
|||
ObjectList(wxWindow* parent);
|
||||
~ObjectList();
|
||||
|
||||
void set_min_height();
|
||||
|
||||
std::map<std::string, wxBitmap> CATEGORY_ICON;
|
||||
|
||||
|
@ -257,6 +258,8 @@ public:
|
|||
bool paste_from_clipboard();
|
||||
void undo();
|
||||
void redo();
|
||||
void increase_instances();
|
||||
void decrease_instances();
|
||||
|
||||
void get_settings_choice(const wxString& category_name);
|
||||
void get_freq_settings_choice(const wxString& bundle_name);
|
||||
|
|
|
@ -30,11 +30,10 @@ public:
|
|||
ArrangePolygon get_arrange_polygon() const
|
||||
{
|
||||
Polygon ap({
|
||||
{coord_t(0), coord_t(0)},
|
||||
{scaled(m_bb_size(X)), coord_t(0)},
|
||||
{scaled(m_bb_size)},
|
||||
{coord_t(0), scaled(m_bb_size(Y))},
|
||||
{coord_t(0), coord_t(0)},
|
||||
{scaled(m_bb.min)},
|
||||
{scaled(m_bb.max.x()), scaled(m_bb.min.y())},
|
||||
{scaled(m_bb.max)},
|
||||
{scaled(m_bb.min.x()), scaled(m_bb.max.y())}
|
||||
});
|
||||
|
||||
ArrangePolygon ret;
|
||||
|
|
|
@ -132,6 +132,7 @@ void KBShortcutsDialog::fill_shortcuts()
|
|||
{ ctrl + "5", L("Switch to 3D") },
|
||||
{ ctrl + "6", L("Switch to Preview") },
|
||||
{ ctrl + "J", L("Print host upload queue") },
|
||||
{ ctrl + "Shift+" + "I", L("Open new instance") },
|
||||
// View
|
||||
{ "0-6", L("Camera view") },
|
||||
{ "E", L("Show/Hide object/instance labels") },
|
||||
|
|
|
@ -1191,9 +1191,8 @@ void MainFrame::init_menubar_as_editor()
|
|||
[this](wxCommandEvent&) { m_printhost_queue_dlg->Show(); }, "upload_queue", nullptr, []() {return true; }, this);
|
||||
|
||||
windowMenu->AppendSeparator();
|
||||
append_menu_item(windowMenu, wxID_ANY, _L("Open new instance") + "\tCtrl+I", _L("Open a new PrusaSlicer instance"),
|
||||
append_menu_item(windowMenu, wxID_ANY, _L("Open new instance") + "\tCtrl+Shift+I", _L("Open a new PrusaSlicer instance"),
|
||||
[this](wxCommandEvent&) { start_new_slicer(); }, "", nullptr, [this]() {return m_plater != nullptr && wxGetApp().app_config->get("single_instance") != "1"; }, this);
|
||||
|
||||
}
|
||||
|
||||
// View menu
|
||||
|
|
|
@ -178,7 +178,7 @@ wxPoint OG_CustomCtrl::get_pos(const Line& line, Field* field_in/* = nullptr*/)
|
|||
#ifdef __WXMSW__
|
||||
// when we use 2 monitors with different DPIs, GetTextExtent() return value for the primary display
|
||||
// so, use dc.GetMultiLineTextExtent on Windows
|
||||
wxPaintDC dc(this);
|
||||
wxClientDC dc(this);
|
||||
dc.SetFont(m_font);
|
||||
dc.GetMultiLineTextExtent(label, &label_w, &label_h);
|
||||
#else
|
||||
|
|
|
@ -25,20 +25,22 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id) {
|
|||
const t_field& OptionsGroup::build_field(const t_config_option_key& id, const ConfigOptionDef& opt) {
|
||||
// Check the gui_type field first, fall through
|
||||
// is the normal type.
|
||||
if (opt.gui_type.compare("select") == 0) {
|
||||
} else if (opt.gui_type.compare("select_open") == 0) {
|
||||
if (opt.gui_type == "select") {
|
||||
} else if (opt.gui_type == "select_open") {
|
||||
m_fields.emplace(id, std::move(Choice::Create<Choice>(this->ctrl_parent(), opt, id)));
|
||||
} else if (opt.gui_type.compare("color") == 0) {
|
||||
} else if (opt.gui_type == "color") {
|
||||
m_fields.emplace(id, std::move(ColourPicker::Create<ColourPicker>(this->ctrl_parent(), opt, id)));
|
||||
} else if (opt.gui_type.compare("f_enum_open") == 0 ||
|
||||
opt.gui_type.compare("i_enum_open") == 0 ||
|
||||
opt.gui_type.compare("i_enum_closed") == 0) {
|
||||
} else if (opt.gui_type == "f_enum_open" ||
|
||||
opt.gui_type == "i_enum_open" ||
|
||||
opt.gui_type == "i_enum_closed") {
|
||||
m_fields.emplace(id, std::move(Choice::Create<Choice>(this->ctrl_parent(), opt, id)));
|
||||
} else if (opt.gui_type.compare("slider") == 0) {
|
||||
} else if (opt.gui_type == "slider") {
|
||||
m_fields.emplace(id, std::move(SliderCtrl::Create<SliderCtrl>(this->ctrl_parent(), opt, id)));
|
||||
} else if (opt.gui_type.compare("i_spin") == 0) { // Spinctrl
|
||||
} else if (opt.gui_type.compare("legend") == 0) { // StaticText
|
||||
} else if (opt.gui_type == "i_spin") { // Spinctrl
|
||||
} else if (opt.gui_type == "legend") { // StaticText
|
||||
m_fields.emplace(id, std::move(StaticText::Create<StaticText>(this->ctrl_parent(), opt, id)));
|
||||
} else if (opt.gui_type == "one_string") {
|
||||
m_fields.emplace(id, std::move(TextCtrl::Create<TextCtrl>(this->ctrl_parent(), opt, id)));
|
||||
} else {
|
||||
switch (opt.type) {
|
||||
case coFloatOrPercent:
|
||||
|
@ -837,9 +839,9 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config
|
|||
}
|
||||
if (config.option<ConfigOptionStrings>(opt_key)->values.empty())
|
||||
ret = text_value;
|
||||
else if (opt->gui_flags.compare("serialized") == 0) {
|
||||
else if (opt->gui_flags == "serialized") {
|
||||
std::vector<std::string> values = config.option<ConfigOptionStrings>(opt_key)->values;
|
||||
if (!values.empty() && values[0].compare("") != 0)
|
||||
if (!values.empty() && !values[0].empty())
|
||||
for (auto el : values)
|
||||
text_value += el + ";";
|
||||
ret = text_value;
|
||||
|
@ -897,6 +899,8 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config
|
|||
case coPoints:
|
||||
if (opt_key == "bed_shape")
|
||||
ret = config.option<ConfigOptionPoints>(opt_key)->values;
|
||||
if (opt_key == "thumbnails")
|
||||
ret = get_thumbnails_string(config.option<ConfigOptionPoints>(opt_key)->values);
|
||||
else
|
||||
ret = config.option<ConfigOptionPoints>(opt_key)->get_at(idx);
|
||||
break;
|
||||
|
|
|
@ -2399,18 +2399,18 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
|||
wxGetApp().sidebar().update_ui_from_settings();
|
||||
};
|
||||
|
||||
if (imperial_units)
|
||||
convert_from_imperial_units(model);
|
||||
else if (model.looks_like_imperial_units()) {
|
||||
wxMessageDialog msg_dlg(q, format_wxstr(_L(
|
||||
"Some object(s) in file %s looks like saved in inches.\n"
|
||||
"Should I consider them as a saved in inches and convert them?"), from_path(filename)) + "\n",
|
||||
_L("The object appears to be saved in inches"), wxICON_WARNING | wxYES | wxNO);
|
||||
if (msg_dlg.ShowModal() == wxID_YES)
|
||||
if (!is_project_file) {
|
||||
if (imperial_units)
|
||||
convert_from_imperial_units(model);
|
||||
}
|
||||
else if (model.looks_like_imperial_units()) {
|
||||
wxMessageDialog msg_dlg(q, format_wxstr(_L(
|
||||
"Some object(s) in file %s looks like saved in inches.\n"
|
||||
"Should I consider them as a saved in inches and convert them?"), from_path(filename)) + "\n",
|
||||
_L("The object appears to be saved in inches"), wxICON_WARNING | wxYES | wxNO);
|
||||
if (msg_dlg.ShowModal() == wxID_YES)
|
||||
convert_from_imperial_units(model);
|
||||
}
|
||||
|
||||
if (! is_project_file) {
|
||||
if (model.looks_like_multipart_object()) {
|
||||
wxMessageDialog msg_dlg(q, _L(
|
||||
"This file contains several objects positioned at multiple heights.\n"
|
||||
|
|
|
@ -94,7 +94,7 @@ void OptionsSearcher::append_options(DynamicPrintConfig* config, Preset::Type ty
|
|||
|
||||
int cnt = 0;
|
||||
|
||||
if ( (type == Preset::TYPE_SLA_MATERIAL || type == Preset::TYPE_PRINTER) && opt_key != "bed_shape")
|
||||
if ( (type == Preset::TYPE_SLA_MATERIAL || type == Preset::TYPE_PRINTER) && opt_key != "bed_shape" && opt_key != "thumbnails")
|
||||
switch (config->option(opt_key)->type())
|
||||
{
|
||||
case coInts: change_opt_key<ConfigOptionInts >(opt_key, config, cnt); break;
|
||||
|
|
|
@ -109,14 +109,14 @@ Tab::Tab(wxNotebook* parent, const wxString& title, Preset::Type type) :
|
|||
m_compatible_printers.type = Preset::TYPE_PRINTER;
|
||||
m_compatible_printers.key_list = "compatible_printers";
|
||||
m_compatible_printers.key_condition = "compatible_printers_condition";
|
||||
m_compatible_printers.dialog_title = _(L("Compatible printers")).ToUTF8();
|
||||
m_compatible_printers.dialog_label = _(L("Select the printers this profile is compatible with.")).ToUTF8();
|
||||
m_compatible_printers.dialog_title = _L("Compatible printers");
|
||||
m_compatible_printers.dialog_label = _L("Select the printers this profile is compatible with.");
|
||||
|
||||
m_compatible_prints.type = Preset::TYPE_PRINT;
|
||||
m_compatible_prints.key_list = "compatible_prints";
|
||||
m_compatible_prints.key_condition = "compatible_prints_condition";
|
||||
m_compatible_prints.dialog_title = _(L("Compatible print profiles")).ToUTF8();
|
||||
m_compatible_prints.dialog_label = _(L("Select the print profiles this profile is compatible with.")).ToUTF8();
|
||||
m_compatible_prints.dialog_title = _L("Compatible print profiles");
|
||||
m_compatible_prints.dialog_label = _L("Select the print profiles this profile is compatible with.");
|
||||
|
||||
wxGetApp().tabs_list.push_back(this);
|
||||
|
||||
|
@ -542,7 +542,7 @@ void Tab::decorate()
|
|||
wxColour* colored_label_clr = nullptr;
|
||||
|
||||
if (opt.first == "bed_shape" || opt.first == "filament_ramming_parameters" ||
|
||||
opt.first == "compatible_prints" || opt.first == "compatible_printers")
|
||||
opt.first == "compatible_prints" || opt.first == "compatible_printers")
|
||||
colored_label_clr = (m_colored_Label_colors.find(opt.first) == m_colored_Label_colors.end()) ? nullptr : m_colored_Label_colors.at(opt.first);
|
||||
|
||||
if (!colored_label_clr) {
|
||||
|
@ -653,7 +653,7 @@ void TabPrinter::init_options_list()
|
|||
|
||||
for (const auto opt_key : m_config->keys())
|
||||
{
|
||||
if (opt_key == "bed_shape") {
|
||||
if (opt_key == "bed_shape" || opt_key == "thumbnails") {
|
||||
m_options_list.emplace(opt_key, m_opt_status_value);
|
||||
continue;
|
||||
}
|
||||
|
@ -1424,6 +1424,7 @@ void TabPrint::build()
|
|||
optgroup->append_single_option_line("extra_perimeters", category_path + "extra-perimeters-if-needed");
|
||||
optgroup->append_single_option_line("ensure_vertical_shell_thickness", category_path + "ensure-vertical-shell-thickness");
|
||||
optgroup->append_single_option_line("avoid_crossing_perimeters", category_path + "avoid-crossing-perimeters");
|
||||
optgroup->append_single_option_line("avoid_crossing_perimeters_max_detour", category_path + "avoid_crossing_perimeters_max_detour");
|
||||
optgroup->append_single_option_line("thin_walls", category_path + "detect-thin-walls");
|
||||
optgroup->append_single_option_line("overhangs", category_path + "detect-bridging-perimeters");
|
||||
|
||||
|
@ -2173,6 +2174,11 @@ void TabPrinter::build_fff()
|
|||
|
||||
optgroup = page->new_optgroup(L("Firmware"));
|
||||
optgroup->append_single_option_line("gcode_flavor");
|
||||
|
||||
option = optgroup->get_option("thumbnails");
|
||||
option.opt.full_width = true;
|
||||
optgroup->append_single_option_line(option);
|
||||
|
||||
optgroup->append_single_option_line("silent_mode");
|
||||
optgroup->append_single_option_line("remaining_times");
|
||||
|
||||
|
|
|
@ -136,8 +136,8 @@ protected:
|
|||
ScalableButton *btn = nullptr;
|
||||
std::string key_list; // "compatible_printers"
|
||||
std::string key_condition;
|
||||
std::string dialog_title;
|
||||
std::string dialog_label;
|
||||
wxString dialog_title;
|
||||
wxString dialog_label;
|
||||
};
|
||||
PresetDependencies m_compatible_printers;
|
||||
PresetDependencies m_compatible_prints;
|
||||
|
|
|
@ -968,6 +968,9 @@ static wxString get_string_value(std::string opt_key, const DynamicPrintConfig&
|
|||
BedShape shape(*config.option<ConfigOptionPoints>(opt_key));
|
||||
return shape.get_full_name_with_params();
|
||||
}
|
||||
if (opt_key == "thumbnails")
|
||||
return get_thumbnails_string(config.option<ConfigOptionPoints>(opt_key)->values);
|
||||
|
||||
Vec2d val = config.opt<ConfigOptionPoints>(opt_key)->get_at(opt_idx);
|
||||
return from_u8((boost::format("[%1%]") % ConfigOptionPoint(val).serialize()).str());
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue