Merge branch 'main' into enh-port-edit-gcode-dlg

This commit is contained in:
Ocraftyone 2024-01-20 19:43:17 -05:00 committed by GitHub
commit 9f44e151ba
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
32 changed files with 423 additions and 196 deletions

View file

@ -68,6 +68,14 @@ Orca Slicer's logo is designed by community member Justin Levine(@freejstnalxndr
- Tools needed: Xcode, Cmake, git, gettext, libtool, automake, autoconf, texinfo
- You can install most of them by running `brew install cmake gettext libtool automake autoconf texinfo`
- run `build_release_macos.sh`
- To build and debug in XCode:
- run `XCode.app`
- open ``build_`arch`/OrcaSlicer.xcodeproj``
- menu bar: Product => Scheme => OrcaSlicer
- menu bar: Product => Scheme => Edit Scheme...
- Run => Info tab => Build Configuration: `RelWithDebInfo`
- Run => Options tab => Document Versions: uncheck `Allow debugging when browsing versions`
- menu bar: Product => Run
- Ubuntu
- Dependencies **Will be auto installed with the shell script**: `libmspack-dev libgstreamerd-3-dev libsecret-1-dev libwebkit2gtk-4.0-dev libosmesa6-dev libssl-dev libcurl4-openssl-dev eglexternalplatform-dev libudev-dev libdbus-1-dev extra-cmake-modules libgtk2.0-dev libglew-dev libudev-dev libdbus-1-dev cmake git texinfo`

View file

@ -12046,7 +12046,7 @@ msgstr ""
msgid ""
"We would rename the presets as \"Vendor Type Serial @printer you "
"selected\". \n"
"To add preset for more prinetrs, Please go to printer selection"
"To add preset for more printers, Please go to printer selection"
msgstr ""
msgid "Create Printer/Nozzle"

View file

@ -12756,7 +12756,7 @@ msgstr ""
msgid ""
"We would rename the presets as \"Vendor Type Serial @printer you "
"selected\". \n"
"To add preset for more prinetrs, Please go to printer selection"
"To add preset for more printers, Please go to printer selection"
msgstr ""
msgid "Create Printer/Nozzle"

View file

@ -12849,7 +12849,7 @@ msgstr ""
msgid ""
"We would rename the presets as \"Vendor Type Serial @printer you "
"selected\". \n"
"To add preset for more prinetrs, Please go to printer selection"
"To add preset for more printers, Please go to printer selection"
msgstr ""
msgid "Create Printer/Nozzle"

View file

@ -12473,7 +12473,7 @@ msgstr ""
msgid ""
"We would rename the presets as \"Vendor Type Serial @printer you "
"selected\". \n"
"To add preset for more prinetrs, Please go to printer selection"
"To add preset for more printers, Please go to printer selection"
msgstr ""
msgid "Create Printer/Nozzle"

View file

@ -12963,7 +12963,7 @@ msgstr ""
msgid ""
"We would rename the presets as \"Vendor Type Serial @printer you "
"selected\". \n"
"To add preset for more prinetrs, Please go to printer selection"
"To add preset for more printers, Please go to printer selection"
msgstr ""
msgid "Create Printer/Nozzle"

View file

@ -12775,7 +12775,7 @@ msgstr ""
msgid ""
"We would rename the presets as \"Vendor Type Serial @printer you "
"selected\". \n"
"To add preset for more prinetrs, Please go to printer selection"
"To add preset for more printers, Please go to printer selection"
msgstr ""
msgid "Create Printer/Nozzle"

View file

@ -7,7 +7,7 @@ msgstr ""
"Project-Id-Version: OrcaSlicer\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-01-13 17:34+0100\n"
"PO-Revision-Date: 2024-01-05 21:10+0300\n"
"PO-Revision-Date: 2024-01-19 01:16+0300\n"
"Last-Translator: Olcay ÖREN\n"
"Language-Team: Türkçe\n"
"Language: tr_TR\n"
@ -4546,6 +4546,9 @@ msgid ""
"Hint: Make sure you have added the corresponding printer before importing "
"the configs."
msgstr ""
"\n"
"İpucu: Yapılandırmaları içe aktarmadan önce ilgili yazıcıyı "
"eklediğinizden emin olun."
msgid "Import result"
msgstr "Sonucu içe aktar"
@ -7808,13 +7811,13 @@ msgid "Gizmo FDM paint-on seam"
msgstr "Gizmo FDM boyalı dikiş"
msgid "Gizmo Text emboss / engrave"
msgstr ""
msgstr "Gizmo Metin kabartma / kazıma"
msgid "Zoom in"
msgstr ""
msgstr "Yakınlaştır"
msgid "Zoom out"
msgstr ""
msgstr "Uzaklaştır"
msgid "Switch between Prepare/Preview"
msgstr "Hazırlama/Önizleme arasında geçiş yap"
@ -9245,7 +9248,7 @@ msgstr ""
"düşünün."
msgid "Don't filter out small internal bridges (experimental)"
msgstr ""
msgstr "Küçük iç köprüleri filtrelemeyin (deneysel)"
msgid ""
"This option can help reducing pillowing on top surfaces in heavily slanted "
@ -9275,15 +9278,41 @@ msgid ""
"overhang. This option is useful for heavily slanted top surface models. "
"However, in most cases it creates too many unecessary bridges."
msgstr ""
"Bu seçenek, aşırı eğimli veya kavisli modellerde üst yüzeylerdeki "
"yastıklamanın azaltılmasına yardımcı olabilir.\n"
"\n"
"Varsayılan olarak küçük iç köprüler filtrelenir ve iç katı dolgu "
"doğrudan seyrek dolgunun üzerine yazdırılır. Bu çoğu durumda işe yarar "
"ve üstün yüzey kalitesinden çok fazla ödün vermeden yazdırmayı "
"hızlandırır. \n"
"\n"
"Bununla birlikte, özellikle çok düşük seyrek dolgu yoğunluğunun kullanıldığı "
"aşırı eğimli veya kavisli modellerde, bu durum desteklenmeyen katı dolgunun "
"kıvrılmasına ve yastıklanmaya neden olmasına neden olabilir.\n"
"\n"
"Bu seçeneğin etkinleştirilmesi, iç köprü katmanını hafif desteklenmeyen "
"dahili katı dolgu üzerine yazdıracaktır. Aşağıdaki seçenekler filtreleme "
"miktarını, yani oluşturulan dahili köprülerin miktarını kontrol eder.\n"
"\n"
"Devre Dışı - Bu seçeneği devre dışı bırakır. Bu varsayılan davranıştır "
"ve çoğu durumda iyi çalışır.\n"
"\n"
"Sınırlı filtreleme - Aşırı eğimli yüzeylerde iç köprüler oluştururken "
"gereksiz iç köprülerin oluşmasını da önler. Bu, çoğu zor modelde "
"işe yarar.\n"
"\n"
"Filtreleme yok - Her potansiyel dahili çıkıntıda dahili köprüler "
"oluşturur. Bu seçenek, aşırı eğimli üst yüzey modelleri için kullanışlıdır. "
"Ancak çoğu durumda çok fazla gereksiz köprü oluşturur."
msgid "Disabled"
msgstr ""
msgstr "Devredışı"
msgid "Limited filtering"
msgstr ""
msgstr "Sınırlı filtreleme"
msgid "No filtering"
msgstr ""
msgstr "Filtresiz"
msgid "Max bridge length"
msgstr "Maksimum köprü uzunluğu"
@ -10365,10 +10394,10 @@ msgid "Klipper"
msgstr "Klipper"
msgid "Support multi bed types"
msgstr ""
msgstr "Çoklu tabla"
msgid "Enable this option if you want to use multiple bed types"
msgstr ""
msgstr "Birden fazla tabla tipi kullanmak istiyorsanız bu seçeneği etkinleştirin"
msgid "Label objects"
msgstr "Nesneleri etiketle"
@ -12368,7 +12397,7 @@ msgstr ""
"üzerinden yüzde olarak ifade edilir"
msgid "Minimum wall length"
msgstr ""
msgstr "Minimum duvar uzunluğu"
msgid ""
"Adjust this value to prevent short, unclosed walls from being printed, which "
@ -12380,6 +12409,14 @@ msgid ""
"top-surface. 'One wall threshold' is only visibile if this setting is set "
"above the default value of 0.5, or if single-wall top surfaces is enabled."
msgstr ""
"Yazdırma süresini artırabilecek kısa, kapatılmamış duvarların yazdırılmasını önlemek için "
"bu değeri ayarlayın. Daha yüksek değerler daha fazla ve daha uzun duvarları kaldırır.\n"
"\n"
"NOT: Modelin dış kısmında görsel boşluk kalmaması için alt ve üst "
"yüzeyler bu değerden etkilenmeyecektir. Üst yüzey olarak kabul edilen şeyin "
"hassasiyetini ayarlamak için aşağıdaki Gelişmiş ayarlarda "
"'Tek duvar eşiği'ni ayarlayın. 'Tek duvar eşiği' yalnızca bu ayar varsayılan değer olan "
"0,5'in üzerine ayarlandığında veya tek duvarlı üst yüzeyler etkinleştirildiğinde görünür."
msgid "First layer minimum wall width"
msgstr "İlk katman minimum duvar genişliği"
@ -13993,6 +14030,8 @@ msgstr ""
"Bu sistemde %s, sistem Sertifika Deposu veya Anahtar Zincirinden alınan "
"HTTPS sertifikalarını kullanıyor."
msgid ""
"To use a custom CA file, please import your CA file into Certificate Store / "
"Keychain."

View file

@ -8,5 +8,6 @@
"default_print_profile": "0.20mm Standard @Kingroon KP3S PRO S1",
"machine_end_gcode": "G1 E-1.0 F2100 ; retract\nG92 E0.0\nG1{if max_layer_z < max_print_height} Z{z_offset+min(max_layer_z+30, max_print_height)}{endif} E-34.0 F720 ; move print head up & retract filament\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y105 F3000 ; park print head\nM84 ; disable motors",
"machine_start_gcode": "G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM204 S[machine_max_acceleration_extruding] T[machine_max_acceleration_retracting]\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nG28 ; home all\nG1 Y1.0 Z0.3 F1000 ; move print head up\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG92 E0.0\n; initial load\n M117 Purge extruder\n G1 X2 Y20 Z0.3 F5000.0 ; move to start-line position\n G1 X2 Y175.0 Z0.3 F1500.0 E15 ; draw 1st line\n G1 X2 Y175.0 Z0.4 F5000.0 ; move to side a little\n G1 X2 Y20 Z0.4 F1500.0 E30 ; draw 2nd line\n G92 E0 ; reset extruder\n G1 Z1.0 F3000 ; move z up little to prevent scratching of surface",
"type": "machine"
"type": "machine",
"nozzle_diameter": ["0.4"]
}

View file

@ -36,5 +36,6 @@
"205x205",
"0x205"
],
"printable_height": "200"
"printable_height": "200",
"nozzle_diameter": ["0.4"]
}

View file

@ -7,5 +7,6 @@
"line_width": "0.4",
"inherits": "fdm_process_common",
"name": "0.08mm Standard @Kingroon KP3S PRO S1",
"print_settings_id": "0.08mm Standard @Kingroon KP3S PRO S1"
"print_settings_id": "0.08mm Standard @Kingroon KP3S PRO S1",
"instantiation": "true"
}

View file

@ -7,5 +7,6 @@
"layer_height": "0.12",
"line_width": "0.4",
"name": "0.12mm Standard @Kingroon KP3S PRO S1",
"print_settings_id": "0.12mm Standard @Kingroon KP3S PRO S1"
"print_settings_id": "0.12mm Standard @Kingroon KP3S PRO S1",
"instantiation": "true"
}

View file

@ -8,5 +8,6 @@
"name": "0.20mm Standard @Kingroon KP3S PRO S1",
"initial_layer_print_height": "0.2",
"layer_height": "0.2",
"line_width": "0.42"
"line_width": "0.42",
"instantiation": "true"
}

View file

@ -8,5 +8,6 @@
"print_settings_id": "0.20mm Standard @Kingroon KP3S PRO V2",
"initial_layer_print_height": "0.2",
"layer_height": "0.2",
"line_width": "0.42"
"line_width": "0.42",
"instantiation": "true"
}

View file

@ -67,7 +67,8 @@ Fill* Fill::new_from_type(const InfillPattern type)
// BBS: for internal solid infill only
case ipConcentricInternal: return new FillConcentricInternal();
// BBS: for bottom and top surface only
case ipMonotonicLine: return new FillMonotonicLineWGapFill();
// Orca: Replace BBS implementation with Prusa implementation
case ipMonotonicLine: return new FillMonotonicLines();
default: throw Slic3r::InvalidArgument("unknown type");
}
}
@ -173,6 +174,66 @@ void Fill::fill_surface_extrusion(const Surface* surface, const FillParams& para
for (size_t i = idx; i < eec->entities.size(); i++)
eec->entities[i]->set_reverse();
}
// Orca: run gap fill
this->_create_gap_fill(surface, params, eec);
}
}
// Orca: Dedicated function to calculate gap fill lines for the provided surface, according to the print object parameters
// and append them to the out ExtrusionEntityCollection.
void Fill::_create_gap_fill(const Surface* surface, const FillParams& params, ExtrusionEntityCollection* out){
//Orca: just to be safe, check against null pointer for the print object config and if NULL return.
if (this->print_object_config == nullptr) return;
// Orca: Enable gap fill as per the user preference. Return early if gap fill is to not be applied.
if ((this->print_object_config->gap_fill_target.value == gftNowhere) ||
(surface->surface_type == stInternalSolid && this->print_object_config->gap_fill_target.value != gftEverywhere))
return;
Flow new_flow = params.flow;
ExPolygons unextruded_areas;
unextruded_areas = diff_ex(this->no_overlap_expolygons, union_ex(out->polygons_covered_by_spacing(10)));
ExPolygons gapfill_areas = union_ex(unextruded_areas);
if (!this->no_overlap_expolygons.empty())
gapfill_areas = intersection_ex(gapfill_areas, this->no_overlap_expolygons);
if (gapfill_areas.size() > 0 && params.density >= 1) {
double min = 0.2 * new_flow.scaled_spacing() * (1 - INSET_OVERLAP_TOLERANCE);
double max = 2. * new_flow.scaled_spacing();
ExPolygons gaps_ex = diff_ex(
opening_ex(gapfill_areas, float(min / 2.)),
offset2_ex(gapfill_areas, -float(max / 2.), float(max / 2. + ClipperSafetyOffset)));
//BBS: sort the gap_ex to avoid mess travel
Points ordering_points;
ordering_points.reserve(gaps_ex.size());
ExPolygons gaps_ex_sorted;
gaps_ex_sorted.reserve(gaps_ex.size());
for (const ExPolygon &ex : gaps_ex)
ordering_points.push_back(ex.contour.first_point());
std::vector<Points::size_type> order2 = chain_points(ordering_points);
for (size_t i : order2)
gaps_ex_sorted.emplace_back(std::move(gaps_ex[i]));
ThickPolylines polylines;
for (ExPolygon& ex : gaps_ex_sorted) {
//BBS: Use DP simplify to avoid duplicated points and accelerate medial-axis calculation as well.
ex.douglas_peucker(SCALED_RESOLUTION * 0.1);
ex.medial_axis(min, max, &polylines);
}
if (!polylines.empty() && !is_bridge(params.extrusion_role)) {
polylines.erase(std::remove_if(polylines.begin(), polylines.end(),
[&](const ThickPolyline& p) {
return p.length() < scale_(params.config->filter_out_gap_fill.value);
}), polylines.end());
ExtrusionEntityCollection gap_fill;
variable_width(polylines, erGapFill, params.flow, gap_fill.entities);
auto gap = std::move(gap_fill.entities);
out->append(gap);
}
}
}

View file

@ -19,6 +19,7 @@
#include "../Flow.hpp"
#include "../ExtrusionEntity.hpp"
#include "../ExtrusionEntityCollection.hpp"
#include "../ShortestPath.hpp"
namespace Slic3r {
@ -106,6 +107,7 @@ public:
FillAdaptive::Octree* adapt_fill_octree = nullptr;
// PrintConfig and PrintObjectConfig are used by infills that use Arachne (Concentric and FillEnsuring).
// Orca: also used by gap fill function.
const PrintConfig *print_config = nullptr;
const PrintObjectConfig *print_object_config = nullptr;
@ -134,7 +136,7 @@ public:
// Perform the fill.
virtual Polylines fill_surface(const Surface *surface, const FillParams &params);
virtual ThickPolylines fill_surface_arachne(const Surface* surface, const FillParams& params);
// BBS: this method is used to fill the ExtrusionEntityCollection.
// It call fill_surface by default
virtual void fill_surface_extrusion(const Surface* surface, const FillParams& params, ExtrusionEntitiesPtr& out);
@ -172,6 +174,10 @@ protected:
virtual float _layer_angle(size_t idx) const { return (idx & 1) ? float(M_PI/2.) : 0; }
virtual std::pair<float, Point> _infill_direction(const Surface *surface) const;
// Orca: Dedicated function to calculate gap fill lines for the provided surface, according to the print object parameters
// and append them to the out ExtrusionEntityCollection.
void _create_gap_fill(const Surface* surface, const FillParams& params, ExtrusionEntityCollection* out);
public:
static void connect_infill(Polylines &&infill_ordered, const ExPolygon &boundary, Polylines &polylines_out, const double spacing, const FillParams &params);

View file

@ -3099,7 +3099,22 @@ Points sample_grid_pattern(const Polygons& polygons, coord_t spacing, const Boun
return sample_grid_pattern(union_ex(polygons), spacing, global_bounding_box);
}
void FillMonotonicLineWGapFill::fill_surface_extrusion(const Surface* surface, const FillParams& params, ExtrusionEntitiesPtr& out)
// Orca: Introduced FillMonotonicLines from Prusa slicer, inhereting from FillRectilinear
// This replaces the FillMonotonicLineWGapFill from BBS
Polylines FillMonotonicLines::fill_surface(const Surface *surface, const FillParams &params)
{
FillParams params2 = params;
params2.monotonic = true;
params2.anchor_length_max = 0.0f;
Polylines polylines_out;
if (! fill_surface_by_lines(surface, params2, 0.f, 0.f, polylines_out))
BOOST_LOG_TRIVIAL(error) << "FillMonotonicLines::fill_surface() failed to fill a region.";
return polylines_out;
}
// Orca: Replaced with FillMonotonicLines from Prusa slicer. Moved gap fill algorithm to
// FillBase to perform gap fill for all fill types.
/*void FillMonotonicLineWGapFill::fill_surface_extrusion(const Surface* surface, const FillParams& params, ExtrusionEntitiesPtr& out)
{
ExtrusionEntityCollection *coll_nosort = new ExtrusionEntityCollection();
coll_nosort->no_sort = this->no_sort();
@ -3274,7 +3289,7 @@ void FillMonotonicLineWGapFill::fill_surface_by_lines(const Surface* surface, co
//assert(! it->has_duplicate_points());
it->remove_duplicate_points();
}
}
}*/
} // namespace Slic3r

View file

@ -119,7 +119,19 @@ protected:
float _layer_angle(size_t idx) const override { return 0.f; }
};
class FillMonotonicLineWGapFill : public Fill
// Orca: Introduced FillMonotonicLines from Prusa slicer, inhereting from FillRectilinear
// This replaces the FillMonotonicLineWGapFill from BBS
class FillMonotonicLines : public FillRectilinear
{
public:
Fill* clone() const override { return new FillMonotonicLines(*this); }
~FillMonotonicLines() override = default;
Polylines fill_surface(const Surface *surface, const FillParams &params) override;
bool no_sort() const override { return true; }
};
//Orca: Replaced with FillMonotonicLines, inheriting from FillRectilinear
/*class FillMonotonicLineWGapFill : public Fill
{
public:
~FillMonotonicLineWGapFill() override = default;
@ -131,7 +143,7 @@ protected:
private:
void fill_surface_by_lines(const Surface* surface, const FillParams& params, Polylines& polylines_out);
};
};*/
Points sample_grid_pattern(const ExPolygon& expolygon, coord_t spacing, const BoundingBox& global_bounding_box);
Points sample_grid_pattern(const ExPolygons& expolygons, coord_t spacing, const BoundingBox& global_bounding_box);

View file

@ -4473,7 +4473,7 @@ static std::unique_ptr<EdgeGrid::Grid> calculate_layer_edge_grid(const Layer& la
}
std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, double speed)
std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, double speed, const ExtrusionEntitiesPtr& region_perimeters)
{
// get a copy; don't modify the orientation of the original loop object otherwise
// next copies (if any) would not detect the correct orientation
@ -4518,8 +4518,12 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
// extrude along the path
std::string gcode;
// Orca:
// Port of "wipe inside before extruding an external perimeter" feature from super slicer
if (m_config.wipe_before_external_loop.value && !paths.empty() && paths.front().size() > 1 && paths.back().size() > 1 && paths.front().role() == erExternalPerimeter) {
// If region perimeters size not greater than or equal to 2, then skip the wipe inside move as we will extrude in mid air
// as no neighbouring perimeter exists. If an internal perimeter exists, we should find 2 perimeters touching the de-retraction point
// 1 - the currently printed external perimeter and 2 - the neighbouring internal perimeter.
if (m_config.wipe_before_external_loop.value && !paths.empty() && paths.front().size() > 1 && paths.back().size() > 1 && paths.front().role() == erExternalPerimeter && region_perimeters.size() > 1) {
const bool is_full_loop_ccw = loop.polygon().is_counter_clockwise();
bool is_hole_loop = (loop.loop_role() & ExtrusionLoopRole::elrHole) != 0; // loop.make_counter_clockwise();
const double nozzle_diam = EXTRUDER_CONFIG(nozzle_diameter);
@ -4560,11 +4564,28 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
pt.rotate(angle, current_point);
pt = (current_pos + vec_dist * (2 * dist / vec_norm)).cast<coord_t>();
pt.rotate(angle, current_point);
// use extrude instead of travel_to_xy to trigger the unretract
ExtrusionPath fake_path_wipe(Polyline{pt, current_point}, paths.front());
fake_path_wipe.mm3_per_mm = 0;
gcode += extrude_path(fake_path_wipe, "move inwards before retraction/seam", speed);
// Search region perimeters for lines that are touching the de-retraction point.
// If an internal perimeter exists, we should find 2 perimeters touching the de-retraction point
// 1: the currently printed external perimeter and 2: the neighbouring internal perimeter.
int discoveredTouchingLines = 0;
for (const ExtrusionEntity* ee : region_perimeters){
auto potential_touching_line = ee->as_polyline();
AABBTreeLines::LinesDistancer<Line> potential_touching_line_distancer{potential_touching_line.lines()};
auto touching_line = potential_touching_line_distancer.all_lines_in_radius(pt, scale_(nozzle_diam));
if(touching_line.size()){
discoveredTouchingLines ++;
if(discoveredTouchingLines > 1) break; // found 2 touching lines. End the search early.
}
}
// found 2 perimeters touching the de-retraction point. Its safe to deretract as the point will be
// inside the model
if(discoveredTouchingLines > 1){
// use extrude instead of travel_to_xy to trigger the unretract
ExtrusionPath fake_path_wipe(Polyline{pt, current_point}, paths.front());
fake_path_wipe.mm3_per_mm = 0;
gcode += extrude_path(fake_path_wipe, "move inwards before retraction/seam", speed);
}
}
@ -4657,14 +4678,14 @@ std::string GCode::extrude_multi_path(ExtrusionMultiPath multipath, std::string
return gcode;
}
std::string GCode::extrude_entity(const ExtrusionEntity &entity, std::string description, double speed)
std::string GCode::extrude_entity(const ExtrusionEntity &entity, std::string description, double speed, const ExtrusionEntitiesPtr& region_perimeters)
{
if (const ExtrusionPath* path = dynamic_cast<const ExtrusionPath*>(&entity))
return this->extrude_path(*path, description, speed);
else if (const ExtrusionMultiPath* multipath = dynamic_cast<const ExtrusionMultiPath*>(&entity))
return this->extrude_multi_path(*multipath, description, speed);
else if (const ExtrusionLoop* loop = dynamic_cast<const ExtrusionLoop*>(&entity))
return this->extrude_loop(*loop, description, speed);
return this->extrude_loop(*loop, description, speed, region_perimeters);
else
throw Slic3r::InvalidArgument("Invalid argument supplied to extrude()");
return "";
@ -4691,7 +4712,7 @@ std::string GCode::extrude_perimeters(const Print &print, const std::vector<Obje
m_config.apply(print.get_print_region(&region - &by_region.front()).config());
for (const ExtrusionEntity* ee : region.perimeters)
gcode += this->extrude_entity(*ee, "perimeter", -1.);
gcode += this->extrude_entity(*ee, "perimeter", -1., region.perimeters);
}
return gcode;
}

View file

@ -348,8 +348,12 @@ private:
std::string preamble();
// BBS
std::string change_layer(coordf_t print_z);
std::string extrude_entity(const ExtrusionEntity &entity, std::string description = "", double speed = -1.);
std::string extrude_loop(ExtrusionLoop loop, std::string description, double speed = -1.);
// Orca: pass the complete collection of region perimeters to the extrude loop to check whether the wipe before external loop
// should be executed
std::string extrude_entity(const ExtrusionEntity &entity, std::string description = "", double speed = -1., const ExtrusionEntitiesPtr& region_perimeters = ExtrusionEntitiesPtr());
// Orca: pass the complete collection of region perimeters to the extrude loop to check whether the wipe before external loop
// should be executed
std::string extrude_loop(ExtrusionLoop loop, std::string description, double speed = -1., const ExtrusionEntitiesPtr& region_perimeters = ExtrusionEntitiesPtr());
std::string extrude_multi_path(ExtrusionMultiPath multipath, std::string description = "", double speed = -1.);
std::string extrude_path(ExtrusionPath path, std::string description = "", double speed = -1.);

View file

@ -768,10 +768,10 @@ bool Preset::has_cali_lines(PresetBundle* preset_bundle)
static std::vector<std::string> s_Preset_print_options {
"layer_height", "initial_layer_print_height", "wall_loops", "alternate_extra_wall", "slice_closing_radius", "spiral_mode", "spiral_mode_smooth", "spiral_mode_max_xy_smoothing", "slicing_mode",
"top_shell_layers", "top_shell_thickness", "bottom_shell_layers", "bottom_shell_thickness",
"extra_perimeters_on_overhangs", "ensure_vertical_shell_thickness", "reduce_crossing_wall", "detect_thin_wall", "detect_overhang_wall", "overhang_reverse", "overhang_reverse_threshold","overhang_reverse_internal_only",
"extra_perimeters_on_overhangs", "ensure_vertical_shell_thickness","reduce_wall_solid_infill", "reduce_crossing_wall", "detect_thin_wall", "detect_overhang_wall", "overhang_reverse", "overhang_reverse_threshold","overhang_reverse_internal_only",
"seam_position", "staggered_inner_seams", "wall_sequence", "is_infill_first", "sparse_infill_density", "sparse_infill_pattern", "top_surface_pattern", "bottom_surface_pattern",
"infill_direction",
"minimum_sparse_infill_area", "reduce_infill_retraction","internal_solid_infill_pattern",
"minimum_sparse_infill_area", "reduce_infill_retraction","internal_solid_infill_pattern","gap_fill_target",
"ironing_type", "ironing_pattern", "ironing_flow", "ironing_speed", "ironing_spacing", "ironing_angle",
"max_travel_detour_distance",
"fuzzy_skin", "fuzzy_skin_thickness", "fuzzy_skin_point_distance", "fuzzy_skin_first_layer",
@ -1125,11 +1125,6 @@ void PresetCollection::load_presets(
std::string version_str = key_values[BBL_JSON_KEY_VERSION];
boost::optional<Semver> version = Semver::parse(version_str);
if (!version) continue;
Semver app_version = *(Semver::parse(SLIC3R_VERSION));
if ( version->maj() != app_version.maj()) {
BOOST_LOG_TRIVIAL(warning) << "Preset incompatibla, not loading: " << name;
continue;
}
preset.version = *version;
if (key_values.find(BBL_JSON_KEY_FILAMENT_ID) != key_values.end())
@ -1574,11 +1569,6 @@ bool PresetCollection::load_user_preset(std::string name, std::map<std::string,
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format("invalid version %1%, not loading for user preset %2%")%version_str %name;
return false;
}
Semver app_version = *(Semver::parse(SLIC3R_VERSION));
if ( cloud_version->maj() != app_version.maj()) {
BOOST_LOG_TRIVIAL(warning)<< __FUNCTION__ << boost::format("version %1% mismatch with app version %2%, not loading for user preset %3%")%version_str %SLIC3R_VERSION %name;
return false;
}
//setting_id
if (preset_values.find(BBL_JSON_KEY_SETTING_ID) == preset_values.end()) {

View file

@ -768,11 +768,6 @@ bool PresetBundle::import_json_presets(PresetsConfigSubstitutions & s
std::string version_str = key_values[BBL_JSON_KEY_VERSION];
boost::optional<Semver> version = Semver::parse(version_str);
if (!version) return false;
Semver app_version = *(Semver::parse(SoftFever_VERSION));
if (version->maj() != app_version.maj()) {
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << " Preset incompatibla, not loading: " << name;
return false;
}
PresetCollection *collection = nullptr;
if (config.has("printer_settings_id"))

View file

@ -248,6 +248,7 @@ static t_config_enum_values s_keys_map_SeamPosition {
};
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(SeamPosition)
// Orca
static t_config_enum_values s_keys_map_InternalBridgeFilter {
{ "disabled", ibfDisabled },
{ "limited", ibfLimited },
@ -255,6 +256,14 @@ static t_config_enum_values s_keys_map_InternalBridgeFilter {
};
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(InternalBridgeFilter)
// Orca
static t_config_enum_values s_keys_map_GapFillTarget {
{ "everywhere", gftEverywhere },
{ "topbottom", gftTopBottom },
{ "nowhere", gftNowhere },
};
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(GapFillTarget)
static const t_config_enum_values s_keys_map_SLADisplayOrientation = {
{ "landscape", sladoLandscape},
{ "portrait", sladoPortrait}
@ -752,6 +761,26 @@ void PrintConfigDef::init_fff_params()
def->sidetext = L("mm");
def->min = 0;
def->set_default_value(new ConfigOptionFloat(0.));
def = this->add("gap_fill_target", coEnum);
def->label = L("Apply gap fill");
def->category = L("Strength");
def->tooltip = L("Enables gap fill for the selected surfaces. The minimum gap length that will be filled can be controlled "
"from the filter out tiny gaps option below.\n\n"
"Options:\n"
"1. Everywhere: Applies gap fill to top, bottom and internal solid surfaces\n"
"2. Top and Bottom surfaces: Applies gap fill to top and bottom surfaces only\n"
"3. Nowhere: Disables gap fill\n");
def->enum_keys_map = &ConfigOptionEnum<GapFillTarget>::get_enum_values();
def->enum_values.push_back("everywhere");
def->enum_values.push_back("topbottom");
def->enum_values.push_back("nowhere");
def->enum_labels.push_back(L("Everywhere"));
def->enum_labels.push_back(L("Top and bottom surfaces"));
def->enum_labels.push_back(L("Nowhere"));
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionEnum<GapFillTarget>(gftEverywhere));
def = this->add("enable_overhang_bridge_fan", coBools);
def->label = L("Force cooling for overhang and bridge");
@ -1297,6 +1326,16 @@ void PrintConfigDef::init_fff_params()
"(top+bottom solid layers)");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(true));
def = this->add("reduce_wall_solid_infill", coBool);
def->label = L("Further reduce solid infill on walls (experimental)");
def->category = L("Strength");
def->tooltip = L("Further reduces any solid infill applied to walls. As there will be very limited infill supporting"
" solid surfaces, make sure that you are using adequate number of walls to support the part on sloping surfaces.\n\n"
"For heavily sloped surfaces this option is not suitable as it will generate too thin of a top layer "
"and should be disabled.");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(false));
auto def_top_fill_pattern = def = this->add("top_surface_pattern", coEnum);
def->label = L("Top surface pattern");

View file

@ -152,10 +152,17 @@ enum SeamPosition {
spNearest, spAligned, spRear, spRandom
};
//Orca
enum InternalBridgeFilter {
ibfDisabled, ibfLimited, ibfNofilter
};
//Orca
enum GapFillTarget {
gftEverywhere, gftTopBottom, gftNowhere
};
enum LiftType {
NormalLift,
SpiralLift,
@ -789,6 +796,7 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionPercent, tree_support_top_rate))
((ConfigOptionFloat, tree_support_branch_diameter_organic))
((ConfigOptionFloat, tree_support_branch_angle_organic))
((ConfigOptionEnum<GapFillTarget>,gap_fill_target))
((ConfigOptionFloat, min_length_factor))
// Move all acceleration and jerk settings to object
@ -824,6 +832,7 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionFloat, bridge_speed))
((ConfigOptionFloatOrPercent, internal_bridge_speed))
((ConfigOptionBool, ensure_vertical_shell_thickness))
((ConfigOptionBool, reduce_wall_solid_infill))
((ConfigOptionEnum<InfillPattern>, top_surface_pattern))
((ConfigOptionEnum<InfillPattern>, bottom_surface_pattern))
((ConfigOptionEnum<InfillPattern>, internal_solid_infill_pattern))

View file

@ -449,17 +449,6 @@ void PrintObject::prepare_infill()
} // for each region
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
// this will detect bridges and reverse bridges
// and rearrange top/bottom/internal surfaces
// It produces enlarged overlapping bridging areas.
//
// 1) stBottomBridge / stBottom infill is grown by 3mm and clipped by the total infill area. Bridges are detected. The areas may overlap.
// 2) stTop is grown by 3mm and clipped by the grown bottom areas. The areas may overlap.
// 3) Clip the internal surfaces by the grown top/bottom surfaces.
// 4) Merge surfaces with the same style. This will mostly get rid of the overlaps.
//FIXME This does not likely merge surfaces, which are supported by a material with different colors, but same properties.
this->process_external_surfaces();
m_print->throw_if_canceled();
// Debugging output.
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
@ -478,9 +467,23 @@ void PrintObject::prepare_infill()
// and to add a configurable number of solid layers above the BOTTOM / BOTTOMBRIDGE surfaces
// to close these surfaces reliably.
//FIXME Vojtech: Is this a good place to add supporting infills below sloping perimeters?
// Orca: Brought this function call before the process_external_surfaces, to allow bridges over holes to expand more than
// one perimeter. Example of this is the bridge over the benchy lettering.
this->discover_horizontal_shells();
m_print->throw_if_canceled();
// this will detect bridges and reverse bridges
// and rearrange top/bottom/internal surfaces
// It produces enlarged overlapping bridging areas.
//
// 1) stBottomBridge / stBottom infill is grown by 3mm and clipped by the total infill area. Bridges are detected. The areas may overlap.
// 2) stTop is grown by 3mm and clipped by the grown bottom areas. The areas may overlap.
// 3) Clip the internal surfaces by the grown top/bottom surfaces.
// 4) Merge surfaces with the same style. This will mostly get rid of the overlaps.
//FIXME This does not likely merge surfaces, which are supported by a material with different colors, but same properties.
this->process_external_surfaces();
m_print->throw_if_canceled();
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
for (size_t region_id = 0; region_id < this->num_printing_regions(); ++ region_id) {
for (const Layer *layer : m_layers) {
@ -3224,7 +3227,10 @@ void PrintObject::discover_horizontal_shells()
// No internal solid needed on this layer. In order to decide whether to continue
// searching on the next neighbor (thus enforcing the configured number of solid
// layers, use different strategies according to configured infill density:
if (region_config.sparse_infill_density.value == 0) {
// Orca: Also use the same strategy if the user has selected to further reduce
// the amount of solid infill on walls.
if (region_config.sparse_infill_density.value == 0 || region_config.reduce_wall_solid_infill) {
// If user expects the object to be void (for example a hollow sloping vase),
// don't continue the search. In this case, we only generate the external solid
// shell if the object would otherwise show a hole (gap between perimeters of
@ -3237,12 +3243,19 @@ void PrintObject::discover_horizontal_shells()
}
}
if (region_config.sparse_infill_density.value == 0) {
if (region_config.sparse_infill_density.value == 0 || region_config.reduce_wall_solid_infill) {
// if we're printing a hollow object we discard any solid shell thinner
// than a perimeter width, since it's probably just crossing a sloping wall
// and it's not wanted in a hollow print even if it would make sense when
// obeying the solid shell count option strictly (DWIM!)
float margin = float(neighbor_layerm->flow(frExternalPerimeter).scaled_width());
// Orca: Also use the same strategy if the user has selected to reduce
// the amount of solid infill on walls. However reduce the margin to 20% overhang
// as we want to generate infill on sloped vertical surfaces but still keep a small amount of
// filtering. This is an arbitrary value to make this option safe
// by ensuring that top surfaces, especially slanted ones dont go **completely** unsupported
// especially when using single perimeter top layers.
float margin = region_config.reduce_wall_solid_infill? float(neighbor_layerm->flow(frExternalPerimeter).scaled_width()) * 0.2f : float(neighbor_layerm->flow(frExternalPerimeter).scaled_width());
Polygons too_narrow = diff(
new_internal_solid,
opening(new_internal_solid, margin, margin + ClipperSafetyOffset, jtMiter, 5));

View file

@ -510,6 +510,18 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
apply(config, &new_conf);
}
// Orca: Hide the filter out tiny gaps field when gap fill target is nowhere as no gap fill will be applied.
bool have_gap_fill = config->opt_enum<GapFillTarget>("gap_fill_target") != gftNowhere;
toggle_line("filter_out_gap_fill", have_gap_fill);
bool have_ensure_vertical_thickness = config->opt_bool("ensure_vertical_shell_thickness");
if(have_ensure_vertical_thickness) {
DynamicPrintConfig new_conf = *config;
new_conf.set_key_value("reduce_wall_solid_infill", new ConfigOptionBool(false));
apply(config, &new_conf);
}
toggle_line("reduce_wall_solid_infill",!have_ensure_vertical_thickness);
bool have_perimeters = config->opt_int("wall_loops") > 0;
for (auto el : { "extra_perimeters_on_overhangs", "ensure_vertical_shell_thickness", "detect_thin_wall", "detect_overhang_wall",
"seam_position", "staggered_inner_seams", "wall_sequence", "outer_wall_line_width",

View file

@ -1181,7 +1181,7 @@ void CreateFilamentPresetDialog::select_curr_radiobox(std::vector<std::pair<Radi
m_filament_preset_combobox->SetLabelColor(DEFAULT_PROMPT_TEXT_COLOUR);
}
} else if (curr_selected_type == m_create_type.base_filament_preset) {
m_filament_preset_text->SetLabel(_L("We would rename the presets as \"Vendor Type Serial @printer you selected\". \nTo add preset for more prinetrs, Please go to printer selection"));
m_filament_preset_text->SetLabel(_L("We would rename the presets as \"Vendor Type Serial @printer you selected\". \nTo add preset for more printers, Please go to printer selection"));
m_filament_preset_combobox->Hide();
if (_L("Select Type") != m_filament_type_combobox->GetLabel()) {

View file

@ -74,10 +74,10 @@ std::string GLGizmoScale3D::get_tooltip() const
return "";
}
void GLGizmoScale3D::enable_ununiversal_scale(bool enable)
static int constraint_id(int grabber_id)
{
for (unsigned int i = 0; i < 6; ++i)
m_grabbers[i].enabled = enable;
static const std::vector<int> id_map = { 1, 0, 3, 2, 5, 4, 8, 9, 6, 7 };
return (0 <= grabber_id && grabber_id < (int)id_map.size()) ? id_map[grabber_id] : -1;
}
bool GLGizmoScale3D::on_mouse(const wxMouseEvent &mouse_event)
@ -99,12 +99,27 @@ bool GLGizmoScale3D::on_mouse(const wxMouseEvent &mouse_event)
transformation_type.set_independent();
selection.scale(m_scale, transformation_type);
if (mouse_event.CmdDown()) selection.translate(m_offset, transformation_type);
if (m_starting.ctrl_down && m_hover_id < 6) {
// constrained scale:
// uses the performed scale to calculate the new position of the constrained grabber
// and from that calculates the offset (in world coordinates) to be applied to fullfill the constraint
update_render_data();
const Vec3d constraint_position = m_grabbers[constraint_id(m_hover_id)].center;
// re-apply the scale because the selection always applies the transformations with respect to the initial state
// set into on_start_dragging() with the call to selection.setup_cache()
m_parent.get_selection().scale_and_translate(m_scale, m_starting.pivots[m_hover_id] - constraint_position, transformation_type);
}
}
}
return use_grabbers(mouse_event);
}
void GLGizmoScale3D::enable_ununiversal_scale(bool enable)
{
for (unsigned int i = 0; i < 6; ++i)
m_grabbers[i].enabled = enable;
}
void GLGizmoScale3D::data_changed(bool is_serializing) {
const Selection &selection = m_parent.get_selection();
bool enable_scale_xyz = selection.is_single_full_instance() ||
@ -156,19 +171,20 @@ void GLGizmoScale3D::on_start_dragging()
m_starting.plane_center = m_grabbers[4].center;
m_starting.plane_nromal = m_grabbers[5].center - m_grabbers[4].center;
m_starting.ctrl_down = wxGetKeyState(WXK_CONTROL);
m_starting.box = (m_starting.ctrl_down && (m_hover_id < 6)) ? m_box : m_parent.get_selection().get_bounding_box();
m_starting.box = m_box;
const Vec3d& center = m_starting.box.center();
m_starting.pivots[0] = m_transform * Vec3d(m_starting.box.max.x(), center.y(), center.z());
m_starting.pivots[1] = m_transform * Vec3d(m_starting.box.min.x(), center.y(), center.z());
m_starting.pivots[2] = m_transform * Vec3d(center.x(), m_starting.box.max.y(), center.z());
m_starting.pivots[3] = m_transform * Vec3d(center.x(), m_starting.box.min.y(), center.z());
m_starting.pivots[4] = m_transform * Vec3d(center.x(), center.y(), m_starting.box.max.z());
m_starting.pivots[5] = m_transform * Vec3d(center.x(), center.y(), m_starting.box.min.z());
m_starting.pivots[0] = m_grabbers[1].center;
m_starting.pivots[1] = m_grabbers[0].center;
m_starting.pivots[2] = m_grabbers[3].center;
m_starting.pivots[3] = m_grabbers[2].center;
m_starting.pivots[4] = m_grabbers[5].center;
m_starting.pivots[5] = m_grabbers[4].center;
}
void GLGizmoScale3D::on_stop_dragging() {
void GLGizmoScale3D::on_stop_dragging()
{
m_parent.do_scale(L("Gizmo-Scale"));
m_starting.ctrl_down = false;
}
void GLGizmoScale3D::on_dragging(const UpdateData& data)
@ -185,97 +201,14 @@ void GLGizmoScale3D::on_dragging(const UpdateData& data)
void GLGizmoScale3D::on_render()
{
const Selection& selection = m_parent.get_selection();
bool single_instance = selection.is_single_full_instance();
bool single_volume = selection.is_single_volume_or_modifier();
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
glsafe(::glEnable(GL_DEPTH_TEST));
m_box.reset();
m_transform = Transform3d::Identity();
// Transforms grabbers' offsets to world refefence system
Transform3d offsets_transform = Transform3d::Identity();
m_offsets_transform = Transform3d::Identity();
Vec3d angles = Vec3d::Zero();
if (single_instance) {
// calculate bounding box in instance local reference system
const Selection::IndicesList& idxs = selection.get_volume_idxs();
for (unsigned int idx : idxs) {
const GLVolume* vol = selection.get_volume(idx);
m_box.merge(vol->bounding_box().transformed(vol->get_volume_transformation().get_matrix()));
}
// gets transform from first selected volume
const GLVolume* v = selection.get_first_volume();
m_transform = v->get_instance_transformation().get_matrix();
// gets angles from first selected volume
angles = v->get_instance_rotation();
// consider rotation+mirror only components of the transform for offsets
offsets_transform = Geometry::assemble_transform(Vec3d::Zero(), angles, Vec3d::Ones(), v->get_instance_mirror());
m_offsets_transform = offsets_transform;
}
else if (single_volume) {
const GLVolume* v = selection.get_first_volume();
m_box = v->bounding_box();
m_transform = v->world_matrix();
angles = Geometry::extract_euler_angles(m_transform);
// consider rotation+mirror only components of the transform for offsets
offsets_transform = Geometry::assemble_transform(Vec3d::Zero(), angles, Vec3d::Ones(), v->get_instance_mirror());
m_offsets_transform = Geometry::assemble_transform(Vec3d::Zero(), v->get_volume_rotation(), Vec3d::Ones(), v->get_volume_mirror());
}
else
m_box = selection.get_bounding_box();
const Vec3d& center = m_box.center();
const Vec3d offset_x = offsets_transform * Vec3d((double)Offset, 0.0, 0.0);
const Vec3d offset_y = offsets_transform * Vec3d(0.0, (double)Offset, 0.0);
const Vec3d offset_z = offsets_transform * Vec3d(0.0, 0.0, (double)Offset);
const bool ctrl_down = (m_dragging && m_starting.ctrl_down) || (!m_dragging && wxGetKeyState(WXK_CONTROL));
// x axis
m_grabbers[0].center = m_transform * Vec3d(m_box.min.x(), center.y(), m_box.min.z());
m_grabbers[1].center = m_transform * Vec3d(m_box.max.x(), center.y(), m_box.min.z());
// y axis
m_grabbers[2].center = m_transform * Vec3d(center.x(), m_box.min.y(), m_box.min.z());
m_grabbers[3].center = m_transform * Vec3d(center.x(), m_box.max.y(), m_box.min.z());
// z axis do not show 4
m_grabbers[4].center = m_transform * Vec3d(center.x(), center.y(), m_box.min.z());
m_grabbers[4].enabled = false;
m_grabbers[5].center = m_transform * Vec3d(center.x(), center.y(), m_box.max.z());
// uniform
m_grabbers[6].center = m_transform * Vec3d(m_box.min.x(), m_box.min.y(), m_box.min.z());
m_grabbers[7].center = m_transform * Vec3d(m_box.max.x(), m_box.min.y(), m_box.min.z());
m_grabbers[8].center = m_transform * Vec3d(m_box.max.x(), m_box.max.y(), m_box.min.z());
m_grabbers[9].center = m_transform * Vec3d(m_box.min.x(), m_box.max.y(), m_box.min.z());
for (int i = 0; i < 6; ++i) {
m_grabbers[i].color = AXES_COLOR[i/2];
m_grabbers[i].hover_color = AXES_HOVER_COLOR[i/2];
}
for (int i = 6; i < 10; ++i) {
m_grabbers[i].color = GRABBER_UNIFORM_COL;
m_grabbers[i].hover_color = GRABBER_UNIFORM_HOVER_COL;
}
// sets grabbers orientation
for (int i = 0; i < 10; ++i) {
m_grabbers[i].angles = angles;
}
update_render_data();
glsafe(::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f));
const BoundingBoxf3& selection_box = selection.get_bounding_box();
const float grabber_mean_size = (float)((selection_box.size().x() + selection_box.size().y() + selection_box.size().z()) / 3.0);
const float grabber_mean_size = (float) ((m_box.size().x() + m_box.size().y() + m_box.size().z()) / 3.0);
//draw connections
GLShaderProgram* shader = wxGetApp().get_shader("flat");
@ -370,35 +303,17 @@ void GLGizmoScale3D::do_scale_along_axis(Axis axis, const UpdateData& data)
{
double ratio = calc_ratio(data);
if (ratio > 0.0) {
m_scale(axis) = m_starting.scale(axis) * ratio;
if (m_starting.ctrl_down) {
double local_offset = 0.5 * (m_scale(axis) - m_starting.scale(axis)) * m_starting.box.size()(axis);
if (m_hover_id == 2 * axis)
local_offset *= -1.0;
Vec3d local_offset_vec;
switch (axis)
{
case X: { local_offset_vec = local_offset * Vec3d::UnitX(); break; }
case Y: { local_offset_vec = local_offset * Vec3d::UnitY(); break; }
case Z: { local_offset_vec = local_offset * Vec3d::UnitZ(); break; }
default: break;
}
m_offset = m_offsets_transform * local_offset_vec;
}
else
m_offset = Vec3d::Zero();
Vec3d curr_scale = m_scale;
curr_scale(axis) = m_starting.scale(axis) * ratio;
m_scale = curr_scale;
}
}
void GLGizmoScale3D::do_scale_uniform(const UpdateData & data)
{
const double ratio = calc_ratio(data);
if (ratio > 0.0) {
if (ratio > 0.0)
m_scale = m_starting.scale * ratio;
m_offset = Vec3d::Zero();
}
}
double GLGizmoScale3D::calc_ratio(const UpdateData& data) const
@ -436,5 +351,78 @@ double GLGizmoScale3D::calc_ratio(const UpdateData& data) const
return ratio;
}
void GLGizmoScale3D::update_render_data()
{
const Selection& selection = m_parent.get_selection();
bool single_instance = selection.is_single_full_instance();
bool single_volume = selection.is_single_volume_or_modifier();
m_box.reset();
m_transform = Transform3d::Identity();
Vec3d angles = Vec3d::Zero();
if (single_instance) {
// calculate bounding box in instance local reference system
const Selection::IndicesList& idxs = selection.get_volume_idxs();
for (unsigned int idx : idxs) {
const GLVolume* vol = selection.get_volume(idx);
m_box.merge(vol->bounding_box().transformed(vol->get_volume_transformation().get_matrix()));
}
// gets transform from first selected volume
const GLVolume* v = selection.get_first_volume();
m_transform = v->get_instance_transformation().get_matrix();
// gets angles from first selected volume
angles = v->get_instance_rotation();
}
else if (single_volume) {
const GLVolume* v = selection.get_first_volume();
m_box = v->bounding_box();
m_transform = v->world_matrix();
angles = Geometry::extract_euler_angles(m_transform);
}
else
m_box = selection.get_bounding_box();
const Vec3d& center = m_box.center();
// x axis
m_grabbers[0].center = m_transform * Vec3d(m_box.min.x(), center.y(), m_box.min.z());
m_grabbers[1].center = m_transform * Vec3d(m_box.max.x(), center.y(), m_box.min.z());
// y axis
m_grabbers[2].center = m_transform * Vec3d(center.x(), m_box.min.y(), m_box.min.z());
m_grabbers[3].center = m_transform * Vec3d(center.x(), m_box.max.y(), m_box.min.z());
// z axis do not show 4
m_grabbers[4].center = m_transform * Vec3d(center.x(), center.y(), m_box.min.z());
m_grabbers[4].enabled = false;
m_grabbers[5].center = m_transform * Vec3d(center.x(), center.y(), m_box.max.z());
// uniform
m_grabbers[6].center = m_transform * Vec3d(m_box.min.x(), m_box.min.y(), m_box.min.z());
m_grabbers[7].center = m_transform * Vec3d(m_box.max.x(), m_box.min.y(), m_box.min.z());
m_grabbers[8].center = m_transform * Vec3d(m_box.max.x(), m_box.max.y(), m_box.min.z());
m_grabbers[9].center = m_transform * Vec3d(m_box.min.x(), m_box.max.y(), m_box.min.z());
for (int i = 0; i < 6; ++i) {
m_grabbers[i].color = AXES_COLOR[i/2];
m_grabbers[i].hover_color = AXES_HOVER_COLOR[i/2];
}
for (int i = 6; i < 10; ++i) {
m_grabbers[i].color = GRABBER_UNIFORM_COL;
m_grabbers[i].hover_color = GRABBER_UNIFORM_HOVER_COL;
}
// sets grabbers orientation
for (int i = 0; i < 10; ++i) {
m_grabbers[i].angles = angles;
}
}
} // namespace GUI
} // namespace Slic3r

View file

@ -34,10 +34,7 @@ class GLGizmoScale3D : public GLGizmoBase
BoundingBoxf3 m_box;
Transform3d m_transform;
// Transforms grabbers offsets to the proper reference system (world for instances, instance for volumes)
Transform3d m_offsets_transform;
Vec3d m_scale{ Vec3d::Ones() };
Vec3d m_offset{ Vec3d::Zero() };
double m_snap_step{ 0.05 };
StartingData m_starting;
@ -99,6 +96,7 @@ private:
void do_scale_uniform(const UpdateData& data);
double calc_ratio(const UpdateData& data) const;
void update_render_data();
};

View file

@ -2646,6 +2646,15 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
sidebar_layout.is_collapsed = !sidebar.IsShown();
}
// Keep tracking the current sidebar size, by storing it using `best_size`, which will be stored
// in the config and re-applied when the app is opened again.
this->sidebar->Bind(wxEVT_IDLE, [&sidebar, this](wxIdleEvent& e) {
if (sidebar.IsShown() && sidebar.IsDocked() && sidebar.rect.GetWidth() > 0) {
sidebar.BestSize(sidebar.rect.GetWidth(), sidebar.best_size.GetHeight());
}
e.Skip();
});
// Hide sidebar initially, will re-show it after initialization when we got proper window size
sidebar.Hide();
m_aui_mgr.Update();

View file

@ -2027,6 +2027,7 @@ void TabPrint::build()
optgroup->append_single_option_line("infill_anchor");
optgroup->append_single_option_line("infill_anchor_max");
optgroup->append_single_option_line("internal_solid_infill_pattern");
optgroup->append_single_option_line("gap_fill_target");
optgroup->append_single_option_line("filter_out_gap_fill");
optgroup = page->new_optgroup(L("Advanced"), L"param_advanced");
@ -2037,6 +2038,7 @@ void TabPrint::build()
optgroup->append_single_option_line("infill_combination");
optgroup->append_single_option_line("detect_narrow_internal_solid_infill");
optgroup->append_single_option_line("ensure_vertical_shell_thickness");
optgroup->append_single_option_line("reduce_wall_solid_infill");
page = add_options_page(L("Speed"), "empty");
optgroup = page->new_optgroup(L("Initial layer speed"), L"param_speed_first", 15);