fix: merge branch feat/plugin-feature

This commit is contained in:
Ian Chua
2026-07-17 14:02:10 +08:00
151 changed files with 5144 additions and 1418 deletions
+2 -2
View File
@@ -5097,7 +5097,7 @@ msgstr ""
msgid "Fan speed (%)"
msgstr ""
msgid "Temperature (°C)"
msgid "Temperature ()"
msgstr ""
msgid "Volumetric flow rate (mm³/s)"
@@ -15194,7 +15194,7 @@ msgid ""
msgstr ""
msgid ""
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50°C, without waiting for the full 60°C.\n"
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50, without waiting for the full 60.\n"
"\n"
"It sets a G-code variable named chamber_minimal_temperature, which can be passed to your print start macro or a heat soak macro, like this: PRINT_START (other variables) CHAMBER_MIN_TEMP=[chamber_minimal_temperature].\n"
"\n"
+3 -3
View File
@@ -5349,8 +5349,8 @@ msgstr "Jerk (mm/s)"
msgid "Fan speed (%)"
msgstr "Velocitat Ventilador ( % )"
msgid "Temperature (°C)"
msgstr "Temperatura ( °C )"
msgid "Temperature ()"
msgstr "Temperatura ( )"
msgid "Volumetric flow rate (mm³/s)"
msgstr "Taxa de flux volumètric ( mm³/seg )"
@@ -16143,7 +16143,7 @@ msgstr ""
"Si està activat, aquest paràmetre també estableix una variable de codi g anomenada chamber_temperature, que es pot utilitzar per passar la temperatura de la cambra desitjada a la macro d'inici d'impressió, o una macro de remull tèrmic com aquesta: PRINT_START (altres variables) CHAMBER_TEMP=[chamber_temperature]. Això pot ser útil si la vostra impressora no admet les ordres M141/M191, o si voleu gestionar el remull de calor a la macro d'inici d'impressió si no hi ha instal·lat un escalfador de cambra actiu."
msgid ""
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50°C, without waiting for the full 60°C.\n"
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50, without waiting for the full 60.\n"
"\n"
"It sets a G-code variable named chamber_minimal_temperature, which can be passed to your print start macro or a heat soak macro, like this: PRINT_START (other variables) CHAMBER_MIN_TEMP=[chamber_minimal_temperature].\n"
"\n"
+3 -3
View File
@@ -5346,8 +5346,8 @@ msgstr "Jerk (mm/s)"
msgid "Fan speed (%)"
msgstr "Rychlost ventilátoru (%)"
msgid "Temperature (°C)"
msgstr "Teplota (°C)"
msgid "Temperature ()"
msgstr "Teplota ()"
msgid "Volumetric flow rate (mm³/s)"
msgstr "Rychlost průtoku (mm³/s)"
@@ -16186,7 +16186,7 @@ msgstr ""
"Pokud je povoleno, tento parametr rovněž nastaví G-code proměnnou s názvem chamber_temperature, kterou lze použít k předání požadované teploty komory do makra spuštění tisku, nebo do makra pro tepelnou stabilizaci, například takto: PRINT_START (další proměnné) CHAMBER_TEMP=[chamber_temperature]. To může být užitečné, pokud vaše tiskárna nepodporuje příkazy M141/M191, nebo pokud chcete provádět tepelnou stabilizaci v makru spuštění tisku, pokud není instalováno aktivní topení komory."
msgid ""
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50°C, without waiting for the full 60°C.\n"
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50, without waiting for the full 60.\n"
"\n"
"It sets a G-code variable named chamber_minimal_temperature, which can be passed to your print start macro or a heat soak macro, like this: PRINT_START (other variables) CHAMBER_MIN_TEMP=[chamber_minimal_temperature].\n"
"\n"
+76 -64
View File
@@ -5350,8 +5350,8 @@ msgstr "Ruck (mm/s)"
msgid "Fan speed (%)"
msgstr "Lüftergeschwindigkeit (%)"
msgid "Temperature (°C)"
msgstr "Temperatur (°C)"
msgid "Temperature ()"
msgstr "Temperatur ()"
msgid "Volumetric flow rate (mm³/s)"
msgstr "Volumetrische Flussrate (mm³/s)"
@@ -8891,10 +8891,10 @@ msgid "Show incompatible/unsupported presets in the printer and filament dropdow
msgstr "Zeigt inkompatible/nicht unterstützte Profile in den Dropdown-Listen für Drucker und Filament an. Diese Profile können nicht ausgewählt werden."
msgid "Experimental Features"
msgstr ""
msgstr "Experimentelle Funktionen"
msgid "Keep painted feature after mesh change"
msgstr ""
msgstr "Bemalte Funktionen nach Mesh-Änderung beibehalten"
msgid ""
"Attempt to keep painted features (color/seam/support/fuzzy etc.) after changing the object mesh (such as cut/reload from disk/simplify/fix etc.)\n"
@@ -9719,10 +9719,10 @@ msgid "Search in preset"
msgstr "In Profilen suchen"
msgid "Synchronization of different extruder drives or nozzle volume types is not supported."
msgstr ""
msgstr "Die Synchronisierung verschiedener Extrudertypen oder Düsenvolumentypen wird nicht unterstützt."
msgid "Synchronize the modification of parameters to the corresponding parameters of another extruder."
msgstr ""
msgstr "Änderungen der Parameter mit den entsprechenden Parametern eines anderen Extruders synchronisieren."
msgid "Click to reset all settings to the last saved preset."
msgstr "Klicken Sie hier, um alle Einstellungen auf die zuletzt gespeicherten Parameter zurückzusetzen."
@@ -10018,13 +10018,13 @@ msgid "Chamber temperature"
msgstr "Druckraum Temperatur"
msgid "Target chamber temperature, and the minimal chamber temperature at which printing should start"
msgstr ""
msgstr "Ziel-Druckraumtemperatur und die minimale Druckraumtemperatur, bei der der Druck beginnen sollte"
msgid "Target"
msgstr ""
msgstr "Ziel"
msgid "Minimal"
msgstr ""
msgstr "Minimal"
msgid "Print temperature"
msgstr "Drucktemperatur"
@@ -10047,7 +10047,7 @@ msgstr "Strukturierte kalte Druckplatte"
# TODO: Review, changed by lang refactor. PR 14254
msgid "This is the bed temperature when the Textured Cool Plate is installed. A value of 0 means the filament does not support printing on the Textured Cool Plate."
msgstr "Dies ist die Betttemperatur, wenn die kalte Druckplatte installiert ist. Ein Wert von 0 bedeutet, dass das Filament auf der texturierten kalten Druckplatte nicht unterstützt wird."
msgstr "Dies ist die Betttemperatur, wenn die texturierte kalte Druckplatte installiert ist. Ein Wert von 0 bedeutet, dass das Filament auf der texturierten kalten Druckplatte nicht unterstützt wird."
# TODO: Review, changed by lang refactor. PR 14254
msgid "This is the bed temperature when the engineering plate is installed. A value of 0 means the filament does not support printing on the Engineering Plate."
@@ -10368,21 +10368,21 @@ msgstr "Nicht erneut für dieses Profil warnen"
#, c-format, boost-format
msgid "%s: %s"
msgstr ""
msgstr "%s: %s"
msgid "No modifications need to be copied."
msgstr ""
msgstr "Es müssen keine Änderungen kopiert werden."
msgid "Copy paramters"
msgstr ""
msgstr "Parameter kopieren"
#, c-format, boost-format
msgid "Modify paramters of %s"
msgstr ""
msgstr "Parameter von %s ändern"
#, c-format, boost-format
msgid "Do you want to modify the following parameters of the %s to that of the %s?"
msgstr ""
msgstr "Möchten Sie die folgenden Parameter von %s auf die von %s ändern?"
msgid "Click to reset current value and attach to the global value."
msgstr "Klicken Sie hier, um den aktuellen Wert zurückzusetzen und ihn dem globalen Wert zuzuordnen."
@@ -10528,10 +10528,10 @@ msgid "Capabilities"
msgstr "Fähigkeiten"
msgid "Left: "
msgstr ""
msgstr "Links: "
msgid "Right: "
msgstr ""
msgstr "Rechts: "
msgid "Show all presets (including incompatible)"
msgstr "Alle Profile anzeigen (auch inkompatible)"
@@ -13887,7 +13887,7 @@ msgid "layer"
msgstr "Schicht"
msgid "First layer fan speed"
msgstr ""
msgstr "Lüftergeschwindigkeit der ersten Schicht"
msgid ""
"Sets an exact fan speed for the first layer, overriding all other cooling settings. Useful for protecting 3D-printed toolhead parts (e.g. Voron-style ABS/ASA ducts) from a hot bed. A small amount of airflow cools the ducts down, without using full cooling that may in certain conditions hurt first-layer adhesion.\n"
@@ -13896,6 +13896,11 @@ msgid ""
"Only available when \"No cooling for the first\" is 0.\n"
"Set to -1 to disable it."
msgstr ""
"Legt eine genaue Lüftergeschwindigkeit für die erste Schicht fest und überschreibt alle anderen Kühlungseinstellungen. Nützlich zum Schutz von 3D-gedruckten Werkzeugkopfteilen (z.B. Voron-Style ABS/ASA-Düsen) vor einem heißen Bett. Eine kleine Menge Luftstrom kühlt die Düsen ab, ohne die volle Kühlung zu verwenden, die unter bestimmten Bedingungen die Haftung der ersten Schicht beeinträchtigen kann.\n"
"Ab der zweiten Schicht wird die normale Kühlung wieder aufgenommen.\n"
"Wenn auch \"Volle Lüfterdrehzahl ab Schicht\" eingestellt ist, steigt der Lüfter von diesem Wert in der ersten Schicht bis zu Ihrem Zielwert in der gewählten Schicht.\n"
"Nur verfügbar, wenn \"Keine Kühlung für die erste\" 0 ist.\n"
"Auf -1 setzen, um es zu deaktivieren."
msgid "Support interface fan speed"
msgstr "Stützstruktur-Schnittstelle"
@@ -16291,15 +16296,20 @@ msgstr ""
"Wenn diese Option aktiviert ist, wird auch eine G-Code-Variable namens chamber_temperature gesetzt, die verwendet werden kann, um die gewünschte Druckraumtemperatur an Ihr Druckstart-Makro oder ein Wärmespeicher-Makro weiterzugeben, wie z.B. PRINT_START (andere Variablen) CHAMBER_TEMP=[chamber_temperature]. Dies kann nützlich sein, wenn Ihr Drucker die Befehle M141/M191 nicht unterstützt oder wenn Sie das Wärmespeichern im Druckstart-Makro behandeln möchten, wenn kein aktiver Druckraumheizer installiert ist."
msgid ""
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50°C, without waiting for the full 60°C.\n"
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50, without waiting for the full 60.\n"
"\n"
"It sets a G-code variable named chamber_minimal_temperature, which can be passed to your print start macro or a heat soak macro, like this: PRINT_START (other variables) CHAMBER_MIN_TEMP=[chamber_minimal_temperature].\n"
"\n"
"Unlike the \"Target\" chamber temperature, this option does not emit any M141/M191 commands; it only exposes the value to your custom G-code. It should not exceed the \"Target\" chamber temperature."
msgstr ""
"Dies ist die Druckraumtemperatur, bei der der Druckvorgang beginnen soll, während der Druckraum weiterhin auf die \"Ziel\"-Druckraumtemperatur erhitzt wird. Zum Beispiel: Setzen Sie das Ziel auf 60 und das Minimum auf 50, um mit dem Drucken zu beginnen, sobald der Druckraum 50°C erreicht hat, ohne auf die vollen 60°C zu warten.\n"
"\n"
"Es wird eine G-Code-Variable namens chamber_minimal_temperature gesetzt, die an Ihr Druckstart-Makro oder ein Wärmespeicher-Makro übergeben werden kann, wie z.B.: PRINT_START (andere Variablen) CHAMBER_MIN_TEMP=[chamber_minimal_temperature].\n"
"\n"
"Im Gegensatz zur \"Ziel\"-Druckraumtemperatur sendet diese Option keine M141/M191-Befehle; sie stellt den Wert nur Ihrem benutzerdefinierten G-Code zur Verfügung. Sie sollte die \"Ziel\"-Druckraumtemperatur nicht überschreiten."
msgid "Chamber minimal temperature"
msgstr ""
msgstr "Minimale Druckraumtemperatur"
# TODO: Review, changed by lang refactor. PR 14254
msgid "Nozzle temperature after the first layer"
@@ -19110,130 +19120,132 @@ msgid "Connection to printers connected via the print host failed."
msgstr "Die Verbindung zu den über den Druck-Host verbundenen Druckern ist fehlgeschlagen."
msgid "Detect Creality K-series printer"
msgstr ""
msgstr "Creality K-Serie Drucker erkennen"
msgid "Click Scan to look for K-series printers on your network."
msgstr ""
msgstr "Klicken Sie auf 'Scannen', um nach K-Serie Druckern in Ihrem Netzwerk zu suchen."
msgid "Use Selected"
msgstr ""
msgstr "Ausgewählten verwenden"
msgid "Scanning the LAN for K-series printers... this takes a few seconds."
msgstr ""
msgstr "Suche im LAN nach K-Serie Druckern... dies dauert einige Sekunden."
msgid "No K-series printers found. Make sure the printer is on the same network and not blocked by Wi-Fi client isolation, then click Scan again."
msgstr ""
msgstr "Keine K-Serie Drucker gefunden. Stellen Sie sicher, dass der Drucker im selben Netzwerk ist und nicht durch Wi-Fi-Client-Isolation blockiert wird, und klicken Sie dann erneut auf 'Scannen'."
#, c-format
msgid "Found %zu Creality printer(s). Select one and click Use Selected."
msgstr ""
msgstr "Es wurden %zu Creality-Drucker gefunden. Wählen Sie einen aus und klicken Sie auf 'Ausgewählten verwenden'."
msgid "Active"
msgstr ""
msgstr "Aktiv"
msgid "Printers"
msgstr ""
msgstr "Drucker"
msgid "Processes"
msgstr ""
msgstr "Prozesse"
msgid "Show/Hide system information"
msgstr ""
msgstr "Systeminformationen anzeigen/verbergen"
msgid "Copy system information to clipboard"
msgstr ""
msgstr "Systeminformationen in die Zwischenablage kopieren"
msgid "We need information for diagnosing source of the issue. Check wiki page for detailed guide."
msgstr ""
msgstr "Wir benötigen Informationen zur Diagnose der Ursache des Problems. Überprüfen Sie die Wiki-Seite für eine detaillierte Anleitung."
msgid "Pack button collects project file and logs of current session onto a zip file."
msgstr ""
msgstr "Die Schaltfläche „Packen“ sammelt die Projektdatei und Protokolle der aktuellen Sitzung in einer ZIP-Datei."
msgid "Any additional visual examples like images or screen recordings might be helpful while reporting the issue."
msgstr ""
msgstr "Zusätzliche visuelle Beispiele wie Bilder oder Bildschirmaufnahmen könnten beim Melden des Problems hilfreich sein."
msgid "Report issue"
msgstr ""
msgstr "Problem melden"
msgid "Pack"
msgstr ""
msgstr "Packen"
msgid "Cleans and rebuilds system profiles cache on next launch"
msgstr ""
msgstr "Bereinigt und erstellt den Systemprofil-Cache beim nächsten Start neu"
msgid "Clean system profiles cache"
msgstr ""
msgstr "Systemprofil-Cache bereinigen"
msgid "Clean"
msgstr ""
msgstr "Bereinigen"
msgid "Loaded profiles overview"
msgstr ""
msgstr "Übersicht der geladenen Profile"
msgid "This section shows information for loaded profiles"
msgstr ""
msgstr "Dieser Abschnitt zeigt Informationen zu den geladenen Profilen"
msgid "Exports detailed overview of loaded profiles in json format"
msgstr ""
msgstr "Exportiert eine detaillierte Übersicht der geladenen Profile im JSON-Format"
msgid "Configurations folder"
msgstr ""
msgstr "Konfigurationsordner"
msgid "Opens configurations folder"
msgstr ""
msgstr "Öffnet den Konfigurationsordner"
msgid "Log level"
msgstr ""
msgstr "Protokollstufe"
msgid "Stored logs"
msgstr ""
msgstr "Gespeicherte Protokolle"
msgid "Packs all stored logs onto a zip file."
msgstr ""
msgstr "Packt alle gespeicherten Protokolle in eine ZIP-Datei."
msgid "Profiles"
msgstr ""
msgstr "Profile"
msgid "Select NO to close dialog and review project"
msgstr ""
msgstr "Wählen Sie NEIN, um das Dialogfeld zu schließen und das Projekt zu überprüfen"
msgid "No project file on current session. Only logs will be included to package"
msgstr ""
msgstr "Keine Projektdatei in der aktuellen Sitzung. Nur Protokolle werden in das Paket aufgenommen"
msgid "Select NO to close dialog and review project."
msgstr ""
msgstr "Wählen Sie NEIN, um das Dialogfeld zu schließen und das Projekt zu überprüfen."
msgid "Please make sure any instances of OrcaSlicer are not running"
msgstr ""
msgstr "Bitte stellen Sie sicher, dass keine Instanzen von OrcaSlicer ausgeführt werden."
msgid "System folder cannot be deleted because some files are in use by another application. Please close any applications using these files and try again."
msgstr ""
msgstr "Der Systemordner kann nicht gelöscht werden, da einige Dateien von einer anderen Anwendung verwendet werden. Bitte schließen Sie alle Anwendungen, die diese Dateien verwenden, und versuchen Sie es erneut."
msgid "Failed to delete system folder..."
msgstr ""
msgstr "Systemordner konnte nicht gelöscht werden..."
msgid "Failed to determine executable path."
msgstr ""
msgstr "Konnte den Pfad zur ausführbaren Datei nicht bestimmen."
msgid "Failed to launch a new instance."
msgstr ""
msgstr "Konnte keine neue Instanz starten."
msgid "log(s)"
msgstr ""
msgstr "Protokoll(e)"
msgid "Choose where to save the exported JSON file"
msgstr ""
msgstr "Wählen Sie, wo die exportierte JSON-Datei gespeichert werden soll"
msgid ""
"Export failed\n"
"Please check write permissions or file in use by another application"
msgstr ""
"Export fehlgeschlagen\n"
"Bitte überprüfen Sie die Schreibberechtigungen oder ob die Datei von einer anderen Anwendung verwendet wird."
msgid "Choose where to save the exported ZIP file"
msgstr ""
msgstr "Wählen Sie, wo die exportierte ZIP-Datei gespeichert werden soll"
msgid "File already exists. Overwrite?"
msgstr ""
msgstr "Datei existiert bereits. Überschreiben?"
msgid "3DPrinterOS Cloud upload options"
msgstr "3DPrinterOS Cloud-Upload-Optionen"
@@ -19318,17 +19330,17 @@ msgid "Could not connect to MKS"
msgstr "Konnte keine Verbindung zu MKS herstellen"
msgid "Connection to Moonraker is working correctly."
msgstr ""
msgstr "Verbindung zu Moonraker funktioniert korrekt."
msgid "Could not connect to Moonraker"
msgstr ""
msgstr "Konnte keine Verbindung zu Moonraker herstellen"
msgid "The host responded but it doesn't look like Moonraker (missing result.klippy_state)."
msgstr ""
msgstr "Der Host hat geantwortet, sieht aber nicht wie Moonraker aus (fehlender result.klippy_state)."
#, c-format, boost-format
msgid "Could not parse Moonraker server response: %s"
msgstr ""
msgstr "Konnte die Moonraker-Serverantwort nicht analysieren: %s"
msgid "Connection to OctoPrint is working correctly."
msgstr "Verbindung zu OctoPrint funktioniert korrekt."
+2 -2
View File
@@ -5093,7 +5093,7 @@ msgstr ""
msgid "Fan speed (%)"
msgstr ""
msgid "Temperature (°C)"
msgid "Temperature ()"
msgstr ""
msgid "Volumetric flow rate (mm³/s)"
@@ -15190,7 +15190,7 @@ msgid ""
msgstr ""
msgid ""
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50°C, without waiting for the full 60°C.\n"
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50, without waiting for the full 60.\n"
"\n"
"It sets a G-code variable named chamber_minimal_temperature, which can be passed to your print start macro or a heat soak macro, like this: PRINT_START (other variables) CHAMBER_MIN_TEMP=[chamber_minimal_temperature].\n"
"\n"
+3 -3
View File
@@ -5251,8 +5251,8 @@ msgstr "Jerk (mm/s)"
msgid "Fan speed (%)"
msgstr "Velocidad Ventilador (%)"
msgid "Temperature (°C)"
msgstr "Temperatura (°C)"
msgid "Temperature ()"
msgstr "Temperatura ()"
msgid "Volumetric flow rate (mm³/s)"
msgstr "Tasa de flujo volumétrico (mm³/seg)"
@@ -15997,7 +15997,7 @@ msgstr ""
"Esta funciuón es útil para imrpesoras no compatibles con los comandos M141 o M191, o si prefiere realizar un precalentamiento usando un macro si no dispone de un sistema de calentamiento activo de cámara."
msgid ""
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50°C, without waiting for the full 60°C.\n"
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50, without waiting for the full 60.\n"
"\n"
"It sets a G-code variable named chamber_minimal_temperature, which can be passed to your print start macro or a heat soak macro, like this: PRINT_START (other variables) CHAMBER_MIN_TEMP=[chamber_minimal_temperature].\n"
"\n"
+3 -3
View File
@@ -5248,8 +5248,8 @@ msgstr "Jerk (mm/s)"
msgid "Fan speed (%)"
msgstr "Vitesse du ventilateur (%)"
msgid "Temperature (°C)"
msgstr "Température (°C)"
msgid "Temperature ()"
msgstr "Température ()"
msgid "Volumetric flow rate (mm³/s)"
msgstr "Débit volumétrique (mm³/s)"
@@ -15968,7 +15968,7 @@ msgstr ""
"Sil est activé, ce paramètre définit également une variable gcode nommée chamber_temperature, qui peut être utilisée pour transmettre la température de caisson souhaitée à votre macro de démarrage de limpression, ou à une macro de trempe thermique comme celle-ci : PRINT_START (autres variables) CHAMBER_TEMP=[chamber_temperature]. Cela peut être utile si votre imprimante ne prend pas en charge les commandes M141/M191, ou si vous souhaitez gérer le préchauffage dans la macro de démarrage de limpression si aucun chauffage de caisson actif nest installé."
msgid ""
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50°C, without waiting for the full 60°C.\n"
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50, without waiting for the full 60.\n"
"\n"
"It sets a G-code variable named chamber_minimal_temperature, which can be passed to your print start macro or a heat soak macro, like this: PRINT_START (other variables) CHAMBER_MIN_TEMP=[chamber_minimal_temperature].\n"
"\n"
+2 -2
View File
@@ -5340,7 +5340,7 @@ msgstr "Rántás (mm/s)"
msgid "Fan speed (%)"
msgstr "Ventilátor fordulatszám (%)"
msgid "Temperature (°C)"
msgid "Temperature ()"
msgstr "Hőmérséklet (°C)"
msgid "Volumetric flow rate (mm³/s)"
@@ -16222,7 +16222,7 @@ msgstr ""
"Bekapcsolva ez a paraméter egy chamber_temperature nevű G-code változót is beállít, amely felhasználható a kívánt kamrahőmérséklet átadására a nyomtatásindító makrónak, vagy egy ilyen hőkiegyenlítő makrónak: PRINT_START (egyéb változók) CHAMBER_TEMP=[chamber_temperature]. Ez akkor lehet hasznos, ha a nyomtatód nem támogatja az M141/M191 parancsokat, vagy ha az aktív kamrafűtés hiányában a hőkiegyenlítést a nyomtatásindító makróban szeretnéd kezelni."
msgid ""
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50°C, without waiting for the full 60°C.\n"
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50, without waiting for the full 60.\n"
"\n"
"It sets a G-code variable named chamber_minimal_temperature, which can be passed to your print start macro or a heat soak macro, like this: PRINT_START (other variables) CHAMBER_MIN_TEMP=[chamber_minimal_temperature].\n"
"\n"
+3 -3
View File
@@ -5341,8 +5341,8 @@ msgstr "Scatto (mm/s)"
msgid "Fan speed (%)"
msgstr "Velocità ventola (%)"
msgid "Temperature (°C)"
msgstr "Temperatura (°C)"
msgid "Temperature ()"
msgstr "Temperatura ()"
msgid "Volumetric flow rate (mm³/s)"
msgstr "Portata volumetrica (mm³/s)"
@@ -16191,7 +16191,7 @@ msgstr ""
"Se abilitato, questo parametro imposta anche una variabile G-code denominata chamber_temperature, che può essere utilizzata per passare la temperatura desiderata della camera nella macro di inizio stampa o in una macro di preriscaldamento in questo modo: PRINT_START (altre variabili) CHAMBER_TEMP=[chamber_temperature]. Questo può essere utile se la stampante non supporta i comandi M141/M191 o, se non è presente un sistema di riscaldamento della camera, si desidera gestire il preriscaldamento nella macro di inizio stampa."
msgid ""
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50°C, without waiting for the full 60°C.\n"
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50, without waiting for the full 60.\n"
"\n"
"It sets a G-code variable named chamber_minimal_temperature, which can be passed to your print start macro or a heat soak macro, like this: PRINT_START (other variables) CHAMBER_MIN_TEMP=[chamber_minimal_temperature].\n"
"\n"
+2 -2
View File
@@ -5314,7 +5314,7 @@ msgstr "Jerk (mm/s)"
msgid "Fan speed (%)"
msgstr "ファン回転速度 (%)"
msgid "Temperature (°C)"
msgid "Temperature ()"
msgstr "温度 (℃)"
msgid "Volumetric flow rate (mm³/s)"
@@ -15803,7 +15803,7 @@ msgid ""
msgstr ""
msgid ""
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50°C, without waiting for the full 60°C.\n"
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50, without waiting for the full 60.\n"
"\n"
"It sets a G-code variable named chamber_minimal_temperature, which can be passed to your print start macro or a heat soak macro, like this: PRINT_START (other variables) CHAMBER_MIN_TEMP=[chamber_minimal_temperature].\n"
"\n"
+2 -2
View File
@@ -5340,7 +5340,7 @@ msgstr "Jerk (mm/s)"
msgid "Fan speed (%)"
msgstr "팬 속도 (%)"
msgid "Temperature (°C)"
msgid "Temperature ()"
msgstr "온도 (℃)"
msgid "Volumetric flow rate (mm³/s)"
@@ -16052,7 +16052,7 @@ msgstr ""
"활성화된 경우 이 매개변수는 원하는 챔버 온도를 출력 시작 매크로 또는 PRINT_START(기타 변수) CHAMBER_TEMP=[chamber_temp]와 같은 열 흡수 매크로에 전달하는 데 사용할 수 있는 Chamber_temp라는 Gcode 변수도 설정합니다. 이는 프린터가 M141/M191 명령을 지원하지 않거나 활성 챔버 히터가 설치되지 않은 경우 출력 시작 매크로에서 열 흡수를 처리하려는 경우 유용할 수 있습니다."
msgid ""
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50°C, without waiting for the full 60°C.\n"
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50, without waiting for the full 60.\n"
"\n"
"It sets a G-code variable named chamber_minimal_temperature, which can be passed to your print start macro or a heat soak macro, like this: PRINT_START (other variables) CHAMBER_MIN_TEMP=[chamber_minimal_temperature].\n"
"\n"
+2
View File
@@ -287,4 +287,6 @@ src/slic3r/GUI/DownloaderFileGet.cpp
src/slic3r/GUI/FileArchiveDialog.cpp
src/slic3r/GUI/PrinterCloudAuthDialog.cpp
src/slic3r/GUI/PrinterWebViewHandler.cpp
src/slic3r/GUI/AMSDryControl.cpp
src/slic3r/GUI/AMSDryControl.hpp
src/libslic3r/PresetBundle.cpp
+2 -2
View File
@@ -5222,8 +5222,8 @@ msgstr "Trūktelėjimas (mm/s)"
msgid "Fan speed (%)"
msgstr ""
msgid "Temperature (°C)"
msgstr "Temperatūra (°C)"
msgid "Temperature ()"
msgstr "Temperatūra ()"
msgid "Volumetric flow rate (mm³/s)"
msgstr "Tūrinis srautas (mm³/s)"
+3 -3
View File
@@ -5285,8 +5285,8 @@ msgstr "Jerk (mm/s)"
msgid "Fan speed (%)"
msgstr "Ventilator snelheid (%)"
msgid "Temperature (°C)"
msgstr "Temperatuur (°C)"
msgid "Temperature ()"
msgstr "Temperatuur ()"
msgid "Volumetric flow rate (mm³/s)"
msgstr "Volumestroom (mm³/s)"
@@ -15730,7 +15730,7 @@ msgid ""
msgstr ""
msgid ""
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50°C, without waiting for the full 60°C.\n"
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50, without waiting for the full 60.\n"
"\n"
"It sets a G-code variable named chamber_minimal_temperature, which can be passed to your print start macro or a heat soak macro, like this: PRINT_START (other variables) CHAMBER_MIN_TEMP=[chamber_minimal_temperature].\n"
"\n"
+7 -7
View File
@@ -5337,8 +5337,8 @@ msgstr "Jerk (mm/s)"
msgid "Fan speed (%)"
msgstr "Prędkość wentylatora (%)"
msgid "Temperature (°C)"
msgstr "Temperatura (°C)"
msgid "Temperature ()"
msgstr "Temperatura ()"
msgid "Volumetric flow rate (mm³/s)"
msgstr "Natężenie przepływu (mm³/s)"
@@ -16069,7 +16069,7 @@ msgstr ""
"Jeśli włączona, ten parametr ustawia także zmienną gcode o nazwie chamber_temperature, która może być użyta do przekazania żądanej temperatury komory do makra rozpoczynającego drukowanie, lub makra utrzymywania ciepła, na przykład: PRINT_START (inne zmienne) CHAMBER_TEMP=[chamber_temperature]. Może to być przydatne, jeśli twoja drukarka nie obsługuje poleceń M141/M191 lub jeśli chcesz zarządzać utrzymywaniem ciepła w makrze rozpoczynającym drukowanie, jeśli nie jest zainstalowany aktywna podgrzewacz komory."
msgid ""
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50°C, without waiting for the full 60°C.\n"
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50, without waiting for the full 60.\n"
"\n"
"It sets a G-code variable named chamber_minimal_temperature, which can be passed to your print start macro or a heat soak macro, like this: PRINT_START (other variables) CHAMBER_MIN_TEMP=[chamber_minimal_temperature].\n"
"\n"
@@ -22423,8 +22423,8 @@ msgstr ""
#~ msgid "Enter the nozzle_temperature needed for extruding your filament."
#~ msgstr "Wprowadź temperaturę dyszy potrzebną do ekstruzji filamentu."
#~ msgid "A rule of thumb is 160 to 230 °C for PLA, and 215 to 250 °C for ABS."
#~ msgstr "Generalną zasadą jest 160 do 230 °C dla PLA i 215 do 250 °C dla ABS."
#~ msgid "A rule of thumb is 160 to 230 for PLA, and 215 to 250 for ABS."
#~ msgstr "Generalną zasadą jest 160 do 230 dla PLA i 215 do 250 dla ABS."
#~ msgid "Extrusion Temperature:"
#~ msgstr "Temperatura ekstrudera:"
@@ -22432,8 +22432,8 @@ msgstr ""
#~ msgid "Enter the bed temperature needed for getting your filament to stick to your heated bed."
#~ msgstr "Wprowadź temperaturę potrzebną do dobrego przylegania filamentu do powierzchni podgrzewanego stołu."
#~ msgid "A rule of thumb is 60 °C for PLA and 110 °C for ABS. Leave zero if you have no heated bed."
#~ msgstr "Generalną zasadą jest 60 °C dla PLA i 110 °C dla ABS. Ustaw zero, jeśli nie masz podgrzewanego stołu."
#~ msgid "A rule of thumb is 60 for PLA and 110 for ABS. Leave zero if you have no heated bed."
#~ msgstr "Generalną zasadą jest 60 dla PLA i 110 dla ABS. Ustaw zero, jeśli nie masz podgrzewanego stołu."
#~ msgid "Bed Temperature:"
#~ msgstr "Temperatura stołu"
+2 -2
View File
@@ -5256,7 +5256,7 @@ msgstr "Jerk (mm/s)"
msgid "Fan speed (%)"
msgstr "Velocidade do ventilador (%)"
msgid "Temperature (°C)"
msgid "Temperature ()"
msgstr "Temperatura (℃)"
msgid "Volumetric flow rate (mm³/s)"
@@ -16049,7 +16049,7 @@ msgstr ""
"Se habilitado, este parâmetro também define uma variável G-code chamada chamber_temperature, que pode ser usada para passar a temperatura desejada da câmara para sua macro de início de impressão ou uma macro de absorção de calor como esta: PRINT_START (outras variáveis) CHAMBER_TEMP=[chamber_temperature]. Isso pode ser útil se sua impressora não suportar comandos M141/M191 ou se você desejar lidar com a absorção de calor na macro de início de impressão se nenhum aquecedor de câmara ativo estiver instalado."
msgid ""
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50°C, without waiting for the full 60°C.\n"
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50, without waiting for the full 60.\n"
"\n"
"It sets a G-code variable named chamber_minimal_temperature, which can be passed to your print start macro or a heat soak macro, like this: PRINT_START (other variables) CHAMBER_MIN_TEMP=[chamber_minimal_temperature].\n"
"\n"
+2 -2
View File
@@ -5417,7 +5417,7 @@ msgstr "Jerk (mm/s)"
msgid "Fan speed (%)"
msgstr "Скорость вентилятора (%)"
msgid "Temperature (°C)"
msgid "Temperature ()"
msgstr "Температура (°C)"
msgid "Volumetric flow rate (mm³/s)"
@@ -16781,7 +16781,7 @@ msgstr ""
"Это особенно полезно, если принтер не поддерживает команды M141/M191, или если управление температурой термокамеры реализовано через макросы (например, при отсутствии активного нагревателя камеры)."
msgid ""
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50°C, without waiting for the full 60°C.\n"
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50, without waiting for the full 60.\n"
"\n"
"It sets a G-code variable named chamber_minimal_temperature, which can be passed to your print start macro or a heat soak macro, like this: PRINT_START (other variables) CHAMBER_MIN_TEMP=[chamber_minimal_temperature].\n"
"\n"
+3 -3
View File
@@ -5275,8 +5275,8 @@ msgstr "Jerk (mm/s)"
msgid "Fan speed (%)"
msgstr "Fläkt hastighet (%)"
msgid "Temperature (°C)"
msgstr "Temperatur (°C)"
msgid "Temperature ()"
msgstr "Temperatur ()"
msgid "Volumetric flow rate (mm³/s)"
msgstr "Volymetrisk flödeshastighet (mm³/s)"
@@ -15701,7 +15701,7 @@ msgid ""
msgstr ""
msgid ""
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50°C, without waiting for the full 60°C.\n"
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50, without waiting for the full 60.\n"
"\n"
"It sets a G-code variable named chamber_minimal_temperature, which can be passed to your print start macro or a heat soak macro, like this: PRINT_START (other variables) CHAMBER_MIN_TEMP=[chamber_minimal_temperature].\n"
"\n"
+3 -3
View File
@@ -5223,8 +5223,8 @@ msgstr "กระตุก (มม./วินาที)"
msgid "Fan speed (%)"
msgstr "ความเร็วพัดลม (%)"
msgid "Temperature (°C)"
msgstr "อุณหภูมิ (°C)"
msgid "Temperature ()"
msgstr "อุณหภูมิ ()"
msgid "Volumetric flow rate (mm³/s)"
msgstr "อัตราการไหลเชิงปริมาตร (มม.³/วินาที)"
@@ -15887,7 +15887,7 @@ msgstr ""
"หากเปิดใช้งาน พารามิเตอร์นี้จะตั้งค่าตัวแปร G-code ชื่อ Chamber_temperature ซึ่งสามารถใช้เพื่อส่งอุณหภูมิห้องเพาะเลี้ยงที่ต้องการไปยังมาโครเริ่มการพิมพ์ของคุณ หรือมาโครความร้อนแช่เช่นนี้: PRINT_START (ตัวแปรอื่นๆ) CHAMBER_TEMP=[chamber_temperature] วิธีนี้อาจเป็นประโยชน์หากเครื่องพิมพ์ของคุณไม่รองรับคำสั่ง M141/M191 หรือหากคุณต้องการจัดการกับความร้อนที่แช่อยู่ในมาโครเริ่มการพิมพ์ หากไม่มีการติดตั้งเครื่องทำความร้อนในห้องที่ใช้งานอยู่"
msgid ""
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50°C, without waiting for the full 60°C.\n"
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50, without waiting for the full 60.\n"
"\n"
"It sets a G-code variable named chamber_minimal_temperature, which can be passed to your print start macro or a heat soak macro, like this: PRINT_START (other variables) CHAMBER_MIN_TEMP=[chamber_minimal_temperature].\n"
"\n"
+3 -3
View File
@@ -5341,8 +5341,8 @@ msgstr "Jerk (mm/s)"
msgid "Fan speed (%)"
msgstr "Fan hızı (%)"
msgid "Temperature (°C)"
msgstr "Sıcaklık (°C)"
msgid "Temperature ()"
msgstr "Sıcaklık ()"
msgid "Volumetric flow rate (mm³/s)"
msgstr "Hacimsel akış hızı (mm³/s)"
@@ -16113,7 +16113,7 @@ msgstr ""
"Etkinleştirilirse, bu parametre aynı zamanda istenen oda sıcaklığını yazdırma başlatma makronuza veya şuna benzer bir ısı emme makrosuna iletmek için kullanılabilecek Chamber_temperature adlı bir gcode değişkenini de ayarlar: PRINT_START (diğer değişkenler) CHAMBER_TEMP=[chamber_temperature]. Yazıcınız M141/M191 komutlarını desteklemiyorsa veya aktif oda ısıtıcısı takılı değilse yazdırma başlatma makrosunda ısı bekletme işlemini gerçekleştirmek istiyorsanız bu yararlı olabilir."
msgid ""
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50°C, without waiting for the full 60°C.\n"
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50, without waiting for the full 60.\n"
"\n"
"It sets a G-code variable named chamber_minimal_temperature, which can be passed to your print start macro or a heat soak macro, like this: PRINT_START (other variables) CHAMBER_MIN_TEMP=[chamber_minimal_temperature].\n"
"\n"
+3 -3
View File
@@ -5344,8 +5344,8 @@ msgstr "Jerk (mm/s)"
msgid "Fan speed (%)"
msgstr "Швидкість Вентилятора (%)"
msgid "Temperature (°C)"
msgstr "Температура (°С)"
msgid "Temperature ()"
msgstr "Температура ()"
msgid "Volumetric flow rate (mm³/s)"
msgstr "Об'ємна витрата (мм³/с)"
@@ -16089,7 +16089,7 @@ msgstr ""
"Це може бути корисним, якщо ваш принтер не підтримує команди M141/M191 або якщо ви хочете керувати прогрівом камери у макросі запуску друку за відсутності активного нагрівача камери."
msgid ""
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50°C, without waiting for the full 60°C.\n"
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50, without waiting for the full 60.\n"
"\n"
"It sets a G-code variable named chamber_minimal_temperature, which can be passed to your print start macro or a heat soak macro, like this: PRINT_START (other variables) CHAMBER_MIN_TEMP=[chamber_minimal_temperature].\n"
"\n"
+3 -3
View File
@@ -5315,8 +5315,8 @@ msgstr "Jerk (mm/s)"
msgid "Fan speed (%)"
msgstr "Tốc độ quạt (%)"
msgid "Temperature (°C)"
msgstr "Nhiệt độ (°C)"
msgid "Temperature ()"
msgstr "Nhiệt độ ()"
msgid "Volumetric flow rate (mm³/s)"
msgstr "Tốc độ flow thể tích (mm³/s)"
@@ -16000,7 +16000,7 @@ msgstr ""
"Nếu được bật, tham số này cũng đặt biến G-code có tên chamber_temperature, có thể được sử dụng để truyền nhiệt độ buồng mong muốn cho macro bắt đầu in của bạn, hoặc macro ngâm nhiệt như thế này: PRINT_START (các biến khác) CHAMBER_TEMP=[chamber_temperature]. Điều này có thể hữu ích nếu máy in của bạn không hỗ trợ lệnh M141/M191, hoặc nếu bạn muốn xử lý ngâm nhiệt trong macro bắt đầu in nếu không có bộ sưởi buồng hoạt động được cài đặt."
msgid ""
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50°C, without waiting for the full 60°C.\n"
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50, without waiting for the full 60.\n"
"\n"
"It sets a G-code variable named chamber_minimal_temperature, which can be passed to your print start macro or a heat soak macro, like this: PRINT_START (other variables) CHAMBER_MIN_TEMP=[chamber_minimal_temperature].\n"
"\n"
+2 -2
View File
@@ -5328,7 +5328,7 @@ msgstr "抖动 (mm/s)"
msgid "Fan speed (%)"
msgstr "风扇速度(%"
msgid "Temperature (°C)"
msgid "Temperature ()"
msgstr "温度(℃)"
msgid "Volumetric flow rate (mm³/s)"
@@ -16215,7 +16215,7 @@ msgid ""
msgstr "对于 ABS、ASA、PC 和 PA 等高温材料,较高的腔室温度有助于抑制或减少翘曲,并有可能提高层间粘合强度。但同时,较高的腔室温度会降低 ABS 和 ASA 的空气过滤效率。 对于 PLA、PETG、TPU、PVA 等低温材料,应禁用此选项(设置为 0),因为腔室温度应较低,以避免热断时材料软化导致挤出机堵塞。 如果启用,此参数还会设置一个名为 chamber_temple 的 G-code 变量,该变量可用于将所需的腔室温度传递给打印启动宏,或热浸宏,如下所示:PRINT_START(其他变量)CHAMBER_TEMP=[chamber_Temperature]。如果您的打印机不支持 M141/M191 命令,或者如果您希望在未安装活动室加热器的情况下在打印启动宏中处理热浸,则这可能很有用。"
msgid ""
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50°C, without waiting for the full 60°C.\n"
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50, without waiting for the full 60.\n"
"\n"
"It sets a G-code variable named chamber_minimal_temperature, which can be passed to your print start macro or a heat soak macro, like this: PRINT_START (other variables) CHAMBER_MIN_TEMP=[chamber_minimal_temperature].\n"
"\n"
+2 -2
View File
@@ -5370,7 +5370,7 @@ msgstr "急衝速度 (mm/s)"
msgid "Fan speed (%)"
msgstr "風扇速度(%"
msgid "Temperature (°C)"
msgid "Temperature ()"
msgstr "溫度(℃)"
msgid "Volumetric flow rate (mm³/s)"
@@ -16263,7 +16263,7 @@ msgid ""
msgstr "對於 ABS、ASA、PC 和 PA 等高溫材料,較高的機箱溫度能有效抑制或減少翹曲,並可能提升層間結合強度。然而,較高的機箱溫度也會降低 ABS 和 ASA 的空氣過濾效率。對於 PLA、PETG、TPU、PVA 和其他低溫材料,建議將此選項停用(設為 0),因機箱溫度應保持較低,以避免因材料在熱端軟化而導致擠出機堵塞。啟用此選項後,會設置一個名為 chamber_temperature 的 G-code 變數,可用於將所需的機箱溫度傳遞給列印開始宏,或像以下的熱浸泡宏(預熱):PRINT_START (其他變數) CHAMBER_TEMP=[chamber_temperature]。這對於不支援 M141/M191 指令的列印設備,或者希望在列印開始宏中處理熱浸泡(預熱)但未安裝主動機箱加熱器的情況下非常實用。"
msgid ""
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50°C, without waiting for the full 60°C.\n"
"This is the chamber temperature at which printing should start, while the chamber continues heating toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to begin printing once the chamber reaches 50, without waiting for the full 60.\n"
"\n"
"It sets a G-code variable named chamber_minimal_temperature, which can be passed to your print start macro or a heat soak macro, like this: PRINT_START (other variables) CHAMBER_MIN_TEMP=[chamber_minimal_temperature].\n"
"\n"
@@ -0,0 +1,5 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="12" cy="12" r="9.35422" fill="#E14747" stroke="#E14747" stroke-width="1.29157"/>
<rect x="11" y="6" width="2" height="9" rx="1" fill="white"/>
<rect x="11" y="16" width="2" height="2" rx="1" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 321 B

@@ -0,0 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M1.80005 12.3C1.80005 6.83238 6.23243 2.4 11.7 2.4C17.1677 2.4 21.6 6.83238 21.6 12.3C21.6 17.7676 17.1677 22.2 11.7 22.2C6.23243 22.2 1.80005 17.7676 1.80005 12.3Z" fill="#009688"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M17.7742 8.66235C18.0746 8.9415 18.0918 9.41131 17.8126 9.7117L12.2128 15.7376C11.5275 16.4751 10.36 16.4751 9.67461 15.7376L6.82482 12.6709C6.54567 12.3706 6.56289 11.9007 6.86328 11.6216C7.16367 11.3424 7.63348 11.3597 7.91263 11.66L10.7624 14.7267C10.8603 14.832 11.0271 14.832 11.125 14.7267L16.7248 8.70081C17.004 8.40042 17.4738 8.3832 17.7742 8.66235Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 759 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.3125 0.7125V2.6125C8.3125 3.00734 7.99484 3.325 7.6 3.325C7.20516 3.325 6.8875 3.00734 6.8875 2.6125V0.7125C6.8875 0.317656 7.20516 0 7.6 0C7.99484 0 8.3125 0.317656 8.3125 0.7125ZM12.9734 3.23297L11.6286 4.57781C11.3495 4.85687 10.8983 4.85687 10.6222 4.57781C10.3461 4.29875 10.3431 3.8475 10.6222 3.57141L11.967 2.22656C12.2461 1.9475 12.6973 1.9475 12.9734 2.22656C13.2495 2.50562 13.2525 2.95688 12.9734 3.23297ZM3.23297 2.22656L4.57781 3.57141C4.85687 3.85047 4.85687 4.30172 4.57781 4.57781C4.29875 4.85391 3.8475 4.85687 3.57141 4.57781L2.22656 3.23297C1.9475 2.95391 1.9475 2.50266 2.22656 2.22656C2.50562 1.95047 2.95688 1.9475 3.23297 2.22656ZM0.7125 6.8875H2.6125C3.00734 6.8875 3.325 7.20516 3.325 7.6C3.325 7.99484 3.00734 8.3125 2.6125 8.3125H0.7125C0.317656 8.3125 0 7.99484 0 7.6C0 7.20516 0.317656 6.8875 0.7125 6.8875ZM12.5875 6.8875H14.4875C14.8823 6.8875 15.2 7.20516 15.2 7.6C15.2 7.99484 14.8823 8.3125 14.4875 8.3125H12.5875C12.1927 8.3125 11.875 7.99484 11.875 7.6C11.875 7.20516 12.1927 6.8875 12.5875 6.8875ZM4.57781 11.6316L3.23297 12.9734C2.95391 13.2525 2.50266 13.2525 2.22656 12.9734C1.95047 12.6944 1.9475 12.2431 2.22656 11.967L3.57141 10.6222C3.85047 10.3431 4.30172 10.3431 4.57781 10.6222C4.85391 10.9012 4.85687 11.3525 4.57781 11.6286V11.6316ZM11.6316 10.6252L12.9734 11.967C13.2525 12.2461 13.2525 12.6973 12.9734 12.9734C12.6944 13.2495 12.2431 13.2525 11.967 12.9734L10.6222 11.6286C10.3431 11.3495 10.3431 10.8983 10.6222 10.6222C10.9012 10.3461 11.3525 10.3431 11.6286 10.6222L11.6316 10.6252ZM8.3125 12.5875V14.4875C8.3125 14.8823 7.99484 15.2 7.6 15.2C7.20516 15.2 6.8875 14.8823 6.8875 14.4875V12.5875C6.8875 12.1927 7.20516 11.875 7.6 11.875C7.99484 11.875 8.3125 12.1927 8.3125 12.5875ZM9.5 7.6C9.5 7.09609 9.29982 6.61282 8.9435 6.2565C8.58718 5.90018 8.10391 5.7 7.6 5.7C7.09609 5.7 6.61282 5.90018 6.2565 6.2565C5.90018 6.61282 5.7 7.09609 5.7 7.6C5.7 8.10391 5.90018 8.58718 6.2565 8.9435C6.61282 9.29982 7.09609 9.5 7.6 9.5C8.10391 9.5 8.58718 9.29982 8.9435 8.9435C9.29982 8.58718 9.5 8.10391 9.5 7.6ZM4.275 7.6C4.275 6.71815 4.62531 5.87243 5.24887 5.24887C5.87243 4.62531 6.71815 4.275 7.6 4.275C8.48184 4.275 9.32757 4.62531 9.95113 5.24887C10.5747 5.87243 10.925 6.71815 10.925 7.6C10.925 8.48184 10.5747 9.32757 9.95113 9.95113C9.32757 10.5747 8.48184 10.925 7.6 10.925C6.71815 10.925 5.87243 10.5747 5.24887 9.95113C4.62531 9.32757 4.275 8.48184 4.275 7.6Z" fill="#F09A17"/>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

@@ -42,8 +42,8 @@
"filament_z_hop_types": [
"Normal Lift"
],
"filament_scarf_seam_type": [
"none"
"filament_dev_drying_cooling_temperature": [
"70"
],
"impact_strength_z": [
"3.4"
@@ -32,6 +32,9 @@
"filament_vendor": [
"Bambu Lab"
],
"filament_dev_drying_cooling_temperature": [
"95"
],
"hot_plate_temp": [
"100"
],
@@ -33,6 +33,9 @@
"full_fan_speed_layer": [
"2"
],
"filament_dev_chamber_drying_time": [
"16"
],
"impact_strength_z": [
"13.3"
],
@@ -45,6 +45,27 @@
"filament_adhesiveness_category": [
"800"
],
"filament_dev_chamber_drying_bed_temperature": [
"90"
],
"filament_dev_ams_drying_ams_limitations": [
"1"
],
"filament_dev_ams_drying_heat_distortion_temperature": [
"165"
],
"filament_dev_drying_cooling_temperature": [
"150"
],
"filament_dev_ams_drying_temperature": [
"65",
"80",
"65",
"80"
],
"filament_dev_drying_softening_temperature": [
"150"
],
"hot_plate_temp": [
"100"
],
@@ -24,6 +24,24 @@
"filament_adhesiveness_category": [
"703"
],
"filament_dev_chamber_drying_time": [
"16"
],
"filament_dev_ams_drying_heat_distortion_temperature": [
"90"
],
"filament_dev_drying_cooling_temperature": [
"75"
],
"filament_dev_ams_drying_temperature": [
"65",
"80",
"65",
"80"
],
"filament_dev_drying_softening_temperature": [
"85"
],
"nozzle_temperature": [
"280"
],
@@ -24,11 +24,20 @@
"filament_vendor": [
"Bambu Lab"
],
"filament_scarf_seam_type": [
"none"
],
"filament_adhesiveness_category": [
"702"
],
"filament_dev_ams_drying_temperature": [
"60",
"60",
"50",
"50"
],
"filament_dev_ams_drying_heat_distortion_temperature": [
"50"
],
"filament_dev_drying_softening_temperature": [
"55"
],
"slow_down_layer_time": [
"8"
@@ -27,14 +27,26 @@
"filament_max_volumetric_speed": [
"6"
],
"filament_scarf_seam_type": [
"none"
],
"filament_vendor": [
"Bambu Lab"
],
"filament_adhesiveness_category": [
"705"
],
"filament_dev_chamber_drying_bed_temperature": [
"80"
],
"filament_dev_ams_drying_temperature": [
"60",
"60",
"50",
"50"
],
"filament_dev_ams_drying_heat_distortion_temperature": [
"50"
],
"filament_dev_drying_softening_temperature": [
"55"
],
"hot_plate_temp": [
"60"
@@ -21,11 +21,26 @@
"filament_vendor": [
"Bambu Lab"
],
"filament_scarf_seam_type": [
"none"
],
"filament_adhesiveness_category": [
"701"
],
"filament_dev_chamber_drying_time": [
"16"
],
"filament_dev_ams_drying_heat_distortion_temperature": [
"90"
],
"filament_dev_drying_cooling_temperature": [
"75"
],
"filament_dev_ams_drying_temperature": [
"65",
"80",
"65",
"80"
],
"filament_dev_drying_softening_temperature": [
"85"
],
"nozzle_temperature": [
"280"
@@ -27,11 +27,14 @@
"filament_vendor": [
"Bambu Lab"
],
"filament_scarf_seam_type": [
"none"
],
"filament_adhesiveness_category": [
"706"
],
"filament_dev_ams_drying_time": [
"12",
"4",
"12",
"4"
],
"nozzle_temperature_range_high": [
"270"
@@ -21,6 +21,21 @@
"filament_max_volumetric_speed": [
"12"
],
"filament_dev_ams_drying_temperature": [
"65",
"80",
"65",
"80"
],
"filament_dev_ams_drying_heat_distortion_temperature": [
"90"
],
"filament_dev_drying_cooling_temperature": [
"65"
],
"filament_dev_drying_softening_temperature": [
"85"
],
"nozzle_temperature": [
"260"
],
@@ -38,6 +38,34 @@
"filament_max_volumetric_speed": [
"6"
],
"filament_dev_chamber_drying_bed_temperature": [
"80"
],
"filament_dev_ams_drying_time": [
"12",
"12",
"12",
"12"
],
"filament_dev_ams_drying_ams_limitations": [
"1",
"0"
],
"filament_dev_ams_drying_heat_distortion_temperature": [
"75"
],
"filament_dev_drying_cooling_temperature": [
"55"
],
"filament_dev_ams_drying_temperature": [
"65",
"65",
"55",
"55"
],
"filament_dev_drying_softening_temperature": [
"60"
],
"hot_plate_temp": [
"70"
],
@@ -4,5 +4,26 @@
"inherits": "fdm_filament_pps",
"from": "system",
"filament_id": "GFT97",
"instantiation": "false"
"instantiation": "false",
"filament_dev_chamber_drying_bed_temperature": [
"90"
],
"filament_dev_ams_drying_ams_limitations": [
"1"
],
"filament_dev_ams_drying_heat_distortion_temperature": [
"90"
],
"filament_dev_drying_cooling_temperature": [
"80"
],
"filament_dev_ams_drying_temperature": [
"65",
"80",
"65",
"80"
],
"filament_dev_drying_softening_temperature": [
"85"
]
}
@@ -41,6 +41,30 @@
"filament_vendor": [
"Polymaker"
],
"filament_adhesiveness_category": [
"800"
],
"filament_dev_chamber_drying_bed_temperature": [
"90"
],
"filament_dev_ams_drying_ams_limitations": [
"1"
],
"filament_dev_ams_drying_heat_distortion_temperature": [
"165"
],
"filament_dev_drying_cooling_temperature": [
"150"
],
"filament_dev_ams_drying_temperature": [
"65",
"80",
"65",
"80"
],
"filament_dev_drying_softening_temperature": [
"150"
],
"hot_plate_temp": [
"70"
],
@@ -83,9 +107,6 @@
"textured_plate_temp_initial_layer": [
"70"
],
"filament_adhesiveness_category": [
"800"
],
"filament_start_gcode": [
"; filament start gcode\n{if (bed_temperature[current_extruder] >80)||(bed_temperature_initial_layer[current_extruder] >80)}M106 P3 S255\n{elsif (bed_temperature[current_extruder] >60)||(bed_temperature_initial_layer[current_extruder] >60)}M106 P3 S180\n{endif}\n\n{if activate_air_filtration[current_extruder] && support_air_filtration}\nM106 P3 S{during_print_exhaust_fan_speed_num[current_extruder]} \n{endif}"
]
@@ -43,6 +43,27 @@
"filament_adhesiveness_category": [
"200"
],
"filament_dev_ams_drying_time": [
"12",
"8.0",
"12",
"8.0"
],
"filament_dev_ams_drying_heat_distortion_temperature": [
"90"
],
"filament_dev_drying_cooling_temperature": [
"75"
],
"filament_dev_ams_drying_temperature": [
"65",
"80",
"65",
"75"
],
"filament_dev_drying_softening_temperature": [
"80"
],
"hot_plate_temp": [
"90"
],
@@ -43,6 +43,27 @@
"filament_adhesiveness_category": [
"200"
],
"filament_dev_ams_drying_time": [
"12",
"8.0",
"12",
"8.0"
],
"filament_dev_ams_drying_heat_distortion_temperature": [
"100"
],
"filament_dev_drying_cooling_temperature": [
"85"
],
"filament_dev_ams_drying_temperature": [
"65",
"80",
"65",
"80"
],
"filament_dev_drying_softening_temperature": [
"85"
],
"hot_plate_temp": [
"90"
],
@@ -43,6 +43,34 @@
"filament_type": [
"BVOH"
],
"filament_dev_chamber_drying_bed_temperature": [
"80"
],
"filament_dev_ams_drying_time": [
"12",
"12",
"12",
"12"
],
"filament_dev_ams_drying_ams_limitations": [
"1",
"0"
],
"filament_dev_ams_drying_heat_distortion_temperature": [
"65"
],
"filament_dev_drying_cooling_temperature": [
"40"
],
"filament_dev_ams_drying_temperature": [
"60",
"60",
"45",
"45"
],
"filament_dev_drying_softening_temperature": [
"50"
],
"hot_plate_temp": [
"55"
],
@@ -7,6 +7,34 @@
"filament_type": [
"EVA"
],
"filament_dev_chamber_drying_bed_temperature": [
"70"
],
"filament_dev_ams_drying_time": [
"12",
"12",
"12",
"12"
],
"filament_dev_ams_drying_ams_limitations": [
"1",
"0"
],
"filament_dev_ams_drying_heat_distortion_temperature": [
"45"
],
"filament_dev_drying_cooling_temperature": [
"40"
],
"filament_dev_ams_drying_temperature": [
"45",
"45",
"45",
"45"
],
"filament_dev_drying_softening_temperature": [
"50"
],
"supertack_plate_temp": [
"0"
],
@@ -4,9 +4,6 @@
"inherits": "fdm_filament_common",
"from": "system",
"instantiation": "false",
"additional_cooling_fan_speed": [
"0"
],
"cool_plate_temp": [
"0"
],
@@ -42,6 +39,27 @@
],
"filament_adhesiveness_category": [
"798"
],
"filament_dev_ams_drying_time": [
"12",
"12",
"12",
"12"
],
"filament_dev_ams_drying_heat_distortion_temperature": [
"90"
],
"filament_dev_drying_cooling_temperature": [
"75"
],
"filament_dev_ams_drying_temperature": [
"65",
"80",
"65",
"75"
],
"filament_dev_drying_softening_temperature": [
"80"
],
"hot_plate_temp": [
"90"
@@ -43,6 +43,30 @@
"filament_adhesiveness_category": [
"400"
],
"filament_dev_ams_drying_time": [
"12",
"12",
"12",
"12"
],
"filament_dev_chamber_drying_time": [
"18"
],
"filament_dev_ams_drying_heat_distortion_temperature": [
"165"
],
"filament_dev_drying_cooling_temperature": [
"150"
],
"filament_dev_ams_drying_temperature": [
"65",
"85",
"65",
"85"
],
"filament_dev_drying_softening_temperature": [
"150"
],
"hot_plate_temp": [
"100"
],
@@ -40,6 +40,27 @@
"filament_adhesiveness_category": [
"500"
],
"filament_dev_ams_drying_time": [
"12",
"8.0",
"12",
"8.0"
],
"filament_dev_ams_drying_heat_distortion_temperature": [
"105"
],
"filament_dev_drying_cooling_temperature": [
"90"
],
"filament_dev_ams_drying_temperature": [
"65",
"80",
"65",
"80"
],
"filament_dev_drying_softening_temperature": [
"90"
],
"hot_plate_temp": [
"110"
],
@@ -28,6 +28,37 @@
"filament_type": [
"PCTG"
],
"filament_dev_chamber_drying_bed_temperature": [
"80"
],
"filament_dev_ams_drying_time": [
"12",
"12",
"12",
"12"
],
"filament_dev_ams_drying_ams_limitations": [
"1",
"0"
],
"filament_dev_chamber_drying_time": [
"12"
],
"filament_dev_ams_drying_heat_distortion_temperature": [
"75"
],
"filament_dev_drying_cooling_temperature": [
"55"
],
"filament_dev_ams_drying_temperature": [
"65",
"65",
"55",
"55"
],
"filament_dev_drying_softening_temperature": [
"60"
],
"hot_plate_temp": [
"80"
],
@@ -40,6 +40,31 @@
"filament_type": [
"PE"
],
"filament_dev_chamber_drying_bed_temperature": [
"70"
],
"filament_dev_ams_drying_time": [
"12",
"12",
"12",
"12"
],
"filament_dev_ams_drying_ams_limitations": [
"1",
"0"
],
"filament_dev_drying_cooling_temperature": [
"50"
],
"filament_dev_ams_drying_temperature": [
"45",
"45",
"45",
"45"
],
"filament_dev_drying_softening_temperature": [
"50"
],
"hot_plate_temp": [
"55"
],
@@ -31,6 +31,34 @@
"filament_adhesiveness_category": [
"300"
],
"filament_dev_chamber_drying_bed_temperature": [
"80"
],
"filament_dev_ams_drying_time": [
"12",
"12",
"12",
"12"
],
"filament_dev_ams_drying_ams_limitations": [
"1",
"0"
],
"filament_dev_ams_drying_heat_distortion_temperature": [
"75"
],
"filament_dev_drying_cooling_temperature": [
"55"
],
"filament_dev_ams_drying_temperature": [
"65",
"65",
"55",
"55"
],
"filament_dev_drying_softening_temperature": [
"60"
],
"hot_plate_temp": [
"80"
],
@@ -40,6 +40,31 @@
"filament_type": [
"PHA"
],
"filament_dev_chamber_drying_bed_temperature": [
"70"
],
"filament_dev_ams_drying_time": [
"12",
"12",
"12",
"12"
],
"filament_dev_ams_drying_ams_limitations": [
"1",
"0"
],
"filament_dev_drying_cooling_temperature": [
"45"
],
"filament_dev_ams_drying_temperature": [
"45",
"45",
"45",
"45"
],
"filament_dev_drying_softening_temperature": [
"50"
],
"hot_plate_temp": [
"55"
],
@@ -37,14 +37,39 @@
"filament_max_volumetric_speed": [
"12"
],
"filament_scarf_seam_type": [
"none"
],
"filament_scarf_gap": [
"15%"
],
"filament_adhesiveness_category": [
"100"
],
"filament_dev_chamber_drying_bed_temperature": [
"70"
],
"filament_dev_ams_drying_time": [
"12",
"12",
"12",
"12"
],
"filament_dev_ams_drying_ams_limitations": [
"1",
"0"
],
"filament_dev_ams_drying_heat_distortion_temperature": [
"45"
],
"filament_dev_drying_cooling_temperature": [
"45"
],
"filament_dev_ams_drying_temperature": [
"45",
"45",
"45",
"45"
],
"filament_dev_drying_softening_temperature": [
"50"
],
"hot_plate_temp": [
"55"
@@ -43,6 +43,34 @@
"filament_adhesiveness_category": [
"902"
],
"filament_dev_chamber_drying_bed_temperature": [
"70"
],
"filament_dev_ams_drying_time": [
"12",
"12",
"12",
"12"
],
"filament_dev_ams_drying_ams_limitations": [
"1",
"0"
],
"filament_dev_ams_drying_heat_distortion_temperature": [
"60"
],
"filament_dev_drying_cooling_temperature": [
"50"
],
"filament_dev_ams_drying_temperature": [
"60",
"60",
"50",
"50"
],
"filament_dev_drying_softening_temperature": [
"55"
],
"hot_plate_temp": [
"55"
],
@@ -46,6 +46,34 @@
"filament_vendor": [
"Bambu Lab"
],
"filament_dev_chamber_drying_bed_temperature": [
"100"
],
"filament_dev_ams_drying_time": [
"12",
"12",
"12",
"12"
],
"filament_dev_ams_drying_ams_limitations": [],
"filament_dev_chamber_drying_time": [
"18"
],
"filament_dev_ams_drying_heat_distortion_temperature": [
"165"
],
"filament_dev_drying_cooling_temperature": [
"150"
],
"filament_dev_ams_drying_temperature": [
"65",
"85",
"65",
"85"
],
"filament_dev_drying_softening_temperature": [
"150"
],
"hot_plate_temp": [
"100"
],
@@ -43,6 +43,31 @@
"filament_adhesiveness_category": [
"801"
],
"filament_dev_chamber_drying_bed_temperature": [
"100"
],
"filament_dev_ams_drying_time": [
"12",
"12",
"12",
"12"
],
"filament_dev_ams_drying_ams_limitations": [],
"filament_dev_ams_drying_heat_distortion_temperature": [
"165"
],
"filament_dev_drying_cooling_temperature": [
"150"
],
"filament_dev_ams_drying_temperature": [
"65",
"85",
"65",
"85"
],
"filament_dev_drying_softening_temperature": [
"150"
],
"hot_plate_temp": [
"110"
],
@@ -49,6 +49,27 @@
"filament_adhesiveness_category": [
"704"
],
"filament_dev_ams_drying_time": [
"12",
"18",
"12",
"18"
],
"filament_dev_ams_drying_heat_distortion_temperature": [
"75"
],
"filament_dev_drying_cooling_temperature": [
"40"
],
"filament_dev_ams_drying_temperature": [
"65",
"85",
"65",
"70"
],
"filament_dev_drying_softening_temperature": [
"75"
],
"hot_plate_temp": [
"55"
],
@@ -46,6 +46,30 @@
"filament_adhesiveness_category": [
"600"
],
"filament_dev_ams_drying_time": [
"12",
"18",
"12",
"18"
],
"filament_dev_chamber_drying_time": [
"16"
],
"filament_dev_ams_drying_heat_distortion_temperature": [
"45"
],
"filament_dev_drying_cooling_temperature": [
"40"
],
"filament_dev_ams_drying_temperature": [
"65",
"75",
"45",
"45"
],
"filament_dev_drying_softening_temperature": [
"50"
],
"hot_plate_temp": [
"35"
],
File diff suppressed because one or more lines are too long
@@ -3,7 +3,7 @@
"name": "0.40mm Standard @Creality K1 SE 0.8 nozzle",
"inherits": "fdm_process_creality_common",
"from": "system",
"setting_id": "caYmVSsFmtESzLNF",
"setting_id": "5mfhrVJYlK4lWDUs",
"instantiation": "true",
"reduce_crossing_wall": "0",
"max_travel_detour_distance": "0",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "Qidi",
"version": "02.04.00.07",
"version": "02.04.00.08",
"force_update": "0",
"description": "Qidi configurations",
"machine_model_list": [
@@ -10,36 +10,6 @@
"machine_pause_gcode": "M0",
"support_chamber_temp_control": "1",
"wipe_tower_type": "type1",
"filament_dev_ams_drying_ams_limitations": [
"1"
],
"filament_dev_ams_drying_temperature": [
"40.0",
"40.0",
"40.0",
"40.0"
],
"filament_dev_ams_drying_time": [
"8.0",
"8.0",
"8.0",
"8.0"
],
"filament_dev_drying_softening_temperature": [
"40.0"
],
"filament_dev_ams_drying_heat_distortion_temperature": [
"45.0"
],
"filament_dev_drying_cooling_temperature": [
"35.0"
],
"filament_dev_chamber_drying_bed_temperature": [
"90.0"
],
"filament_dev_chamber_drying_time": [
"12.0"
],
"retraction_length": [
"1"
],
@@ -3,7 +3,7 @@
"name": "0.30mm Big @RatRig V-Core 4 0.8",
"inherits": "fdm_process_ratrig_common",
"from": "system",
"setting_id": "7FOG8fkUbrLknvuz",
"setting_id": "2tM04aSQ8NcTsmQo",
"instantiation": "true",
"layer_height": "0.3",
"inital_layer_height": "0.35",
@@ -3,6 +3,7 @@
"name": "0.15mm Standard @iQ TiQ2 (0.25 Nozzle)",
"inherits": "fdm_process_tiq_common",
"from": "system",
"setting_id": "PNxZXC0peOlGlKwG",
"instantiation": "true",
"compatible_printers": [
"iQ TiQ2 0.25 Nozzle"
@@ -3,6 +3,7 @@
"name": "0.15mm Standard @iQ TiQ8 (0.25 Nozzle)",
"inherits": "fdm_process_tiq_common",
"from": "system",
"setting_id": "K0Ybw0qUqEIL05PY",
"instantiation": "true",
"compatible_printers": [
"iQ TiQ8 0.25 Nozzle"
@@ -3,6 +3,7 @@
"name": "0.30mm Standard @iQ TiQ2 (0.6 Nozzle)",
"inherits": "fdm_process_tiq_common",
"from": "system",
"setting_id": "IGN3ZUR73J0veLrE",
"instantiation": "true",
"compatible_printers": [
"iQ TiQ2 0.6 Nozzle"
@@ -3,6 +3,7 @@
"name": "0.30mm Standard @iQ TiQ8 (0.6 Nozzle)",
"inherits": "fdm_process_tiq_common",
"from": "system",
"setting_id": "QEODQzrO9UZEgrtB",
"instantiation": "true",
"compatible_printers": [
"iQ TiQ8 0.6 Nozzle"
@@ -3,6 +3,7 @@
"name": "0.40mm Standard @iQ TiQ2 (0.8 Nozzle)",
"inherits": "fdm_process_tiq_common",
"from": "system",
"setting_id": "ZoiYkGXOTBh39HTB",
"instantiation": "true",
"compatible_printers": [
"iQ TiQ2 0.8 Nozzle"
@@ -3,6 +3,7 @@
"name": "0.40mm Standard @iQ TiQ8 (0.8 Nozzle)",
"inherits": "fdm_process_tiq_common",
"from": "system",
"setting_id": "C7TZWdCzQroB8pKL",
"instantiation": "true",
"compatible_printers": [
"iQ TiQ8 0.8 Nozzle"
+2
View File
@@ -231,6 +231,8 @@ void main()
s = max(s, DetectSilho(fragCoord.xy + vec2(i, 0)));
s = max(s, DetectSilho(fragCoord.xy + vec2(0, i)));
}
if (s < 0.01)
discard;
gl_FragColor = vec4(mix(color.rgb, getBackfaceColor(color.rgb), s), color.a);
}
#ifdef ENABLE_ENVIRONMENT_MAP
+11
View File
@@ -30,6 +30,8 @@ uniform mat4 projection_matrix;
uniform mat3 view_normal_matrix;
uniform mat4 volume_world_matrix;
uniform SlopeDetection slope;
uniform bool is_outline;
uniform vec2 screen_size;
// Clipping plane, x = min z, y = max z. Used by the FFF and SLA previews to clip with a top / bottom plane.
uniform vec2 z_range;
@@ -75,6 +77,15 @@ void main()
world_normal_z = slope.actived ? (normalize(slope.volume_world_normal_matrix * v_normal)).z : 0.0;
gl_Position = projection_matrix * position;
if (is_outline) {
vec3 n = normalize((view_normal_matrix * v_normal).xyz);
vec2 dir = normalize(n.xy);
if (dot(dir, dir) > 0.0) {
//set outline thickness
float px = 3.0;
gl_Position.xy += dir * (px * 2.0 / screen_size) * gl_Position.w;
}
}
// Fill in the scalars for fragment shader clipping. Fragments with any of these components lower than zero are discarded.
clipping_planes_dots = vec3(dot(world_pos, clipping_plane), world_pos.z - z_range.x, z_range.y - world_pos.z);
color_clip_plane_dot = dot(world_pos, color_clip_plane);
+2 -2
View File
@@ -1,11 +1,11 @@
#version 110
uniform sampler2D Texture;
uniform sampler2D s_texture;
varying vec2 Frag_UV;
varying vec4 Frag_Color;
void main()
{
gl_FragColor = Frag_Color * texture2D(Texture, Frag_UV.st);
gl_FragColor = Frag_Color * texture2D(s_texture, Frag_UV.st);
}
+2
View File
@@ -273,6 +273,8 @@ void main()
s = max(s, DetectSilho(fragCoord.xy + vec2(i, 0)));
s = max(s, DetectSilho(fragCoord.xy + vec2(0, i)));
}
if (s < 0.01)
discard;
gl_FragColor = vec4(mix(shaded_color.rgb, getBackfaceColor(shaded_color.rgb), s), shaded_color.a);
}
#ifdef ENABLE_ENVIRONMENT_MAP
+11
View File
@@ -14,6 +14,8 @@ uniform mat4 projection_matrix;
uniform mat3 view_normal_matrix;
uniform mat4 volume_world_matrix;
uniform SlopeDetection slope;
uniform bool is_outline;
uniform vec2 screen_size;
// Clipping plane, x = min z, y = max z. Used by the FFF and SLA previews to clip with a top / bottom plane.
uniform vec2 z_range;
@@ -48,6 +50,15 @@ void main()
world_normal_z = slope.actived ? (normalize(slope.volume_world_normal_matrix * v_normal)).z : 0.0;
gl_Position = projection_matrix * position;
if (is_outline) {
vec3 n = normalize((view_normal_matrix * v_normal).xyz);
vec2 dir = normalize(n.xy);
if (dot(dir, dir) > 0.0) {
//set outline thickness
float px = 3.0;
gl_Position.xy += dir * (px * 2.0 / screen_size) * gl_Position.w;
}
}
// Fill in the scalars for fragment shader clipping. Fragments with any of these components lower than zero are discarded.
clipping_planes_dots = vec3(dot(world_pos, clipping_plane), world_pos.z - z_range.x, z_range.y - world_pos.z);
color_clip_plane_dot = dot(world_pos, color_clip_plane);
+5
View File
@@ -11,6 +11,7 @@ uniform sampler2D normal_texture;
uniform vec2 inv_tex_size;
uniform float z_near;
uniform float z_far;
uniform bool is_outline;
varying vec2 tex_coord;
@@ -22,6 +23,10 @@ float linearize_depth(float depth)
void main()
{
if (is_outline) {
gl_FragColor = vec4(texture2D(color_texture, tex_coord).rgb, 1.0);
return;
}
vec3 base = texture2D(color_texture, tex_coord).rgb;
float depth_center = linearize_depth(texture2D(depth_texture, tex_coord).r);
+2
View File
@@ -232,6 +232,8 @@ void main()
s = max(s, DetectSilho(fragCoord.xy + vec2(i, 0)));
s = max(s, DetectSilho(fragCoord.xy + vec2(0, i)));
}
if (s < 0.01)
discard;
out_color = vec4(mix(color.rgb, getBackfaceColor(color.rgb), s), color.a);
}
#ifdef ENABLE_ENVIRONMENT_MAP
+11
View File
@@ -30,6 +30,8 @@ uniform mat4 projection_matrix;
uniform mat3 view_normal_matrix;
uniform mat4 volume_world_matrix;
uniform SlopeDetection slope;
uniform bool is_outline;
uniform vec2 screen_size;
// Clipping plane, x = min z, y = max z. Used by the FFF and SLA previews to clip with a top / bottom plane.
uniform vec2 z_range;
@@ -75,6 +77,15 @@ void main()
world_normal_z = slope.actived ? (normalize(slope.volume_world_normal_matrix * v_normal)).z : 0.0;
gl_Position = projection_matrix * position;
if (is_outline) {
vec3 n = normalize((view_normal_matrix * v_normal).xyz);
vec2 dir = normalize(n.xy);
if (dot(dir, dir) > 0.0) {
//set outline thickness
float px = 3.0;
gl_Position.xy += dir * (px * 2.0 / screen_size) * gl_Position.w;
}
}
// Fill in the scalars for fragment shader clipping. Fragments with any of these components lower than zero are discarded.
clipping_planes_dots = vec3(dot(world_pos, clipping_plane), world_pos.z - z_range.x, z_range.y - world_pos.z);
color_clip_plane_dot = dot(world_pos, color_clip_plane);
+2 -2
View File
@@ -1,6 +1,6 @@
#version 140
uniform sampler2D Texture;
uniform sampler2D s_texture;
in vec2 Frag_UV;
in vec4 Frag_Color;
@@ -9,5 +9,5 @@ out vec4 out_color;
void main()
{
out_color = Frag_Color * texture(Texture, Frag_UV.st);
out_color = Frag_Color * texture(s_texture, Frag_UV.st);
}
+2
View File
@@ -277,6 +277,8 @@ void main()
s = max(s, DetectSilho(fragCoord.xy + vec2(i, 0)));
s = max(s, DetectSilho(fragCoord.xy + vec2(0, i)));
}
if (s < 0.01)
discard;
out_color = vec4(mix(shaded_color.rgb, getBackfaceColor(shaded_color.rgb), s), shaded_color.a);
}
#ifdef ENABLE_ENVIRONMENT_MAP
+11
View File
@@ -14,6 +14,8 @@ uniform mat4 projection_matrix;
uniform mat3 view_normal_matrix;
uniform mat4 volume_world_matrix;
uniform SlopeDetection slope;
uniform bool is_outline;
uniform vec2 screen_size;
// Clipping plane, x = min z, y = max z. Used by the FFF and SLA previews to clip with a top / bottom plane.
uniform vec2 z_range;
@@ -48,6 +50,15 @@ void main()
world_normal_z = slope.actived ? (normalize(slope.volume_world_normal_matrix * v_normal)).z : 0.0;
gl_Position = projection_matrix * position;
if (is_outline) {
vec3 n = normalize((view_normal_matrix * v_normal).xyz);
vec2 dir = normalize(n.xy);
if (dot(dir, dir) > 0.0) {
//set outline thickness
float px = 3.0;
gl_Position.xy += dir * (px * 2.0 / screen_size) * gl_Position.w;
}
}
// Fill in the scalars for fragment shader clipping. Fragments with any of these components lower than zero are discarded.
clipping_planes_dots = vec3(dot(world_pos, clipping_plane), world_pos.z - z_range.x, z_range.y - world_pos.z);
color_clip_plane_dot = dot(world_pos, color_clip_plane);
+5
View File
@@ -10,6 +10,7 @@ uniform sampler2D depth_texture;
uniform sampler2D normal_texture;
uniform float z_near;
uniform float z_far;
uniform bool is_outline;
in vec2 tex_coord;
out vec4 frag_color;
@@ -22,6 +23,10 @@ float linearize_depth(float depth)
void main()
{
if (is_outline) {
frag_color = vec4(texture(color_texture, tex_coord).rgb, 1.0);
return;
}
ivec2 pixel = ivec2(gl_FragCoord.xy);
float center_depth = linearize_depth(texelFetch(depth_texture, pixel, 0).r);
+1 -1
View File
@@ -1518,7 +1518,7 @@ function RunScriptPlugin(pluginId, capabilityName = "") {
if (!plugin || !capability)
return;
SendMessage("run_script_plugin", {
SendMessage("run_script_plugin_capability", {
plugin_key: pluginId,
capability_name: String(capability.name || "")
});
+7 -4
View File
@@ -162,11 +162,14 @@ void Fill::fill_surface_extrusion(const Surface* surface, const FillParams& para
out.push_back(eec = new ExtrusionEntityCollection());
// Only concentric fills are not sorted.
eec->no_sort = this->no_sort();
// ORCA: special flag for flow rate calibration
auto is_flow_calib = params.extrusion_role == erTopSolidInfill && this->print_object_config->has("calib_flowrate_topinfill_special_order") &&
this->print_object_config->option("calib_flowrate_topinfill_special_order")->getBool();
// Orca: a forced surface fill order must survive the G-code path planner, which would
// otherwise re-chain and possibly reverse the paths. This also covers the flow rate
// calibration, which forces an outward fill order on its top surfaces.
// otherwise re-chain and possibly reverse the paths. The same applies to the flow rate
// calibration's special toolpath order.
const bool keep_fill_order = params.fill_order != SurfaceFillOrder::Default;
if (keep_fill_order) {
if (is_flow_calib || keep_fill_order) {
eec->no_sort = true;
}
size_t idx = eec->entities.size();
@@ -181,7 +184,7 @@ void Fill::fill_surface_extrusion(const Surface* surface, const FillParams& para
params.extrusion_role,
flow_mm3_per_mm, float(flow_width), params.flow.height());
}
if (!params.can_reverse || keep_fill_order) {
if (!params.can_reverse || is_flow_calib || keep_fill_order) {
for (size_t i = idx; i < eec->entities.size(); i++)
eec->entities[i]->set_reverse();
}
+28 -1
View File
@@ -134,7 +134,34 @@ void FillPlanePath::_fill_surface_single(
if (!polylines.empty()) {
Polylines chained;
if (params.dont_connect() || params.density > 0.5) {
if (params.fill_order != SurfaceFillOrder::Default) {
// ORCA: special flag for flow rate calibration. The chords chained ahead of the
// inside-out center spiral collide with it in opposing directions, raising a
// tactile lip that the calibration reads. Only applies while the fill order is
// Default, so it can be overridden from the calibration objects.
auto is_flow_calib = params.fill_order == SurfaceFillOrder::Default &&
params.extrusion_role == erTopSolidInfill &&
this->print_object_config->has("calib_flowrate_topinfill_special_order") &&
this->print_object_config->option("calib_flowrate_topinfill_special_order")->getBool() &&
dynamic_cast<FillArchimedeanChords*>(this);
if (is_flow_calib) {
// We want the spiral part to be printed inside-out
// Find the center spiral line first, by looking for the longest one
auto it = std::max_element(polylines.begin(), polylines.end(),
[](const Polyline& a, const Polyline& b) { return a.length() < b.length(); });
Polyline center_spiral = std::move(*it);
// Ensure the spiral is printed from inside to out
if (center_spiral.first_point().squaredNorm() > center_spiral.last_point().squaredNorm()) {
center_spiral.reverse();
}
// Chain the other polylines
polylines.erase(it);
chained = chain_polylines(std::move(polylines), nullptr);
// Then add the center spiral back
chained.push_back(std::move(center_spiral));
} else if (params.fill_order != SurfaceFillOrder::Default) {
// Orca: print the fragments in the order they appear along the generated
// path, which runs from the center outwards. The Euclidean distance from
// the center cannot be used for this: along the Octagram Spiral the radius
+28 -1
View File
@@ -470,6 +470,8 @@ void Preset::normalize(DynamicPrintConfig &config)
continue;
if (filament_options_with_variant.find(key) != filament_options_with_variant.end())
continue;
if (filament_dev_options.find(key) != filament_dev_options.end())
continue;
auto *opt = config.option(key, false);
/*assert(opt != nullptr);
assert(opt->is_vector());*/
@@ -1311,6 +1313,7 @@ static std::vector<std::string> s_Preset_print_options{
"interlocking_depth",
"interlocking_boundary_avoidance",
"interlocking_beam_width",
"calib_flowrate_topinfill_special_order",
// Z Anti-Aliasing (ZAA)
"zaa_enabled",
"zaa_minimize_perimeter_height",
@@ -1375,7 +1378,11 @@ static std::vector<std::string> s_Preset_filament_options {/*"filament_colour",
"filament_preheat_temperature_delta", "filament_retract_length_nc",
"filament_change_length_nc", "filament_prime_volume_nc",
"long_retractions_when_ec", "retraction_distances_when_ec",
"plugin_preference_overrides"
"plugin_preference_overrides",
//ams chamber
"filament_dev_ams_drying_ams_limitations", "filament_dev_ams_drying_temperature", "filament_dev_ams_drying_time", "filament_dev_ams_drying_heat_distortion_temperature",
"filament_dev_chamber_drying_bed_temperature", "filament_dev_chamber_drying_time",
"filament_dev_drying_softening_temperature", "filament_dev_drying_cooling_temperature"
};
static std::vector<std::string> s_Preset_machine_limits_options {
@@ -3828,6 +3835,26 @@ void PresetCollection::set_custom_preset_alias(Preset &preset)
set_printer_hold_alias(preset.alias, preset);
}
std::string PresetCollection::get_preset_alias(Preset &preset, bool force)
{
if (!preset.alias.empty())
return preset.alias;
else
set_custom_preset_alias(preset);
if (!preset.alias.empty() || !force)
return preset.alias;
std::string alias_name;
std::string preset_name = preset.name;
size_t end_pos = preset_name.find_first_of("@");
if (end_pos != std::string::npos) {
alias_name = preset_name.substr(0, end_pos);
boost::trim_right(alias_name);
}
return alias_name;
}
void PresetCollection::set_printer_hold_alias(const std::string &alias, Preset &preset, bool remove)
{
auto compatible_printers = dynamic_cast<ConfigOptionStrings *>(preset.config.option("compatible_printers"));
+3
View File
@@ -805,6 +805,9 @@ public:
std::string path_from_name(const std::string &new_name, bool detach = false) const;
std::string path_for_preset(const Preset & preset) const;
// Get the alias of a preset, setting it if it's empty
std::string get_preset_alias(Preset &preset, bool force = false);
size_t num_default_presets() { return m_num_default_presets; }
protected:
+49 -10
View File
@@ -2031,7 +2031,7 @@ void PrintConfigDef::init_fff_params()
def = this->add("initial_layer_travel_acceleration", coFloatsOrPercents);
def->label = L("First layer travel");
def->tooltip = L("Travel acceleration of first layer.\nThe percentage value is relative to Travel Acceleration.");
def->sidetext = L("mm/s² or %");
def->sidetext = L(u8"mm/s² or %");
def->min = 0;
def->mode = comAdvanced;
def->ratio_over = "travel_acceleration";
@@ -2042,7 +2042,7 @@ void PrintConfigDef::init_fff_params()
def->label = L("Bridge");
def->category = L("Speed");
def->tooltip = L("Acceleration of bridges. If the value is expressed as a percentage (e.g. 50%), it will be calculated based on the outer wall acceleration.");
def->sidetext = L("mm/s² or %");
def->sidetext = L(u8"mm/s² or %");
def->min = 0;
def->mode = comAdvanced;
def->ratio_over = "outer_wall_acceleration";
@@ -3466,7 +3466,7 @@ void PrintConfigDef::init_fff_params()
def->label = L("Sparse infill");
def->category = L("Speed");
def->tooltip = L("Acceleration of sparse infill. If the value is expressed as a percentage (e.g. 100%), it will be calculated based on the default acceleration.");
def->sidetext = L("mm/s² or %");
def->sidetext = L(u8"mm/s² or %");
def->min = 0;
def->mode = comAdvanced;
def->ratio_over = "default_acceleration";
@@ -3477,7 +3477,7 @@ void PrintConfigDef::init_fff_params()
def->label = L("Internal solid infill");
def->category = L("Speed");
def->tooltip = L("Acceleration of internal solid infill. If the value is expressed as a percentage (e.g. 100%), it will be calculated based on the default acceleration.");
def->sidetext = L("mm/s² or %");
def->sidetext = L(u8"mm/s² or %");
def->min = 0;
def->mode = comAdvanced;
def->ratio_over = "default_acceleration";
@@ -3933,7 +3933,7 @@ void PrintConfigDef::init_fff_params()
"The shift is applied once every number of layers set by Layers between ripple offset, so layers within the same group are printed identically.");
def->min = 0;
def->max = 100;
def->sidetext = ("%");
def->sidetext = "%";
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionPercent(50));
@@ -4141,7 +4141,7 @@ void PrintConfigDef::init_fff_params()
"value that the firmware would silently drop, and the fan never receives a value below the one "
"you know it can actually spool at."
"\nSet to 0 to deactivate.");
def->sidetext = L("%");
def->sidetext = "%";
def->min = 0;
def->max = 100;
def->mode = comAdvanced;
@@ -4661,6 +4661,11 @@ void PrintConfigDef::init_fff_params()
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionInt(2));
// ORCA: special flag for flow rate calibration
def = this->add("calib_flowrate_topinfill_special_order", coBool);
def->mode = comDevelop;
def->set_default_value(new ConfigOptionBool(false));
def = this->add("ironing_type", coEnum);
def->label = L("Ironing type");
def->category = L("Quality");
@@ -5091,7 +5096,7 @@ void PrintConfigDef::init_fff_params()
def = this->add("input_shaping_freq_x", coFloat);
def->label = L("X");
def->tooltip = L("Resonant frequency for the X axis input shaper.\nZero will use the firmware frequency.\nTo disable input shaping, use the Disable type.\nRRF: X and Y values are equal.");
def->sidetext = "Hz";
def->sidetext = L("Hz"); // Hertz, CIS languages need translation
def->min = 0;
def->max = 1000;
def->mode = comExpert;
@@ -5100,7 +5105,7 @@ void PrintConfigDef::init_fff_params()
def = this->add("input_shaping_freq_y", coFloat);
def->label = L("Y");
def->tooltip = L("Resonant frequency for the Y axis input shaper.\nZero will use the firmware frequency.\nTo disable input shaping, use the Disable type.");
def->sidetext = "Hz";
def->sidetext = L("Hz"); // Hertz, CIS languages need translation
def->min = 0;
def->max = 1000;
def->mode = comExpert;
@@ -7150,7 +7155,7 @@ void PrintConfigDef::init_fff_params()
def->label = L("Minimal");
def->tooltip = L("This is the chamber temperature at which printing should start, while the chamber continues heating "
"toward the \"Target\" chamber temperature. For example, set the Target to 60 and the Minimal to 50 to "
"begin printing once the chamber reaches 50°C, without waiting for the full 60°C.\n\n"
"begin printing once the chamber reaches 50, without waiting for the full 60.\n\n"
"It sets a G-code variable named chamber_minimal_temperature, which can be passed to your print start macro "
"or a heat soak macro, like this: PRINT_START (other variables) CHAMBER_MIN_TEMP=[chamber_minimal_temperature].\n\n"
"Unlike the \"Target\" chamber temperature, this option does not emit any M141/M191 commands; it only exposes "
@@ -7827,6 +7832,30 @@ void PrintConfigDef::init_fff_params()
def->min = 0;
def->set_default_value(new ConfigOptionPercent(85));
def = this->add("filament_dev_ams_drying_ams_limitations", coStrings);
def->set_default_value(new ConfigOptionStrings{""});
def = this->add("filament_dev_ams_drying_temperature", coFloats);
def->set_default_value(new ConfigOptionFloats{0});
def = this->add("filament_dev_ams_drying_time", coFloats);
def->set_default_value(new ConfigOptionFloats{0});
def = this->add("filament_dev_ams_drying_heat_distortion_temperature", coFloats);
def->set_default_value(new ConfigOptionFloats{0});
def = this->add("filament_dev_chamber_drying_bed_temperature", coFloats);
def->set_default_value(new ConfigOptionFloats{0});
def = this->add("filament_dev_chamber_drying_time", coFloats);
def->set_default_value(new ConfigOptionFloats{0});
def = this->add("filament_dev_drying_softening_temperature", coFloats);
def->set_default_value(new ConfigOptionFloats{0});
def = this->add("filament_dev_drying_cooling_temperature", coFloats);
def->set_default_value(new ConfigOptionFloats{0});
// Declare retract values for filament profile, overriding the printer's extruder profile.
for (auto& opt_key : filament_extruder_override_keys) {
const std::string filament_prefix = "filament_";
@@ -9022,7 +9051,6 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
"internal_bridge_support_thickness", "top_area_threshold", "reduce_wall_solid_infill","filament_load_time","filament_unload_time",
"smooth_coefficient", "overhang_totally_speed", "silent_mode",
"overhang_speed_classic", "filament_prime_volume",
"calib_flowrate_topinfill_special_order",
"anisotropic_surfaces", // superseded by top_surface_fill_order / bottom_surface_fill_order
};
@@ -9262,6 +9290,17 @@ std::set<std::string> printer_options_with_variant_2 = {
std::set<std::string> empty_options;
std::set<std::string> filament_dev_options = {
"filament_dev_ams_drying_ams_limitations",
"filament_dev_ams_drying_temperature",
"filament_dev_ams_drying_time",
"filament_dev_ams_drying_heat_distortion_temperature",
"filament_dev_chamber_drying_bed_temperature",
"filament_dev_chamber_drying_time",
"filament_dev_drying_softening_temperature",
"filament_dev_drying_cooling_temperature"
};
DynamicPrintConfig DynamicPrintConfig::full_print_config()
{
return DynamicPrintConfig((const PrintRegionConfig&)FullPrintConfig::defaults());
+15
View File
@@ -840,6 +840,8 @@ extern std::set<std::string> printer_options_with_variant_1;
extern std::set<std::string> printer_options_with_variant_2;
extern std::set<std::string> empty_options;
extern std::set<std::string> filament_dev_options;
extern void update_static_print_config_from_dynamic(ConfigBase& config, const DynamicPrintConfig& dest_config, std::vector<int> variant_index, std::set<std::string>& key_set1, int stride = 1);
extern void compute_filament_override_value(const std::string& opt_key, const ConfigOption *opt_old_machine, const ConfigOption *opt_new_machine, const ConfigOption *opt_new_filament, const DynamicPrintConfig& new_full_config,
t_config_option_keys& diff_keys, DynamicPrintConfig& filament_overrides, std::vector<int>& f_map_indices);
@@ -1219,6 +1221,9 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionInt, interlocking_beam_layer_count))
((ConfigOptionInt, interlocking_depth))
((ConfigOptionInt, interlocking_boundary_avoidance))
// Orca: internal use only
((ConfigOptionBool, calib_flowrate_topinfill_special_order)) // ORCA: special flag for flow rate calibration
)
// This object is mapped to Perl as Slic3r::Config::PrintRegion.
@@ -1678,6 +1683,16 @@ PRINT_CONFIG_CLASS_DEFINE(
// Printer flag: whether the printer offers the fast-purge mode selector.
// Default false; no shipping profile sets it, so the fast-purge UI stays hidden.
((ConfigOptionBool, support_fast_purge_mode))
//ams chamber
((ConfigOptionStrings, filament_dev_ams_drying_ams_limitations))
((ConfigOptionFloats, filament_dev_ams_drying_temperature))
((ConfigOptionFloats, filament_dev_ams_drying_time))
((ConfigOptionFloats, filament_dev_ams_drying_heat_distortion_temperature))
((ConfigOptionFloats, filament_dev_chamber_drying_bed_temperature))
((ConfigOptionFloats, filament_dev_chamber_drying_time))
((ConfigOptionFloats, filament_dev_drying_softening_temperature))
((ConfigOptionFloats, filament_dev_drying_cooling_temperature))
)
// This object is mapped to Perl as Slic3r::Config::Print.
+2 -2
View File
@@ -28,6 +28,8 @@ set(SLIC3R_GUI_SOURCES
GUI/AMSMaterialsSetting.hpp
GUI/AMSSetting.cpp
GUI/AMSSetting.hpp
GUI/AMSDryControl.cpp
GUI/AMSDryControl.hpp
GUI/AmsWidgets.cpp
GUI/AmsWidgets.hpp
GUI/Auxiliary.cpp
@@ -596,8 +598,6 @@ set(SLIC3R_GUI_SOURCES
GUI/wxExtensions.hpp
plugin/PythonInterpreter.cpp
plugin/PythonInterpreter.hpp
plugin/PythonFileUtils.cpp
plugin/PythonFileUtils.hpp
plugin/PythonPluginBridge.cpp
plugin/PythonPluginBridge.hpp
plugin/PythonPluginInterface.hpp
+23 -1
View File
@@ -495,7 +495,29 @@ void GLVolume::render_with_outline(const GUI::Size& cnv_size)
simple_render(shader, model_objects, colors);
return;
}
// 0th. render pass, render the model using stencil buffer
glsafe(::glEnable(GL_STENCIL_TEST));
glsafe(::glStencilMask(0xFF));
glsafe(::glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE));
glsafe(::glClearStencil(0));
glsafe(::glClear(GL_STENCIL_BUFFER_BIT));
glsafe(::glStencilFunc(GL_ALWAYS, 0xFF, 0xFF));
if (tverts_range == std::make_pair<size_t, size_t>(0, -1))
model.render(shader);
else
model.render(this->tverts_range, shader);
glsafe(::glStencilFunc(GL_NOTEQUAL, 0xFF, 0xFF));
glsafe(::glStencilMask(0x00));
shader->set_uniform("is_outline", true);
shader->set_uniform("screen_size", Vec2f{cnv_size.get_width(), cnv_size.get_height()});
if (tverts_range == std::make_pair<size_t, size_t>(0, -1))
model.render(shader);
else
model.render(this->tverts_range, shader);
shader->set_uniform("is_outline", false);
glsafe(::glStencilMask(0xFF));
glsafe(::glDisable(GL_STENCIL_TEST));
// render the outline using depth buffer and discard the pixels that are not on the outline
// 1st. render pass, render the model into a separate render target that has only depth buffer
GLuint depth_fbo = 0;
GLuint depth_tex = 0;
+1864
View File
@@ -0,0 +1,1864 @@
#include "AMSDryControl.hpp"
#include "slic3r/GUI/DeviceCore/DevFilaSystem.h"
#include "GUI_App.hpp"
#include "I18N.hpp"
#include "slic3r/GUI/DeviceCore/DevExtruderSystem.h"
#include "slic3r/GUI/DeviceCore/DevManager.h"
#include "slic3r/GUI/MsgDialog.hpp"
#include "slic3r/GUI/Widgets/AnimaController.hpp"
#include "slic3r/GUI/Widgets/Label.hpp"
#include "slic3r/GUI/Widgets/ComboBox.hpp"
#include "slic3r/GUI/Widgets/ProgressBar.hpp"
#include "slic3r/GUI/DeviceCore/DevUtilBackend.h"
#include "libslic3r/PresetBundle.hpp"
#include "libslic3r/Preset.hpp"
#include <boost/log/trivial.hpp>
namespace Slic3r { namespace GUI {
const int AMS_DRY_STATUS_IMAGE_SIZE = 96;
static std::string get_humidity_level_img_path(int humidity_percent)
{
const int num_levels = 5;
int hum_level;
if (humidity_percent <= 100 / num_levels) {
hum_level = 5;
} else if (humidity_percent <= 100 / num_levels * 2) {
hum_level = 4;
} else if (humidity_percent <= 100 / num_levels * 3) {
hum_level = 3;
} else if (humidity_percent <= 100 / num_levels * 4) {
hum_level = 2;
} else {
hum_level = 1;
}
if (wxGetApp().dark_mode()) {
return "hum_level" + std::to_string(hum_level) + "_no_num_dark";
} else {
return "hum_level" + std::to_string(hum_level) + "_no_num_light";
}
}
static std::string get_dry_status_img_path(DevAmsType type, DevAms::DryStatus status, DevAms::DrySubStatus sub_status)
{
std::string img_name = "dev_ams_dry_ctr_";
switch (type) {
case DevAmsType::N3S:
img_name += "n3s";
break;
case DevAmsType::N3F:
img_name += "n3f";
break;
default:
return "";
}
img_name += "_";
switch (status) {
case DevAms::DryStatus::Error:
img_name += "error";
return img_name;
}
switch (sub_status) {
case DevAms::DrySubStatus::Heating:
img_name += "heating";
return img_name;
case DevAms::DrySubStatus::Dehumidify:
img_name += "dehumidifying";
return img_name;
}
return "";
}
FilamentItemPanel::FilamentItemPanel(wxWindow* parent, const wxString& text, const std::string& icon_name, wxWindowID id)
: wxPanel(parent, id)
, m_icon_name(icon_name)
{
SetBackgroundColour(wxColour("#F0F0F1")); // Light gray background
SetMinSize(wxSize(FromDIP(64), FromDIP(106))); // Width: 64, Height: 106
SetSize(wxSize(FromDIP(64), FromDIP(106))); // Fixed size
// Create sizer for vertical layout
wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
// Top section with text - moved to be closer to center
wxBoxSizer* top_sizer = new wxBoxSizer(wxVERTICAL);
top_sizer->AddStretchSpacer(5);
m_text_label = new Label(this, text);
m_text_label->SetForegroundColour(StateColor::darkModeColorFor(wxColour(*wxBLACK)));
m_text_label->SetBackgroundColour(StateColor::darkModeColorFor(wxColour("#F0F0F1")));
m_text_label->SetFont(Label::Body_12);
m_text_label->Wrap(FromDIP(40));
top_sizer->Add(m_text_label, 0, wxALIGN_CENTER_HORIZONTAL);
top_sizer->AddStretchSpacer(1); // Increased bottom spacer to push text down
sizer->Add(top_sizer, 1, wxEXPAND);
// Bottom section with icon - vertically centered in bottom half
wxBoxSizer* bottom_sizer = new wxBoxSizer(wxVERTICAL);
bottom_sizer->AddStretchSpacer(1);
m_icon_bitmap = new wxStaticBitmap(this, wxID_ANY, wxNullBitmap);
m_icon_bitmap->SetBackgroundColour(StateColor::darkModeColorFor(wxColour("#F0F0F1")));
m_icon_bitmap->SetMinSize(wxSize(FromDIP(24), FromDIP(24)));
m_icon_bitmap->SetMaxSize(wxSize(FromDIP(24), FromDIP(24)));
bottom_sizer->Add(m_icon_bitmap, 0, wxALIGN_CENTER_HORIZONTAL);
bottom_sizer->AddStretchSpacer(1);
sizer->Add(bottom_sizer, 1, wxEXPAND);
SetSizer(sizer);
// Bind events
Bind(wxEVT_PAINT, &FilamentItemPanel::OnPaint, this);
Bind(wxEVT_SIZE, &FilamentItemPanel::OnSize, this);
SetIcon(icon_name);
wxGetApp().UpdateDarkUI(this);
}
void FilamentItemPanel::SetText(const wxString& text)
{
m_text_label->SetLabel(text);
Layout();
}
void FilamentItemPanel::SetIcon(const std::string& icon_name)
{
m_icon_name = icon_name;
if (!icon_name.empty()) {
try {
m_icon = ScalableBitmap(this, icon_name, 20);
m_icon.msw_rescale();
m_icon_bitmap->SetBitmap(m_icon.bmp());
} catch (Exception&) {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": failed to load filament icon";
m_icon_bitmap->SetBitmap(wxNullBitmap);
}
} else {
m_icon_bitmap->SetBitmap(wxNullBitmap);
}
m_icon_bitmap->Refresh();
}
void FilamentItemPanel::msw_rescale()
{
if (m_icon_bitmap && !m_icon_name.empty()) {
m_icon.msw_rescale();
m_icon_bitmap->SetBitmap(m_icon.bmp());
m_icon_bitmap->Refresh();
}
Layout();
}
void FilamentItemPanel::OnPaint(wxPaintEvent& event)
{
wxPaintDC dc(this);
wxSize size = GetSize();
// bool is_dark_mode = wxGetApp().dark_mode();
wxColour backgroundColor = StateColor::darkModeColorFor(wxColour("#F0F0F1"));
wxColour borderColor = StateColor::darkModeColorFor(wxColour("#DBDBDB"));
// Draw white background rectangle with rounded corners inside the thick vertical lines
dc.SetBrush(wxBrush(backgroundColor));
dc.SetPen(wxPen(backgroundColor));
dc.DrawRectangle(FromDIP(6), FromDIP(12), size.GetWidth() - FromDIP(12), size.GetHeight() - 2 * FromDIP(12));
// Draw much thicker vertical rounded rectangles on left and right (3 times thicker)
dc.SetBrush(wxBrush(wxColour(borderColor)));
dc.SetPen(wxPen(wxColour(borderColor)));
dc.DrawRoundedRectangle(FromDIP(0), FromDIP(0), FromDIP(6), size.GetHeight(), FromDIP(6)); // Left rounded rectangle
dc.DrawRoundedRectangle(size.GetWidth() - FromDIP(6), FromDIP(0), FromDIP(6), size.GetHeight(), FromDIP(6)); // Right rounded rectangle
// Draw thin horizontal rounded rectangles on top and bottom (moved closer to center by half the distance)
dc.SetBrush(wxBrush(wxColour(borderColor)));
dc.SetPen(wxPen(wxColour(borderColor)));
dc.DrawRoundedRectangle(FromDIP(6), FromDIP(12), size.GetWidth() - FromDIP(12), FromDIP(3), FromDIP(1)); // Top rounded rectangle
dc.DrawRoundedRectangle(FromDIP(6), size.GetHeight() - FromDIP(13), size.GetWidth() - FromDIP(12), FromDIP(3), FromDIP(1)); // Bottom rounded rectangle
}
void FilamentItemPanel::OnSize(wxSizeEvent& event)
{
Refresh();
event.Skip();
}
// class AMSFilamentPanel
AMSFilamentPanel::AMSFilamentPanel(wxWindow* parent, const wxString& ams_name, wxWindowID id)
: wxPanel(parent, id)
{
SetBackgroundColour(wxColour("#DBDBDB"));
wxBoxSizer* main_sizer = new wxBoxSizer(wxVERTICAL);
// Filament items section
m_filament_container = new wxPanel(this);
m_filament_container->SetBackgroundColour(wxColour("#F0F0F1"));
m_filament_sizer = new wxBoxSizer(wxHORIZONTAL);
m_filament_container->SetSizer(m_filament_sizer);
// AMS name section
m_ams_name_label = new Label(this, ams_name);
m_ams_name_label->SetForegroundColour(wxColour("#858585"));
m_ams_name_label->SetFont(Label::Body_14);
m_ams_name_label->SetBackgroundColour(wxColour("#DBDBDB"));
main_sizer->Add(m_filament_container, 1, wxEXPAND | wxALL, 0);
main_sizer->Add(m_ams_name_label, 0, wxALIGN_LEFT | wxALL, FromDIP(5));
SetSizer(main_sizer);
wxGetApp().UpdateDarkUI(this);
}
void AMSFilamentPanel::AddFilamentItem(FilamentItemPanel* panel)
{
if (panel) {
panel->Reparent(m_filament_container);
m_filament_sizer->Add(panel, 0, wxALL, FromDIP(5));
m_filament_items.push_back(panel);
Layout();
}
}
void AMSFilamentPanel::AddFilamentItem(const wxString& text, const std::string& icon_name)
{
FilamentItemPanel* item = new FilamentItemPanel(m_filament_container, text, icon_name);
m_filament_items.push_back(item);
m_filament_sizer->Add(item, 0, wxALL, FromDIP(5));
Layout();
}
void AMSFilamentPanel::SetAmsName(const wxString& ams_name)
{
m_ams_name_label->SetLabel(ams_name);
Layout();
}
void AMSFilamentPanel::Clear()
{
m_filament_sizer->Clear(true);
m_filament_items.clear();
}
void AMSFilamentPanel::msw_rescale()
{
for (auto item : m_filament_items) {
item->msw_rescale();
}
Layout();
}
AMSDryCtrWin::AMSDryCtrWin(wxWindow *parent)
:DPIDialog(parent, wxID_ANY, _L("AMS Dryness Control"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX)
{
create();
}
AMSDryCtrWin::~AMSDryCtrWin()
{
if (m_progress_timer) {
delete m_progress_timer;
}
}
wxScrolledWindow* AMSDryCtrWin::create_preview_scrolled_window(wxWindow* parent)
{
wxScrolledWindow* panel = new wxScrolledWindow(parent, wxID_ANY);
panel->SetScrollRate(10, 0);
panel->SetSize(AMS_ITEMS_PANEL_SIZE);
panel->SetMinSize(AMS_ITEMS_PANEL_SIZE);
panel->SetBackgroundColour(AMS_CONTROL_DEF_BLOCK_BK_COLOUR);
return panel;
}
wxBoxSizer* AMSDryCtrWin::create_humidity_status_section(wxPanel* parent)
{
wxBoxSizer* image_sizer = new wxBoxSizer(wxVERTICAL);
m_humidity_img = new wxStaticBitmap(parent, wxID_ANY, wxNullBitmap);
image_sizer->Add(m_humidity_img, 1, wxALIGN_CENTER_HORIZONTAL, 0);
m_humidity_img->SetBitmap(wxNullBitmap);
// Create a horizontal sizer for description and icon
wxBoxSizer* desc_sizer = new wxBoxSizer(wxHORIZONTAL);
m_image_description_icon = new wxStaticBitmap(parent, wxID_ANY, wxNullBitmap);
m_image_description_icon->SetBackgroundColour(*wxWHITE);
m_image_description_icon->SetMinSize(wxSize(FromDIP(20), FromDIP(20)));
m_image_description_icon->SetMaxSize(wxSize(FromDIP(20), FromDIP(20)));
m_image_description_icon->Show(false);
desc_sizer->Add(m_image_description_icon, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, FromDIP(5));
m_image_description = new Label(parent, _L("Idle"));
m_image_description->SetFont(Label::Head_14);
m_image_description->SetForegroundColour(*wxBLACK);
m_image_description->SetBackgroundColour(*wxWHITE);
desc_sizer->Add(m_image_description, 0, wxALIGN_CENTER_VERTICAL);
image_sizer->Add(desc_sizer, 0, wxALIGN_CENTER | wxALL, FromDIP(5));
return image_sizer;
}
wxBoxSizer* AMSDryCtrWin::create_description_item(wxPanel* parent, const wxString& title, Label*& dataLabel)
{
wxBoxSizer* item_sizer = new wxBoxSizer(wxVERTICAL);
Label* titleLabel = new Label(parent, title);
titleLabel->SetForegroundColour(*wxBLACK);
titleLabel->SetFont(Label::Body_16);
dataLabel = new Label(parent, wxT("--"));
dataLabel->SetForegroundColour(*wxBLACK);
dataLabel->SetFont(Label::Body_14);
item_sizer->AddStretchSpacer();
item_sizer->Add(titleLabel, 0, wxALIGN_CENTER | wxALL, FromDIP(2));
item_sizer->Add(dataLabel, 0, wxALIGN_CENTER | wxALL, FromDIP(2));
item_sizer->AddStretchSpacer();
return item_sizer;
}
wxBoxSizer* AMSDryCtrWin::create_status_descriptions_section(wxPanel* parent)
{
wxBoxSizer* desc_sizer = new wxBoxSizer(wxHORIZONTAL);
wxBoxSizer* hum_desc_sizer = create_description_item(parent, _L("Humidity"), m_humidity_data_label);
desc_sizer->Add(hum_desc_sizer, 1, wxEXPAND, FromDIP(1));
wxStaticLine* vert_separator = new wxStaticLine(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL);
desc_sizer->Add(vert_separator, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(5));
wxBoxSizer* temp_desc_sizer = create_description_item(parent, _L("Temperature"), m_temperature_data_label);
desc_sizer->Add(temp_desc_sizer, 1, wxEXPAND, FromDIP(1));
m_time_descrition_container = new wxBoxSizer(wxHORIZONTAL);
wxStaticLine* vert_separator2 = new wxStaticLine(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL);
m_time_descrition_container->Add(vert_separator2, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(5));
wxBoxSizer* time_desc_sizer = create_description_item(parent, _L("Left Time"), m_time_data_label);
m_time_descrition_container->Add(time_desc_sizer, 1, wxEXPAND, FromDIP(1));
desc_sizer->Add(m_time_descrition_container, 1, wxEXPAND, 0);
// m_time_descrition_container->Show(false);
return desc_sizer;
}
wxBoxSizer* AMSDryCtrWin::create_left_panel(wxPanel* parent)
{
wxBoxSizer* left_sizer = new wxBoxSizer(wxVERTICAL);
wxBoxSizer* image_section = create_humidity_status_section(parent);
left_sizer->Add(image_section, 1, wxEXPAND | wxALL, FromDIP(5));
wxBoxSizer* descriptions_section = create_status_descriptions_section(parent);
left_sizer->Add(descriptions_section, 0, wxEXPAND | wxALL, FromDIP(20));
return left_sizer;
}
Button* AMSDryCtrWin::create_button(wxPanel* parent, const wxString& title,
const wxColour& background_color, const wxColour& border_color, const wxColour& text_color)
{
Button* button = new Button(parent, title);
// Create state colors for background
StateColor bg_color(
std::pair<wxColour, int>(AMS_CONTROL_DISABLE_COLOUR, StateColor::Disabled),
std::pair<wxColour, int>(background_color.ChangeLightness(80), StateColor::Pressed),
std::pair<wxColour, int>(background_color.ChangeLightness(120), StateColor::Hovered),
std::pair<wxColour, int>(background_color, StateColor::Normal)
);
// Create state colors for border
StateColor bd_color(
std::pair<wxColour, int>(AMS_CONTROL_WHITE_COLOUR, StateColor::Disabled),
std::pair<wxColour, int>(border_color, StateColor::Enabled)
);
button->SetBackgroundColor(bg_color);
button->SetBorderColor(bd_color);
button->SetTextColor(text_color);
button->SetFont(Label::Body_14);
// Auto-size button based on text content with padding
wxSize best_size = button->GetBestSize();
int padding_width = FromDIP(4);
int padding_height = FromDIP(2);
wxSize final_size(best_size.GetWidth() + padding_width, best_size.GetHeight() + padding_height);
button->SetMinSize(final_size);
return button;
}
wxBoxSizer* AMSDryCtrWin::create_normal_state_panel(wxPanel* parent)
{
wxBoxSizer* normal_state_sizer = new wxBoxSizer(wxVERTICAL);
Label* description_label = new Label(parent, _L("Filament Drying Settings"));
description_label->SetForegroundColour(*wxBLACK);
description_label->SetFont(Label::Head_14);
normal_state_sizer->Add(description_label, 0, wxALL, FromDIP(5));
// Part 2: ComboBox for material selection
wxBoxSizer* combo_sizer = new wxBoxSizer(wxHORIZONTAL);
m_trays_combo = new ComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(-1, FromDIP(26)), 0, nullptr, wxCB_READONLY);
m_trays_combo->SetFont(Label::Body_14);
combo_sizer->Add(m_trays_combo, 1, wxEXPAND);
normal_state_sizer->Add(combo_sizer, 0, wxEXPAND | wxALL, FromDIP(5));
m_trays_combo->Bind(wxEVT_COMBOBOX, &AMSDryCtrWin::OnFilamentSelectionChanged, this);
// part 3 time and temperature
// Temperature part
wxBoxSizer* temp_sizer = new wxBoxSizer(wxHORIZONTAL);
m_temperature_input = new wxTextCtrl(parent, wxID_ANY, "", wxDefaultPosition, wxSize(FromDIP(80), -1));
m_temperature_input->SetMaxLength(3); // Limit to 3 digits
m_temperature_input->Bind(wxEVT_CHAR, [this](wxKeyEvent& event) {
int keycode = event.GetKeyCode();
if (keycode >= '0' && keycode <= '9') {
event.Skip();
} else if (keycode == WXK_BACK || keycode == WXK_DELETE || keycode == WXK_LEFT || keycode == WXK_RIGHT) {
event.Skip();
}
});
m_temperature_input->Bind(wxEVT_TEXT, [this](wxCommandEvent&) {
m_next_button->Disable();
m_start_button->Disable();
});
m_temperature_input->SetBackgroundColour(StateColor::darkModeColorFor(*wxWHITE));
m_temperature_input->SetForegroundColour(StateColor::darkModeColorFor(*wxBLACK));
Label* temp_unit_label = new Label(parent, wxString::FromUTF8(""));
temp_unit_label->SetForegroundColour(*wxBLACK);
temp_sizer->Add(m_temperature_input, 1, wxRIGHT, FromDIP(1));
temp_sizer->Add(temp_unit_label, 0, wxALIGN_CENTER_VERTICAL);
// Time part
wxBoxSizer* time_sizer = new wxBoxSizer(wxHORIZONTAL);
m_time_input = new wxTextCtrl(parent, wxID_ANY, "", wxDefaultPosition, wxSize(FromDIP(100), -1));
m_time_input->SetMaxLength(3); // Limit to 3 digits
m_time_input->Bind(wxEVT_CHAR, [this](wxKeyEvent& event) {
int keycode = event.GetKeyCode();
if (keycode >= '0' && keycode <= '9') {
event.Skip();
} else if (keycode == WXK_BACK || keycode == WXK_DELETE || keycode == WXK_LEFT || keycode == WXK_RIGHT) {
event.Skip();
}
});
m_time_input->Bind(wxEVT_TEXT, [this](wxCommandEvent&) {
m_next_button->Disable();
m_start_button->Disable();
});
m_time_input->SetBackgroundColour(StateColor::darkModeColorFor(*wxWHITE));
m_time_input->SetForegroundColour(StateColor::darkModeColorFor(*wxBLACK));
Label* time_unit_label = new Label(parent, "H");
time_unit_label->SetForegroundColour(*wxBLACK);
time_sizer->Add(m_time_input, 1, wxRIGHT, FromDIP(1));
time_sizer->Add(time_unit_label, 0, wxALIGN_CENTER_VERTICAL);
wxBoxSizer* input_sizer = new wxBoxSizer(wxHORIZONTAL);
input_sizer->Add(temp_sizer, 1, wxRIGHT, FromDIP(10));
input_sizer->Add(time_sizer, 1, 0);
normal_state_sizer->Add(input_sizer, 0, wxEXPAND | wxALL, FromDIP(5));
// Part 4: Abnormal description/message area
m_normal_description = new Label(parent, "");
m_normal_description->SetForegroundColour(wxColour("#F09A17"));
m_normal_description->SetFont(Label::Body_12);
normal_state_sizer->Add(m_normal_description, 0, wxALL, FromDIP(5));
// Part 5: Start button
m_next_button = create_button(
parent,
_L("Start"),
AMS_CONTROL_BRAND_COLOUR, // Background color - green
AMS_CONTROL_BRAND_COLOUR, // Border color - green
wxColour("#FFFFFE") // Text color - white
);
m_next_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this](wxCommandEvent& event) {
m_main_simplebook->SetSelection(1);
});
normal_state_sizer->Add(m_next_button, 0, wxALL, FromDIP(5));
m_next_button->Disable();
m_stop_button = create_button(
parent,
_L("Stop"),
wxColour(255, 0, 0), // Background color - red
wxColour(255, 0, 0), // Border color - red
wxColour("#FFFFFE") // Text color - white
);
m_stop_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this](wxCommandEvent& event) {
auto fila_system = get_fila_system();
if (!fila_system) {
BOOST_LOG_TRIVIAL(info) << "AMSDryCtrWin::start_sending_drying_command: Invalid FilaSystem Pointer";
return;
}
fila_system->CtrlAmsStopDrying(std::stoi(m_ams_info.m_ams_id));
// Temporarily show stopping state, then restore after 2 seconds
if (m_stop_button) {
m_stop_button->SetLabel(_L("Stopping"));
update_button_size(m_stop_button); // Adjust button size for longer text
m_stop_button->Disable();
m_stop_button->Layout();
m_stop_button->GetParent()->Layout(); // Relayout parent container
m_stop_button->Refresh();
m_stop_button_restore_deadline.reset();
m_stop_button_restore_deadline = std::chrono::steady_clock::now() + std::chrono::seconds(2);
}
});
m_stop_button->Show(false);
normal_state_sizer->Add(m_stop_button, 0, wxALL, FromDIP(5));
return normal_state_sizer;
}
wxBoxSizer* AMSDryCtrWin::create_cannot_dry_panel(wxPanel* parent)
{
wxBoxSizer* abnormal_sizer = new wxBoxSizer(wxVERTICAL);
Label* description_label = new Label(parent, _L("Unable to dry temporarily due to ..."));
description_label->SetForegroundColour(*wxBLACK);
description_label->SetFont(Label::Head_16);
description_label->Wrap(FromDIP(300));
abnormal_sizer->Add(description_label, 0, wxALIGN_CENTER_VERTICAL, FromDIP(10));
// Add a description label for the abnormal state
m_cannot_dry_description_label = new Label(parent, (""));
m_cannot_dry_description_label->SetForegroundColour(*wxBLACK);
m_cannot_dry_description_label->SetFont(Label::Body_14);
m_cannot_dry_description_label->Wrap(FromDIP(250)); // Wrap text to fit within panel
abnormal_sizer->Add(m_cannot_dry_description_label, 0, wxALIGN_CENTER_VERTICAL, FromDIP(10));
// Unload button shown only when ConsumableAtAmsOutlet reason is active
m_unload_button = create_button(
parent,
_L("Unload"),
AMS_CONTROL_BRAND_COLOUR, // Background color - light gray
AMS_CONTROL_BRAND_COLOUR, // Border color - gray
*wxWHITE // Text color - white
);
m_unload_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this](wxCommandEvent& event) {
auto fila_system = get_fila_system();
if (!fila_system) {
BOOST_LOG_TRIVIAL(info) << "AMSDryCtrWin::unload_button: Invalid FilaSystem Pointer";
return;
}
MachineObject* obj = fila_system->GetOwner();
if (!obj) {
BOOST_LOG_TRIVIAL(info) << "AMSDryCtrWin::unload_button: Invalid MachineObject Pointer";
return;
}
obj->command_ams_change_filament(false, m_ams_info.m_ams_id, "255");
m_unload_button->Disable();
m_unload_button_restore_deadline.reset();
m_unload_button_restore_deadline = std::chrono::steady_clock::now() + std::chrono::seconds(5);
});
m_unload_button->Show(false);
abnormal_sizer->Add(m_unload_button, 0, wxALL, FromDIP(5));
return abnormal_sizer;
}
wxBoxSizer* AMSDryCtrWin::create_drying_error_panel(wxPanel* parent)
{
wxBoxSizer* err_sizer = new wxBoxSizer(wxVERTICAL);
Label* description_label = new Label(parent, _L("Drying Error"));
description_label->SetForegroundColour(*wxRED);
description_label->SetFont(Label::Body_14); // Wrap text to fit within panel
err_sizer->Add(description_label, 0, wxALIGN_CENTER_VERTICAL, FromDIP(10));
Label* additional_description_label = new Label(parent, _L("Please check the Assistant for troubleshooting"));
additional_description_label->SetForegroundColour(*wxBLACK);
additional_description_label->SetFont(Label::Body_14); // Wrap text to fit within panel
err_sizer->Add(additional_description_label, 0, wxALIGN_CENTER_VERTICAL, FromDIP(10));
return err_sizer;
}
wxBoxSizer* AMSDryCtrWin::create_right_panel(wxPanel* parent)
{
wxBoxSizer* right_sizer = new wxBoxSizer(wxHORIZONTAL);
m_normal_state_sizer = create_normal_state_panel(parent);
m_cannot_dry_sizer = create_cannot_dry_panel(parent);
m_dry_error_sizer = create_drying_error_panel(parent);
right_sizer->Add(m_normal_state_sizer, 1, wxEXPAND);
right_sizer->Add(m_cannot_dry_sizer, 1, wxEXPAND);
m_cannot_dry_sizer->Show(false);
m_dry_error_sizer->Show(false);
return right_sizer;
}
wxBoxSizer* AMSDryCtrWin::create_main_content_section(wxPanel* parent)
{
wxBoxSizer* content_sizer = new wxBoxSizer(wxHORIZONTAL);
wxBoxSizer* left_panel = create_left_panel(parent);
content_sizer->Add(left_panel, 2, wxALIGN_CENTER_VERTICAL | wxALL, FromDIP(5));
left_panel->SetMinSize(wxSize(FromDIP(250), -1));
wxBoxSizer* right_panel = create_right_panel(parent);
content_sizer->Add(right_panel, 1, wxALIGN_CENTER_VERTICAL | wxALL, FromDIP(5));
right_panel->SetMinSize(wxSize(FromDIP(250), -1));
return content_sizer;
}
wxBoxSizer* AMSDryCtrWin::create_main_page_sizer(wxPanel* parent)
{
wxBoxSizer* main_sizer = new wxBoxSizer(wxVERTICAL);
wxBoxSizer* content_section = create_main_content_section(parent);
main_sizer->Add(content_section, 1, wxEXPAND | wxALL, FromDIP(5));
return main_sizer;
}
wxBoxSizer* AMSDryCtrWin::create_guide_info_filament(wxPanel* parent)
{
wxBoxSizer* filament_section = new wxBoxSizer(wxHORIZONTAL);
m_ams_filament_panel = new AMSFilamentPanel(parent, "");
filament_section->Add(m_ams_filament_panel, 0, wxEXPAND | wxALL | wxALIGN_CENTER_HORIZONTAL, FromDIP(5));
return filament_section;
}
wxBoxSizer* AMSDryCtrWin::create_guide_info_section(wxPanel* parent)
{
wxBoxSizer* info_section = new wxBoxSizer(wxVERTICAL);
// Part 1: Title
m_guide_title_label = new Label(parent, _L("Please remove and store the filament (as shown)."));
m_guide_title_label->SetForegroundColour(*wxBLACK);
m_guide_title_label->SetFont(Label::Head_18);
info_section->Add(m_guide_title_label, 0, wxEXPAND | wxALL, FromDIP(5));
// Part 2: Description
m_guide_description_label = new Label(parent, _L("The AMS can rotate the filament which is properly stored, providing better drying results."));
m_guide_description_label->SetForegroundColour(*wxBLACK);
m_guide_description_label->SetFont(Label::Body_14);
m_guide_description_label->Wrap(FromDIP(300)); // Wrap text to fit within panel
info_section->Add(m_guide_description_label, 0, wxEXPAND | wxALL, FromDIP(5));
// Part 3: filament panel
wxBoxSizer* fila_section = create_guide_info_filament(parent);
info_section->Add(fila_section, 0, wxEXPAND | wxALL, FromDIP(5));
// Part 4: Circular toggle with description
wxBoxSizer* toggle_section = new wxBoxSizer(wxHORIZONTAL);
m_rotate_spool_toggle = new wxCheckBox(parent, wxID_ANY, "");
m_rotate_spool_toggle->SetValue(false);
m_rotate_spool_toggle->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent& event) {
bool is_checked = event.IsChecked();
// Add toggle behavior logic here
});
toggle_section->Add(m_rotate_spool_toggle, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, FromDIP(10));
// Toggle description
Label* toggle_description = new Label(parent, _L("Rotate spool when drying"), LB_AUTO_WRAP);
toggle_description->SetForegroundColour(*wxBLACK);
toggle_description->SetFont(Label::Body_12);
toggle_section->Add(toggle_description, 1, wxALIGN_CENTER_VERTICAL | wxEXPAND, 0);
info_section->Add(toggle_section, 0, wxEXPAND | wxALL, FromDIP(5));
return info_section;
}
wxBoxSizer* AMSDryCtrWin::create_guide_right_section(wxPanel* parent)
{
wxBoxSizer* right_section = new wxBoxSizer(wxVERTICAL);
// Upper part: Image section
m_image_placeholder = new wxStaticBitmap(parent, wxID_ANY, wxNullBitmap);
m_guide_image = ScalableBitmap(parent, "dev_ams_dry_ctr_filament_in_chamber", 256);
m_image_placeholder->SetBitmap(m_guide_image.bmp());
wxBoxSizer* image_container = new wxBoxSizer(wxHORIZONTAL);
image_container->AddStretchSpacer(1);
image_container->Add(m_image_placeholder, 0, wxALL, FromDIP(5));
right_section->Add(image_container, 0, wxEXPAND | wxALL, FromDIP(5));
wxBoxSizer* buttons_container = new wxBoxSizer(wxHORIZONTAL);
buttons_container->AddStretchSpacer(1);
m_back_button = create_button(
parent,
wxString::FromUTF8(_CTX_utf8(L_CONTEXT("Back", "amsdrying"), "amsdrying")),
wxColour("#F8F8F8"), // Background color - light gray
wxColour("#D0D0D0"), // Border color - gray
*wxBLACK // Text color - black
);
m_back_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this](wxCommandEvent& event) {
m_main_simplebook->SetSelection(0);
});
buttons_container->Add(m_back_button, 0, wxALL, FromDIP(5));
m_start_button = create_button(
parent,
_L("Start"),
AMS_CONTROL_BRAND_COLOUR, // Background color - green
AMS_CONTROL_BRAND_COLOUR, // Border color - green
wxColour("#FFFFFE") // Text color - white
);
m_start_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this](wxCommandEvent& event) {
m_main_simplebook->SetSelection(2);
m_progress_gauge->SetValue(0);
m_progress_timer->Start(70);
m_progress_value = 0;
start_sending_drying_command();
});
buttons_container->Add(m_start_button, 0, wxALL, FromDIP(5));
right_section->Add(buttons_container, 0, wxEXPAND | wxALL, FromDIP(5));
return right_section;
}
wxBoxSizer* AMSDryCtrWin::create_guide_page_sizer(wxPanel* parent)
{
wxBoxSizer* guide_sizer = new wxBoxSizer(wxHORIZONTAL);
wxBoxSizer* info_section = create_guide_info_section(parent);
guide_sizer->Add(info_section, 1, wxEXPAND | wxALL, FromDIP(10));
wxBoxSizer* right_section = create_guide_right_section(parent);
guide_sizer->Add(right_section, 0, wxEXPAND | wxALL, FromDIP(10));
return guide_sizer;
}
void AMSDryCtrWin::start_sending_drying_command()
{
auto fila_system = get_fila_system();
if (!fila_system) {
BOOST_LOG_TRIVIAL(info) << "AMSDryCtrWin::start_sending_drying_command: Invalid FilaSystem Pointer";
return;
}
if (m_temperature_input->GetValue().IsEmpty() || m_time_input->GetValue().IsEmpty()) {
// Show error message to user
BOOST_LOG_TRIVIAL(info) << "AMSDryCtrWin::start_sending_drying_command: Time or temperature is empty";
return;
}
long temperature, time;
if (!m_temperature_input->GetValue().ToLong(&temperature) ||
!m_time_input->GetValue().ToLong(&time)) {
BOOST_LOG_TRIVIAL(info) << "AMSDryCtrWin::start_sending_drying_command: Failed to convert temperature or time";
return;
}
int tray_index;
tray_index = m_trays_combo->GetSelection();
if (m_tray_ids.empty() || tray_index < 0 || tray_index >= m_tray_ids.size()) {
BOOST_LOG_TRIVIAL(warning) << "AMSDryCtrWin::start_sending_drying_command: Invalid tray_index " << tray_index
<< ", m_tray_ids.size=" << m_tray_ids.size();
return;
}
int cooling_temp = 50;
std::optional<DevFilamentDryingPreset> preset = DevUtilBackend::GetFilamentDryingPreset(m_tray_ids[tray_index].filament_id);
if (preset.has_value()) {
cooling_temp = static_cast<int>(preset.value().filament_dev_drying_softening_temperature);
}
fila_system->CtrlAmsStartDryingHour(std::stoi(m_ams_info.m_ams_id), m_tray_ids[tray_index].filament_type,
temperature, time, m_rotate_spool_toggle->GetValue(), cooling_temp, false);
m_dry_setting.m_filament_names[m_ams_info.m_ams_id] = m_tray_ids[tray_index].filament_name;
m_dry_setting.m_filament_type[m_ams_info.m_ams_id] = m_tray_ids[tray_index].filament_type;
m_dry_setting.m_dry_temp[m_ams_info.m_ams_id] = temperature;
m_dry_setting.m_dry_time[m_ams_info.m_ams_id] = time;
}
void AMSDryCtrWin::OnProgressTimer(wxTimerEvent& event)
{
m_progress_value += 1;
if (m_progress_value <= 100)
m_progress_gauge->SetValue(m_progress_value);
if (m_progress_value == 1) { // First tick, reset message index
m_progress_message_index = 0;
if (!m_progress_text.empty()) {
m_progress_title->SetLabel(m_progress_text[0]);
}
}
else if (m_progress_value % 15 == 0) { // Approximately every second
m_progress_message_index++;
if (m_progress_message_index < m_progress_text.size()) {
m_progress_title->SetLabel(m_progress_text[m_progress_message_index]);
m_progress_title->Refresh();
}
}
if (m_progress_value >= 100 && !is_dry_ctr_idle()) {
m_progress_value = 0;
m_progress_timer->Stop();
m_main_simplebook->SetSelection(0);
}
}
void AMSDryCtrWin::restore_stop_button_if_deadline_passed()
{
if (m_stop_button_restore_deadline.has_value()) {
if (std::chrono::steady_clock::now() >= m_stop_button_restore_deadline.value()) {
if (m_stop_button) {
m_stop_button->SetLabel(_L("Stop"));
update_button_size(m_stop_button); // Adjust button size back to original
m_stop_button->Enable();
m_stop_button->Layout();
m_stop_button->GetParent()->Layout();
m_stop_button->Refresh();
}
m_stop_button_restore_deadline.reset();
}
}
}
void AMSDryCtrWin::restore_unload_button_if_deadline_passed()
{
if (m_unload_button_restore_deadline.has_value()) {
if (std::chrono::steady_clock::now() >= m_unload_button_restore_deadline.value()) {
if (m_unload_button) {
m_unload_button->Enable();
}
m_unload_button_restore_deadline.reset();
}
}
}
void AMSDryCtrWin::update_button_size(Button* button)
{
if (!button) return;
// Reset MinSize first to avoid accumulation of size
button->SetMinSize(wxSize(-1, -1));
// Recalculate button size based on current text and DPI settings
wxSize best_size = button->GetBestSize();
int padding_width = FromDIP(4);
int padding_height = FromDIP(2);
wxSize final_size(best_size.GetWidth() + padding_width, best_size.GetHeight() + padding_height);
button->SetMinSize(final_size);
}
void AMSDryCtrWin::OnShow(wxShowEvent& event)
{
if (event.IsShown()) {
wxGetApp().UpdateDlgDarkUI(this);
msw_rescale();
}
event.Skip();
}
void AMSDryCtrWin::OnClose(wxCloseEvent& event)
{
if (m_progress_timer && m_progress_timer->IsRunning()) {
m_progress_timer->Stop();
}
if (m_progress_gauge) {
m_progress_gauge->SetValue(0);
}
m_progress_value = 0;
m_progress_message_index = 0;
if (m_main_simplebook) {
m_main_simplebook->SetSelection(0);
}
if (m_progress_title && !m_progress_text.empty()) {
m_progress_title->SetLabel(m_progress_text[0]);
}
// Clean up and restore stop button state
if (m_stop_button) {
m_stop_button->SetLabel(_L("Stop"));
update_button_size(m_stop_button); // Adjust button size back to original
m_stop_button->Enable();
m_stop_button->Layout();
m_stop_button->GetParent()->Layout();
m_stop_button->Refresh();
}
m_stop_button_restore_deadline.reset();
// Clean up unload button state
if (m_unload_button) {
m_unload_button->Enable();
}
m_unload_button_restore_deadline.reset();
event.Skip();
}
wxBoxSizer* AMSDryCtrWin::create_progress_page_sizer(wxPanel* parent)
{
wxBoxSizer* progress_sizer = new wxBoxSizer(wxVERTICAL);
m_progress_title = new Label(parent, m_progress_text[0]);
m_progress_title->SetForegroundColour(*wxBLACK);
m_progress_title->SetFont(Label::Body_16);
progress_sizer->Add(0, 0, 1, wxEXPAND, 0); // Spacer
progress_sizer->Add(m_progress_title, 0, wxALIGN_CENTER | wxALL, FromDIP(30));
m_progress_gauge = new ProgressBar(parent, wxID_ANY, 100, wxDefaultPosition, wxSize(FromDIP(300), FromDIP(8)));
m_progress_gauge->SetValue(0);
m_progress_gauge->SetHeight(FromDIP(8));
progress_sizer->Add(m_progress_gauge, 0, wxALIGN_CENTER | wxALL, FromDIP(10));
progress_sizer->Add(0, 0, 1, wxEXPAND, 0);
return progress_sizer;
}
void AMSDryCtrWin::create()
{
// set title icon
SetBackgroundColour(StateColor::darkModeColorFor(*wxWHITE));
this->SetDoubleBuffered(true);
std::string icon_path = (boost::format("%1%/images/OrcaSlicerTitle.ico") % resources_dir()).str();
SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO));
SetSize(wxSize(FromDIP(700), FromDIP(500)));
SetMinSize(wxSize(FromDIP(700), FromDIP(500)));
SetMaxSize(wxSize(FromDIP(700), FromDIP(500)));
m_main_simplebook = new wxSimplebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize);
// Create main page
m_original_page = new wxPanel(m_main_simplebook, wxID_ANY);
m_original_page->SetBackgroundColour(*wxWHITE);
wxBoxSizer* main_sizer = create_main_page_sizer(m_original_page);
m_original_page->SetSizer(main_sizer);
m_main_simplebook->AddPage(m_original_page, "Main Page");
m_guide_page = new wxPanel(m_main_simplebook, wxID_ANY);
m_guide_page->SetBackgroundColour(*wxWHITE);
wxBoxSizer* guide_sizer = create_guide_page_sizer(m_guide_page);
m_guide_page->SetSizer(guide_sizer);
m_main_simplebook->AddPage(m_guide_page, "Guide Page");
// Create progress page
m_progress_page = new wxPanel(m_main_simplebook, wxID_ANY);
m_progress_page->SetBackgroundColour(*wxWHITE);
wxBoxSizer* progress_sizer = create_progress_page_sizer(m_progress_page);
m_progress_page->SetSizer(progress_sizer);
m_main_simplebook->AddPage(m_progress_page, "Progress Page");
m_progress_timer = new wxTimer(this, wxID_ANY);
Bind(wxEVT_TIMER, &AMSDryCtrWin::OnProgressTimer, this, m_progress_timer->GetId());
Bind(wxEVT_CLOSE_WINDOW, &AMSDryCtrWin::OnClose, this);
wxBoxSizer* top_level_sizer = new wxBoxSizer(wxVERTICAL);
top_level_sizer->Add(m_main_simplebook, 1, wxEXPAND | wxALL, FromDIP(10));
Bind(wxEVT_SHOW, &AMSDryCtrWin::OnShow, this);
SetSizer(top_level_sizer);
Layout();
Refresh();
wxGetApp().UpdateDlgDarkUI(this);
}
void AMSDryCtrWin::on_dpi_changed(const wxRect &suggested_rect)
{
msw_rescale();
}
void AMSDryCtrWin::msw_rescale()
{
if (!IsShown()) {
return;
}
if (m_ams_filament_panel) {m_ams_filament_panel->msw_rescale();}
if (m_trays_combo) {m_trays_combo->Rescale(); m_trays_combo->Layout(); m_trays_combo->SetFont(Label::Body_14), m_trays_combo->Refresh();}
if (m_humidity_img && m_humidity_image.bmp().IsOk()) {m_humidity_image.msw_rescale(); m_humidity_img->SetBitmap(m_humidity_image.bmp());}
if (m_image_placeholder && m_guide_image.bmp().IsOk()) {m_guide_image.msw_rescale();m_image_placeholder->SetBitmap(m_guide_image.bmp());}
if (m_image_description_icon && m_description_icon_bitmap.bmp().IsOk()) {m_description_icon_bitmap.msw_rescale(); m_image_description_icon->SetBitmap(m_description_icon_bitmap.bmp());}
// Rescale and update button sizes based on text content
if (m_next_button) {
m_next_button->Rescale();
update_button_size(m_next_button);
m_next_button->Layout();
m_next_button->Refresh();
}
if (m_stop_button) {
m_stop_button->Rescale();
update_button_size(m_stop_button);
m_stop_button->Layout();
m_stop_button->Refresh();
}
if (m_start_button) {
m_start_button->Rescale();
update_button_size(m_start_button);
m_start_button->Layout();
m_start_button->Refresh();
}
if (m_back_button) {
m_back_button->Rescale();
update_button_size(m_back_button);
m_back_button->Layout();
m_back_button->Refresh();
}
if (m_unload_button) {
m_unload_button->Rescale();
update_button_size(m_unload_button);
m_unload_button->Layout();
m_unload_button->Refresh();
}
if (m_guide_page) {m_guide_page->Layout();}
if (m_original_page) {m_original_page->Layout();}
Fit();
Layout();
Refresh();
}
void AMSDryCtrWin::set_ams_id(const std::string& ams_id)
{
m_ams_info.m_ams_id = ams_id;
m_is_ams_changed = true;
}
void AMSDryCtrWin::update_img_description(DevAms::DryStatus status, DevAms::DrySubStatus sub_status)
{
if (status == DevAms::DryStatus::Off || status == DevAms::DryStatus::Cooling) {
m_image_description->SetLabel(_L("Idle"));
m_image_description_icon->Show(false);
return;
}
// Determine label text for non-idle states
wxString label_text;
if (status == DevAms::DryStatus::Error) {
label_text = _L("Drying");
} else if (sub_status == DevAms::DrySubStatus::Heating) {
label_text = _L("Drying-Heating");
} else if (sub_status == DevAms::DrySubStatus::Dehumidify) {
label_text = _L("Drying-Dehumidifying");
} else {
m_image_description_icon->Show(false);
return;
}
m_image_description->SetLabel(label_text);
try {
m_description_icon_bitmap = ScalableBitmap(this, "dev_ams_dry_ctr_heating_icon", 20);
m_description_icon_bitmap.msw_rescale();
m_image_description_icon->SetBitmap(m_description_icon_bitmap.bmp());
m_image_description_icon->Show(true);
} catch (Exception&) {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " Error loading drying icon";
m_image_description_icon->Show(false);
}
}
int AMSDryCtrWin::update_image(DevAmsType model, DevAms::DryStatus status, DevAms::DrySubStatus sub_status, int humidity_percent)
{
if (model == m_ams_info.m_model && status == m_ams_info.m_dry_status
&& sub_status == m_ams_info.m_dry_sub_status && humidity_percent == m_ams_info.m_humidity_percent) {
return 0;
}
std::string img_path;
if (status == DevAms::DryStatus::Off && sub_status == DevAms::DrySubStatus::Off) {
img_path = get_humidity_level_img_path(humidity_percent);
} else {
img_path = get_dry_status_img_path(model, status, sub_status);
}
if (img_path.empty()) {
return 0;
}
m_humidity_image = ScalableBitmap(this, img_path, AMS_DRY_STATUS_IMAGE_SIZE);
m_humidity_img->SetBitmap(m_humidity_image.bmp());
update_img_description(status, sub_status);
return 1;
}
bool AMSDryCtrWin::check_values_changed(DevAms* dev_ams)
{
bool changed = false;
if (m_ams_info.m_model != dev_ams->GetAmsType()) {
m_ams_info.m_model = dev_ams->GetAmsType();
changed = true;
}
if (dev_ams->GetDryStatus().has_value() && m_ams_info.m_dry_status != dev_ams->GetDryStatus()) {
m_ams_info.m_dry_status = dev_ams->GetDryStatus().value();
changed = true;
}
if (dev_ams->GetDrySubStatus().has_value() && m_ams_info.m_dry_sub_status != dev_ams->GetDrySubStatus()) {
m_ams_info.m_dry_sub_status = dev_ams->GetDrySubStatus().value();
changed = true;
}
if (m_ams_info.m_humidity_percent != dev_ams->GetHumidityPercent()) {
m_ams_info.m_humidity_percent = dev_ams->GetHumidityPercent();
changed = true;
}
return changed;
}
void AMSDryCtrWin::update_normal_description(DevAms* dev_ams)
{
if (m_tray_ids.empty() || m_trays_combo->GetSelection() >= m_tray_ids.size()) { return; }
FilamentBaseInfo info = m_tray_ids[m_trays_combo->GetSelection()];
wxString warning_text;
bool can_enable_button = true;
long temp_val = 0, time_val = 0;
m_temperature_input->GetValue().ToLong(&temp_val);
m_time_input->GetValue().ToLong(&time_val);
std::optional<Slic3r::DevFilamentDryingPreset> preset = DevUtilBackend::GetFilamentDryingPreset(info.filament_id);
auto total_dry = preset.has_value() ? preset.value().ams_limitations : std::unordered_set<DevAmsType>();
struct AmsTempLimit { DevAmsType type; int min_temp; int max_temp; const char* name; };
static const AmsTempLimit ams_limits[] = {
{ DevAmsType::N3F, 45, 65, "AMS2" },
{ DevAmsType::N3S, 45, 85, "AMS-S" }
};
for (const auto& lim : ams_limits) {
if (dev_ams->GetAmsType() == lim.type) {
if (temp_val > lim.max_temp) {
wxString msg = wxString(lim.name) + _L(" maximum drying temperature is ") + wxString::Format(wxT("%d"), lim.max_temp) + wxString::FromUTF8("°C.");
warning_text += msg + "\n";
can_enable_button = false;
} else if (temp_val < lim.min_temp) {
wxString msg = wxString(lim.name) + _L(" minimum drying temperature is ") + wxString::Format(wxT("%d"), lim.min_temp) + wxString::FromUTF8("°C.");
warning_text += msg + "\n";
can_enable_button = false;
}
if (total_dry.find(lim.type) == total_dry.end()) {
warning_text += _L("This filament may not be completely dried.") + "\n\n";
}
break;
}
}
if (m_printer_status.m_is_printing && temp_val > m_ams_info.m_recommand_dry_temp) {
warning_text += _L("This AMS is currently printing. To ensure print quality, the drying temperature cannot exceed the recommended drying temperature.") + "\n";
can_enable_button = false;
} else if (preset.has_value()) {
// Only check heat distortion temperature when AMS has filament inserted;
// empty AMS only needs to respect the device hardware temperature limit.
bool has_filament_inserted = false;
for (const auto& tray_pair : dev_ams->GetTrays()) {
if (tray_pair.second && tray_pair.second->is_exists) {
has_filament_inserted = true;
break;
}
}
if (has_filament_inserted) {
auto limit_temperature = preset.value().filament_dev_ams_drying_heat_distortion_temperature;
if (temp_val > limit_temperature) {
warning_text += _L("The temperature shall not exceed the filament's heat distortion temperature") + "(" +
wxString::Format(wxT("%d"), static_cast<int>(limit_temperature)) + wxString::FromUTF8("°C)\n");
can_enable_button = false;
}
}
}
if (time_val < 1) {
warning_text += _L("Minimum time value cannot be less than 1.") + "\n";
can_enable_button = false;
} else if (time_val > 24) {
warning_text += _L("Maximum time value cannot be greater than 24.") + "\n";
can_enable_button = false;
}
m_next_button->Enable(can_enable_button);
m_normal_description->SetLabel(warning_text);
m_normal_description->Wrap(FromDIP(250));
m_normal_description->GetParent()->Layout();
}
void AMSDryCtrWin::update_normal_state(DevAms* dev_ams)
{
if (is_dry_ctr_idle(dev_ams)) {
m_next_button->Show(true);
m_normal_description->Show(true);
m_trays_combo->Enable();
m_temperature_input->SetEditable(true);
m_time_input->SetEditable(true);
m_stop_button->Hide();
m_dry_error_sizer->Show(false);
} else if (is_dry_ctr_err(dev_ams)) {
m_dry_error_sizer->Show(true);
m_next_button->Hide();
m_normal_description->Hide();
m_trays_combo->Hide();
m_temperature_input->Hide();
m_time_input->Hide();
m_stop_button->Show(true);
} else {
m_next_button->Hide();
m_normal_description->Hide();
m_trays_combo->Disable();
m_temperature_input->SetEditable(false);
m_time_input->SetEditable(false);
m_stop_button->Show(true);
m_dry_error_sizer->Show(false);
}
if (m_temperature_input->GetValue().IsEmpty() || m_time_input->GetValue().IsEmpty()) {
m_next_button->Disable();
m_start_button->Disable();
} else {
m_next_button->Enable();
}
update_normal_description(dev_ams);
}
void AMSDryCtrWin::OnFilamentSelectionChanged(wxCommandEvent& event)
{
int selectionIndex = event.GetSelection();
wxString selectedFilament = event.GetString();
auto fila_system = get_fila_system();
if (!fila_system) {
BOOST_LOG_TRIVIAL(info) << "AMSDryCtrWin::OnFilamentSelectionChanged: Invalid FilaSystem Pointer";
return;
}
DevAms* dev_ams = fila_system->GetAmsById(m_ams_info.m_ams_id);
if (!dev_ams) {
BOOST_LOG_TRIVIAL(info) << "AMSDryCtrWin::OnFilamentSelectionChanged: Invalid AMS id";
return;
}
std::optional<Slic3r::DevFilamentDryingPreset> preset = DevUtilBackend::GetFilamentDryingPreset(m_tray_ids[selectionIndex].filament_id);
if (preset.has_value()) {
DevFilamentDryingPreset info = preset.value();
if (m_printer_status.m_is_printing) {
m_temperature_input->SetValue(std::to_string(static_cast<int>(info.filament_dev_ams_drying_temperature_on_print[dev_ams->GetAmsType()])));
m_time_input->SetValue(std::to_string(static_cast<int>(info.filament_dev_ams_drying_time_on_print[dev_ams->GetAmsType()])));
} else {
m_temperature_input->SetValue(std::to_string(static_cast<int>(info.filament_dev_ams_drying_temperature_on_idle[dev_ams->GetAmsType()])));
m_time_input->SetValue(std::to_string(static_cast<int>(info.filament_dev_ams_drying_time_on_idle[dev_ams->GetAmsType()])));
}
}
update_filament_guide_info(dev_ams);
}
wxString get_cannot_reason_text(DevAms::CannotDryReason reason)
{
wxString cannot_reason_text;
switch (reason)
{
case DevAms::CannotDryReason::InsufficientPower:
cannot_reason_text = "*" + _L("Insufficient power") + "\n";
cannot_reason_text += _L(" Too many AMS drying simultaneously. Please plug in the power or stop other drying processes before starting.") + "\n";
break;
case DevAms::CannotDryReason::AmsBusy:
cannot_reason_text = "*" + _L("AMS is busy") + "\n";
cannot_reason_text += _L(" AMS is calibrating | reading RFID | loading/unloading material, please wait.") + "\n";
break;
case DevAms::CannotDryReason::ConsumableAtAmsOutlet:
cannot_reason_text = "*" + _L("Filament in AMS outlet") + "\n";
cannot_reason_text += _L(" The high drying temperature may cause AMS blockage, please unload first.");
break;
case DevAms::CannotDryReason::InitiatingAmsDrying:
cannot_reason_text = "*" + _L("Initiating AMS drying") + "\n";
break;
case DevAms::CannotDryReason::NotSupportedIn2dMode:
cannot_reason_text = "*" + _L("Not supported in 2D mode") + "\n";
break;
case DevAms::CannotDryReason::DryingInProgress:
cannot_reason_text = "*" + _L("Task in progress") + "\n";
cannot_reason_text += _L(" The AMS might be in use during Task.") + "\n";
break;
case DevAms::CannotDryReason::Upgrading:
cannot_reason_text = "*" + _L("Upgrading") + "\n";
cannot_reason_text += _L(" Firmware update in progress, please wait...") + "\n";
break;
case DevAms::CannotDryReason::InsufficientPowerNeedPluginPower:
cannot_reason_text = "*" + _L("Insufficient power") + "\n";
cannot_reason_text += _L(" Please plug in the power and then use the drying function.") + "\n";
break;
case DevAms::CannotDryReason::FilamentAtAmsOutletManualUnload:
cannot_reason_text = "*" + _L("Filament in AMS outlet") + "\n";
cannot_reason_text += _L(" The high drying temperature may cause AMS blockage. Please unload the filament manually before proceeding.") + "\n";
break;
default:
cannot_reason_text = "*" + _L("System is busy") + "\n";
cannot_reason_text += _L(" Initiating other drying processes, please wait a few seconds...") + "\n";
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": unknown cannot dry reason";
break;
}
return cannot_reason_text;
}
wxString organize_cannot_reasons_text(std::vector<DevAms::CannotDryReason>& reasons)
{
wxString cannot_reasons_text;
if (std::find(reasons.begin(), reasons.end(), DevAms::CannotDryReason::DryingInProgress) != reasons.end()) {
cannot_reasons_text += get_cannot_reason_text(DevAms::CannotDryReason::DryingInProgress);
} else if (std::find(reasons.begin(), reasons.end(), DevAms::CannotDryReason::AmsBusy) != reasons.end()) {
cannot_reasons_text += get_cannot_reason_text(DevAms::CannotDryReason::AmsBusy);
} else if (std::find(reasons.begin(), reasons.end(), DevAms::CannotDryReason::ConsumableAtAmsOutlet) != reasons.end()) {
cannot_reasons_text += get_cannot_reason_text(DevAms::CannotDryReason::ConsumableAtAmsOutlet);
} else if (std::find(reasons.begin(), reasons.end(), DevAms::CannotDryReason::FilamentAtAmsOutletManualUnload) != reasons.end()) {
cannot_reasons_text += get_cannot_reason_text(DevAms::CannotDryReason::FilamentAtAmsOutletManualUnload);
}
if (std::find(reasons.begin(), reasons.end(), DevAms::CannotDryReason::InsufficientPower) != reasons.end()) {
cannot_reasons_text += get_cannot_reason_text(DevAms::CannotDryReason::InsufficientPower);
}
for (auto reason : reasons) {
if (reason == DevAms::CannotDryReason::InsufficientPowerNeedPluginPower) {
cannot_reasons_text += get_cannot_reason_text(DevAms::CannotDryReason::InsufficientPowerNeedPluginPower);
} else if (reason == DevAms::CannotDryReason::NotSupportedIn2dMode) {
cannot_reasons_text += get_cannot_reason_text(DevAms::CannotDryReason::NotSupportedIn2dMode);
} else if (reason == DevAms::CannotDryReason::InitiatingAmsDrying) {
cannot_reasons_text += get_cannot_reason_text(DevAms::CannotDryReason::InitiatingAmsDrying);
} else if (reason == DevAms::CannotDryReason::Upgrading) {
cannot_reasons_text += get_cannot_reason_text(DevAms::CannotDryReason::Upgrading);
}
}
if (cannot_reasons_text.empty()) {
cannot_reasons_text += "*" + _L("System is busy") + "\n";
cannot_reasons_text += _L(" Initiating other drying processes, please wait a few seconds...") + "\n";
}
return cannot_reasons_text;
}
int AMSDryCtrWin::update_state(DevAms* dev_ams)
{
std::vector<DevAms::CannotDryReason> cannot_reasons = dev_ams->GetCannotDryReason().has_value()?
dev_ams->GetCannotDryReason().value(): std::vector<DevAms::CannotDryReason>();
if (cannot_reasons.size() == 0 ||
(cannot_reasons.size() == 1 && cannot_reasons[0] == DevAms::CannotDryReason::DryingInProgress)) {
m_normal_state_sizer->Show(true);
m_cannot_dry_sizer->Show(false);
m_unload_button->Show(false);
update_normal_state(dev_ams);
} else if (cannot_reasons.size() > 0) {
m_normal_state_sizer->Show(false);
m_cannot_dry_sizer->Show(true);
m_cannot_dry_description_label->SetLabel(organize_cannot_reasons_text(cannot_reasons));
m_cannot_dry_description_label->Wrap(FromDIP(300));
// Show unload button when ConsumableAtAmsOutlet reason is present
bool has_consumable_at_outlet = std::find(cannot_reasons.begin(), cannot_reasons.end(),
DevAms::CannotDryReason::ConsumableAtAmsOutlet) != cannot_reasons.end();
m_unload_button->Show(has_consumable_at_outlet);
}
restore_stop_button_if_deadline_passed();
restore_unload_button_if_deadline_passed();
return 1;
}
int AMSDryCtrWin::update_ams_change(DevAms* dev_ams)
{
if (!is_ams_changed(dev_ams)) {
return 0;
}
m_ams_info.m_ams_id = dev_ams->GetAmsId();
if (dev_ams->GetAmsType() == DevAmsType::N3F) {
m_temperature_input->SetHint("45-65" + wxString::FromUTF8("°C"));
} else if (dev_ams->GetAmsType() == DevAmsType::N3S) {
m_temperature_input->SetHint("45-85" + wxString::FromUTF8("°C"));
}
m_time_input->SetHint("1-24 h");
return 0;
}
int AMSDryCtrWin::update_dryness_status(DevAms* dev_ams)
{
int updated = 0;
if (m_ams_info.m_humidity_percent != dev_ams->GetHumidityPercent()) {
updated += 1;
m_ams_info.m_humidity_percent = dev_ams->GetHumidityPercent();
m_humidity_data_label->SetLabel(std::to_string(m_ams_info.m_humidity_percent) + "%");
}
if (m_ams_info.m_temperature != dev_ams->GetCurrentTemperature()) {
updated += 1;
m_ams_info.m_temperature = dev_ams->GetCurrentTemperature();
m_temperature_data_label->SetLabel(std::to_string(m_ams_info.m_temperature) + wxString::FromUTF8("°C"));
}
if (is_dry_ctr_idle(dev_ams)) {
m_time_descrition_container->Show(false);
m_original_page->Layout();
} else {
if (is_dry_status_changed(dev_ams)) {
m_time_descrition_container->Show(true);
m_original_page->Layout();
}
if (m_ams_info.m_left_dry_time != dev_ams->GetLeftDryTime()) {
updated += 1;
m_ams_info.m_left_dry_time = dev_ams->GetLeftDryTime();
m_time_data_label->SetLabel(wxString::Format("%02d : %02d",
m_ams_info.m_left_dry_time / 60, m_ams_info.m_left_dry_time % 60));
}
}
return updated;
}
bool AMSDryCtrWin::is_tray_changed(DevAms* dev_ams)
{
return false;
}
void AMSDryCtrWin::update_filament_guide_info(DevAms* dev_ams)
{
if (!IsShown()) {
return;
}
m_guide_page->Freeze();
m_ams_filament_panel->Clear();
m_ams_filament_panel->SetAmsName(dev_ams->GetDisplayName());
// Get the temperature input value
long input_temp = 0;
bool valid_temp = !m_temperature_input->GetValue().IsEmpty() &&
m_temperature_input->GetValue().ToLong(&input_temp);
bool can_start = true;
int slot_count = 0, empty_count = 0;
for (auto& tray_pair : dev_ams->GetTrays()) {
if (!tray_pair.second) {
continue;
}
++slot_count;
if (!tray_pair.second->is_exists) {
m_ams_filament_panel->AddFilamentItem("/", "dev_ams_dry_ctr_enable");
++empty_count;
continue;
}
auto preset_opt = tray_pair.second->get_ams_drying_preset();
wxString filament_type = tray_pair.second->get_display_filament_type();
DevFilamentDryingPreset preset;
if (filament_type.IsEmpty()) {
auto fallback_preset = DevUtilBackend::GetFilamentDryingPreset("GFA00");
preset = fallback_preset.value();
filament_type = "?";
} else if (preset_opt.has_value()) {
preset = preset_opt.value();
} else {
auto fallback_preset = DevUtilBackend::GetFilamentDryingPreset("GFA00");
preset = fallback_preset.value();
}
std::string icon_path = "dev_ams_dry_ctr_enable";
int distortion_temp = static_cast<int>(preset.filament_dev_ams_drying_heat_distortion_temperature);
if (valid_temp && distortion_temp < input_temp) {
icon_path = "dev_ams_dry_ctr_disable";
can_start = false;
}
m_ams_filament_panel->AddFilamentItem(filament_type, icon_path);
}
if (slot_count == 0) {
can_start = false;
}
if (can_start) {
m_guide_title_label->SetLabel(_L("For better drying results, remove the filament and allow it to rotate."));
m_guide_description_label->SetLabel(_L("The AMS will automatically rotate the stored filament slots to enhance the drying performance.") +
"\n" + _L("Alternatively, you can dry the filament without removing it.") +
"\n" + "*" + _L("Unknown filaments will be treated as PLA."));
m_guide_description_label->Wrap(FromDIP(300));
} else {
m_guide_title_label->SetLabel(_L("Please store the filament marked with an exclamation mark."));
m_guide_description_label->SetLabel(_L("Filament left in the feeder during drying may soften because the drying temperature exceeds the softening point of materials like PLA and TPU.") +
"\n" + "*" + _L("Unknown filaments will be treated as PLA."));
m_guide_description_label->Wrap(FromDIP(300));
}
m_start_button->Enable(can_start);
m_guide_page->Layout();
m_guide_page->Thaw();
}
int AMSDryCtrWin::update_filament_list(DevAms* dev_ams, MachineObject* obj)
{
const bool ams_changed = is_ams_changed(dev_ams);
bool rebuilt_filament_list = false;
// Build `m_tray_ids` and the combobox items from the preset bundle.
// This list is also used as a lookup table in non-idle state (type -> name),
// so it must be available even when the combobox is disabled.
auto rebuild_filament_list = [&]() -> bool {
m_trays_combo->Clear();
m_tray_ids.clear();
PresetBundle *preset_bundle = wxGetApp().preset_bundle;
if (!preset_bundle || !obj) {
return false;
}
std::set<std::string> filament_id_set;
auto & filaments = preset_bundle->filaments;
// Get nozzle diameter using the same method as AMSMaterialsSetting::Popup
std::ostringstream stream;
int extruder_id = obj->GetFilaSystem()->GetExtruderIdByAmsId(m_ams_info.m_ams_id);
if (!obj->GetExtderSystem()->GetExtderById(extruder_id)) {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " get extruder id failed";
extruder_id = 0;
}
stream << std::fixed << std::setprecision(1) << obj->GetExtderSystem()->GetNozzleDiameter(extruder_id);
std::string nozzle_diameter_str = stream.str();
std::set<std::string> printer_names = preset_bundle->get_printer_names_by_printer_type_and_nozzle(
DevPrinterConfigUtil::get_printer_display_name(obj->printer_type), nozzle_diameter_str);
for (auto filament_it = filaments.begin(); filament_it != filaments.end(); ++filament_it) {
Preset& preset = *filament_it;
// Filter by system preset: root preset and (system preset or user preset is supported)
if (filaments.get_preset_base(*filament_it) != &preset || (!filament_it->is_system && !obj->is_support_user_preset)) {
continue;
}
ConfigOption * printer_opt = filament_it->config.option("compatible_printers");
ConfigOptionStrings *printer_strs = dynamic_cast<ConfigOptionStrings *>(printer_opt);
if (!printer_strs) continue;
for (auto printer_str : printer_strs->values) {
if (printer_names.find(printer_str) != printer_names.end()) {
if (filament_id_set.find(filament_it->filament_id) != filament_id_set.end()) {
continue;
}
filament_id_set.insert(filament_it->filament_id);
auto filament_alias = filaments.get_preset_alias(*filament_it, true);
if (!filament_alias.empty()) {
auto opt_info = preset_bundle->get_filament_by_filament_id(filament_it->filament_id);
if (opt_info.has_value()) {
auto real_info = opt_info.value();
real_info.filament_name = filament_alias;
m_tray_ids.push_back(std::move(real_info));
m_trays_combo->Append(wxString::FromUTF8(filament_alias));
}
}
}
}
}
if (m_tray_ids.empty()) {
BOOST_LOG_TRIVIAL(warning) << "AMSDryCtrWin::update_filament_list: No valid filaments found";
return false;
}
return true;
};
if (ams_changed || m_tray_ids.empty() || m_trays_combo->GetCount() == 0) {
// Disable start button during rebuild
if (m_start_button) {
m_start_button->Disable();
}
rebuilt_filament_list = rebuild_filament_list();
}
if (!is_dry_ctr_idle(dev_ams)) {
const std::string& ams_id = dev_ams->GetAmsId();
const auto settings_opt = dev_ams->GetDrySettings();
// Set the combobox display label by the filament "type" string.
// Priority: last saved selection for this AMS (if the type matches) -> fallback to current `m_tray_ids`.
auto set_filament_label_by_type = [&](const std::string& filament_type) {
if (filament_type.empty()) {
return;
}
auto it_name = m_dry_setting.m_filament_names.find(ams_id);
auto it_type = m_dry_setting.m_filament_type.find(ams_id);
if (it_name != m_dry_setting.m_filament_names.end() && it_type != m_dry_setting.m_filament_type.end()
&& it_type->second == filament_type) {
m_trays_combo->SetLabel(wxString::FromUTF8(it_name->second));
return;
}
const auto it = std::find_if(m_tray_ids.begin(), m_tray_ids.end(), [&](const FilamentBaseInfo& tray) {
return tray.filament_type == filament_type;
});
if (it != m_tray_ids.end()) {
m_trays_combo->SetLabel(wxString::FromUTF8(it->filament_name));
}
};
if (settings_opt.has_value()) {
const auto& settings = settings_opt.value();
m_temperature_input->SetValue(std::to_string(settings.dry_temp));
m_time_input->SetValue(std::to_string(settings.dry_hour));
set_filament_label_by_type(settings.dry_filament);
} else {
auto it_name = m_dry_setting.m_filament_names.find(ams_id);
if (it_name != m_dry_setting.m_filament_names.end()) {
m_trays_combo->SetLabel(wxString::FromUTF8(it_name->second));
m_temperature_input->SetValue(std::to_string(m_dry_setting.m_dry_temp[ams_id]));
m_time_input->SetValue(std::to_string(m_dry_setting.m_dry_time[ams_id]));
}
}
return 0;
}
// Idle state: avoid re-selecting / firing selection change unless the list was rebuilt.
if (!rebuilt_filament_list && !ams_changed && is_dry_ctr_idle()) {
return 0;
}
if (m_tray_ids.empty()) {
return 0;
}
// Select recommended drying temperature and default filament
float min_dry_temp = std::numeric_limits<float>::max();
std::string default_filament_id = "GFA00";
bool has_ready = false;
const auto fallback_preset = DevUtilBackend::GetFilamentDryingPreset("GFA00");
for (const auto& tray_pair : dev_ams->GetTrays()) {
if (!tray_pair.second || !tray_pair.second->is_tray_info_ready()) continue;
has_ready = true;
wxString filament_type = tray_pair.second->get_display_filament_type();
Slic3r::DevFilamentDryingPreset preset;
if (filament_type.IsEmpty()) {
// no filament type, is PLA
if (!fallback_preset) continue;
preset = fallback_preset.value();
} else {
auto preset_opt = tray_pair.second->get_ams_drying_preset();
if (preset_opt.has_value()) {
preset = preset_opt.value();
} else {
// no presetis PLA
if (!fallback_preset) continue;
preset = fallback_preset.value();
}
}
float cur_temp = m_printer_status.m_is_printing
? std::min({preset.filament_dev_ams_drying_temperature_on_print[dev_ams->GetAmsType()],
preset.filament_dev_drying_softening_temperature, preset.filament_dev_ams_drying_heat_distortion_temperature})
: preset.filament_dev_ams_drying_temperature_on_idle[dev_ams->GetAmsType()];
if (cur_temp < min_dry_temp) {
min_dry_temp = cur_temp;
default_filament_id = preset.filament_id;
}
}
// if no tray is ready, use PLA as default
if (!has_ready) {
if (fallback_preset.has_value()) {
Slic3r::DevFilamentDryingPreset preset = fallback_preset.value();
float cur_temp = m_printer_status.m_is_printing
? std::min({preset.filament_dev_ams_drying_temperature_on_print[dev_ams->GetAmsType()],
preset.filament_dev_drying_softening_temperature, preset.filament_dev_ams_drying_heat_distortion_temperature})
: preset.filament_dev_ams_drying_temperature_on_idle[dev_ams->GetAmsType()];
min_dry_temp = cur_temp;
default_filament_id = preset.filament_id;
}
}
m_ams_info.m_recommand_dry_temp = min_dry_temp;
// Set default selection
unsigned int default_index = 0;
for (unsigned int i = 0; i < m_tray_ids.size(); i++) {
if (m_tray_ids[i].filament_id == default_filament_id) {
default_index = i;
break;
}
}
m_trays_combo->SetSelection(default_index);
wxCommandEvent evt(wxEVT_COMBOBOX, m_trays_combo->GetId());
evt.SetInt(default_index);
OnFilamentSelectionChanged(evt);
return 1;
}
std::shared_ptr<DevFilaSystem> AMSDryCtrWin::get_fila_system() const
{
std::shared_ptr<DevFilaSystem> fila_system = m_fila_system.lock();
if (!fila_system) {
const_cast<AMSDryCtrWin*>(this)->Close();
}
return fila_system;
}
void AMSDryCtrWin::update_printer_state(MachineObject* obj)
{
m_printer_status.m_is_printing = obj->is_in_printing()
&& obj->GetExtderSystem()->GetCurrentAmsId() == m_ams_info.m_ams_id;
}
void AMSDryCtrWin::update(std::shared_ptr<DevFilaSystem> fila_system, MachineObject* obj)
{
if (!fila_system || !obj) {
return;
}
update_printer_state(obj);
m_fila_system = fila_system;
DevAms* dev_ams = fila_system->GetAmsById(m_ams_info.m_ams_id);
if (!dev_ams) {
BOOST_LOG_TRIVIAL(info) << "AMSDryCtrWin::update: Invalid AMS id";
m_ams_info.m_ams_id = "";
Close();
return;
}
if (!dev_ams->IsSupportRemoteDry(fila_system->GetOwner())) {
BOOST_LOG_TRIVIAL(info) << "AMSDryCtrWin::update: Selected AMS does not support remote drying";
Close();
return;
}
update_ams_change(dev_ams);
update_image(dev_ams->GetAmsType(),
dev_ams->GetDryStatus().has_value()? dev_ams->GetDryStatus().value(): DevAms::DryStatus::Off,
dev_ams->GetDrySubStatus().has_value()? dev_ams->GetDrySubStatus().value(): DevAms::DrySubStatus::Off,
dev_ams->GetHumidityPercent());
update_state(dev_ams);
update_dryness_status(dev_ams);
update_filament_list(dev_ams, obj);
update_filament_guide_info(dev_ams);
m_is_ams_changed = false;
check_values_changed(dev_ams);
Layout();
Refresh();
}
bool AMSDryCtrWin::is_ams_changed(DevAms* dev_ams)
{
return m_ams_info.m_ams_id != dev_ams->GetAmsId() || m_is_ams_changed;
}
bool AMSDryCtrWin::is_dry_status_changed(DevAms* dev_ams)
{
if (!dev_ams->GetDryStatus().has_value() || !dev_ams->GetDrySubStatus().has_value()) {
return true;
}
return dev_ams->GetDryStatus().value() != m_ams_info.m_dry_status
|| dev_ams->GetDrySubStatus().value() != m_ams_info.m_dry_sub_status;
}
bool AMSDryCtrWin::is_dry_ctr_idle(DevAms* dev_ams)
{
if (!dev_ams->GetDryStatus().has_value() || !dev_ams->GetDrySubStatus().has_value()) {
return true;
}
return dev_ams->GetDryStatus().value() == DevAms::DryStatus::Off
|| dev_ams->GetDryStatus().value() == DevAms::DryStatus::Cooling;
}
bool AMSDryCtrWin::is_dry_ctr_idle()
{
return m_ams_info.m_dry_status == DevAms::DryStatus::Off || m_ams_info.m_dry_status == DevAms::DryStatus::Cooling;
}
bool AMSDryCtrWin::is_dry_ctr_err(DevAms* dev_ams)
{
if (!dev_ams->GetDryStatus().has_value() || !dev_ams->GetDrySubStatus().has_value()) {
return false;
}
return dev_ams->GetDryStatus().value() == DevAms::DryStatus::Error;
}
} // GUI
} // Slic3r
+253
View File
@@ -0,0 +1,253 @@
#pragma once
#include "GUI_ObjectLayers.hpp"
#include "slic3r/GUI/Widgets/AMSItem.hpp"
#include "slic3r/GUI/Widgets/Label.hpp"
#include "slic3r/GUI/Widgets/PopupWindow.hpp"
#include "slic3r/GUI/wxExtensions.hpp"
#include "slic3r/GUI/DeviceCore/DevFilaSystem.h"
#include "slic3r/GUI/I18N.hpp"
#include <chrono>
#include <optional>
//Previous defintions
class wxGrid;
namespace Slic3r {
namespace GUI {
enum class DryCtrState {
IDLE,
DRY_WHEN_PRINT,
UNKNOWN
};
enum class DryCtrDev {
N3S,
N3F,
UNKNOWN
};
struct DryingPreset {
DryCtrState state;
DryCtrDev dev;
int dry_temp;
int dry_time;
};
class FilamentItemPanel : public wxPanel
{
public:
FilamentItemPanel(wxWindow* parent, const wxString& text, const std::string& icon_name = "",
wxWindowID id = wxID_ANY);
void SetText(const wxString& text);
void SetIcon(const std::string& icon_name);
void msw_rescale();
private:
void OnPaint(wxPaintEvent& event);
void OnSize(wxSizeEvent& event);
Label* m_text_label;
wxStaticBitmap* m_icon_bitmap;
int m_target_size;
std::string m_icon_name;
ScalableBitmap m_icon;
};
class AMSFilamentPanel : public wxPanel
{
wxBoxSizer* m_filament_sizer;
Label* m_ams_name_label;
int m_border_radius;
wxPanel* m_filament_container{nullptr};
std::vector<FilamentItemPanel*> m_filament_items;
public:
AMSFilamentPanel(wxWindow* parent, const wxString& ams_name, wxWindowID id = wxID_ANY);
void AddFilamentItem(const wxString& text, const std::string& icon_name);
void AddFilamentItem(FilamentItemPanel* panel);
void SetAmsName(const wxString& ams_name);
void Clear();
void msw_rescale();
private:
void OnPaint(wxPaintEvent& event);
};
class AMSDryCtrWin : public DPIDialog
{
public:
AMSDryCtrWin(wxWindow *parent);
~AMSDryCtrWin();
void msw_rescale();
void update(std::shared_ptr<DevFilaSystem> fila_system, MachineObject* obj);
void set_ams_id(const std::string& ams_id);
protected:
void on_dpi_changed(const wxRect &suggested_rect) override;
private:
wxSimplebook* m_main_simplebook{nullptr};
wxPanel* m_original_page{nullptr};
wxWindow* m_amswin{nullptr};
wxBoxSizer* m_sizer_ams_items{nullptr};
wxScrolledWindow* m_panel_prv_left {nullptr};
wxScrolledWindow* m_panel_prv_right{nullptr};
wxBoxSizer* m_sizer_prv_left{nullptr};
wxBoxSizer* m_sizer_prv_right{nullptr};
// left panel related members
ScalableBitmap m_humidity_image;
wxStaticBitmap* m_humidity_img{nullptr};
Label* m_image_description{nullptr};
wxStaticBitmap* m_image_description_icon{nullptr};
ScalableBitmap m_description_icon_bitmap;
Label* m_humidity_data_label = nullptr;
Label* m_temperature_data_label = nullptr;
Label* m_time_data_label = nullptr;
wxBoxSizer* m_time_descrition_container = nullptr;
// right panel related members
wxBoxSizer* m_normal_state_sizer{nullptr};
wxBoxSizer* m_cannot_dry_sizer{nullptr};
wxBoxSizer* m_dry_error_sizer{nullptr};
Label* m_cannot_dry_description_label = nullptr;
// right panel normal state
ComboBox* m_trays_combo;
std::vector<FilamentBaseInfo> m_tray_ids;
wxTextCtrl* m_temperature_input;
wxTextCtrl* m_time_input;
Label* m_normal_description;
Button* m_start_button{nullptr};
Button* m_next_button{nullptr};
Button* m_stop_button{nullptr};
Button* m_back_button{nullptr};
Button* m_unload_button{nullptr};
// guide page description
Label* m_guide_title_label{nullptr};
Label* m_guide_description_label{nullptr};
wxCheckBox* m_rotate_spool_toggle{nullptr};
wxPanel* m_progress_page;
ProgressBar* m_progress_gauge;
wxTimer* m_progress_timer;
std::optional<std::chrono::steady_clock::time_point> m_stop_button_restore_deadline;
std::optional<std::chrono::steady_clock::time_point> m_unload_button_restore_deadline;
Label* m_progress_title;
int m_progress_value;
int m_progress_message_index;
std::vector<wxString> m_progress_text = {
_L("Starting: Checking adapter connection"),
_L("Starting: Checking filament status"),
_L("Starting: Checking drying presets"),
_L("Starting: Checking filament location"),
_L("Starting: Checking air intake"),
_L("Starting: Checking air vent")
};
// Guide page
wxPanel* m_guide_page{nullptr};
AMSFilamentPanel* m_ams_filament_panel{nullptr};
std::map<std::string, FilamentItemPanel*> m_filament_items;
wxStaticBitmap* m_image_placeholder{nullptr};
ScalableBitmap m_guide_image;
bool m_is_ams_changed = false;
std::weak_ptr<DevFilaSystem> m_fila_system;
struct {
std::string m_ams_id;
DevAmsType m_model = DevAmsType::EXT_SPOOL;
DevAms::DryStatus m_dry_status = DevAms::DryStatus::Off;
DevAms::DrySubStatus m_dry_sub_status = DevAms::DrySubStatus::Off;
int m_humidity_percent;
int m_temperature;
int m_left_dry_time;
float m_recommand_dry_temp;
} m_ams_info;
struct {
std::unordered_map<std::string, std::string> m_filament_names;
std::unordered_map<std::string, std::string> m_filament_type;
std::unordered_map<std::string, int> m_dry_temp;
std::unordered_map<std::string, int> m_dry_time;
} m_dry_setting;
struct {
bool m_is_printing = false;
} m_printer_status;
private:
void create();
wxBoxSizer* create_guide_page_sizer(wxPanel* parent);
wxBoxSizer* create_main_content_section(wxPanel* parent);
wxBoxSizer* create_guide_info_filament(wxPanel* parent);
wxBoxSizer* create_guide_info_section(wxPanel* parent);
wxBoxSizer* create_guide_right_section(wxPanel* parent);
wxBoxSizer* create_main_page_sizer(wxPanel* parent);
wxBoxSizer* create_left_panel(wxPanel* parent);
wxBoxSizer* create_humidity_status_section(wxPanel* parent);
wxBoxSizer* create_description_item(wxPanel* parent, const wxString& title, Label*& dataLabel);
wxBoxSizer* create_status_descriptions_section(wxPanel* parent);
wxBoxSizer* create_right_panel(wxPanel* parent);
wxBoxSizer* create_normal_state_panel(wxPanel* parent);
wxBoxSizer* create_cannot_dry_panel(wxPanel* parent);
wxBoxSizer* create_drying_error_panel(wxPanel* parent);
Button* create_button(wxPanel* parent, const wxString& title,
const wxColour& background_color, const wxColour& border_color, const wxColour& text_color);
wxBoxSizer* create_progress_page_sizer(wxPanel* parent);
void OnProgressTimer(wxTimerEvent& event);
void OnClose(wxCloseEvent& event);
void OnShow(wxShowEvent& event);
void OnFilamentSelectionChanged(wxCommandEvent& event);
wxScrolledWindow* create_preview_scrolled_window(wxWindow* parent);
bool check_values_changed(DevAms* dev_ams);
int update_image(DevAmsType type, DevAms::DryStatus status, DevAms::DrySubStatus sub_status, int humidity_percent);
void update_img_description(DevAms::DryStatus status, DevAms::DrySubStatus sub_status);
void update_normal_description(DevAms* dev_ams);
int update_state(DevAms* dev_ams);
int update_dryness_status(DevAms* dev_ams);
int update_ams_change(DevAms* dev_ams);
int update_filament_list(DevAms* dev_ams, MachineObject* obj);
void update_filament_guide_info(DevAms* dev_ams);
void update_normal_state(DevAms* dev_ams);
void update_printer_state(MachineObject* obj);
std::shared_ptr<DevFilaSystem> get_fila_system() const;
void start_sending_drying_command();
void restore_stop_button_if_deadline_passed();
void restore_unload_button_if_deadline_passed();
void update_button_size(Button* button);
bool is_dry_status_changed(DevAms* dev_ams);
bool is_dry_ctr_idle(DevAms* dev_ams);
bool is_ams_changed(DevAms* dev_ams);
bool is_dry_ctr_idle();
bool is_tray_changed(DevAms* dev_ams);
bool is_dry_ctr_err(DevAms* dev_ams);
};
} // GUI
} // Slic3r

Some files were not shown because too many files have changed in this diff Show More