Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/supermerill/SuperSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--resources/ui_layout/print.ui43
-rw-r--r--resources/ui_layout/sla_material.ui6
-rw-r--r--src/libslic3r/Config.hpp5
-rw-r--r--src/libslic3r/Flow.cpp2
-rw-r--r--src/libslic3r/GCode.cpp3
-rw-r--r--src/libslic3r/PerimeterGenerator.cpp103
-rw-r--r--src/libslic3r/PerimeterGenerator.hpp8
-rw-r--r--src/libslic3r/Preset.cpp12
-rw-r--r--src/libslic3r/Print.cpp1
-rw-r--r--src/libslic3r/PrintConfig.cpp34
-rw-r--r--src/libslic3r/PrintConfig.hpp4
-rw-r--r--src/libslic3r/PrintObject.cpp1
-rw-r--r--src/libslic3r/Thread.cpp4
-rw-r--r--src/slic3r/GUI/ConfigManipulation.cpp3
-rw-r--r--src/slic3r/GUI/Field.cpp117
-rw-r--r--src/slic3r/GUI/Field.hpp4
-rw-r--r--src/slic3r/GUI/GUI.cpp5
-rw-r--r--src/slic3r/GUI/NotificationManager.cpp2
-rw-r--r--src/slic3r/GUI/OG_CustomCtrl.cpp98
-rw-r--r--src/slic3r/GUI/OG_CustomCtrl.hpp4
-rw-r--r--src/slic3r/GUI/OptionsGroup.cpp16
-rw-r--r--src/slic3r/GUI/Tab.cpp1
22 files changed, 275 insertions, 201 deletions
diff --git a/resources/ui_layout/print.ui b/resources/ui_layout/print.ui
index 5e4a4b83a..00ff40a7d 100644
--- a/resources/ui_layout/print.ui
+++ b/resources/ui_layout/print.ui
@@ -54,7 +54,7 @@ group:label_width$12:Overhangs
group:Advanced
setting:width$25:no_perimeter_unsupported_algo
line:Gap Fill
- setting:label$_:gap_fill_enable
+ setting:label$_:gap_fill_enabled
setting:width$5:gap_fill_min_area
setting:width$5:gap_fill_last
end_line
@@ -68,6 +68,11 @@ group:Advanced
setting:label_width$5:label$Seam:perimeter_loop_seam
end_line
setting:perimeter_round_corners
+ line:Fuzzy skin (experimental)
+ setting:sidetext_width$1:label$_:fuzzy_skin
+ setting:width$6:sidetext_width$6:fuzzy_skin_thickness
+ setting:width$6:sidetext_width$5:fuzzy_skin_point_dist
+ end_line
group:External perimeter first
setting:label$Activate:external_perimeters_first
line:Apply on
@@ -76,10 +81,6 @@ group:External perimeter first
end_line
setting:external_perimeters_vase
setting:perimeter_bonding
-group:Fuzzy skin (experimental)
- settingfuzzy_skin
- settingfuzzy_skin_thickness
- settingfuzzy_skin_point_dist
page:Slicing:layers
group:Layer height
@@ -149,7 +150,7 @@ group:Reducing printing time
setting:sidetext_width$0:label$_:infill_dense
setting:width$20:infill_dense_algo
end_line
-group:sidetext_width$3:Advanced
+group:sidetext_width$5:Advanced
setting:solid_infill_every_layers
setting:solid_infill_below_area
line:Angle
@@ -187,7 +188,7 @@ group:Skirt
setting:label$from brim:skirt_distance_from_brim
end_line
setting:skirt_height
- setting:draft_shield
+ setting:width$8::draft_shield
setting:skirt_brim
setting:min_skirt_length
group:Brim
@@ -195,9 +196,9 @@ group:Brim
setting:brim_inside_holes
setting:brim_width_interior
line:Brim ears
- setting:label$_:brim_ears
- setting:width$3:brim_ears_max_angle
- setting:width$3:brim_ears_detection_length
+ setting:label$_:sidetext_width$0:brim_ears
+ setting:width$3:sidetext_width$1:brim_ears_max_angle
+ setting:width$3:sidetext_width$3:brim_ears_detection_length
setting:brim_ears_pattern
end_line
setting:brim_separation
@@ -223,7 +224,7 @@ group:Raft
group:Options for support material and raft
setting:support_material_style
line:Z-offset
- setting:width$11:support_material_contact_distance_type
+ setting:width$13:support_material_contact_distance_type
setting:width$6:support_material_contact_distance
setting:width$6:support_material_bottom_contact_distance
end_line
@@ -277,8 +278,8 @@ group:sidetext_width$7:Modifiers
setting:label_width$8:width$4:first_layer_min_speed
setting:label_width$8:width$4:first_layer_speed
setting:label_width$8:width$4:first_layer_infill_speed
+ setting:label_width$8:width$4:label$Over raft:first_layer_speed_over_raft
end_line
- setting:first_layer_speed_over_raft
line:Small perimeter speed
setting:label_width$8:width$4:small_perimeter_min_length
setting:label_width$8:width$4:small_perimeter_max_length
@@ -313,7 +314,7 @@ group:label_width$9:sidetext_width$8:Acceleration control (advanced)
setting:width$4:travel_deceleration_use_target
line:First layer acceleration
setting:width$4:first_layer_acceleration
- setting:width$4:first_layer_acceleration_over_raft
+ setting:label_width$35:width$4:first_layer_acceleration_over_raft
end_line
page:Width & Flow:width
@@ -355,17 +356,17 @@ group:Extrusion width
recommended_extrusion_width_description
group:Overlap
line:Perimeter overlap
- setting:label$Default:perimeter_overlap
- setting:label$External:external_perimeter_overlap
- setting:label$Gap Fill:gap_fill_overlap
+ setting:label_width$7:label$Default:perimeter_overlap
+ setting:label_width$7:label$External:external_perimeter_overlap
+ setting:label_width$7:label$Gap Fill:gap_fill_overlap
end_line
- setting:solid_infill_overlap
+ setting:width$4:solid_infill_overlap
line:Bridge lines density
- setting:bridge_overlap_min
- setting:bridge_overlap
+ setting:label_width$7:bridge_overlap_min
+ setting:label_width$7:bridge_overlap
end_line
- setting:sidetext_width$7:infill_overlap
-group:Flow
+ setting:width$4:sidetext_width$7:infill_overlap
+group:sidetext_width$2:Flow
line:Flow ratio
setting:bridge_flow_ratio
setting:over_bridge_flow_ratio
diff --git a/resources/ui_layout/sla_material.ui b/resources/ui_layout/sla_material.ui
index 81f7862db..bcf720ad7 100644
--- a/resources/ui_layout/sla_material.ui
+++ b/resources/ui_layout/sla_material.ui
@@ -16,9 +16,9 @@ group:Exposure
group:label_width$19:Corrections
line:material_correction
- setting:label$X:width$6:material_correction_X
- setting:label$Y:width$6:material_correction_Y
- setting:label$Z:width$6:material_correction_Z
+ setting:label$X:width$6:material_correction_x
+ setting:label$Y:width$6:material_correction_y
+ setting:label$Z:width$6:material_correction_z
end_line
page:Notes:note
diff --git a/src/libslic3r/Config.hpp b/src/libslic3r/Config.hpp
index 9709a3f6f..423bd93c5 100644
--- a/src/libslic3r/Config.hpp
+++ b/src/libslic3r/Config.hpp
@@ -16,6 +16,7 @@
#include "Exception.hpp"
#include "Point.hpp"
+#include <boost/any.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/format/format_fwd.hpp>
@@ -364,7 +365,7 @@ public:
virtual ConfigOption* clone() const = 0;
// Set a value from a ConfigOption. The two options should be compatible.
virtual void set(const ConfigOption *option) = 0;
- virtual int32_t getInt() const { throw BadOptionTypeException("Calling ConfigOption::getInt on a non-int ConfigOption"); }
+ virtual int32_t getInt() const { throw BadOptionTypeException("Calling ConfigOption::getInt on a non-int ConfigOption"); }
virtual double getFloat() const { throw BadOptionTypeException("Calling ConfigOption::getFloat on a non-float ConfigOption"); }
virtual bool getBool() const { throw BadOptionTypeException("Calling ConfigOption::getBool on a non-boolean ConfigOption"); }
virtual void setInt(int32_t /* val */) { throw BadOptionTypeException("Calling ConfigOption::setInt on a non-int ConfigOption"); }
@@ -1646,7 +1647,7 @@ public:
ConfigOptionEnum<T>& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
bool operator==(const ConfigOptionEnum<T> &rhs) const throw() { return this->value == rhs.value; }
bool operator< (const ConfigOptionEnum<T> &rhs) const throw() { return int(this->value) < int(rhs.value); }
- int32_t getInt() const override { return (int32_t)this->value; }
+ int32_t getInt() const override { return (int32_t)this->value; }
void setInt(int val) override { this->value = T(val); }
bool operator==(const ConfigOption &rhs) const override
diff --git a/src/libslic3r/Flow.cpp b/src/libslic3r/Flow.cpp
index fed2f7667..eb835f4ff 100644
--- a/src/libslic3r/Flow.cpp
+++ b/src/libslic3r/Flow.cpp
@@ -217,7 +217,7 @@ Flow Flow::new_from_config_width(FlowRole role, const ConfigOptionFloatOrPercent
w = auto_extrusion_width(role, nozzle_diameter);
} else {
// If user set a manual value, use it.
- w = float(width.get_abs_value(height));
+ w = float(width.get_abs_value(nozzle_diameter));
}
return Flow(w, height, rounded_rectangle_extrusion_spacing(w, height), nozzle_diameter, spacing_ratio, false);
diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp
index ada1ea797..97a6a8906 100644
--- a/src/libslic3r/GCode.cpp
+++ b/src/libslic3r/GCode.cpp
@@ -3145,7 +3145,8 @@ GCode::LayerResult GCode::process_layer(
BOOST_LOG_TRIVIAL(trace) << "Exported layer " << layer.id() << " print_z " << print_z <<
log_memory_info();
- print.set_status(int((layer.id() * 100) / layer_count()), std::string(L("Generating G-code layer %s / %s")), std::vector<std::string>{ std::to_string(layer.id()), std::to_string(layer_count()) }, PrintBase::SlicingStatus::DEFAULT | PrintBase::SlicingStatus::SECONDARY_STATE);
+ if(object_layer)
+ print.set_status(int((layer.id() * 100) / layer_count()), std::string(L("Generating G-code layer %s / %s")), std::vector<std::string>{ std::to_string(layer.id()), std::to_string(layer_count()) }, PrintBase::SlicingStatus::DEFAULT | PrintBase::SlicingStatus::SECONDARY_STATE);
result.gcode = std::move(gcode);
result.cooling_buffer_flush = object_layer || raft_layer || last_layer;
diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp
index b1f4af1f3..85d927187 100644
--- a/src/libslic3r/PerimeterGenerator.cpp
+++ b/src/libslic3r/PerimeterGenerator.cpp
@@ -35,7 +35,7 @@ PerimeterGeneratorLoops get_all_Childs(PerimeterGeneratorLoop loop) {
}
// Thanks Cura developers for this function.
-static void fuzzy_polygon(Polygon& poly, double fuzzy_skin_thickness, double fuzzy_skin_point_dist)
+static void fuzzy_polygon(Polygon& poly, coordf_t fuzzy_skin_thickness, coordf_t fuzzy_skin_point_dist)
{
const double min_dist_between_points = fuzzy_skin_point_dist * 3. / 4.; // hardcoded: the point distance may vary between 3/4 and 5/4 the supplied value
const double range_random_point_dist = fuzzy_skin_point_dist / 2.;
@@ -731,13 +731,16 @@ void PerimeterGenerator::process()
}
}
+ // fuzzify
+ const bool fuzzify_contours = this->config->fuzzy_skin != FuzzySkinType::None && perimeter_idx == 0 && this->layer->id() > 0;
+ const bool fuzzify_holes = this->layer->id() > 0 && this->config->fuzzy_skin == FuzzySkinType::All;
for (const ExPolygon& expolygon : next_onion) {
//TODO: add width here to allow variable width (if we want to extrude a sightly bigger perimeter, see thin wall)
- contours[perimeter_idx].emplace_back(expolygon.contour, perimeter_idx, true, has_steep_overhang);
+ contours[perimeter_idx].emplace_back(expolygon.contour, perimeter_idx, true, has_steep_overhang, fuzzify_contours || fuzzify_holes);
if (!expolygon.holes.empty()) {
holes[perimeter_idx].reserve(holes[perimeter_idx].size() + expolygon.holes.size());
for (const Polygon& hole : expolygon.holes)
- holes[perimeter_idx].emplace_back(hole, perimeter_idx, false, has_steep_overhang);
+ holes[perimeter_idx].emplace_back(hole, perimeter_idx, false, has_steep_overhang, fuzzify_holes);
}
}
last = std::move(next_onion);
@@ -872,6 +875,9 @@ void PerimeterGenerator::process()
//svg.draw(to_polylines(top_fills), "green");
//svg.Close();
//}
+
+ // fuzzify
+ const bool fuzzify_gapfill = this->config->fuzzy_skin == FuzzySkinType::All && this->layer->id() > 0;
// check for extracting extra perimeters from gapfill
if (!gaps.empty()) {
// if needed, add it to the first empty contour list
@@ -892,7 +898,7 @@ void PerimeterGenerator::process()
holes.emplace_back();
}
//Add the new periemter
- contours[contours_size].emplace_back(contour_expolygon.front().contour, contours_size, true, has_steep_overhang);
+ contours[contours_size].emplace_back(contour_expolygon.front().contour, contours_size, true, has_steep_overhang, fuzzify_gapfill);
//create the new gapfills
ExPolygons gapfill_area = offset_ex(Polygons{ expoly.contour }, -(float)(perimeter_spacing));
ExPolygons to_add = intersection_ex(ExPolygons{ expoly }, gapfill_area);
@@ -1078,7 +1084,7 @@ void PerimeterGenerator::process()
// collapse
double min = 0.2 * perimeter_width * (1 - INSET_OVERLAP_TOLERANCE);
//be sure we don't gapfill where the perimeters are already touching each other (negative spacing).
- min = std::max(min, double(Flow::new_from_spacing(EPSILON, this->perimeter_flow.nozzle_diameter(), (float)this->layer->height, this->perimeter_flow.spacing_ratio(), false).scaled_width()));
+ min = std::max(min, double(Flow::new_from_spacing((float)EPSILON, (float)this->perimeter_flow.nozzle_diameter(), (float)this->layer->height, (float)this->perimeter_flow.spacing_ratio(), false).scaled_width()));
double max = 2.2 * perimeter_spacing;
//remove areas that are too big (shouldn't occur...)
ExPolygons too_big = offset2_ex(gaps, double(-max / 2), double(+max / 2));
@@ -1493,6 +1499,57 @@ ExtrusionPaths PerimeterGenerator::create_overhangs(const Polyline& loop_polygon
return paths;
}
+static void fuzzy_polygon(ExtrusionPaths& paths, coordf_t fuzzy_skin_thickness, coordf_t fuzzy_skin_point_dist)
+{
+ const coordf_t min_dist_between_points = fuzzy_skin_point_dist * 3. / 4.; // hardcoded: the point distance may vary between 3/4 and 5/4 the supplied value
+ const coordf_t range_random_point_dist = fuzzy_skin_point_dist / 2.;
+ coordf_t dist_left_over = coordf_t(rand()) * (min_dist_between_points / 2) / double(RAND_MAX); // the distance to be traversed on the line before making the first new point
+
+ Point last_point = paths.back().last_point();
+ bool is_loop = true; //always a loop currently paths.front().first_point() == last_point;
+ Point p0 = last_point;
+ for (ExtrusionPath &path : paths) {
+ Points out;
+ size_t next_idx = 0;
+ if (p0 == path.polyline.points.front()) {
+ next_idx = 1;
+ }
+ out.reserve(path.polyline.points.size());
+ for (; next_idx < path.polyline.points.size(); next_idx++)
+ {
+ Point& p1 = path.polyline.points[next_idx];
+ // 'a' is the (next) new point between p0 and p1
+ Vec2d p0p1 = (p1 - p0).cast<double>();
+ coordf_t p0p1_size = p0p1.norm();
+ // so that p0p1_size - dist_last_point evaulates to dist_left_over - p0p1_size
+ coordf_t dist_last_point = dist_left_over + p0p1_size * 2.;
+ for (coordf_t p0pa_dist = dist_left_over; p0pa_dist < p0p1_size;
+ p0pa_dist += min_dist_between_points + coordf_t(rand()) * range_random_point_dist / double(RAND_MAX))
+ {
+ coordf_t r = coordf_t(rand()) * (fuzzy_skin_thickness * 2.) / double(RAND_MAX) - fuzzy_skin_thickness;
+ out.emplace_back(p0 + (p0p1 * (p0pa_dist / p0p1_size) + perp(p0p1).cast<double>().normalized() * r).cast<coord_t>());
+ dist_last_point = p0pa_dist;
+ }
+ dist_left_over = p0p1_size - dist_last_point;
+ p0 = p1;
+ }
+ while (path.polyline.size() < 3) {
+ size_t point_idx = path.polyline.size() - 2;
+ out.emplace_back(path.polyline.points[point_idx]);
+ if (point_idx == 0)
+ break;
+ --point_idx;
+ }
+ if (out.size() >= 3)
+ path.polyline.points = std::move(out);
+ }
+ if (is_loop) {
+ paths.back().polyline.points.push_back(paths.front().polyline.points.front());
+ } else {
+ paths.back().polyline.points.push_back(last_point);
+ }
+}
+
ExtrusionEntityCollection PerimeterGenerator::_traverse_loops(
const PerimeterGeneratorLoops &loops, ThickPolylines &thin_walls) const
{
@@ -1543,6 +1600,12 @@ ExtrusionEntityCollection PerimeterGenerator::_traverse_loops(
assert(path.height == path.height);
paths.push_back(path);
}
+ if (loop.fuzzify) {
+ double nozle_diameter = is_external ? this->ext_perimeter_flow.nozzle_diameter() : this->perimeter_flow.nozzle_diameter();
+ double fuzzy_skin_thickness = config->fuzzy_skin_thickness.get_abs_value(nozle_diameter);
+ double fuzzy_skin_point_dist = config->fuzzy_skin_point_dist.get_abs_value(nozle_diameter);
+ fuzzy_polygon(paths, scale_d(fuzzy_skin_thickness), scale_d(fuzzy_skin_point_dist));
+ }
coll.append(ExtrusionLoop(paths, loop_role));
}
@@ -1905,12 +1968,22 @@ PerimeterGenerator::_extrude_and_cut_loop(const PerimeterGeneratorLoop &loop, co
Polyline initial_polyline;
const coord_t dist_cut = (coord_t)scale_(this->print_config->nozzle_diameter.get_at(this->config->perimeter_extruder - 1));
+ //fuzzify first in this case, as it's a bit complicated to do it after.
+ Polygon fuzzy_poly;
+ if (loop.fuzzify) {
+ fuzzy_poly = loop.polygon;
+ double nozle_diameter = loop.is_external() ? this->ext_perimeter_flow.nozzle_diameter() : this->perimeter_flow.nozzle_diameter();
+ double fuzzy_skin_thickness = config->fuzzy_skin_thickness.get_abs_value(nozle_diameter);
+ double fuzzy_skin_point_dist = config->fuzzy_skin_point_dist.get_abs_value(nozle_diameter);
+ fuzzy_polygon(fuzzy_poly, scale_d(fuzzy_skin_thickness), scale_d(fuzzy_skin_point_dist));
+ }
+ const Polygon& poly_to_use = loop.fuzzify ? fuzzy_poly : loop.polygon;
- if (loop.polygon.points.size() < 3) return ExtrusionLoop(elrDefault);
- if (loop.polygon.length() < dist_cut * 2) {
+ if (poly_to_use.points.size() < 3) return ExtrusionLoop(elrDefault);
+ if (poly_to_use.length() < dist_cut * 2) {
ExtrusionLoop single_point(elrDefault);
Polyline poly_point;
- poly_point.append(loop.polygon.centroid());
+ poly_point.append(poly_to_use.centroid());
single_point.paths.emplace_back(
loop.is_external() ? erExternalPerimeter : erPerimeter,
(double)(loop.is_external() ? this->ext_mm3_per_mm (): this->mm3_per_mm()),
@@ -1919,24 +1992,24 @@ PerimeterGenerator::_extrude_and_cut_loop(const PerimeterGeneratorLoop &loop, co
single_point.paths.back().polyline = poly_point;
return single_point;
}
- const size_t idx_closest_from_entry_point = loop.polygon.closest_point_index(entry_point);
- if (loop.polygon.points[idx_closest_from_entry_point].distance_to(entry_point) > SCALED_EPSILON) {
+ const size_t idx_closest_from_entry_point = poly_to_use.closest_point_index(entry_point);
+ if (poly_to_use.points[idx_closest_from_entry_point].distance_to(entry_point) > SCALED_EPSILON * 2) {
//create new Point
//get first point
size_t idx_before = -1;
- for (size_t idx_p_a = 0; idx_p_a < loop.polygon.points.size(); ++idx_p_a) {
- Line l(loop.polygon.points[idx_p_a], loop.polygon.points[(idx_p_a + 1 == loop.polygon.points.size()) ? 0 : (idx_p_a + 1)]);
+ for (size_t idx_p_a = 0; idx_p_a < poly_to_use.points.size(); ++idx_p_a) {
+ Line l(poly_to_use.points[idx_p_a], poly_to_use.points[(idx_p_a + 1 == poly_to_use.points.size()) ? 0 : (idx_p_a + 1)]);
if (entry_point.distance_to(l) < SCALED_EPSILON) {
idx_before = idx_p_a;
break;
}
}
if (idx_before == (size_t)-1) std::cerr << "ERROR: _traverse_and_join_loops : idx_before can't be finded to create new point\n";
- initial_polyline = loop.polygon.split_at_index(idx_before);
+ initial_polyline = poly_to_use.split_at_index(idx_before);
initial_polyline.points.push_back(entry_point);
initial_polyline.points[0] = entry_point;
} else {
- initial_polyline = loop.polygon.split_at_index(idx_closest_from_entry_point);
+ initial_polyline = poly_to_use.split_at_index(idx_closest_from_entry_point);
}
@@ -2323,7 +2396,7 @@ PerimeterGenerator::_traverse_and_join_loops(const PerimeterGeneratorLoop &loop,
for (size_t i = 0; i < my_loop.paths.size(); i++) {
if (my_loop.paths[i].polyline.size() < 2) {
if (my_loop.paths[i].polyline.size() == 1)
- std::cout << "erase one-point extrusion : layer " << this->layer->id() << " " << my_loop.paths[i].polyline.points.front().x() << ":" << my_loop.paths[i].polyline.points.front().y() << "\n";
+ BOOST_LOG_TRIVIAL(warning) << "erase one-point extrusion : layer " << this->layer->id() << " " << my_loop.paths[i].polyline.points.front().x() << ":" << my_loop.paths[i].polyline.points.front().y() << "\n";
my_loop.paths.erase(my_loop.paths.begin() + i);
i--;
}
diff --git a/src/libslic3r/PerimeterGenerator.hpp b/src/libslic3r/PerimeterGenerator.hpp
index 18a7485a2..71368807c 100644
--- a/src/libslic3r/PerimeterGenerator.hpp
+++ b/src/libslic3r/PerimeterGenerator.hpp
@@ -35,12 +35,14 @@ public:
unsigned short depth;
// Children contour, may be both CCW and CW oriented (outer contours or holes).
std::vector<PerimeterGeneratorLoop> children;
+ // can be fuzzified?
+ bool fuzzify;
PerimeterGeneratorLoop(Polygon polygon, unsigned short depth, bool is_contour) :
- polygon(polygon), is_contour(is_contour), depth(depth), is_steep_overhang(false) {}
- PerimeterGeneratorLoop(Polygon polygon, unsigned short depth, bool is_contour, bool is_steep_overhang) :
- polygon(polygon), is_contour(is_contour), depth(depth), is_steep_overhang(is_steep_overhang) {}
+ polygon(polygon), is_contour(is_contour), depth(depth), is_steep_overhang(false), fuzzify(false) {}
+ PerimeterGeneratorLoop(Polygon polygon, unsigned short depth, bool is_contour, bool is_steep_overhang, bool is_fuzzy) :
+ polygon(polygon), is_contour(is_contour), depth(depth), is_steep_overhang(is_steep_overhang), fuzzify(is_fuzzy) {}
// External perimeter. It may be CCW or CW oriented (outer contour or hole contour).
bool is_external() const { return this->depth == 0; }
// it's the last loop of the contour (not hol), so the first to be printed (if all goes well)
diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp
index 318673ba3..b2897f841 100644
--- a/src/libslic3r/Preset.cpp
+++ b/src/libslic3r/Preset.cpp
@@ -510,6 +510,7 @@ static std::vector<std::string> s_Preset_print_options {
"external_perimeter_speed",
"first_layer_speed",
"first_layer_min_speed",
+ "first_layer_speed_over_raft",
"infill_speed",
"perimeter_speed",
"small_perimeter_speed",
@@ -529,6 +530,10 @@ static std::vector<std::string> s_Preset_print_options {
"gap_fill_min_area",
"gap_fill_overlap",
"gap_fill_speed",
+ // fuzzy
+ "fuzzy_skin",
+ "fuzzy_skin_point_dist",
+ "fuzzy_skin_thickness",
// acceleration
"bridge_acceleration",
"bridge_internal_acceleration",
@@ -569,7 +574,12 @@ static std::vector<std::string> s_Preset_print_options {
//"brim_type",
// support
"support_material", "support_material_auto", "support_material_threshold", "support_material_enforce_layers",
- "raft_layers", "support_material_pattern", "support_material_with_sheath", "support_material_spacing",
+ "raft_contact_distance",
+ "raft_expansion",
+ "raft_first_layer_density",
+ "raft_first_layer_expansion",
+ "raft_layers",
+ "support_material_pattern", "support_material_with_sheath", "support_material_spacing",
"support_material_closing_radius", "support_material_style",
"support_material_synchronize_layers", "support_material_angle",
"support_material_interface_layers", "support_material_bottom_interface_layers",
diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp
index 45e312ea3..cac670862 100644
--- a/src/libslic3r/Print.cpp
+++ b/src/libslic3r/Print.cpp
@@ -990,6 +990,7 @@ void Print::process()
obj->infill();
for (PrintObject *obj : m_objects)
obj->ironing();
+ this->set_status(50, L("Generating support material"));
for (PrintObject *obj : m_objects)
obj->generate_support_material();
if (this->set_started(psWipeTower)) {
diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp
index 37a8ce32b..20c75a70d 100644
--- a/src/libslic3r/PrintConfig.cpp
+++ b/src/libslic3r/PrintConfig.cpp
@@ -690,7 +690,7 @@ void PrintConfigDef::init_fff_params()
"\nThis setting allow you to choose the base for the bridge flow compute, the result will be multiplied by the bridge flow to have the final result."
" The preview will display the expected shape of the bridge extrusion (cylinder), don't expect a magical thick and solid air to flatten the extrusion magically.");
def->sidetext = L("%");
- def->enum_keys_map = &ConfigOptionEnum<FuzzySkinType>::get_enum_values();
+ def->enum_keys_map = &ConfigOptionEnum<BridgeType>::get_enum_values();
def->enum_values.push_back("nozzle");
def->enum_values.push_back("height");
def->enum_values.push_back("flow");
@@ -1256,7 +1256,7 @@ void PrintConfigDef::init_fff_params()
def->full_label = L("Default infill margin");
def->category = OptionCategory::infill;
def->tooltip = L("This parameter grows the top/bottom/solid layers by the specified mm to anchor them into the sparse infill and support the perimeters above. Put 0 to deactivate it. Can be a % of the width of the perimeters.");
- def->sidetext = L("mm/%");
+ def->sidetext = L("mm or %");
def->ratio_over = "perimeter_extrusion_width";
def->min = 0;
def->max_literal = { 50, true };
@@ -1268,7 +1268,7 @@ void PrintConfigDef::init_fff_params()
def->full_label = L("Bridge margin");
def->category = OptionCategory::infill;
def->tooltip = L("This parameter grows the bridged solid infill layers by the specified mm to anchor them into the sparse infill and over the perimeters below. Put 0 to deactivate it. Can be a % of the width of the external perimeter.");
- def->sidetext = L("mm/%");
+ def->sidetext = L("mm or %");
def->ratio_over = "external_perimeter_extrusion_width";
def->min = 0;
def->max_literal = { 50, true };
@@ -1605,7 +1605,7 @@ void PrintConfigDef::init_fff_params()
def->label = L("Default extrusion width");
def->category = OptionCategory::width;
def->tooltip = L("This is the DEFAULT extrusion width. It's ONLY used to REPLACE 0-width fields. It's useless when all other width fields have a value."
- "Set this to a non-zero value to allow a manual extrusion width. "
+ "\nSet this to a non-zero value to allow a manual extrusion width. "
"If left to zero, Slic3r derives extrusion widths from the nozzle diameter "
"(see the tooltips for perimeter extrusion width, infill extrusion width etc). "
"If expressed as percentage (for example: 105%), it will be computed over nozzle diameter."
@@ -1617,7 +1617,7 @@ void PrintConfigDef::init_fff_params()
def->max_literal = { 10, true };
def->precision = 6;
def->can_phony = true;
- def->mode = comAdvanced;
+ def->mode = comExpert;
def->set_default_value(new ConfigOptionFloatOrPercent(0, false, true));
def = this->add("extrusion_spacing", coFloatOrPercent);
@@ -2435,25 +2435,27 @@ void PrintConfigDef::init_fff_params()
def->mode = comSimple;
def->set_default_value(new ConfigOptionEnum<FuzzySkinType>(FuzzySkinType::None));
- def = this->add("fuzzy_skin_thickness", coFloat);
+ def = this->add("fuzzy_skin_thickness", coFloatOrPercent);
def->label = L("Fuzzy skin thickness");
def->category = OptionCategory::fuzzy_skin;
def->tooltip = L("The maximum distance that each skin point can be offset (both ways), "
- "measured perpendicular to the perimeter wall.");
- def->sidetext = L("mm");
+ "measured perpendicular to the perimeter wall."
+ "\nCan be a % of the nozzle diameter.");
+ def->sidetext = L("mm or %");
def->min = 0;
def->mode = comAdvanced;
- def->set_default_value(new ConfigOptionFloat(0.3));
+ def->set_default_value(new ConfigOptionFloatOrPercent(150, true));
- def = this->add("fuzzy_skin_point_dist", coFloat);
+ def = this->add("fuzzy_skin_point_dist", coFloatOrPercent);
def->label = L("Fuzzy skin point distance");
def->category = OptionCategory::fuzzy_skin;
def->tooltip = L("Perimeters will be split into multiple segments by inserting Fuzzy skin points. "
- "Lowering the Fuzzy skin point distance will increase the number of randomly offset points on the perimeter wall.");
- def->sidetext = L("mm");
+ "Lowering the Fuzzy skin point distance will increase the number of randomly offset points on the perimeter wall."
+ "\nCan be a % of the nozzle diameter.");
+ def->sidetext = L("mm or %");
def->min = 0;
def->mode = comAdvanced;
- def->set_default_value(new ConfigOptionFloat(0.8));
+ def->set_default_value(new ConfigOptionFloatOrPercent(200, true));
def = this->add("gap_fill_enabled", coBool);
def->label = L("Gap fill");
@@ -3411,7 +3413,7 @@ void PrintConfigDef::init_fff_params()
def->min = 0;
def->max_literal = { 15, false };
def->mode = comExpert;
- def->set_default_value(new ConfigOptionFloatOrPercent(200, true));
+ def->set_default_value(new ConfigOptionFloatOrPercent(100, true));
def = this->add("min_print_speed", coFloats);
def->label = L("Min print speed");
@@ -3715,6 +3717,7 @@ void PrintConfigDef::init_fff_params()
"\nYou can set either 'Spacing', or 'Width'; the other will be calculated, using the perimeter 'Overlap' percentages and default layer height.");
def->sidetext = L("mm or %");
def->aliases = { "perimeters_extrusion_width" };
+ def->ratio_over = "nozzle_diameter";
def->min = 0;
def->max = 1000;
def->max_literal = { 10, true };
@@ -3731,6 +3734,8 @@ void PrintConfigDef::init_fff_params()
"\nYou can set either 'Spacing', or 'Width'; the other will be calculated, using the perimeter 'Overlap' percentages and default layer height.");
def->sidetext = L("mm or %");
def->aliases = { "perimeters_extrusion_width" };
+ def->ratio_over = "nozzle_diameter";
+ def->is_vector_extruder = true;
def->min = 0;
def->max = 1000;
def->max_literal = { 10, true };
@@ -4254,6 +4259,7 @@ void PrintConfigDef::init_fff_params()
" If left as zero, first layer extrusion width will be used if set and the skirt is only 1 layer height"
", or perimeter extrusion width will be used (using the computed value if not set).");
def->sidetext = L("mm or %");
+ def->ratio_over = "nozzle_diameter";
def->min = 0;
def->max = 1000;
def->max_literal = { 10, true };
diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp
index ca04e05f1..e15c4519e 100644
--- a/src/libslic3r/PrintConfig.hpp
+++ b/src/libslic3r/PrintConfig.hpp
@@ -777,8 +777,8 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionPercent, fill_density))
((ConfigOptionEnum<InfillPattern>, fill_pattern))
((ConfigOptionEnum<FuzzySkinType>, fuzzy_skin))
- ((ConfigOptionFloat, fuzzy_skin_thickness))
- ((ConfigOptionFloat, fuzzy_skin_point_dist))
+ ((ConfigOptionFloatOrPercent, fuzzy_skin_thickness))
+ ((ConfigOptionFloatOrPercent, fuzzy_skin_point_dist))
((ConfigOptionPercent, fill_top_flow_ratio))
((ConfigOptionPercent, fill_smooth_distribution))
((ConfigOptionFloatOrPercent, fill_smooth_width))
diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp
index aefc044f2..de64d3eef 100644
--- a/src/libslic3r/PrintObject.cpp
+++ b/src/libslic3r/PrintObject.cpp
@@ -613,7 +613,6 @@ std::vector<std::reference_wrapper<const PrintRegion>> PrintObject::all_regions(
if (this->set_started(posSupportMaterial)) {
this->clear_support_layers();
if ((this->has_support() && m_layers.size() > 1) || (this->has_raft() && ! m_layers.empty())) {
- m_print->set_status(85, L("Generating support material"));
this->_generate_support_material();
m_print->throw_if_canceled();
} else {
diff --git a/src/libslic3r/Thread.cpp b/src/libslic3r/Thread.cpp
index a77f6bc91..fc4debc69 100644
--- a/src/libslic3r/Thread.cpp
+++ b/src/libslic3r/Thread.cpp
@@ -202,11 +202,11 @@ void name_tbb_thread_pool_threads_set_locale()
const size_t nthreads_hw = tbb::this_task_arena::max_concurrency();
size_t nthreads = nthreads_hw;
-#ifdef SLIC3R_PROFILE
+//#ifdef SLIC3R_PROFILE
// Shiny profiler is not thread safe, thus disable parallelization.
disable_multi_threading();
nthreads = 1;
-#endif
+//#endif
size_t nthreads_running(0);
std::condition_variable cv;
diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp
index 8bccaa1a2..852b1e99e 100644
--- a/src/slic3r/GUI/ConfigManipulation.cpp
+++ b/src/slic3r/GUI/ConfigManipulation.cpp
@@ -351,6 +351,9 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config)
for (auto el : { "gap_fill_last", "gap_fill_min_area" })
toggle_field(el, config->opt_bool("gap_fill_enabled"));
+ for (auto el : { "fuzzy_skin_thickness", "fuzzy_skin_point_dist" })
+ toggle_field(el, config->option<ConfigOptionEnum<FuzzySkinType>>("fuzzy_skin")->value != FuzzySkinType::None);
+
toggle_field("avoid_crossing_not_first_layer", config->opt_bool("avoid_crossing_perimeters"));
bool have_infill = config->option<ConfigOptionPercent>("fill_density")->value > 0;
diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp
index 929451f9d..e6a0463c2 100644
--- a/src/slic3r/GUI/Field.cpp
+++ b/src/slic3r/GUI/Field.cpp
@@ -1314,12 +1314,11 @@ void Choice::set_value(const std::string& value, bool change_event) //! Redunda
m_disable_change_event = false;
}
-template<class T>
-int Choice::idx_from_enum_value(int val) {
+int32_t Choice::idx_from_enum_value(int32_t val) {
if (!m_opt.enum_values.empty()) {
std::string key;
- t_config_enum_values map_names = ConfigOptionEnum<T>::get_enum_values();
- for (auto it : map_names) {
+ const t_config_enum_values* map_names = m_opt.enum_keys_map;
+ for (auto it : *map_names) {
if (val == it.second) {
key = it.first;
break;
@@ -1386,57 +1385,8 @@ void Choice::set_value(const boost::any& value, bool change_event)
break;
}
case coEnum: {
- int val = boost::any_cast<int>(value);
-// if (m_opt_id.compare("host_type") == 0 && val != 0 &&
-// m_opt.enum_values.size() > field->GetCount()) // for case, when PrusaLink isn't used as a HostType
-// val--;
-
-
-
- if (m_opt_id == "top_fill_pattern" || m_opt_id == "bottom_fill_pattern" || m_opt_id == "solid_fill_pattern"
- || m_opt_id == "fill_pattern" || m_opt_id == "support_material_interface_pattern" || m_opt_id == "brim_ears_pattern")
- val = idx_from_enum_value<InfillPattern>(val);
- else if (m_opt_id.compare("complete_objects_sort") == 0)
- val = idx_from_enum_value<CompleteObjectSort>(val);
- else if (m_opt_id.compare("bridge_type") == 0)
- val = idx_from_enum_value<BridgeType>(val);
- else if (m_opt_id.compare("display_orientation") == 0)
- val = idx_from_enum_value<SLADisplayOrientation>(val);
- else if (m_opt_id.compare("gcode_flavor") == 0)
- val = idx_from_enum_value<GCodeFlavor>(val);
- else if (m_opt_id.compare("host_type") == 0)
- val = idx_from_enum_value<PrintHostType>(val);
- else if (m_opt_id =="infill_connection" || m_opt_id =="infill_connection_solid"
- || m_opt_id =="infill_connection_top" || m_opt_id =="infill_connection_bottom")
- val = idx_from_enum_value<InfillConnection>(val);
- else if (m_opt_id.compare("infill_dense_algo") == 0)
- val = idx_from_enum_value<DenseInfillAlgo>(val);
- else if (m_opt_id == "ironing_type")
- val = idx_from_enum_value<IroningType>(val);
- else if (m_opt_id.compare("machine_limits_usage") == 0)
- val = idx_from_enum_value<MachineLimitsUsage>(val);
- else if (m_opt_id.compare("no_perimeter_unsupported_algo") == 0)
- val = idx_from_enum_value<NoPerimeterUnsupportedAlgo>(val);
- else if (m_opt_id.compare("perimeter_loop_seam") == 0)
- val = idx_from_enum_value<SeamPosition>(val);
- else if (m_opt_id == "printhost_authorization_type")
- val = idx_from_enum_value<AuthorizationType>(val);
- else if (m_opt_id.compare("remaining_times_type") == 0)
- val = idx_from_enum_value<RemainingTimeType>(val);
- else if (m_opt_id.compare("seam_position") == 0)
- val = idx_from_enum_value<SeamPosition>(val);
- else if (m_opt_id.compare("support_material_contact_distance_type") == 0)
- val = idx_from_enum_value<SupportZDistanceType>(val);
- else if (m_opt_id.compare("support_material_pattern") == 0)
- val = idx_from_enum_value<SupportMaterialPattern>(val);
- else if (m_opt_id.compare("support_pillar_connection_mode") == 0)
- val = idx_from_enum_value<SLAPillarConnectionMode>(val);
- else if (m_opt_id.compare("wipe_advanced_algo") == 0)
- val = idx_from_enum_value<WipeAlgo>(val);
- else if (m_opt_id.compare("output_format") == 0)
- val = idx_from_enum_value<OutputFormat>(val);
- else if (m_opt_id.compare("config_compatibility") == 0)
- val = idx_from_enum_value<ForwardCompatibilitySubstitutionRule>(val);
+ int32_t val = boost::any_cast<int32_t>(value);
+ val = idx_from_enum_value(val);
BOOST_LOG_TRIVIAL(debug) << "Set field from key "<< m_opt_id << " as int " << boost::any_cast<int>(value) << " modified to " << val;
field->SetSelection(val);
break;
@@ -1468,17 +1418,16 @@ void Choice::set_values(const std::vector<std::string>& values)
m_disable_change_event = false;
}
-template<class T>
-void Choice::convert_to_enum_value(int ret_enum) {
+void Choice::convert_to_enum_value(int32_t ret_enum) {
if (!m_opt.enum_values.empty()) {
std::string key = m_opt.enum_values[ret_enum];
- t_config_enum_values map_names = ConfigOptionEnum<T>::get_enum_values();
- int value = map_names.at(key);
+ const t_config_enum_values *map_names = m_opt.enum_keys_map;
+ int32_t value = map_names->at(key);
- m_value = static_cast<T>(value);
+ m_value = value;
}
else
- m_value = static_cast<T>(m_opt.default_value.get()->getInt());
+ m_value = m_opt.default_value.get()->getInt();
}
//TODO: check if used (from prusa)
@@ -1517,51 +1466,7 @@ boost::any& Choice::get_value()
if (m_opt.type == coEnum)
{
int ret_enum = field->GetSelection();
-// if (m_opt_id.compare("host_type") == 0 &&
-// m_opt.enum_values.size() > field->GetCount()) // for case, when PrusaLink isn't used as a HostType
-// ret_enum++;
- if (m_opt_id == "top_fill_pattern" || m_opt_id == "bottom_fill_pattern" || m_opt_id == "solid_fill_pattern"
- || m_opt_id == "support_material_interface_pattern" || m_opt_id == "fill_pattern" || m_opt_id == "brim_ears_pattern")
- convert_to_enum_value<InfillPattern>(ret_enum);
- else if (m_opt_id.compare("complete_objects_sort") == 0)
- convert_to_enum_value<CompleteObjectSort>(ret_enum);
- else if (m_opt_id.compare("display_orientation") == 0)
- convert_to_enum_value<SLADisplayOrientation>(ret_enum);
- else if (m_opt_id.compare("gcode_flavor") == 0)
- convert_to_enum_value<GCodeFlavor>(ret_enum);
- else if (m_opt_id.compare("host_type") == 0)
- convert_to_enum_value<PrintHostType>(ret_enum);
- else if (m_opt_id =="infill_connection" || m_opt_id =="infill_connection_solid"
- || m_opt_id =="infill_connection_top" || m_opt_id =="infill_connection_bottom")
- convert_to_enum_value<InfillConnection>(ret_enum);
- else if (m_opt_id.compare("infill_dense_algo") == 0)
- convert_to_enum_value<DenseInfillAlgo>(ret_enum);
- else if (m_opt_id == "ironing_type")
- convert_to_enum_value<IroningType>(ret_enum);
- else if (m_opt_id.compare("machine_limits_usage") == 0)
- convert_to_enum_value<MachineLimitsUsage>(ret_enum);
- else if (m_opt_id.compare("no_perimeter_unsupported_algo") == 0)
- convert_to_enum_value<NoPerimeterUnsupportedAlgo>(ret_enum);
- else if (m_opt_id.compare("perimeter_loop_seam") == 0)
- convert_to_enum_value<SeamPosition>(ret_enum);
- else if (m_opt_id == "printhost_authorization_type")
- convert_to_enum_value<AuthorizationType>(ret_enum);
- else if (m_opt_id.compare("remaining_times_type") == 0)
- convert_to_enum_value<RemainingTimeType>(ret_enum);
- else if (m_opt_id.compare("seam_position") == 0)
- convert_to_enum_value<SeamPosition>(ret_enum);
- else if (m_opt_id.compare("support_material_contact_distance_type") == 0)
- convert_to_enum_value<SupportZDistanceType>(ret_enum);
- else if (m_opt_id.compare("support_material_pattern") == 0)
- convert_to_enum_value<SupportMaterialPattern>(ret_enum);
- else if (m_opt_id.compare("support_pillar_connection_mode") == 0)
- convert_to_enum_value<SLAPillarConnectionMode>(ret_enum);
- else if (m_opt_id.compare("wipe_advanced_algo") == 0)
- convert_to_enum_value<WipeAlgo>(ret_enum);
- else if (m_opt_id.compare("output_format") == 0)
- convert_to_enum_value<OutputFormat>(ret_enum);
- else if(m_opt_id.compare("config_compatibility") == 0)
- convert_to_enum_value<ForwardCompatibilitySubstitutionRule>(ret_enum);
+ convert_to_enum_value(ret_enum);
}
else if (m_opt.gui_type == ConfigOptionDef::GUIType::f_enum_open || m_opt.gui_type == ConfigOptionDef::GUIType::i_enum_open) {
const int ret_enum = field->GetSelection();
diff --git a/src/slic3r/GUI/Field.hpp b/src/slic3r/GUI/Field.hpp
index 573ab7670..ca37298e8 100644
--- a/src/slic3r/GUI/Field.hpp
+++ b/src/slic3r/GUI/Field.hpp
@@ -368,8 +368,8 @@ class Choice : public Field {
protected:
//used by get_value when it's an enum
//convert the value from the select to the enum value. store it in m_value
- template<class T> void convert_to_enum_value(int idx_val);
- template<class T> int idx_from_enum_value(int enum_val);
+ void convert_to_enum_value(int32_t idx_val);
+ int32_t idx_from_enum_value(int32_t enum_val);
public:
Choice(const ConfigOptionDef& opt, const t_config_option_key& id) : Field(opt, id) {}
Choice(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : Field(parent, opt, id) {}
diff --git a/src/slic3r/GUI/GUI.cpp b/src/slic3r/GUI/GUI.cpp
index 6b239b278..5ba6898de 100644
--- a/src/slic3r/GUI/GUI.cpp
+++ b/src/slic3r/GUI/GUI.cpp
@@ -193,9 +193,8 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt
}
break;
case coEnum:{
- auto *opt = opt_def->default_value.get()->clone();
- opt->setInt(boost::any_cast<int>(value));
- // same as config.set_key_value(opt_key, new ConfigOptionEnum<InfillPattern>(boost::any_cast<InfillPattern>(value)));
+ ConfigOption* opt = opt_def->default_value.get()->clone();
+ opt->setInt(boost::any_cast<int32_t>(value)); // we transport an int convertion of the enum in the boost anycast.
BOOST_LOG_TRIVIAL(debug) << "Set enum "<< opt_key << " as int " << boost::any_cast<int>(value) << " into enum " << opt->serialize();
config.set_key_value(opt_key, opt);
}
diff --git a/src/slic3r/GUI/NotificationManager.cpp b/src/slic3r/GUI/NotificationManager.cpp
index 69f4f6455..956436ac5 100644
--- a/src/slic3r/GUI/NotificationManager.cpp
+++ b/src/slic3r/GUI/NotificationManager.cpp
@@ -1164,7 +1164,7 @@ void NotificationManager::SlicingProgressNotification::set_status_text(const std
break;
case Slic3r::GUI::NotificationManager::SlicingProgressNotification::SlicingProgressState::SP_PROGRESS:
{
- NotificationData data{ NotificationType::SlicingProgress, NotificationLevel::ProgressBarNotificationLevel, 0, text + "." };
+ NotificationData data{ NotificationType::SlicingProgress, NotificationLevel::ProgressBarNotificationLevel, 0, text };
update(data);
m_state = EState::NotFading;
}
diff --git a/src/slic3r/GUI/OG_CustomCtrl.cpp b/src/slic3r/GUI/OG_CustomCtrl.cpp
index 7e2e9c05d..aae8710b8 100644
--- a/src/slic3r/GUI/OG_CustomCtrl.cpp
+++ b/src/slic3r/GUI/OG_CustomCtrl.cpp
@@ -90,7 +90,6 @@ void OG_CustomCtrl::init_ctrl_lines()
// if we have a single option with no label, no sidetext just add it directly to sizer
if (option_set.size() == 1 && opt_group->title_width == 0 && option_set.front().opt.full_width &&
- option_set.front().opt.label.empty() &&
option_set.front().opt.sidetext.size() == 0 && option_set.front().side_widget == nullptr &&
line.get_extra_widgets().size() == 0)
{
@@ -132,6 +131,15 @@ wxPoint OG_CustomCtrl::get_pos(const Line& line, Field* field_in/* = nullptr*/)
line_height = win_height;
};
+ auto correct_horiz_pos = [this](int& h_pos, Field* field) {
+ if (m_max_win_width > 0 && field->getWindow()) {
+ int win_width = field->getWindow()->GetSize().GetWidth();
+ if (dynamic_cast<CheckBox*>(field))
+ win_width *= 0.5;
+ h_pos += m_max_win_width - win_width;
+ }
+ };
+
for (CtrlLine& ctrl_line : ctrl_lines) {
if (&ctrl_line.og_line == &line)
{
@@ -170,15 +178,16 @@ wxPoint OG_CustomCtrl::get_pos(const Line& line, Field* field_in/* = nullptr*/)
// If we have a single option with no sidetext
const std::vector<Option>& option_set = line.get_options();
if (option_set.size() == 1 && option_set.front().opt.sidetext.size() == 0 &&
- option_set.front().opt.label.empty() &&
option_set.front().side_widget == nullptr && line.get_extra_widgets().size() == 0)
{
h_pos += 2 * blinking_button_width;
Field* field = opt_group->get_field(option_set.front().opt_id);
correct_line_height(ctrl_line.height, field->getWindow());
+ //correct_horiz_pos(h_pos, field); //TODO test
break;
}
+ bool is_multioption_line = option_set.size() > 1 || !option_set.front().opt.label.empty();
for (size_t i = 0; i < option_set.size(); ++i) {
if (i >= ctrl_line.is_visible.size() || !ctrl_line.is_visible[i])
continue;
@@ -188,7 +197,7 @@ wxPoint OG_CustomCtrl::get_pos(const Line& line, Field* field_in/* = nullptr*/)
ConfigOptionDef option = opt.opt;
// add label if any
- if (!option.label.empty()) {
+ if (is_multioption_line && !option.label.empty()) {
std::string opt_label = (option.label.empty() || option.label.back() != '_') ? option.label : option.label.substr(0, option.label.size() - 1);
//! To correct translation by context have to use wxGETTEXT_IN_CONTEXT macro from wxWidget 3.1.1
label = /*(opt_label == L_CONTEXT("Top", "Layers") || opt_label == L_CONTEXT("Bottom", "Layers")) ?
@@ -246,8 +255,10 @@ wxPoint OG_CustomCtrl::get_pos(const Line& line, Field* field_in/* = nullptr*/)
// size of little widget before the real one
h_pos += 2 * blinking_button_width;
- if (field == field_in)
+ if (field == field_in) {
+ //correct_horiz_pos(h_pos, field);
break;
+ }
if (opt.opt.gui_type == ConfigOptionDef::GUIType::legend)
h_pos += 2 * blinking_button_width;
@@ -309,11 +320,20 @@ void OG_CustomCtrl::OnMotion(wxMouseEvent& event)
bool suppress_hyperlinks = get_app_config()->get("suppress_hyperlinks") == "1";
for (CtrlLine& line : ctrl_lines) {
- line.is_focused = is_point_in_rect(pos, line.rect_label);
+ line.is_focused = false;
+ wxString *str_tooltip;
+ size_t idx = 0;
+ for (; idx < line.rects_tooltip.size(); ++idx) {
+ line.is_focused = is_point_in_rect(pos, line.rects_tooltip[idx].first);
+ if (line.is_focused) {
+ str_tooltip = &line.rects_tooltip[idx].second;
+ break;
+ }
+ }
if (line.is_focused) {
if (!suppress_hyperlinks && !line.og_line.label_path.empty())
- tooltip = get_url(line.og_line.label_path) +"\n\n";
- tooltip += line.og_line.label_tooltip;
+ tooltip = OptionsGroup::get_url(line.og_line.label_path) +"\n\n";
+ tooltip += *str_tooltip;
break;
}
@@ -419,6 +439,8 @@ void OG_CustomCtrl::correct_widgets_position(wxSizer* widget, const Line& line,
wxPoint pos = line_pos;
wxSize sz = child->GetWindow()->GetSize();
pos.y += std::max(0, int(0.5 * (line_height - sz.y)));
+ if (line.extra_widget_sizer && widget == line.extra_widget_sizer)
+ pos.x += m_h_gap;
child->GetWindow()->SetPosition(pos);
line_pos.x += sz.x + m_h_gap;
}
@@ -460,6 +482,8 @@ void OG_CustomCtrl::msw_rescale()
m_bmp_blinking_sz = create_scaled_bitmap("search_blink", this).GetSize();
if (!m_has_icon) m_bmp_blinking_sz.x = 0;
+ m_max_win_width = 0;
+
wxCoord v_pos = 0;
for (CtrlLine& line : ctrl_lines) {
line.msw_rescale();
@@ -549,6 +573,8 @@ void OG_CustomCtrl::CtrlLine::msw_rescale()
void OG_CustomCtrl::CtrlLine::update_visibility(ConfigOptionMode mode)
{
+ if (og_line.is_separator())
+ return;
const std::vector<Option>& option_set = og_line.get_options();
ConfigOptionMode line_mode = option_set.front().opt.mode;
@@ -588,8 +614,27 @@ void OG_CustomCtrl::CtrlLine::update_visibility(ConfigOptionMode mode)
correct_items_positions();
}
+void OG_CustomCtrl::CtrlLine::render_separator(wxDC& dc, wxCoord v_pos)
+{
+ wxPoint begin(ctrl->m_h_gap, v_pos);
+ wxPoint end(ctrl->GetSize().GetWidth() - ctrl->m_h_gap, v_pos);
+
+ wxPen pen, old_pen = pen = dc.GetPen();
+ pen.SetColour(*wxLIGHT_GREY);
+ dc.SetPen(pen);
+ dc.DrawLine(begin, end);
+ dc.SetPen(old_pen);
+}
+
+//TODO push string manipulation out of the render loop (tooltip replace, adding ':')
void OG_CustomCtrl::CtrlLine::render(wxDC& dc, wxCoord v_pos)
{
+ if (is_separator()) {
+ render_separator(dc, v_pos);
+ return;
+ }
+ rects_tooltip.clear(); // reset the tooltip detection area, they are re-created by draw_text
+
Field* field = ctrl->opt_group->get_field(og_line.get_options().front().opt_id);
int blinking_button_width = ctrl->m_bmp_blinking_sz.GetWidth();
if(blinking_button_width ) blinking_button_width += ctrl->m_h_gap;
@@ -613,11 +658,14 @@ void OG_CustomCtrl::CtrlLine::render(wxDC& dc, wxCoord v_pos)
bool is_url_string = false;
if (ctrl->opt_group->title_width != 0 && !og_line.label.IsEmpty()) {
- const wxColour* text_clr = (option_set.size() == 1 && field ? field->label_color() : og_line.full_Label_color);
+ bool is_multiline = option_set.size() > 1 || !option_set.front().opt.label.empty();
+ // Color the line label is the first settig doesn't have a label
+ const wxColour* text_clr = ((option_set.front().opt.label.empty() || option_set.front().opt.label == "_") && field ?
+ field->label_color() : og_line.full_Label_color);
is_url_string = !suppress_hyperlinks && !og_line.label_path.empty();
wxString opt_label = (og_line.label.empty() || og_line.label.Last() != '_') ? og_line.label : og_line.label.substr(0, og_line.label.size() - 1);
- bool no_dots = og_line.label.empty() || og_line.label.Last() == '_';
- h_pos = draw_text(dc, wxPoint(h_pos, v_pos), (no_dots ? opt_label : opt_label + ':'), text_clr, ctrl->opt_group->title_width * ctrl->m_em_unit, is_url_string);
+ bool no_dots = og_line.label.empty() || og_line.label.Last() == '_' || is_multiline;
+ h_pos = draw_text(dc, wxPoint(h_pos, v_pos), (no_dots ? opt_label : opt_label + ':'), og_line.label_tooltip , text_clr, ctrl->opt_group->title_width * ctrl->m_em_unit, is_url_string);
}
// If there's a widget, build it and set result to the correct position.
@@ -634,12 +682,13 @@ void OG_CustomCtrl::CtrlLine::render(wxDC& dc, wxCoord v_pos)
// If we have a single option with no sidetext just add it directly to the grid sizer
if (option_set.size() == 1 && option_set.front().opt.sidetext.size() == 0 &&
- option_set.front().opt.label.empty() &&
option_set.front().side_widget == nullptr && og_line.get_extra_widgets().size() == 0)
{
if (field) {
if (field->undo_to_sys_bitmap())
h_pos = draw_act_bmps(dc, wxPoint(h_pos, v_pos), field->undo_to_sys_bitmap()->bmp(), field->undo_bitmap()->bmp(), field->blink()) + ctrl->m_h_gap;
+ else if (field && !field->undo_to_sys_bitmap() && field->blink())
+ draw_blinking_bmp(dc, wxPoint(h_pos, v_pos), field->blink());
else
h_pos += 2 * blinking_button_width;
}
@@ -650,15 +699,20 @@ void OG_CustomCtrl::CtrlLine::render(wxDC& dc, wxCoord v_pos)
}
size_t bmp_rect_id = 0;
- bool is_multioption_line = option_set.size() > 1;
+ bool is_multioption_line = option_set.size() > 1 || !option_set.front().opt.label.empty();
for (size_t i = 0; i < option_set.size(); ++i) {
if (i >= is_visible.size() || !is_visible[i])
continue;
const Option& opt = option_set[i];
field = ctrl->opt_group->get_field(opt.opt_id);
ConfigOptionDef option = opt.opt;
+
+ //tooltip for labels
+ wxString option_tooltip = _(option.tooltip);
+ update_Slic3r_string(option_tooltip);
+
// add label if any
- if (!option.label.empty()) {
+ if (is_multioption_line && !option.label.empty()) {
std::string opt_label = (option.label.empty() || option.label.back() != '_') ? option.label : option.label.substr(0, option.label.size() - 1);
//! To correct translation by context have to use wxGETTEXT_IN_CONTEXT macro from wxWidget 3.1.1
wxString label = /*(opt_label == L_CONTEXT("Top", "Layers") || opt_label == L_CONTEXT("Bottom", "Layers")) ?
@@ -681,8 +735,8 @@ void OG_CustomCtrl::CtrlLine::render(wxDC& dc, wxCoord v_pos)
if (is_url_string)
is_url_string = false;
else if (opt == option_set.front())
- is_url_string = !suppress_hyperlinks && !og_line.label_path.empty();
- h_pos = draw_text(dc, wxPoint(h_pos, v_pos), label, field ? field->label_color() : nullptr, width, is_url_string, !field->m_opt.aligned_label_left);
+ is_url_string = !suppress_hyperlinks && !og_line.label_path.empty();
+ h_pos = draw_text(dc, wxPoint(h_pos, v_pos), label, option_tooltip, field ? field->label_color() : nullptr, width, is_url_string, !field->m_opt.aligned_label_left);
}
}
@@ -711,7 +765,7 @@ void OG_CustomCtrl::CtrlLine::render(wxDC& dc, wxCoord v_pos)
// add sidetext if any
if ( (!option.sidetext.empty() || ctrl->opt_group->sidetext_width > 0 || option.sidetext_width > 0 ) && option.sidetext_width != 0)
- h_pos = draw_text(dc, wxPoint(h_pos, v_pos), _(option.sidetext), nullptr, (option.sidetext_width > 0 ? option.sidetext_width : ctrl->opt_group->sidetext_width ) * ctrl->m_em_unit);
+ h_pos = draw_text(dc, wxPoint(h_pos, v_pos), _(option.sidetext), option_tooltip, nullptr, (option.sidetext_width > 0 ? option.sidetext_width : ctrl->opt_group->sidetext_width ) * ctrl->m_em_unit);
if (opt.opt_id != option_set.back().opt_id) //! istead of (opt != option_set.back())
h_pos += lround(0.6 * ctrl->m_em_unit);
@@ -737,7 +791,7 @@ wxCoord OG_CustomCtrl::CtrlLine::draw_mode_bmp(wxDC& dc, wxCoord v_pos)
return get_bitmap_size(bmp).GetWidth() + ctrl->m_h_gap;
}
-wxCoord OG_CustomCtrl::CtrlLine::draw_text(wxDC& dc, wxPoint pos, const wxString& text, const wxColour* color, int width, bool is_url/* = false*/, bool align_right/* = false*/)
+wxCoord OG_CustomCtrl::CtrlLine::draw_text(wxDC& dc, wxPoint pos, const wxString& text, const wxString& tooltip, const wxColour* color, int width, bool is_url/* = false*/, bool align_right/* = false*/)
{
wxString multiline_text;
if (width > 0 && dc.GetTextExtent(text).x > width) {
@@ -773,8 +827,7 @@ wxCoord OG_CustomCtrl::CtrlLine::draw_text(wxDC& dc, wxPoint pos, const wxStr
wxPoint draw_pos = pos;
if (align_right && width > 0)
draw_pos.x += width - text_width;
- if (width > 0)
- rect_label = wxRect(draw_pos, wxSize(text_width, text_height));
+ rects_tooltip.emplace_back(wxRect{draw_pos, wxSize(text_width, text_height)}, tooltip);
wxColour old_clr = dc.GetTextForeground();
wxFont old_font = dc.GetFont();
@@ -785,7 +838,12 @@ wxCoord OG_CustomCtrl::CtrlLine::draw_text(wxDC& dc, wxPoint pos, const wxStr
#else
dc.SetFont(old_font.Bold().Underlined());
#endif
- dc.SetTextForeground(color ? *color : wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
+ dc.SetTextForeground(color ? *color :
+#ifdef _WIN32
+ wxGetApp().get_label_clr_default());
+#else
+ wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
+#endif /* _WIN32 */
dc.DrawText(out_text, draw_pos);
dc.SetTextForeground(old_clr);
dc.SetFont(old_font);
diff --git a/src/slic3r/GUI/OG_CustomCtrl.hpp b/src/slic3r/GUI/OG_CustomCtrl.hpp
index 05119c2c1..965540250 100644
--- a/src/slic3r/GUI/OG_CustomCtrl.hpp
+++ b/src/slic3r/GUI/OG_CustomCtrl.hpp
@@ -63,7 +63,7 @@ class OG_CustomCtrl :public wxPanel
void render(wxDC& dc, wxCoord v_pos);
wxCoord draw_mode_bmp(wxDC& dc, wxCoord v_pos);
- wxCoord draw_text (wxDC& dc, wxPoint pos, const wxString& text, const wxColour* color, int width, bool is_url = false, bool align_right = false);
+ wxCoord draw_text (wxDC& dc, wxPoint pos, const wxString& text, const wxString& tooltip, const wxColour* color, int width, bool is_url = false, bool align_right = false);
wxPoint draw_blinking_bmp(wxDC& dc, wxPoint pos, bool is_blinking);
wxCoord draw_act_bmps(wxDC& dc, wxPoint pos, const wxBitmap& bmp_undo_to_sys, const wxBitmap& bmp_undo, bool is_blinking, size_t rect_id = 0);
bool launch_browser() const;
@@ -71,7 +71,7 @@ class OG_CustomCtrl :public wxPanel
std::vector<wxRect> rects_undo_icon;
std::vector<wxRect> rects_undo_to_sys_icon;
- wxRect rect_label;
+ std::vector<std::pair<wxRect, wxString>> rects_tooltip;
};
std::vector<CtrlLine> ctrl_lines;
diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp
index 52c0f0bb0..dc569c8a6 100644
--- a/src/slic3r/GUI/OptionsGroup.cpp
+++ b/src/slic3r/GUI/OptionsGroup.cpp
@@ -192,6 +192,13 @@ void OptionsGroup::append_line(const Line& line)
for (auto opt : option_set)
m_options.emplace(opt.opt_id, opt);
+ //if first control don't have a label, use the line one for hte tooltip
+ if (option_set.front().opt.label.empty() || "_" == option_set.front().opt.label) {
+ wxString tooltip = _(option_set.front().opt.tooltip);
+ update_Slic3r_string(tooltip);
+ m_lines.back().label_tooltip = tooltip;
+ }
+
// add mode value for current line to m_options_mode
if (!option_set.empty()){
m_line_sizer.emplace_back();
@@ -549,7 +556,14 @@ Line OptionsGroup::create_single_option_line(const Option& option, const std::st
update_Slic3r_string(tooltip);
Line retval{ _(option.opt.label), tooltip };
retval.label_path = path;
- retval.append_option(option);
+ if(option.opt.label.empty()) {
+ retval.append_option(option);
+ } else {
+ //remove label from option
+ Option tmp(option);
+ tmp.opt.label = std::string("");
+ retval.append_option(tmp);
+ }
return retval;
}
diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp
index 506caa471..eafafdffb 100644
--- a/src/slic3r/GUI/Tab.cpp
+++ b/src/slic3r/GUI/Tab.cpp
@@ -1915,6 +1915,7 @@ bool Tab::create_pages(std::string setting_type_name, int idx_page)
bool need_to_notified_search = false;
bool colored = false;
+ bool custom_label = false;
std::string label_path;
for (int i = 1; i < params.size() - 1; i++) {
if (params[i] == "simple")