mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-19 22:39:07 +08:00
Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer into et_texture_support
This commit is contained in:
commit
39368570b3
@ -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.
|
||||
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-beta0 Added multiple Filatech and BASF filament profiles. Added material profiles for SL1S.
|
||||
min_slic3r_version = 2.4.0-alpha0
|
||||
|
@ -1544,30 +1544,37 @@ void GCode::process_layers(
|
||||
const size_t single_object_idx,
|
||||
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;
|
||||
tbb::parallel_pipeline(12,
|
||||
tbb::make_filter<void, GCode::LayerResult>(
|
||||
tbb::filter::serial_in_order,
|
||||
[this, &print, &tool_ordering, &layers_to_print, &layer_to_print_idx, single_object_idx](tbb::flow_control& fc) -> GCode::LayerResult {
|
||||
if (layer_to_print_idx == layers_to_print.size()) {
|
||||
fc.stop();
|
||||
return {};
|
||||
} else {
|
||||
LayerToPrint &layer = layers_to_print[layer_to_print_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);
|
||||
}
|
||||
}) &
|
||||
tbb::make_filter<GCode::LayerResult, std::string>(
|
||||
tbb::filter::serial_in_order,
|
||||
[&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);
|
||||
}) &
|
||||
tbb::make_filter<std::string, void>(
|
||||
tbb::filter::serial_in_order,
|
||||
[&output_stream](std::string s) { output_stream.write(s); }
|
||||
));
|
||||
const auto generator = tbb::make_filter<void, GCode::LayerResult>(tbb::filter::serial_in_order,
|
||||
[this, &print, &tool_ordering, &layers_to_print, &layer_to_print_idx, single_object_idx](tbb::flow_control& fc) -> GCode::LayerResult {
|
||||
if (layer_to_print_idx == layers_to_print.size()) {
|
||||
fc.stop();
|
||||
return {};
|
||||
} else {
|
||||
LayerToPrint &layer = layers_to_print[layer_to_print_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 {
|
||||
spiral_vase.enable(in.spiral_vase_enable);
|
||||
return { spiral_vase.process_layer(std::move(in.gcode)), in.layer_id, in.spiral_vase_enable, 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 {
|
||||
return cooling_buffer.process_layer(std::move(in.gcode), in.layer_id, in.cooling_buffer_flush);
|
||||
});
|
||||
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)
|
||||
|
@ -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.
|
||||
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.
|
||||
int parent_region_id = 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)
|
||||
assert(parent_region_id >= 0);
|
||||
return find_volume_extents(layer_range, *layer_range.volume_regions[parent_region_id].model_volume);
|
||||
const PrintObjectRegions::VolumeRegion &this_region = layer_range.volume_regions[this_region_id];
|
||||
const PrintObjectRegions::BoundingBox *this_extents = find_volume_extents(layer_range, *this_region.model_volume);
|
||||
assert(this_extents);
|
||||
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);
|
||||
@ -679,17 +691,13 @@ bool verify_update_print_object_regions(
|
||||
layer_range.volume_regions[next_region_id].parent == parent_region_id) {
|
||||
// A parent region is already overridden.
|
||||
++ 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.
|
||||
const PrintObjectRegions::BoundingBox *parent_bbox = find_modifier_volume_extents(layer_range, parent_region_id);
|
||||
assert(parent_bbox != nullptr);
|
||||
if (parent_bbox->intersects(*bbox))
|
||||
// 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, **it_model_volume, num_extruders);
|
||||
config != parent_region.region->config())
|
||||
// This modifier newly overrides a region, which it did not before. We need to reslice.
|
||||
return false;
|
||||
}
|
||||
// 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, **it_model_volume, num_extruders);
|
||||
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) {
|
||||
const PrintObjectRegions::VolumeRegion &parent_region = layer_range.volume_regions[parent_region_id];
|
||||
const ModelVolume &parent_volume = *parent_region.model_volume;
|
||||
if (parent_volume.is_model_part() || parent_volume.is_modifier()) {
|
||||
const PrintObjectRegions::BoundingBox *parent_bbox = find_modifier_volume_extents(layer_range, parent_region_id);
|
||||
assert(parent_bbox != nullptr);
|
||||
if (parent_bbox->intersects(*bbox))
|
||||
if (parent_volume.is_model_part() || parent_volume.is_modifier())
|
||||
if (PrintObjectRegions::BoundingBox parent_bbox = find_modifier_volume_extents(layer_range, parent_region_id); parent_bbox.intersects(*bbox))
|
||||
// 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);
|
||||
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 });
|
||||
} else if (parent_model_part_id == -1 && parent_volume.is_model_part())
|
||||
parent_model_part_id = parent_region_id;
|
||||
}
|
||||
}
|
||||
if (! added && parent_model_part_id >= 0)
|
||||
// This modifier does not override any printable volume's configuration, however it may in the future.
|
||||
|
@ -2688,7 +2688,7 @@ void PrintConfigDef::init_fff_params()
|
||||
def->enum_labels.push_back(L("Rectilinear"));
|
||||
def->enum_labels.push_back(L("Concentric"));
|
||||
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->label = L("Pattern spacing");
|
||||
|
@ -1866,9 +1866,13 @@ std::vector<ExPolygons> slice_mesh_ex(
|
||||
//FIXME simplify
|
||||
if (this_mode == MeshSlicingParams::SlicingMode::PositiveLargestContour)
|
||||
keep_largest_contour_only(expolygons);
|
||||
if (resolution != 0.)
|
||||
for (ExPolygon &ex : expolygons)
|
||||
ex.simplify(resolution);
|
||||
if (resolution != 0.) {
|
||||
ExPolygons simplified;
|
||||
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";
|
||||
|
@ -162,8 +162,8 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
|
||||
|
||||
if (config->opt_bool("support_material")) {
|
||||
// Ask only once.
|
||||
if (!support_material_overhangs_queried) {
|
||||
support_material_overhangs_queried = true;
|
||||
if (!m_support_material_overhangs_queried) {
|
||||
m_support_material_overhangs_queried = true;
|
||||
if (!config->opt_bool("overhangs")/* != 1*/) {
|
||||
wxString msg_text = _(L("Supports work better, if the following feature is enabled:\n"
|
||||
"- Detect bridging perimeters"));
|
||||
@ -182,7 +182,7 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
|
||||
}
|
||||
}
|
||||
else {
|
||||
support_material_overhangs_queried = false;
|
||||
m_support_material_overhangs_queried = false;
|
||||
}
|
||||
|
||||
if (config->option<ConfigOptionPercent>("fill_density")->value == 100) {
|
||||
|
@ -17,15 +17,12 @@ class ModelConfig;
|
||||
|
||||
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
|
||||
{
|
||||
bool is_msg_dlg_already_exist{ false };
|
||||
|
||||
bool m_is_initialized_support_material_overhangs_queried{ false };
|
||||
bool m_support_material_overhangs_queried{ false };
|
||||
|
||||
// function to loading of changed configuration
|
||||
std::function<void()> load_config = nullptr;
|
||||
@ -66,7 +63,7 @@ public:
|
||||
void initialize_support_material_overhangs_queried(bool queried)
|
||||
{
|
||||
m_is_initialized_support_material_overhangs_queried = true;
|
||||
support_material_overhangs_queried = queried;
|
||||
m_support_material_overhangs_queried = queried;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
#include <cmath>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <random>
|
||||
#include "Field.hpp"
|
||||
#include "format.hpp"
|
||||
@ -1446,6 +1447,18 @@ wxString Control::get_tooltip(int tick/*=-1*/)
|
||||
std::string space = " ";
|
||||
tooltip = space;
|
||||
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);
|
||||
return gcode;
|
||||
};
|
||||
|
@ -95,6 +95,11 @@ RetinaHelper::~RetinaHelper() {}
|
||||
float RetinaHelper::get_scale_factor() { return float(m_window->GetContentScaleFactor()); }
|
||||
#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()
|
||||
: m_width(0)
|
||||
, m_height(0)
|
||||
|
@ -109,7 +109,7 @@ void GLGizmoSimplify::add_simplify_suggestion_notification(
|
||||
if (big_ids.empty()) return;
|
||||
|
||||
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 "
|
||||
"could be slow. It is highly recommend to reduce "
|
||||
"amount of triangles."), objects[object_id]->name);
|
||||
|
@ -96,7 +96,7 @@ PrintHostSendDialog::PrintHostSendDialog(const fs::path &path, bool can_start_pr
|
||||
}
|
||||
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->Bind(wxEVT_BUTTON, [this, suffix](wxCommandEvent&) {
|
||||
wxString path = txt_filename->GetValue();
|
||||
|
@ -127,6 +127,7 @@ struct Http::priv
|
||||
Http::CompleteFn completefn;
|
||||
Http::ErrorFn errorfn;
|
||||
Http::ProgressFn progressfn;
|
||||
Http::IPResolveFn ipresolvefn;
|
||||
|
||||
priv(const std::string &url);
|
||||
~priv();
|
||||
@ -390,6 +391,13 @@ void Http::priv::http_perform()
|
||||
if (errorfn) { errorfn(std::move(buffer), std::string(), http_status); }
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
|
||||
Http& Http::on_ip_resolve(IPResolveFn fn)
|
||||
{
|
||||
if (p) { p->ipresolvefn = std::move(fn); }
|
||||
return *this;
|
||||
}
|
||||
|
||||
Http::Ptr Http::perform()
|
||||
{
|
||||
auto self = std::make_shared<Http>(std::move(*this));
|
||||
|
@ -41,6 +41,8 @@ public:
|
||||
// Writing true to the `cancel` reference cancels the request in progress.
|
||||
typedef std::function<void(Progress, bool& /* cancel */)> ProgressFn;
|
||||
|
||||
typedef std::function<void(std::string/* address */)> IPResolveFn;
|
||||
|
||||
Http(Http &&other);
|
||||
|
||||
// Note: strings are expected to be UTF-8-encoded
|
||||
@ -113,6 +115,9 @@ public:
|
||||
// See the `Progress` structure for description of the data passed.
|
||||
// Writing a true-ish value into the cancel reference parameter cancels the request.
|
||||
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
|
||||
Ptr perform();
|
||||
|
@ -76,6 +76,9 @@ bool OctoPrint::test(wxString &msg) const
|
||||
})
|
||||
#ifdef WIN32
|
||||
.ssl_revoke_best_effort(m_ssl_revoke_best_effort)
|
||||
.on_ip_resolve([&](std::string address) {
|
||||
msg = boost::nowide::widen(address);
|
||||
})
|
||||
#endif
|
||||
.perform_sync();
|
||||
|
||||
@ -108,9 +111,25 @@ bool OctoPrint::upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, Erro
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string url;
|
||||
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%")
|
||||
% 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) :
|
||||
OctoPrint(config),
|
||||
m_authorization_type(dynamic_cast<const ConfigOptionEnum<AuthorizationType>*>(config->option("printhost_authorization_type"))->value),
|
||||
|
@ -44,6 +44,7 @@ private:
|
||||
|
||||
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& addr) const;
|
||||
};
|
||||
|
||||
class SL1Host: public OctoPrint
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
set(SLIC3R_APP_NAME "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_RC_VERSION "2,4,0,0")
|
||||
set(SLIC3R_RC_VERSION_DOTS "2.4.0.0")
|
||||
|
Loading…
x
Reference in New Issue
Block a user