mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-12 06:19:00 +08:00
Added STEP loading dialog (SPE-2723)
This commit is contained in:
parent
8d4f86b84a
commit
5b0a81fca4
@ -88,6 +88,7 @@ src/slic3r/GUI/Jobs/SLAImportDialog.hpp
|
||||
src/slic3r/GUI/Jobs/SLAImportJob.cpp
|
||||
src/slic3r/GUI/KBShortcutsDialog.cpp
|
||||
src/slic3r/GUI/BulkExportDialog.cpp
|
||||
src/slic3r/GUI/LoadStepDialog.cpp
|
||||
src/slic3r/GUI/LoginDialog.cpp
|
||||
src/slic3r/GUI/MainFrame.cpp
|
||||
src/slic3r/GUI/Mouse3DController.cpp
|
||||
|
@ -235,6 +235,15 @@ void AppConfig::set_defaults()
|
||||
set("sys_menu_enabled", "1");
|
||||
#endif // _WIN32
|
||||
|
||||
if (get("show_step_import_parameters").empty())
|
||||
set("show_step_import_parameters", "1");
|
||||
|
||||
if (get("linear_precision").empty())
|
||||
set("linear_precision", "0.005");
|
||||
|
||||
if (get("angle_precision").empty())
|
||||
set("angle_precision", "1.");
|
||||
|
||||
// Remove legacy window positions/sizes
|
||||
erase("", "main_frame_maximized");
|
||||
erase("", "main_frame_pos");
|
||||
|
@ -37,7 +37,7 @@ bool is_project_file(const std::string& input_file)
|
||||
}
|
||||
|
||||
// Loading model from a file, it may be a simple geometry file as STL or OBJ, however it may be a project file as well.
|
||||
static Model read_model_from_file(const std::string& input_file, LoadAttributes options)
|
||||
static Model read_model_from_file(const std::string& input_file, LoadAttributes options, const std::optional<std::pair<double, double>>& step_deflections = std::nullopt)
|
||||
{
|
||||
Model model;
|
||||
|
||||
@ -49,8 +49,9 @@ static Model read_model_from_file(const std::string& input_file, LoadAttributes
|
||||
result = load_stl(input_file.c_str(), &model);
|
||||
else if (boost::algorithm::iends_with(input_file, ".obj"))
|
||||
result = load_obj(input_file.c_str(), &model);
|
||||
else if (boost::algorithm::iends_with(input_file, ".step") || boost::algorithm::iends_with(input_file, ".stp"))
|
||||
result = load_step(input_file.c_str(), &model);
|
||||
else if (boost::algorithm::iends_with(input_file, ".step") || boost::algorithm::iends_with(input_file, ".stp")) {
|
||||
result = load_step(input_file.c_str(), &model, step_deflections);
|
||||
}
|
||||
else if (boost::algorithm::iends_with(input_file, ".amf") || boost::algorithm::iends_with(input_file, ".amf.xml"))
|
||||
//? result = load_amf(input_file.c_str(), &temp_config, &temp_config_substitutions_context, &model, options & LoadAttribute::CheckVersion);
|
||||
//? LoadAttribute::CheckVersion is needed here, when we loading just a geometry
|
||||
@ -216,9 +217,10 @@ static int removed_objects_with_zero_volume(Model& model)
|
||||
|
||||
Model load_model(const std::string& input_file,
|
||||
LoadAttributes options/* = LoadAttribute::AddDefaultInstances*/,
|
||||
LoadStats* stats/*= nullptr*/)
|
||||
LoadStats* stats/*= nullptr*/,
|
||||
std::optional<std::pair<double, double>> step_deflections/* = std::nullopt*/)
|
||||
{
|
||||
Model model = read_model_from_file(input_file, options);
|
||||
Model model = read_model_from_file(input_file, options, step_deflections);
|
||||
|
||||
for (auto obj : model.objects)
|
||||
if (obj->name.empty())
|
||||
|
@ -14,6 +14,8 @@
|
||||
|
||||
#include "PrintConfig.hpp"
|
||||
#include "enum_bitmask.hpp"
|
||||
#include <utility>
|
||||
#include <optional>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
@ -46,7 +48,8 @@ namespace FileReader
|
||||
// Exceptions don't catched inside
|
||||
Model load_model(const std::string& input_file,
|
||||
LoadAttributes options = LoadAttribute::AddDefaultInstances,
|
||||
LoadStats* statistics = nullptr);
|
||||
LoadStats* statistics = nullptr,
|
||||
std::optional<std::pair<double, double>> step_deflections = std::nullopt);
|
||||
|
||||
// Load model, config and config substitutions from input file and fill statistics if it's required.
|
||||
// Exceptions don't catched inside
|
||||
|
@ -27,9 +27,12 @@
|
||||
namespace Slic3r {
|
||||
|
||||
#if __APPLE__
|
||||
extern "C" bool load_step_internal(const char *path, OCCTResult* res);
|
||||
extern "C" bool load_step_internal(const char *path, OCCTResult* res, std::optional<std::pair<double, double>> deflections /*= std::nullopt*/);
|
||||
#endif
|
||||
|
||||
// Inside deflections pair:
|
||||
// * first value is linear deflection
|
||||
// * second value is angle deflection
|
||||
LoadStepFn get_load_step_fn()
|
||||
{
|
||||
static LoadStepFn load_step_fn = nullptr;
|
||||
@ -80,7 +83,7 @@ LoadStepFn get_load_step_fn()
|
||||
return load_step_fn;
|
||||
}
|
||||
|
||||
bool load_step(const char *path, Model *model /*BBS:, ImportStepProgressFn proFn*/)
|
||||
bool load_step(const char *path, Model *model /*BBS:, ImportStepProgressFn proFn*/, std::optional<std::pair<double, double>> deflections)
|
||||
{
|
||||
OCCTResult occt_object;
|
||||
|
||||
@ -89,7 +92,7 @@ bool load_step(const char *path, Model *model /*BBS:, ImportStepProgressFn proFn
|
||||
if (!load_step_fn)
|
||||
return false;
|
||||
|
||||
load_step_fn(path, &occt_object);
|
||||
load_step_fn(path, &occt_object, deflections);
|
||||
|
||||
assert(! occt_object.volumes.empty());
|
||||
|
||||
|
@ -9,6 +9,9 @@
|
||||
#ifndef slic3r_Format_STEP_hpp_
|
||||
#define slic3r_Format_STEP_hpp_
|
||||
|
||||
#include <utility>
|
||||
#include <optional>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class Model;
|
||||
@ -16,7 +19,10 @@ class Model;
|
||||
//typedef std::function<void(int load_stage, int current, int total, bool& cancel)> ImportStepProgressFn;
|
||||
|
||||
// Load a step file into a provided model.
|
||||
extern bool load_step(const char *path_str, Model *model /*LMBBS:, ImportStepProgressFn proFn = nullptr*/);
|
||||
// Inside deflections pair:
|
||||
// * first value is linear deflection
|
||||
// * second value is angle deflection
|
||||
extern bool load_step(const char *path_str, Model *model /*LMBBS:, ImportStepProgressFn proFn = nullptr*/, std::optional<std::pair<double, double>> deflections = std::nullopt);
|
||||
|
||||
}; // namespace Slic3r
|
||||
|
||||
|
@ -79,7 +79,7 @@ static void getNamedSolids(const TopLoc_Location& location, const Handle(XCAFDoc
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" OCCTWRAPPER_EXPORT bool load_step_internal(const char *path, OCCTResult* res /*BBS:, ImportStepProgressFn proFn*/)
|
||||
extern "C" OCCTWRAPPER_EXPORT bool load_step_internal(const char *path, OCCTResult* res /*BBS:, ImportStepProgressFn proFn*/, std::optional<std::pair<double, double>> deflections /*= std::nullopt*/)
|
||||
{
|
||||
try {
|
||||
//bool cb_cancel = false;
|
||||
@ -129,7 +129,9 @@ try {
|
||||
res->object_name = obj_name;
|
||||
|
||||
for (const NamedSolid &namedSolid : namedSolids) {
|
||||
BRepMesh_IncrementalMesh mesh(namedSolid.solid, STEP_TRANS_CHORD_ERROR, false, STEP_TRANS_ANGLE_RES, true);
|
||||
BRepMesh_IncrementalMesh mesh(namedSolid.solid,
|
||||
deflections.has_value() ? deflections.value().first : STEP_TRANS_CHORD_ERROR, false,
|
||||
deflections.has_value() ? deflections.value().second : STEP_TRANS_ANGLE_RES, true);
|
||||
res->volumes.emplace_back();
|
||||
|
||||
std::vector<Vec3f> vertices;
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <optional>
|
||||
|
||||
struct stl_facet;
|
||||
|
||||
@ -21,7 +23,7 @@ struct OCCTResult {
|
||||
std::vector<OCCTVolume> volumes;
|
||||
};
|
||||
|
||||
using LoadStepFn = bool (*)(const char *path, OCCTResult* occt_result);
|
||||
using LoadStepFn = bool (*)(const char *path, OCCTResult* occt_result, std::optional<std::pair<double, double>> deflections);
|
||||
|
||||
}; // namespace Slic3r
|
||||
|
||||
|
@ -143,6 +143,8 @@ set(SLIC3R_GUI_SOURCES
|
||||
GUI/Sidebar.hpp
|
||||
GUI/Plater.cpp
|
||||
GUI/Plater.hpp
|
||||
GUI/LoadStepDialog.cpp
|
||||
GUI/LoadStepDialog.hpp
|
||||
GUI/PresetComboBoxes.hpp
|
||||
GUI/PresetComboBoxes.cpp
|
||||
GUI/BitmapComboBox.hpp
|
||||
|
247
src/slic3r/GUI/LoadStepDialog.cpp
Normal file
247
src/slic3r/GUI/LoadStepDialog.cpp
Normal file
@ -0,0 +1,247 @@
|
||||
///|/ Copyright (c) Prusa Research 2018 - 2023 Vojtěch Bubník @bubnikv, Lukáš Matěna @lukasmatena, Oleksandra Iushchenko @YuSanka, Enrico Turri @enricoturri1966, Tomáš Mészáros @tamasmeszaros, David Kocík @kocikdav, Lukáš Hejl @hejllukas, Pavel Mikuš @Godrak, Filip Sykala @Jony01, Vojtěch Král @vojtechkral
|
||||
///|/ Copyright (c) 2022 Michael Kirsch
|
||||
///|/ Copyright (c) 2021 Boleslaw Ciesielski
|
||||
///|/ Copyright (c) 2019 John Drake @foxox
|
||||
///|/
|
||||
///|/ ported from lib/Slic3r/GUI/Plater.pm:
|
||||
///|/ Copyright (c) Prusa Research 2016 - 2019 Vojtěch Bubník @bubnikv, Vojtěch Král @vojtechkral, Enrico Turri @enricoturri1966, Oleksandra Iushchenko @YuSanka, Lukáš Matěna @lukasmatena, Tomáš Mészáros @tamasmeszaros
|
||||
///|/ Copyright (c) 2018 Martin Loidl @LoidlM
|
||||
///|/ Copyright (c) 2017 Matthias Gazzari @qtux
|
||||
///|/ Copyright (c) Slic3r 2012 - 2016 Alessandro Ranellucci @alranel
|
||||
///|/ Copyright (c) 2017 Joseph Lenox @lordofhyphens
|
||||
///|/ Copyright (c) 2015 Daren Schwenke
|
||||
///|/ Copyright (c) 2014 Mark Hindess
|
||||
///|/ Copyright (c) 2012 Mike Sheldrake @mesheldrake
|
||||
///|/ Copyright (c) 2012 Henrik Brix Andersen @henrikbrixandersen
|
||||
///|/ Copyright (c) 2012 Sam Wong
|
||||
///|/
|
||||
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
|
||||
///|/
|
||||
|
||||
#include "LoadStepDialog.hpp"
|
||||
#include <wx/window.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/radiobut.h>
|
||||
#include <wx/slider.h>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
#include "GUI_App.hpp"
|
||||
#include "format.hpp"
|
||||
#include "MsgDialog.hpp"
|
||||
#include "Widgets/CheckBox.hpp"
|
||||
|
||||
namespace Slic3r::GUI {
|
||||
|
||||
static std::vector<std::pair<std::string, PrecisionParams>> default_step_import_params = {
|
||||
{"Low" , {0.1, 1. }},
|
||||
{"Medium" , {0.05, 0.5 }},
|
||||
{"High" , {0.001, 0.03}},
|
||||
};
|
||||
|
||||
LoadStepDialog::LoadStepDialog(wxWindow* parent, const std::string& filename, double linear_precision, double angle_precision, bool multiple_loading)
|
||||
: DPIDialog(parent, wxID_ANY, format_wxstr(_L("STEP import quality (%1%)"), filename), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER),
|
||||
m_params({ linear_precision, angle_precision })
|
||||
{
|
||||
|
||||
#ifdef _WIN32
|
||||
wxGetApp().UpdateDarkUI(this);
|
||||
#else
|
||||
//SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
||||
#endif
|
||||
const wxFont& font = wxGetApp().normal_font();
|
||||
SetFont(font);
|
||||
|
||||
// Call your custom function manually after constructing base
|
||||
wxBoxSizer* main_sizer = new wxBoxSizer(wxVERTICAL); // Get the sizer
|
||||
|
||||
add_params(main_sizer);
|
||||
|
||||
main_sizer->Add(new StaticLine(this), 0, wxEXPAND | wxLEFT | wxRIGHT, em_unit());
|
||||
|
||||
wxBoxSizer* bottom_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_remember_chb = new ::CheckBox(this, _L("Remember my choice"));
|
||||
|
||||
bottom_sizer->Add(m_remember_chb, 0, wxEXPAND | wxRIGHT, 5);
|
||||
bottom_sizer->AddStretchSpacer();
|
||||
|
||||
auto buttons_sizer = CreateStdDialogButtonSizer(wxOK | wxCANCEL);
|
||||
|
||||
if (multiple_loading) {
|
||||
auto apply_btn = new wxButton(this, wxID_APPLY, "Apply to all");
|
||||
apply_btn->Bind(wxEVT_BUTTON, [this](wxEvent&) {
|
||||
m_apply_to_all = true;
|
||||
EndModal(wxID_OK);
|
||||
});
|
||||
buttons_sizer->Insert(0, apply_btn, 0, wxRIGHT, 5);
|
||||
}
|
||||
|
||||
bottom_sizer->Add(buttons_sizer, 0, wxEXPAND | wxLEFT, 5);
|
||||
main_sizer->Add(bottom_sizer, 0, wxEXPAND | wxALL, 10);
|
||||
|
||||
SetSizer(main_sizer);
|
||||
main_sizer->SetSizeHints(this);
|
||||
|
||||
m_custom_sizer->ShowItems(!m_default);
|
||||
|
||||
// Update DarkUi just for buttons
|
||||
wxGetApp().UpdateDlgDarkUI(this, true);
|
||||
|
||||
}
|
||||
|
||||
void LoadStepDialog::add_params(wxSizer* sizer)
|
||||
{
|
||||
wxBoxSizer* main_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
main_sizer->Add(new wxStaticText(this, wxID_ANY, _L("Select requested quality of the mesh after import: ")));
|
||||
|
||||
// add radio buttons for selection default parameters
|
||||
|
||||
for (const auto& [name, params] : default_step_import_params) {
|
||||
wxRadioButton* radio_def = new wxRadioButton(this, wxID_ANY, format_wxstr("%1%", _L(name)));
|
||||
radio_def->Bind(wxEVT_RADIOBUTTON, [params_copy = params, this](wxEvent&) {
|
||||
m_params.linear = params_copy.linear;
|
||||
m_params.angle = params_copy.angle;
|
||||
|
||||
m_custom_sizer->ShowItems(false);
|
||||
});
|
||||
bool is_selected = m_params.linear == params.linear && params.angle == params.angle;
|
||||
radio_def->SetValue(is_selected);
|
||||
|
||||
m_default |= is_selected;
|
||||
|
||||
main_sizer->Add(radio_def, 0, wxLEFT | wxTOP, em_unit());
|
||||
}
|
||||
|
||||
// add radio buttons for set custom parameters
|
||||
|
||||
wxRadioButton* radio_custom = new wxRadioButton(this, wxID_ANY, _L("Custom"));
|
||||
radio_custom->Bind(wxEVT_RADIOBUTTON, [&, this](wxEvent&) {
|
||||
m_custom_sizer->ShowItems(true);
|
||||
#ifdef __linux__
|
||||
this->Fit();
|
||||
#endif // __linux__
|
||||
m_params.linear = string_to_double_decimal_point(m_linear_precision_val->GetValue().ToStdString());
|
||||
m_params.angle = string_to_double_decimal_point(m_angle_precision_val->GetValue().ToStdString());
|
||||
});
|
||||
|
||||
main_sizer->Add(radio_custom, 0, wxLEFT | wxTOP, em_unit());
|
||||
radio_custom->SetValue(!m_default);
|
||||
|
||||
long slyder_style = wxSL_HORIZONTAL | wxSL_TICKS;
|
||||
long text_ctrl_style = wxTE_PROCESS_ENTER;
|
||||
#ifdef _WIN32
|
||||
text_ctrl_style |= wxBORDER_SIMPLE;
|
||||
#endif
|
||||
|
||||
const wxSize def_slider_size = wxSize(15 * em_unit(), wxDefaultCoord);
|
||||
const wxSize def_editor_size = wxSize(5 * em_unit(), wxDefaultCoord);
|
||||
|
||||
const int hgap = 5;
|
||||
wxFlexGridSizer* grid_sizer = new wxFlexGridSizer(4, em_unit(), hgap);
|
||||
grid_sizer->SetFlexibleDirection(wxBOTH);
|
||||
grid_sizer->AddGrowableCol(1, 1);
|
||||
grid_sizer->AddGrowableRow(0, 1);
|
||||
grid_sizer->AddGrowableRow(1, 1);
|
||||
|
||||
wxBoxSizer* labels_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
{
|
||||
const wxString left_text = _L("Lower quality");
|
||||
const int left_text_gap = std::max(GetTextExtent(_L("Linear precision")).x, GetTextExtent(_L("Angle precision")).x) + 4 * hgap - GetTextExtent(left_text).x * 0.5;
|
||||
const wxString right_text = _L("Higher quality");
|
||||
const int right_text_gap = GetTextExtent(_L("mm")).x + def_editor_size.x + 4 * hgap - GetTextExtent(right_text).x * 0.5;
|
||||
labels_sizer->Add(new wxStaticText(this, wxID_ANY, left_text), 0, wxLEFT, left_text_gap);
|
||||
labels_sizer->Add(new wxStaticText(this, wxID_ANY, wxEmptyString), 1, wxEXPAND);
|
||||
labels_sizer->Add(new wxStaticText(this, wxID_ANY, right_text), 0, wxRIGHT, right_text_gap);
|
||||
}
|
||||
|
||||
auto high_vals = std::find_if(default_step_import_params.begin(), default_step_import_params.end(),
|
||||
[](const std::pair<std::string, PrecisionParams>& val) { return val.first == "High"; });
|
||||
auto low_vals = std::find_if(default_step_import_params.begin(), default_step_import_params.end(),
|
||||
[](const std::pair<std::string, PrecisionParams>& val) { return val.first == "Low"; });
|
||||
assert(high_vals != default_step_import_params.end() && low_vals != default_step_import_params.end());
|
||||
|
||||
m_linear_precision_sl.init(high_vals->second.linear, low_vals->second.linear, 0.001);
|
||||
m_angle_precision_sl.init(high_vals->second.angle, low_vals->second.angle, 0.01);
|
||||
|
||||
auto process_value_change = [](double& precision, wxTextCtrl* text_ctrl, wxSlider* slider, const SliderHelper& sl_helper) -> void {
|
||||
wxString str_val = text_ctrl->GetValue();
|
||||
double val = string_to_double_decimal_point(str_val.ToStdString());
|
||||
precision = sl_helper.adjust_to_region(val);
|
||||
slider->SetValue(sl_helper.get_pos(precision));
|
||||
|
||||
if (wxString str_precision = format_wxstr("%1%", precision); str_precision != str_val)
|
||||
text_ctrl->SetValue(str_precision);
|
||||
};
|
||||
|
||||
// Add "Linear precision"
|
||||
|
||||
m_linear_precision_slider = new wxSlider(this, wxID_ANY, m_linear_precision_sl.get_pos(m_params.linear), m_linear_precision_sl.beg_sl_pos, m_linear_precision_sl.end_sl_pos, wxDefaultPosition, def_slider_size, slyder_style);
|
||||
m_linear_precision_slider->SetTickFreq(10);
|
||||
m_linear_precision_slider->Bind(wxEVT_SLIDER, [this](wxCommandEvent e) {
|
||||
m_params.linear = m_linear_precision_sl.get_value(m_linear_precision_slider->GetValue());
|
||||
m_linear_precision_val->SetValue(format_wxstr("%1%", m_params.linear));
|
||||
});
|
||||
|
||||
m_linear_precision_val = new wxTextCtrl(this, wxID_ANY, format_wxstr("%1%", m_linear_precision_sl.adjust_to_region(m_params.linear)), wxDefaultPosition, def_editor_size, text_ctrl_style);
|
||||
m_linear_precision_val->SetToolTip(format_wxstr("Set value from the range [%1%; %2%] with %3% step",
|
||||
m_linear_precision_sl.min_val, m_linear_precision_sl.max_val, m_linear_precision_sl.val_step));
|
||||
|
||||
m_linear_precision_val->Bind(wxEVT_TEXT_ENTER, [process_value_change, this](wxCommandEvent& e) {
|
||||
process_value_change(m_params.linear, m_linear_precision_val, m_linear_precision_slider, m_linear_precision_sl);
|
||||
});
|
||||
m_linear_precision_val->Bind(wxEVT_KILL_FOCUS, [process_value_change, this](wxFocusEvent& e) {
|
||||
process_value_change(m_params.linear, m_linear_precision_val, m_linear_precision_slider, m_linear_precision_sl);
|
||||
e.Skip();
|
||||
});
|
||||
|
||||
grid_sizer->Add(new wxStaticText(this, wxID_ANY, _L("Linear precision") + ": "), 0, wxALIGN_CENTER_VERTICAL);
|
||||
grid_sizer->Add(m_linear_precision_slider, 1, wxEXPAND);
|
||||
grid_sizer->Add(m_linear_precision_val, 0, wxALIGN_CENTER_VERTICAL);
|
||||
grid_sizer->Add(new wxStaticText(this, wxID_ANY, _L("mm")), 0, wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
// Add "Angle precision"
|
||||
|
||||
m_angle_precision_slider = new wxSlider(this, wxID_ANY, m_angle_precision_sl.get_pos(m_params.angle), m_angle_precision_sl.beg_sl_pos, m_angle_precision_sl.end_sl_pos, wxDefaultPosition, def_slider_size, slyder_style);
|
||||
m_angle_precision_slider->SetTickFreq(10);
|
||||
m_angle_precision_slider->Bind(wxEVT_SLIDER, [this](wxCommandEvent e) {
|
||||
m_params.angle = m_angle_precision_sl.get_value(m_angle_precision_slider->GetValue());
|
||||
m_angle_precision_val->SetValue(format_wxstr("%1%", m_params.angle));
|
||||
});
|
||||
|
||||
m_angle_precision_val = new wxTextCtrl(this, wxID_ANY, format_wxstr("%1%", m_angle_precision_sl.adjust_to_region(m_params.angle)), wxDefaultPosition, def_editor_size, text_ctrl_style);
|
||||
m_angle_precision_val->SetToolTip(format_wxstr("Set value from the range [%1%; %2%] with %3% step",
|
||||
m_angle_precision_sl.min_val, m_angle_precision_sl.max_val, m_angle_precision_sl.val_step));
|
||||
|
||||
m_angle_precision_val->Bind(wxEVT_TEXT_ENTER, [process_value_change, this](wxCommandEvent& e) {
|
||||
process_value_change(m_params.angle, m_angle_precision_val, m_angle_precision_slider, m_angle_precision_sl);
|
||||
});
|
||||
m_angle_precision_val->Bind(wxEVT_KILL_FOCUS, [process_value_change, this](wxFocusEvent& e) {
|
||||
process_value_change(m_params.angle, m_angle_precision_val, m_angle_precision_slider, m_angle_precision_sl);
|
||||
e.Skip();
|
||||
});
|
||||
|
||||
grid_sizer->Add(new wxStaticText(this, wxID_ANY, _L("Angle precision") + ": "), 0, wxALIGN_CENTER_VERTICAL);
|
||||
grid_sizer->Add(m_angle_precision_slider, 1, wxEXPAND);
|
||||
grid_sizer->Add(m_angle_precision_val, 0, wxALIGN_CENTER_VERTICAL);
|
||||
grid_sizer->Add(new wxStaticText(this, wxID_ANY, _L("°")), 0, wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
m_custom_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
m_custom_sizer->Add(labels_sizer, 0, wxEXPAND | wxBOTTOM | wxTOP, em_unit());
|
||||
m_custom_sizer->Add(grid_sizer, 1, wxEXPAND);
|
||||
|
||||
main_sizer->Add(m_custom_sizer, 1, wxEXPAND | wxLEFT, 3 * em_unit());
|
||||
sizer->Add(main_sizer, 1, wxEXPAND | wxALL, em_unit());
|
||||
}
|
||||
|
||||
bool LoadStepDialog::IsCheckBoxChecked()
|
||||
{
|
||||
return m_remember_chb && m_remember_chb->GetValue();
|
||||
}
|
||||
|
||||
bool LoadStepDialog::IsApplyToAllClicked()
|
||||
{
|
||||
return m_apply_to_all;
|
||||
}
|
||||
|
||||
} // namespace Slic3r::GUI
|
99
src/slic3r/GUI/LoadStepDialog.hpp
Normal file
99
src/slic3r/GUI/LoadStepDialog.hpp
Normal file
@ -0,0 +1,99 @@
|
||||
///|/ Copyright (c) Prusa Research 2018 - 2025 Oleksandra Iushchenko @YuSanka
|
||||
///|/
|
||||
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
|
||||
///|/
|
||||
|
||||
#ifndef slic3r_LoadStepDialog_hpp_
|
||||
#define slic3r_LoadStepDialog_hpp_
|
||||
|
||||
#include <string>
|
||||
#include <wx/dialog.h>
|
||||
#include "GUI_Utils.hpp"
|
||||
|
||||
class wxBoxSizer;
|
||||
class wxTextCtrl;
|
||||
class wxSlider;
|
||||
class CheckBox;
|
||||
|
||||
namespace Slic3r::GUI {
|
||||
|
||||
struct PrecisionParams
|
||||
{
|
||||
double linear;
|
||||
double angle;
|
||||
};
|
||||
|
||||
struct SliderHelper
|
||||
{
|
||||
double min_val;
|
||||
double max_val;
|
||||
double val_step;
|
||||
int beg_sl_pos;
|
||||
int end_sl_pos;
|
||||
|
||||
void init(double min, double max, double step, int beg_pos = 1) {
|
||||
assert(val_step != 0.);
|
||||
min_val = min;
|
||||
max_val = max;
|
||||
val_step = step;
|
||||
|
||||
beg_sl_pos = beg_pos;
|
||||
end_sl_pos = beg_sl_pos + int(double(max_val - min_val) / val_step);
|
||||
}
|
||||
|
||||
double get_value(int pos) const {
|
||||
return max_val - val_step * (pos - beg_sl_pos);
|
||||
}
|
||||
|
||||
int get_pos(double value) const {
|
||||
return beg_sl_pos + int((max_val - value) / val_step);
|
||||
}
|
||||
|
||||
double adjust_to_region(double value) const {
|
||||
return std::max(std::min(value, max_val), min_val);
|
||||
}
|
||||
};
|
||||
|
||||
class LoadStepDialog : public DPIDialog
|
||||
{
|
||||
public:
|
||||
LoadStepDialog(wxWindow* parent, const std::string& filename, double linear_precision, double angle_precision, bool multiple_loading);
|
||||
~LoadStepDialog() = default;
|
||||
|
||||
bool IsCheckBoxChecked();
|
||||
bool IsApplyToAllClicked();
|
||||
|
||||
double get_linear_precision() { return m_params.linear; }
|
||||
double get_angle_precision() { return m_params.angle; }
|
||||
|
||||
protected:
|
||||
void on_dpi_changed(const wxRect& suggested_rect) override {}
|
||||
void on_sys_color_changed() override {};
|
||||
|
||||
|
||||
private:
|
||||
void add_params(wxSizer* sizer);
|
||||
|
||||
private:
|
||||
PrecisionParams m_params;
|
||||
|
||||
::CheckBox* m_remember_chb { nullptr };
|
||||
|
||||
wxTextCtrl* m_linear_precision_val { nullptr };
|
||||
wxTextCtrl* m_angle_precision_val { nullptr };
|
||||
|
||||
wxSlider* m_linear_precision_slider { nullptr };
|
||||
wxSlider* m_angle_precision_slider { nullptr };
|
||||
|
||||
wxBoxSizer* m_custom_sizer { nullptr };
|
||||
|
||||
bool m_default { false };
|
||||
bool m_apply_to_all { false };
|
||||
|
||||
SliderHelper m_linear_precision_sl;
|
||||
SliderHelper m_angle_precision_sl;
|
||||
};
|
||||
|
||||
} // namespace Slic3r::GUI
|
||||
|
||||
#endif
|
@ -30,6 +30,7 @@
|
||||
#include <string>
|
||||
#include <regex>
|
||||
#include <future>
|
||||
#include <utility>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/nowide/cstdio.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
@ -138,6 +139,7 @@
|
||||
#include "ConfigWizardWebViewPage.hpp"
|
||||
#include "PresetArchiveDatabase.hpp"
|
||||
#include "BulkExportDialog.hpp"
|
||||
#include "LoadStepDialog.hpp"
|
||||
|
||||
#include "libslic3r/ArrangeHelper.hpp"
|
||||
|
||||
@ -325,6 +327,7 @@ struct Plater::priv
|
||||
static const std::regex pattern_prusa;
|
||||
static const std::regex pattern_zip;
|
||||
static const std::regex pattern_printRequest;
|
||||
static const std::regex pattern_step;
|
||||
|
||||
priv(Plater *q, MainFrame *main_frame);
|
||||
~priv();
|
||||
@ -615,11 +618,13 @@ private:
|
||||
bool show_warning_dialog { false };
|
||||
};
|
||||
|
||||
// FIXME: Some of the regex patterns are wrong (missing [.] before file extension).
|
||||
const std::regex Plater::priv::pattern_bundle(".*[.](amf|amf[.]xml|3mf)", std::regex::icase);
|
||||
const std::regex Plater::priv::pattern_3mf(".*3mf", std::regex::icase);
|
||||
const std::regex Plater::priv::pattern_any_amf(".*[.](amf|amf[.]xml|zip[.]amf)", std::regex::icase);
|
||||
const std::regex Plater::priv::pattern_zip(".*zip", std::regex::icase);
|
||||
const std::regex Plater::priv::pattern_printRequest(".*printRequest", std::regex::icase);
|
||||
const std::regex Plater::priv::pattern_step(".*[.](step|stp)", std::regex::icase);
|
||||
|
||||
Plater::priv::priv(Plater* q, MainFrame* main_frame)
|
||||
: q(q)
|
||||
@ -1288,6 +1293,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
||||
int answer_convert_from_meters = wxOK_DEFAULT;
|
||||
int answer_convert_from_imperial_units = wxOK_DEFAULT;
|
||||
int answer_consider_as_multi_part_objects = wxOK_DEFAULT;
|
||||
bool apply_step_import_parameters_to_all { false };
|
||||
|
||||
bool in_temp = false;
|
||||
const fs::path temp_path = wxStandardPaths::Get().GetTempDir().utf8_str().data();
|
||||
@ -1303,7 +1309,26 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
||||
const auto &path = input_files[i];
|
||||
#endif // _WIN32
|
||||
in_temp = (path.parent_path() == temp_path);
|
||||
const auto filename = path.filename();
|
||||
const boost::filesystem::path filename = path.filename();
|
||||
|
||||
const bool type_step = std::regex_match(path.string(), pattern_step);
|
||||
if (type_step && !apply_step_import_parameters_to_all &&
|
||||
wxGetApp().app_config->get_bool("show_step_import_parameters")) {
|
||||
|
||||
double linear_precision = string_to_double_decimal_point(wxGetApp().app_config->get("linear_precision"));
|
||||
double angle_precision = string_to_double_decimal_point(wxGetApp().app_config->get("angle_precision"));
|
||||
|
||||
LoadStepDialog dlg(q, filename.string(), linear_precision, angle_precision, (input_files_size - i) > 1);
|
||||
if (dlg.ShowModal() == wxID_OK) {
|
||||
wxGetApp().app_config->set("linear_precision", float_to_string_decimal_point(dlg.get_linear_precision()));
|
||||
wxGetApp().app_config->set("angle_precision", float_to_string_decimal_point(dlg.get_angle_precision()));
|
||||
if (dlg.IsCheckBoxChecked())
|
||||
wxGetApp().app_config->set("show_step_import_parameters", "0");
|
||||
apply_step_import_parameters_to_all = dlg.IsApplyToAllClicked();
|
||||
} else
|
||||
continue;
|
||||
}
|
||||
|
||||
if (progress_dlg) {
|
||||
progress_dlg->Update(static_cast<int>(100.0f * static_cast<float>(i) / static_cast<float>(input_files.size())), _L("Loading file") + ": " + from_path(filename));
|
||||
progress_dlg->Fit();
|
||||
@ -1352,7 +1377,14 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
||||
model = FileReader::load_model_with_config(path.string(), &config_loaded, &config_substitutions, prusaslicer_generator_version, FileReader::LoadAttribute::CheckVersion, &load_stats);
|
||||
}
|
||||
else if (load_model) {
|
||||
model = FileReader::load_model(path.string(), FileReader::LoadAttributes{}, &load_stats);
|
||||
if (type_step) {
|
||||
double linear_precision = string_to_double_decimal_point(wxGetApp().app_config->get("linear_precision"));
|
||||
double angle_precision = string_to_double_decimal_point(wxGetApp().app_config->get("angle_precision"));
|
||||
model = FileReader::load_model(path.string(), FileReader::LoadAttributes{}, &load_stats,
|
||||
std::make_pair(linear_precision, angle_precision));
|
||||
}
|
||||
else
|
||||
model = FileReader::load_model(path.string(), FileReader::LoadAttributes{}, &load_stats);
|
||||
}
|
||||
} catch (const ConfigurationError &e) {
|
||||
std::string message = GUI::format(_L("Failed loading file \"%1%\" due to an invalid configuration."), filename.string()) + "\n\n" + e.what();
|
||||
|
@ -135,7 +135,7 @@ void PreferencesDialog::show(const std::string& highlight_opt_key /*= std::strin
|
||||
downloader->set_path_name(app_config->get("url_downloader_dest"));
|
||||
downloader->allow(!app_config->has("downloader_url_registered") || app_config->get_bool("downloader_url_registered"));
|
||||
|
||||
for (const std::string opt_key : {"suppress_hyperlinks", "downloader_url_registered", "show_login_button"})
|
||||
for (const std::string opt_key : {"suppress_hyperlinks", "downloader_url_registered", "show_login_button", "show_step_import_parameters"})
|
||||
m_optgroup_other->set_value(opt_key, app_config->get_bool(opt_key));
|
||||
// by default "Log in" button is visible
|
||||
if (!app_config->has("show_login_button"))
|
||||
@ -629,6 +629,11 @@ void PreferencesDialog::build()
|
||||
// "If disabled, the descriptions of configuration parameters in settings tabs will work as hyperlinks."),
|
||||
app_config->get_bool("suppress_hyperlinks"));
|
||||
|
||||
append_bool_option(m_optgroup_other, "show_step_import_parameters",
|
||||
L("Show STEP file import parameters"),
|
||||
L("If enabled, PrusaSlicer will show dialog with quality selection when importing STEP file."),
|
||||
app_config->get_bool("show_step_import_parameters"));
|
||||
|
||||
append_bool_option(m_optgroup_other, "show_login_button",
|
||||
L("Show \"Log in\" button in application top bar"),
|
||||
L("If enabled, PrusaSlicer will show up \"Log in\" button in application top bar."),
|
||||
|
Loading…
x
Reference in New Issue
Block a user