Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer into et_texture_support

This commit is contained in:
enricoturri1966 2021-11-29 13:50:57 +01:00
commit 39368570b3
16 changed files with 146 additions and 60 deletions

View File

@ -1,5 +1,6 @@
min_slic3r_version = 2.4.0-beta0 min_slic3r_version = 2.4.0-beta2
1.4.0-beta2 Added SLA material colors. Updated BASF filament profiles. 1.4.0-beta2 Added SLA material colors. Updated BASF filament profiles.
min_slic3r_version = 2.4.0-beta0
1.4.0-beta1 Updated pad wall slope angle for SLA printers. Updated Filatech Filacarbon profile for Prusa MINI. 1.4.0-beta1 Updated pad wall slope angle for SLA printers. Updated Filatech Filacarbon profile for Prusa MINI.
1.4.0-beta0 Added multiple Filatech and BASF filament profiles. Added material profiles for SL1S. 1.4.0-beta0 Added multiple Filatech and BASF filament profiles. Added material profiles for SL1S.
min_slic3r_version = 2.4.0-alpha0 min_slic3r_version = 2.4.0-alpha0

View File

@ -1544,30 +1544,37 @@ void GCode::process_layers(
const size_t single_object_idx, const size_t single_object_idx,
GCodeOutputStream &output_stream) GCodeOutputStream &output_stream)
{ {
// The pipeline is fixed: Neither wipe tower nor vase mode are implemented for sequential print. // The pipeline is variable: The vase mode filter is optional.
size_t layer_to_print_idx = 0; size_t layer_to_print_idx = 0;
tbb::parallel_pipeline(12, const auto generator = tbb::make_filter<void, GCode::LayerResult>(tbb::filter::serial_in_order,
tbb::make_filter<void, GCode::LayerResult>( [this, &print, &tool_ordering, &layers_to_print, &layer_to_print_idx, single_object_idx](tbb::flow_control& fc) -> GCode::LayerResult {
tbb::filter::serial_in_order, if (layer_to_print_idx == layers_to_print.size()) {
[this, &print, &tool_ordering, &layers_to_print, &layer_to_print_idx, single_object_idx](tbb::flow_control& fc) -> GCode::LayerResult { fc.stop();
if (layer_to_print_idx == layers_to_print.size()) { return {};
fc.stop(); } else {
return {}; LayerToPrint &layer = layers_to_print[layer_to_print_idx ++];
} else { print.throw_if_canceled();
LayerToPrint &layer = layers_to_print[layer_to_print_idx ++]; return this->process_layer(print, { std::move(layer) }, tool_ordering.tools_for_layer(layer.print_z()), &layer == &layers_to_print.back(), nullptr, single_object_idx);
print.throw_if_canceled(); }
return this->process_layer(print, { std::move(layer) }, tool_ordering.tools_for_layer(layer.print_z()), &layer == &layers_to_print.back(), nullptr, single_object_idx); });
} const auto spiral_vase = tbb::make_filter<GCode::LayerResult, GCode::LayerResult>(tbb::filter::serial_in_order,
}) & [&spiral_vase = *this->m_spiral_vase.get()](GCode::LayerResult in)->GCode::LayerResult {
tbb::make_filter<GCode::LayerResult, std::string>( spiral_vase.enable(in.spiral_vase_enable);
tbb::filter::serial_in_order, return { spiral_vase.process_layer(std::move(in.gcode)), in.layer_id, in.spiral_vase_enable, in.cooling_buffer_flush };
[&cooling_buffer = *this->m_cooling_buffer.get()](GCode::LayerResult in) -> std::string { });
return cooling_buffer.process_layer(std::move(in.gcode), in.layer_id, in.cooling_buffer_flush); const auto cooling = tbb::make_filter<GCode::LayerResult, std::string>(tbb::filter::serial_in_order,
}) & [&cooling_buffer = *this->m_cooling_buffer.get()](GCode::LayerResult in)->std::string {
tbb::make_filter<std::string, void>( return cooling_buffer.process_layer(std::move(in.gcode), in.layer_id, in.cooling_buffer_flush);
tbb::filter::serial_in_order, });
[&output_stream](std::string s) { output_stream.write(s); } const auto output = tbb::make_filter<std::string, void>(tbb::filter::serial_in_order,
)); [&output_stream](std::string s) { output_stream.write(s); }
);
// The pipeline elements are joined using const references, thus no copying is performed.
if (m_spiral_vase)
tbb::parallel_pipeline(12, generator & spiral_vase & cooling & output);
else
tbb::parallel_pipeline(12, generator & cooling & output);
} }
std::string GCode::placeholder_parser_process(const std::string &name, const std::string &templ, unsigned int current_extruder_id, const DynamicConfig *config_override) std::string GCode::placeholder_parser_process(const std::string &name, const std::string &templ, unsigned int current_extruder_id, const DynamicConfig *config_override)

View File

@ -613,13 +613,25 @@ const PrintObjectRegions::BoundingBox* find_volume_extents(const PrintObjectRegi
} }
// Find a bounding box of a topmost printable volume referenced by this modifier given this_region_id. // Find a bounding box of a topmost printable volume referenced by this modifier given this_region_id.
const PrintObjectRegions::BoundingBox* find_modifier_volume_extents(const PrintObjectRegions::LayerRangeRegions &layer_range, const int this_region_id) PrintObjectRegions::BoundingBox find_modifier_volume_extents(const PrintObjectRegions::LayerRangeRegions &layer_range, const int this_region_id)
{ {
// Find the top-most printable volume of this modifier, or the printable volume itself. // Find the top-most printable volume of this modifier, or the printable volume itself.
int parent_region_id = this_region_id; const PrintObjectRegions::VolumeRegion &this_region = layer_range.volume_regions[this_region_id];
for (; ! layer_range.volume_regions[parent_region_id].model_volume->is_model_part(); parent_region_id = layer_range.volume_regions[parent_region_id].parent) const PrintObjectRegions::BoundingBox *this_extents = find_volume_extents(layer_range, *this_region.model_volume);
assert(parent_region_id >= 0); assert(this_extents);
return find_volume_extents(layer_range, *layer_range.volume_regions[parent_region_id].model_volume); PrintObjectRegions::BoundingBox out { *this_extents };
if (! this_region.model_volume->is_model_part())
for (int parent_region_id = this_region.parent;;) {
assert(parent_region_id >= 0);
const PrintObjectRegions::VolumeRegion &parent_region = layer_range.volume_regions[parent_region_id];
const PrintObjectRegions::BoundingBox *parent_extents = find_volume_extents(layer_range, *parent_region.model_volume);
assert(parent_extents);
out.extend(*parent_extents);
if (parent_region.model_volume->is_model_part())
break;
parent_region_id = parent_region.parent;
}
return out;
} }
PrintRegionConfig region_config_from_model_volume(const PrintRegionConfig &default_or_parent_region_config, const DynamicPrintConfig *layer_range_config, const ModelVolume &volume, size_t num_extruders); PrintRegionConfig region_config_from_model_volume(const PrintRegionConfig &default_or_parent_region_config, const DynamicPrintConfig *layer_range_config, const ModelVolume &volume, size_t num_extruders);
@ -679,17 +691,13 @@ bool verify_update_print_object_regions(
layer_range.volume_regions[next_region_id].parent == parent_region_id) { layer_range.volume_regions[next_region_id].parent == parent_region_id) {
// A parent region is already overridden. // A parent region is already overridden.
++ next_region_id; ++ next_region_id;
} else { } else if (PrintObjectRegions::BoundingBox parent_bbox = find_modifier_volume_extents(layer_range, parent_region_id); parent_bbox.intersects(*bbox))
// Such parent region does not exist. If it is needed, then we need to reslice. // Such parent region does not exist. If it is needed, then we need to reslice.
const PrintObjectRegions::BoundingBox *parent_bbox = find_modifier_volume_extents(layer_range, parent_region_id); // Only create new region for a modifier, which actually modifies config of it's parent.
assert(parent_bbox != nullptr); if (PrintRegionConfig config = region_config_from_model_volume(parent_region.region->config(), nullptr, **it_model_volume, num_extruders);
if (parent_bbox->intersects(*bbox)) config != parent_region.region->config())
// Only create new region for a modifier, which actually modifies config of it's parent. // This modifier newly overrides a region, which it did not before. We need to reslice.
if (PrintRegionConfig config = region_config_from_model_volume(parent_region.region->config(), nullptr, **it_model_volume, num_extruders); return false;
config != parent_region.region->config())
// This modifier newly overrides a region, which it did not before. We need to reslice.
return false;
}
} }
} }
} }
@ -911,10 +919,8 @@ static PrintObjectRegions* generate_print_object_regions(
for (int parent_region_id = int(layer_range.volume_regions.size()) - 1; parent_region_id >= 0; -- parent_region_id) { for (int parent_region_id = int(layer_range.volume_regions.size()) - 1; parent_region_id >= 0; -- parent_region_id) {
const PrintObjectRegions::VolumeRegion &parent_region = layer_range.volume_regions[parent_region_id]; const PrintObjectRegions::VolumeRegion &parent_region = layer_range.volume_regions[parent_region_id];
const ModelVolume &parent_volume = *parent_region.model_volume; const ModelVolume &parent_volume = *parent_region.model_volume;
if (parent_volume.is_model_part() || parent_volume.is_modifier()) { if (parent_volume.is_model_part() || parent_volume.is_modifier())
const PrintObjectRegions::BoundingBox *parent_bbox = find_modifier_volume_extents(layer_range, parent_region_id); if (PrintObjectRegions::BoundingBox parent_bbox = find_modifier_volume_extents(layer_range, parent_region_id); parent_bbox.intersects(*bbox))
assert(parent_bbox != nullptr);
if (parent_bbox->intersects(*bbox))
// Only create new region for a modifier, which actually modifies config of it's parent. // Only create new region for a modifier, which actually modifies config of it's parent.
if (PrintRegionConfig config = region_config_from_model_volume(parent_region.region->config(), nullptr, volume, num_extruders); if (PrintRegionConfig config = region_config_from_model_volume(parent_region.region->config(), nullptr, volume, num_extruders);
config != parent_region.region->config()) { config != parent_region.region->config()) {
@ -922,7 +928,6 @@ static PrintObjectRegions* generate_print_object_regions(
layer_range.volume_regions.push_back({ &volume, parent_region_id, get_create_region(std::move(config)), bbox }); layer_range.volume_regions.push_back({ &volume, parent_region_id, get_create_region(std::move(config)), bbox });
} else if (parent_model_part_id == -1 && parent_volume.is_model_part()) } else if (parent_model_part_id == -1 && parent_volume.is_model_part())
parent_model_part_id = parent_region_id; parent_model_part_id = parent_region_id;
}
} }
if (! added && parent_model_part_id >= 0) if (! added && parent_model_part_id >= 0)
// This modifier does not override any printable volume's configuration, however it may in the future. // This modifier does not override any printable volume's configuration, however it may in the future.

View File

@ -2688,7 +2688,7 @@ void PrintConfigDef::init_fff_params()
def->enum_labels.push_back(L("Rectilinear")); def->enum_labels.push_back(L("Rectilinear"));
def->enum_labels.push_back(L("Concentric")); def->enum_labels.push_back(L("Concentric"));
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionEnum<SupportMaterialPattern>(smpRectilinear)); def->set_default_value(new ConfigOptionEnum<SupportMaterialInterfacePattern>(smipRectilinear));
def = this->add("support_material_spacing", coFloat); def = this->add("support_material_spacing", coFloat);
def->label = L("Pattern spacing"); def->label = L("Pattern spacing");

View File

@ -1866,9 +1866,13 @@ std::vector<ExPolygons> slice_mesh_ex(
//FIXME simplify //FIXME simplify
if (this_mode == MeshSlicingParams::SlicingMode::PositiveLargestContour) if (this_mode == MeshSlicingParams::SlicingMode::PositiveLargestContour)
keep_largest_contour_only(expolygons); keep_largest_contour_only(expolygons);
if (resolution != 0.) if (resolution != 0.) {
for (ExPolygon &ex : expolygons) ExPolygons simplified;
ex.simplify(resolution); simplified.reserve(expolygons.size());
for (const ExPolygon &ex : expolygons)
append(simplified, ex.simplify(resolution));
expolygons = std::move(simplified);
}
} }
}); });
// BOOST_LOG_TRIVIAL(debug) << "slice_mesh make_expolygons in parallel - end"; // BOOST_LOG_TRIVIAL(debug) << "slice_mesh make_expolygons in parallel - end";

View File

@ -162,8 +162,8 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
if (config->opt_bool("support_material")) { if (config->opt_bool("support_material")) {
// Ask only once. // Ask only once.
if (!support_material_overhangs_queried) { if (!m_support_material_overhangs_queried) {
support_material_overhangs_queried = true; m_support_material_overhangs_queried = true;
if (!config->opt_bool("overhangs")/* != 1*/) { if (!config->opt_bool("overhangs")/* != 1*/) {
wxString msg_text = _(L("Supports work better, if the following feature is enabled:\n" wxString msg_text = _(L("Supports work better, if the following feature is enabled:\n"
"- Detect bridging perimeters")); "- Detect bridging perimeters"));
@ -182,7 +182,7 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
} }
} }
else { else {
support_material_overhangs_queried = false; m_support_material_overhangs_queried = false;
} }
if (config->option<ConfigOptionPercent>("fill_density")->value == 100) { if (config->option<ConfigOptionPercent>("fill_density")->value == 100) {

View File

@ -17,15 +17,12 @@ class ModelConfig;
namespace GUI { namespace GUI {
// This variable have to be static because of use its value from Preset configuration
// and from object/parts configuration from the Settings in sidebar
static bool support_material_overhangs_queried {false};
class ConfigManipulation class ConfigManipulation
{ {
bool is_msg_dlg_already_exist{ false }; bool is_msg_dlg_already_exist{ false };
bool m_is_initialized_support_material_overhangs_queried{ false }; bool m_is_initialized_support_material_overhangs_queried{ false };
bool m_support_material_overhangs_queried{ false };
// function to loading of changed configuration // function to loading of changed configuration
std::function<void()> load_config = nullptr; std::function<void()> load_config = nullptr;
@ -66,7 +63,7 @@ public:
void initialize_support_material_overhangs_queried(bool queried) void initialize_support_material_overhangs_queried(bool queried)
{ {
m_is_initialized_support_material_overhangs_queried = true; m_is_initialized_support_material_overhangs_queried = true;
support_material_overhangs_queried = queried; m_support_material_overhangs_queried = queried;
} }
}; };

View File

@ -26,6 +26,7 @@
#include <cmath> #include <cmath>
#include <boost/algorithm/string/replace.hpp> #include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/split.hpp>
#include <random> #include <random>
#include "Field.hpp" #include "Field.hpp"
#include "format.hpp" #include "format.hpp"
@ -1446,6 +1447,18 @@ wxString Control::get_tooltip(int tick/*=-1*/)
std::string space = " "; std::string space = " ";
tooltip = space; tooltip = space;
auto format_gcode = [space](std::string gcode) { auto format_gcode = [space](std::string gcode) {
// when the tooltip is too long, it starts to flicker, see: https://github.com/prusa3d/PrusaSlicer/issues/7368
// so we limit the number of lines shown
std::vector<std::string> lines;
boost::split(lines, gcode, boost::is_any_of("\n"), boost::token_compress_off);
static const size_t MAX_LINES = 10;
if (lines.size() > MAX_LINES) {
gcode = lines.front() + '\n';
for (size_t i = 1; i < MAX_LINES; ++i) {
gcode += lines[i] + '\n';
}
gcode += "[" + into_u8(_L("continue")) + "]\n";
}
boost::replace_all(gcode, "\n", "\n" + space); boost::replace_all(gcode, "\n", "\n" + space);
return gcode; return gcode;
}; };

View File

@ -95,6 +95,11 @@ RetinaHelper::~RetinaHelper() {}
float RetinaHelper::get_scale_factor() { return float(m_window->GetContentScaleFactor()); } float RetinaHelper::get_scale_factor() { return float(m_window->GetContentScaleFactor()); }
#endif // __WXGTK3__ #endif // __WXGTK3__
// Fixed the collision between BuildVolume::Type::Convex and macro Convex defined inside /usr/include/X11/X.h that is included by WxWidgets 3.0.
#if defined(__linux__) && defined(Convex)
#undef Convex
#endif
Size::Size() Size::Size()
: m_width(0) : m_width(0)
, m_height(0) , m_height(0)

View File

@ -109,7 +109,7 @@ void GLGizmoSimplify::add_simplify_suggestion_notification(
if (big_ids.empty()) return; if (big_ids.empty()) return;
for (size_t object_id : big_ids) { for (size_t object_id : big_ids) {
std::string t = GUI::format(_u8L( std::string t = GUI::format(_L(
"Processing model '%1%' with more than 1M triangles " "Processing model '%1%' with more than 1M triangles "
"could be slow. It is highly recommend to reduce " "could be slow. It is highly recommend to reduce "
"amount of triangles."), objects[object_id]->name); "amount of triangles."), objects[object_id]->name);

View File

@ -96,7 +96,7 @@ PrintHostSendDialog::PrintHostSendDialog(const fs::path &path, bool can_start_pr
} }
add_button(wxID_CANCEL); add_button(wxID_CANCEL);
if (auto* btn_ok = get_button(wxID_NO); btn_ok != NULL) { if (auto* btn_ok = get_button(wxID_OK); btn_ok != NULL) {
btn_ok->SetLabel(_L("Upload")); btn_ok->SetLabel(_L("Upload"));
btn_ok->Bind(wxEVT_BUTTON, [this, suffix](wxCommandEvent&) { btn_ok->Bind(wxEVT_BUTTON, [this, suffix](wxCommandEvent&) {
wxString path = txt_filename->GetValue(); wxString path = txt_filename->GetValue();

View File

@ -127,6 +127,7 @@ struct Http::priv
Http::CompleteFn completefn; Http::CompleteFn completefn;
Http::ErrorFn errorfn; Http::ErrorFn errorfn;
Http::ProgressFn progressfn; Http::ProgressFn progressfn;
Http::IPResolveFn ipresolvefn;
priv(const std::string &url); priv(const std::string &url);
~priv(); ~priv();
@ -390,6 +391,13 @@ void Http::priv::http_perform()
if (errorfn) { errorfn(std::move(buffer), std::string(), http_status); } if (errorfn) { errorfn(std::move(buffer), std::string(), http_status); }
} else { } else {
if (completefn) { completefn(std::move(buffer), http_status); } if (completefn) { completefn(std::move(buffer), http_status); }
if (ipresolvefn) {
char* ct;
res = curl_easy_getinfo(curl, CURLINFO_PRIMARY_IP, &ct);
if ((CURLE_OK == res) && ct) {
ipresolvefn(ct);
}
}
} }
} }
} }
@ -554,6 +562,12 @@ Http& Http::on_progress(ProgressFn fn)
return *this; return *this;
} }
Http& Http::on_ip_resolve(IPResolveFn fn)
{
if (p) { p->ipresolvefn = std::move(fn); }
return *this;
}
Http::Ptr Http::perform() Http::Ptr Http::perform()
{ {
auto self = std::make_shared<Http>(std::move(*this)); auto self = std::make_shared<Http>(std::move(*this));

View File

@ -41,6 +41,8 @@ public:
// Writing true to the `cancel` reference cancels the request in progress. // Writing true to the `cancel` reference cancels the request in progress.
typedef std::function<void(Progress, bool& /* cancel */)> ProgressFn; typedef std::function<void(Progress, bool& /* cancel */)> ProgressFn;
typedef std::function<void(std::string/* address */)> IPResolveFn;
Http(Http &&other); Http(Http &&other);
// Note: strings are expected to be UTF-8-encoded // Note: strings are expected to be UTF-8-encoded
@ -113,6 +115,9 @@ public:
// See the `Progress` structure for description of the data passed. // See the `Progress` structure for description of the data passed.
// Writing a true-ish value into the cancel reference parameter cancels the request. // Writing a true-ish value into the cancel reference parameter cancels the request.
Http& on_progress(ProgressFn fn); Http& on_progress(ProgressFn fn);
// Callback called after succesful HTTP request (after on_complete callback)
// Called if curl_easy_getinfo resolved just used IP address.
Http& on_ip_resolve(IPResolveFn fn);
// Starts performing the request in a background thread // Starts performing the request in a background thread
Ptr perform(); Ptr perform();

View File

@ -76,6 +76,9 @@ bool OctoPrint::test(wxString &msg) const
}) })
#ifdef WIN32 #ifdef WIN32
.ssl_revoke_best_effort(m_ssl_revoke_best_effort) .ssl_revoke_best_effort(m_ssl_revoke_best_effort)
.on_ip_resolve([&](std::string address) {
msg = boost::nowide::widen(address);
})
#endif #endif
.perform_sync(); .perform_sync();
@ -108,9 +111,25 @@ bool OctoPrint::upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, Erro
return false; return false;
} }
std::string url;
bool res = true; bool res = true;
auto url = make_url("api/files/local"); if (m_host.find("https://") == 0 || test_msg.empty())
{
// If https is entered we assume signed ceritificate is being used
// IP resolving will not happen - it could resolve into address not being specified in cert
url = make_url("api/files/local");
} else {
// Curl uses easy_getinfo to get ip address of last successful transaction.
// If it got the address use it instead of the stored in "host" variable.
// This new address returns in "test_msg" variable.
// Solves troubles of uploades failing with name address.
std::string resolved_addr = boost::nowide::narrow(test_msg);
// put ipv6 into [] brackets (there shouldn't be any http:// if its resolved addr)
if (resolved_addr.find(':') != std::string::npos && resolved_addr.at(0) != '[')
resolved_addr = "[" + resolved_addr + "]";
url = make_url("api/files/local", resolved_addr);
}
BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Uploading file %2% at %3%, filename: %4%, path: %5%, print: %6%") BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Uploading file %2% at %3%, filename: %4%, path: %5%, print: %6%")
% name % name
@ -176,6 +195,21 @@ std::string OctoPrint::make_url(const std::string &path) const
} }
} }
std::string OctoPrint::make_url(const std::string& path, const std::string& addr) const
{
std::string hst = addr.empty() ? m_host : addr;
if (hst.find("http://") == 0 || hst.find("https://") == 0) {
if (hst.back() == '/') {
return (boost::format("%1%%2%") % hst % path).str();
}
else {
return (boost::format("%1%/%2%") % hst % path).str();
}
} else {
return (boost::format("http://%1%/%2%") % hst % path).str();
}
}
SL1Host::SL1Host(DynamicPrintConfig *config) : SL1Host::SL1Host(DynamicPrintConfig *config) :
OctoPrint(config), OctoPrint(config),
m_authorization_type(dynamic_cast<const ConfigOptionEnum<AuthorizationType>*>(config->option("printhost_authorization_type"))->value), m_authorization_type(dynamic_cast<const ConfigOptionEnum<AuthorizationType>*>(config->option("printhost_authorization_type"))->value),

View File

@ -44,6 +44,7 @@ private:
virtual void set_auth(Http &http) const; virtual void set_auth(Http &http) const;
std::string make_url(const std::string &path) const; std::string make_url(const std::string &path) const;
std::string make_url(const std::string& path, const std::string& addr) const;
}; };
class SL1Host: public OctoPrint class SL1Host: public OctoPrint

View File

@ -3,7 +3,7 @@
set(SLIC3R_APP_NAME "PrusaSlicer") set(SLIC3R_APP_NAME "PrusaSlicer")
set(SLIC3R_APP_KEY "PrusaSlicer") set(SLIC3R_APP_KEY "PrusaSlicer")
set(SLIC3R_VERSION "2.4.0-beta1") set(SLIC3R_VERSION "2.4.0-beta2")
set(SLIC3R_BUILD_ID "PrusaSlicer-${SLIC3R_VERSION}+UNKNOWN") set(SLIC3R_BUILD_ID "PrusaSlicer-${SLIC3R_VERSION}+UNKNOWN")
set(SLIC3R_RC_VERSION "2,4,0,0") set(SLIC3R_RC_VERSION "2,4,0,0")
set(SLIC3R_RC_VERSION_DOTS "2.4.0.0") set(SLIC3R_RC_VERSION_DOTS "2.4.0.0")