Merge branch 'main' into enh-port-edit-gcode-dlg
This commit is contained in:
commit
9f44e151ba
32 changed files with 423 additions and 196 deletions
|
@ -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`
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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."
|
||||
|
|
|
@ -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"]
|
||||
}
|
|
@ -36,5 +36,6 @@
|
|||
"205x205",
|
||||
"0x205"
|
||||
],
|
||||
"printable_height": "200"
|
||||
"printable_height": "200",
|
||||
"nozzle_diameter": ["0.4"]
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
|
@ -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"
|
||||
}
|
|
@ -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"
|
||||
}
|
|
@ -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"
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 ¶ms);
|
||||
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 ¶ms);
|
||||
|
|
|
@ -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 ¶ms)
|
||||
{
|
||||
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
|
||||
|
|
|
@ -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 ¶ms) 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);
|
||||
|
|
|
@ -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(®ion - &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;
|
||||
}
|
||||
|
|
|
@ -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.);
|
||||
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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"))
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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()) {
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue