Merge remote-tracking branch 'origin/main' into dev/gizmo

This commit is contained in:
Noisyfox 2023-11-10 09:57:11 +08:00
commit cf5c19fa24
19 changed files with 328 additions and 170 deletions

View file

@ -1787,10 +1787,10 @@ msgid "An SD card needs to be inserted before printing via LAN."
msgstr "Před tiskem přes LAN je třeba vložit SD kartu."
msgid "Sending gcode file over LAN"
msgstr "Odesílání souboru gcode přes LAN"
msgstr "Odesílání souboru gkód přes LAN"
msgid "Sending gcode file to sdcard"
msgstr "Odesílání souboru gcode na sdcard"
msgstr "Odesílání souboru gkód na sd kartu"
#, c-format, boost-format
msgid "Successfully sent. Close current page in %s s"
@ -2181,7 +2181,7 @@ msgid ""
"(Currently supporting automatic supply of consumables with the same brand, "
"material type, and color)"
msgstr ""
"Pokud v AMS existují dva identické filameny, bude povolena záloha AMS "
"Pokud v AMS existují dva identické filamenty, bude povolena záloha AMS "
"filamentu. \n"
"(Aktuálně podporuje automatické doplňování spotřebního materiálu stejné "
"značky, typu materiálu a barvy)"
@ -2333,7 +2333,7 @@ msgid ""
"Error message: %1%.\n"
"Source file %2%."
msgstr ""
"Soubor gcode se nepodařilo uložit.\n"
"Soubor gkód se nepodařilo uložit.\n"
"Chybová zpráva: %1%.\n"
"Zdrojový soubor %2%."
@ -2524,7 +2524,7 @@ msgstr ""
"typ časosběru je tradiční."
msgid " But machines with I3 structure will not generate timelapse videos."
msgstr " Ale stroje s I3 strukturou nevytvoří timelapse videa."
msgstr " Ale stroje s I3 strukturou nevytvářejí časosběrná videa."
msgid ""
"Change these settings automatically? \n"
@ -2645,7 +2645,7 @@ msgid "Calibrating the micro lida"
msgstr "Kalibrace mikro lida"
msgid "Calibrating extrusion flow"
msgstr "Kalibrace extruze průtpku"
msgstr "Kalibrace extruze průtoku"
msgid "Paused due to nozzle temperature malfunction"
msgstr "Pozastaveno kvůli poruše teploty trysky"
@ -3449,7 +3449,7 @@ msgid "Export current sliced file"
msgstr "Exportovat aktuální Slicovaný soubor"
msgid "Export all plate sliced file"
msgstr "Exportovat všechny soubor slicované na pdložce"
msgstr "Exportovat všechny soubor slicované na podložce"
msgid "Export G-code"
msgstr "Exportovat G-kód"
@ -4132,7 +4132,7 @@ msgid " upload config prase failed\n"
msgstr " nahrávání konfigurace se nepodařilo zpracovat\n"
msgid " No corresponding storage bucket\n"
msgstr " Žádný odpovídající úložný bucket\n"
msgstr " Žádný odpovídající úložný prostor\n"
msgid " can not be opened\n"
msgstr " nelze otevřít\n"
@ -4808,7 +4808,7 @@ msgid ""
"The loaded file contains gcode only, Can not enter the Prepare page"
msgstr ""
"Režim pouze náhled:\n"
"Načtený soubor obsahuje pouze gcode, nelze vstoupit na stránku Příprava"
"Načtený soubor obsahuje pouze gkód, nelze vstoupit na stránku Příprava"
msgid "You can keep the modified presets to the new project or discard them"
msgstr "Upravené předvolby si můžete ponechat pro nový projekt nebo je zahodit"
@ -4914,7 +4914,7 @@ msgid "The following characters are not allowed by a FAT file system:"
msgstr "Následující znaky nejsou v souborovém systému FAT povoleny:"
msgid "Save Sliced file as:"
msgstr "Uložit Slicované soubor jako:"
msgstr "Uložit Slicovaný soubor jako:"
#, c-format, boost-format
msgid ""
@ -4932,7 +4932,7 @@ msgstr ""
"kladné části."
msgid "Is the printer ready? Is the print sheet in place, empty and clean?"
msgstr "Je tiskarna připravená k tisku? Je podložka prázdná a čistá?"
msgstr "Je tiskárna připravená k tisku? Je podložka prázdná a čistá?"
msgid "Upload and Print"
msgstr "Nahrát a Tisknout"
@ -6226,7 +6226,7 @@ msgid "Jerk limitation"
msgstr "Omezení Jerk-Ryv"
msgid "Single extruder multimaterial setup"
msgstr "Nastavení multimaterialu s jedním extruderem"
msgstr "Nastavení multimateriálu s jedním extruderem"
msgid "Wipe tower"
msgstr "Čistící věž"
@ -6558,7 +6558,7 @@ msgid "Login"
msgstr "Přihlášení"
msgid "The configuration package is changed in previous Config Guide"
msgstr "Konfigurační balíček byl změněn v předchozím Config Guide"
msgstr "Konfigurační balíček byl změněn v předchozím průvodci konfigurací"
msgid "Configuration package changed"
msgstr "Konfigurační balíček změněn"
@ -8221,7 +8221,7 @@ msgid ""
msgstr ""
"Materiál může mít objemovou změnu po přepnutí mezi roztaveným a krystalickým "
"stavem. Toto nastavení proporcionálně změní veškerý vytlačovací tok tohoto "
"filamentu v gcode. Doporučený rozsah hodnot je mezi 0,95 a 1,05. Možná "
"filamentu v gkódu. Doporučený rozsah hodnot je mezi 0,95 a 1,05. Možná "
"můžete tuto hodnotu vyladit, abyste získali pěkně rovný povrch, když dochází "
"k mírnému přetečení nebo podtečení"
@ -8323,7 +8323,7 @@ msgid ""
"Filament diameter is used to calculate extrusion in gcode, so it's important "
"and should be accurate"
msgstr ""
"Průměr filamentu se používá k výpočtu vytlačování v gcode, takže je důležitý "
"Průměr filamentu se používá k výpočtu vytlačování v gkódu, takže je důležitý "
"a měl by být přesný"
msgid "Shrinkage"
@ -8337,7 +8337,7 @@ msgid ""
"Be sure to allow enough space between objects, as this compensation is done "
"after the checks."
msgstr ""
"Zadejte procento smrštění, které filament získá po ochlazení (94% pokud "
"Zadejte procento smrštění, které filament získá po ochlazení (94% i pokud "
"naměříte 94mm místo 100mm). Část bude pro kompenzaci zmenšena v xy. Bere se "
"v úvahu pouze filamentu použit pro obvod.\n"
"Ujistěte se aby byl mezi objekty dostatek prostoru, protože tato kompenzace "
@ -8431,7 +8431,7 @@ msgid ""
msgstr ""
"Doba, po kterou firmware tiskárny (nebo jednotka Multi Material 2.0) zavádí "
"nový filament během jeho výměny (při provádění kódu T). Tento čas je přidán "
"k celkové době tisku pomocí G-code odhadovače tiskového času."
"k celkové době tisku pomocí G-kódu odhadovače tiskového času."
msgid "Ramming parameters"
msgstr "Parametry rapidní extruze"
@ -8450,7 +8450,7 @@ msgid ""
msgstr ""
"Doba, po kterou firmware tiskárny (nebo jednotka Multi Material 2.0) vysouvá "
"filament během jeho výměny (při provádění kódu T). Tento čas je přidán k "
"celkové době tisku pomocí G-code odhadovače tiskového času."
"celkové době tisku pomocí G-kódu odhadovače tiskového času."
msgid "Enable ramming for multitool setups"
msgstr "Povolení rapidní extruze tiskárny s více nástroji"
@ -9037,7 +9037,7 @@ msgid "G-code flavor"
msgstr "Druh G-kódu"
msgid "What kind of gcode the printer is compatible with"
msgstr "S jakým typem gcode je tiskárna kompatibilní"
msgstr "S jakým typem gkódu je tiskárna kompatibilní"
msgid "Klipper"
msgstr "Klipper"
@ -9181,7 +9181,7 @@ msgstr ""
"použije výchozí metodu."
msgid "This gcode part is inserted at every layer change after lift z"
msgstr "Tato část gcode je vložena při každé změně vrstvy po zvednutí z"
msgstr "Tato část gkódu je vložena při každé změně vrstvy po zvednutí z"
msgid "Supports silent mode"
msgstr "Podporuje tichý režim"
@ -9198,7 +9198,7 @@ msgid ""
"pause G-code in gcode viewer"
msgstr ""
"Tento G-kód bude použit jako kód pro pozastavený tisk. Uživatel může vložit "
"pauzu G-kód do prohlížeče gcode"
"pauzu G-kód do prohlížeče gkódu"
msgid "This G-code will be used as a custom code"
msgstr "Tento G-kód bude použit jako vlastní kód"
@ -9669,7 +9669,7 @@ msgid ""
"resolution and more time to slice"
msgstr ""
"Cesta G-kódu se generuje po zjednodušení obrysu modelu, aby se předešlo "
"příliš velkému počtu bodů a Linek gcode v souboru gcode. Menší hodnota "
"příliš velkému počtu bodů a Linek gkódu v souboru gkód. Menší hodnota "
"znamená vyšší rozlišení a více času na slicování"
msgid "Travel distance threshold"
@ -9680,7 +9680,7 @@ msgid ""
"threshold"
msgstr ""
"Spusťte retrakci pouze tehdy, když je dráha jízdy delší než tato hraniční "
"hohnota"
"hodnota"
msgid "Retract amount before wipe"
msgstr "Délka retrakce před očištěním"
@ -9925,7 +9925,7 @@ msgid ""
"The printing speed in exported gcode will be slowed down, when the estimated "
"layer time is shorter than this value, to get better cooling for these layers"
msgstr ""
"Rychlost tisku v exportovaném kódu gcode se zpomalí, když je odhadovaná doba "
"Rychlost tisku v exportovaném kódu gkód se zpomalí, když je odhadovaná doba "
"vrstvy kratší než tato hodnota, aby se dosáhlo lepšího chlazení pro tyto "
"vrstvy"
@ -10089,7 +10089,7 @@ msgid ""
"print bed, set this to -0.3 (or fix your endstop)."
msgstr ""
"Tato hodnota bude přidána (nebo odečtena) ze všech souřadnic Z ve výstupním "
"G-code. Používá se ke kompenzování špatné pozice endstopu Z. Například pokud "
"G-kódu. Používá se ke kompenzování špatné pozice endstopu Z. Například pokud "
"endstop 0 skutečně ponechá trysku 0,3 mm daleko od tiskové podložky, "
"nastavte hodnotu -0,3 (nebo dolaďte svůj koncový doraz)."
@ -10283,7 +10283,7 @@ msgstr ""
"ušetří materiál a sníží poškození objektu.\n"
"Pro stromovou podpěru, tenký a organický styl bude agresivněji slučovat "
"větve a ušetří mnoho materiálu (výchozí organický), zatímco hybridní styl "
"vytvoří podobnou strukturu jako běžná podpěra pod velkými plochými převiy."
"vytvoří podobnou strukturu jako běžná podpěra pod velkými plochými převisy."
msgid "Snug"
msgstr "Přiléhavý"
@ -10390,7 +10390,7 @@ msgstr ""
"automaticky vypočítány"
msgid "Tree support brim width"
msgstr "Šířka Limce podpěr stromů"
msgstr "Šířka Límce podpěr stromů"
msgid "Distance from tree branch to the outermost brim line"
msgstr "Vzdálenost od větve stromu k nejvzdálenější linii Límce"
@ -10406,7 +10406,7 @@ msgid "Tree support branch diameter"
msgstr "Průměr větve podpěr stromů"
msgid "This setting determines the initial diameter of support nodes."
msgstr "Toto nastavení určuje počáteční průměr uzlů poděry."
msgstr "Toto nastavení určuje počáteční průměr uzlů podpěr."
#. TRN PrintSettings: #lmFIXME
msgid "Branch Diameter Angle"
@ -10501,7 +10501,7 @@ msgid ""
"This gcode is inserted when change filament, including T command to trigger "
"tool change"
msgstr ""
"Tento gcode se vloží při výměně filamentu, včetně příkazu T ke spuštění "
"Tento gkód se vloží při výměně filamentu, včetně příkazu T ke spuštění "
"výměny nástroje"
msgid ""
@ -10957,7 +10957,7 @@ msgid "Update the configs values of 3mf to latest."
msgstr "Aktualizujte konfigurační hodnoty 3mf na nejnovější."
msgid "Load default filaments"
msgstr "Načíst výchozí filameny"
msgstr "Načíst výchozí filamenty"
msgid "Load first filament as default for those not loaded"
msgstr "Načíst první filament jako výchozí pro ty, které nebyly načteny"
@ -11399,7 +11399,7 @@ msgid ""
"3. If the max volumetric speed or print temperature is changed in the "
"filament setting."
msgstr ""
"Nyní jsme přidali automatickou kalibraci pro různé filameny, která je plně "
"Nyní jsme přidali automatickou kalibraci pro různé filamenty, která je plně "
"automatizovaná a výsledek bude uložen do tiskárny pro budoucí použití. "
"Kalibraci musíte provést pouze v následujících omezených případech:\n"
"1. Pokud použijete nový filament jiné značky/modelu nebo je filament vlhký;\n"
@ -11747,7 +11747,7 @@ msgid "Success to get history result"
msgstr "Úspěšně načtený historický výsledek kalibrace dynamiky průtoku"
msgid "Refreshing the historical Flow Dynamics Calibration records"
msgstr "Aktualizace historických záznamů kalibrace dynamiky průtpku probíhá"
msgstr "Aktualizace historických záznamů kalibrace dynamiky průtoku probíhá"
msgid "Action"
msgstr "Akce"
@ -11768,7 +11768,7 @@ msgid "Service name"
msgstr "Název služby"
msgid "OctoPrint version"
msgstr "Service name"
msgstr "Verze OctoPrintu"
msgid "Searching for devices"
msgstr "Vyhledávání zařízení"

View file

@ -148,7 +148,7 @@ msgid "Bucket fill"
msgstr "Flächenfüllung"
msgid "Height range"
msgstr "Höhenreichweite"
msgstr "Höhenbereich"
msgid "Ctrl + Shift + Enter"
msgstr "Strg + Umschalt + Eingabetaste"
@ -163,7 +163,7 @@ msgid "Triangle"
msgstr "Dreieck"
msgid "Height Range"
msgstr "Höhenreichweite"
msgstr "Höhenbereich"
msgid "Vertical"
msgstr "Vertikal"

View file

@ -65,7 +65,10 @@
"50%"
],
"close_fan_the_first_x_layers": [
"1"
"2"
],
"full_fan_speed_layer": [
"4"
],
"nozzle_temperature": [
"220"

View file

@ -22,9 +22,8 @@ public:
} else {
m_E = 0;
m_retracted = 0;
m_restart_extra = 0;
}
m_restart_extra = 0;
m_absolute_E = 0;
}
@ -34,7 +33,7 @@ public:
double retract(double length, double restart_extra);
double unretract();
double E() const { return m_share_extruder ? m_share_E : m_E; }
void reset_E() { m_E = 0.; m_share_E = 0.; }
void reset_E() { reset(); }
double e_per_mm(double mm3_per_mm) const { return mm3_per_mm * m_e_per_mm3; }
double e_per_mm3() const { return m_e_per_mm3; }
// Used filament volume in mm^3.

View file

@ -1402,6 +1402,8 @@ namespace DoExport {
//BBS
//if (ret.size() < MAX_TAGS_COUNT) check(_(L("Printing by object G-code")), config.printing_by_object_gcode.value);
//if (ret.size() < MAX_TAGS_COUNT) check(_(L("Color Change G-code")), config.color_change_gcode.value);
//Orca
if (ret.size() < MAX_TAGS_COUNT) check(_(L("Change extrusion role G-code")), config.change_extrusion_role_gcode.value);
if (ret.size() < MAX_TAGS_COUNT) check(_(L("Pause G-code")), config.machine_pause_gcode.value);
if (ret.size() < MAX_TAGS_COUNT) check(_(L("Template Custom G-code")), config.template_custom_gcode.value);
if (ret.size() < MAX_TAGS_COUNT) {
@ -4755,6 +4757,18 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
double F = speed * 60; // convert mm/sec to mm/min
//Orca: process custom gcode for extrusion role change
if (path.role() != m_last_extrusion_role && !m_config.change_extrusion_role_gcode.value.empty()) {
DynamicConfig config;
config.set_key_value("extrusion_role", new ConfigOptionString(extrusion_role_to_string_for_parser(path.role())));
config.set_key_value("last_extrusion_role", new ConfigOptionString(extrusion_role_to_string_for_parser(m_last_extrusion_role)));
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index + 1));
config.set_key_value("layer_z", new ConfigOptionFloat(m_layer == nullptr ? m_last_height : m_layer->print_z));
gcode += this->placeholder_parser_process("change_extrusion_role_gcode",
m_config.change_extrusion_role_gcode.value, m_writer.extruder()->id(), &config)
+ "\n";
}
// extrude arc or line
if (m_enable_extrusion_role_markers) {
if (path.role() != m_last_extrusion_role) {
@ -5002,6 +5016,35 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
return gcode;
}
//Orca: get string name of extrusion role. used for change_extruder_role_gcode
std::string GCode::extrusion_role_to_string_for_parser(const ExtrusionRole & role)
{
switch (role) {
case erPerimeter: return "Perimeter";
case erExternalPerimeter: return "ExternalPerimeter";
case erOverhangPerimeter: return "OverhangPerimeter";
case erInternalInfill: return "InternalInfill";
case erSolidInfill: return "SolidInfill";
case erTopSolidInfill: return "TopSolidInfill";
case erBottomSurface: return "BottomSurface";
case erBridgeInfill:
case erInternalBridgeInfill: return "BridgeInfill";
case erGapFill: return "GapFill";
case erIroning: return "Ironing";
case erSkirt: return "Skirt";
case erBrim: return "Brim";
case erSupportMaterial: return "SupportMaterial";
case erSupportMaterialInterface: return "SupportMaterialInterface";
case erSupportTransition: return "SupportTransition";
case erWipeTower: return "WipeTower";
case erCustom:
case erMixed:
case erCount:
case erNone:
default: return "Mixed";
}
}
std::string encodeBase64(uint64_t value)
{
//Always use big endian mode

View file

@ -205,6 +205,7 @@ public:
// inside the generated string and after the G-code export finishes.
std::string placeholder_parser_process(const std::string &name, const std::string &templ, unsigned int current_extruder_id, const DynamicConfig *config_override = nullptr);
bool enable_cooling_markers() const { return m_enable_cooling_markers; }
std::string extrusion_role_to_string_for_parser(const ExtrusionRole &);
// For Perl bindings, to be used exclusively by unit tests.
unsigned int layer_count() const { return m_layer_count; }
@ -213,7 +214,7 @@ public:
std::string travel_to(const Point& point, ExtrusionRole role, std::string comment);
bool needs_retraction(const Polyline& travel, ExtrusionRole role, LiftType& lift_type);
std::string retract(bool toolchange = false, bool is_last_retraction = false, LiftType lift_type = LiftType::SpiralLift);
std::string retract(bool toolchange = false, bool is_last_retraction = false, LiftType lift_type = LiftType::NormalLift);
std::string unretract() { return m_writer.unlift() + m_writer.unretract(); }
std::string set_extruder(unsigned int extruder_id, double print_z);
bool is_BBL_Printer();

View file

@ -1,3 +1,7 @@
///|/ Copyright (c) Prusa Research 2020 - 2022 Vojtěch Bubník @bubnikv, Lukáš Hejl @hejllukas
///|/
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
///|/
#include "../Layer.hpp"
#include "../GCode.hpp"
#include "../EdgeGrid.hpp"
@ -13,6 +17,8 @@
#include <unordered_set>
#include <boost/range/adaptor/reversed.hpp>
//#define AVOID_CROSSING_PERIMETERS_DEBUG_OUTPUT
namespace Slic3r {
struct TravelPoint
@ -20,6 +26,8 @@ struct TravelPoint
Point point;
// Index of the polygon containing this point. A negative value indicates that the point is not on any border.
int border_idx;
// simplify_travel() doesn't remove this point.
bool do_not_remove = false;
};
struct Intersection
@ -32,6 +40,8 @@ struct Intersection
Point point;
// Distance from the first point in the corresponding boundary
float distance;
// simplify_travel() doesn't remove this point.
bool do_not_remove = false;
};
struct ClosestLine
@ -207,8 +217,8 @@ static std::vector<Intersection> extend_for_closest_lines(const std::vector<Inte
const ClosestLine &cl_start = start_lines[cl_indices.first];
const ClosestLine &cl_end = end_lines[cl_indices.second];
std::vector<Intersection> new_intersections;
new_intersections.push_back({cl_start.border_idx, cl_start.line_idx, cl_start.point, compute_distance(cl_start)});
new_intersections.push_back({cl_end.border_idx, cl_end.line_idx, cl_end.point, compute_distance(cl_end)});
new_intersections.push_back({cl_start.border_idx, cl_start.line_idx, cl_start.point, compute_distance(cl_start), true});
new_intersections.push_back({cl_end.border_idx, cl_end.line_idx, cl_end.point, compute_distance(cl_end), true});
return new_intersections;
}
}
@ -259,7 +269,7 @@ static std::vector<Intersection> extend_for_closest_lines(const std::vector<Inte
if (cl_start_idx != std::numeric_limits<size_t>::max()) {
// If there is any ClosestLine around the start point closer to the Intersection, then replace this Intersection with ClosestLine.
const ClosestLine &cl_start = start_lines[cl_start_idx];
new_intersections.front() = {cl_start.border_idx, cl_start.line_idx, cl_start.point, compute_distance(cl_start)};
new_intersections.front() = {cl_start.border_idx, cl_start.line_idx, cl_start.point, compute_distance(cl_start), true};
} else {
// Check if there is any ClosestLine with the same boundary_idx as any Intersection. If this ClosestLine exists, then add it to the
// vector of intersections. This allows in some cases when it is more than one around ClosestLine start point chose that one which
@ -267,7 +277,7 @@ static std::vector<Intersection> extend_for_closest_lines(const std::vector<Inte
// use the first one, which is the closest one to the start point.
size_t start_closest_lines_idx = find_closest_line_with_same_boundary_idx(start_lines, new_intersections, true);
const ClosestLine &cl_start = (start_closest_lines_idx != std::numeric_limits<size_t>::max()) ? start_lines[start_closest_lines_idx] : start_lines.front();
new_intersections.insert(new_intersections.begin(),{cl_start.border_idx, cl_start.line_idx, cl_start.point, compute_distance(cl_start)});
new_intersections.insert(new_intersections.begin(),{cl_start.border_idx, cl_start.line_idx, cl_start.point, compute_distance(cl_start), true});
}
}
@ -276,7 +286,7 @@ static std::vector<Intersection> extend_for_closest_lines(const std::vector<Inte
if (cl_end_idx != std::numeric_limits<size_t>::max()) {
// If there is any ClosestLine around the end point closer to the Intersection, then replace this Intersection with ClosestLine.
const ClosestLine &cl_end = end_lines[cl_end_idx];
new_intersections.back() = {cl_end.border_idx, cl_end.line_idx, cl_end.point, compute_distance(cl_end)};
new_intersections.back() = {cl_end.border_idx, cl_end.line_idx, cl_end.point, compute_distance(cl_end), true};
} else {
// Check if there is any ClosestLine with the same boundary_idx as any Intersection. If this ClosestLine exists, then add it to the
// vector of intersections. This allows in some cases when it is more than one around ClosestLine end point chose that one which
@ -284,7 +294,7 @@ static std::vector<Intersection> extend_for_closest_lines(const std::vector<Inte
// use the first one, which is the closest one to the end point.
size_t end_closest_lines_idx = find_closest_line_with_same_boundary_idx(end_lines, new_intersections, false);
const ClosestLine &cl_end = (end_closest_lines_idx != std::numeric_limits<size_t>::max()) ? end_lines[end_closest_lines_idx] : end_lines.front();
new_intersections.push_back({cl_end.border_idx, cl_end.line_idx, cl_end.point, compute_distance(cl_end)});
new_intersections.push_back({cl_end.border_idx, cl_end.line_idx, cl_end.point, compute_distance(cl_end), true});
}
}
return new_intersections;
@ -350,8 +360,6 @@ static Polyline to_polyline(const std::vector<TravelPoint> &travel)
return result;
}
// #define AVOID_CROSSING_PERIMETERS_DEBUG_OUTPUT
#ifdef AVOID_CROSSING_PERIMETERS_DEBUG_OUTPUT
static void export_travel_to_svg(const Polygons &boundary,
const Line &original_travel,
@ -359,16 +367,17 @@ static void export_travel_to_svg(const Polygons &boundary,
const std::vector<Intersection> &intersections,
const std::string &path)
{
coordf_t stroke_width = scale_(0.05);
BoundingBox bbox = get_extents(boundary);
::Slic3r::SVG svg(path, bbox);
svg.draw_outline(boundary, "green");
svg.draw(original_travel, "blue");
svg.draw(result_travel, "red");
svg.draw(original_travel.a, "black");
svg.draw(original_travel.b, "grey");
svg.draw_outline(boundary, "green", stroke_width);
svg.draw(original_travel, "blue", stroke_width);
svg.draw(result_travel, "red", stroke_width);
svg.draw(original_travel.a, "black", stroke_width);
svg.draw(original_travel.b, "grey", stroke_width);
for (const Intersection &intersection : intersections)
svg.draw(intersection.point, "lightseagreen");
svg.draw(intersection.point, "lightseagreen", stroke_width);
}
static void export_travel_to_svg(const Polygons &boundary,
@ -433,7 +442,16 @@ static std::vector<TravelPoint> simplify_travel(const AvoidCrossingPerimeters::B
visitor.pt_current = &current_point;
if (!next.do_not_remove)
for (size_t point_idx_2 = point_idx + 1; point_idx_2 < travel.size(); ++point_idx_2) {
// Workaround for some issue in MSVC 19.29.30037 32-bit compiler.
#if defined(_WIN32) && !defined(_WIN64)
if (bool volatile do_not_remove = travel[point_idx_2].do_not_remove; do_not_remove)
break;
#else
if (travel[point_idx_2].do_not_remove)
break;
#endif
if (travel[point_idx_2].point == current_point) {
next = travel[point_idx_2];
point_idx = point_idx_2;
@ -507,6 +525,25 @@ static float get_perimeter_spacing_external(const Layer &layer)
return perimeter_spacing;
}
// Returns average perimeter width calculated from all LayerRegion within the layer.
static float get_external_perimeter_width(const Layer &layer)
{
size_t regions_count = 0;
float perimeter_width = 0.f;
for (const LayerRegion *layer_region : layer.regions())
if (layer_region != nullptr && ! layer_region->slices.empty()) {
perimeter_width += float(layer_region->flow(frExternalPerimeter).scaled_width());
++regions_count;
}
assert(perimeter_width >= 0.f);
if (regions_count != 0)
perimeter_width /= float(regions_count);
else
perimeter_width = get_default_perimeter_spacing(*layer.object());
return perimeter_width;
}
// Called by avoid_perimeters() and by simplify_travel_heuristics().
static size_t avoid_perimeters_inner(const AvoidCrossingPerimeters::Boundary &boundary,
const Point &start,
@ -566,7 +603,7 @@ static size_t avoid_perimeters_inner(const AvoidCrossingPerimeters::Boundary &bo
// Offset of the polygon's point using get_middle_point_offset is used to simplify the calculation of intersection between the
// boundary and the travel. The appended point is translated in the direction of inward normal. This translation ensures that the
// appended point will be inside the polygon and not on the polygon border.
result.push_back({get_middle_point_offset(boundaries[intersection_first.border_idx], left_idx, right_idx, intersection_first.point, coord_t(SCALED_EPSILON)), int(intersection_first.border_idx)});
result.push_back({get_middle_point_offset(boundaries[intersection_first.border_idx], left_idx, right_idx, intersection_first.point, coord_t(SCALED_EPSILON)), int(intersection_first.border_idx), intersection_first.do_not_remove});
// Check if intersection line also exit the boundary polygon
if (it_second_r != it_last_item) {
@ -590,7 +627,7 @@ static size_t avoid_perimeters_inner(const AvoidCrossingPerimeters::Boundary &bo
// Append the farthest intersection into the path
left_idx = intersection_second.line_idx;
right_idx = (intersection_second.line_idx >= (boundaries[intersection_second.border_idx].points.size() - 1)) ? 0 : (intersection_second.line_idx + 1);
result.push_back({get_middle_point_offset(boundaries[intersection_second.border_idx], left_idx, right_idx, intersection_second.point, coord_t(SCALED_EPSILON)), int(intersection_second.border_idx)});
result.push_back({get_middle_point_offset(boundaries[intersection_second.border_idx], left_idx, right_idx, intersection_second.point, coord_t(SCALED_EPSILON)), int(intersection_second.border_idx), intersection_second.do_not_remove});
// Skip intersections in between
it_first = it_second;
}
@ -645,22 +682,22 @@ static size_t avoid_perimeters(const AvoidCrossingPerimeters::Boundary &boundary
// Check if anyone of ExPolygons contains whole travel.
// called by need_wipe() and AvoidCrossingPerimeters::travel_to()
// FIXME Lukas H.: Maybe similar approach could also be used for ExPolygon::contains()
static bool any_expolygon_contains(const ExPolygons &ex_polygons,
const std::vector<BoundingBox> &ex_polygons_bboxes,
const EdgeGrid::Grid &grid_lslice,
static bool any_expolygon_contains(const ExPolygons &lslices_offset,
const std::vector<BoundingBox> &lslices_offset_bboxes,
const EdgeGrid::Grid &grid_lslices_offset,
const Line &travel)
{
assert(ex_polygons.size() == ex_polygons_bboxes.size());
if(!grid_lslice.bbox().contains(travel.a) || !grid_lslice.bbox().contains(travel.b))
assert(lslices_offset.size() == lslices_offset_bboxes.size());
if(!grid_lslices_offset.bbox().contains(travel.a) || !grid_lslices_offset.bbox().contains(travel.b))
return false;
FirstIntersectionVisitor visitor(grid_lslice);
FirstIntersectionVisitor visitor(grid_lslices_offset);
visitor.pt_current = &travel.a;
visitor.pt_next = &travel.b;
grid_lslice.visit_cells_intersecting_line(*visitor.pt_current, *visitor.pt_next, visitor);
grid_lslices_offset.visit_cells_intersecting_line(*visitor.pt_current, *visitor.pt_next, visitor);
if (!visitor.intersect) {
for (const ExPolygon &ex_polygon : ex_polygons) {
const BoundingBox &bbox = ex_polygons_bboxes[&ex_polygon - &ex_polygons.front()];
for (const ExPolygon &ex_polygon : lslices_offset) {
const BoundingBox &bbox = lslices_offset_bboxes[&ex_polygon - &lslices_offset.front()];
if (bbox.contains(travel.a) && bbox.contains(travel.b) && ex_polygon.contains(travel.a))
return true;
}
@ -670,18 +707,18 @@ static bool any_expolygon_contains(const ExPolygons &ex_polygons,
// Check if anyone of ExPolygons contains whole travel.
// called by need_wipe()
static bool any_expolygon_contains(const ExPolygons &ex_polygons, const std::vector<BoundingBox> &ex_polygons_bboxes, const EdgeGrid::Grid &grid_lslice, const Polyline &travel)
static bool any_expolygon_contains(const ExPolygons &ex_polygons, const std::vector<BoundingBox> &ex_polygons_bboxes, const EdgeGrid::Grid &grid_lslice_offset, const Polyline &travel)
{
assert(ex_polygons.size() == ex_polygons_bboxes.size());
if(std::any_of(travel.points.begin(), travel.points.end(), [&grid_lslice](const Point &point) { return !grid_lslice.bbox().contains(point); }))
if(std::any_of(travel.points.begin(), travel.points.end(), [&grid_lslice_offset](const Point &point) { return !grid_lslice_offset.bbox().contains(point); }))
return false;
FirstIntersectionVisitor visitor(grid_lslice);
FirstIntersectionVisitor visitor(grid_lslice_offset);
bool any_intersection = false;
for (size_t line_idx = 1; line_idx < travel.size(); ++line_idx) {
visitor.pt_current = &travel.points[line_idx - 1];
visitor.pt_next = &travel.points[line_idx];
grid_lslice.visit_cells_intersecting_line(*visitor.pt_current, *visitor.pt_next, visitor);
grid_lslice_offset.visit_cells_intersecting_line(*visitor.pt_current, *visitor.pt_next, visitor);
any_intersection = visitor.intersect;
if (any_intersection) break;
}
@ -698,13 +735,13 @@ static bool any_expolygon_contains(const ExPolygons &ex_polygons, const std::vec
}
static bool need_wipe(const GCode &gcodegen,
const EdgeGrid::Grid &grid_lslice,
const ExPolygons &lslices_offset,
const std::vector<BoundingBox> &lslices_offset_bboxes,
const EdgeGrid::Grid &grid_lslices_offset,
const Line &original_travel,
const Polyline &result_travel,
const size_t intersection_count)
{
const ExPolygons &lslices = gcodegen.layer()->lslices;
const std::vector<BoundingBox> &lslices_bboxes = gcodegen.layer()->lslices_bboxes;
bool z_lift_enabled = gcodegen.config().z_hop.get_at(gcodegen.writer().extruder()->id()) > 0.;
bool wipe_needed = false;
@ -714,16 +751,16 @@ static bool need_wipe(const GCode &gcodegen,
// The original layer is intersected with defined boundaries. Then it is necessary to make a detailed test.
// If the z-lift is enabled, then a wipe is needed when the original travel leads above the holes.
if (z_lift_enabled) {
if (any_expolygon_contains(lslices, lslices_bboxes, grid_lslice, original_travel)) {
if (any_expolygon_contains(lslices_offset, lslices_offset_bboxes, grid_lslices_offset, original_travel)) {
// Check if original_travel and result_travel are not same.
// If both are the same, then it is possible to skip testing of result_travel
wipe_needed = !(result_travel.size() > 2 && result_travel.first_point() == original_travel.a && result_travel.last_point() == original_travel.b) &&
!any_expolygon_contains(lslices, lslices_bboxes, grid_lslice, result_travel);
!any_expolygon_contains(lslices_offset, lslices_offset_bboxes, grid_lslices_offset, result_travel);
} else {
wipe_needed = true;
}
} else {
wipe_needed = !any_expolygon_contains(lslices, lslices_bboxes, grid_lslice, result_travel);
wipe_needed = !any_expolygon_contains(lslices_offset, lslices_offset_bboxes, grid_lslices_offset, result_travel);
}
}
@ -945,14 +982,22 @@ static std::vector<float> contour_distance(const EdgeGrid::Grid &grid,
// ExPolygons are handled one by one so returned ExPolygons could intersect.
static ExPolygons inner_offset(const ExPolygons &ex_polygons, double offset)
{
double min_contour_width = 2. * offset + SCALED_EPSILON;
double search_radius = 2. * (offset + min_contour_width);
const std::vector<double> min_contour_width_values = {offset / 2., offset, 2. * offset + SCALED_EPSILON};
ExPolygons ex_poly_result = ex_polygons;
resample_expolygons(ex_poly_result, offset / 2, scaled<double>(0.5));
for (ExPolygon &ex_poly : ex_poly_result) {
BoundingBox bbox(get_extents(ex_poly));
bbox.offset(SCALED_EPSILON);
// Filter out expolygons smaller than 0.1mm^2
if (Vec2d bbox_size = bbox.size().cast<double>(); bbox_size.x() * bbox_size.y() < Slic3r::sqr(scale_(0.1f)))
continue;
for (const double &min_contour_width : min_contour_width_values) {
const size_t min_contour_width_idx = &min_contour_width - &min_contour_width_values.front();
const double search_radius = 2. * (offset + min_contour_width);
EdgeGrid::Grid grid;
grid.set_bbox(bbox);
grid.create(ex_poly, coord_t(0.7 * search_radius));
@ -979,8 +1024,14 @@ static ExPolygons inner_offset(const ExPolygons &ex_polygons, double offset)
ExPolygons offset_ex_poly = variable_offset_inner_ex(ex_poly, offsets);
// If variable_offset_inner_ex produces empty result, then original ex_polygon is used
if (offset_ex_poly.size() == 1) {
if (offset_ex_poly.size() == 1 && offset_ex_poly.front().holes.size() == ex_poly.holes.size()) {
ex_poly = std::move(offset_ex_poly.front());
break;
} else if ((min_contour_width_idx + 1) < min_contour_width_values.size()) {
continue; // Try the next round with bigger min_contour_width.
} else if (offset_ex_poly.size() == 1) {
ex_poly = std::move(offset_ex_poly.front());
break;
} else if (offset_ex_poly.size() > 1) {
// fix_after_inner_offset called inside variable_offset_inner_ex sometimes produces
// tiny artefacts polygons, so these artefacts are removed.
@ -994,6 +1045,8 @@ static ExPolygons inner_offset(const ExPolygons &ex_polygons, double offset)
}
}
ex_poly = std::move(offset_ex_poly[max_area_idx]);
break;
}
}
}
return ex_poly_result;
@ -1133,10 +1186,8 @@ Polyline AvoidCrossingPerimeters::travel_to(const GCode &gcodegen, const Point &
Vec2d startf = start.cast<double>();
Vec2d endf = end .cast<double>();
const ExPolygons &lslices = gcodegen.layer()->lslices;
const std::vector<BoundingBox> &lslices_bboxes = gcodegen.layer()->lslices_bboxes;
bool is_support_layer = (dynamic_cast<const SupportLayer *>(gcodegen.layer()) != nullptr);
if (!use_external && (is_support_layer || (!lslices.empty() && !any_expolygon_contains(lslices, lslices_bboxes, m_grid_lslice, travel)))) {
bool is_support_layer = dynamic_cast<const SupportLayer *>(gcodegen.layer()) != nullptr;
if (!use_external && (is_support_layer || (!m_lslices_offset.empty() && !any_expolygon_contains(m_lslices_offset, m_lslices_offset_bboxes, m_grid_lslices_offset, travel)))) {
// Initialize m_internal only when it is necessary.
if (m_internal.boundaries.empty())
init_boundary(&m_internal, to_polygons(get_boundary(*gcodegen.layer())));
@ -1186,7 +1237,7 @@ Polyline AvoidCrossingPerimeters::travel_to(const GCode &gcodegen, const Point &
} else if (max_detour_length_exceeded) {
*could_be_wipe_disabled = false;
} else
*could_be_wipe_disabled = !need_wipe(gcodegen, m_grid_lslice, travel, result_pl, travel_intersection_count);
*could_be_wipe_disabled = !need_wipe(gcodegen, m_lslices_offset, m_lslices_offset_bboxes, m_grid_lslices_offset, travel, result_pl, travel_intersection_count);
return result_pl;
}
@ -1197,13 +1248,21 @@ void AvoidCrossingPerimeters::init_layer(const Layer &layer)
{
m_internal.clear();
m_external.clear();
m_lslices_offset.clear();
m_lslices_offset_bboxes.clear();
float perimeter_offset = -get_external_perimeter_width(layer) / float(2.);
m_lslices_offset = offset_ex(layer.lslices, perimeter_offset);
m_lslices_offset_bboxes.reserve(m_lslices_offset.size());
for (const ExPolygon &ex_poly : m_lslices_offset)
m_lslices_offset_bboxes.emplace_back(get_extents(ex_poly));
BoundingBox bbox_slice(get_extents(layer.lslices));
bbox_slice.offset(SCALED_EPSILON);
m_grid_lslice.set_bbox(bbox_slice);
//FIXME 1mm grid?
m_grid_lslice.create(layer.lslices, coord_t(scale_(1.)));
m_grid_lslices_offset.set_bbox(bbox_slice);
m_grid_lslices_offset.create(m_lslices_offset, coord_t(scale_(1.)));
}
#if 0

View file

@ -1,3 +1,7 @@
///|/ Copyright (c) Prusa Research 2020 - 2022 Lukáš Hejl @hejllukas, Vojtěch Bubník @bubnikv
///|/
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
///|/
#ifndef slic3r_AvoidCrossingPerimeters_hpp_
#define slic3r_AvoidCrossingPerimeters_hpp_
@ -58,8 +62,11 @@ private:
// we enable it by default for the first travel move in print
bool m_disabled_once { true };
// Lslices offseted by half an external perimeter width. Used for detection if line or polyline is inside of any polygon.
ExPolygons m_lslices_offset;
std::vector<BoundingBox> m_lslices_offset_bboxes;
// Used for detection of line or polyline is inside of any polygon.
EdgeGrid::Grid m_grid_lslice;
EdgeGrid::Grid m_grid_lslices_offset;
// Store all needed data for travels inside object
Boundary m_internal;
// Store all needed data for travels outside object

View file

@ -320,7 +320,7 @@ std::string GCodeWriter::reset_e(bool force)
return "";
if (m_extruder != nullptr) {
if (m_extruder->E() == 0. && ! force)
if (is_zero(m_extruder->E()) && ! force)
return "";
m_extruder->reset_E();
}
@ -709,7 +709,7 @@ std::string GCodeWriter::_retract(double length, double restart_extra, const std
length = 1;
std::string gcode;
if (double dE = m_extruder->retract(length, restart_extra); dE != 0) {
if (double dE = m_extruder->retract(length, restart_extra); !is_zero(dE)) {
if (this->config.use_firmware_retraction) {
gcode = FLAVOR_IS(gcfMachinekit) ? "G22 ; retract\n" : "G10 ; retract\n";
}
@ -737,7 +737,7 @@ std::string GCodeWriter::unretract()
if (FLAVOR_IS(gcfMakerWare))
gcode = "M101 ; extruder on\n";
if (double dE = m_extruder->unretract(); dE != 0) {
if (double dE = m_extruder->unretract(); !is_zero(dE)) {
if (this->config.use_firmware_retraction) {
gcode += FLAVOR_IS(gcfMachinekit) ? "G23 ; unretract\n" : "G11 ; unretract\n";
gcode += this->reset_e();

View file

@ -819,7 +819,7 @@ static std::vector<std::string> s_Preset_printer_options {
"printer_technology",
"printable_area", "bed_exclude_area","bed_custom_texture", "bed_custom_model", "gcode_flavor",
"fan_kickstart", "fan_speedup_time", "fan_speedup_overhangs",
"single_extruder_multi_material", "manual_filament_change", "machine_start_gcode", "machine_end_gcode", "before_layer_change_gcode", "layer_change_gcode", "time_lapse_gcode", "change_filament_gcode",
"single_extruder_multi_material", "manual_filament_change", "machine_start_gcode", "machine_end_gcode", "before_layer_change_gcode", "layer_change_gcode", "time_lapse_gcode", "change_filament_gcode", "change_extrusion_role_gcode",
"printer_model", "printer_variant", "printable_height", "extruder_clearance_radius", "extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod",
"default_print_profile", "inherits",
"silent_mode",

View file

@ -3970,6 +3970,15 @@ def = this->add("filament_loading_speed", coFloats);
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionString(""));
def = this->add("change_extrusion_role_gcode", coString);
def->label = L("Change extrusion role G-code");
def->tooltip = L("This gcode is inserted when the extrusion role is changed");
def->multiline = true;
def->full_width = true;
def->height = 5;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionString(""));
def = this->add("top_surface_line_width", coFloatOrPercent);
def->label = L("Top surface");
def->category = L("Quality");

View file

@ -969,6 +969,7 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionBool, single_extruder_multi_material_priming))
((ConfigOptionBool, wipe_tower_no_sparse_layers))
((ConfigOptionString, change_filament_gcode))
((ConfigOptionString, change_extrusion_role_gcode))
((ConfigOptionFloat, travel_speed))
((ConfigOptionFloat, travel_speed_z))
((ConfigOptionBool, silent_mode))

View file

@ -278,6 +278,12 @@ constexpr inline T sqr(T x)
return x * x;
}
template<typename Number> constexpr
inline bool is_zero(Number value)
{
return std::fabs(double(value)) < 1e-6;
}
template <typename T, typename Number>
constexpr inline T lerp(const T& a, const T& b, Number t)
{

View file

@ -2123,16 +2123,15 @@ void GUI_App::init_app_config()
app_config = new AppConfig();
//app_config = new AppConfig(is_editor() ? AppConfig::EAppMode::Editor : AppConfig::EAppMode::GCodeViewer);
m_config_corrupted = false;
// load settings
m_app_conf_exists = app_config->exists();
if (m_app_conf_exists) {
std::string error = app_config->load();
if (!error.empty()) {
// Error while parsing config file. We'll customize the error message and rethrow to be displayed.
throw Slic3r::RuntimeError(
_u8L("OrcaSlicer configuration file may be corrupted and is not abled to be parsed."
"Please delete the file and try again.") +
"\n\n" + app_config->config_path() + "\n\n" + error);
// Orca: if the config file is corrupted, we will show a error dialog and create a default config file.
m_config_corrupted = true;
}
// Save orig_version here, so its empty if no app_config existed before this run.
m_last_config_version = app_config->orig_version();//parse_semver_from_ini(app_config->config_path());
@ -2749,6 +2748,7 @@ bool GUI_App::on_init_inner()
if (m_post_initialized && app_config->dirty())
app_config->save();
});
m_initialized = true;
@ -2756,6 +2756,13 @@ bool GUI_App::on_init_inner()
flush_logs();
BOOST_LOG_TRIVIAL(info) << "finished the gui app init";
if (m_config_corrupted) {
m_config_corrupted = false;
show_error(nullptr,
_u8L(
"The OrcaSlicer configuration file may be corrupted and cannot be parsed.\nOrcaSlicer has attempted to recreate the "
"configuration file.\nPlease note, application settings will be lost, but printer profiles will not be affected."));
}
//BBS: delete splash screen
delete scrn;
return true;

View file

@ -658,6 +658,7 @@ private:
bool m_datadir_redefined { false };
std::string m_older_data_dir_path;
boost::optional<Semver> m_last_config_version;
bool m_config_corrupted { false };
};
DECLARE_APP(GUI_App)

View file

@ -149,6 +149,17 @@ bool GLGizmoText::on_init()
reset_text_info();
m_desc["font"] = _L("Font");
m_desc["size"] = _L("Size");
m_desc["thickness"] = _L("Thickness");
m_desc["text_gap"] = _L("Text Gap");
m_desc["angle"] = _L("Angle");
m_desc["embeded_depth"] = _L("Embeded\ndepth");
m_desc["input_text"] = _L("Input text");
m_desc["surface"] = _L("Surface");
m_desc["horizontal_text"] = _L("Horizontal text");
m_desc["rotate_text_caption"] = _L("Shift + Mouse move up or dowm");
m_desc["rotate_text"] = _L("Rotate text");
@ -667,13 +678,13 @@ void GLGizmoText::on_render_input_window(float x, float y, float bottom_limit)
ImGui::PushStyleVar(ImGuiStyleVar_ScrollbarSize, 4.0f * currt_scale);
GizmoImguiBegin("Text", ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar);
float space_size = m_imgui->get_style_scaling() * 8;
float font_cap = m_imgui->calc_text_size(_L("Font")).x;
float size_cap = m_imgui->calc_text_size(_L("Size")).x;
float thickness_cap = m_imgui->calc_text_size(_L("Thickness")).x;
float input_cap = m_imgui->calc_text_size(_L("Input text")).x;
float depth_cap = m_imgui->calc_text_size(_L("Embeded")).x;
float caption_size = std::max(std::max(font_cap, size_cap), std::max(depth_cap, input_cap)) + space_size + ImGui::GetStyle().WindowPadding.x;
const float space_size = m_imgui->get_style_scaling() * 8;
const std::array<std::string, 7> cap_array = std::array<std::string, 7>{ "font", "size", "thickness", "text_gap", "angle", "embeded_depth", "input_text" };
float caption_size = 0.0f;
for (const auto &t : cap_array) {
caption_size = std::max(caption_size, m_imgui->calc_text_size(m_desc[t]).x);
}
caption_size += space_size + ImGui::GetStyle().WindowPadding.x;
float input_text_size = m_imgui->scaled(10.0f);
float button_size = ImGui::GetFrameHeight();
@ -700,7 +711,7 @@ void GLGizmoText::on_render_input_window(float x, float y, float bottom_limit)
ImGui::AlignTextToFramePadding();
m_imgui->text(_L("Font"));
m_imgui->text(m_desc["font"]);
ImGui::SameLine(caption_size);
ImGui::PushItemWidth(list_width);
push_combo_style(currt_scale);
@ -740,7 +751,7 @@ void GLGizmoText::on_render_input_window(float x, float y, float bottom_limit)
ImGui::PopStyleVar(2);
pop_combo_style();
ImGui::AlignTextToFramePadding();
m_imgui->text(_L("Size"));
m_imgui->text(m_desc["size"]);
ImGui::SameLine(caption_size);
ImGui::PushItemWidth(input_size);
if(ImGui::InputFloat("###font_size", &m_font_size, 0.0f, 0.0f, "%.2f"))
@ -767,7 +778,7 @@ void GLGizmoText::on_render_input_window(float x, float y, float bottom_limit)
ImGui::PopStyleVar(3);
ImGui::AlignTextToFramePadding();
m_imgui->text(_L("Thickness"));
m_imgui->text(m_desc["thickness"]);
ImGui::SameLine(caption_size);
ImGui::PushItemWidth(list_width);
float old_value = m_thickness;
@ -782,7 +793,7 @@ void GLGizmoText::on_render_input_window(float x, float y, float bottom_limit)
const float drag_left_width = caption_size + slider_width + space_size;
ImGui::AlignTextToFramePadding();
m_imgui->text(_L("Text Gap"));
m_imgui->text(m_desc["text_gap"]);
ImGui::SameLine(caption_size);
ImGui::PushItemWidth(slider_width);
if (m_imgui->bbl_slider_float_style("##text_gap", &m_text_gap, -100, 100, "%.2f", 1.0f, true))
@ -793,7 +804,7 @@ void GLGizmoText::on_render_input_window(float x, float y, float bottom_limit)
m_need_update_text = true;
ImGui::AlignTextToFramePadding();
m_imgui->text(_L("Angle"));
m_imgui->text(m_desc["angle"]);
ImGui::SameLine(caption_size);
ImGui::PushItemWidth(slider_width);
if (m_imgui->bbl_slider_float_style("##angle", &m_rotate_angle, 0, 360, "%.2f", 1.0f, true))
@ -804,7 +815,7 @@ void GLGizmoText::on_render_input_window(float x, float y, float bottom_limit)
m_need_update_text = true;
ImGui::AlignTextToFramePadding();
m_imgui->text(_L("Embeded\ndepth"));
m_imgui->text(m_desc["embeded_depth"]);
ImGui::SameLine(caption_size);
ImGui::PushItemWidth(list_width);
old_value = m_embeded_depth;
@ -815,7 +826,7 @@ void GLGizmoText::on_render_input_window(float x, float y, float bottom_limit)
m_need_update_text = true;
ImGui::AlignTextToFramePadding();
m_imgui->text(_L("Input text"));
m_imgui->text(m_desc["input_text"]);
ImGui::SameLine(caption_size);
ImGui::PushItemWidth(list_width);
@ -833,12 +844,12 @@ void GLGizmoText::on_render_input_window(float x, float y, float bottom_limit)
ImGui::SameLine(caption_size);
ImGui::AlignTextToFramePadding();
if (m_imgui->bbl_checkbox(_L("Surface"), m_is_surface_text))
if (m_imgui->bbl_checkbox(m_desc["surface"], m_is_surface_text))
m_need_update_text = true;
ImGui::SameLine();
ImGui::AlignTextToFramePadding();
if (m_imgui->bbl_checkbox(_L("Horizontal text"), m_keep_horizontal))
if (m_imgui->bbl_checkbox(m_desc["horizontal_text"], m_keep_horizontal))
m_need_update_text = true;
//ImGui::SameLine();

View file

@ -16,7 +16,7 @@ constexpr double miscalculation = scale_(scale_(1)); // equal to 1 mm2
static const float LEFT_MARGIN = 13.0f + 100.0f; // avoid thumbnail toolbar
static const float HORIZONTAL_SLIDER_WINDOW_HEIGHT = 64.0f;
static const float VERTICAL_SLIDER_WINDOW_WIDTH = 124.0f;
static const float VERTICAL_SLIDER_WINDOW_WIDTH = 160.0f;
static const float GROOVE_WIDTH = 12.0f;
static const ImVec2 ONE_LAYER_MARGIN = ImVec2(20.0f, 20.0f);
static const ImVec2 ONE_LAYER_BUTTON_SIZE = ImVec2(28.0f, 28.0f);

View file

@ -534,7 +534,7 @@ void PartPlate::calc_vertex_for_icons(int index, PickingModel &model)
ExPolygon poly;
auto bed_ext = get_extents(m_shape);
Vec2d p = bed_ext[2];
if (m_plater->get_build_volume_type() == BuildVolume_Type::Circle)
if (m_plater && m_plater->get_build_volume_type() == BuildVolume_Type::Circle)
p[1] -= std::max(
0.0, (bed_ext.size()(1) - 5 * PARTPLATE_ICON_SIZE - 4 * PARTPLATE_ICON_GAP_Y - PARTPLATE_ICON_GAP_TOP) / 2);

View file

@ -3232,6 +3232,17 @@ void TabPrinter::build_fff()
option.opt.height = gcode_field_height;//150;
optgroup->append_single_option_line(option);
optgroup = page->new_optgroup(L("Change extrusion role G-code"), L"param_gcode", 0);
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
validate_custom_gcode_cb(this, optgroup, opt_key, value);
};
option = optgroup->get_option("change_extrusion_role_gcode");
option.opt.full_width = true;
option.opt.is_code = true;
option.opt.height = gcode_field_height;//150;
optgroup->append_single_option_line(option);
optgroup = page->new_optgroup(L("Pause G-code"), L"param_gcode", 0);
optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) {
validate_custom_gcode_cb(this, optgroup_title, opt_key, value);