mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-06 23:31:19 +00:00
Compare commits
9
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f5bd05d20d | ||
|
|
13d4a0d922 | ||
|
|
c74ac8a6c3 | ||
|
|
2d90345d1e | ||
|
|
5a8eb3f14e | ||
|
|
e7d6f5e6c0 | ||
|
|
e098c933f0 | ||
|
|
d1afb1fed6 | ||
|
|
f8dd56053c |
@@ -131,13 +131,6 @@
|
||||
<true/>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
|
||||
<key>NSLocalNetworkUsageDescription</key>
|
||||
<string>OrcaSlicer uses your local network to discover and connect to printers.</string>
|
||||
<key>NSBonjourServices</key>
|
||||
<array>
|
||||
<string>_octoprint._tcp</string>
|
||||
<string>_http._tcp</string>
|
||||
</array>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<!-- Disable App Transport Security. Resolves https://github.com/OrcaSlicer/OrcaSlicer/issues/791 -->
|
||||
|
||||
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-10-06 13:42+0800\n"
|
||||
"POT-Creation-Date: 2026-10-05 10:49-0300\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -4046,9 +4046,6 @@ msgstr ""
|
||||
msgid "You need to select the material type and color first."
|
||||
msgstr ""
|
||||
|
||||
msgid "The minimum temperature cannot be greater than the maximum temperature."
|
||||
msgstr ""
|
||||
|
||||
#, possible-c-format, possible-boost-format
|
||||
msgid "Please input a valid value (K in %.1f~%.1f)"
|
||||
msgstr ""
|
||||
@@ -5785,7 +5782,7 @@ msgstr ""
|
||||
msgid "Size:"
|
||||
msgstr ""
|
||||
|
||||
#, possible-boost-format
|
||||
#, possible-c-format, possible-boost-format
|
||||
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
|
||||
msgstr ""
|
||||
|
||||
@@ -6624,22 +6621,6 @@ msgstr ""
|
||||
msgid "File '%s' was lost! Please download it again."
|
||||
msgstr ""
|
||||
|
||||
msgid "gcodes"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to delete the file from printer."
|
||||
msgstr ""
|
||||
|
||||
#, possible-c-format, possible-boost-format
|
||||
msgid "Do you want to print the file '%s' from printer?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Print file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to start the print job."
|
||||
msgstr ""
|
||||
|
||||
#, possible-c-format, possible-boost-format
|
||||
msgid ""
|
||||
"File: %s\n"
|
||||
@@ -9483,6 +9464,14 @@ msgstr ""
|
||||
msgid "Show incompatible/unsupported presets in the printer and filament dropdown lists. These presets cannot be selected."
|
||||
msgstr ""
|
||||
|
||||
msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
|
||||
msgid "Experimental Features"
|
||||
msgstr ""
|
||||
|
||||
@@ -9494,14 +9483,6 @@ msgid ""
|
||||
"Highly experimental! Slow and may create artifact."
|
||||
msgstr ""
|
||||
|
||||
msgid "Use printer agents instead of print hosts"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
|
||||
msgid "Allow Abnormal Storage"
|
||||
msgstr ""
|
||||
|
||||
@@ -10207,12 +10188,6 @@ msgstr ""
|
||||
msgid "Clean Up"
|
||||
msgstr ""
|
||||
|
||||
msgid "AMS filament mapping is not available for this printer. Clear the AMS mapping before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "A filament used by this print has no AMS mapping. Assign it before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "Preparing print job"
|
||||
msgstr ""
|
||||
|
||||
@@ -14804,12 +14779,6 @@ msgstr ""
|
||||
msgid "If the model has two parts that are symmetric about the Y axis, and you want these parts to have symmetric textures, please click this option on one of the parts."
|
||||
msgstr ""
|
||||
|
||||
msgid "Fill pattern tops"
|
||||
msgstr ""
|
||||
|
||||
msgid "Choose this option if you want to completely fill in the tops of the infill pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Infill combination - Max layer height"
|
||||
msgstr ""
|
||||
|
||||
@@ -26331,9 +26300,6 @@ msgstr ""
|
||||
msgid "An error occurred loading %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "/"
|
||||
msgstr ""
|
||||
|
||||
#, possible-boost-format
|
||||
msgid "Load %1% to %2%"
|
||||
msgstr ""
|
||||
|
||||
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-10-06 13:42+0800\n"
|
||||
"POT-Creation-Date: 2026-10-05 10:49-0300\n"
|
||||
"PO-Revision-Date: 2025-03-15 10:55+0100\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
@@ -4426,9 +4426,6 @@ msgstr "Estàs segur que vols esborrar la informació del filament?"
|
||||
msgid "You need to select the material type and color first."
|
||||
msgstr "Primer heu de seleccionar el tipus de material i el color."
|
||||
|
||||
msgid "The minimum temperature cannot be greater than the maximum temperature."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Please input a valid value (K in %.1f~%.1f)"
|
||||
msgstr "Introduïu un valor vàlid (K a %.1f~%.1f)"
|
||||
@@ -6303,7 +6300,7 @@ msgid "Size:"
|
||||
msgstr "Mida:"
|
||||
|
||||
# AI Translated
|
||||
#, boost-format
|
||||
#, c-format, boost-format
|
||||
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
|
||||
msgstr "S'han trobat conflictes de rutes de G-code a la capa %d, Z = %.2lfmm. Si us plau, separeu els objectes conflictius més lluny ( %s <-> %s )."
|
||||
|
||||
@@ -7183,22 +7180,6 @@ msgstr "El fitxer .gcode.3mf no conté dades de G-code. Lamineu-lo amb Orca Slic
|
||||
msgid "File '%s' was lost! Please download it again."
|
||||
msgstr "L'arxiu '%s' s'ha perdut! Si us plau, descarregueu-lo de nou."
|
||||
|
||||
msgid "gcodes"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to delete the file from printer."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Do you want to print the file '%s' from printer?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Print file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to start the print job."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid ""
|
||||
"File: %s\n"
|
||||
@@ -10439,6 +10420,18 @@ msgstr "Mostrar els perfils no compatibles"
|
||||
msgid "Show incompatible/unsupported presets in the printer and filament dropdown lists. These presets cannot be selected."
|
||||
msgstr "Mostra els perfils incompatibles o no compatibles a les llistes desplegables d'impressora i de filament. Aquests perfils no es poden seleccionar."
|
||||
|
||||
# AI Translated
|
||||
msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
msgstr "(Experimental) Utilitza agents d'impressora en lloc d'amfitrions d'impressió"
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"Envia els treballs d'impressió de les impressores que no són Bambu a través dels agents de connector d'impressora en lloc del flux clàssic de pujada a l'amfitrió d'impressió.\n"
|
||||
"Quan està desactivat, OrcaSlicer utilitza el comportament antic de l'amfitrió d'impressió."
|
||||
|
||||
# AI Translated
|
||||
msgid "Experimental Features"
|
||||
msgstr "Funcions experimentals"
|
||||
@@ -10455,17 +10448,6 @@ msgstr ""
|
||||
"Intenta conservar les característiques pintades (color/costura/suport/pell difusa, etc.) després de canviar la malla de l'objecte (com ara tallar, recarregar des del disc, simplificar, reparar, etc.).\n"
|
||||
"Molt experimental! És lent i pot generar defectes."
|
||||
|
||||
msgid "Use printer agents instead of print hosts"
|
||||
msgstr ""
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"Envia els treballs d'impressió de les impressores que no són Bambu a través dels agents de connector d'impressora en lloc del flux clàssic de pujada a l'amfitrió d'impressió.\n"
|
||||
"Quan està desactivat, OrcaSlicer utilitza el comportament antic de l'amfitrió d'impressió."
|
||||
|
||||
msgid "Allow Abnormal Storage"
|
||||
msgstr "Permet emmagatzematge anormal"
|
||||
|
||||
@@ -11281,12 +11263,6 @@ msgstr "Cancel·lar el timelapse i imprimir"
|
||||
msgid "Clean Up"
|
||||
msgstr "Netejar"
|
||||
|
||||
msgid "AMS filament mapping is not available for this printer. Clear the AMS mapping before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "A filament used by this print has no AMS mapping. Assign it before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "Preparing print job"
|
||||
msgstr "Preparant el treball d'impressió"
|
||||
|
||||
@@ -16588,12 +16564,6 @@ msgstr "Farciment simètric eix Y"
|
||||
msgid "If the model has two parts that are symmetric about the Y axis, and you want these parts to have symmetric textures, please click this option on one of the parts."
|
||||
msgstr "Si el model té dues parts simètriques respecte a l'eix Y i voleu que aquestes parts tinguin textures simètriques, feu clic en aquesta opció en una de les parts."
|
||||
|
||||
msgid "Fill pattern tops"
|
||||
msgstr ""
|
||||
|
||||
msgid "Choose this option if you want to completely fill in the tops of the infill pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Infill combination - Max layer height"
|
||||
msgstr "Combinació de farciment: alçada màxima de la capa"
|
||||
|
||||
@@ -30537,9 +30507,6 @@ msgstr "Activar les eines de desenvolupament"
|
||||
msgid "An error occurred loading %s"
|
||||
msgstr "S'ha produït un error en carregar %s"
|
||||
|
||||
msgid "/"
|
||||
msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, boost-format
|
||||
msgid "Load %1% to %2%"
|
||||
@@ -32243,6 +32210,9 @@ msgstr ""
|
||||
#~ msgid "An error occurred loading "
|
||||
#~ msgstr "S'ha produït un error en carregar "
|
||||
|
||||
#~ msgid "/"
|
||||
#~ msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, c-format, boost-format
|
||||
#~ msgid "Load %s to "
|
||||
@@ -32448,10 +32418,6 @@ msgstr ""
|
||||
#~ msgid "Support/Color Painting: adjust section position"
|
||||
#~ msgstr "Suport/Pintat de color: configuració de la posició de la secció"
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
#~ msgstr "(Experimental) Utilitza agents d'impressora en lloc d'amfitrions d'impressió"
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "Tab"
|
||||
#~ msgstr "Pestanya"
|
||||
|
||||
@@ -3,7 +3,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Orca Slicer\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-10-06 13:42+0800\n"
|
||||
"POT-Creation-Date: 2026-10-05 10:49-0300\n"
|
||||
"PO-Revision-Date: \n"
|
||||
"Last-Translator: Jakub Hencl\n"
|
||||
"Language-Team: \n"
|
||||
@@ -4384,9 +4384,6 @@ msgstr "Opravdu chcete vymazat informace o filamentu?"
|
||||
msgid "You need to select the material type and color first."
|
||||
msgstr "Nejprve musíte vybrat typ materiálu a barvu."
|
||||
|
||||
msgid "The minimum temperature cannot be greater than the maximum temperature."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Please input a valid value (K in %.1f~%.1f)"
|
||||
msgstr "Zadejte platnou hodnotu (K v rozsahu %.1f~%.1f)"
|
||||
@@ -6272,7 +6269,7 @@ msgid "Size:"
|
||||
msgstr "Velikost:"
|
||||
|
||||
# AI Translated
|
||||
#, boost-format
|
||||
#, c-format, boost-format
|
||||
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
|
||||
msgstr "Byly nalezeny konflikty drah G-code ve vrstvě %d, Z = %.2lf mm. Oddělte prosím konfliktní objekty více od sebe (%s <-> %s)."
|
||||
|
||||
@@ -7162,22 +7159,6 @@ msgstr "Soubor .gcode.3mf neobsahuje žádná G-code data. Prosím, rozřežte m
|
||||
msgid "File '%s' was lost! Please download it again."
|
||||
msgstr "Soubor '%s' byl ztracen! Stáhněte jej prosím znovu."
|
||||
|
||||
msgid "gcodes"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to delete the file from printer."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Do you want to print the file '%s' from printer?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Print file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to start the print job."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid ""
|
||||
"File: %s\n"
|
||||
@@ -10401,6 +10382,18 @@ msgstr "Zobrazit nepodporované předvolby"
|
||||
msgid "Show incompatible/unsupported presets in the printer and filament dropdown lists. These presets cannot be selected."
|
||||
msgstr "Zobrazovat nekompatibilní/nepodporované předvolby v rozevíracích seznamech tiskáren a filamentů. Tyto předvolby nelze vybrat."
|
||||
|
||||
# AI Translated
|
||||
msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
msgstr "(Experimentální) Používat agenty tiskárny místo tiskových hostů"
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"Směruje tiskové úlohy pro tiskárny jiné než Bambu přes agenty pluginů tiskárny místo klasického nahrávání na tiskový host.\n"
|
||||
"Pokud je vypnuto, OrcaSlicer používá původní chování tiskového hosta."
|
||||
|
||||
# AI Translated
|
||||
msgid "Experimental Features"
|
||||
msgstr "Experimentální funkce"
|
||||
@@ -10417,17 +10410,6 @@ msgstr ""
|
||||
"Pokusí se zachovat malované prvky (barva/šev/podpory/fuzzy atd.) po změně sítě objektu (například řez / znovunačtení z disku / zjednodušení / oprava atd.)\n"
|
||||
"Vysoce experimentální! Pomalé a může vytvářet artefakty."
|
||||
|
||||
msgid "Use printer agents instead of print hosts"
|
||||
msgstr ""
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"Směruje tiskové úlohy pro tiskárny jiné než Bambu přes agenty pluginů tiskárny místo klasického nahrávání na tiskový host.\n"
|
||||
"Pokud je vypnuto, OrcaSlicer používá původní chování tiskového hosta."
|
||||
|
||||
msgid "Allow Abnormal Storage"
|
||||
msgstr "Povolit neobvyklé úložiště"
|
||||
|
||||
@@ -11245,12 +11227,6 @@ msgstr "Zrušit časosběr a tisknout"
|
||||
msgid "Clean Up"
|
||||
msgstr "Vyčistit"
|
||||
|
||||
msgid "AMS filament mapping is not available for this printer. Clear the AMS mapping before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "A filament used by this print has no AMS mapping. Assign it before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "Preparing print job"
|
||||
msgstr "Příprava tiskové úlohy"
|
||||
|
||||
@@ -16558,12 +16534,6 @@ msgstr "Symetrická výplň podle osy Y"
|
||||
msgid "If the model has two parts that are symmetric about the Y axis, and you want these parts to have symmetric textures, please click this option on one of the parts."
|
||||
msgstr "Pokud má model dvě části symetrické podle osy Y a chcete, aby měly symetrické textury, klikněte na tuto možnost u jedné z těchto částí."
|
||||
|
||||
msgid "Fill pattern tops"
|
||||
msgstr ""
|
||||
|
||||
msgid "Choose this option if you want to completely fill in the tops of the infill pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Infill combination - Max layer height"
|
||||
msgstr "Kombinace výplně – maximální výška vrstvy"
|
||||
|
||||
@@ -30547,10 +30517,6 @@ msgstr "Povolit vývojářské nástroje"
|
||||
msgid "An error occurred loading %s"
|
||||
msgstr "Při načítání %s došlo k chybě"
|
||||
|
||||
# AI Translated
|
||||
msgid "/"
|
||||
msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, boost-format
|
||||
msgid "Load %1% to %2%"
|
||||
@@ -32260,6 +32226,10 @@ msgstr ""
|
||||
#~ msgid "An error occurred loading "
|
||||
#~ msgstr "Při načítání došlo k chybě: "
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "/"
|
||||
#~ msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, c-format, boost-format
|
||||
#~ msgid "Load %s to "
|
||||
@@ -32466,10 +32436,6 @@ msgstr ""
|
||||
#~ msgid "Support/Color Painting: adjust section position"
|
||||
#~ msgstr "Podpora/barva malování: nastavení pozice úseku"
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
#~ msgstr "(Experimentální) Používat agenty tiskárny místo tiskových hostů"
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "Tab"
|
||||
#~ msgstr "Tab"
|
||||
|
||||
@@ -3,7 +3,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Orca Slicer\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-10-06 13:42+0800\n"
|
||||
"POT-Creation-Date: 2026-10-05 10:49-0300\n"
|
||||
"PO-Revision-Date: \n"
|
||||
"Last-Translator: Heiko Liebscher <hliebschergmail.com>\n"
|
||||
"Language-Team: \n"
|
||||
@@ -4297,9 +4297,6 @@ msgstr "Sind Sie sicher, dass Sie die Filamentinformationen löschen möchten?"
|
||||
msgid "You need to select the material type and color first."
|
||||
msgstr "Sie müssen zuerst den Materialtyp und die Farbe auswählen."
|
||||
|
||||
msgid "The minimum temperature cannot be greater than the maximum temperature."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Please input a valid value (K in %.1f~%.1f)"
|
||||
msgstr "Bitte geben Sie einen gültigen Wert ein (K in %.1f~%.1f)"
|
||||
@@ -6162,7 +6159,7 @@ msgstr "Volumen:"
|
||||
msgid "Size:"
|
||||
msgstr "Größe:"
|
||||
|
||||
#, boost-format
|
||||
#, c-format, boost-format
|
||||
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
|
||||
msgstr "Konflikte von G-Code-Pfaden wurden bei Layer %d, Z = %.2lf mm gefunden.Bitte trennen Sie die konfliktbehafteten Objekte weiter voneinander (%s <-> %s)."
|
||||
|
||||
@@ -7030,22 +7027,6 @@ msgstr "Die .gcode.3mf-Datei enthält keine G-Code-Daten. Bitte slicen Sie sie m
|
||||
msgid "File '%s' was lost! Please download it again."
|
||||
msgstr "Die Datei '%s' ist verloren gegangen! Bitte laden Sie diese erneut herunter."
|
||||
|
||||
msgid "gcodes"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to delete the file from printer."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Do you want to print the file '%s' from printer?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Print file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to start the print job."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid ""
|
||||
"File: %s\n"
|
||||
@@ -10230,6 +10211,18 @@ msgstr "Nicht unterstützte Profile anzeigen"
|
||||
msgid "Show incompatible/unsupported presets in the printer and filament dropdown lists. These presets cannot be selected."
|
||||
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."
|
||||
|
||||
# AI Translated
|
||||
msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
msgstr "(Experimentell) Drucker-Agenten anstelle von Druck-Hosts verwenden"
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"Leitet Druckaufträge für Nicht-Bambu-Drucker über Drucker-Plugin-Agenten statt über den klassischen Druck-Host-Upload.\n"
|
||||
"Wenn deaktiviert, verwendet OrcaSlicer das bisherige Druck-Host-Verhalten."
|
||||
|
||||
msgid "Experimental Features"
|
||||
msgstr "Experimentelle Funktionen"
|
||||
|
||||
@@ -10243,17 +10236,6 @@ msgstr ""
|
||||
"Versuchen Sie, bemalte Funktionen (Farbe/Naht/Stütze/unscharf usw.) nach Änderung des Objekt-Meshs (z. B. schneiden/neu laden von der Festplatte/vereinfachen/reparieren usw.) beizubehalten\n"
|
||||
"Sehr experimentell! Langsam und kann Artefakte erzeugen."
|
||||
|
||||
msgid "Use printer agents instead of print hosts"
|
||||
msgstr ""
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"Leitet Druckaufträge für Nicht-Bambu-Drucker über Drucker-Plugin-Agenten statt über den klassischen Druck-Host-Upload.\n"
|
||||
"Wenn deaktiviert, verwendet OrcaSlicer das bisherige Druck-Host-Verhalten."
|
||||
|
||||
msgid "Allow Abnormal Storage"
|
||||
msgstr "Fehlerhaften Speicher zulassen"
|
||||
|
||||
@@ -11064,12 +11046,6 @@ msgstr "Zeitraffer abbrechen & Drucken"
|
||||
msgid "Clean Up"
|
||||
msgstr "Bereinigen"
|
||||
|
||||
msgid "AMS filament mapping is not available for this printer. Clear the AMS mapping before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "A filament used by this print has no AMS mapping. Assign it before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "Preparing print job"
|
||||
msgstr "Druckauftrag vorbereiten"
|
||||
|
||||
@@ -16235,12 +16211,6 @@ msgstr "Symmetrische Füllung Y-Achse"
|
||||
msgid "If the model has two parts that are symmetric about the Y axis, and you want these parts to have symmetric textures, please click this option on one of the parts."
|
||||
msgstr "Wenn das Modell zwei Teile hat, die symmetrisch zur Y-Achse sind, und Sie möchten, dass diese Teile symmetrische Texturen haben, klicken Sie bitte auf diese Option auf einem der Teile."
|
||||
|
||||
msgid "Fill pattern tops"
|
||||
msgstr ""
|
||||
|
||||
msgid "Choose this option if you want to completely fill in the tops of the infill pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Infill combination - Max layer height"
|
||||
msgstr "Kombinieren der Füllung - Maximale Schichthöhe"
|
||||
|
||||
@@ -29933,9 +29903,6 @@ msgstr "Entwicklertools aktivieren"
|
||||
msgid "An error occurred loading %s"
|
||||
msgstr "Fehler beim Laden von %s"
|
||||
|
||||
msgid "/"
|
||||
msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, boost-format
|
||||
msgid "Load %1% to %2%"
|
||||
@@ -31637,6 +31604,9 @@ msgstr ""
|
||||
#~ msgid "An error occurred loading "
|
||||
#~ msgstr "Fehler beim Laden von "
|
||||
|
||||
#~ msgid "/"
|
||||
#~ msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, c-format, boost-format
|
||||
#~ msgid "Load %s to "
|
||||
@@ -31842,10 +31812,6 @@ msgstr ""
|
||||
#~ msgid "Support/Color Painting: adjust section position"
|
||||
#~ msgstr "Stützen/Farbmalen: Position des Abschnitts anpassen"
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
#~ msgstr "(Experimentell) Drucker-Agenten anstelle von Druck-Hosts verwenden"
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "Tab"
|
||||
#~ msgstr "Tab"
|
||||
|
||||
@@ -3,7 +3,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Orca Slicer\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-10-06 13:42+0800\n"
|
||||
"POT-Creation-Date: 2026-10-05 10:49-0300\n"
|
||||
"PO-Revision-Date: 2026-06-17 15:44-0300\n"
|
||||
"Last-Translator: Alexandre Folle de Menezes\n"
|
||||
"Language-Team: \n"
|
||||
@@ -4042,9 +4042,6 @@ msgstr ""
|
||||
msgid "You need to select the material type and color first."
|
||||
msgstr ""
|
||||
|
||||
msgid "The minimum temperature cannot be greater than the maximum temperature."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Please input a valid value (K in %.1f~%.1f)"
|
||||
msgstr ""
|
||||
@@ -5781,7 +5778,7 @@ msgstr ""
|
||||
msgid "Size:"
|
||||
msgstr ""
|
||||
|
||||
#, boost-format
|
||||
#, c-format, boost-format
|
||||
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
|
||||
msgstr ""
|
||||
|
||||
@@ -6620,22 +6617,6 @@ msgstr ""
|
||||
msgid "File '%s' was lost! Please download it again."
|
||||
msgstr ""
|
||||
|
||||
msgid "gcodes"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to delete the file from printer."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Do you want to print the file '%s' from printer?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Print file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to start the print job."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid ""
|
||||
"File: %s\n"
|
||||
@@ -9479,6 +9460,14 @@ msgstr ""
|
||||
msgid "Show incompatible/unsupported presets in the printer and filament dropdown lists. These presets cannot be selected."
|
||||
msgstr ""
|
||||
|
||||
msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
|
||||
msgid "Experimental Features"
|
||||
msgstr ""
|
||||
|
||||
@@ -9490,14 +9479,6 @@ msgid ""
|
||||
"Highly experimental! Slow and may create artifact."
|
||||
msgstr ""
|
||||
|
||||
msgid "Use printer agents instead of print hosts"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
|
||||
msgid "Allow Abnormal Storage"
|
||||
msgstr ""
|
||||
|
||||
@@ -10203,12 +10184,6 @@ msgstr ""
|
||||
msgid "Clean Up"
|
||||
msgstr ""
|
||||
|
||||
msgid "AMS filament mapping is not available for this printer. Clear the AMS mapping before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "A filament used by this print has no AMS mapping. Assign it before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "Preparing print job"
|
||||
msgstr ""
|
||||
|
||||
@@ -14800,12 +14775,6 @@ msgstr ""
|
||||
msgid "If the model has two parts that are symmetric about the Y axis, and you want these parts to have symmetric textures, please click this option on one of the parts."
|
||||
msgstr ""
|
||||
|
||||
msgid "Fill pattern tops"
|
||||
msgstr ""
|
||||
|
||||
msgid "Choose this option if you want to completely fill in the tops of the infill pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Infill combination - Max layer height"
|
||||
msgstr ""
|
||||
|
||||
@@ -26327,9 +26296,6 @@ msgstr ""
|
||||
msgid "An error occurred loading %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "/"
|
||||
msgstr ""
|
||||
|
||||
#, boost-format
|
||||
msgid "Load %1% to %2%"
|
||||
msgstr ""
|
||||
|
||||
@@ -3,7 +3,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Orca Slicer\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-10-06 13:42+0800\n"
|
||||
"POT-Creation-Date: 2026-10-05 10:49-0300\n"
|
||||
"PO-Revision-Date: \n"
|
||||
"Last-Translator: Ian A. Bassi <>\n"
|
||||
"Language-Team: \n"
|
||||
@@ -4175,9 +4175,6 @@ msgstr "¿Estás seguro que quieres limpiar la información de filamento?"
|
||||
msgid "You need to select the material type and color first."
|
||||
msgstr "Necesitas seleccionar el tipo y el color del material primero."
|
||||
|
||||
msgid "The minimum temperature cannot be greater than the maximum temperature."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Please input a valid value (K in %.1f~%.1f)"
|
||||
msgstr "Por favor, introduzca un valor válido (K in %.1f~%.1f)"
|
||||
@@ -6015,7 +6012,7 @@ msgstr "Volumen:"
|
||||
msgid "Size:"
|
||||
msgstr "Tamaño:"
|
||||
|
||||
#, boost-format
|
||||
#, c-format, boost-format
|
||||
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
|
||||
msgstr "Se han encontrado conflictos de rutas G-Code en la capa %d, Z = %.2lfmm. Por favor, separe más los objetos en conflicto (%s <-> %s)."
|
||||
|
||||
@@ -6882,22 +6879,6 @@ msgstr "El archivo .gcode .3mf no contiene datos de G-Code. Por favor, lamine co
|
||||
msgid "File '%s' was lost! Please download it again."
|
||||
msgstr "¡El archivo '%s' se perdió!\" Por favor, vuelva a descargárlo."
|
||||
|
||||
msgid "gcodes"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to delete the file from printer."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Do you want to print the file '%s' from printer?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Print file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to start the print job."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid ""
|
||||
"File: %s\n"
|
||||
@@ -9991,6 +9972,18 @@ msgstr "Mostrar ajustes preestablecidos no compatibles"
|
||||
msgid "Show incompatible/unsupported presets in the printer and filament dropdown lists. These presets cannot be selected."
|
||||
msgstr "Mostrar los ajustes preestablecidos incompatibles o no compatibles en los menús desplegables de impresoras y filamentos. Estos ajustes preestablecidos no se pueden seleccionar."
|
||||
|
||||
# AI Translated
|
||||
msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
msgstr "(Experimental) Usar agentes de impresora en lugar de hosts de impresión"
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"Envía los trabajos de impresión de impresoras que no son Bambu a través de los agentes de plugin de impresora en lugar del flujo clásico de subida al host de impresión.\n"
|
||||
"Cuando está desactivado, OrcaSlicer utiliza el comportamiento heredado del host de impresión."
|
||||
|
||||
msgid "Experimental Features"
|
||||
msgstr "Funciones experimentales"
|
||||
|
||||
@@ -10004,17 +9997,6 @@ msgstr ""
|
||||
"Intenta conservar las característica pintadas (color, costuras, soportes, piel rugosa, etc.) tras modificar la malla del objeto (por ejemplo, al cortar, volver a cargar desde el disco, simplificar, corregir, etc.).\n"
|
||||
"¡Muy experimental! Es lento y puede generar artefactos."
|
||||
|
||||
msgid "Use printer agents instead of print hosts"
|
||||
msgstr ""
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"Envía los trabajos de impresión de impresoras que no son Bambu a través de los agentes de plugin de impresora en lugar del flujo clásico de subida al host de impresión.\n"
|
||||
"Cuando está desactivado, OrcaSlicer utiliza el comportamiento heredado del host de impresión."
|
||||
|
||||
msgid "Allow Abnormal Storage"
|
||||
msgstr "Permitir almacenamiento anómalo"
|
||||
|
||||
@@ -10796,12 +10778,6 @@ msgstr "Cancelar timelapse e imprimir"
|
||||
msgid "Clean Up"
|
||||
msgstr "Limpiar"
|
||||
|
||||
msgid "AMS filament mapping is not available for this printer. Clear the AMS mapping before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "A filament used by this print has no AMS mapping. Assign it before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "Preparing print job"
|
||||
msgstr "Preparando el trabajo de impresión"
|
||||
|
||||
@@ -15887,12 +15863,6 @@ msgstr "Relleno simétrico respecto al eje Y"
|
||||
msgid "If the model has two parts that are symmetric about the Y axis, and you want these parts to have symmetric textures, please click this option on one of the parts."
|
||||
msgstr "Si el modelo tiene dos piezas simétricas respecto al eje Y y desea que tengan texturas simétricas, active esta opción en una de las piezas."
|
||||
|
||||
msgid "Fill pattern tops"
|
||||
msgstr ""
|
||||
|
||||
msgid "Choose this option if you want to completely fill in the tops of the infill pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Infill combination - Max layer height"
|
||||
msgstr "Combinación de relleno - Altura máxima de la capa"
|
||||
|
||||
@@ -29489,9 +29459,6 @@ msgstr "Activar herramientas de desarrollo"
|
||||
msgid "An error occurred loading %s"
|
||||
msgstr "Se produjo un error al cargar %s"
|
||||
|
||||
msgid "/"
|
||||
msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, boost-format
|
||||
msgid "Load %1% to %2%"
|
||||
@@ -30171,10 +30138,6 @@ msgstr ""
|
||||
"Evita la deformación\n"
|
||||
"¿Sabías que al imprimir materiales propensos a la deformación como el ABS, aumentar adecuadamente la temperatura de la cama térmica puede reducir la probabilidad de deformaciones?"
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
#~ msgstr "(Experimental) Usar agentes de impresora en lugar de hosts de impresión"
|
||||
|
||||
#~ msgid "X"
|
||||
#~ msgstr "X"
|
||||
|
||||
@@ -31197,6 +31160,9 @@ msgstr ""
|
||||
#~ msgid "An error occurred loading "
|
||||
#~ msgstr "Se produjo un error al cargar "
|
||||
|
||||
#~ msgid "/"
|
||||
#~ msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, c-format, boost-format
|
||||
#~ msgid "Load %s to "
|
||||
|
||||
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-10-06 13:42+0800\n"
|
||||
"POT-Creation-Date: 2026-10-05 10:49-0300\n"
|
||||
"PO-Revision-Date: 2026-07-20 13:33+0200\n"
|
||||
"Last-Translator: Manu Goiogana <mgoiogana@gmail.com>\n"
|
||||
"Language-Team: \n"
|
||||
@@ -4218,9 +4218,6 @@ msgstr "Ziur zaude filamentuaren informazioa garbitu nahi duzula?"
|
||||
msgid "You need to select the material type and color first."
|
||||
msgstr "Lehenik eta behin, material-mota eta kolorea hautatu behar dituzu."
|
||||
|
||||
msgid "The minimum temperature cannot be greater than the maximum temperature."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Please input a valid value (K in %.1f~%.1f)"
|
||||
msgstr "Mesedez, sartu baliozko balio bat (K in %.1f~%.1f)"
|
||||
@@ -6069,7 +6066,7 @@ msgstr "Bolumena:"
|
||||
msgid "Size:"
|
||||
msgstr "Tamaina:"
|
||||
|
||||
#, boost-format
|
||||
#, c-format, boost-format
|
||||
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
|
||||
msgstr "G-code ibilbideen gatazkak aurkitu dira %d geruzan, Z = %.2lf mm. Urrundu gehiago gatazkan dauden objektuak (%s <-> %s)."
|
||||
|
||||
@@ -6933,22 +6930,6 @@ msgstr ".gcode.3mf fitxategiak ez du G-code daturik. Mesedez, xerratu OrcaSlicer
|
||||
msgid "File '%s' was lost! Please download it again."
|
||||
msgstr "'%s' fitxategia galdu da! Deskargatu berriro."
|
||||
|
||||
msgid "gcodes"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to delete the file from printer."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Do you want to print the file '%s' from printer?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Print file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to start the print job."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid ""
|
||||
"File: %s\n"
|
||||
@@ -10080,6 +10061,18 @@ msgstr "Erakutsi onartzen ez diren aurrezarpenak"
|
||||
msgid "Show incompatible/unsupported presets in the printer and filament dropdown lists. These presets cannot be selected."
|
||||
msgstr "Erakutsi bateraezinak edo onartu gabeak diren aurrezarpenak inprimagailuaren eta filamentuaren goitibeherako zerrendetan. Aurrezarpen hauek ezin dira hautatu."
|
||||
|
||||
# AI Translated
|
||||
msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
msgstr "(Esperimentala) Erabili inprimagailu-agenteak inprimatze-hostenen ordez"
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"Bideratu Bambu ez diren inprimagailuen inprimatze-lanak inprimagailuaren plugin-agenteen bidez, inprimatze-hostera igotzeko fluxu klasikoaren ordez.\n"
|
||||
"Desgaituta dagoenean, OrcaSlicer-ek inprimatze-hostaren aurreko portaera erabiltzen du."
|
||||
|
||||
msgid "Experimental Features"
|
||||
msgstr "Ezaugarri esperimentalak"
|
||||
|
||||
@@ -10093,17 +10086,6 @@ msgstr ""
|
||||
"Saiatu pintatutako eginbideak (kolorea/jostura/euskarria/gainazal zimurra eta abar) mantentzen objektuaren sarea aldatu ondoren (adibidez, ebaki/diskotik birkargatu/sinplifikatu/konpondu eta abar).\n"
|
||||
"Oso esperimentala! Motela da eta artefaktuak sor ditzake."
|
||||
|
||||
msgid "Use printer agents instead of print hosts"
|
||||
msgstr ""
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"Bideratu Bambu ez diren inprimagailuen inprimatze-lanak inprimagailuaren plugin-agenteen bidez, inprimatze-hostera igotzeko fluxu klasikoaren ordez.\n"
|
||||
"Desgaituta dagoenean, OrcaSlicer-ek inprimatze-hostaren aurreko portaera erabiltzen du."
|
||||
|
||||
msgid "Allow Abnormal Storage"
|
||||
msgstr "Baimendu biltegiratze anormala"
|
||||
|
||||
@@ -10902,12 +10884,6 @@ msgstr "Utzi timelapsea eta inprimatu"
|
||||
msgid "Clean Up"
|
||||
msgstr "Garbitu"
|
||||
|
||||
msgid "AMS filament mapping is not available for this printer. Clear the AMS mapping before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "A filament used by this print has no AMS mapping. Assign it before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "Preparing print job"
|
||||
msgstr "Inprimatze-lana prestatzen"
|
||||
|
||||
@@ -16046,12 +16022,6 @@ msgstr "Betegarri simetrikoaren Y ardatza"
|
||||
msgid "If the model has two parts that are symmetric about the Y axis, and you want these parts to have symmetric textures, please click this option on one of the parts."
|
||||
msgstr "Modeloak Y ardatzarekiko simetrikoak diren bi zati baditu eta zati horiek testura simetrikoak izatea nahi baduzu, aktibatu aukera hau zatietako batean."
|
||||
|
||||
msgid "Fill pattern tops"
|
||||
msgstr ""
|
||||
|
||||
msgid "Choose this option if you want to completely fill in the tops of the infill pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Infill combination - Max layer height"
|
||||
msgstr "Betegarri-konbinazioa - Gehieneko geruza-altuera"
|
||||
|
||||
@@ -29680,9 +29650,6 @@ msgstr "Gaitu garapen-tresnak"
|
||||
msgid "An error occurred loading %s"
|
||||
msgstr "Errore bat gertatu da %s kargatzean"
|
||||
|
||||
msgid "/"
|
||||
msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, boost-format
|
||||
msgid "Load %1% to %2%"
|
||||
@@ -30362,10 +30329,6 @@ msgstr ""
|
||||
"Saihestu okertzea\n"
|
||||
"Ba al zenekien ABS bezalako okertzeko joera duten materialak inprimatzean ohe beroaren tenperatura egoki igotzeak okertzeko probabilitatea murriztu dezakeela?"
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
#~ msgstr "(Esperimentala) Erabili inprimagailu-agenteak inprimatze-hostenen ordez"
|
||||
|
||||
#~ msgid "X"
|
||||
#~ msgstr "X"
|
||||
|
||||
@@ -31392,6 +31355,9 @@ msgstr ""
|
||||
#~ msgid "An error occurred loading "
|
||||
#~ msgstr "Errore bat gertatu da hau kargatzean: "
|
||||
|
||||
#~ msgid "/"
|
||||
#~ msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, c-format, boost-format
|
||||
#~ msgid "Load %s to "
|
||||
|
||||
@@ -6,7 +6,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Orca Slicer\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-10-06 13:42+0800\n"
|
||||
"POT-Creation-Date: 2026-10-05 10:49-0300\n"
|
||||
"PO-Revision-Date: \n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Guislain Cyril, Thomas Lété\n"
|
||||
@@ -4247,9 +4247,6 @@ msgstr "Voulez-vous vraiment effacer les informations du filament ?"
|
||||
msgid "You need to select the material type and color first."
|
||||
msgstr "Vous devez d'abord sélectionner le type de matériau et sa couleur."
|
||||
|
||||
msgid "The minimum temperature cannot be greater than the maximum temperature."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Please input a valid value (K in %.1f~%.1f)"
|
||||
msgstr "Veuillez saisir une valeur valide (K entre %.1f~%.1f)"
|
||||
@@ -6104,7 +6101,7 @@ msgstr "Volume :"
|
||||
msgid "Size:"
|
||||
msgstr "Taille :"
|
||||
|
||||
#, boost-format
|
||||
#, c-format, boost-format
|
||||
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
|
||||
msgstr "Des conflits de chemins G-code ont été trouvés au niveau de la couche %d, z = %.2lfmm. Veuillez séparer davantage les objets en conflit (%s <-> %s)."
|
||||
|
||||
@@ -6972,22 +6969,6 @@ msgstr "Le fichier G-code .3mf ne contient pas de données G-code. Veuillez le d
|
||||
msgid "File '%s' was lost! Please download it again."
|
||||
msgstr "Le fichier « %s » a été perdu ! Veuillez le télécharger à nouveau."
|
||||
|
||||
msgid "gcodes"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to delete the file from printer."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Do you want to print the file '%s' from printer?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Print file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to start the print job."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid ""
|
||||
"File: %s\n"
|
||||
@@ -10100,6 +10081,18 @@ msgstr "Afficher les préréglages non pris en charge"
|
||||
msgid "Show incompatible/unsupported presets in the printer and filament dropdown lists. These presets cannot be selected."
|
||||
msgstr "Affiche les préréglages incompatibles ou non pris en charge dans les listes déroulantes d’imprimantes et de filaments. Ces préréglages ne peuvent pas être sélectionnés."
|
||||
|
||||
# AI Translated
|
||||
msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
msgstr "(Expérimental) Utiliser les agents d’imprimante au lieu des hôtes d’impression"
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"Achemine les tâches d’impression des imprimantes non Bambu via les agents de plugin d’imprimante au lieu du flux classique d’envoi vers l’hôte d’impression.\n"
|
||||
"Lorsque cette option est désactivée, OrcaSlicer utilise l’ancien comportement de l’hôte d’impression."
|
||||
|
||||
msgid "Experimental Features"
|
||||
msgstr "Fonctionnalités expérimentales"
|
||||
|
||||
@@ -10113,17 +10106,6 @@ msgstr ""
|
||||
"Tente de conserver les éléments peints (couleur/couture/support/surface irrégulière, etc.) après une modification du maillage de l’objet (découpe/rechargement depuis le disque/simplification/réparation, etc.)\n"
|
||||
"Hautement expérimental ! Lent et susceptible de créer des artefacts."
|
||||
|
||||
msgid "Use printer agents instead of print hosts"
|
||||
msgstr ""
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"Achemine les tâches d’impression des imprimantes non Bambu via les agents de plugin d’imprimante au lieu du flux classique d’envoi vers l’hôte d’impression.\n"
|
||||
"Lorsque cette option est désactivée, OrcaSlicer utilise l’ancien comportement de l’hôte d’impression."
|
||||
|
||||
msgid "Allow Abnormal Storage"
|
||||
msgstr "Autoriser le stockage anormal"
|
||||
|
||||
@@ -10918,12 +10900,6 @@ msgstr "Annuler le timelapse et imprimer"
|
||||
msgid "Clean Up"
|
||||
msgstr "Nettoyer"
|
||||
|
||||
msgid "AMS filament mapping is not available for this printer. Clear the AMS mapping before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "A filament used by this print has no AMS mapping. Assign it before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "Preparing print job"
|
||||
msgstr "Préparation du travail d'impression"
|
||||
|
||||
@@ -16069,12 +16045,6 @@ msgstr "Axe Y de remplissage symétrique"
|
||||
msgid "If the model has two parts that are symmetric about the Y axis, and you want these parts to have symmetric textures, please click this option on one of the parts."
|
||||
msgstr "Si le modèle a deux parties symétriques par rapport à l'axe Y et que vous souhaitez que ces parties aient des textures symétriques, veuillez cliquer sur cette option sur l'une des parties."
|
||||
|
||||
msgid "Fill pattern tops"
|
||||
msgstr ""
|
||||
|
||||
msgid "Choose this option if you want to completely fill in the tops of the infill pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Infill combination - Max layer height"
|
||||
msgstr "Combinaison de remplissage - Hauteur maximale de la couche"
|
||||
|
||||
@@ -29422,9 +29392,6 @@ msgstr "Activer les outils de développement"
|
||||
msgid "An error occurred loading %s"
|
||||
msgstr "Une erreur s’est produite lors du chargement de %s"
|
||||
|
||||
msgid "/"
|
||||
msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, boost-format
|
||||
msgid "Load %1% to %2%"
|
||||
@@ -30104,10 +30071,6 @@ msgstr ""
|
||||
"Éviter la déformation\n"
|
||||
"Saviez-vous que lors de l’impression de matériaux susceptibles de se déformer, tels que l’ABS, une augmentation appropriée de la température du plateau chauffant peut réduire la probabilité de déformation?"
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
#~ msgstr "(Expérimental) Utiliser les agents d’imprimante au lieu des hôtes d’impression"
|
||||
|
||||
#~ msgid "X"
|
||||
#~ msgstr "X"
|
||||
|
||||
@@ -31127,6 +31090,9 @@ msgstr ""
|
||||
#~ msgid "An error occurred loading "
|
||||
#~ msgstr "Une erreur s’est produite lors du chargement de "
|
||||
|
||||
#~ msgid "/"
|
||||
#~ msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, c-format, boost-format
|
||||
#~ msgid "Load %s to "
|
||||
|
||||
@@ -3,7 +3,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Orca Slicer\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-10-06 13:42+0800\n"
|
||||
"POT-Creation-Date: 2026-10-05 10:49-0300\n"
|
||||
"Language: hu\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@@ -4357,9 +4357,6 @@ msgstr "Biztosan törölni szeretnéd a filament adatait?"
|
||||
msgid "You need to select the material type and color first."
|
||||
msgstr "Először ki kell választanod az anyagtípust és a színt."
|
||||
|
||||
msgid "The minimum temperature cannot be greater than the maximum temperature."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Please input a valid value (K in %.1f~%.1f)"
|
||||
msgstr "Adj meg érvényes értéket (K tartomány: %.1f~%.1f)"
|
||||
@@ -6239,7 +6236,7 @@ msgid "Size:"
|
||||
msgstr "Méret:"
|
||||
|
||||
# AI Translated
|
||||
#, boost-format
|
||||
#, c-format, boost-format
|
||||
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
|
||||
msgstr "G-code útvonalütközés található a(z) %d. rétegen, Z = %.2lfmm. Helyezd távolabb egymástól az ütköző objektumokat (%s <-> %s)."
|
||||
|
||||
@@ -7125,22 +7122,6 @@ msgstr "A .gcode.3mf fájl nem tartalmaz G-code adatot. Szeleteld újra Orca Sli
|
||||
msgid "File '%s' was lost! Please download it again."
|
||||
msgstr "A(z) '%s' fájl elveszett! Kérlek, töltsd le újra."
|
||||
|
||||
msgid "gcodes"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to delete the file from printer."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Do you want to print the file '%s' from printer?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Print file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to start the print job."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid ""
|
||||
"File: %s\n"
|
||||
@@ -10351,6 +10332,18 @@ msgstr "Nem támogatott beállítások megjelenítése"
|
||||
msgid "Show incompatible/unsupported presets in the printer and filament dropdown lists. These presets cannot be selected."
|
||||
msgstr "Megjeleníti a nem kompatibilis vagy nem támogatott beállításokat a nyomtató- és filamentlegördülő listákban. Ezek a beállítások nem választhatók ki."
|
||||
|
||||
# AI Translated
|
||||
msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
msgstr "(Kísérleti) Nyomtatóügynökök használata nyomtatókiszolgálók helyett"
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"A nem Bambu nyomtatók nyomtatási feladatait a nyomtató bővítményügynökein keresztül továbbítja a klasszikus nyomtatókiszolgálóra való feltöltés helyett.\n"
|
||||
"Ha ki van kapcsolva, az OrcaSlicer a régi nyomtatókiszolgáló-viselkedést használja."
|
||||
|
||||
# AI Translated
|
||||
msgid "Experimental Features"
|
||||
msgstr "Kísérleti funkciók"
|
||||
@@ -10366,17 +10359,6 @@ msgstr ""
|
||||
"Megpróbálja tartani a festett jellemzőket (szín/varrat/támasz/fuzzy stb.) az objektumháló megváltoztatása után (például kivágás/újratöltés lemezről/egyszerűsítés/javítás stb.)\n"
|
||||
"Kísérletei szint! Lassú és hibákat hozhat létre."
|
||||
|
||||
msgid "Use printer agents instead of print hosts"
|
||||
msgstr ""
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"A nem Bambu nyomtatók nyomtatási feladatait a nyomtató bővítményügynökein keresztül továbbítja a klasszikus nyomtatókiszolgálóra való feltöltés helyett.\n"
|
||||
"Ha ki van kapcsolva, az OrcaSlicer a régi nyomtatókiszolgáló-viselkedést használja."
|
||||
|
||||
msgid "Allow Abnormal Storage"
|
||||
msgstr "Rendellenes tároló engedélyezése"
|
||||
|
||||
@@ -11195,12 +11177,6 @@ msgstr "Timelapse megszakítása és nyomtatás"
|
||||
msgid "Clean Up"
|
||||
msgstr "Tisztítás"
|
||||
|
||||
msgid "AMS filament mapping is not available for this printer. Clear the AMS mapping before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "A filament used by this print has no AMS mapping. Assign it before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "Preparing print job"
|
||||
msgstr "Nyomtatási feladat előkészítése"
|
||||
|
||||
@@ -16489,12 +16465,6 @@ msgstr "Szimmetrikus kitöltés Y tengely"
|
||||
msgid "If the model has two parts that are symmetric about the Y axis, and you want these parts to have symmetric textures, please click this option on one of the parts."
|
||||
msgstr "Ha a modell két, az Y tengelyre szimmetrikus részből áll, és azt szeretnéd, hogy ezek a részek szimmetrikus textúrát kapjanak, kattints erre az opcióra az egyik részen."
|
||||
|
||||
msgid "Fill pattern tops"
|
||||
msgstr ""
|
||||
|
||||
msgid "Choose this option if you want to completely fill in the tops of the infill pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Infill combination - Max layer height"
|
||||
msgstr "Kitöltés összevonása - maximális rétegmagasság"
|
||||
|
||||
@@ -30410,10 +30380,6 @@ msgstr "Fejlesztői eszközök engedélyezése"
|
||||
msgid "An error occurred loading %s"
|
||||
msgstr "Hiba történt a(z) %s betöltésekor"
|
||||
|
||||
# AI Translated
|
||||
msgid "/"
|
||||
msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, boost-format
|
||||
msgid "Load %1% to %2%"
|
||||
@@ -32117,6 +32083,10 @@ msgstr ""
|
||||
#~ msgid "An error occurred loading "
|
||||
#~ msgstr "Hiba történt a betöltés során: "
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "/"
|
||||
#~ msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, c-format, boost-format
|
||||
#~ msgid "Load %s to "
|
||||
@@ -32323,10 +32293,6 @@ msgstr ""
|
||||
#~ msgid "Support/Color Painting: adjust section position"
|
||||
#~ msgstr "Támasz/Színfestés: metszet pozíciójának beállítása"
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
#~ msgstr "(Kísérleti) Nyomtatóügynökök használata nyomtatókiszolgálók helyett"
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "Tab"
|
||||
#~ msgstr "Tab"
|
||||
|
||||
@@ -3,7 +3,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Orca Slicer\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-10-06 13:42+0800\n"
|
||||
"POT-Creation-Date: 2026-10-05 10:49-0300\n"
|
||||
"PO-Revision-Date: \n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
@@ -4350,9 +4350,6 @@ msgstr "Sei sicuro di voler cancellare le informazioni del filamento?"
|
||||
msgid "You need to select the material type and color first."
|
||||
msgstr "Devi prima selezionare il tipo e il colore del materiale."
|
||||
|
||||
msgid "The minimum temperature cannot be greater than the maximum temperature."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Please input a valid value (K in %.1f~%.1f)"
|
||||
msgstr "Si prega di immettere un valore valido (K in %.1f~%.1f)"
|
||||
@@ -6212,7 +6209,7 @@ msgstr "Volume:"
|
||||
msgid "Size:"
|
||||
msgstr "Dimensione:"
|
||||
|
||||
#, boost-format
|
||||
#, c-format, boost-format
|
||||
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
|
||||
msgstr "Sono stati trovati conflitti di percorsi nel G-code sullo strato %d, Z = %.2lfmm. Si prega di separare gli oggetti in conflitto (%s <-> %s)."
|
||||
|
||||
@@ -7089,22 +7086,6 @@ msgstr "Il file .gcode.3mf non contiene dati G-code. Elaboralo con OrcaSlicer ed
|
||||
msgid "File '%s' was lost! Please download it again."
|
||||
msgstr "Il file '%s' è stato perso! Si prega di scaricarlo di nuovo."
|
||||
|
||||
msgid "gcodes"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to delete the file from printer."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Do you want to print the file '%s' from printer?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Print file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to start the print job."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid ""
|
||||
"File: %s\n"
|
||||
@@ -10314,6 +10295,18 @@ msgstr "Mostra i profili non supportati"
|
||||
msgid "Show incompatible/unsupported presets in the printer and filament dropdown lists. These presets cannot be selected."
|
||||
msgstr "Mostra i profili incompatibili/non supportati negli elenchi a discesa di stampante e filamento. Questi profili non possono essere selezionati."
|
||||
|
||||
# AI Translated
|
||||
msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
msgstr "(Sperimentale) Usa gli agenti stampante invece degli host di stampa"
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"Instrada i lavori di stampa delle stampanti non Bambu attraverso gli agenti plugin della stampante invece del classico flusso di caricamento sull'host di stampa.\n"
|
||||
"Quando è disattivato, OrcaSlicer usa il comportamento legacy dell'host di stampa."
|
||||
|
||||
# AI Translated
|
||||
msgid "Experimental Features"
|
||||
msgstr "Funzionalità sperimentali"
|
||||
@@ -10330,17 +10323,6 @@ msgstr ""
|
||||
"Tenta di mantenere le zone dipinte (colore/cucitura/supporto/ruvida ecc.) dopo la modifica della mesh dell'oggetto (come taglio/ricarica dal disco/semplifica/correggi ecc.)\n"
|
||||
"Altamente sperimentale! Lento e può creare artefatti."
|
||||
|
||||
msgid "Use printer agents instead of print hosts"
|
||||
msgstr ""
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"Instrada i lavori di stampa delle stampanti non Bambu attraverso gli agenti plugin della stampante invece del classico flusso di caricamento sull'host di stampa.\n"
|
||||
"Quando è disattivato, OrcaSlicer usa il comportamento legacy dell'host di stampa."
|
||||
|
||||
msgid "Allow Abnormal Storage"
|
||||
msgstr "Consenti memoria anomala"
|
||||
|
||||
@@ -11154,12 +11136,6 @@ msgstr "Annulla timelapse e stampa"
|
||||
msgid "Clean Up"
|
||||
msgstr "Pulisci"
|
||||
|
||||
msgid "AMS filament mapping is not available for this printer. Clear the AMS mapping before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "A filament used by this print has no AMS mapping. Assign it before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "Preparing print job"
|
||||
msgstr "Preparazione della stampa"
|
||||
|
||||
@@ -16398,12 +16374,6 @@ msgstr "Riempimento simmetrico asse Y"
|
||||
msgid "If the model has two parts that are symmetric about the Y axis, and you want these parts to have symmetric textures, please click this option on one of the parts."
|
||||
msgstr "Se il modello ha due parti simmetriche rispetto all'asse Y e si desidera che queste parti abbiano texture simmetriche, fare clic su questa opzione su una delle parti."
|
||||
|
||||
msgid "Fill pattern tops"
|
||||
msgstr ""
|
||||
|
||||
msgid "Choose this option if you want to completely fill in the tops of the infill pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Infill combination - Max layer height"
|
||||
msgstr "Combinazione riempimento - Altezza massima strato"
|
||||
|
||||
@@ -30274,9 +30244,6 @@ msgstr "Abilita strumenti per sviluppatori"
|
||||
msgid "An error occurred loading %s"
|
||||
msgstr "Si è verificato un errore durante il caricamento di %s"
|
||||
|
||||
msgid "/"
|
||||
msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, boost-format
|
||||
msgid "Load %1% to %2%"
|
||||
@@ -31980,6 +31947,9 @@ msgstr ""
|
||||
#~ msgid "An error occurred loading "
|
||||
#~ msgstr "Si è verificato un errore durante il caricamento di "
|
||||
|
||||
#~ msgid "/"
|
||||
#~ msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, c-format, boost-format
|
||||
#~ msgid "Load %s to "
|
||||
@@ -32185,10 +32155,6 @@ msgstr ""
|
||||
#~ msgid "Support/Color Painting: adjust section position"
|
||||
#~ msgstr "Supporto/Pittura a colori: regola la posizione della sezione"
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
#~ msgstr "(Sperimentale) Usa gli agenti stampante invece degli host di stampa"
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "Tab"
|
||||
#~ msgstr "Tab"
|
||||
|
||||
@@ -3,7 +3,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Orca Slicer\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-10-06 13:42+0800\n"
|
||||
"POT-Creation-Date: 2026-10-05 10:49-0300\n"
|
||||
"PO-Revision-Date: \n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
@@ -4352,9 +4352,6 @@ msgstr "フィラメント情報をクリアしてもよろしいですか?"
|
||||
msgid "You need to select the material type and color first."
|
||||
msgstr "まず材料タイプと色を選択してください。"
|
||||
|
||||
msgid "The minimum temperature cannot be greater than the maximum temperature."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Please input a valid value (K in %.1f~%.1f)"
|
||||
msgstr "有効な値を入力してください(Kは%.1f~%.1f)"
|
||||
@@ -6236,7 +6233,7 @@ msgstr "ボリューム"
|
||||
msgid "Size:"
|
||||
msgstr "サイズ:"
|
||||
|
||||
#, boost-format
|
||||
#, c-format, boost-format
|
||||
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
|
||||
msgstr "レイヤー%d、Z = %.2lfmmでG-codeパスの衝突が検出されました。衝突するオブジェクトをもっと離してください(%s <-> %s)。"
|
||||
|
||||
@@ -7105,22 +7102,6 @@ msgstr ".gcode.3mfファイルにG-codeデータが含まれていません。Or
|
||||
msgid "File '%s' was lost! Please download it again."
|
||||
msgstr "ファイル %s が見つかりませんでした、もう一度ダウンロードしてください。"
|
||||
|
||||
msgid "gcodes"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to delete the file from printer."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Do you want to print the file '%s' from printer?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Print file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to start the print job."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid ""
|
||||
"File: %s\n"
|
||||
@@ -10348,6 +10329,18 @@ msgstr "非対応のプリセットを表示"
|
||||
msgid "Show incompatible/unsupported presets in the printer and filament dropdown lists. These presets cannot be selected."
|
||||
msgstr "プリンターとフィラメントのドロップダウンリストに、互換性のない/非対応のプリセットを表示します。これらのプリセットは選択できません。"
|
||||
|
||||
# AI Translated
|
||||
msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
msgstr "(実験的) プリントホストの代わりにプリンターエージェントを使用"
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"Bambu 以外のプリンターの印刷ジョブを、従来のプリントホストへのアップロードではなく、プリンターのプラグインエージェント経由で送信します。\n"
|
||||
"無効の場合、OrcaSlicer は従来のプリントホストの動作を使用します。"
|
||||
|
||||
# AI Translated
|
||||
msgid "Experimental Features"
|
||||
msgstr "実験的機能"
|
||||
@@ -10364,17 +10357,6 @@ msgstr ""
|
||||
"オブジェクトのメッシュを変更した後 (カット/ディスクから再読み込み/簡略化/修正など) も、ペイントした情報 (カラー/継ぎ目/サポート/ファジーなど) の保持を試みます。\n"
|
||||
"非常に実験的な機能です。処理が遅く、アーティファクトが発生する場合があります。"
|
||||
|
||||
msgid "Use printer agents instead of print hosts"
|
||||
msgstr ""
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"Bambu 以外のプリンターの印刷ジョブを、従来のプリントホストへのアップロードではなく、プリンターのプラグインエージェント経由で送信します。\n"
|
||||
"無効の場合、OrcaSlicer は従来のプリントホストの動作を使用します。"
|
||||
|
||||
msgid "Allow Abnormal Storage"
|
||||
msgstr "異常なストレージを許可"
|
||||
|
||||
@@ -11187,12 +11169,6 @@ msgstr "タイムラプスを中止して印刷"
|
||||
msgid "Clean Up"
|
||||
msgstr "整理する"
|
||||
|
||||
msgid "AMS filament mapping is not available for this printer. Clear the AMS mapping before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "A filament used by this print has no AMS mapping. Assign it before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "Preparing print job"
|
||||
msgstr "造形タスクを準備"
|
||||
|
||||
@@ -16604,12 +16580,6 @@ msgstr "Y軸対称インフィル"
|
||||
msgid "If the model has two parts that are symmetric about the Y axis, and you want these parts to have symmetric textures, please click this option on one of the parts."
|
||||
msgstr "モデルにY軸に対して対称な2つのパーツがあり、それらのテクスチャを対称にしたい場合は、一方のパーツでこのオプションをクリックしてください。"
|
||||
|
||||
msgid "Fill pattern tops"
|
||||
msgstr ""
|
||||
|
||||
msgid "Choose this option if you want to completely fill in the tops of the infill pattern"
|
||||
msgstr ""
|
||||
|
||||
# AI Translated
|
||||
msgid "Infill combination - Max layer height"
|
||||
msgstr "インフィル結合 - 最大積層ピッチ"
|
||||
@@ -30796,9 +30766,6 @@ msgstr "開発者ツールを有効化"
|
||||
msgid "An error occurred loading %s"
|
||||
msgstr "%s の読み込み中にエラーが発生しました"
|
||||
|
||||
msgid "/"
|
||||
msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, boost-format
|
||||
msgid "Load %1% to %2%"
|
||||
@@ -32539,6 +32506,9 @@ msgstr ""
|
||||
#~ msgid "An error occurred loading "
|
||||
#~ msgstr "読み込み中にエラーが発生しました: "
|
||||
|
||||
#~ msgid "/"
|
||||
#~ msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, c-format, boost-format
|
||||
#~ msgid "Load %s to "
|
||||
@@ -32745,10 +32715,6 @@ msgstr ""
|
||||
#~ msgid "Support/Color Painting: adjust section position"
|
||||
#~ msgstr "サポート/色塗り: 断面の位置"
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
#~ msgstr "(実験的) プリントホストの代わりにプリンターエージェントを使用"
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "Tab"
|
||||
#~ msgstr "Tab"
|
||||
|
||||
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Orca Slicer\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-10-06 13:42+0800\n"
|
||||
"POT-Creation-Date: 2026-10-05 10:49-0300\n"
|
||||
"PO-Revision-Date: 2025-06-02 17:12+0900\n"
|
||||
"Last-Translator: crwusiz <crwusiz@gmail.com>\n"
|
||||
"Language-Team: \n"
|
||||
@@ -4377,9 +4377,6 @@ msgstr "정말 필라멘트 정보를 삭제하시겠습니까?"
|
||||
msgid "You need to select the material type and color first."
|
||||
msgstr "재료 유형과 색상을 먼저 선택해야 합니다."
|
||||
|
||||
msgid "The minimum temperature cannot be greater than the maximum temperature."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Please input a valid value (K in %.1f~%.1f)"
|
||||
msgstr "유효한 값을 입력하세요 (%.1f~%.1f 사이의 K)"
|
||||
@@ -6269,7 +6266,7 @@ msgid "Size:"
|
||||
msgstr "크기:"
|
||||
|
||||
# AI Translated
|
||||
#, boost-format
|
||||
#, c-format, boost-format
|
||||
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
|
||||
msgstr "레이어 %d, Z = %.2lf mm에서 G-code 경로 충돌이 발견되었습니다. 충돌하는 객체를 더 멀리 분리하세요 (%s <-> %s)."
|
||||
|
||||
@@ -7149,22 +7146,6 @@ msgstr ".gcode.3mf 파일에는 G-code 데이터가 없습니다. OrcaSlicer에
|
||||
msgid "File '%s' was lost! Please download it again."
|
||||
msgstr "'%s' 파일이 손실되었습니다! 다시 다운로드하세요."
|
||||
|
||||
msgid "gcodes"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to delete the file from printer."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Do you want to print the file '%s' from printer?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Print file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to start the print job."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid ""
|
||||
"File: %s\n"
|
||||
@@ -10481,6 +10462,18 @@ msgstr "지원되지 않는 사전 설정 표시"
|
||||
msgid "Show incompatible/unsupported presets in the printer and filament dropdown lists. These presets cannot be selected."
|
||||
msgstr "프린터 및 필라멘트 드롭다운 목록에 호환되지 않거나 지원되지 않는 사전 설정을 표시합니다. 이러한 사전 설정은 선택할 수 없습니다."
|
||||
|
||||
# AI Translated
|
||||
msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
msgstr "(실험적) 출력 호스트 대신 프린터 에이전트 사용"
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"Bambu 이외의 프린터 출력 작업을 기존 출력 호스트 업로드 방식 대신 프린터 플러그인 에이전트를 통해 전달합니다.\n"
|
||||
"비활성화하면 OrcaSlicer는 기존 출력 호스트 동작을 사용합니다."
|
||||
|
||||
# AI Translated
|
||||
msgid "Experimental Features"
|
||||
msgstr "실험적 기능"
|
||||
@@ -10497,17 +10490,6 @@ msgstr ""
|
||||
"객체 메시를 변경한 후(자르기/디스크에서 다시 불러오기/단순화/수정 등)에도 칠한 기능(색상/재봉선/서포트/퍼지 등)을 유지하려고 시도합니다.\n"
|
||||
"매우 실험적인 기능입니다! 속도가 느리고 아티팩트가 생길 수 있습니다."
|
||||
|
||||
msgid "Use printer agents instead of print hosts"
|
||||
msgstr ""
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"Bambu 이외의 프린터 출력 작업을 기존 출력 호스트 업로드 방식 대신 프린터 플러그인 에이전트를 통해 전달합니다.\n"
|
||||
"비활성화하면 OrcaSlicer는 기존 출력 호스트 동작을 사용합니다."
|
||||
|
||||
# AI Translated
|
||||
msgid "Allow Abnormal Storage"
|
||||
msgstr "비정상 저장 장치 허용"
|
||||
@@ -11328,12 +11310,6 @@ msgstr "타임랩스 취소 후 출력"
|
||||
msgid "Clean Up"
|
||||
msgstr "정리"
|
||||
|
||||
msgid "AMS filament mapping is not available for this printer. Clear the AMS mapping before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "A filament used by this print has no AMS mapping. Assign it before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "Preparing print job"
|
||||
msgstr "출력 작업 준비 중"
|
||||
|
||||
@@ -16762,12 +16738,6 @@ msgstr "Y축 대칭 채우기"
|
||||
msgid "If the model has two parts that are symmetric about the Y axis, and you want these parts to have symmetric textures, please click this option on one of the parts."
|
||||
msgstr "모델에 Y축을 기준으로 대칭인 두 부품이 있고 이 부품들이 대칭 질감을 갖게 하려면, 두 부품 중 하나에서 이 옵션을 선택하십시오."
|
||||
|
||||
msgid "Fill pattern tops"
|
||||
msgstr ""
|
||||
|
||||
msgid "Choose this option if you want to completely fill in the tops of the infill pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Infill combination - Max layer height"
|
||||
msgstr "채우기 조합 - 최대 레이어 높이"
|
||||
|
||||
@@ -30813,9 +30783,6 @@ msgstr "개발자 도구 사용"
|
||||
msgid "An error occurred loading %s"
|
||||
msgstr "%s 로드 중 오류가 발생했습니다"
|
||||
|
||||
msgid "/"
|
||||
msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, boost-format
|
||||
msgid "Load %1% to %2%"
|
||||
@@ -32528,6 +32495,9 @@ msgstr ""
|
||||
#~ msgid "An error occurred loading "
|
||||
#~ msgstr "로드 중 오류가 발생했습니다: "
|
||||
|
||||
#~ msgid "/"
|
||||
#~ msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, c-format, boost-format
|
||||
#~ msgid "Load %s to "
|
||||
@@ -32734,10 +32704,6 @@ msgstr ""
|
||||
#~ msgid "Support/Color Painting: adjust section position"
|
||||
#~ msgstr "서포트/색상 칠하기: 단면 위치 조정"
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
#~ msgstr "(실험적) 출력 호스트 대신 프린터 에이전트 사용"
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "Tab"
|
||||
#~ msgstr "탭"
|
||||
|
||||
@@ -147,7 +147,6 @@ src/slic3r/GUI/HMSPanel.cpp
|
||||
src/slic3r/GUI/MainFrame.cpp
|
||||
src/slic3r/GUI/MediaPlayCtrl.cpp
|
||||
src/slic3r/GUI/MediaFilePanel.cpp
|
||||
src/slic3r/GUI/OrcaFilesPanel.cpp
|
||||
src/slic3r/GUI/ImageGrid.cpp
|
||||
src/slic3r/GUI/Widgets/ImageSwitchButton.cpp
|
||||
src/slic3r/GUI/Printer/PrinterFileSystem.cpp
|
||||
|
||||
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-10-06 13:42+0800\n"
|
||||
"POT-Creation-Date: 2026-10-05 10:49-0300\n"
|
||||
"PO-Revision-Date: 2026-07-02 14:13+0300\n"
|
||||
"Last-Translator: Gintaras Kučinskas <sharanchius@gmail.com>\n"
|
||||
"Language-Team: \n"
|
||||
@@ -4343,9 +4343,6 @@ msgstr "Ar jūs tikrai norite išvalyti gijos informaciją?"
|
||||
msgid "You need to select the material type and color first."
|
||||
msgstr "Pradžioje jums reikia pasirinkti medžiagos tipą ir spalvą."
|
||||
|
||||
msgid "The minimum temperature cannot be greater than the maximum temperature."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Please input a valid value (K in %.1f~%.1f)"
|
||||
msgstr "Įveskite tinkamą reikšmę (K %.1f~%.1f)"
|
||||
@@ -6225,7 +6222,7 @@ msgid "Size:"
|
||||
msgstr "Dydis:"
|
||||
|
||||
# AI Translated
|
||||
#, boost-format
|
||||
#, c-format, boost-format
|
||||
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
|
||||
msgstr "Rasta G-code trajektorijų konfliktų %d sluoksnyje, Z = %.2lfmm. Prašome labiau atskirti konfliktuojančius objektus (%s <-> %s)."
|
||||
|
||||
@@ -7110,22 +7107,6 @@ msgstr "Failas „.gcode.3mf“ neturi G-code duomenų. Supjaustykite jį su „
|
||||
msgid "File '%s' was lost! Please download it again."
|
||||
msgstr "Failas „%s“ nerastas! Atsisiųskite jį iš naujo."
|
||||
|
||||
msgid "gcodes"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to delete the file from printer."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Do you want to print the file '%s' from printer?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Print file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to start the print job."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid ""
|
||||
"File: %s\n"
|
||||
@@ -10316,6 +10297,18 @@ msgstr "Rodyti nepalaikomus profilius"
|
||||
msgid "Show incompatible/unsupported presets in the printer and filament dropdown lists. These presets cannot be selected."
|
||||
msgstr "Rodyti nesuderinamus / nepalaikomus profilius spausdintuvų ir gijų išskleidžiamuosiuose sąrašuose. Šių profilių pasirinkti negalima."
|
||||
|
||||
# AI Translated
|
||||
msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
msgstr "(Eksperimentinė) Naudoti spausdintuvo agentus vietoj spausdinimo serverių"
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"Nukreipia ne Bambu spausdintuvų spausdinimo užduotis per spausdintuvo papildinių agentus, o ne per klasikinį įkėlimo į spausdinimo serverį srautą.\n"
|
||||
"Kai išjungta, OrcaSlicer naudoja senąjį spausdinimo serverio veikimą."
|
||||
|
||||
msgid "Experimental Features"
|
||||
msgstr "Eksperimentinis"
|
||||
|
||||
@@ -10329,17 +10322,6 @@ msgstr ""
|
||||
"Bando išsaugoti nudažytas ypatybes (spalvą, siūlę, atramas, šiauštą paviršių ir kt.) pakeitus objekto tinklelio modelį (pvz., po pjovimo, įkėlimo iš naujo, supaprastinimo, taisymo ir kt.)\n"
|
||||
"Labai eksperimentinė funkcija! Veikia lėtai ir gali sukurti artefaktų."
|
||||
|
||||
msgid "Use printer agents instead of print hosts"
|
||||
msgstr ""
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"Nukreipia ne Bambu spausdintuvų spausdinimo užduotis per spausdintuvo papildinių agentus, o ne per klasikinį įkėlimo į spausdinimo serverį srautą.\n"
|
||||
"Kai išjungta, OrcaSlicer naudoja senąjį spausdinimo serverio veikimą."
|
||||
|
||||
msgid "Allow Abnormal Storage"
|
||||
msgstr "Leisti sutrikusią (neįprastą) laikmeną"
|
||||
|
||||
@@ -11150,12 +11132,6 @@ msgstr "Atšaukti intervalinį fotografavimą ir spausdinti"
|
||||
msgid "Clean Up"
|
||||
msgstr "Išvalyti"
|
||||
|
||||
msgid "AMS filament mapping is not available for this printer. Clear the AMS mapping before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "A filament used by this print has no AMS mapping. Assign it before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "Preparing print job"
|
||||
msgstr "Spausdinimo užduoties rengimas"
|
||||
|
||||
@@ -16386,12 +16362,6 @@ msgstr "Simetriškas užpildas pagal Y ašį"
|
||||
msgid "If the model has two parts that are symmetric about the Y axis, and you want these parts to have symmetric textures, please click this option on one of the parts."
|
||||
msgstr "Jei modelis turi dvi dalis, kurios yra simetriškos Y ašies atžvilgiu, ir norite, kad šios dalys turėtų simetriškas tekstūras, spustelėkite šią parinktį vienoje iš dalių."
|
||||
|
||||
msgid "Fill pattern tops"
|
||||
msgstr ""
|
||||
|
||||
msgid "Choose this option if you want to completely fill in the tops of the infill pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Infill combination - Max layer height"
|
||||
msgstr "Užpildo derinimas – maksimalus sluoksnio aukštis"
|
||||
|
||||
@@ -30146,10 +30116,6 @@ msgstr "Įjungti kūrėjo įrankius"
|
||||
msgid "An error occurred loading %s"
|
||||
msgstr "Įvyko klaida įkeliant %s"
|
||||
|
||||
# AI Translated
|
||||
msgid "/"
|
||||
msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, boost-format
|
||||
msgid "Load %1% to %2%"
|
||||
@@ -30830,10 +30796,6 @@ msgstr ""
|
||||
"Venkite deformacijų (warping)\n"
|
||||
"Ar žinojote, kad spausdinant medžiagas, kurios yra linkusios trauktis ir riestis (pvz., ABS), tinkamas kaitinamojo pagrindo temperatūros padidinimas gali sumažinti deformacijų (warping) tikimybę?"
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
#~ msgstr "(Eksperimentinė) Naudoti spausdintuvo agentus vietoj spausdinimo serverių"
|
||||
|
||||
#~ msgid "X"
|
||||
#~ msgstr "X"
|
||||
|
||||
@@ -31862,6 +31824,10 @@ msgstr ""
|
||||
#~ msgid "An error occurred loading "
|
||||
#~ msgstr "Įvyko klaida įkeliant "
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "/"
|
||||
#~ msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, c-format, boost-format
|
||||
#~ msgid "Load %s to "
|
||||
|
||||
@@ -3,7 +3,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Orca Slicer\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-10-06 13:42+0800\n"
|
||||
"POT-Creation-Date: 2026-10-05 10:49-0300\n"
|
||||
"PO-Revision-Date: \n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
@@ -4719,9 +4719,6 @@ msgstr "Weet u zeker dat u de filamentinformatie wilt wissen?"
|
||||
msgid "You need to select the material type and color first."
|
||||
msgstr "U moet eerst het materiaaltype en de kleur selecteren."
|
||||
|
||||
msgid "The minimum temperature cannot be greater than the maximum temperature."
|
||||
msgstr ""
|
||||
|
||||
# AI Translated
|
||||
#, c-format, boost-format
|
||||
msgid "Please input a valid value (K in %.1f~%.1f)"
|
||||
@@ -6749,7 +6746,7 @@ msgid "Size:"
|
||||
msgstr "Maat:"
|
||||
|
||||
# AI Translated
|
||||
#, boost-format
|
||||
#, c-format, boost-format
|
||||
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
|
||||
msgstr "Er zijn conflicten tussen G-code-paden gevonden op laag %d, Z = %.2lfmm. Plaats de conflicterende objecten verder uit elkaar (%s <-> %s)."
|
||||
|
||||
@@ -7689,22 +7686,6 @@ msgstr "Het .gcode.3mf-bestand bevat geen G-code-gegevens. Slice het met Orca Sl
|
||||
msgid "File '%s' was lost! Please download it again."
|
||||
msgstr "Bestand '%s' is verloren gegaan! Download het opnieuw."
|
||||
|
||||
msgid "gcodes"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to delete the file from printer."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Do you want to print the file '%s' from printer?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Print file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to start the print job."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid ""
|
||||
"File: %s\n"
|
||||
@@ -11173,6 +11154,18 @@ msgstr "Niet-ondersteunde voorinstellingen tonen"
|
||||
msgid "Show incompatible/unsupported presets in the printer and filament dropdown lists. These presets cannot be selected."
|
||||
msgstr "Toon incompatibele/niet-ondersteunde voorinstellingen in de keuzelijsten voor printer en filament. Deze voorinstellingen kunnen niet worden geselecteerd."
|
||||
|
||||
# AI Translated
|
||||
msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
msgstr "(Experimenteel) Printeragents gebruiken in plaats van printhosts"
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"Stuurt printtaken voor niet-Bambu-printers via printer-plug-inagents in plaats van via de klassieke uploadstroom naar de printhost.\n"
|
||||
"Wanneer dit is uitgeschakeld, gebruikt OrcaSlicer het oude printhostgedrag."
|
||||
|
||||
# AI Translated
|
||||
msgid "Experimental Features"
|
||||
msgstr "Experimentele functies"
|
||||
@@ -11189,17 +11182,6 @@ msgstr ""
|
||||
"Probeer geschilderde kenmerken (kleur/naad/ondersteuning/vaag enz.) te behouden na het wijzigen van de mesh van het object (zoals snijden/opnieuw laden vanaf schijf/vereenvoudigen/repareren enz.)\n"
|
||||
"Zeer experimenteel! Traag en kan artefacten veroorzaken."
|
||||
|
||||
msgid "Use printer agents instead of print hosts"
|
||||
msgstr ""
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"Stuurt printtaken voor niet-Bambu-printers via printer-plug-inagents in plaats van via de klassieke uploadstroom naar de printhost.\n"
|
||||
"Wanneer dit is uitgeschakeld, gebruikt OrcaSlicer het oude printhostgedrag."
|
||||
|
||||
# AI Translated
|
||||
msgid "Allow Abnormal Storage"
|
||||
msgstr "Afwijkend opslagmedium toestaan"
|
||||
@@ -12044,12 +12026,6 @@ msgstr "Timelapse annuleren en printen"
|
||||
msgid "Clean Up"
|
||||
msgstr "Opruimen"
|
||||
|
||||
msgid "AMS filament mapping is not available for this printer. Clear the AMS mapping before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "A filament used by this print has no AMS mapping. Assign it before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "Preparing print job"
|
||||
msgstr "Print opdracht voorbereiden"
|
||||
|
||||
@@ -17796,12 +17772,6 @@ msgstr "Symmetrische vulling om de Y-as"
|
||||
msgid "If the model has two parts that are symmetric about the Y axis, and you want these parts to have symmetric textures, please click this option on one of the parts."
|
||||
msgstr "Als het model twee delen heeft die symmetrisch zijn ten opzichte van de Y-as en u wilt dat deze delen symmetrische texturen hebben, klik dan op deze optie bij een van de delen."
|
||||
|
||||
msgid "Fill pattern tops"
|
||||
msgstr ""
|
||||
|
||||
msgid "Choose this option if you want to completely fill in the tops of the infill pattern"
|
||||
msgstr ""
|
||||
|
||||
# AI Translated
|
||||
msgid "Infill combination - Max layer height"
|
||||
msgstr "Vullingcombinatie - Maximale laaghoogte"
|
||||
@@ -32344,9 +32314,6 @@ msgstr "Ontwikkelaarstools inschakelen"
|
||||
msgid "An error occurred loading %s"
|
||||
msgstr "Er is een fout opgetreden bij het laden van %s"
|
||||
|
||||
msgid "/"
|
||||
msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, boost-format
|
||||
msgid "Load %1% to %2%"
|
||||
@@ -34113,6 +34080,9 @@ msgstr ""
|
||||
#~ msgid "An error occurred loading "
|
||||
#~ msgstr "Er is een fout opgetreden bij het laden van "
|
||||
|
||||
#~ msgid "/"
|
||||
#~ msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, c-format, boost-format
|
||||
#~ msgid "Load %s to "
|
||||
@@ -34322,10 +34292,6 @@ msgstr ""
|
||||
#~ msgid "Support/Color Painting: adjust section position"
|
||||
#~ msgstr "Support/kleur intekenen: pas de sectie positie aan"
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
#~ msgstr "(Experimenteel) Printeragents gebruiken in plaats van printhosts"
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "Tab"
|
||||
#~ msgstr "Tab"
|
||||
|
||||
@@ -3,7 +3,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: OrcaSlicer 2.3.0-rc\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-10-06 13:42+0800\n"
|
||||
"POT-Creation-Date: 2026-10-05 10:49-0300\n"
|
||||
"PO-Revision-Date: \n"
|
||||
"Last-Translator: Krzysztof Morga <<tlumaczeniebs@gmail.com>>\n"
|
||||
"Language-Team: \n"
|
||||
@@ -4438,9 +4438,6 @@ msgstr "Czy na pewno usunąć informacje o filamentach?"
|
||||
msgid "You need to select the material type and color first."
|
||||
msgstr "Najpierw należy wybrać rodzaj i kolor filamentu."
|
||||
|
||||
msgid "The minimum temperature cannot be greater than the maximum temperature."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Please input a valid value (K in %.1f~%.1f)"
|
||||
msgstr "Proszę podać prawidłową wartość (K w zakresie %.1f~%.1f)"
|
||||
@@ -6344,7 +6341,7 @@ msgstr "Objętość:"
|
||||
msgid "Size:"
|
||||
msgstr "Rozmiar:"
|
||||
|
||||
#, boost-format
|
||||
#, c-format, boost-format
|
||||
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
|
||||
msgstr "Wykryto konflikty ścieżek G-code na warstwie %d, Z = %.2lfmm. Proszę oddalić od siebie obiekty będące w konflikcie (%s <-> %s)."
|
||||
|
||||
@@ -7241,22 +7238,6 @@ msgstr "Plik .gcode.3mf nie zawiera danych G-code. Proszę poddać go obróbce w
|
||||
msgid "File '%s' was lost! Please download it again."
|
||||
msgstr "Plik „%s” został utracony! Proszę pobrać go ponownie."
|
||||
|
||||
msgid "gcodes"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to delete the file from printer."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Do you want to print the file '%s' from printer?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Print file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to start the print job."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid ""
|
||||
"File: %s\n"
|
||||
@@ -10579,6 +10560,18 @@ msgstr "Pokaż nieobsługiwane profile"
|
||||
msgid "Show incompatible/unsupported presets in the printer and filament dropdown lists. These presets cannot be selected."
|
||||
msgstr "Pokazuj niekompatybilne/nieobsługiwane profile na listach rozwijanych drukarek i filamentów. Tych profili nie można wybrać."
|
||||
|
||||
# AI Translated
|
||||
msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
msgstr "(Eksperymentalne) Używaj agentów drukarki zamiast serwerów druku"
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"Kieruje zadania druku dla drukarek innych niż Bambu przez agentów wtyczek drukarki zamiast klasycznego przesyłania do serwera druku.\n"
|
||||
"Gdy opcja jest wyłączona, OrcaSlicer korzysta z dotychczasowego działania serwera druku."
|
||||
|
||||
# AI Translated
|
||||
msgid "Experimental Features"
|
||||
msgstr "Funkcje eksperymentalne"
|
||||
@@ -10595,17 +10588,6 @@ msgstr ""
|
||||
"Próbuje zachować malowane cechy (kolor/szew/podpory/skórę fuzzy itp.) po zmianie siatki obiektu (np. cięcie/wczytanie ponownie z dysku/uproszczenie/naprawa itp.)\n"
|
||||
"Wysoce eksperymentalne! Powolne i może tworzyć artefakty."
|
||||
|
||||
msgid "Use printer agents instead of print hosts"
|
||||
msgstr ""
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"Kieruje zadania druku dla drukarek innych niż Bambu przez agentów wtyczek drukarki zamiast klasycznego przesyłania do serwera druku.\n"
|
||||
"Gdy opcja jest wyłączona, OrcaSlicer korzysta z dotychczasowego działania serwera druku."
|
||||
|
||||
# AI Translated
|
||||
msgid "Allow Abnormal Storage"
|
||||
msgstr "Zezwalaj na nieprawidłową pamięć"
|
||||
@@ -11429,12 +11411,6 @@ msgstr "Anuluj timelapse i drukuj"
|
||||
msgid "Clean Up"
|
||||
msgstr "Wyczyść"
|
||||
|
||||
msgid "AMS filament mapping is not available for this printer. Clear the AMS mapping before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "A filament used by this print has no AMS mapping. Assign it before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "Preparing print job"
|
||||
msgstr "Przygotowywanie zadania do druku"
|
||||
|
||||
@@ -16823,12 +16799,6 @@ msgstr "Symetryczne wypełnienie względem osi Y"
|
||||
msgid "If the model has two parts that are symmetric about the Y axis, and you want these parts to have symmetric textures, please click this option on one of the parts."
|
||||
msgstr "Jeśli model ma dwie części symetryczne względem osi Y i chcesz, aby miały symetryczne tekstury, zaznacz tę opcję dla jednej z części."
|
||||
|
||||
msgid "Fill pattern tops"
|
||||
msgstr ""
|
||||
|
||||
msgid "Choose this option if you want to completely fill in the tops of the infill pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Infill combination - Max layer height"
|
||||
msgstr "Kombinacja wypełnienia - Maks. wysokość warstwy"
|
||||
|
||||
@@ -30798,9 +30768,6 @@ msgstr "Włącz narzędzia deweloperskie"
|
||||
msgid "An error occurred loading %s"
|
||||
msgstr "Wystąpił błąd podczas ładowania %s"
|
||||
|
||||
msgid "/"
|
||||
msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, boost-format
|
||||
msgid "Load %1% to %2%"
|
||||
@@ -31480,10 +31447,6 @@ msgstr ""
|
||||
"Unikaj odkształceń\n"
|
||||
"Czy wiesz, że podczas drukowania filamentami podatnymi na odkształcenia, takimi jak ABS, odpowiednie zwiększenie temperatury podgrzewanej płyty może zmniejszyć prawdopodobieństwo odkształceń?"
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
#~ msgstr "(Eksperymentalne) Używaj agentów drukarki zamiast serwerów druku"
|
||||
|
||||
#~ msgid "X"
|
||||
#~ msgstr "X"
|
||||
|
||||
@@ -32482,6 +32445,9 @@ msgstr ""
|
||||
#~ msgid "An error occurred loading "
|
||||
#~ msgstr "Wystąpił błąd podczas ładowania"
|
||||
|
||||
#~ msgid "/"
|
||||
#~ msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, c-format, boost-format
|
||||
#~ msgid "Load %s to "
|
||||
|
||||
@@ -3,7 +3,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Orca Slicer\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-10-06 13:42+0800\n"
|
||||
"POT-Creation-Date: 2026-10-05 10:49-0300\n"
|
||||
"PO-Revision-Date: 2026-07-26 11:14-0300\n"
|
||||
"Last-Translator: Alexandre Folle de Menezes\n"
|
||||
"Language-Team: Portuguese, Brazilian\n"
|
||||
@@ -4184,9 +4184,6 @@ msgstr "Tem certeza de que deseja limpar as informações do filamento?"
|
||||
msgid "You need to select the material type and color first."
|
||||
msgstr "Você precisa selecionar o tipo e a cor do material primeiro."
|
||||
|
||||
msgid "The minimum temperature cannot be greater than the maximum temperature."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Please input a valid value (K in %.1f~%.1f)"
|
||||
msgstr "Por favor insira um valor válido (K entre %.1f~%.1f)"
|
||||
@@ -6018,7 +6015,7 @@ msgstr "Volume:"
|
||||
msgid "Size:"
|
||||
msgstr "Tamanho:"
|
||||
|
||||
#, boost-format
|
||||
#, c-format, boost-format
|
||||
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
|
||||
msgstr "Foram encontrados conflitos de caminhos de G-code na camada %d, Z = %.2lfmm. Por favor, separe mais os objetos em conflito (%s <-> %s)."
|
||||
|
||||
@@ -6881,22 +6878,6 @@ msgstr "O arquivo .gcode.3mf não contém dados de G-code. Por favor, fatie com
|
||||
msgid "File '%s' was lost! Please download it again."
|
||||
msgstr "O arquivo '%s' foi perdido! Por favor, baixe-o novamente."
|
||||
|
||||
msgid "gcodes"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to delete the file from printer."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Do you want to print the file '%s' from printer?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Print file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to start the print job."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid ""
|
||||
"File: %s\n"
|
||||
@@ -9959,6 +9940,16 @@ msgstr "Mostrar predefinições não suportadas"
|
||||
msgid "Show incompatible/unsupported presets in the printer and filament dropdown lists. These presets cannot be selected."
|
||||
msgstr "Exibir predefinições incompatíveis e não suportadas nas listas de impressora e filamento. Essas predefinições não podem ser selecionadas."
|
||||
|
||||
msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
msgstr "(Experimental) Usar agentes de impressora em vez de hosts de impressão"
|
||||
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"Encaminha os trabalhos de impressão de impressoras que não são Bambu pelos agentes de plugin de impressora em vez do fluxo clássico de envio ao host de impressão.\n"
|
||||
"Quando desativado, o OrcaSlicer usa o comportamento antigo do host de impressão."
|
||||
|
||||
msgid "Experimental Features"
|
||||
msgstr "Recursos Experimentais"
|
||||
|
||||
@@ -9972,16 +9963,6 @@ msgstr ""
|
||||
"Tenta manter recursos pintados (cor/costura/suporte/textura difusa etc.) após alterar a malha do objeto (como cortar/recarregar do disco/simplificar/corrigir etc.)\n"
|
||||
"Altamente experimental! Lento e pode criar artefatos."
|
||||
|
||||
msgid "Use printer agents instead of print hosts"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"Encaminha os trabalhos de impressão de impressoras que não são Bambu pelos agentes de plugin de impressora em vez do fluxo clássico de envio ao host de impressão.\n"
|
||||
"Quando desativado, o OrcaSlicer usa o comportamento antigo do host de impressão."
|
||||
|
||||
msgid "Allow Abnormal Storage"
|
||||
msgstr "Permitir Armazenamento Anormal"
|
||||
|
||||
@@ -10738,12 +10719,6 @@ msgstr "Cancelar Timelapse e Imprimir"
|
||||
msgid "Clean Up"
|
||||
msgstr "Limpar"
|
||||
|
||||
msgid "AMS filament mapping is not available for this printer. Clear the AMS mapping before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "A filament used by this print has no AMS mapping. Assign it before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "Preparing print job"
|
||||
msgstr "Preparando trabalho de impressão"
|
||||
|
||||
@@ -15819,12 +15794,6 @@ msgstr "Preenchimento simétrico no eixo Y"
|
||||
msgid "If the model has two parts that are symmetric about the Y axis, and you want these parts to have symmetric textures, please click this option on one of the parts."
|
||||
msgstr "Se o modelo tiver duas partes simétricas em relação ao eixo Y e você quiser que essas partes tenham texturas simétricas, clique nesta opção em uma das partes."
|
||||
|
||||
msgid "Fill pattern tops"
|
||||
msgstr ""
|
||||
|
||||
msgid "Choose this option if you want to completely fill in the tops of the infill pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Infill combination - Max layer height"
|
||||
msgstr "Combinação de preenchimento - Altura máx da camada"
|
||||
|
||||
@@ -29370,10 +29339,6 @@ msgstr "Ativar Ferramentas de Desenvolvedor"
|
||||
msgid "An error occurred loading %s"
|
||||
msgstr "Ocorreu um erro ao carregar %s"
|
||||
|
||||
# AI Translated
|
||||
msgid "/"
|
||||
msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, boost-format
|
||||
msgid "Load %1% to %2%"
|
||||
@@ -30053,9 +30018,6 @@ msgstr ""
|
||||
"Evitar empenamento\n"
|
||||
"Você sabia que ao imprimir materiais propensos ao empenamento como ABS, aumentar adequadamente a temperatura da mesa aquecida pode reduzir a probabilidade de empenamento?"
|
||||
|
||||
#~ msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
#~ msgstr "(Experimental) Usar agentes de impressora em vez de hosts de impressão"
|
||||
|
||||
#~ msgid "X"
|
||||
#~ msgstr "X"
|
||||
|
||||
@@ -31077,6 +31039,10 @@ msgstr ""
|
||||
#~ msgid "An error occurred loading "
|
||||
#~ msgstr "Ocorreu um erro ao carregar "
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "/"
|
||||
#~ msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, c-format, boost-format
|
||||
#~ msgid "Load %s to "
|
||||
|
||||
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: OrcaSlicer V2.5.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-10-06 13:42+0800\n"
|
||||
"POT-Creation-Date: 2026-10-05 10:49-0300\n"
|
||||
"PO-Revision-Date: 2026-02-25 13:38+0300\n"
|
||||
"Last-Translator: Felix14_v2\n"
|
||||
"Language-Team: Felix14_v2 (ДС/ТГ: @felix14_v2, почта: aleks111001@list.ru), Andylg <andylg@yandex.ru>\n"
|
||||
@@ -4319,9 +4319,6 @@ msgstr "Вы действительно хотите удалить информ
|
||||
msgid "You need to select the material type and color first."
|
||||
msgstr "Сначала нужно выбрать тип материала и цвет."
|
||||
|
||||
msgid "The minimum temperature cannot be greater than the maximum temperature."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Please input a valid value (K in %.1f~%.1f)"
|
||||
msgstr "Пожалуйста, введите допустимое значение (K в диапазоне %.1f~%.1f)"
|
||||
@@ -6236,7 +6233,7 @@ msgstr "Объём:"
|
||||
msgid "Size:"
|
||||
msgstr "Размер:"
|
||||
|
||||
#, boost-format
|
||||
#, c-format, boost-format
|
||||
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
|
||||
msgstr "В G-code на %d слое (z = %.2lf мм) обнаружен конфликт путей. Пожалуйста, разместите конфликтующие модели дальше друг от друга (%s <-> %s)."
|
||||
|
||||
@@ -7147,22 +7144,6 @@ msgstr "Файл .gcode.3mf не содержит данных G-code. Испо
|
||||
msgid "File '%s' was lost! Please download it again."
|
||||
msgstr "Файл '%s' потерян! Пожалуйста, загрузите его снова."
|
||||
|
||||
msgid "gcodes"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to delete the file from printer."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Do you want to print the file '%s' from printer?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Print file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to start the print job."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid ""
|
||||
"File: %s\n"
|
||||
@@ -10340,6 +10321,18 @@ msgstr ""
|
||||
"\n"
|
||||
"Примечание: профили остаются недоступными для выбора."
|
||||
|
||||
# AI Translated
|
||||
msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
msgstr "(Экспериментально) Использовать агентов принтера вместо хостов печати"
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"Отправлять задания печати для принтеров, отличных от Bambu, через агентов плагинов принтера вместо классической загрузки на хост печати.\n"
|
||||
"Если отключено, OrcaSlicer использует прежнее поведение хоста печати."
|
||||
|
||||
msgid "Experimental Features"
|
||||
msgstr "Экспериментальные настройки"
|
||||
|
||||
@@ -10354,17 +10347,6 @@ msgstr ""
|
||||
"\n"
|
||||
"Внимание: функция экспериментальна! Возможны падение производительности и артефакты работы."
|
||||
|
||||
msgid "Use printer agents instead of print hosts"
|
||||
msgstr ""
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"Отправлять задания печати для принтеров, отличных от Bambu, через агентов плагинов принтера вместо классической загрузки на хост печати.\n"
|
||||
"Если отключено, OrcaSlicer использует прежнее поведение хоста печати."
|
||||
|
||||
msgid "Allow Abnormal Storage"
|
||||
msgstr "Игнорировать неисправность хранилища"
|
||||
|
||||
@@ -11163,12 +11145,6 @@ msgstr "Отключить таймлапс и продолжить"
|
||||
msgid "Clean Up"
|
||||
msgstr "Очистить"
|
||||
|
||||
msgid "AMS filament mapping is not available for this printer. Clear the AMS mapping before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "A filament used by this print has no AMS mapping. Assign it before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "Preparing print job"
|
||||
msgstr "Подготовка задания на печать"
|
||||
|
||||
@@ -16593,12 +16569,6 @@ msgstr "Отразить шаблон"
|
||||
msgid "If the model has two parts that are symmetric about the Y axis, and you want these parts to have symmetric textures, please click this option on one of the parts."
|
||||
msgstr "Если модель состоит из двух симметричных частей, у одной из них можно отразить шаблон заполнения, чтобы модель имела симметричную текстуру поверхности."
|
||||
|
||||
msgid "Fill pattern tops"
|
||||
msgstr ""
|
||||
|
||||
msgid "Choose this option if you want to completely fill in the tops of the infill pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Infill combination - Max layer height"
|
||||
msgstr "Предел высоты объединённого слоя"
|
||||
|
||||
@@ -30637,9 +30607,6 @@ msgstr "Включить инструменты разработчика"
|
||||
msgid "An error occurred loading %s"
|
||||
msgstr "Ошибка при загрузке %s"
|
||||
|
||||
msgid "/"
|
||||
msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, boost-format
|
||||
msgid "Load %1% to %2%"
|
||||
@@ -31317,10 +31284,6 @@ msgstr ""
|
||||
"Предотвращение коробления материала\n"
|
||||
"Знаете ли вы, что при печати материалами, склонными к короблению, таких как ABS, повышение температуры подогреваемого стола может снизить эту вероятность?"
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
#~ msgstr "(Экспериментально) Использовать агентов принтера вместо хостов печати"
|
||||
|
||||
#~ msgid "X"
|
||||
#~ msgstr "X"
|
||||
|
||||
@@ -32355,6 +32318,9 @@ msgstr ""
|
||||
#~ msgid "An error occurred loading "
|
||||
#~ msgstr "Ошибка при загрузке "
|
||||
|
||||
#~ msgid "/"
|
||||
#~ msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, c-format, boost-format
|
||||
#~ msgid "Load %s to "
|
||||
|
||||
@@ -3,7 +3,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Orca Slicer\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-10-06 13:42+0800\n"
|
||||
"POT-Creation-Date: 2026-10-05 10:49-0300\n"
|
||||
"Language: sv\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@@ -4784,9 +4784,6 @@ msgstr "Är du säker på att du vill rensa filament informationen?"
|
||||
msgid "You need to select the material type and color first."
|
||||
msgstr "Du måste först välja materialtyp och färg."
|
||||
|
||||
msgid "The minimum temperature cannot be greater than the maximum temperature."
|
||||
msgstr ""
|
||||
|
||||
# AI Translated
|
||||
#, c-format, boost-format
|
||||
msgid "Please input a valid value (K in %.1f~%.1f)"
|
||||
@@ -6843,7 +6840,7 @@ msgid "Size:"
|
||||
msgstr "Storlek:"
|
||||
|
||||
# AI Translated
|
||||
#, boost-format
|
||||
#, c-format, boost-format
|
||||
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
|
||||
msgstr "Konflikter mellan G-code-banor hittades på lager %d, Z = %.2lfmm. Placera de objekt som krockar längre ifrån varandra (%s <-> %s)."
|
||||
|
||||
@@ -7784,22 +7781,6 @@ msgstr "Filen .gcode.3mf innehåller inga G-code-data. Bered den med Orca Slicer
|
||||
msgid "File '%s' was lost! Please download it again."
|
||||
msgstr "Filen '%s' förlorades! Ladda ner den igen."
|
||||
|
||||
msgid "gcodes"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to delete the file from printer."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Do you want to print the file '%s' from printer?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Print file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to start the print job."
|
||||
msgstr ""
|
||||
|
||||
# AI Translated
|
||||
#, c-format, boost-format
|
||||
msgid ""
|
||||
@@ -11316,6 +11297,18 @@ msgstr "Visa förinställningar som inte stöds"
|
||||
msgid "Show incompatible/unsupported presets in the printer and filament dropdown lists. These presets cannot be selected."
|
||||
msgstr "Visa inkompatibla förinställningar och förinställningar som inte stöds i rullgardinslistorna för skrivare och filament. Dessa förinställningar kan inte väljas."
|
||||
|
||||
# AI Translated
|
||||
msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
msgstr "(Experimentellt) Använd skrivaragenter i stället för utskriftsvärdar"
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"Skickar utskriftsjobb för icke-Bambu-skrivare via skrivarens insticksmodulagenter i stället för det klassiska uppladdningsflödet till utskriftsvärden.\n"
|
||||
"När detta är avaktiverat använder OrcaSlicer det äldre beteendet för utskriftsvärdar."
|
||||
|
||||
# AI Translated
|
||||
msgid "Experimental Features"
|
||||
msgstr "Experimentella funktioner"
|
||||
@@ -11332,17 +11325,6 @@ msgstr ""
|
||||
"Försök att behålla målade egenskaper (färg/söm/support/ojämn yta osv.) efter att objektets mesh ändrats (t.ex. snitt, läs in från disk igen, förenkla, reparera osv.)\n"
|
||||
"Mycket experimentellt! Långsamt och kan skapa artefakter."
|
||||
|
||||
msgid "Use printer agents instead of print hosts"
|
||||
msgstr ""
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"Skickar utskriftsjobb för icke-Bambu-skrivare via skrivarens insticksmodulagenter i stället för det klassiska uppladdningsflödet till utskriftsvärden.\n"
|
||||
"När detta är avaktiverat använder OrcaSlicer det äldre beteendet för utskriftsvärdar."
|
||||
|
||||
# AI Translated
|
||||
msgid "Allow Abnormal Storage"
|
||||
msgstr "Tillåt onormalt lagringsmedium"
|
||||
@@ -12193,12 +12175,6 @@ msgstr "Avbryt timelapse och skriv ut"
|
||||
msgid "Clean Up"
|
||||
msgstr "Rensa"
|
||||
|
||||
msgid "AMS filament mapping is not available for this printer. Clear the AMS mapping before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "A filament used by this print has no AMS mapping. Assign it before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "Preparing print job"
|
||||
msgstr "Förbereder utskriftsjobb"
|
||||
|
||||
@@ -18058,12 +18034,6 @@ msgstr "Symmetrisk ifyllnad kring Y-axeln"
|
||||
msgid "If the model has two parts that are symmetric about the Y axis, and you want these parts to have symmetric textures, please click this option on one of the parts."
|
||||
msgstr "Om modellen har två delar som är symmetriska kring Y-axeln och du vill att dessa delar ska ha symmetriska texturer, klickar du i det här alternativet på en av delarna."
|
||||
|
||||
msgid "Fill pattern tops"
|
||||
msgstr ""
|
||||
|
||||
msgid "Choose this option if you want to completely fill in the tops of the infill pattern"
|
||||
msgstr ""
|
||||
|
||||
# AI Translated
|
||||
msgid "Infill combination - Max layer height"
|
||||
msgstr "Ifyllnadskombination – max lagerhöjd"
|
||||
@@ -32678,9 +32648,6 @@ msgstr "Aktivera utvecklarverktyg"
|
||||
msgid "An error occurred loading %s"
|
||||
msgstr "Ett fel uppstod vid inläsning av %s"
|
||||
|
||||
msgid "/"
|
||||
msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, boost-format
|
||||
msgid "Load %1% to %2%"
|
||||
@@ -34467,6 +34434,9 @@ msgstr ""
|
||||
#~ msgid "An error occurred loading "
|
||||
#~ msgstr "Ett fel uppstod vid inläsning av "
|
||||
|
||||
#~ msgid "/"
|
||||
#~ msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, c-format, boost-format
|
||||
#~ msgid "Load %s to "
|
||||
@@ -34676,10 +34646,6 @@ msgstr ""
|
||||
#~ msgid "Support/Color Painting: adjust section position"
|
||||
#~ msgstr "Support/Färgläggning:justera sektions positionen"
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
#~ msgstr "(Experimentellt) Använd skrivaragenter i stället för utskriftsvärdar"
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "Tab"
|
||||
#~ msgstr "Tabb"
|
||||
|
||||
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Orca Slicer\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-10-06 13:42+0800\n"
|
||||
"POT-Creation-Date: 2026-10-05 10:49-0300\n"
|
||||
"PO-Revision-Date: 2026-06-19 13:40+0700\n"
|
||||
"Last-Translator: Icezaza\n"
|
||||
"Language-Team: Thai\n"
|
||||
@@ -4332,9 +4332,6 @@ msgstr "คุณแน่ใจหรือไม่ว่าต้องกา
|
||||
msgid "You need to select the material type and color first."
|
||||
msgstr "คุณต้องเลือกประเภทวัสดุและสีก่อน"
|
||||
|
||||
msgid "The minimum temperature cannot be greater than the maximum temperature."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Please input a valid value (K in %.1f~%.1f)"
|
||||
msgstr "โปรดป้อนค่าที่ถูกต้อง (K อยู่ในช่วง %.1f~%.1f)"
|
||||
@@ -6195,7 +6192,7 @@ msgid "Size:"
|
||||
msgstr "ขนาด:"
|
||||
|
||||
# AI Translated
|
||||
#, boost-format
|
||||
#, c-format, boost-format
|
||||
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
|
||||
msgstr "พบความขัดแย้งของเส้นทาง G-code ที่เลเยอร์ %d, Z = %.2lfmm โปรดแยกวัตถุที่ขัดแย้งกันให้ไกลออกไป (%s <-> %s)"
|
||||
|
||||
@@ -7064,22 +7061,6 @@ msgstr "ไฟล์ .gcode.3mf ไม่มีข้อมูล G-code โป
|
||||
msgid "File '%s' was lost! Please download it again."
|
||||
msgstr "ไฟล์ '%s' สูญหาย! กรุณาดาวน์โหลดอีกครั้ง."
|
||||
|
||||
msgid "gcodes"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to delete the file from printer."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Do you want to print the file '%s' from printer?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Print file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to start the print job."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid ""
|
||||
"File: %s\n"
|
||||
@@ -10245,6 +10226,18 @@ msgstr "แสดงค่าที่ตั้งไว้ล่วงหน้
|
||||
msgid "Show incompatible/unsupported presets in the printer and filament dropdown lists. These presets cannot be selected."
|
||||
msgstr "แสดงค่าที่ตั้งไว้ล่วงหน้าที่ไม่เข้ากันหรือไม่รองรับในรายการเลือกเครื่องพิมพ์และเส้นพลาสติก ไม่สามารถเลือกค่าที่ตั้งไว้ล่วงหน้าเหล่านี้ได้"
|
||||
|
||||
# AI Translated
|
||||
msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
msgstr "(ทดลอง) ใช้เอเจนต์เครื่องพิมพ์แทนโฮสต์การพิมพ์"
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"ส่งงานพิมพ์ของเครื่องพิมพ์ที่ไม่ใช่ Bambu ผ่านเอเจนต์ปลั๊กอินของเครื่องพิมพ์ แทนการอัพโหลดไปยังโฮสต์การพิมพ์แบบเดิม\n"
|
||||
"เมื่อปิดใช้ OrcaSlicer จะใช้พฤติกรรมโฮสต์การพิมพ์แบบเดิม"
|
||||
|
||||
# AI Translated
|
||||
msgid "Experimental Features"
|
||||
msgstr "ฟีเจอร์ทดลอง"
|
||||
@@ -10260,17 +10253,6 @@ msgstr ""
|
||||
"พยายามคงคุณสมบัติการทาสีไว้ (สี/รอยตะเข็บ/ส่วนรองรับ/ผิวฟัซซี ฯลฯ) หลังจากเปลี่ยนตาข่ายวัตถุ (เช่น ตัด/โหลดซ้ำจากดิสก์/ลดความซับซ้อน/แก้ไข ฯลฯ)\n"
|
||||
"น่าทดลองมาก! ช้าและอาจสร้างสิ่งประดิษฐ์"
|
||||
|
||||
msgid "Use printer agents instead of print hosts"
|
||||
msgstr ""
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"ส่งงานพิมพ์ของเครื่องพิมพ์ที่ไม่ใช่ Bambu ผ่านเอเจนต์ปลั๊กอินของเครื่องพิมพ์ แทนการอัพโหลดไปยังโฮสต์การพิมพ์แบบเดิม\n"
|
||||
"เมื่อปิดใช้ OrcaSlicer จะใช้พฤติกรรมโฮสต์การพิมพ์แบบเดิม"
|
||||
|
||||
msgid "Allow Abnormal Storage"
|
||||
msgstr "อนุญาตให้จัดเก็บผิดปกติ"
|
||||
|
||||
@@ -11081,12 +11063,6 @@ msgstr "ยกเลิกไทม์แลปส์และพิมพ์"
|
||||
msgid "Clean Up"
|
||||
msgstr "ล้าง"
|
||||
|
||||
msgid "AMS filament mapping is not available for this printer. Clear the AMS mapping before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "A filament used by this print has no AMS mapping. Assign it before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "Preparing print job"
|
||||
msgstr "กำลังเตรียมงานพิมพ์"
|
||||
|
||||
@@ -16271,12 +16247,6 @@ msgstr "แกน Y ไส้ในแบบสมมาตร"
|
||||
msgid "If the model has two parts that are symmetric about the Y axis, and you want these parts to have symmetric textures, please click this option on one of the parts."
|
||||
msgstr "หากแบบจำลองมีสองส่วนที่สมมาตรเกี่ยวกับแกน Y และคุณต้องการให้ส่วนเหล่านี้มีพื้นผิวที่สมมาตร โปรดคลิกตัวเลือกนี้บนส่วนใดส่วนหนึ่ง"
|
||||
|
||||
msgid "Fill pattern tops"
|
||||
msgstr ""
|
||||
|
||||
msgid "Choose this option if you want to completely fill in the tops of the infill pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Infill combination - Max layer height"
|
||||
msgstr "ชุดค่าผสม ไส้ใน - ความสูงของชั้นสูงสุด"
|
||||
|
||||
@@ -30026,10 +29996,6 @@ msgstr "เปิดใช้งานเครื่องมือนักพ
|
||||
msgid "An error occurred loading %s"
|
||||
msgstr "เกิดข้อผิดพลาดในการโหลด %s"
|
||||
|
||||
# AI Translated
|
||||
msgid "/"
|
||||
msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, boost-format
|
||||
msgid "Load %1% to %2%"
|
||||
@@ -30709,10 +30675,6 @@ msgstr ""
|
||||
"หลีกเลี่ยงการบิดเบี้ยว\n"
|
||||
"คุณรู้หรือไม่ว่าเมื่อพิมพ์วัสดุที่มีแนวโน้มที่จะเกิดการบิดเบี้ยว เช่น ABS การเพิ่มอุณหภูมิฐานพิมพ์อย่างเหมาะสมสามารถลดความน่าจะเป็นของการบิดเบี้ยวได้"
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
#~ msgstr "(ทดลอง) ใช้เอเจนต์เครื่องพิมพ์แทนโฮสต์การพิมพ์"
|
||||
|
||||
#~ msgid "X"
|
||||
#~ msgstr "X"
|
||||
|
||||
@@ -31737,6 +31699,10 @@ msgstr ""
|
||||
#~ msgid "An error occurred loading "
|
||||
#~ msgstr "เกิดข้อผิดพลาดในการโหลด "
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "/"
|
||||
#~ msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, c-format, boost-format
|
||||
#~ msgid "Load %s to "
|
||||
|
||||
@@ -3,7 +3,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Orca Slicer\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-10-06 13:42+0800\n"
|
||||
"POT-Creation-Date: 2026-10-05 10:49-0300\n"
|
||||
"PO-Revision-Date: 2026-08-21 23:18+0300\n"
|
||||
"Last-Translator: GlauTech\n"
|
||||
"Language-Team: \n"
|
||||
@@ -4384,9 +4384,6 @@ msgstr "Filament bilgisini temizlemek istediğinizden emin misiniz?"
|
||||
msgid "You need to select the material type and color first."
|
||||
msgstr "Önce malzeme türünü ve rengini seçmeniz gerekir."
|
||||
|
||||
msgid "The minimum temperature cannot be greater than the maximum temperature."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Please input a valid value (K in %.1f~%.1f)"
|
||||
msgstr "Lütfen geçerli bir değer girin (K %.1f~%.1f içinde)"
|
||||
@@ -6261,7 +6258,7 @@ msgstr "Hacim:"
|
||||
msgid "Size:"
|
||||
msgstr "Boyut:"
|
||||
|
||||
#, boost-format
|
||||
#, c-format, boost-format
|
||||
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
|
||||
msgstr "%d katmanında G-code yollarında çakışmalar bulundu, Z = %.2lfmm. Lütfen çakışan nesneleri daha uzağa ayırın (%s <-> %s)."
|
||||
|
||||
@@ -7137,22 +7134,6 @@ msgstr ".gcode.3mf dosyası hiçbir G-code verisi içermiyor. Lütfen dosyayı B
|
||||
msgid "File '%s' was lost! Please download it again."
|
||||
msgstr "'%s' dosyası kayboldu! Lütfen tekrar indirin."
|
||||
|
||||
msgid "gcodes"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to delete the file from printer."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Do you want to print the file '%s' from printer?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Print file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to start the print job."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid ""
|
||||
"File: %s\n"
|
||||
@@ -10377,6 +10358,18 @@ msgstr "Desteklenmeyen ön ayarları göster"
|
||||
msgid "Show incompatible/unsupported presets in the printer and filament dropdown lists. These presets cannot be selected."
|
||||
msgstr "Yazıcı ve filament açılır listelerinde uyumsuz/desteklenmeyen ön ayarları gösterir. Bu ön ayarlar seçilemez."
|
||||
|
||||
# AI Translated
|
||||
msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
msgstr "(Deneysel) Baskı sunucuları yerine yazıcı aracılarını kullan"
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"Bambu olmayan yazıcıların baskı işlerini, klasik baskı sunucusuna yükleme akışı yerine yazıcı eklenti aracıları üzerinden yönlendirir.\n"
|
||||
"Devre dışı bırakıldığında OrcaSlicer eski baskı sunucusu davranışını kullanır."
|
||||
|
||||
# AI Translated
|
||||
msgid "Experimental Features"
|
||||
msgstr "Deneysel Özellikler"
|
||||
@@ -10393,17 +10386,6 @@ msgstr ""
|
||||
"Nesne mesh'i değiştikten sonra (kesme/diskten yeniden yükleme/basitleştirme/onarma vb.) boyanmış özellikleri (renk/dikiş/destek/pütür vb.) korumaya çalışır.\n"
|
||||
"Oldukça deneyseldir! Yavaştır ve bozulmalara yol açabilir."
|
||||
|
||||
msgid "Use printer agents instead of print hosts"
|
||||
msgstr ""
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"Bambu olmayan yazıcıların baskı işlerini, klasik baskı sunucusuna yükleme akışı yerine yazıcı eklenti aracıları üzerinden yönlendirir.\n"
|
||||
"Devre dışı bırakıldığında OrcaSlicer eski baskı sunucusu davranışını kullanır."
|
||||
|
||||
msgid "Allow Abnormal Storage"
|
||||
msgstr "Anormal Depolamaya İzin Ver"
|
||||
|
||||
@@ -11217,12 +11199,6 @@ msgstr "Timelapse'i İptal Et ve Yazdır"
|
||||
msgid "Clean Up"
|
||||
msgstr "Temizle"
|
||||
|
||||
msgid "AMS filament mapping is not available for this printer. Clear the AMS mapping before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "A filament used by this print has no AMS mapping. Assign it before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "Preparing print job"
|
||||
msgstr "Yazdırma için hazırlanıyor"
|
||||
|
||||
@@ -16527,12 +16503,6 @@ msgstr "Simetrik dolgu Y ekseni"
|
||||
msgid "If the model has two parts that are symmetric about the Y axis, and you want these parts to have symmetric textures, please click this option on one of the parts."
|
||||
msgstr "Modelin Y ekseni etrafında simetrik iki parçası varsa ve bu parçaların simetrik dokulara sahip olmasını istiyorsanız, lütfen parçalardan birinde bu seçeneğe tıklayın."
|
||||
|
||||
msgid "Fill pattern tops"
|
||||
msgstr ""
|
||||
|
||||
msgid "Choose this option if you want to completely fill in the tops of the infill pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Infill combination - Max layer height"
|
||||
msgstr "Dolgu kombinasyonu - Maksimum katman yüksekliği"
|
||||
|
||||
@@ -30475,10 +30445,6 @@ msgstr "Geliştirici Araçlarını Etkinleştir"
|
||||
msgid "An error occurred loading %s"
|
||||
msgstr "%s yüklenirken bir hata oluştu"
|
||||
|
||||
# AI Translated
|
||||
msgid "/"
|
||||
msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, boost-format
|
||||
msgid "Load %1% to %2%"
|
||||
@@ -32182,6 +32148,10 @@ msgstr ""
|
||||
#~ msgid "An error occurred loading "
|
||||
#~ msgstr "Yüklenirken bir hata oluştu: "
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "/"
|
||||
#~ msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, c-format, boost-format
|
||||
#~ msgid "Load %s to "
|
||||
@@ -32387,10 +32357,6 @@ msgstr ""
|
||||
#~ msgid "Support/Color Painting: adjust section position"
|
||||
#~ msgstr "Destek/Renkli Boyama: bölüm konumunu ayarlayın"
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
#~ msgstr "(Deneysel) Baskı sunucuları yerine yazıcı aracılarını kullan"
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "Tab"
|
||||
#~ msgstr "Sekme"
|
||||
|
||||
@@ -3,7 +3,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: orcaslicerua\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-10-06 13:42+0800\n"
|
||||
"POT-Creation-Date: 2026-10-05 10:49-0300\n"
|
||||
"PO-Revision-Date: 2026-07-17 16:25+0300\n"
|
||||
"Last-Translator: Andrij Mizyk <andm1zyk@proton.me>\n"
|
||||
"Language-Team: Ukrainian\n"
|
||||
@@ -4298,9 +4298,6 @@ msgstr "Ви впевнені, що хочете видалити інформа
|
||||
msgid "You need to select the material type and color first."
|
||||
msgstr "Спочатку потрібно вибрати тип матеріалу та колір."
|
||||
|
||||
msgid "The minimum temperature cannot be greater than the maximum temperature."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Please input a valid value (K in %.1f~%.1f)"
|
||||
msgstr "Будь ласка введіть коректне значення (K в %.1f~%.1f)"
|
||||
@@ -6215,7 +6212,7 @@ msgid "Size:"
|
||||
msgstr "Розмір:"
|
||||
|
||||
# AI Translated
|
||||
#, boost-format
|
||||
#, c-format, boost-format
|
||||
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
|
||||
msgstr "Виявлено конфлікти шляхів G-code на шарі %d, Z = %.2lf мм. Будь ласка, рознесіть конфліктуючі обʼєкти далі один від одного (%s <-> %s)."
|
||||
|
||||
@@ -7106,22 +7103,6 @@ msgstr "Файл .gcode.3mf не містить даних G-code. Будь ла
|
||||
msgid "File '%s' was lost! Please download it again."
|
||||
msgstr "Файл '%s' втрачений! Завантажте його знову."
|
||||
|
||||
msgid "gcodes"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to delete the file from printer."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Do you want to print the file '%s' from printer?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Print file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to start the print job."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid ""
|
||||
"File: %s\n"
|
||||
@@ -10384,6 +10365,18 @@ msgstr "Показати непідтримувані пресети"
|
||||
msgid "Show incompatible/unsupported presets in the printer and filament dropdown lists. These presets cannot be selected."
|
||||
msgstr "Показати несумісні/непідтримувані пресети у випадаючому списку принтера і філаменту. Ці пресети не можна вибрати."
|
||||
|
||||
# AI Translated
|
||||
msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
msgstr "(Експериментально) Використовувати агентів принтера замість хостів друку"
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"Спрямовує завдання друку для принтерів, відмінних від Bambu, через агентів плагінів принтера замість класичного завантаження на хост друку.\n"
|
||||
"Коли вимкнено, OrcaSlicer використовує попередню поведінку хоста друку."
|
||||
|
||||
msgid "Experimental Features"
|
||||
msgstr "Експериментальні функції"
|
||||
|
||||
@@ -10398,17 +10391,6 @@ msgstr ""
|
||||
"Намагатися зберегти намальовані елементи (колір/шов/підтримки/шорсткість тощо) після зміни сітки обʼєкта (наприклад, розрізання/перезавантаження з диска/спрощення/виправлення тощо)\n"
|
||||
"Дуже експериментально! Повільно і може створювати артефакти."
|
||||
|
||||
msgid "Use printer agents instead of print hosts"
|
||||
msgstr ""
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"Спрямовує завдання друку для принтерів, відмінних від Bambu, через агентів плагінів принтера замість класичного завантаження на хост друку.\n"
|
||||
"Коли вимкнено, OrcaSlicer використовує попередню поведінку хоста друку."
|
||||
|
||||
msgid "Allow Abnormal Storage"
|
||||
msgstr "Дозволити незвичне сховище"
|
||||
|
||||
@@ -11234,12 +11216,6 @@ msgstr "Скасувати таймлапс і друкувати"
|
||||
msgid "Clean Up"
|
||||
msgstr "Очистити"
|
||||
|
||||
msgid "AMS filament mapping is not available for this printer. Clear the AMS mapping before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "A filament used by this print has no AMS mapping. Assign it before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "Preparing print job"
|
||||
msgstr "Підготовка завдання для друку"
|
||||
|
||||
@@ -16680,12 +16656,6 @@ msgstr "Симетричне заповнення по осі Y"
|
||||
msgid "If the model has two parts that are symmetric about the Y axis, and you want these parts to have symmetric textures, please click this option on one of the parts."
|
||||
msgstr "Якщо модель має дві частини, симетричні відносно осі Y, і ви хочете, щоб ці частини мали симетричні текстури, увімкніть цю опцію на одній із частин."
|
||||
|
||||
msgid "Fill pattern tops"
|
||||
msgstr ""
|
||||
|
||||
msgid "Choose this option if you want to completely fill in the tops of the infill pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Infill combination - Max layer height"
|
||||
msgstr "Комбінація заповнення - Максимальна висота шару"
|
||||
|
||||
@@ -30642,9 +30612,6 @@ msgstr "Увімкнути інструменти розробника"
|
||||
msgid "An error occurred loading %s"
|
||||
msgstr "Помилка під час завантаження %s"
|
||||
|
||||
msgid "/"
|
||||
msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, boost-format
|
||||
msgid "Load %1% to %2%"
|
||||
@@ -31329,10 +31296,6 @@ msgstr ""
|
||||
"Уникнення деформації\n"
|
||||
"Чи знаєте ви, що при друку матеріалами, схильними до деформації, такими як ABS, відповідне підвищення температури столу може зменшити ймовірність деформації?"
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
#~ msgstr "(Експериментально) Використовувати агентів принтера замість хостів друку"
|
||||
|
||||
#~ msgid "X"
|
||||
#~ msgstr "X"
|
||||
|
||||
@@ -32379,6 +32342,9 @@ msgstr ""
|
||||
#~ msgid "An error occurred loading "
|
||||
#~ msgstr "Помилка під час завантаження "
|
||||
|
||||
#~ msgid "/"
|
||||
#~ msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, c-format, boost-format
|
||||
#~ msgid "Load %s to "
|
||||
|
||||
@@ -3,7 +3,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Orca Slicer\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-10-06 13:42+0800\n"
|
||||
"POT-Creation-Date: 2026-10-05 10:49-0300\n"
|
||||
"PO-Revision-Date: 2025-10-02 17:43+0700\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: hainguyen.ts13@gmail.com\n"
|
||||
@@ -4558,9 +4558,6 @@ msgstr "Bạn có chắc muốn xóa thông tin filament?"
|
||||
msgid "You need to select the material type and color first."
|
||||
msgstr "Bạn cần chọn loại vật liệu và màu trước."
|
||||
|
||||
msgid "The minimum temperature cannot be greater than the maximum temperature."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Please input a valid value (K in %.1f~%.1f)"
|
||||
msgstr "Vui lòng nhập giá trị hợp lệ (K trong %.1f~%.1f)"
|
||||
@@ -6568,7 +6565,7 @@ msgstr "Thể tích:"
|
||||
msgid "Size:"
|
||||
msgstr "Kích thước:"
|
||||
|
||||
#, boost-format
|
||||
#, c-format, boost-format
|
||||
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
|
||||
msgstr "Đã tìm thấy xung đột đường đi G-code tại lớp %d, Z = %.2lfmm. Vui lòng tách các vật thể xung đột ra xa hơn (%s <-> %s)."
|
||||
|
||||
@@ -7472,22 +7469,6 @@ msgstr "File .gcode.3mf không chứa dữ liệu G-code. Vui lòng slice với
|
||||
msgid "File '%s' was lost! Please download it again."
|
||||
msgstr "File '%s' đã bị mất! Vui lòng tải lại."
|
||||
|
||||
msgid "gcodes"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to delete the file from printer."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Do you want to print the file '%s' from printer?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Print file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to start the print job."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid ""
|
||||
"File: %s\n"
|
||||
@@ -10895,6 +10876,18 @@ msgstr "Hiện cài đặt sẵn không được hỗ trợ"
|
||||
msgid "Show incompatible/unsupported presets in the printer and filament dropdown lists. These presets cannot be selected."
|
||||
msgstr "Hiện các cài đặt sẵn không tương thích/không được hỗ trợ trong danh sách thả xuống máy in và filament. Không thể chọn các cài đặt sẵn này."
|
||||
|
||||
# AI Translated
|
||||
msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
msgstr "(Thử nghiệm) Dùng tác nhân máy in thay cho máy chủ in"
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"Định tuyến các tác vụ in của máy in không phải Bambu qua các tác nhân plugin máy in thay vì luồng tải lên máy chủ in cổ điển.\n"
|
||||
"Khi tắt, OrcaSlicer sẽ dùng hành vi máy chủ in cũ."
|
||||
|
||||
# AI Translated
|
||||
msgid "Experimental Features"
|
||||
msgstr "Tính năng thử nghiệm"
|
||||
@@ -10911,17 +10904,6 @@ msgstr ""
|
||||
"Cố gắng giữ lại các phần đã tô (màu/đường nối/support/fuzzy v.v.) sau khi thay đổi lưới của vật thể (như cắt/tải lại từ đĩa/đơn giản hóa/sửa v.v.)\n"
|
||||
"Rất thử nghiệm! Chậm và có thể tạo ra khuyết điểm."
|
||||
|
||||
msgid "Use printer agents instead of print hosts"
|
||||
msgstr ""
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"Định tuyến các tác vụ in của máy in không phải Bambu qua các tác nhân plugin máy in thay vì luồng tải lên máy chủ in cổ điển.\n"
|
||||
"Khi tắt, OrcaSlicer sẽ dùng hành vi máy chủ in cũ."
|
||||
|
||||
# AI Translated
|
||||
msgid "Allow Abnormal Storage"
|
||||
msgstr "Cho phép Bộ nhớ bất thường"
|
||||
@@ -11760,12 +11742,6 @@ msgstr "Hủy timelapse & In"
|
||||
msgid "Clean Up"
|
||||
msgstr "Dọn dẹp"
|
||||
|
||||
msgid "AMS filament mapping is not available for this printer. Clear the AMS mapping before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "A filament used by this print has no AMS mapping. Assign it before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "Preparing print job"
|
||||
msgstr "Đang chuẩn bị công việc in"
|
||||
|
||||
@@ -17226,12 +17202,6 @@ msgstr "Infill đối xứng trục Y"
|
||||
msgid "If the model has two parts that are symmetric about the Y axis, and you want these parts to have symmetric textures, please click this option on one of the parts."
|
||||
msgstr "Nếu model có hai phần đối xứng về trục Y, và bạn muốn các phần này có kết cấu đối xứng, vui lòng nhấp tùy chọn này trên một trong các phần."
|
||||
|
||||
msgid "Fill pattern tops"
|
||||
msgstr ""
|
||||
|
||||
msgid "Choose this option if you want to completely fill in the tops of the infill pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Infill combination - Max layer height"
|
||||
msgstr "Kết hợp infill - Chiều cao lớp tối đa"
|
||||
|
||||
@@ -31315,10 +31285,6 @@ msgstr "Bật công cụ nhà phát triển"
|
||||
msgid "An error occurred loading %s"
|
||||
msgstr "Đã xảy ra lỗi khi tải %s"
|
||||
|
||||
# AI Translated
|
||||
msgid "/"
|
||||
msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, boost-format
|
||||
msgid "Load %1% to %2%"
|
||||
@@ -33056,6 +33022,10 @@ msgstr ""
|
||||
#~ msgid "An error occurred loading "
|
||||
#~ msgstr "Đã xảy ra lỗi khi tải "
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "/"
|
||||
#~ msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, c-format, boost-format
|
||||
#~ msgid "Load %s to "
|
||||
@@ -33262,10 +33232,6 @@ msgstr ""
|
||||
#~ msgid "Support/Color Painting: adjust section position"
|
||||
#~ msgstr "Tô support/màu: điều chỉnh vị trí phần"
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
#~ msgstr "(Thử nghiệm) Dùng tác nhân máy in thay cho máy chủ in"
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "Tab"
|
||||
#~ msgstr "Tab"
|
||||
|
||||
@@ -6,7 +6,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Slic3rPE\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-10-06 13:42+0800\n"
|
||||
"POT-Creation-Date: 2026-10-05 10:49-0300\n"
|
||||
"PO-Revision-Date: 2026-06-11 12:37-0300\n"
|
||||
"Last-Translator: Handle <mail@bysb.net>\n"
|
||||
"Language-Team: \n"
|
||||
@@ -4185,9 +4185,6 @@ msgstr "您确定要清除耗材丝信息吗?"
|
||||
msgid "You need to select the material type and color first."
|
||||
msgstr "您需要先选择材料类型和颜色。"
|
||||
|
||||
msgid "The minimum temperature cannot be greater than the maximum temperature."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Please input a valid value (K in %.1f~%.1f)"
|
||||
msgstr "请输入有效的数值(K的范围为%.1f~%.1f)"
|
||||
@@ -6045,7 +6042,7 @@ msgstr "体积:"
|
||||
msgid "Size:"
|
||||
msgstr "尺寸:"
|
||||
|
||||
#, boost-format
|
||||
#, c-format, boost-format
|
||||
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
|
||||
msgstr "发现G-code路径在层%d,高度为%.2lf mm处有冲突。请将有冲突的对象分离得更远(%s <-> %s)。"
|
||||
|
||||
@@ -6909,22 +6906,6 @@ msgstr ".gcode.3mf文件中不包含G-code数据。请使用Orca Slicer进行切
|
||||
msgid "File '%s' was lost! Please download it again."
|
||||
msgstr "文件%s丢失,请重新下载。"
|
||||
|
||||
msgid "gcodes"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to delete the file from printer."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Do you want to print the file '%s' from printer?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Print file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to start the print job."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid ""
|
||||
"File: %s\n"
|
||||
@@ -10056,6 +10037,18 @@ msgstr "显示不受支持的预设"
|
||||
msgid "Show incompatible/unsupported presets in the printer and filament dropdown lists. These presets cannot be selected."
|
||||
msgstr "在打印机和耗材下拉列表中显示不兼容/不受支持的预设。这些预设无法被选择。"
|
||||
|
||||
# AI Translated
|
||||
msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
msgstr "(实验性)使用打印机代理替代打印主机"
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"非 Bambu 打印机的打印任务将通过打印机插件代理发送,而不是经典的打印主机上传流程。\n"
|
||||
"禁用时,OrcaSlicer 使用旧的打印主机行为。"
|
||||
|
||||
# AI Translated
|
||||
msgid "Experimental Features"
|
||||
msgstr "实验性功能"
|
||||
@@ -10071,17 +10064,6 @@ msgstr ""
|
||||
"在更改对象网格(如切割/从磁盘重新加载/简化/修复等)后,尝试保留绘制的特征(颜色/接缝/支撑/绒毛等)。\n"
|
||||
"高度实验性!速度较慢且可能产生瑕疵。"
|
||||
|
||||
msgid "Use printer agents instead of print hosts"
|
||||
msgstr ""
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"非 Bambu 打印机的打印任务将通过打印机插件代理发送,而不是经典的打印主机上传流程。\n"
|
||||
"禁用时,OrcaSlicer 使用旧的打印主机行为。"
|
||||
|
||||
msgid "Allow Abnormal Storage"
|
||||
msgstr "允许异常存储"
|
||||
|
||||
@@ -10869,12 +10851,6 @@ msgstr "取消延时摄影,继续打印"
|
||||
msgid "Clean Up"
|
||||
msgstr "清理"
|
||||
|
||||
msgid "AMS filament mapping is not available for this printer. Clear the AMS mapping before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "A filament used by this print has no AMS mapping. Assign it before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "Preparing print job"
|
||||
msgstr "正在准备打印任务"
|
||||
|
||||
@@ -16009,12 +15985,6 @@ msgstr "对称填充Y轴"
|
||||
msgid "If the model has two parts that are symmetric about the Y axis, and you want these parts to have symmetric textures, please click this option on one of the parts."
|
||||
msgstr "若模型有两个在Y轴上对称的部分,并且您想对其使用对称的纹理,就请在对应的模型部分上应用此设置。"
|
||||
|
||||
msgid "Fill pattern tops"
|
||||
msgstr ""
|
||||
|
||||
msgid "Choose this option if you want to completely fill in the tops of the infill pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Infill combination - Max layer height"
|
||||
msgstr "填充组合 - 最大层高"
|
||||
|
||||
@@ -29754,10 +29724,6 @@ msgstr "启用开发者工具"
|
||||
msgid "An error occurred loading %s"
|
||||
msgstr "加载 %s 时出错"
|
||||
|
||||
# AI Translated
|
||||
msgid "/"
|
||||
msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, boost-format
|
||||
msgid "Load %1% to %2%"
|
||||
@@ -30437,10 +30403,6 @@ msgstr ""
|
||||
"避免翘曲\n"
|
||||
"您知道吗?打印ABS这类易翘曲材料时,适当提高热床温度可以降低翘曲的概率。"
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
#~ msgstr "(实验性)使用打印机代理替代打印主机"
|
||||
|
||||
#~ msgid "X"
|
||||
#~ msgstr "X"
|
||||
|
||||
@@ -31460,6 +31422,10 @@ msgstr ""
|
||||
#~ msgid "An error occurred loading "
|
||||
#~ msgstr "加载时出错: "
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "/"
|
||||
#~ msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, c-format, boost-format
|
||||
#~ msgid "Load %s to "
|
||||
|
||||
@@ -9,7 +9,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Orca Slicer\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-10-06 13:42+0800\n"
|
||||
"POT-Creation-Date: 2026-10-05 10:49-0300\n"
|
||||
"PO-Revision-Date: 2025-11-28 13:48-0600\n"
|
||||
"Last-Translator: tntchn <15895303+tntchn@users.noreply.github.com>\n"
|
||||
"Language-Team: \n"
|
||||
@@ -4290,9 +4290,6 @@ msgstr "您確認要清除線材資訊嗎?"
|
||||
msgid "You need to select the material type and color first."
|
||||
msgstr "您需要先選擇線材類型和顏色。"
|
||||
|
||||
msgid "The minimum temperature cannot be greater than the maximum temperature."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Please input a valid value (K in %.1f~%.1f)"
|
||||
msgstr "請輸入有效的數值 (K於 %.1f~%.1f 之間)"
|
||||
@@ -6175,7 +6172,7 @@ msgstr "體積:"
|
||||
msgid "Size:"
|
||||
msgstr "尺寸:"
|
||||
|
||||
#, boost-format
|
||||
#, c-format, boost-format
|
||||
msgid "Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s)."
|
||||
msgstr "發現 G-code 路徑在 %d 層,Z = %.2lf mm 處的衝突。請將有衝突的物件分離得更遠(%s <-> %s)。"
|
||||
|
||||
@@ -7044,22 +7041,6 @@ msgstr ".gcode.3mf 檔案不包含 G-code 資料。請使用 OrcaSlicer 切片
|
||||
msgid "File '%s' was lost! Please download it again."
|
||||
msgstr "檔案 %s 遺失,請重新下載。"
|
||||
|
||||
msgid "gcodes"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to delete the file from printer."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Do you want to print the file '%s' from printer?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Print file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to start the print job."
|
||||
msgstr ""
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid ""
|
||||
"File: %s\n"
|
||||
@@ -10231,6 +10212,18 @@ msgstr "顯示不支援的預設"
|
||||
msgid "Show incompatible/unsupported presets in the printer and filament dropdown lists. These presets cannot be selected."
|
||||
msgstr "在列印裝置和線材下拉選單中顯示不相容/不支援的預設。這些預設無法選取。"
|
||||
|
||||
# AI Translated
|
||||
msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
msgstr "(實驗性)使用列印裝置代理程式取代列印主機"
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"將非 Bambu 列印裝置的列印工作透過列印裝置外掛代理程式傳送,而非傳統的列印主機上傳流程。\n"
|
||||
"停用時,OrcaSlicer 會使用舊有的列印主機行為。"
|
||||
|
||||
# AI Translated
|
||||
msgid "Experimental Features"
|
||||
msgstr "實驗性功能"
|
||||
@@ -10246,17 +10239,6 @@ msgstr ""
|
||||
"嘗試在變更物件網格(例如切割/從磁碟重新載入/簡化/修復等)後,保留已繪製的特徵(顏色/Z 縫/支撐/絨毛等)。\n"
|
||||
"高度實驗性!速度緩慢且可能產生瑕疵。"
|
||||
|
||||
msgid "Use printer agents instead of print hosts"
|
||||
msgstr ""
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Route print jobs for non-Bambu printers through printer plug-in agents instead of the classic print-host upload flow.\n"
|
||||
"When disabled, OrcaSlicer uses the legacy print-host behavior."
|
||||
msgstr ""
|
||||
"將非 Bambu 列印裝置的列印工作透過列印裝置外掛代理程式傳送,而非傳統的列印主機上傳流程。\n"
|
||||
"停用時,OrcaSlicer 會使用舊有的列印主機行為。"
|
||||
|
||||
msgid "Allow Abnormal Storage"
|
||||
msgstr "允許異常儲存空間"
|
||||
|
||||
@@ -11067,12 +11049,6 @@ msgstr "取消縮時攝影並列印"
|
||||
msgid "Clean Up"
|
||||
msgstr "清理"
|
||||
|
||||
msgid "AMS filament mapping is not available for this printer. Clear the AMS mapping before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "A filament used by this print has no AMS mapping. Assign it before printing."
|
||||
msgstr ""
|
||||
|
||||
msgid "Preparing print job"
|
||||
msgstr "正在準備列印作業"
|
||||
|
||||
@@ -16215,12 +16191,6 @@ msgstr "對稱填充Y軸"
|
||||
msgid "If the model has two parts that are symmetric about the Y axis, and you want these parts to have symmetric textures, please click this option on one of the parts."
|
||||
msgstr "若模型有兩個在Y軸上對稱的部分,並且您想對其使用對稱的紋理,就請在對應的模型部分上應用此設定。"
|
||||
|
||||
msgid "Fill pattern tops"
|
||||
msgstr ""
|
||||
|
||||
msgid "Choose this option if you want to completely fill in the tops of the infill pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Infill combination - Max layer height"
|
||||
msgstr "合併填充 - 最大層高"
|
||||
|
||||
@@ -29947,10 +29917,6 @@ msgstr "啟用開發者工具"
|
||||
msgid "An error occurred loading %s"
|
||||
msgstr "載入 %s 時發生錯誤"
|
||||
|
||||
# AI Translated
|
||||
msgid "/"
|
||||
msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, boost-format
|
||||
msgid "Load %1% to %2%"
|
||||
@@ -30651,10 +30617,6 @@ msgstr ""
|
||||
"避免翹曲\n"
|
||||
"您知道嗎?當列印容易翹曲的材料(如 ABS)時,適當提高熱床溫度可以降低翹曲的機率。"
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "(Experimental) Use printer agents instead of print hosts"
|
||||
#~ msgstr "(實驗性)使用列印裝置代理程式取代列印主機"
|
||||
|
||||
#~ msgid "X"
|
||||
#~ msgstr "X"
|
||||
|
||||
@@ -31675,6 +31637,10 @@ msgstr ""
|
||||
#~ msgid "An error occurred loading "
|
||||
#~ msgstr "載入時發生錯誤: "
|
||||
|
||||
# AI Translated
|
||||
#~ msgid "/"
|
||||
#~ msgstr "/"
|
||||
|
||||
# AI Translated
|
||||
#, c-format, boost-format
|
||||
#~ msgid "Load %s to "
|
||||
|
||||
+45
-14
@@ -8,6 +8,9 @@ include) fails wherever the error is. Headers are compiled on their own, and
|
||||
fail only on errors in their changed lines. Deleting an #include also fails
|
||||
on every use, changed or not, that now lacks the header it provided.
|
||||
|
||||
With -- --fix, clang-tidy adds the missing includes, on those lines only, and
|
||||
each file it changed is checked again so that only what remains is reported.
|
||||
|
||||
The checks come from .clang-tidy at the repository root. The compile database
|
||||
must come from a configure with SLIC3R_PCH=OFF, or the precompiled header hides
|
||||
missing includes.
|
||||
@@ -102,9 +105,10 @@ def is_checked(path):
|
||||
|
||||
def changed_files(merge_base):
|
||||
# Against the working tree, so a local run covers uncommitted edits too.
|
||||
# core.quotePath=false keeps a non-ASCII path unquoted, so parse_diff sees its b/ prefix.
|
||||
# core.quotePath=false keeps a non-ASCII path unquoted, and the explicit prefixes
|
||||
# override diff.noprefix and diff.mnemonicPrefix, so parse_diff sees its b/ prefix.
|
||||
diff = subprocess.run(["git", "-c", "core.quotePath=false", "diff", "-U0", "--no-color", "--no-ext-diff",
|
||||
"--diff-filter=AMR", merge_base],
|
||||
"--src-prefix=a/", "--dst-prefix=b/", "--diff-filter=AMR", merge_base],
|
||||
check=True, capture_output=True, **UTF8).stdout
|
||||
return {path: change for path, change in parse_diff(diff).items() if is_checked(path)}
|
||||
|
||||
@@ -201,13 +205,19 @@ def errors_alone_at(revision, clang_tidy, build_dir, path):
|
||||
|
||||
|
||||
def check_file(clang_tidy, build_dir, merge_base, path, change, extra_args):
|
||||
"""Run clang-tidy on one file and return (failed, output, failing diagnostics)."""
|
||||
"""Run clang-tidy on one file and return (failed, output, failing diagnostics, fixed)."""
|
||||
fixing = any(arg.startswith("--fix") for arg in extra_args)
|
||||
if fixing:
|
||||
with open(path, "rb") as f:
|
||||
before = f.read()
|
||||
# A deleted include can orphan uses on unchanged lines, so such a file is
|
||||
# checked whole and the findings narrowed here. --fix keeps the line filter
|
||||
# so it never rewrites unrelated code.
|
||||
whole = bool(change.removed_includes) and not extra_args
|
||||
# checked whole and the findings narrowed here. --fix keeps a line filter so
|
||||
# it never rewrites unrelated code, which for such a file means a second,
|
||||
# fixing run limited to the lines the first one found wanting.
|
||||
whole = bool(change.removed_includes)
|
||||
returncode, output, diagnostics = run_clang_tidy(clang_tidy, build_dir, path,
|
||||
None if whole else change.lines, extra_args)
|
||||
None if whole else change.lines,
|
||||
[] if whole else extra_args)
|
||||
real = os.path.realpath(path)
|
||||
|
||||
def introduced(d):
|
||||
@@ -223,14 +233,25 @@ def check_file(clang_tidy, build_dir, merge_base, path, change, extra_args):
|
||||
if errors and change.removed_includes:
|
||||
with open(path, encoding="utf-8") as f:
|
||||
text = f.read()
|
||||
before = errors_alone_at(merge_base, clang_tidy, build_dir, path)
|
||||
before_sites = errors_alone_at(merge_base, clang_tidy, build_dir, path)
|
||||
failing += [d for d in errors if d not in failing
|
||||
and (error_sites([d], text) - before)]
|
||||
return bool(failing), output, failing
|
||||
if whole:
|
||||
and (error_sites([d], text) - before_sites)]
|
||||
failed = bool(failing)
|
||||
elif whole:
|
||||
failing = [d for d in diagnostics if d.is_compile_error or introduced(d)]
|
||||
return bool(failing), output, failing
|
||||
return returncode != 0, output, diagnostics
|
||||
failed = bool(failing)
|
||||
else:
|
||||
failing, failed = diagnostics, returncode != 0
|
||||
if not fixing:
|
||||
return failed, output, failing, False
|
||||
if whole and failing:
|
||||
lines = change.lines + [[d.line, d.line] for d in failing if os.path.realpath(d.file) == real]
|
||||
run_clang_tidy(clang_tidy, build_dir, path, lines, extra_args)
|
||||
with open(path, "rb") as f:
|
||||
if f.read() == before:
|
||||
return failed, output, failing, False
|
||||
# Checked again, so what is reported is what the fixes left.
|
||||
return check_file(clang_tidy, build_dir, merge_base, path, change, [])[:3] + (True,)
|
||||
|
||||
|
||||
def main():
|
||||
@@ -263,11 +284,14 @@ def main():
|
||||
annotate = os.environ.get("GITHUB_ACTIONS") == "true"
|
||||
root = os.getcwd() + os.sep
|
||||
failed = []
|
||||
fixed = []
|
||||
with ThreadPoolExecutor(max_workers=args.jobs) as pool:
|
||||
jobs = {path: pool.submit(check_file, args.clang_tidy, args.build_dir, merge_base, path, change, args.extra_args)
|
||||
for path, change in todo}
|
||||
for path, job in jobs.items():
|
||||
file_failed, output, diagnostics = job.result()
|
||||
file_failed, output, diagnostics, file_fixed = job.result()
|
||||
if file_fixed:
|
||||
fixed.append(path)
|
||||
if not file_failed:
|
||||
continue
|
||||
failed.append(path)
|
||||
@@ -282,6 +306,13 @@ def main():
|
||||
if len(diagnostics) > MAX_REPORTED:
|
||||
print(f"... and {len(diagnostics) - MAX_REPORTED} more")
|
||||
|
||||
if fixed:
|
||||
print(f"\nAdded includes to {len(fixed)} file(s):")
|
||||
for path in fixed:
|
||||
print(f" {path}")
|
||||
if failed and fixed:
|
||||
print(f"\nclang-tidy still fails on {len(failed)} file(s); the findings above are what --fix could not add.")
|
||||
return 1
|
||||
if failed:
|
||||
print(f"\nclang-tidy failed on {len(failed)} file(s). Add the includes it names, or apply its "
|
||||
"suggestions locally with scripts/run_clang_tidy.sh --fix (scripts\\run_clang_tidy.ps1 -Fix on Windows).")
|
||||
|
||||
+40
-10
@@ -6,8 +6,9 @@
|
||||
# scripts/run_clang_tidy.sh --fix also add the missing includes it names
|
||||
#
|
||||
# It configures a separate build directory (build-tidy) without the precompiled
|
||||
# header, installs the pinned clang-tidy into a virtual environment inside it, and
|
||||
# runs scripts/clang_tidy_diff.py the way CI does. Uncommitted changes are checked too.
|
||||
# header, uses the clang-tidy on your system or installs the pinned one into a
|
||||
# virtual environment inside it, and runs scripts/clang_tidy_diff.py the way CI
|
||||
# does. Uncommitted changes are checked too.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
@@ -23,7 +24,8 @@ Usage: scripts/run_clang_tidy.sh [options]
|
||||
deps/build/<arch> on macOS)
|
||||
-j, --jobs N parallel clang-tidy runs (default: all cores)
|
||||
--fix apply clang-tidy's fixes (adds the missing includes)
|
||||
-y, --yes install missing tools without asking
|
||||
-y, --yes install missing tools without asking; another clang-tidy
|
||||
version found on the system is then not offered
|
||||
-h, --help show this help
|
||||
EOF
|
||||
}
|
||||
@@ -136,12 +138,38 @@ REQUIREMENTS="$ROOT/scripts/clang_tidy_requirements.txt"
|
||||
PINNED=$(sed -n 's/^clang-tidy==//p' "$REQUIREMENTS")
|
||||
VENV="$BUILD_DIR/clang-tidy-venv"
|
||||
|
||||
if [ -n "${CLANG_TIDY:-}" ]; then
|
||||
is_pinned() {
|
||||
[ -x "$1" ] && "$1" --version 2>/dev/null | grep -q "version $PINNED"
|
||||
}
|
||||
|
||||
CLANG_TIDY="${CLANG_TIDY:-}"
|
||||
if [ -n "$CLANG_TIDY" ]; then
|
||||
# Set by the caller: use it as is.
|
||||
:
|
||||
is_pinned "$CLANG_TIDY" || echo "Warning: $CLANG_TIDY is not clang-tidy $PINNED, so results may differ from CI." >&2
|
||||
else
|
||||
# One already on the system comes first: the pinned version outright, another
|
||||
# version if the user accepts the difference. The pinned version is installed
|
||||
# into a virtual environment otherwise.
|
||||
INSTALLED=""
|
||||
for candidate in $(command -v clang-tidy "clang-tidy-${PINNED%%.*}" || true) \
|
||||
"/usr/lib/llvm-${PINNED%%.*}/bin/clang-tidy" \
|
||||
"$(brew --prefix llvm 2>/dev/null || true)/bin/clang-tidy"; do
|
||||
if is_pinned "$candidate"; then
|
||||
CLANG_TIDY="$candidate"
|
||||
break
|
||||
fi
|
||||
[ -z "$INSTALLED" ] && [ -x "$candidate" ] && INSTALLED="$candidate"
|
||||
done
|
||||
if [ -z "$CLANG_TIDY" ] && [ -n "$INSTALLED" ] && [ "$YES" = 0 ] && ! is_pinned "$VENV/bin/clang-tidy"; then
|
||||
echo "Found $INSTALLED, which is $("$INSTALLED" --version | sed -n 's/.*version \([0-9.]*\).*/\1/p' | head -n 1), not the $PINNED CI uses, so results may differ slightly."
|
||||
if ask "Use it anyway?"; then
|
||||
CLANG_TIDY="$INSTALLED"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if [ -z "$CLANG_TIDY" ]; then
|
||||
CLANG_TIDY="$VENV/bin/clang-tidy"
|
||||
if [ ! -x "$CLANG_TIDY" ] || ! "$CLANG_TIDY" --version | grep -q "version $PINNED"; then
|
||||
if ! is_pinned "$CLANG_TIDY"; then
|
||||
if ask "clang-tidy $PINNED (the version CI uses) is not installed. Install it into $VENV?"; then
|
||||
mkdir -p "$BUILD_DIR"
|
||||
if ! python3 -m venv "$VENV"; then
|
||||
@@ -158,9 +186,6 @@ else
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if ! "$CLANG_TIDY" --version | grep -q "version $PINNED"; then
|
||||
echo "Warning: $CLANG_TIDY is not clang-tidy $PINNED, so results may differ from CI." >&2
|
||||
fi
|
||||
|
||||
# --- Dependencies -------------------------------------------------------------
|
||||
|
||||
@@ -217,7 +242,12 @@ cmake --build "$BUILD_DIR" --target git_commit_hash_header >/dev/null
|
||||
|
||||
if [ -z "$BASE" ]; then
|
||||
REMOTE=$(git remote -v | awk '/github\.com[:\/]OrcaSlicer\/OrcaSlicer(\.git)? \(fetch\)/ { print $1; exit }')
|
||||
REMOTE="${REMOTE:-origin}"
|
||||
if [ -z "$REMOTE" ]; then
|
||||
# Against a fork's main that already has the commits, nothing is checked.
|
||||
echo "Warning: no remote points at github.com/OrcaSlicer/OrcaSlicer, so this compares against origin/main." >&2
|
||||
echo "If origin is your fork, add the upstream remote (git remote add upstream https://github.com/OrcaSlicer/OrcaSlicer.git) or pass --base." >&2
|
||||
REMOTE=origin
|
||||
fi
|
||||
if [ "$FETCH" = 1 ]; then
|
||||
git fetch --quiet "$REMOTE" main
|
||||
fi
|
||||
|
||||
@@ -155,6 +155,8 @@ class TestSubprocessCalls(unittest.TestCase):
|
||||
diff = "+++ b/src/libslic3r/Über.cpp\n@@ -1,0 +2 @@\n+// 打印\n"
|
||||
files, call, _ = self.run_patched(clang_tidy_diff.changed_files, "base", stdout=diff)
|
||||
self.assertIn("core.quotePath=false", call.args[0])
|
||||
# Whatever diff.noprefix or diff.mnemonicPrefix a user has set.
|
||||
self.assertIn("--dst-prefix=b/", call.args[0])
|
||||
self.assertEqual(call.kwargs["encoding"], "utf-8")
|
||||
self.assertEqual(files["src/libslic3r/Über.cpp"].lines, [[2, 2]])
|
||||
|
||||
@@ -167,5 +169,60 @@ class TestSubprocessCalls(unittest.TestCase):
|
||||
self.assertEqual(call.kwargs["encoding"], "utf-8")
|
||||
|
||||
|
||||
class TestCheckFileFix(unittest.TestCase):
|
||||
"""check_file with -- --fix: what clang-tidy is run on, and what is reported afterwards."""
|
||||
|
||||
def setUp(self):
|
||||
self.dir = tempfile.TemporaryDirectory()
|
||||
self.addCleanup(self.dir.cleanup)
|
||||
self.path = os.path.join(self.dir.name, "Color.cpp")
|
||||
with open(self.path, "w") as f:
|
||||
f.write("int x;\n")
|
||||
|
||||
def finding(self, line, include=""):
|
||||
return clang_tidy_diff.Diagnostic(self.path, line, 1, "error",
|
||||
'no header providing "x" is directly included [misc-include-cleaner]', include)
|
||||
|
||||
def check(self, change, results, fix_writes=None):
|
||||
"""Run check_file with run_clang_tidy answering from `results` in turn; the --fix run
|
||||
rewrites the file with `fix_writes` when given. Returns (result, calls)."""
|
||||
calls = []
|
||||
|
||||
def run(clang_tidy, build_dir, path, lines, extra_args):
|
||||
calls.append((lines, extra_args))
|
||||
if "--fix" in extra_args and fix_writes is not None:
|
||||
with open(path, "w") as f:
|
||||
f.write(fix_writes)
|
||||
return results[len(calls) - 1]
|
||||
|
||||
with mock.patch.object(clang_tidy_diff, "run_clang_tidy", side_effect=run):
|
||||
result = clang_tidy_diff.check_file("clang-tidy", "build", "base", self.path, change, ["--fix"])
|
||||
return result, calls
|
||||
|
||||
def test_a_deleted_include_is_fixed_on_the_lines_it_orphaned_only(self):
|
||||
change = clang_tidy_diff.FileChange(lines=[[4, 4]], removed_includes={"libslic3r/Point.hpp"})
|
||||
orphaned = self.finding(50, "<libslic3r/Point.hpp>")
|
||||
unrelated = self.finding(60, "<vector>")
|
||||
(failed, _, failing, fixed), calls = self.check(
|
||||
change, [(1, "", [orphaned, unrelated]), (1, "", [orphaned]), (0, "", [])], fix_writes="#include <libslic3r/Point.hpp>\n")
|
||||
self.assertEqual(calls, [(None, []), ([[4, 4], [50, 50]], ["--fix"]), (None, [])])
|
||||
self.assertEqual((failed, failing, fixed), (False, [], True))
|
||||
|
||||
def test_a_file_the_fix_did_not_change_keeps_its_findings(self):
|
||||
change = clang_tidy_diff.FileChange(lines=[[4, 4]])
|
||||
error = clang_tidy_diff.Diagnostic(self.path, 4, 1, "error", "unknown type name 'Foo' [clang-diagnostic-error]")
|
||||
(failed, _, failing, fixed), calls = self.check(change, [(1, "", [error])])
|
||||
self.assertEqual(calls, [([[4, 4]], ["--fix"])])
|
||||
self.assertEqual((failed, failing, fixed), (True, [error], False))
|
||||
|
||||
def test_a_changed_file_is_checked_again_and_reports_what_is_left(self):
|
||||
change = clang_tidy_diff.FileChange(lines=[[4, 4]])
|
||||
error = clang_tidy_diff.Diagnostic(self.path, 4, 1, "error", "unknown type name 'Foo' [clang-diagnostic-error]")
|
||||
(failed, _, failing, fixed), calls = self.check(
|
||||
change, [(1, "", [self.finding(4, "<vector>"), error]), (1, "", [error])], fix_writes="#include <vector>\n")
|
||||
self.assertEqual(calls, [([[4, 4]], ["--fix"]), ([[4, 4]], [])])
|
||||
self.assertEqual((failed, failing, fixed), (True, [error], True))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
@@ -126,13 +126,6 @@
|
||||
</array>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.10</string>
|
||||
<key>NSLocalNetworkUsageDescription</key>
|
||||
<string>OrcaSlicer uses your local network to discover and connect to printers.</string>
|
||||
<key>NSBonjourServices</key>
|
||||
<array>
|
||||
<string>_octoprint._tcp</string>
|
||||
<string>_http._tcp</string>
|
||||
</array>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
|
||||
@@ -352,6 +352,16 @@ void FillSpiralInset::_fill_surface_single(const FillParams& params,
|
||||
assert(params.use_arachne);
|
||||
assert(this->print_config != nullptr && this->print_object_config != nullptr);
|
||||
|
||||
// Internal solid infill must not add Arachne's standalone thin walls: one of those walls can
|
||||
// become the extra centre point after the spiral has finished. Top and bottom surfaces keep
|
||||
// Arachne, including the centre plug handled by generate_spiral_insets().
|
||||
if (params.extrusion_role == erSolidInfill) {
|
||||
Polylines polylines;
|
||||
this->_fill_surface_single(params, thickness_layers, direction, expolygon, polylines);
|
||||
append(thick_polylines_out, to_thick_polylines(std::move(polylines), scaled<coord_t>(this->spacing)));
|
||||
return;
|
||||
}
|
||||
|
||||
// Only a solid surface is worth the variable width walls; a sparse one falls back to plain loops.
|
||||
if (params.density <= 0.9999f || params.dont_adjust) {
|
||||
Polylines polylines;
|
||||
|
||||
@@ -751,6 +751,50 @@ template<typename T>
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
// Writes G-code to a file in blocks and records in lines_ends the file offset after every '\n'
|
||||
class GCodeFileWriter
|
||||
{
|
||||
public:
|
||||
GCodeFileWriter(FilePtr& out, const std::string& out_path, std::vector<size_t>& lines_ends, const char* error_message)
|
||||
: m_out(out), m_out_path(out_path), m_lines_ends(lines_ends), m_error_message(error_message)
|
||||
{}
|
||||
~GCodeFileWriter() { assert(m_buffer.empty() || std::uncaught_exceptions() > 0); }
|
||||
|
||||
void append(std::string_view text)
|
||||
{
|
||||
const size_t text_pos = m_file_pos + m_buffer.size();
|
||||
for (size_t i = text.find('\n'); i != std::string_view::npos; i = text.find('\n', i + 1))
|
||||
m_lines_ends.emplace_back(text_pos + i + 1);
|
||||
m_buffer += text;
|
||||
if (m_buffer.size() >= GCodeProcessor::Output_Block_Size)
|
||||
flush();
|
||||
}
|
||||
|
||||
void flush()
|
||||
{
|
||||
if (m_buffer.empty())
|
||||
return;
|
||||
fwrite(m_buffer.data(), 1, m_buffer.size(), m_out.f);
|
||||
if (ferror(m_out.f)) {
|
||||
m_out.close();
|
||||
boost::nowide::remove(m_out_path.c_str());
|
||||
throw Slic3r::RuntimeError(m_error_message);
|
||||
}
|
||||
m_file_pos += m_buffer.size();
|
||||
m_buffer.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
FilePtr& m_out;
|
||||
const std::string& m_out_path;
|
||||
std::vector<size_t>& m_lines_ends;
|
||||
const char* m_error_message;
|
||||
std::string m_buffer;
|
||||
size_t m_file_pos{0};
|
||||
};
|
||||
} // namespace
|
||||
|
||||
// Helper class to modify and export gcode to file
|
||||
class ExportLines
|
||||
{
|
||||
@@ -765,16 +809,6 @@ public:
|
||||
enum class EWriteType { BySize, ByTime };
|
||||
|
||||
private:
|
||||
static void update_lines_ends_and_out_file_pos(const std::string& out_string, std::vector<size_t>& lines_ends, size_t* out_file_pos)
|
||||
{
|
||||
for (size_t i = 0; i < out_string.size(); ++i) {
|
||||
if (out_string[i] == '\n')
|
||||
lines_ends.emplace_back((out_file_pos != nullptr) ? *out_file_pos + i + 1 : i + 1);
|
||||
}
|
||||
if (out_file_pos != nullptr)
|
||||
*out_file_pos += out_string.size();
|
||||
}
|
||||
|
||||
struct LineData
|
||||
{
|
||||
std::string line;
|
||||
@@ -814,12 +848,14 @@ private:
|
||||
EWriteType m_write_type{EWriteType::BySize};
|
||||
// Time machines containing g1 times cache
|
||||
const std::array<GCodeProcessor::TimeMachine, static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count)>& m_machines;
|
||||
// Output file writer
|
||||
GCodeFileWriter& m_writer;
|
||||
// Current time
|
||||
std::array<float, static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count)> m_times{0.0f, 0.0f};
|
||||
// Current size in bytes
|
||||
// Current size of the cache in bytes
|
||||
size_t m_size{0};
|
||||
|
||||
// gcode lines cache
|
||||
// gcode lines cache, used only when writing by time
|
||||
std::deque<LineData> m_lines;
|
||||
size_t m_added_lines_counter{0};
|
||||
// map of gcode line ids from original to final
|
||||
@@ -827,16 +863,16 @@ private:
|
||||
std::vector<std::pair<size_t, size_t>> m_gcode_lines_map;
|
||||
|
||||
size_t m_times_cache_id{0};
|
||||
size_t m_out_file_pos{0};
|
||||
|
||||
public:
|
||||
ExportLines(EWriteType type, const std::array<GCodeProcessor::TimeMachine, static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count)>& machines)
|
||||
ExportLines(EWriteType type, const std::array<GCodeProcessor::TimeMachine, static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count)>& machines, GCodeFileWriter& writer)
|
||||
#ifndef NDEBUG
|
||||
: m_statistics(*this)
|
||||
, m_write_type(type)
|
||||
, m_machines(machines){}
|
||||
, m_machines(machines)
|
||||
, m_writer(writer){}
|
||||
#else
|
||||
: m_write_type(type), m_machines(machines)
|
||||
: m_write_type(type), m_machines(machines), m_writer(writer)
|
||||
{}
|
||||
#endif // NDEBUG
|
||||
|
||||
@@ -890,11 +926,14 @@ public:
|
||||
if (line.empty())
|
||||
return;
|
||||
|
||||
m_lines.push_back({line, m_times});
|
||||
if (m_write_type == EWriteType::ByTime) {
|
||||
m_lines.push_back({line, m_times});
|
||||
#ifndef NDEBUG
|
||||
m_statistics.add_line(line.length());
|
||||
m_statistics.add_line(line.length());
|
||||
#endif // NDEBUG
|
||||
m_size += line.length();
|
||||
m_size += line.length();
|
||||
} else
|
||||
m_writer.append(line);
|
||||
++m_added_lines_counter;
|
||||
if (!ignore_from_move) {
|
||||
assert(!m_gcode_lines_map.empty());
|
||||
@@ -960,65 +999,35 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
// write to file:
|
||||
// m_write_type == EWriteType::ByTime - all lines older than m_time - backtrace_time
|
||||
// m_write_type == EWriteType::BySize - all lines if current size is greater than 65535 bytes
|
||||
void write(FilePtr& out, float backtrace_time, GCodeProcessorResult& result, const std::string& out_path)
|
||||
// when writing by time, pass the cached lines older than m_times[Normal] - backtrace_time to the writer
|
||||
void write(float backtrace_time)
|
||||
{
|
||||
if (m_lines.empty())
|
||||
if (m_write_type != EWriteType::ByTime)
|
||||
return;
|
||||
|
||||
// collect lines to write into a single string
|
||||
std::string out_string;
|
||||
if (!m_lines.empty()) {
|
||||
if (m_write_type == EWriteType::ByTime) {
|
||||
while (m_lines.front().times[Normal] < m_times[Normal] - backtrace_time) {
|
||||
const LineData& data = m_lines.front();
|
||||
out_string += data.line;
|
||||
m_size -= data.line.length();
|
||||
m_lines.pop_front();
|
||||
while (!m_lines.empty() && m_lines.front().times[Normal] < m_times[Normal] - backtrace_time) {
|
||||
const LineData& data = m_lines.front();
|
||||
m_writer.append(data.line);
|
||||
m_size -= data.line.length();
|
||||
m_lines.pop_front();
|
||||
#ifndef NDEBUG
|
||||
m_statistics.remove_line();
|
||||
m_statistics.remove_line();
|
||||
#endif // NDEBUG
|
||||
}
|
||||
} else {
|
||||
if (m_size > 65535) {
|
||||
while (!m_lines.empty()) {
|
||||
out_string += m_lines.front().line;
|
||||
m_lines.pop_front();
|
||||
}
|
||||
m_size = 0;
|
||||
#ifndef NDEBUG
|
||||
m_statistics.remove_all_lines();
|
||||
#endif // NDEBUG
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
write_to_file(out, out_string, result, out_path);
|
||||
update_lines_ends_and_out_file_pos(out_string, result.lines_ends, &m_out_file_pos);
|
||||
}
|
||||
}
|
||||
|
||||
// flush the current content of the cache to file
|
||||
void flush(FilePtr& out, GCodeProcessorResult& result, const std::string& out_path)
|
||||
// flush the current content of the cache and the writer to file
|
||||
void flush()
|
||||
{
|
||||
// collect lines to flush into a single string
|
||||
std::string out_string;
|
||||
while (!m_lines.empty()) {
|
||||
out_string += m_lines.front().line;
|
||||
m_writer.append(m_lines.front().line);
|
||||
m_lines.pop_front();
|
||||
}
|
||||
m_size = 0;
|
||||
#ifndef NDEBUG
|
||||
m_statistics.remove_all_lines();
|
||||
#endif // NDEBUG
|
||||
|
||||
{
|
||||
write_to_file(out, out_string, result, out_path);
|
||||
update_lines_ends_and_out_file_pos(out_string, result.lines_ends, &m_out_file_pos);
|
||||
}
|
||||
m_writer.flush();
|
||||
}
|
||||
|
||||
void synchronize_moves(GCodeProcessorResult& result) const
|
||||
@@ -1051,20 +1060,7 @@ public:
|
||||
|
||||
size_t get_size() const { return m_size; }
|
||||
|
||||
private:
|
||||
void write_to_file(FilePtr& out, const std::string& out_string, GCodeProcessorResult& result, const std::string& out_path)
|
||||
{
|
||||
if (!out_string.empty()) {
|
||||
if (true) {
|
||||
fwrite((const void*) out_string.c_str(), 1, out_string.length(), out.f);
|
||||
if (ferror(out.f)) {
|
||||
out.close();
|
||||
boost::nowide::remove(out_path.c_str());
|
||||
throw Slic3r::RuntimeError("GCode processor post process export failed.\nIs the disk full?");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void reserve(size_t lines_count) { m_gcode_lines_map.reserve(lines_count); }
|
||||
};
|
||||
|
||||
void GCodeProcessor::run_post_process()
|
||||
@@ -1160,8 +1156,13 @@ void GCodeProcessor::run_post_process()
|
||||
last_exported_stop[i] = time_in_minutes(m_time_processor.machines[i].time);
|
||||
}
|
||||
|
||||
m_result.lines_ends.clear();
|
||||
// m_result.lines_ends.emplace_back(std::vector<size_t>());
|
||||
GCodeFileWriter writer(out, out_path, m_result.lines_ends, "GCode processor post process export failed.\nIs the disk full?");
|
||||
ExportLines export_line(m_result.backtrace_enabled ? ExportLines::EWriteType::ByTime : ExportLines::EWriteType::BySize,
|
||||
m_time_processor.machines);
|
||||
m_time_processor.machines, writer);
|
||||
// The line map holds an entry for each line of the file, and the first pass counted them
|
||||
export_line.reserve(m_line_id);
|
||||
|
||||
// replace placeholder lines with the proper final value
|
||||
// gcode_line is in/out parameter, to reduce expensive memory allocation
|
||||
@@ -1535,9 +1536,6 @@ void GCodeProcessor::run_post_process()
|
||||
}
|
||||
};
|
||||
|
||||
m_result.lines_ends.clear();
|
||||
// m_result.lines_ends.emplace_back(std::vector<size_t>());
|
||||
|
||||
// Orca: freshly collect SKIPPABLE ranges each post-process pass. The ranges are stored on the
|
||||
// member (rather than a local) so the injection pass can consume them, hence the clear here to
|
||||
// avoid stale ranges on re-invocation.
|
||||
@@ -1802,7 +1800,7 @@ void GCodeProcessor::run_post_process()
|
||||
|
||||
if (!gcode_line.empty())
|
||||
export_line.append_line(gcode_line);
|
||||
export_line.write(out, 1.1f * max_backtrace_time, m_result, out_path);
|
||||
export_line.write(1.1f * max_backtrace_time);
|
||||
gcode_line.clear();
|
||||
}
|
||||
}
|
||||
@@ -1844,7 +1842,7 @@ void GCodeProcessor::run_post_process()
|
||||
}
|
||||
}
|
||||
|
||||
export_line.flush(out, m_result, out_path);
|
||||
export_line.flush();
|
||||
|
||||
out.close();
|
||||
in.close();
|
||||
@@ -1992,31 +1990,13 @@ void GCodeProcessor::run_second_pass_injection()
|
||||
// The rewrite may shift byte positions (once the injector inserts lines), so rebuild lines_ends from scratch.
|
||||
// With an empty map the scanned '\n' offsets reproduce the current lines_ends exactly.
|
||||
m_result.lines_ends.clear();
|
||||
size_t out_file_pos = 0;
|
||||
|
||||
auto write_out = [&out, &out_path, this, &out_file_pos](std::string& str) {
|
||||
if (str.empty())
|
||||
return;
|
||||
fwrite((const void*) str.c_str(), 1, str.length(), out.f);
|
||||
if (ferror(out.f)) {
|
||||
out.close();
|
||||
boost::nowide::remove(out_path.c_str());
|
||||
throw Slic3r::RuntimeError(std::string("GCode processor pre-heat injection pass failed.\nIs the disk full?\n"));
|
||||
}
|
||||
for (size_t i = 0; i < str.size(); ++i) {
|
||||
if (str[i] == '\n')
|
||||
m_result.lines_ends.emplace_back(out_file_pos + i + 1);
|
||||
}
|
||||
out_file_pos += str.size();
|
||||
str.clear();
|
||||
};
|
||||
GCodeFileWriter writer(out, out_path, m_result.lines_ends, "GCode processor pre-heat injection pass failed.\nIs the disk full?\n");
|
||||
|
||||
// Orca: read/split lines with EOL-preserving semantics (keep the original \r and \n bytes, and
|
||||
// synthesize no trailing newline). This is required for the empty-map identity: normalizing every
|
||||
// line ending to "\n" would not be byte-identical if the finished file used \r\n or lacked a
|
||||
// final newline.
|
||||
std::string gcode_line;
|
||||
std::string export_buffer;
|
||||
unsigned int line_id = 0;
|
||||
auto op_it = inserted_operation_lines.begin();
|
||||
std::vector<char> buffer(65536 * 10, 0);
|
||||
@@ -2058,16 +2038,14 @@ void GCodeProcessor::run_second_pass_injection()
|
||||
}
|
||||
++op_it;
|
||||
}
|
||||
export_buffer += gcode_line;
|
||||
writer.append(gcode_line);
|
||||
gcode_line.clear();
|
||||
if (export_buffer.length() >= 65536)
|
||||
write_out(export_buffer);
|
||||
}
|
||||
}
|
||||
if (eof)
|
||||
break;
|
||||
}
|
||||
write_out(export_buffer);
|
||||
writer.flush();
|
||||
|
||||
out.close();
|
||||
in.close();
|
||||
|
||||
@@ -491,6 +491,9 @@ class Print;
|
||||
static const std::string VFlush_End_Tag;
|
||||
static const std::string External_Purge_Tag;
|
||||
public:
|
||||
// Size of the blocks the post-processing passes write the G-code in
|
||||
static constexpr size_t Output_Block_Size = 65536;
|
||||
|
||||
// Orca: SKIPPABLE region tags, stored as static strings (the FLUSH idiom above) rather than
|
||||
// a CustomETags/CustomTags array. Public so the emission sites (WipeTower / change_filament
|
||||
// path) can reference them single-sourced.
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
namespace Slic3r::Geometry {
|
||||
|
||||
using VD = VoronoiDiagram;
|
||||
using PolygonsSegmentIndexConstIt = std::vector<Arachne::PolygonsSegmentIndex>::const_iterator;
|
||||
using LinesIt = Lines::iterator;
|
||||
using ColoredLinesConstIt = ColoredLines::const_iterator;
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
namespace Slic3r::Geometry {
|
||||
|
||||
using VD = VoronoiDiagram;
|
||||
using PolygonsSegmentIndexConstIt = std::vector<Arachne::PolygonsSegmentIndex>::const_iterator;
|
||||
using LinesIt = Lines::iterator;
|
||||
using ColoredLinesIt = ColoredLines::iterator;
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
#include "libslic3r/Point.hpp"
|
||||
#include "libslic3r/libslic3r.h"
|
||||
|
||||
using VD = Slic3r::Geometry::VoronoiDiagram;
|
||||
|
||||
namespace Slic3r::Geometry {
|
||||
|
||||
// Represent trapezoid Voronoi cell around segment.
|
||||
@@ -19,8 +17,8 @@ template<typename PT> struct SegmentCellRange
|
||||
{
|
||||
const PT source_segment_start_point; // The start point of the source segment of this cell.
|
||||
const PT source_segment_end_point; // The end point of the source segment of this cell.
|
||||
const VD::edge_type *edge_begin = nullptr; // The edge of the Voronoi diagram where the loop around the cell starts.
|
||||
const VD::edge_type *edge_end = nullptr; // The edge of the Voronoi diagram where the loop around the cell ends.
|
||||
const VoronoiDiagram::edge_type *edge_begin = nullptr; // The edge of the Voronoi diagram where the loop around the cell starts.
|
||||
const VoronoiDiagram::edge_type *edge_end = nullptr; // The edge of the Voronoi diagram where the loop around the cell ends.
|
||||
|
||||
SegmentCellRange() = delete;
|
||||
explicit SegmentCellRange(const PT &source_segment_start_point, const PT &source_segment_end_point)
|
||||
@@ -34,8 +32,8 @@ template<typename PT> struct SegmentCellRange
|
||||
template<typename PT> struct PointCellRange
|
||||
{
|
||||
const PT source_point; // The source point of this cell.
|
||||
const VD::edge_type *edge_begin = nullptr; // The edge of the Voronoi diagram where the loop around the cell starts.
|
||||
const VD::edge_type *edge_end = nullptr; // The edge of the Voronoi diagram where the loop around the cell ends.
|
||||
const VoronoiDiagram::edge_type *edge_begin = nullptr; // The edge of the Voronoi diagram where the loop around the cell starts.
|
||||
const VoronoiDiagram::edge_type *edge_end = nullptr; // The edge of the Voronoi diagram where the loop around the cell ends.
|
||||
|
||||
PointCellRange() = delete;
|
||||
explicit PointCellRange(const PT &source_point) : source_point(source_point) {}
|
||||
@@ -46,20 +44,20 @@ template<typename PT> struct PointCellRange
|
||||
class VoronoiUtils
|
||||
{
|
||||
public:
|
||||
static Vec2i64 to_point(const VD::vertex_type *vertex);
|
||||
static Vec2i64 to_point(const VoronoiDiagram::vertex_type *vertex);
|
||||
|
||||
static Vec2i64 to_point(const VD::vertex_type &vertex);
|
||||
static Vec2i64 to_point(const VoronoiDiagram::vertex_type &vertex);
|
||||
|
||||
static bool is_finite(const VD::vertex_type &vertex);
|
||||
static bool is_finite(const VoronoiDiagram::vertex_type &vertex);
|
||||
|
||||
static VD::vertex_type make_rotated_vertex(VD::vertex_type &vertex, double angle);
|
||||
static VoronoiDiagram::vertex_type make_rotated_vertex(VoronoiDiagram::vertex_type &vertex, double angle);
|
||||
|
||||
template<typename SegmentIterator>
|
||||
static typename boost::polygon::enable_if<
|
||||
typename boost::polygon::gtl_if<typename boost::polygon::is_segment_concept<
|
||||
typename boost::polygon::geometry_concept<typename std::iterator_traits<SegmentIterator>::value_type>::type>::type>::type,
|
||||
typename std::iterator_traits<SegmentIterator>::reference>::type
|
||||
get_source_segment(const VD::cell_type &cell, SegmentIterator segment_begin, SegmentIterator segment_end);
|
||||
get_source_segment(const VoronoiDiagram::cell_type &cell, SegmentIterator segment_begin, SegmentIterator segment_end);
|
||||
|
||||
template<typename SegmentIterator>
|
||||
static typename boost::polygon::enable_if<
|
||||
@@ -73,7 +71,7 @@ public:
|
||||
typename boost::polygon::gtl_if<typename boost::polygon::is_segment_concept<
|
||||
typename boost::polygon::geometry_concept<typename std::iterator_traits<SegmentIterator>::value_type>::type>::type>::type,
|
||||
Arachne::PolygonsPointIndex>::type
|
||||
get_source_point_index(const VD::cell_type &cell, SegmentIterator segment_begin, SegmentIterator segment_end);
|
||||
get_source_point_index(const VoronoiDiagram::cell_type &cell, SegmentIterator segment_begin, SegmentIterator segment_end);
|
||||
|
||||
/**
|
||||
* Discretize a parabola based on (approximate) step size.
|
||||
@@ -113,7 +111,7 @@ public:
|
||||
typename boost::polygon::geometry_concept<typename std::iterator_traits<SegmentIterator>::value_type>::type>::type>::type,
|
||||
Geometry::SegmentCellRange<
|
||||
typename boost::polygon::segment_point_type<typename std::iterator_traits<SegmentIterator>::value_type>::type>>::type
|
||||
compute_segment_cell_range(const VD::cell_type &cell, SegmentIterator segment_begin, SegmentIterator segment_end);
|
||||
compute_segment_cell_range(const VoronoiDiagram::cell_type &cell, SegmentIterator segment_begin, SegmentIterator segment_end);
|
||||
|
||||
/**
|
||||
* Compute the range of line segments that surround a cell of the skeletal
|
||||
@@ -140,19 +138,19 @@ public:
|
||||
typename boost::polygon::geometry_concept<typename std::iterator_traits<SegmentIterator>::value_type>::type>::type>::type,
|
||||
Geometry::PointCellRange<
|
||||
typename boost::polygon::segment_point_type<typename std::iterator_traits<SegmentIterator>::value_type>::type>>::type
|
||||
compute_point_cell_range(const VD::cell_type &cell, SegmentIterator segment_begin, SegmentIterator segment_end);
|
||||
compute_point_cell_range(const VoronoiDiagram::cell_type &cell, SegmentIterator segment_begin, SegmentIterator segment_end);
|
||||
|
||||
template<typename T> static bool is_in_range(double value)
|
||||
{
|
||||
return double(std::numeric_limits<T>::lowest()) <= value && value <= double(std::numeric_limits<T>::max());
|
||||
}
|
||||
|
||||
template<typename T> static bool is_in_range(const VD::vertex_type &vertex)
|
||||
template<typename T> static bool is_in_range(const VoronoiDiagram::vertex_type &vertex)
|
||||
{
|
||||
return VoronoiUtils::is_finite(vertex) && is_in_range<T>(vertex.x()) && is_in_range<T>(vertex.y());
|
||||
}
|
||||
|
||||
template<typename T> static bool is_in_range(const VD::edge_type &edge)
|
||||
template<typename T> static bool is_in_range(const VoronoiDiagram::edge_type &edge)
|
||||
{
|
||||
if (edge.vertex0() == nullptr || edge.vertex1() == nullptr)
|
||||
return false;
|
||||
|
||||
@@ -63,6 +63,7 @@ namespace Slic3r { enum class EnforcerBlockerType : int8_t; }
|
||||
|
||||
namespace Slic3r {
|
||||
using boost::polygon::voronoi_diagram;
|
||||
using VD = Geometry::VoronoiDiagram;
|
||||
|
||||
static inline Point mk_point(const Voronoi::VD::vertex_type *point) { return {coord_t(point->x()), coord_t(point->y())}; }
|
||||
|
||||
|
||||
@@ -759,6 +759,59 @@ static void clip_inner_walls_over_top(std::vector<Arachne::VariableWidthLines> &
|
||||
}
|
||||
}
|
||||
|
||||
// ORCA: only_one_wall_top - widest bead of the given walls.
|
||||
static coord_t widest_bead(const std::vector<Arachne::VariableWidthLines> &walls)
|
||||
{
|
||||
coord_t widest = 0;
|
||||
for (const Arachne::VariableWidthLines &group : walls)
|
||||
for (const Arachne::ExtrusionLine &el : group)
|
||||
for (const Arachne::ExtrusionJunction &j : el.junctions)
|
||||
widest = std::max(widest, j.w);
|
||||
return widest;
|
||||
}
|
||||
|
||||
// ORCA: only_one_wall_top - length of the walls running further than tolerance from the reference walls, outside the
|
||||
// excluded area.
|
||||
static double length_off_reference(const std::vector<Arachne::VariableWidthLines> &walls, const Arachne::VariableWidthLines &reference,
|
||||
const ExPolygons &excluded, coord_t tolerance)
|
||||
{
|
||||
auto append_centerlines = [](const Arachne::VariableWidthLines &lines, Polylines &out) {
|
||||
for (const Arachne::ExtrusionLine &el : lines) {
|
||||
if (el.junctions.size() < 2)
|
||||
continue;
|
||||
Polyline ¢erline = out.emplace_back();
|
||||
centerline.points.reserve(el.junctions.size());
|
||||
for (const Arachne::ExtrusionJunction &j : el.junctions)
|
||||
centerline.points.emplace_back(j.p);
|
||||
}
|
||||
};
|
||||
Polylines wall_centerlines;
|
||||
Polylines reference_centerlines;
|
||||
for (const Arachne::VariableWidthLines &group : walls)
|
||||
append_centerlines(group, wall_centerlines);
|
||||
append_centerlines(reference, reference_centerlines);
|
||||
|
||||
Polylines off_reference = diff_pl(wall_centerlines, offset(reference_centerlines, float(tolerance)));
|
||||
if (! excluded.empty())
|
||||
off_reference = diff_pl(off_reference, excluded);
|
||||
return total_length(off_reference);
|
||||
}
|
||||
|
||||
// ORCA: only_one_wall_top - area covered by the given walls at their local widths.
|
||||
static Polygons walls_footprint(const Arachne::VariableWidthLines &walls)
|
||||
{
|
||||
Polygons footprint;
|
||||
for (const Arachne::ExtrusionLine &el : walls)
|
||||
for (size_t i = 1; i < el.junctions.size(); ++ i) {
|
||||
const Arachne::ExtrusionJunction &a = el.junctions[i - 1];
|
||||
const Arachne::ExtrusionJunction &b = el.junctions[i];
|
||||
const coord_t width = std::max(a.w, b.w);
|
||||
if (width > 0)
|
||||
append(footprint, offset(Polyline(a.p, b.p), float(width) / 2.f));
|
||||
}
|
||||
return union_(footprint);
|
||||
}
|
||||
|
||||
void PerimeterGenerator::split_top_surfaces(const ExPolygons &orig_polygons, ExPolygons &top_fills,
|
||||
ExPolygons &non_top_polygons, ExPolygons &fill_clip) const {
|
||||
// other perimeters
|
||||
@@ -2546,44 +2599,90 @@ void PerimeterGenerator::process_arachne()
|
||||
if (inner_loop_number >= 0) {
|
||||
assert(upper_slices != nullptr);
|
||||
|
||||
// Infill contour bounding box.
|
||||
BoundingBox infill_contour_bbox = get_extents(infill_contour);
|
||||
infill_contour_bbox.offset(SCALED_EPSILON);
|
||||
|
||||
coord_t perimeter_width = this->perimeter_flow.scaled_width();
|
||||
|
||||
// Get top ExPolygons from current infill contour.
|
||||
Polygons upper_slices_clipped;
|
||||
if (object_config->interface_shells) {
|
||||
auto upper_slicer_same_region = to_expolygons(this->upper_slices_same_region->surfaces);
|
||||
upper_slices_clipped = ClipperUtils::clip_clipper_polygons_with_subject_bbox(upper_slicer_same_region, infill_contour_bbox);
|
||||
} else
|
||||
upper_slices_clipped = ClipperUtils::clip_clipper_polygons_with_subject_bbox(*upper_slices, infill_contour_bbox);
|
||||
// Filter out areas that are too thin and expand top surface polygons a bit to hide the wall line.
|
||||
// ORCA: skip if the top surface area is smaller than "min_width_top_surface"
|
||||
const float top_surface_min_width = std::max<float>(float(ext_perimeter_spacing) / 4.f + scaled<float>(0.00001), float(scale_(config->min_width_top_surface.get_abs_value(unscale_(perimeter_width)))) / 4.f);
|
||||
|
||||
top_expolygons = diff_ex(infill_contour, upper_slices_clipped);
|
||||
// Get top ExPolygons from the given contour. uncovered reports whether the upper layer leaves any of the
|
||||
// contour uncovered, before bridges and too thin areas are filtered out.
|
||||
auto get_top_expolygons = [&](const ExPolygons &contour, bool &uncovered) {
|
||||
// Contour bounding box.
|
||||
BoundingBox contour_bbox = get_extents(contour);
|
||||
contour_bbox.offset(SCALED_EPSILON);
|
||||
|
||||
Polygons upper_slices_clipped;
|
||||
if (object_config->interface_shells) {
|
||||
auto upper_slicer_same_region = to_expolygons(this->upper_slices_same_region->surfaces);
|
||||
upper_slices_clipped = ClipperUtils::clip_clipper_polygons_with_subject_bbox(upper_slicer_same_region, contour_bbox);
|
||||
} else
|
||||
upper_slices_clipped = ClipperUtils::clip_clipper_polygons_with_subject_bbox(*upper_slices, contour_bbox);
|
||||
|
||||
ExPolygons top = diff_ex(contour, upper_slices_clipped);
|
||||
uncovered = !top.empty();
|
||||
if (top.empty())
|
||||
return top;
|
||||
|
||||
if (!top_expolygons.empty()) {
|
||||
if (lower_slices != nullptr) {
|
||||
const float bridge_offset = float(std::max<coord_t>(ext_perimeter_spacing, perimeter_width));
|
||||
const Polygons lower_slices_clipped = ClipperUtils::clip_clipper_polygons_with_subject_bbox(*lower_slices, infill_contour_bbox);
|
||||
const ExPolygons current_slices_bridges = offset_ex(diff_ex(top_expolygons, lower_slices_clipped), bridge_offset);
|
||||
const Polygons lower_slices_clipped = ClipperUtils::clip_clipper_polygons_with_subject_bbox(*lower_slices, contour_bbox);
|
||||
const ExPolygons current_slices_bridges = offset_ex(diff_ex(top, lower_slices_clipped), bridge_offset);
|
||||
|
||||
// Remove bridges from top surface polygons.
|
||||
top_expolygons = diff_ex(top_expolygons, current_slices_bridges);
|
||||
top = diff_ex(top, current_slices_bridges);
|
||||
}
|
||||
|
||||
// Filter out areas that are too thin and expand top surface polygons a bit to hide the wall line.
|
||||
// ORCA: skip if the top surface area is smaller than "min_width_top_surface"
|
||||
const float top_surface_min_width = std::max<float>(float(ext_perimeter_spacing) / 4.f + scaled<float>(0.00001), float(scale_(config->min_width_top_surface.get_abs_value(unscale_(perimeter_width)))) / 4.f);
|
||||
// Shrink the polygon to remove the small areas, then expand it back out plus a maragin to hide the wall line a little.
|
||||
// ORCA: Expand the polygon with half the perimeter width in addition to the contracted amount,
|
||||
// not the full perimeter width as PS does, to enable thin lettering to print on the top surface without nozzle collisions
|
||||
// due to thin lines being generated
|
||||
top_expolygons = offset2_ex(top_expolygons, -top_surface_min_width, top_surface_min_width + float(perimeter_width * 0.85));
|
||||
top = offset2_ex(top, -top_surface_min_width, top_surface_min_width + float(perimeter_width * 0.85));
|
||||
|
||||
// Get final top ExPolygons (bridges were excluded above, so they stay walled).
|
||||
top_expolygons = intersection_ex(top_expolygons, infill_contour);
|
||||
return intersection_ex(top, contour);
|
||||
};
|
||||
|
||||
// Walls with the full count, as generated when the single perimeter feature is disabled. Generated on first use.
|
||||
std::vector<Arachne::VariableWidthLines> full_perimeters;
|
||||
Polygons full_inner_contour;
|
||||
bool full_perimeters_generated = false;
|
||||
auto generate_full_perimeters = [&]() {
|
||||
if (full_perimeters_generated)
|
||||
return;
|
||||
Arachne::WallToolPaths full_tool_paths(last_p, bead_width_0, perimeter_spacing, coord_t(inner_loop_number + 2), wall_0_inset, layer_height, input_params_tmp);
|
||||
full_perimeters = full_tool_paths.getToolPaths();
|
||||
full_inner_contour = full_tool_paths.getInnerContour();
|
||||
full_perimeters_generated = true;
|
||||
};
|
||||
|
||||
// ORCA: the single wall pass allows Arachne 2 beads across a wall, so it fills a wall narrower than 3 outer wall
|
||||
// widths by widening both, where the full pass adds a middle bead. Over the top surface that is the intent;
|
||||
// anywhere else it leaves no room for the inner walls. When the single wall pass's outer walls run away from
|
||||
// the full pass's outside the top surface, take the full pass's outer walls and the area inside them instead.
|
||||
// Walls closer than outer_wall_tolerance count as the same wall: a widened bead's centerline moves by half
|
||||
// the width added, and only beads widened by more than twice the tolerance are looked for.
|
||||
const coord_t outer_wall_tolerance = bead_width_0 / 10;
|
||||
if (widest_bead(perimeters) > bead_width_0 + 2 * outer_wall_tolerance) {
|
||||
// The single wall pass's inner contour where it widens no bead: inside nominal width outer walls.
|
||||
const ExPolygons nominal_infill_contour = offset_ex(last, -float(bead_width_0 + wall_0_inset));
|
||||
bool nominal_uncovered = false;
|
||||
// Grown by an outer wall width to take in the outer walls bordering the top surface.
|
||||
const ExPolygons top_zone = offset_ex(get_top_expolygons(nominal_infill_contour, nominal_uncovered), float(bead_width_0));
|
||||
if (nominal_uncovered) {
|
||||
generate_full_perimeters();
|
||||
if (! full_perimeters.empty() && ! full_perimeters.front().empty() &&
|
||||
length_off_reference(perimeters, full_perimeters.front(), top_zone, outer_wall_tolerance) > double(perimeter_width)) {
|
||||
perimeters = { full_perimeters.front() };
|
||||
infill_contour = diff_ex(nominal_infill_contour, walls_footprint(full_perimeters.front()), ApplySafetyOffset::Yes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool uncovered = false;
|
||||
top_expolygons = get_top_expolygons(infill_contour, uncovered);
|
||||
|
||||
if (uncovered) {
|
||||
// ORCA: onion the real region (inside the outer wall) so the remaining walls follow the actual
|
||||
// geometry, then cut away the parts over the top surface. Re-onioning the non-top complement
|
||||
// instead - the fallback when there is no top fill - walls the top/non-top interface and rings
|
||||
@@ -2612,11 +2711,11 @@ void PerimeterGenerator::process_arachne()
|
||||
perimeters.insert(perimeters.end(), inner_perimeters.begin(), inner_perimeters.end());
|
||||
infill_contour = union_ex(top_expolygons, inner_wall_tool_paths.getInnerContour());
|
||||
} else {
|
||||
// There is no top surface ExPolygon, so we call Arachne again with parameters
|
||||
// like when the single perimeter feature is disabled.
|
||||
Arachne::WallToolPaths no_single_perimeter_tool_paths(last_p, bead_width_0, perimeter_spacing, coord_t(inner_loop_number + 2), wall_0_inset, layer_height, input_params_tmp);
|
||||
perimeters = no_single_perimeter_tool_paths.getToolPaths();
|
||||
infill_contour = union_ex(no_single_perimeter_tool_paths.getInnerContour());
|
||||
// There is no top surface ExPolygon, so use the walls generated like when the single perimeter
|
||||
// feature is disabled.
|
||||
generate_full_perimeters();
|
||||
perimeters = std::move(full_perimeters);
|
||||
infill_contour = union_ex(full_inner_contour);
|
||||
}
|
||||
}
|
||||
//PS
|
||||
|
||||
+38
-111
@@ -80,6 +80,8 @@
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
// Mark string for localization and translate.
|
||||
#define L(s) Slic3r::I18N::translate(s)
|
||||
|
||||
@@ -3813,11 +3815,7 @@ void PresetBundle::get_ams_cobox_infos(AMSComboInfo& combox_info)
|
||||
auto ams_name = ams.opt_string("tray_name", 0u);
|
||||
auto filament_changed = !ams.has("filament_changed") || ams.opt_bool("filament_changed");
|
||||
auto filament_multi_color = ams.opt<ConfigOptionStrings>("filament_multi_colour")->values;
|
||||
auto filament_type = ams.opt_string("filament_type", 0u);
|
||||
auto is_placeholder = ams.has("filament_slot_placeholder") && ams.opt_bool("filament_slot_placeholder", 0u);
|
||||
// A printer-set tray carries a material type but no preset id; resolve it to the
|
||||
// matching Generic preset so it is not dropped and the combo array keeps aligning.
|
||||
if (filament_id.empty() && (is_placeholder || filament_type.empty())) {
|
||||
if (filament_id.empty()) {
|
||||
continue;
|
||||
}
|
||||
if (!filament_changed && this->filament_presets.size() > combox_info.ams_filament_presets.size()) {
|
||||
@@ -3827,48 +3825,16 @@ void PresetBundle::get_ams_cobox_infos(AMSComboInfo& combox_info)
|
||||
combox_info.ams_names.push_back(ams_name);
|
||||
continue;
|
||||
}
|
||||
auto iter = filaments.end();
|
||||
if (!filament_id.empty()) {
|
||||
iter = std::find_if(filaments.begin(), filaments.end(),
|
||||
[this, &filament_id](auto &f) { return f.is_compatible && filaments.get_preset_base(f) == &f && f.filament_id == filament_id; });
|
||||
warn_ambiguous_filament_id_match(filaments, iter, filament_id);
|
||||
}
|
||||
auto iter = std::find_if(filaments.begin(), filaments.end(),
|
||||
[this, &filament_id](auto &f) { return f.is_compatible && filaments.get_preset_base(f) == &f && f.filament_id == filament_id; });
|
||||
warn_ambiguous_filament_id_match(filaments, iter, filament_id);
|
||||
if (iter == filaments.end()) {
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": filament_id %1% not found or system or compatible") % filament_id;
|
||||
auto filament_type = ams.opt_string("filament_type", 0u);
|
||||
if (!filament_type.empty()) {
|
||||
auto original_type = filament_type;
|
||||
filament_type = "Generic " + filament_type;
|
||||
iter = std::find_if(filaments.begin(), filaments.end(),
|
||||
[&filament_type](auto &f) { return f.is_compatible && f.is_system && boost::algorithm::starts_with(f.name, filament_type); });
|
||||
if (iter == filaments.end()) {
|
||||
// Similarity fallback: find a generic preset whose filament_type
|
||||
// appears as a whole word in the AMS type (e.g. "ASA" in "ASA Sparkle").
|
||||
auto upper_type = boost::to_upper_copy(original_type);
|
||||
auto contains_word = [](const std::string& haystack, const std::string& needle) {
|
||||
auto pos = haystack.find(needle);
|
||||
while (pos != std::string::npos) {
|
||||
bool start_ok = (pos == 0 || !std::isalnum(static_cast<unsigned char>(haystack[pos - 1])));
|
||||
bool end_ok = (pos + needle.size() >= haystack.size() ||
|
||||
!std::isalnum(static_cast<unsigned char>(haystack[pos + needle.size()])));
|
||||
if (start_ok && end_ok)
|
||||
return true;
|
||||
pos = haystack.find(needle, pos + 1);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
// Find the longest-matching preset type to prefer e.g. "PA-CF" over "PA".
|
||||
size_t best_len = 0;
|
||||
for (auto it = filaments.begin(); it != filaments.end(); ++it) {
|
||||
if (!it->is_compatible || !it->is_system || !boost::algorithm::starts_with(it->name, "Generic "))
|
||||
continue;
|
||||
auto preset_type = boost::to_upper_copy(it->config.opt_string("filament_type", 0u));
|
||||
if (preset_type.size() > best_len && contains_word(upper_type, preset_type)) {
|
||||
iter = it;
|
||||
best_len = preset_type.size();
|
||||
filament_type = "Generic " + it->config.opt_string("filament_type", 0u);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (iter == filaments.end()) {
|
||||
// Prefer old selection
|
||||
@@ -3879,11 +3845,7 @@ void PresetBundle::get_ams_cobox_infos(AMSComboInfo& combox_info)
|
||||
combox_info.ams_names.push_back(ams_name);
|
||||
continue;
|
||||
}
|
||||
iter = std::find_if(filaments.begin(), filaments.end(), [](auto &f) {
|
||||
return f.is_compatible && f.is_system && boost::algorithm::starts_with(f.name, "Generic ");
|
||||
});
|
||||
if (iter == filaments.end())
|
||||
iter = std::find_if(filaments.begin(), filaments.end(), [](auto &f) { return f.is_compatible && f.is_system; });
|
||||
iter = std::find_if(filaments.begin(), filaments.end(), [](auto &f) { return f.is_compatible && f.is_system; });
|
||||
if (iter == filaments.end())
|
||||
continue;
|
||||
}
|
||||
@@ -3921,7 +3883,6 @@ unsigned int PresetBundle::sync_ams_list(std::vector<std::pair<DynamicPrintConfi
|
||||
for (auto &entry : filament_ams_list) {
|
||||
auto & ams = entry.second;
|
||||
auto filament_id = ams.opt_string("filament_id", 0u);
|
||||
const bool printer_set_tray = filament_id.empty();
|
||||
auto filament_color = ams.opt_string("filament_colour", 0u);
|
||||
auto filament_color_type = ams.opt_string("filament_colour_type", 0u);
|
||||
auto filament_changed = !ams.has("filament_changed") || ams.opt_bool("filament_changed");
|
||||
@@ -3934,58 +3895,42 @@ unsigned int PresetBundle::sync_ams_list(std::vector<std::pair<DynamicPrintConfi
|
||||
ams_array_maps.push_back(temp);
|
||||
index++;
|
||||
if (filament_id.empty()) {
|
||||
// A tray written by the printer UI carries a material type but no
|
||||
// OrcaSlicer preset id. Resolve it to the matching Generic preset with
|
||||
// the tray's own color instead of dropping it (direct sync) or forcing
|
||||
// "Generic PLA" (mapping sync). Placeholders and typeless trays keep
|
||||
// the previous behavior.
|
||||
const auto tray_type = ams.opt_string("filament_type", 0u);
|
||||
if (is_placeholder || tray_type.empty()) {
|
||||
if (use_map) {
|
||||
for (int j = maps.size() - 1; j >= 0; j--) {
|
||||
if (maps[j].slot_id == slot_id && maps[j].ams_id == ams_id) {
|
||||
maps.erase(j);
|
||||
}
|
||||
if (use_map) {
|
||||
for (int j = maps.size() - 1; j >= 0; j--) {
|
||||
if (maps[j].slot_id == slot_id && maps[j].ams_id == ams_id) {
|
||||
maps.erase(j);
|
||||
}
|
||||
ams_filament_presets.push_back("Generic PLA");//for unknow matieral
|
||||
auto default_unknown_color = "#CECECE";
|
||||
ams_filament_colors.push_back(default_unknown_color);
|
||||
ams_filament_color_types.push_back("1");
|
||||
if (filament_multi_color.size() == 0) {
|
||||
filament_multi_color.push_back(default_unknown_color);
|
||||
}
|
||||
ams_multi_color_filment.push_back(filament_multi_color);
|
||||
} else if (is_placeholder) {
|
||||
// Orca: push placeholders to keep index alignment with ams_infos
|
||||
ams_filament_presets.push_back("");
|
||||
ams_filament_colors.push_back("");
|
||||
ams_filament_color_types.push_back("");
|
||||
ams_multi_color_filment.push_back({});
|
||||
}
|
||||
continue;
|
||||
ams_filament_presets.push_back("Generic PLA");//for unknow matieral
|
||||
auto default_unknown_color = "#CECECE";
|
||||
ams_filament_colors.push_back(default_unknown_color);
|
||||
ams_filament_color_types.push_back("1");
|
||||
if (filament_multi_color.size() == 0) {
|
||||
filament_multi_color.push_back(default_unknown_color);
|
||||
}
|
||||
ams_multi_color_filment.push_back(filament_multi_color);
|
||||
} else if (is_placeholder) {
|
||||
// Orca: push placeholders to keep index alignment with ams_infos
|
||||
ams_filament_presets.push_back("");
|
||||
ams_filament_colors.push_back("");
|
||||
ams_filament_color_types.push_back("");
|
||||
ams_multi_color_filment.push_back({});
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!filament_changed && this->filament_presets.size() > ams_filament_presets.size()) {
|
||||
ams_filament_presets.push_back(this->filament_presets[ams_filament_presets.size()]);
|
||||
ams_filament_colors.push_back(filament_color);
|
||||
ams_filament_color_types.push_back(filament_color_type);
|
||||
ams_multi_color_filment.push_back(filament_multi_color);
|
||||
ams_infos.back().valid = true;
|
||||
continue;
|
||||
}
|
||||
bool has_type = false;
|
||||
auto filament_type = ams.opt_string("filament_type", 0u);
|
||||
auto iter = filaments.end();
|
||||
if (!filament_id.empty()) {
|
||||
iter = std::find_if(filaments.begin(), filaments.end(), [this, &filament_id, &has_type, filament_type](auto &f) {
|
||||
has_type |= f.config.opt_string("filament_type", 0u) == filament_type;
|
||||
return f.is_compatible && filaments.get_preset_base(f) == &f && f.filament_id == filament_id; });
|
||||
warn_ambiguous_filament_id_match(filaments, iter, filament_id);
|
||||
} else {
|
||||
// The material type is the only identity a printer-set tray carries.
|
||||
has_type = std::any_of(filaments.begin(), filaments.end(), [&filament_type](auto &f) {
|
||||
return f.is_compatible && f.config.opt_string("filament_type", 0u) == filament_type; });
|
||||
}
|
||||
auto iter = std::find_if(filaments.begin(), filaments.end(), [this, &filament_id, &has_type, filament_type](auto &f) {
|
||||
has_type |= f.config.opt_string("filament_type", 0u) == filament_type;
|
||||
return f.is_compatible && filaments.get_preset_base(f) == &f && f.filament_id == filament_id; });
|
||||
warn_ambiguous_filament_id_match(filaments, iter, filament_id);
|
||||
if (iter == filaments.end()) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": filament_id %1% not found or system or compatible") % filament_id;
|
||||
if (!filament_type.empty()) {
|
||||
@@ -4025,7 +3970,6 @@ unsigned int PresetBundle::sync_ams_list(std::vector<std::pair<DynamicPrintConfi
|
||||
}
|
||||
}
|
||||
}
|
||||
const bool resolved_by_material_type = printer_set_tray && iter != filaments.end();
|
||||
if (iter == filaments.end()) {
|
||||
// Prefer old selection
|
||||
if (ams_filament_presets.size() < this->filament_presets.size()) {
|
||||
@@ -4033,7 +3977,6 @@ unsigned int PresetBundle::sync_ams_list(std::vector<std::pair<DynamicPrintConfi
|
||||
ams_filament_colors.push_back(filament_color);
|
||||
ams_filament_color_types.push_back(filament_color_type);
|
||||
ams_multi_color_filment.push_back(filament_multi_color);
|
||||
ams_infos.back().valid = true;
|
||||
unknowns.emplace_back(&ams, has_type ? L("The filament may not be compatible with the current machine settings. Generic filament presets will be used.") :
|
||||
L("The filament model is unknown. Still using the previous filament preset."));
|
||||
continue;
|
||||
@@ -4049,8 +3992,7 @@ unsigned int PresetBundle::sync_ams_list(std::vector<std::pair<DynamicPrintConfi
|
||||
if (iter == filaments.end())
|
||||
continue;
|
||||
}
|
||||
if (!resolved_by_material_type)
|
||||
unknowns.emplace_back(&ams, boost::algorithm::starts_with(iter->name, filament_type) ?
|
||||
unknowns.emplace_back(&ams, boost::algorithm::starts_with(iter->name, filament_type) ?
|
||||
(has_type ? L("The filament may not be compatible with the current machine settings. Generic filament presets will be used.") :
|
||||
L("The filament model is unknown. Generic filament presets will be used.")) :
|
||||
(has_type ? L("The filament may not be compatible with the current machine settings. A random filament preset will be used.") :
|
||||
@@ -4061,7 +4003,6 @@ unsigned int PresetBundle::sync_ams_list(std::vector<std::pair<DynamicPrintConfi
|
||||
ams_filament_colors.push_back(filament_color);
|
||||
ams_filament_color_types.push_back(filament_color_type);
|
||||
ams_multi_color_filment.push_back(filament_multi_color);
|
||||
ams_infos.back().valid = true;
|
||||
}
|
||||
if (ams_filament_presets.empty())
|
||||
return 0;
|
||||
@@ -4501,21 +4442,9 @@ std::vector<std::vector<DynamicPrintConfig>> PresetBundle::get_extruder_filament
|
||||
return filament_infos;
|
||||
}
|
||||
|
||||
std::string PresetBundle::get_printer_model_display_name(const std::string &model_id) const
|
||||
{
|
||||
if (model_id.empty())
|
||||
return {};
|
||||
for (const auto &vendor_entry : vendors) {
|
||||
for (const auto &model : vendor_entry.second.models) {
|
||||
if (model.model_id == model_id)
|
||||
return model.name;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
// ORCA TODO: this assumes printer names follow "<printer_model> <nozzle_diameter>", e.g.
|
||||
// "Bambu Lab X2D 0.4 nozzle". Other naming schemes may not resolve correctly.
|
||||
// ORCA TODO: currently, this function assumes the printer name follows the pattern of "<printer_model> <nozzle_diameter>", e.g.
|
||||
// printer_type: "Bambu Lab X2D", nozzle_diameter_str: "0.4 nozzle" => printer_name: "Bambu Lab X2D 0.4 nozzle". If the printer name does
|
||||
// not follow this pattern, the function may not work correctly.
|
||||
std::set<std::string> PresetBundle::get_printer_names_by_printer_type_and_nozzle(const std::string &printer_type, std::string nozzle_diameter_str, bool system_only)
|
||||
{
|
||||
std::set<std::string> printer_names;
|
||||
@@ -4537,9 +4466,7 @@ std::set<std::string> PresetBundle::get_printer_names_by_printer_type_and_nozzle
|
||||
if (printer_it->name.find(nozzle_diameter_str) != std::string::npos) printer_names.insert(printer_it->name);
|
||||
}
|
||||
|
||||
// No match is normal for a connected machine the user has not installed; only an
|
||||
// ambiguous match is a bug (the caller assumes one preset per model and nozzle).
|
||||
assert(printer_names.size() <= 1);
|
||||
assert(printer_names.size() == 1);
|
||||
|
||||
for (auto& printer_name : printer_names) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " " << __LINE__ << " printer name: " << printer_name;
|
||||
@@ -4552,8 +4479,8 @@ std::vector<Preset *> PresetBundle::get_filament_presets_for_machine(const std::
|
||||
const std::string &nozzle_diameter_str,
|
||||
bool include_user_presets)
|
||||
{
|
||||
// Printer model plus nozzle diameter normally resolves to a single system printer preset.
|
||||
// Zero matches is normal for a connected machine the user never installed.
|
||||
// Printer model plus nozzle diameter is expected to resolve to a single system printer preset;
|
||||
// get_printer_names_by_printer_type_and_nozzle asserts as much in debug builds.
|
||||
const std::set<std::string> printer_names = get_printer_names_by_printer_type_and_nozzle(printer_type, nozzle_diameter_str);
|
||||
const Preset *printer = printer_names.empty() ? nullptr : printers.find_preset(*printer_names.begin());
|
||||
if (printer == nullptr)
|
||||
|
||||
@@ -411,9 +411,6 @@ public:
|
||||
|
||||
std::vector<std::vector<DynamicPrintConfig>> get_extruder_filament_info() const;
|
||||
|
||||
// Resolve a vendor model id (an agent-reported machine identity) to the display name
|
||||
// printer profiles use as printer_model. Empty when no loaded vendor declares it.
|
||||
std::string get_printer_model_display_name(const std::string &model_id) const;
|
||||
std::set<std::string> get_printer_names_by_printer_type_and_nozzle(const std::string &printer_type, std::string nozzle_diameter_str, bool system_only = true);
|
||||
// Orca: the root filament presets a connected machine can use, resolved with the rule the rest
|
||||
// of the app applies (is_compatible_with_printer): an empty compatible_printers means every
|
||||
|
||||
@@ -11,8 +11,6 @@
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class BBLProject;
|
||||
@@ -208,7 +206,7 @@ public:
|
||||
std::string task_profile_id; /* profile id*/
|
||||
std::string task_name; /* task name, generally filename as task name */
|
||||
std::string task_file; /* local full file path of 3mf or gcode */
|
||||
fs::path task_path; /* local path of 3mf or gcode */
|
||||
boost::filesystem::path task_path; /* local path of 3mf or gcode */
|
||||
std::string task_gcode_in_3mf; /* gcode in 3mf */
|
||||
std::string task_create_time; /* time created by cloud */
|
||||
std::string task_thumbnail_url; /* url of task thumbnail */
|
||||
@@ -326,7 +324,7 @@ public:
|
||||
std::string project_url_md5; /* md5 of project url file */
|
||||
std::string project_name;
|
||||
std::string project_3mf_file;
|
||||
fs::path project_path;
|
||||
boost::filesystem::path project_path;
|
||||
std::string project_content;
|
||||
std::string project_country_code;
|
||||
|
||||
|
||||
@@ -368,10 +368,6 @@ set(SLIC3R_GUI_SOURCES
|
||||
GUI/MarkdownTip.hpp
|
||||
GUI/MediaFilePanel.cpp
|
||||
GUI/MediaFilePanel.h
|
||||
GUI/OrcaFilesPanel.cpp
|
||||
GUI/OrcaFilesPanel.h
|
||||
GUI/StoragePanel.cpp
|
||||
GUI/StoragePanel.h
|
||||
GUI/MediaPlayCtrl.cpp
|
||||
GUI/MediaPlayCtrl.h
|
||||
GUI/WebRtcMediaController.cpp
|
||||
@@ -461,11 +457,6 @@ set(SLIC3R_GUI_SOURCES
|
||||
GUI/PresetHints.hpp
|
||||
GUI/PrinterCloudAuthDialog.cpp
|
||||
GUI/PrinterCloudAuthDialog.hpp
|
||||
GUI/Printer/BambuFileGridModel.cpp
|
||||
GUI/Printer/BambuFileGridModel.h
|
||||
GUI/Printer/IFileGridModel.h
|
||||
GUI/Printer/RemoteFileGridModel.cpp
|
||||
GUI/Printer/RemoteFileGridModel.h
|
||||
GUI/Printer/PrinterFileSystem.cpp
|
||||
GUI/Printer/PrinterFileSystem.h
|
||||
GUI/PrinterWebView.cpp
|
||||
@@ -781,12 +772,8 @@ set(SLIC3R_GUI_SOURCES
|
||||
Utils/ICameraSignalingChannel.hpp
|
||||
Utils/OrcaCloudServiceAgent.cpp
|
||||
Utils/OrcaCloudServiceAgent.hpp
|
||||
Utils/OrcaMqttConnection.cpp
|
||||
Utils/OrcaMqttConnection.hpp
|
||||
Utils/OrcaPrinterAgent.cpp
|
||||
Utils/OrcaPrinterAgent.hpp
|
||||
Utils/OrcaCloudSignalingChannel.cpp
|
||||
Utils/OrcaCloudSignalingChannel.hpp
|
||||
Utils/QidiPrinterAgent.cpp
|
||||
Utils/QidiPrinterAgent.hpp
|
||||
Utils/SnapmakerPrinterAgent.cpp
|
||||
@@ -930,7 +917,7 @@ target_include_directories(libslic3r_gui PRIVATE Utils ${CMAKE_CURRENT_BINARY_DI
|
||||
|
||||
if (WIN32)
|
||||
target_include_directories(libslic3r_gui SYSTEM PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../deps/WebView2/include)
|
||||
target_link_libraries(libslic3r_gui Advapi32 Crypt32)
|
||||
target_link_libraries(libslic3r_gui Advapi32)
|
||||
endif()
|
||||
|
||||
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SLIC3R_GUI_SOURCES})
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include "slic3r/GUI/DeviceCore/DevExtruderSystem.h"
|
||||
|
||||
#include "slic3r/GUI/DeviceCore/DevManager.h"
|
||||
#include "slic3r/GUI/DeviceManager.hpp"
|
||||
|
||||
#include "slic3r/GUI/MsgDialog.hpp"
|
||||
|
||||
@@ -1634,16 +1633,8 @@ int AMSDryCtrWin::update_filament_list(DevAms* dev_ams, MachineObject* obj)
|
||||
stream << std::fixed << std::setprecision(1) << obj->GetExtderSystem()->GetNozzleDiameter(extruder_id);
|
||||
std::string nozzle_diameter_str = stream.str();
|
||||
|
||||
// The connected device's model may not resolve (OrcaSonar's is optional); the
|
||||
// helper falls back to the selected profile so the list is never empty.
|
||||
const std::string filament_printer_model = resolve_filament_printer_model(obj->printer_type, preset_bundle);
|
||||
if (filament_printer_model.empty()) {
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << " cannot resolve a printer model for the filament list";
|
||||
return false;
|
||||
}
|
||||
|
||||
for (Preset *filament_it : preset_bundle->get_filament_presets_for_machine(
|
||||
filament_printer_model, nozzle_diameter_str, obj->is_support_user_preset)) {
|
||||
DevPrinterConfigUtil::get_printer_display_name(obj->printer_type), nozzle_diameter_str, obj->is_support_user_preset)) {
|
||||
if (!filament_id_set.insert(filament_it->filament_id).second)
|
||||
continue;
|
||||
const std::string filament_alias = filaments.get_preset_alias(*filament_it, true);
|
||||
|
||||
@@ -4,12 +4,10 @@
|
||||
#include "GUI_App.hpp"
|
||||
#include "GUI.hpp"
|
||||
#include "slic3r/Utils/NetworkAgent.hpp"
|
||||
#include "slic3r/Utils/NetworkAgentFactory.hpp"
|
||||
#include "libslic3r/Preset.hpp"
|
||||
#include "I18N.hpp"
|
||||
#include <algorithm>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <slic3r/GUI/DeviceManager.hpp>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <ios>
|
||||
@@ -474,13 +472,6 @@ void AMSMaterialsSetting::update_filament_editing(bool is_printing)
|
||||
m_button_confirm->Show(true);
|
||||
}
|
||||
|
||||
// A third-party tray owns its temp range; BBL RFID trays keep the read-only preset values.
|
||||
// Only the OrcaSonar agent accepts the temp fields, so other agents stay read-only.
|
||||
const bool is_orca_agent = obj && obj->printer_agent_id == ORCA_PRINTER_AGENT_ID;
|
||||
const bool can_edit = !is_printing || obj->is_support_filament_setting_inprinting;
|
||||
m_input_nozzle_min->Enable(m_is_third && can_edit && is_orca_agent);
|
||||
m_input_nozzle_max->Enable(m_is_third && can_edit && is_orca_agent);
|
||||
|
||||
if (!m_is_third) {
|
||||
m_tip_readonly->SetLabelText(wxEmptyString);
|
||||
m_tip_readonly->Hide();
|
||||
@@ -503,8 +494,6 @@ void AMSMaterialsSetting::update_filament_editing(bool is_printing)
|
||||
if (m_view_only) { // Orca: view-only (2D laser/cut) — lock every edit control and hide apply/reset
|
||||
m_comboBox_filament->Enable(false);
|
||||
m_comboBox_cali_result->Enable(false);
|
||||
m_input_nozzle_min->Enable(false);
|
||||
m_input_nozzle_max->Enable(false);
|
||||
m_input_k_val->Enable(false);
|
||||
m_input_n_val->Enable(false);
|
||||
m_button_confirm->Hide();
|
||||
@@ -554,7 +543,7 @@ void AMSMaterialsSetting::on_select_reset(wxCommandEvent& event) {
|
||||
}
|
||||
|
||||
// set k / n value
|
||||
if (obj->supports_extrusion_cali() && obj->cali_version <= -1 && obj->get_printer_series() == PrinterSeries::SERIES_P1P) {
|
||||
if (obj->cali_version <= -1 && obj->get_printer_series() == PrinterSeries::SERIES_P1P) {
|
||||
// set extrusion cali ratio
|
||||
int cali_tray_id = ams_id * 4 + slot_id;
|
||||
|
||||
@@ -575,7 +564,7 @@ void AMSMaterialsSetting::on_select_reset(wxCommandEvent& event) {
|
||||
}
|
||||
obj->command_extrusion_cali_set(cali_tray_id, "", "", k, n);
|
||||
}
|
||||
else if (obj->supports_extrusion_cali()) {
|
||||
else {
|
||||
PACalibIndexInfo select_index_info;
|
||||
int tray_id = ams_id * 4 + slot_id;
|
||||
if (is_virtual_tray()) {
|
||||
@@ -734,21 +723,6 @@ void AMSMaterialsSetting::on_select_ok(wxCommandEvent &event)
|
||||
return;
|
||||
}
|
||||
|
||||
if (nozzle_temp_min_int < FILAMENT_MIN_TEMP || nozzle_temp_min_int > FILAMENT_MAX_TEMP ||
|
||||
nozzle_temp_max_int < FILAMENT_MIN_TEMP || nozzle_temp_max_int > FILAMENT_MAX_TEMP) {
|
||||
MessageDialog msg_dlg(nullptr,
|
||||
wxString::Format(_L("The input value should be greater than %1% and less than %2%"), FILAMENT_MIN_TEMP, FILAMENT_MAX_TEMP),
|
||||
wxEmptyString, wxICON_WARNING | wxOK);
|
||||
msg_dlg.ShowModal();
|
||||
return;
|
||||
}
|
||||
if (nozzle_temp_min_int > nozzle_temp_max_int) {
|
||||
MessageDialog msg_dlg(nullptr, _L("The minimum temperature cannot be greater than the maximum temperature."),
|
||||
wxEmptyString, wxICON_WARNING | wxOK);
|
||||
msg_dlg.ShowModal();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Orca: log the tray payload this dialog hands the printer, so the filament_id resolved from the
|
||||
// dropdown selection can be checked against the tray_info_idx the AMS actually receives. A
|
||||
@@ -772,7 +746,7 @@ void AMSMaterialsSetting::on_select_ok(wxCommandEvent &event)
|
||||
wxString k_text = m_input_k_val->GetTextCtrl()->GetValue();
|
||||
wxString n_text = m_input_n_val->GetTextCtrl()->GetValue();
|
||||
|
||||
if (obj->supports_extrusion_cali() && obj->cali_version <= -1 && (obj->get_printer_series() != PrinterSeries::SERIES_X1) && !ExtrusionCalibration::check_k_validation(k_text)) {
|
||||
if (obj->cali_version <= -1 && (obj->get_printer_series() != PrinterSeries::SERIES_X1) && !ExtrusionCalibration::check_k_validation(k_text)) {
|
||||
wxString k_tips = wxString::Format(_L("Please input a valid value (K in %.1f~%.1f)"), MIN_PA_K_VALUE, MAX_PA_K_VALUE);
|
||||
wxString kn_tips = wxString::Format(_L("Please input a valid value (K in %.1f~%.1f, N in %.1f~%.1f)"), MIN_PA_K_VALUE, MAX_PA_K_VALUE, 0.6, 2.0);
|
||||
MessageDialog msg_dlg(nullptr, k_tips, wxEmptyString, wxICON_WARNING | wxOK);
|
||||
@@ -802,7 +776,7 @@ void AMSMaterialsSetting::on_select_ok(wxCommandEvent &event)
|
||||
vt_tray = VIRTUAL_TRAY_DEPUTY_ID;
|
||||
}
|
||||
|
||||
if (obj->supports_extrusion_cali() && obj->cali_version >= 0) {
|
||||
if (obj->cali_version >= 0) {
|
||||
PACalibIndexInfo select_index_info;
|
||||
select_index_info.tray_id = vt_tray;
|
||||
select_index_info.ams_id = ams_id;
|
||||
@@ -821,7 +795,7 @@ void AMSMaterialsSetting::on_select_ok(wxCommandEvent &event)
|
||||
|
||||
CalibUtils::select_PA_calib_result(select_index_info);
|
||||
}
|
||||
else if (obj->supports_extrusion_cali()) {
|
||||
else {
|
||||
obj->command_extrusion_cali_set(vt_tray, "", "", k, n);
|
||||
}
|
||||
}
|
||||
@@ -843,7 +817,7 @@ void AMSMaterialsSetting::on_select_ok(wxCommandEvent &event)
|
||||
;
|
||||
}
|
||||
|
||||
if (obj->supports_extrusion_cali() && obj->cali_version >= 0) {
|
||||
if (obj->cali_version >= 0) {
|
||||
PACalibIndexInfo select_index_info;
|
||||
select_index_info.tray_id = cali_tray_id;
|
||||
select_index_info.ams_id = ams_id;
|
||||
@@ -862,7 +836,7 @@ void AMSMaterialsSetting::on_select_ok(wxCommandEvent &event)
|
||||
|
||||
CalibUtils::select_PA_calib_result(select_index_info);
|
||||
}
|
||||
else if (obj->supports_extrusion_cali()) {
|
||||
else {
|
||||
obj->command_extrusion_cali_set(cali_tray_id, "", "", k, n);
|
||||
}
|
||||
}
|
||||
@@ -958,12 +932,7 @@ bool AMSMaterialsSetting::is_virtual_tray()
|
||||
|
||||
void AMSMaterialsSetting::update_widgets()
|
||||
{
|
||||
if (obj && !obj->supports_extrusion_cali()) {
|
||||
// No printer-side K/N records: do not offer them.
|
||||
m_panel_normal->Show();
|
||||
m_panel_kn->Hide();
|
||||
}
|
||||
else if (obj && obj->get_printer_series() == PrinterSeries::SERIES_X1 && obj->cali_version <= -1) {
|
||||
if (obj && obj->get_printer_series() == PrinterSeries::SERIES_X1 && obj->cali_version <= -1) {
|
||||
// Low version firmware does not display k value
|
||||
m_panel_kn->Hide();
|
||||
}
|
||||
@@ -1024,9 +993,6 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi
|
||||
|
||||
m_input_k_val->GetTextCtrl()->SetValue(k);
|
||||
m_input_n_val->GetTextCtrl()->SetValue(n);
|
||||
// Tray values are re-supplied by every caller; clear so a previous popup cannot leak in.
|
||||
m_input_nozzle_min->GetTextCtrl()->SetValue(wxEmptyString);
|
||||
m_input_nozzle_max->GetTextCtrl()->SetValue(wxEmptyString);
|
||||
|
||||
wxArrayString filament_items;
|
||||
wxString bambu_filament_name;
|
||||
@@ -1050,14 +1016,11 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi
|
||||
}
|
||||
stream << std::fixed << std::setprecision(1) << machine_diameter;
|
||||
std::string nozzle_diameter_str = stream.str();
|
||||
// OrcaSonar's model id is optional, so the device model alone can resolve to nothing;
|
||||
// the helper falls back to the selected profile so the dropdown is never empty.
|
||||
const std::string filament_printer_model = resolve_filament_printer_model(obj->printer_type, preset_bundle);
|
||||
|
||||
if (preset_bundle && !filament_printer_model.empty()) {
|
||||
if (preset_bundle) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "system_preset_bundle filament number=" << preset_bundle->filaments.size();
|
||||
for (Preset *filament_it : preset_bundle->get_filament_presets_for_machine(
|
||||
filament_printer_model, nozzle_diameter_str, obj->is_support_user_preset)) {
|
||||
DevPrinterConfigUtil::get_printer_display_name(obj->printer_type), nozzle_diameter_str, obj->is_support_user_preset)) {
|
||||
if (!filament_id_set.insert(filament_it->filament_id).second)
|
||||
continue;
|
||||
const std::string alias = preset_bundle->filaments.get_preset_alias(*filament_it, true);
|
||||
@@ -1124,12 +1087,6 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi
|
||||
else {
|
||||
m_comboBox_filament->Show();
|
||||
m_readonly_filament->Hide();
|
||||
// A printer-set tray carries its own temps; the preset selection only fills
|
||||
// them when the tray has none.
|
||||
if (!temp_min.IsEmpty() && temp_min != "0")
|
||||
m_input_nozzle_min->GetTextCtrl()->SetValue(temp_min);
|
||||
if (!temp_max.IsEmpty() && temp_max != "0")
|
||||
m_input_nozzle_max->GetTextCtrl()->SetValue(temp_max);
|
||||
}
|
||||
|
||||
if (obj->cali_version >= 0) {
|
||||
@@ -1266,12 +1223,7 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi
|
||||
}
|
||||
}
|
||||
|
||||
if (filament_items.IsEmpty())
|
||||
BOOST_LOG_TRIVIAL(warning) << "ams_materials_setting: no filament presets for printer model \""
|
||||
<< filament_printer_model << "\" at nozzle " << nozzle_diameter_str;
|
||||
|
||||
m_comboBox_filament->Set(filament_items);
|
||||
m_comboBox_from_printer = true;
|
||||
m_comboBox_filament->SetSelection(selection_idx);
|
||||
post_select_event(selection_idx);
|
||||
|
||||
@@ -1279,6 +1231,9 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi
|
||||
m_comboBox_filament->SetValue(wxEmptyString);
|
||||
}
|
||||
|
||||
// Set the flag whether to open the filament setting dialog from the device page
|
||||
m_comboBox_filament->SetClientData(new int(1));
|
||||
|
||||
update();
|
||||
Layout();
|
||||
Fit();
|
||||
@@ -1322,53 +1277,50 @@ int AMSMaterialsSetting::get_filament_variant_index(const Preset &filament, cons
|
||||
|
||||
void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt)
|
||||
{
|
||||
// True for the popup's own initial selection: the dialog pre-filled the tray's
|
||||
// temps, so the matching preset must not overwrite them.
|
||||
const bool initial_printer_selection = m_comboBox_from_printer;
|
||||
// Get the flag whether to open the filament setting dialog from the device page
|
||||
int* from_printer = static_cast<int*>(m_comboBox_filament->GetClientData());
|
||||
|
||||
m_filament_type = "";
|
||||
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
|
||||
std::string filament_printer_model;
|
||||
if (preset_bundle) {
|
||||
std::ostringstream stream;
|
||||
if (obj) {
|
||||
// Use the selected profile's nozzle diameter until the connected device reports one.
|
||||
// Defensive: this dialog is opened only from StatusPanel (BBL-only) today, so the fallback fires
|
||||
// only during the brief BBL startup window before firmware reports nozzle info. Without this,
|
||||
// the "0.0" lookup string returns an empty set and filament lookup yields no results.
|
||||
float machine_diameter = obj->GetExtderSystem()->GetNozzleDiameter(0);
|
||||
if (machine_diameter == 0.0f) {
|
||||
const ConfigOption *opt = preset_bundle->printers.get_selected_preset().config.option("nozzle_diameter");
|
||||
if (opt) machine_diameter = static_cast<const ConfigOptionFloats *>(opt)->values[0];
|
||||
}
|
||||
stream << std::fixed << std::setprecision(1) << machine_diameter;
|
||||
filament_printer_model = resolve_filament_printer_model(obj->printer_type, preset_bundle);
|
||||
}
|
||||
std::string nozzle_diameter_str = stream.str();
|
||||
// Resolve the selection against the same list Popup() built the dropdown from, so the two
|
||||
// halves of the dialog cannot disagree about which filaments this machine can use.
|
||||
const std::string selected = m_comboBox_filament->GetValue().ToStdString();
|
||||
if (!selected.empty() && !filament_printer_model.empty()) {
|
||||
if (!selected.empty()) {
|
||||
const std::string filament_id = map_filament_items[selected].filament_id;
|
||||
for (Preset *it : preset_bundle->get_filament_presets_for_machine(
|
||||
filament_printer_model, nozzle_diameter_str, obj->is_support_user_preset)) {
|
||||
DevPrinterConfigUtil::get_printer_display_name(obj->printer_type), nozzle_diameter_str, obj->is_support_user_preset)) {
|
||||
if (it->filament_id != filament_id)
|
||||
continue;
|
||||
if (!initial_printer_selection) {
|
||||
// ) if nozzle_temperature_range is found
|
||||
const int variant_index = get_filament_variant_index(*it, nozzle_diameter_str);
|
||||
ConfigOption* opt_min = it->config.option("nozzle_temperature_range_low");
|
||||
if (opt_min) {
|
||||
ConfigOptionInts* opt_min_ints = dynamic_cast<ConfigOptionInts*>(opt_min);
|
||||
if (opt_min_ints) {
|
||||
wxString text_nozzle_temp_min = wxString::Format("%d", opt_min_ints->get_at(variant_index));
|
||||
m_input_nozzle_min->GetTextCtrl()->SetValue(text_nozzle_temp_min);
|
||||
}
|
||||
// ) if nozzle_temperature_range is found
|
||||
const int variant_index = get_filament_variant_index(*it, nozzle_diameter_str);
|
||||
ConfigOption* opt_min = it->config.option("nozzle_temperature_range_low");
|
||||
if (opt_min) {
|
||||
ConfigOptionInts* opt_min_ints = dynamic_cast<ConfigOptionInts*>(opt_min);
|
||||
if (opt_min_ints) {
|
||||
wxString text_nozzle_temp_min = wxString::Format("%d", opt_min_ints->get_at(variant_index));
|
||||
m_input_nozzle_min->GetTextCtrl()->SetValue(text_nozzle_temp_min);
|
||||
}
|
||||
ConfigOption* opt_max = it->config.option("nozzle_temperature_range_high");
|
||||
if (opt_max) {
|
||||
ConfigOptionInts* opt_max_ints = dynamic_cast<ConfigOptionInts*>(opt_max);
|
||||
if (opt_max_ints) {
|
||||
wxString text_nozzle_temp_max = wxString::Format("%d", opt_max_ints->get_at(variant_index));
|
||||
m_input_nozzle_max->GetTextCtrl()->SetValue(text_nozzle_temp_max);
|
||||
}
|
||||
}
|
||||
ConfigOption* opt_max = it->config.option("nozzle_temperature_range_high");
|
||||
if (opt_max) {
|
||||
ConfigOptionInts* opt_max_ints = dynamic_cast<ConfigOptionInts*>(opt_max);
|
||||
if (opt_max_ints) {
|
||||
wxString text_nozzle_temp_max = wxString::Format("%d", opt_max_ints->get_at(variant_index));
|
||||
m_input_nozzle_max->GetTextCtrl()->SetValue(text_nozzle_temp_max);
|
||||
}
|
||||
}
|
||||
ConfigOption* opt_type = it->config.option("filament_type");
|
||||
@@ -1407,16 +1359,13 @@ void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt)
|
||||
m_button_confirm->Disable(); // ORCA No need to change style
|
||||
m_comboBox_cali_result->Clear();
|
||||
m_comboBox_cali_result->SetValue(wxEmptyString);
|
||||
if (!initial_printer_selection) {
|
||||
m_input_k_val->GetTextCtrl()->SetValue(wxEmptyString);
|
||||
m_input_n_val->GetTextCtrl()->SetValue(wxEmptyString);
|
||||
}
|
||||
m_comboBox_from_printer = false;
|
||||
m_input_k_val->GetTextCtrl()->SetValue(wxEmptyString);
|
||||
m_input_n_val->GetTextCtrl()->SetValue(wxEmptyString);
|
||||
m_comboBox_filament->SetClientData(new int(0));
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (!m_view_only)
|
||||
m_button_confirm->Enable(true); // ORCA No need to change style
|
||||
m_button_confirm->Enable(true); // ORCA No need to change style
|
||||
}
|
||||
|
||||
//filament id
|
||||
@@ -1440,9 +1389,6 @@ void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt)
|
||||
}
|
||||
}
|
||||
|
||||
if (!ams_filament_id.empty())
|
||||
m_clr_picker->is_empty(false);
|
||||
|
||||
wxArrayString items;
|
||||
m_pa_profile_items.clear();
|
||||
m_comboBox_cali_result->SetValue(wxEmptyString);
|
||||
@@ -1498,7 +1444,7 @@ void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt)
|
||||
|
||||
m_comboBox_cali_result->Set(items);
|
||||
if (ams_id == VIRTUAL_TRAY_MAIN_ID || ams_id == VIRTUAL_TRAY_DEPUTY_ID) {
|
||||
if (initial_printer_selection) {
|
||||
if (from_printer && (*from_printer == 1)) {
|
||||
for (auto slot : obj->vt_slot) {
|
||||
if (slot.id == std::to_string(ams_id))
|
||||
cali_select_idx = CalibUtils::get_selected_calib_idx(m_pa_profile_items, slot.cali_idx);
|
||||
@@ -1515,11 +1461,10 @@ void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt)
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (initial_printer_selection) {
|
||||
if (from_printer && (*from_printer == 1)) {
|
||||
DevAmsTray* selected_tray = this->obj->GetFilaSystem()->GetAmsTray(std::to_string(ams_id), std::to_string(slot_id));
|
||||
if (!selected_tray)
|
||||
{
|
||||
m_comboBox_from_printer = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1550,7 +1495,7 @@ void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt)
|
||||
else {
|
||||
if (!ams_filament_id.empty()) {
|
||||
//m_input_k_val->GetTextCtrl()->SetValue("0.00");
|
||||
m_input_k_val->Enable(!m_view_only);
|
||||
m_input_k_val->Enable(true);
|
||||
}
|
||||
else {
|
||||
//m_input_k_val->GetTextCtrl()->SetValue("0.00");
|
||||
@@ -1558,7 +1503,7 @@ void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt)
|
||||
}
|
||||
}
|
||||
|
||||
m_comboBox_from_printer = false;
|
||||
m_comboBox_filament->SetClientData(new int(0));
|
||||
}
|
||||
|
||||
void AMSMaterialsSetting::on_dpi_changed(const wxRect &suggested_rect)
|
||||
|
||||
@@ -138,7 +138,7 @@ public:
|
||||
std::string ams_filament_id;
|
||||
std::string ams_setting_id;
|
||||
|
||||
bool m_is_third = false;
|
||||
bool m_is_third;
|
||||
// Orca: view-only mode (laser/cut). When set, the dialog is inspectable but every
|
||||
// editing control is disabled and no command is sent.
|
||||
bool m_view_only = false;
|
||||
@@ -200,9 +200,6 @@ protected:
|
||||
wxStaticText* m_n_param;
|
||||
TextInput* m_input_n_val;
|
||||
int m_filament_selection;
|
||||
// True while the popup's initial, printer-driven selection is being handled; it
|
||||
// keeps that selection from overwriting the tray's own temps with preset temps.
|
||||
bool m_comboBox_from_printer = false;
|
||||
|
||||
int m_pa_cali_select_id = 0;
|
||||
|
||||
|
||||
@@ -530,8 +530,7 @@ void AMSSetting::on_insert_material_read(wxCommandEvent &event)
|
||||
bool tray_read_opt = m_checkbox_Insert_material_auto_read->GetValue();
|
||||
bool remain_opt = m_checkbox_remain->GetValue();
|
||||
|
||||
if (m_obj->command_ams_user_settings(start_read_opt, tray_read_opt, remain_opt) != 0)
|
||||
UpdateByObj(m_obj);
|
||||
m_obj->command_ams_user_settings(start_read_opt, tray_read_opt, remain_opt);
|
||||
|
||||
m_sizer_Insert_material_tip_inline->Layout();
|
||||
Layout();
|
||||
@@ -557,8 +556,7 @@ void AMSSetting::on_starting_read(wxCommandEvent &event)
|
||||
bool tray_read_opt = m_checkbox_Insert_material_auto_read->GetValue();
|
||||
bool remain_opt = m_checkbox_remain->GetValue();
|
||||
|
||||
if (m_obj->command_ams_user_settings(start_read_opt, tray_read_opt, remain_opt) != 0)
|
||||
UpdateByObj(m_obj);
|
||||
m_obj->command_ams_user_settings(start_read_opt, tray_read_opt, remain_opt);
|
||||
|
||||
m_sizer_starting_tip_inline->Layout();
|
||||
Layout();
|
||||
@@ -572,8 +570,7 @@ void AMSSetting::on_remain(wxCommandEvent& event)
|
||||
bool start_read_opt = m_checkbox_starting_auto_read->GetValue();
|
||||
bool tray_read_opt = m_checkbox_Insert_material_auto_read->GetValue();
|
||||
bool remain_opt = m_checkbox_remain->GetValue();
|
||||
if (m_obj->command_ams_user_settings(start_read_opt, tray_read_opt, remain_opt) != 0)
|
||||
UpdateByObj(m_obj);
|
||||
m_obj->command_ams_user_settings(start_read_opt, tray_read_opt, remain_opt);
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
@@ -809,4 +806,4 @@ void AMSSettingArrangeAMSOrder::OnBtnRearrangeClicked(wxCommandEvent& event)
|
||||
}
|
||||
#endif
|
||||
|
||||
}} // namespace Slic3r::GUI
|
||||
}} // namespace Slic3r::GUI
|
||||
@@ -41,6 +41,7 @@
|
||||
#define TOPBAR_TITLE_WIDTH 300
|
||||
|
||||
using namespace Slic3r;
|
||||
using namespace Slic3r::GUI;
|
||||
|
||||
enum CUSTOM_ID
|
||||
{
|
||||
|
||||
@@ -18,8 +18,6 @@ class wxMouseCaptureLostEvent;
|
||||
class wxMouseEvent;
|
||||
class wxWindow;
|
||||
|
||||
using namespace Slic3r::GUI;
|
||||
|
||||
class CenteredTitle : public wxControl
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -218,7 +218,7 @@ std::string BackgroundSlicingProcess::output_filepath_for_project(const boost::f
|
||||
void BackgroundSlicingProcess::process_fff()
|
||||
{
|
||||
assert(m_print == m_fff_print);
|
||||
PresetBundle& preset_bundle = *wxGetApp().preset_bundle;
|
||||
PresetBundle& preset_bundle = *GUI::wxGetApp().preset_bundle;
|
||||
m_fff_print->is_BBL_printer() = preset_bundle.is_bbl_vendor();
|
||||
// BBS: add the logic to process from an existed gcode file
|
||||
if (m_print->finished()) {
|
||||
@@ -727,7 +727,7 @@ StringObjectException BackgroundSlicingProcess::validate(std::vector<StringObjec
|
||||
assert(m_print != nullptr);
|
||||
assert(m_print == m_fff_print);
|
||||
|
||||
m_fff_print->is_BBL_printer() = wxGetApp().preset_bundle->is_bbl_vendor();
|
||||
m_fff_print->is_BBL_printer() = GUI::wxGetApp().preset_bundle->is_bbl_vendor();
|
||||
return m_print->validate(warnings, collison_polygons, height_polygons);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include "Widgets/DialogButtons.hpp"
|
||||
#include "libslic3r/Config.hpp"
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <slic3r/GUI/DeviceManager.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "libslic3r/calib.hpp"
|
||||
@@ -746,15 +745,9 @@ wxArrayString NewCalibrationHistoryDialog::get_all_filaments(const MachineObject
|
||||
std::string nozzle_diameter_str = stream.str();
|
||||
|
||||
if (preset_bundle) {
|
||||
// OrcaSonar's model id is optional; the helper falls back to the selected profile
|
||||
// so the list is never empty.
|
||||
const std::string filament_printer_model = resolve_filament_printer_model(obj->printer_type, preset_bundle);
|
||||
if (filament_printer_model.empty())
|
||||
return filament_items;
|
||||
|
||||
BOOST_LOG_TRIVIAL(trace) << "system_preset_bundle filament number=" << preset_bundle->filaments.size();
|
||||
for (Preset *filament_it : preset_bundle->get_filament_presets_for_machine(
|
||||
filament_printer_model, nozzle_diameter_str, obj->is_support_user_preset)) {
|
||||
DevPrinterConfigUtil::get_printer_display_name(obj->printer_type), nozzle_diameter_str, obj->is_support_user_preset)) {
|
||||
if (!filament_id_set.insert(filament_it->filament_id).second)
|
||||
continue;
|
||||
const std::string alias = preset_bundle->filaments.get_preset_alias(*filament_it, true);
|
||||
|
||||
@@ -43,8 +43,6 @@
|
||||
#include <wx/types.h>
|
||||
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
@@ -88,7 +86,7 @@ struct Bundle
|
||||
// cache or its profile JSONs, whichever is usable.
|
||||
// Returns false if not loaded. Reason for that is logged as boost::log error.
|
||||
//BBS: set BBL as default
|
||||
bool load(fs::path dir, const std::string &vendor_name, bool is_in_resources, bool is_bbl_bundle = false);
|
||||
bool load(boost::filesystem::path dir, const std::string &vendor_name, bool is_in_resources, bool is_bbl_bundle = false);
|
||||
|
||||
const std::string& vendor_id() const { return vendor_profile->id; }
|
||||
};
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cassert>
|
||||
@@ -9,7 +8,6 @@
|
||||
#include <cstdlib>
|
||||
#include <chrono>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <wx/app.h>
|
||||
#include <wx/colour.h>
|
||||
#include <string>
|
||||
#include <wx/string.h>
|
||||
@@ -22,7 +20,6 @@
|
||||
#include "DevFilaSystem.h"
|
||||
#include "json_diff.hpp"
|
||||
#include "slic3r/Utils/NetworkAgent.hpp"
|
||||
#include "slic3r/Utils/NetworkAgentFactory.hpp" // ORCA_PRINTER_AGENT_ID
|
||||
#include "DevNozzleSystem.h" // DevNozzle / DevNozzleSystem for GetNozzleFlowStringByAmsId
|
||||
|
||||
// TODO: remove this include
|
||||
@@ -65,15 +62,6 @@ void DevAmsTray::UpdateColorFromStr(const std::string& color)
|
||||
}
|
||||
}
|
||||
|
||||
void DevAmsTray::UpdateEmptyState(bool material_fields_present, bool classify_empty)
|
||||
{
|
||||
const auto is_zero_or_empty = [](const std::string& value) {
|
||||
return value.empty() || std::all_of(value.begin(), value.end(), [](char c) { return c == '0'; });
|
||||
};
|
||||
is_empty = material_fields_present && classify_empty && setting_id.empty() && m_fila_type.empty() &&
|
||||
is_zero_or_empty(color) && is_zero_or_empty(tag_uid);
|
||||
}
|
||||
|
||||
void DevAmsTray::reset()
|
||||
{
|
||||
tag_uid = "";
|
||||
@@ -95,7 +83,6 @@ void DevAmsTray::reset()
|
||||
k = 0.0f;
|
||||
n = 0.0f;
|
||||
is_bbl = false;
|
||||
is_empty = false;
|
||||
hold_count = 0;
|
||||
remain = 0;
|
||||
}
|
||||
@@ -695,7 +682,7 @@ void DevFilaSystemParser::ParseV1_0(const json& jj, MachineObject* obj, DevFilaS
|
||||
//std::string type = (*tray_it)["tray_type"].get<std::string>();
|
||||
std::string type = MachineObject::setting_id_to_type(curr_tray->setting_id, (*tray_it)["tray_type"].get<std::string>());
|
||||
// curr_tray->setting_id is our OF id; GFS00/GFS01 are the printer's own support-filament ids.
|
||||
auto* agent = wxTheApp != nullptr ? GUI::wxGetApp().getAgent() : nullptr;
|
||||
auto* agent = GUI::wxGetApp().getAgent();
|
||||
const std::string printer_filament_id = agent ? agent->from_orca_filament_id(curr_tray->setting_id) : curr_tray->setting_id;
|
||||
if (printer_filament_id == "GFS00")
|
||||
{
|
||||
@@ -795,8 +782,6 @@ void DevFilaSystemParser::ParseV1_0(const json& jj, MachineObject* obj, DevFilaS
|
||||
{
|
||||
curr_tray->remain = -1;
|
||||
}
|
||||
curr_tray->UpdateEmptyState(tray_it->contains("tray_info_idx") && tray_it->contains("tray_type"),
|
||||
obj->printer_agent_id == ORCA_PRINTER_AGENT_ID);
|
||||
// The tray objects are reused across status updates. Reset this
|
||||
// state when a previously empty slot receives a filament again.
|
||||
curr_tray->is_slot_placeholder = tray_it->contains("tray_slot_placeholder");
|
||||
|
||||
@@ -83,7 +83,6 @@ public:
|
||||
wxColour wx_color;
|
||||
bool is_bbl;
|
||||
bool is_exists = false;
|
||||
bool is_empty = false; // Explicitly reported as having no filament.
|
||||
bool is_slot_placeholder = false; // Orca: True for empty tray slots from pull-mode agents
|
||||
int hold_count = 0;
|
||||
int remain = 0; // filament remain: 0 ~ 100
|
||||
@@ -92,15 +91,13 @@ public:
|
||||
// operators
|
||||
bool operator==(DevAmsTray const& o) const
|
||||
{
|
||||
return id == o.id && m_fila_type == o.m_fila_type && filament_setting_id == o.filament_setting_id &&
|
||||
color == o.color && is_empty == o.is_empty;
|
||||
return id == o.id && m_fila_type == o.m_fila_type && filament_setting_id == o.filament_setting_id && color == o.color;
|
||||
}
|
||||
bool operator!=(DevAmsTray const& o) const { return !operator==(o); }
|
||||
|
||||
// setters
|
||||
void reset();
|
||||
void UpdateColorFromStr(const std::string& color);
|
||||
void UpdateEmptyState(bool material_fields_present, bool classify_empty);
|
||||
void set_hold_count() { hold_count = HOLD_COUNT_MAX; }
|
||||
|
||||
// getter
|
||||
|
||||
@@ -65,7 +65,6 @@
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <wx/app.h>
|
||||
#include <wx/colour.h>
|
||||
#include <tuple>
|
||||
#include <wx/dir.h>
|
||||
@@ -432,32 +431,6 @@ NozzleVolumeType convert_to_nozzle_type(const std::string &str)
|
||||
return res;
|
||||
}
|
||||
|
||||
std::string resolve_filament_printer_model(const std::string& printer_type, PresetBundle* preset_bundle)
|
||||
{
|
||||
if (!preset_bundle)
|
||||
return {};
|
||||
|
||||
// Devices with a shipped printer config (Bambu) resolve directly.
|
||||
if (const std::string display_name = DevPrinterConfigUtil::get_printer_display_name(printer_type); !display_name.empty())
|
||||
return display_name;
|
||||
|
||||
// A vendor model id the device reported (SSDP modelNumber, manual binding).
|
||||
if (!printer_type.empty()) {
|
||||
if (const std::string model_name = preset_bundle->get_printer_model_display_name(printer_type); !model_name.empty())
|
||||
return model_name;
|
||||
}
|
||||
|
||||
// OrcaSonar's model id is optional; a generic device resolves against the selected profile.
|
||||
if (const ConfigOptionString* model = preset_bundle->printers.get_selected_preset().config.opt<ConfigOptionString>("printer_model");
|
||||
model && !model->value.empty()) {
|
||||
BOOST_LOG_TRIVIAL(info) << "resolve_filament_printer_model: device type \"" << printer_type
|
||||
<< "\" has no installed model; using the selected profile \"" << model->value << "\"";
|
||||
return model->value;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
wxString MachineObject::get_printer_type_display_str() const
|
||||
{
|
||||
std::string display_name = DevPrinterConfigUtil::get_printer_display_name(printer_type);
|
||||
@@ -1760,10 +1733,6 @@ int MachineObject::check_resume_condition()
|
||||
}
|
||||
int MachineObject::command_ams_change_filament(bool load, std::string ams_id, std::string slot_id, int old_temp, int new_temp, std::optional<int> extruder_id)
|
||||
{
|
||||
if (!printer_supports_command("print.ams_change_filament")) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "command_ams_change_filament: printer agent does not support the command";
|
||||
return command_with_dialog(ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED);
|
||||
}
|
||||
json j;
|
||||
try {
|
||||
auto tray_id = 0;
|
||||
@@ -1807,10 +1776,6 @@ int MachineObject::command_ams_change_filament(bool load, std::string ams_id, st
|
||||
|
||||
int MachineObject::command_ams_user_settings(bool start_read_opt, bool tray_read_opt, bool remain_flag)
|
||||
{
|
||||
if (!printer_supports_command("print.ams_user_setting")) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "command_ams_user_settings: printer agent does not support the command";
|
||||
return command_with_dialog(ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED);
|
||||
}
|
||||
json j;
|
||||
j["print"]["command"] = "ams_user_setting";
|
||||
j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++);
|
||||
@@ -1819,59 +1784,22 @@ int MachineObject::command_ams_user_settings(bool start_read_opt, bool tray_read
|
||||
j["print"]["tray_read_option"] = tray_read_opt;
|
||||
j["print"]["calibrate_remain_flag"] = remain_flag;
|
||||
|
||||
const int rc = this->publish_json(j);
|
||||
if (rc == 0) {
|
||||
m_fila_system->GetAmsSystemSetting().SetDetectOnInsertEnabled(tray_read_opt);
|
||||
m_fila_system->GetAmsSystemSetting().SetDetectOnPowerupEnabled(start_read_opt);
|
||||
m_fila_system->GetAmsSystemSetting().SetDetectRemainEnabled(remain_flag);
|
||||
ams_user_setting_start = time(nullptr);
|
||||
}
|
||||
return rc;
|
||||
m_fila_system->GetAmsSystemSetting().SetDetectOnInsertEnabled(tray_read_opt);
|
||||
m_fila_system->GetAmsSystemSetting().SetDetectOnPowerupEnabled(start_read_opt);
|
||||
m_fila_system->GetAmsSystemSetting().SetDetectRemainEnabled(remain_flag);
|
||||
ams_user_setting_start = time(nullptr);
|
||||
|
||||
return this->publish_json(j);
|
||||
}
|
||||
|
||||
int MachineObject::command_ams_calibrate(int ams_id)
|
||||
{
|
||||
if (!m_agent) return -1;
|
||||
if (!m_agent->owns_agent(printer_agent_id))
|
||||
return command_with_dialog(ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED);
|
||||
return command_with_dialog(m_agent->command_ams_calibrate(get_dev_id(), ams_id, MachineObject::m_sequence_id++, is_lan_mode_printer()));
|
||||
}
|
||||
|
||||
bool MachineObject::printer_supports_command(const char* command) const
|
||||
{
|
||||
if (!command || !m_agent)
|
||||
return false;
|
||||
return m_agent->supports_command(printer_agent_id, get_dev_id(), command);
|
||||
}
|
||||
|
||||
bool MachineObject::printer_uses_filament_mapping() const
|
||||
{
|
||||
if (!m_agent)
|
||||
return false;
|
||||
// An unrecorded owner goes through owns_agent() like any other, because
|
||||
// whichever agent is active is also the one formatting the payload. Only a
|
||||
// recorded owner that differs from the active agent is a mismatch.
|
||||
return m_agent->uses_filament_mapping(printer_agent_id);
|
||||
}
|
||||
|
||||
bool MachineObject::printer_supports_feature(const char* feature) const
|
||||
{
|
||||
return feature && m_agent && m_agent->supports_feature(printer_agent_id, get_dev_id(), feature);
|
||||
}
|
||||
|
||||
bool MachineObject::supports_extrusion_cali() const
|
||||
{
|
||||
// Devices with no agent id predate the agent split and keep the Bambu path.
|
||||
return printer_agent_id.empty() || printer_agent_id == BBL_PRINTER_AGENT_ID;
|
||||
}
|
||||
|
||||
int MachineObject::command_ams_filament_settings(int ams_id, int slot_id, std::string filament_id, std::string setting_id, std::string tray_color, std::string tray_type, int nozzle_temp_min, int nozzle_temp_max)
|
||||
{
|
||||
if (!printer_supports_command("print.ams_filament_setting")) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "command_ams_filament_settings: printer agent does not support slot metadata updates";
|
||||
return command_with_dialog(ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
int tag_tray_id = 0;
|
||||
int tag_ams_id = ams_id;
|
||||
int tag_slot_id = slot_id;
|
||||
@@ -1906,10 +1834,6 @@ int MachineObject::command_ams_filament_settings(int ams_id, int slot_id, std::s
|
||||
int MachineObject::command_ams_refresh_rfid(int ams_id, int slot_id)
|
||||
{
|
||||
if (!m_agent) return -1;
|
||||
if (!printer_supports_command("print.ams_get_rfid")) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "command_ams_refresh_rfid: printer agent does not support the command";
|
||||
return command_with_dialog(ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED);
|
||||
}
|
||||
return command_with_dialog(m_agent->command_ams_refresh_rfid(get_dev_id(), ams_id, slot_id, MachineObject::m_sequence_id++, is_lan_mode_printer()));
|
||||
}
|
||||
|
||||
@@ -1923,19 +1847,11 @@ int MachineObject::command_start_camera()
|
||||
int MachineObject::command_ams_select_tray(std::string tray_id)
|
||||
{
|
||||
if (!m_agent) return -1;
|
||||
if (!printer_supports_command("print.ams_change_filament")) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "command_ams_select_tray: printer agent does not support the command";
|
||||
return command_with_dialog(ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED);
|
||||
}
|
||||
return command_with_dialog(m_agent->command_ams_select_tray(get_dev_id(), tray_id, MachineObject::m_sequence_id++, is_lan_mode_printer()));
|
||||
}
|
||||
|
||||
int MachineObject::command_ams_control(std::string action)
|
||||
{
|
||||
if (!printer_supports_command("print.ams_control")) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "command_ams_control: printer agent does not support the command";
|
||||
return command_with_dialog(ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED);
|
||||
}
|
||||
if (action == "resume" && check_resume_condition()) return 0;
|
||||
|
||||
//valid actions
|
||||
@@ -1951,10 +1867,6 @@ int MachineObject::command_ams_control(std::string action)
|
||||
|
||||
int MachineObject::command_ams_drying_stop()
|
||||
{
|
||||
if (!printer_supports_command("print.auto_stop_ams_dry")) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "command_ams_drying_stop: printer agent does not support the command";
|
||||
return command_with_dialog(ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED);
|
||||
}
|
||||
json j;
|
||||
j["print"]["command"] = "auto_stop_ams_dry";
|
||||
j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++);
|
||||
@@ -2905,9 +2817,7 @@ bool MachineObject::is_camera_busy_off()
|
||||
int MachineObject::publish_json(const json& json_item, int qos, int flag)
|
||||
{
|
||||
int rtn = 0;
|
||||
if (m_agent && !m_agent->owns_agent(printer_agent_id)) {
|
||||
rtn = ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED;
|
||||
} else if (is_lan_mode_printer()) {
|
||||
if (is_lan_mode_printer()) {
|
||||
rtn = local_publish_json(json_item.dump(), qos, flag);
|
||||
} else {
|
||||
rtn = cloud_publish_json(json_item.dump(), qos, flag);
|
||||
@@ -2951,7 +2861,6 @@ int MachineObject::local_publish_json(std::string json_str, int qos, int flag)
|
||||
std::string MachineObject::setting_id_to_type(std::string setting_id, std::string tray_type)
|
||||
{
|
||||
std::string type;
|
||||
if (wxTheApp == nullptr) return tray_type;
|
||||
PresetBundle* preset_bundle = GUI::wxGetApp().preset_bundle;
|
||||
if (preset_bundle) {
|
||||
for (auto it = preset_bundle->filaments.begin(); it != preset_bundle->filaments.end(); it++) {
|
||||
@@ -4288,9 +4197,6 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_
|
||||
vt_slot[0].setting_id = jj["tray_info_idx"].get<std::string>();
|
||||
//vt_tray.type = jj["tray_type"].get<std::string>();
|
||||
vt_slot[0].m_fila_type = setting_id_to_type(vt_slot[0].setting_id, jj["tray_type"].get<std::string>());
|
||||
// The ack carries the whole slot; re-derive empty so the panel flips off
|
||||
// "Empty" without waiting out the hold.
|
||||
vt_slot[0].UpdateEmptyState(true, printer_agent_id == ORCA_PRINTER_AGENT_ID);
|
||||
// delay update
|
||||
vt_slot[0].set_hold_count();
|
||||
} else {
|
||||
@@ -4316,9 +4222,6 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_
|
||||
|
||||
tray_it->second->setting_id = jj["tray_info_idx"].get<std::string>();
|
||||
tray_it->second->m_fila_type = setting_id_to_type(tray_it->second->setting_id, jj["tray_type"].get<std::string>());
|
||||
// The ack carries the whole slot; re-derive empty so the panel flips off
|
||||
// "Empty" without waiting out the hold.
|
||||
tray_it->second->UpdateEmptyState(true, printer_agent_id == ORCA_PRINTER_AGENT_ID);
|
||||
// delay update
|
||||
tray_it->second->set_hold_count();
|
||||
} else {
|
||||
@@ -5257,7 +5160,7 @@ DevAmsTray MachineObject::parse_vt_tray(json vtray)
|
||||
//std::string type = vtray["tray_type"].get<std::string>();
|
||||
std::string type = setting_id_to_type(vt_tray.setting_id, vtray["tray_type"].get<std::string>());
|
||||
// vt_tray.setting_id is our OF id (translated on the way in); the two support ids below are the printer's own.
|
||||
auto* agent = wxTheApp != nullptr ? GUI::wxGetApp().getAgent() : nullptr;
|
||||
auto* agent = GUI::wxGetApp().getAgent();
|
||||
const std::string printer_filament_id = agent ? agent->from_orca_filament_id(vt_tray.setting_id) : vt_tray.setting_id;
|
||||
if (printer_filament_id == "GFS00") {
|
||||
vt_tray.m_fila_type = "PLA-S";
|
||||
@@ -5352,8 +5255,6 @@ DevAmsTray MachineObject::parse_vt_tray(json vtray)
|
||||
else {
|
||||
vt_tray.remain = -1;
|
||||
}
|
||||
vt_tray.UpdateEmptyState(vtray.contains("tray_info_idx") && vtray.contains("tray_type"),
|
||||
printer_agent_id == ORCA_PRINTER_AGENT_ID);
|
||||
}
|
||||
|
||||
return vt_tray;
|
||||
@@ -5647,11 +5548,11 @@ void MachineObject::parse_new_info2(const json& info)
|
||||
if (capabilities_it == info.end() || !capabilities_it->is_object())
|
||||
return;
|
||||
const auto flags_it = capabilities_it->find("flags");
|
||||
const bool has_flags = flags_it != capabilities_it->end() && flags_it->is_object();
|
||||
if (!has_flags)
|
||||
if (flags_it == capabilities_it->end() || !flags_it->is_object())
|
||||
return;
|
||||
|
||||
const json& flags = *flags_it;
|
||||
BOOST_LOG_TRIVIAL(info) << "parse_new_info2: capability flags=" << flags.dump();
|
||||
BOOST_LOG_TRIVIAL(info) << "parse_new_info2: OrcaSonar capability flags=" << flags.dump();
|
||||
|
||||
auto parse_bool = [&flags](const char* name, bool& target) {
|
||||
const auto it = flags.find(name);
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <chrono>
|
||||
#include <set>
|
||||
#include <unordered_set>
|
||||
#include <optional>
|
||||
#include <boost/thread.hpp>
|
||||
@@ -74,7 +73,6 @@ class DeviceErrorDialog; // Previous definitions
|
||||
|
||||
class NetworkAgent;
|
||||
// Orca: ManualPaCaliMethod now provided by DeviceCore/DevCalib.h (enum class)
|
||||
class PresetBundle;
|
||||
|
||||
#define UpgradeNoError 0
|
||||
#define UpgradeDownloadFailed -1
|
||||
@@ -110,11 +108,6 @@ struct DevPrintTaskRatingInfo;
|
||||
// given nozzle diameter (mm), bucketed per nozzle size to mirror the printer firmware.
|
||||
bool is_stringing_prone_filament(const std::string& filament_id, float nozzle_diameter);
|
||||
|
||||
// The printer model filament presets are matched against for a connected machine. OrcaSonar's
|
||||
// model id is optional, so a device with no installed vendor model falls back to the selected
|
||||
// printer profile rather than resolving to no filament list at all.
|
||||
std::string resolve_filament_printer_model(const std::string& printer_type, PresetBundle* preset_bundle);
|
||||
|
||||
class MachineObject
|
||||
{
|
||||
private:
|
||||
@@ -803,13 +796,6 @@ public:
|
||||
int command_refresh_nozzle();
|
||||
int command_set_chamber(int temp);
|
||||
int check_resume_condition();
|
||||
bool printer_supports_command(const char* command) const;
|
||||
bool printer_supports_feature(const char* feature) const;
|
||||
bool printer_uses_filament_mapping() const;
|
||||
// The per-tray flow-dynamics K/N records are a Bambu firmware feature. Other
|
||||
// agents have no printer-side calibration to read or write, so the AMS UI must
|
||||
// not offer K/N for them.
|
||||
bool supports_extrusion_cali() const;
|
||||
// ams controls
|
||||
//int command_ams_switch(int tray_index, int old_temp = 210, int new_temp = 210);
|
||||
int command_ams_change_filament(bool load, std::string ams_id, std::string slot_id, int old_temp = 210, int new_temp = 210, std::optional<int> extruder_id = std::nullopt);
|
||||
|
||||
@@ -970,11 +970,7 @@ int ReselectMachineDialog::CaculateSwitcherDistribution(MachineObject* obj, cons
|
||||
const auto& can = ams.cans[j];
|
||||
auto id = getTrayID(obj, ams.ams_id, can.can_id);
|
||||
auto material = can.material_name;
|
||||
if (can.is_empty || can.material_state == AMSCanType::AMS_CAN_TYPE_EMPTY)
|
||||
{
|
||||
material = L("Empty");
|
||||
}
|
||||
else if (can.material_state == AMSCanType::AMS_CAN_TYPE_THIRDBRAND ||
|
||||
if (can.material_state == AMSCanType::AMS_CAN_TYPE_THIRDBRAND ||
|
||||
can.material_state == AMSCanType::AMS_CAN_TYPE_BRAND ||
|
||||
can.material_state == AMSCanType::AMS_CAN_TYPE_VIRTUAL)
|
||||
{
|
||||
@@ -983,6 +979,10 @@ int ReselectMachineDialog::CaculateSwitcherDistribution(MachineObject* obj, cons
|
||||
material = L("?");
|
||||
}
|
||||
}
|
||||
if (can.material_state == AMSCanType::AMS_CAN_TYPE_EMPTY)
|
||||
{
|
||||
material = L("Empty");
|
||||
}
|
||||
|
||||
auto itOK = std::find_if(posOK.begin(), posOK.end(), [&](const trayHelper& tray){
|
||||
auto amsID = std::get<0>(tray);
|
||||
|
||||
@@ -1,105 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "libslic3r/ProjectTask.hpp"
|
||||
#include "DeviceManager.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
// True when the normalized ams_mapping2 carries any entry the agent's serializer
|
||||
// would put on the wire: every integer pair except the {255,255} unmatched
|
||||
// sentinel, external slots ({255,0}/{254,0}) included. This mirrors
|
||||
// OrcaPrinterAgent::build_filament_mapping exactly, so the GUI gate and the
|
||||
// agent gate agree; a mismatch lets an entry reach the agent and be refused late
|
||||
// with a generic publish error instead of the designed message.
|
||||
inline bool has_engaged_filament_mapping(const std::string& ams_mapping2)
|
||||
{
|
||||
const nlohmann::json mapping = nlohmann::json::parse(ams_mapping2, nullptr, false);
|
||||
if (mapping.is_discarded() || !mapping.is_array())
|
||||
return false;
|
||||
for (const auto& entry : mapping) {
|
||||
if (!entry.is_object())
|
||||
continue;
|
||||
const auto ams_id_it = entry.find("ams_id");
|
||||
const auto slot_id_it = entry.find("slot_id");
|
||||
if (ams_id_it == entry.end() || slot_id_it == entry.end())
|
||||
continue;
|
||||
if (!ams_id_it->is_number_integer() || !slot_id_it->is_number_integer())
|
||||
continue;
|
||||
if (ams_id_it->get<int>() == 255 && slot_id_it->get<int>() == 255)
|
||||
continue; // unmatched/unused sentinel: the serializer drops it
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// A device with no AMS units has a single source: the external spool. OrcaSlicer's
|
||||
// auto-mapping force-selects it for every filament (DevMapping.cpp), but that is not
|
||||
// a lane choice: keep it out of the send gate and off print.gcode_file.
|
||||
inline void drop_forced_external_selection(bool device_has_ams, std::string& ams_mapping2)
|
||||
{
|
||||
if (!device_has_ams)
|
||||
ams_mapping2.clear();
|
||||
}
|
||||
|
||||
// A used filament with no target would be silently dropped from the wire
|
||||
// mapping, so the print must be refused rather than run the wrong material.
|
||||
// m_ams_mapping_result carries exactly the filaments the slice uses.
|
||||
inline bool has_used_filament_without_target(const std::vector<FilamentInfo>& result)
|
||||
{
|
||||
for (const auto& f : result) {
|
||||
if (f.get_ams_id() < 0 || f.get_slot_id() < 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// True when at least one used filament already has a target. The used-unmapped
|
||||
// refusal applies to a partially mapped print; a print with no mapping at all
|
||||
// is handled by the existing all-invalid send-path flow.
|
||||
inline bool has_any_mapped_target(const std::vector<FilamentInfo>& result)
|
||||
{
|
||||
for (const auto& f : result) {
|
||||
if (f.get_ams_id() >= 0 && f.get_slot_id() >= 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Refusal reason for a printer agent that serializes lane selection into
|
||||
// print.gcode_file's per-print filament_mapping field.
|
||||
enum class MappingSendError {
|
||||
none, // no refusal; ams_mapping2 is normalized for send
|
||||
unsupported, // a mapping is engaged but the connector did not advertise it
|
||||
incomplete, // a used filament has no target while others do
|
||||
};
|
||||
|
||||
// Applies the send-time mapping policy and normalizes ams_mapping2 in place.
|
||||
// Agents that do not speak filament_mapping keep their legacy payload untouched.
|
||||
inline MappingSendError prepare_filament_mapping_for_send(MachineObject* obj,
|
||||
std::string& ams_mapping2,
|
||||
const std::vector<FilamentInfo>& mapping_result)
|
||||
{
|
||||
if (!obj || !obj->printer_uses_filament_mapping())
|
||||
return MappingSendError::none;
|
||||
|
||||
// A device with no AMS units has one source, the external spool:
|
||||
// auto-mapping force-selects it, which is not a lane choice. Drop it before
|
||||
// the capability gate so it cannot refuse a print nobody mapped.
|
||||
drop_forced_external_selection(obj->HasAms(), ams_mapping2);
|
||||
|
||||
if (!obj->printer_supports_feature("filament_mapping") && has_engaged_filament_mapping(ams_mapping2))
|
||||
return MappingSendError::unsupported;
|
||||
if (has_any_mapped_target(mapping_result) && has_used_filament_without_target(mapping_result))
|
||||
return MappingSendError::incomplete;
|
||||
return MappingSendError::none;
|
||||
}
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
@@ -3622,7 +3622,7 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
|
||||
if (extruder_id + 1 != static_cast<unsigned char>(item.extruder))
|
||||
continue;
|
||||
|
||||
if (item.type != ColorChange)
|
||||
if (item.type != CustomGCode::ColorChange)
|
||||
continue;
|
||||
|
||||
if (!zs_built) {
|
||||
@@ -4789,10 +4789,10 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
|
||||
ImGui::SameLine();
|
||||
|
||||
switch (custom_gcode.type) {
|
||||
case PausePrint: imgui.text(cgcode_pause_str); break;
|
||||
case Template: imgui.text(cgcode_template_str); break;
|
||||
case ToolChange: imgui.text(cgcode_toolchange_str); break;
|
||||
case Custom: imgui.text(cgcode_custom_str); break;
|
||||
case CustomGCode::PausePrint: imgui.text(cgcode_pause_str); break;
|
||||
case CustomGCode::Template: imgui.text(cgcode_template_str); break;
|
||||
case CustomGCode::ToolChange: imgui.text(cgcode_toolchange_str); break;
|
||||
case CustomGCode::Custom: imgui.text(cgcode_custom_str); break;
|
||||
default: imgui.text(cgcode_unknown_str); break;
|
||||
}
|
||||
ImGui::SameLine(max_len);
|
||||
|
||||
@@ -184,12 +184,12 @@ static Slic3r::ColorRGBA DEFAULT_BG_LIGHT_COLOR_DARK = { 0.329f, 0.329f, 0.353f,
|
||||
static Slic3r::ColorRGBA ERROR_BG_LIGHT_COLOR = { 0.753f, 0.192f, 0.039f, 1.0f };
|
||||
static Slic3r::ColorRGBA ERROR_BG_LIGHT_COLOR_DARK = { 0.753f, 0.192f, 0.039f, 1.0f };
|
||||
|
||||
void GLCanvas3D::update_render_colors()
|
||||
void Slic3r::GUI::GLCanvas3D::update_render_colors()
|
||||
{
|
||||
DEFAULT_BG_LIGHT_COLOR = ImGuiWrapper::from_ImVec4(RenderColor::colors[RenderCol_3D_Background]);
|
||||
}
|
||||
|
||||
void GLCanvas3D::load_render_colors()
|
||||
void Slic3r::GUI::GLCanvas3D::load_render_colors()
|
||||
{
|
||||
RenderColor::colors[RenderCol_3D_Background] = ImGuiWrapper::to_ImVec4(DEFAULT_BG_LIGHT_COLOR);
|
||||
}
|
||||
@@ -7970,9 +7970,16 @@ void GLCanvas3D::_render_fps_overlay(int fps) const
|
||||
const float margin = 10.0f * get_scale();
|
||||
const ImVec2 display_size = ImGui::GetIO().DisplaySize;
|
||||
ImVec2 pos(display_size.x - margin, margin);
|
||||
// Last frame's size; zero until the overlay has been shown once.
|
||||
const ImGuiWindow* self = ImGui::FindWindowByName("###fps_overlay");
|
||||
const float left = pos.x - (self != nullptr ? self->Size.x : 0.0f);
|
||||
// The Preview legend takes the top-right corner.
|
||||
if (const ImGuiWindow* legend = ImGui::FindWindowByName("Legend"); m_canvas_type == ECanvasType::CanvasPreview && legend != nullptr && legend->Active)
|
||||
pos = ImVec2(legend->Pos.x - margin, legend->Pos.y);
|
||||
// The toolbar row can reach the corner on a narrow canvas; stack the overlay below it then.
|
||||
else if (m_main_toolbar.is_enabled() &&
|
||||
get_main_toolbar_offset() + m_main_toolbar.get_width() + m_separator_toolbar.get_width() + m_gizmos.get_scaled_total_width() + m_assemble_view_toolbar.get_width() > left)
|
||||
pos.y = std::max(m_main_toolbar.get_height(), m_gizmos.get_scaled_total_height()) + margin;
|
||||
ImGui::SetNextWindowPos(pos, ImGuiCond_Always, ImVec2(1.0f, 0.0f));
|
||||
ImGui::SetNextWindowBgAlpha(0.35f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 8.0f * get_scale());
|
||||
|
||||
@@ -309,6 +309,7 @@ typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS2)(
|
||||
#include <gtk/gtk.h>
|
||||
#endif
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
using namespace std::literals;
|
||||
namespace pt = boost::property_tree;
|
||||
|
||||
@@ -1158,8 +1159,7 @@ void GUI_App::post_init()
|
||||
m_agent->set_on_http_error_fn([this](CloudEvent event, unsigned int status, std::string body) {
|
||||
this->handle_http_error(status, body, event.provider);
|
||||
});
|
||||
if (should_start_ssdp_discovery())
|
||||
m_agent->start_discovery(true, false);
|
||||
m_agent->start_discovery(true, false);
|
||||
}
|
||||
|
||||
//update the plugin tips
|
||||
@@ -4131,18 +4131,6 @@ std::string GUI_App::resolve_printer_agent_id(const std::string& stored_id) cons
|
||||
return (preset_bundle && preset_bundle->is_bbl_vendor()) ? BBL_PRINTER_AGENT_ID : ORCA_PRINTER_AGENT_ID;
|
||||
}
|
||||
|
||||
bool GUI_App::should_start_ssdp_discovery()
|
||||
{
|
||||
// Non-Orca agents (BBL, plugins) keep their own discovery; OrcaSonar only scans in the
|
||||
// background when one of its machines is already configured, otherwise the popup drives it.
|
||||
const std::string agent_id = resolve_printer_agent_id(
|
||||
preset_bundle ? preset_bundle->printers.get_edited_preset().config.opt_string("printer_agent")
|
||||
: std::string());
|
||||
if (agent_id != ORCA_PRINTER_AGENT_ID)
|
||||
return true;
|
||||
return m_device_manager && !m_device_manager->get_my_machine_list(ORCA_PRINTER_AGENT_ID).empty();
|
||||
}
|
||||
|
||||
std::string GUI_App::canonical_printer_agent_id(const std::string& picked_id)
|
||||
{
|
||||
return picked_id == resolve_printer_agent_id("") ? std::string() : picked_id;
|
||||
@@ -4214,8 +4202,7 @@ void GUI_App::switch_printer_agent()
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": printer agent switched to " << effective_agent_id;
|
||||
|
||||
// Start discovery so Python agents can populate the device list via SSDP callback
|
||||
if (should_start_ssdp_discovery())
|
||||
m_agent->start_discovery(true, false);
|
||||
m_agent->start_discovery(true, false);
|
||||
|
||||
// Auto-switch MachineObject (new agent has empty device_info, so always re-select)
|
||||
select_machine(effective_agent_id);
|
||||
|
||||
@@ -399,9 +399,6 @@ public:
|
||||
// Reconcile the live printer agent with the stored preset selection.
|
||||
void switch_printer_agent();
|
||||
|
||||
// Whether the background SSDP scan should run for the effective printer agent.
|
||||
bool should_start_ssdp_discovery();
|
||||
|
||||
std::string resolve_printer_agent_id(const std::string& stored_id) const;
|
||||
// ORCA TODO: in the future, bbl presets should specify "bbl" printer agent id
|
||||
// then, all resolve and canonical would just be ORCA<->""
|
||||
|
||||
@@ -41,19 +41,20 @@ namespace GUI
|
||||
ObjectLayers::ObjectLayers(wxWindow* parent) :
|
||||
OG_Settings(parent, true)
|
||||
{
|
||||
m_grid_sizer = new wxFlexGridSizer(5, 0, wxGetApp().em_unit()); // Title, Min Z, "to", Max Z, unit & buttons sizer
|
||||
m_grid_sizer = new wxFlexGridSizer(5, parent ? parent->FromDIP(2) : 2, wxGetApp().em_unit()); // Title, Min Z, "to", Max Z, buttons sizer
|
||||
m_grid_sizer->SetFlexibleDirection(wxHORIZONTAL);
|
||||
m_grid_sizer->AddGrowableCol(1);
|
||||
m_grid_sizer->AddGrowableCol(3);
|
||||
|
||||
m_og->activate();
|
||||
m_og->sizer->Clear(true);
|
||||
m_og->sizer->Add(m_grid_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, 5);
|
||||
m_og->sizer->Add(m_grid_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, parent ? parent->FromDIP(2) : 2);
|
||||
if (auto stb = dynamic_cast<LabeledStaticBox*>(m_og->stb))
|
||||
stb->SetCornerRadius(0);
|
||||
|
||||
m_bmp_delete = ScalableBitmap(parent, "delete");
|
||||
m_bmp_add = ScalableBitmap(parent, "add");
|
||||
m_bmp_layer = ScalableBitmap(parent, "height_range_layer");
|
||||
}
|
||||
|
||||
void ObjectLayers::select_editor(LayerRangeEditor* editor, const bool is_last_edited_range)
|
||||
@@ -95,10 +96,14 @@ wxSizer* ObjectLayers::create_layer(const t_layer_height_range& range, PlusMinus
|
||||
};
|
||||
|
||||
// Add text
|
||||
auto head_text = new wxStaticText(m_og->ctrl_parent(), wxID_ANY, _L("Height Range"), wxDefaultPosition, wxDefaultSize, wxST_ELLIPSIZE_END);
|
||||
auto title_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
auto head_text = new wxStaticText(m_og->ctrl_parent(), wxID_ANY, _L("Range"));
|
||||
head_text->SetBackgroundStyle(wxBG_STYLE_PAINT);
|
||||
head_text->SetFont(wxGetApp().normal_font());
|
||||
m_grid_sizer->Add(head_text, 0, wxALIGN_CENTER_VERTICAL);
|
||||
auto icon = new wxStaticBitmap(m_og->ctrl_parent(), wxID_ANY, m_bmp_layer.bmp());
|
||||
title_sizer->Add(icon, 0, wxALIGN_CENTER_VERTICAL);
|
||||
title_sizer->Add(head_text, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, m_og->ctrl_parent()->FromDIP(5));
|
||||
m_grid_sizer->Add(title_sizer, 0, wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
// Add control for the "Min Z"
|
||||
|
||||
@@ -126,7 +131,7 @@ wxSizer* ObjectLayers::create_layer(const t_layer_height_range& range, PlusMinus
|
||||
|
||||
m_grid_sizer->Add(editor, 1, wxEXPAND);
|
||||
|
||||
auto middle_text = new wxStaticText(m_og->ctrl_parent(), wxID_ANY, _L("to"), wxDefaultPosition, wxDefaultSize, wxST_ELLIPSIZE_END);
|
||||
auto middle_text = new wxStaticText(m_og->ctrl_parent(), wxID_ANY, "-");
|
||||
middle_text->SetBackgroundStyle(wxBG_STYLE_PAINT);
|
||||
middle_text->SetFont(wxGetApp().normal_font());
|
||||
m_grid_sizer->Add(middle_text, 0, wxALIGN_CENTER_VERTICAL);
|
||||
@@ -156,11 +161,6 @@ wxSizer* ObjectLayers::create_layer(const t_layer_height_range& range, PlusMinus
|
||||
m_grid_sizer->Add(editor, 1, wxEXPAND);
|
||||
|
||||
auto sizer2 = new wxBoxSizer(wxHORIZONTAL);
|
||||
auto unit_text = new wxStaticText(m_og->ctrl_parent(), wxID_ANY, _L("mm"), wxDefaultPosition, wxDefaultSize, wxST_ELLIPSIZE_END);
|
||||
unit_text->SetBackgroundStyle(wxBG_STYLE_PAINT);
|
||||
unit_text->SetFont(wxGetApp().normal_font());
|
||||
sizer2->Add(unit_text, 0, wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
m_grid_sizer->Add(sizer2, 0, wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
// BBS
|
||||
@@ -205,8 +205,9 @@ void ObjectLayers::create_layers_list()
|
||||
|
||||
auto sizer = create_layer(range, del_btn, add_btn);
|
||||
auto b_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
b_sizer->Add(del_btn, 0, wxRIGHT | wxLEFT, em_unit(m_parent));
|
||||
b_sizer->Add(add_btn);
|
||||
b_sizer->Add(del_btn, 0, wxLEFT, m_og->ctrl_parent()->FromDIP(5));
|
||||
b_sizer->AddSpacer(m_og->ctrl_parent()->FromDIP(15));
|
||||
b_sizer->Add(add_btn, 0, wxRIGHT, m_og->ctrl_parent()->FromDIP(5));
|
||||
sizer->Add(b_sizer, 0, wxALIGN_CENTER_HORIZONTAL | wxTOP, m_parent->FromDIP(1)); // aligns +/- buttons vertically since we got 1px gap on bottom of icons
|
||||
|
||||
del_btn->Bind(wxEVT_BUTTON, [del_btn](wxEvent &) {
|
||||
@@ -277,6 +278,7 @@ void ObjectLayers::msw_rescale()
|
||||
{
|
||||
m_bmp_delete.msw_rescale();
|
||||
m_bmp_add.msw_rescale();
|
||||
m_bmp_layer.msw_rescale();
|
||||
|
||||
m_grid_sizer->SetHGap(wxGetApp().em_unit());
|
||||
|
||||
@@ -367,20 +369,17 @@ LayerRangeEditor::LayerRangeEditor( ObjectLayers* parent,
|
||||
m_valid_value(value),
|
||||
m_type(type),
|
||||
m_set_focus_data(set_focus_data_fn),
|
||||
wxTextCtrl(parent->m_og->ctrl_parent(), wxID_ANY, value, wxDefaultPosition,
|
||||
wxSize(em_unit(parent->m_parent), wxDefaultCoord), wxTE_PROCESS_ENTER
|
||||
#ifdef _WIN32
|
||||
| wxBORDER_SIMPLE
|
||||
#endif
|
||||
)
|
||||
TextInput(parent->m_og->ctrl_parent(), value, _L("mm"), "", wxDefaultPosition, wxSize(em_unit(parent->m_parent), wxDefaultCoord), wxTE_PROCESS_ENTER)
|
||||
{
|
||||
this->SetFont(wxGetApp().normal_font());
|
||||
wxGetApp().UpdateDarkUI(this);
|
||||
|
||||
wxTextCtrl* ctrl = GetTextCtrl();
|
||||
|
||||
// Reset m_enter_pressed flag to _false_, when value is editing
|
||||
this->Bind(wxEVT_TEXT, [this](wxEvent&) { m_enter_pressed = false; }, this->GetId());
|
||||
ctrl->Bind(wxEVT_TEXT, [this](wxEvent&) { m_enter_pressed = false; }, ctrl->GetId());
|
||||
|
||||
this->Bind(wxEVT_TEXT_ENTER, [this, edit_fn](wxEvent&)
|
||||
ctrl->Bind(wxEVT_TEXT_ENTER, [this, edit_fn](wxCommandEvent& e)
|
||||
{
|
||||
m_enter_pressed = true;
|
||||
// If LayersList wasn't updated/recreated, we can call wxEVT_KILL_FOCUS.Skip()
|
||||
@@ -395,9 +394,9 @@ LayerRangeEditor::LayerRangeEditor( ObjectLayers* parent,
|
||||
SetValue(m_valid_value);
|
||||
m_call_kill_focus = true;
|
||||
}
|
||||
}, this->GetId());
|
||||
}, ctrl->GetId());
|
||||
|
||||
this->Bind(wxEVT_KILL_FOCUS, [this, edit_fn](wxFocusEvent& e)
|
||||
ctrl->Bind(wxEVT_KILL_FOCUS, [this, edit_fn](wxFocusEvent& e)
|
||||
{
|
||||
if (!m_enter_pressed) {
|
||||
#ifndef __WXGTK__
|
||||
@@ -426,14 +425,14 @@ LayerRangeEditor::LayerRangeEditor( ObjectLayers* parent,
|
||||
m_call_kill_focus = false;
|
||||
e.Skip();
|
||||
}
|
||||
}, this->GetId());
|
||||
}, ctrl->GetId());
|
||||
|
||||
this->Bind(wxEVT_SET_FOCUS, [this, parent](wxFocusEvent& e)
|
||||
ctrl->Bind(wxEVT_SET_FOCUS, [this, parent](wxFocusEvent& e)
|
||||
{
|
||||
set_focus_data();
|
||||
parent->update_scene_from_editor_selection();
|
||||
e.Skip();
|
||||
}, this->GetId());
|
||||
}, ctrl->GetId());
|
||||
|
||||
#ifdef __WXGTK__ // Workaround! To take information about selectable range
|
||||
this->Bind(wxEVT_LEFT_DOWN, [this](wxEvent& e)
|
||||
@@ -447,7 +446,7 @@ LayerRangeEditor::LayerRangeEditor( ObjectLayers* parent,
|
||||
{
|
||||
// select all text using Ctrl+A
|
||||
if (wxGetKeyState(wxKeyCode('A')) && wxGetKeyState(WXK_CONTROL))
|
||||
this->SetSelection(-1, -1); //select all
|
||||
GetTextCtrl()->SetSelection(-1, -1); //select all
|
||||
event.Skip();
|
||||
}));
|
||||
}
|
||||
@@ -477,7 +476,7 @@ coordf_t LayerRangeEditor::get_value()
|
||||
|
||||
void LayerRangeEditor::msw_rescale()
|
||||
{
|
||||
SetMinSize(wxSize(wxGetApp().em_unit(), wxDefaultCoord));
|
||||
Rescale();
|
||||
}
|
||||
|
||||
} //namespace GUI
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/event.h>
|
||||
|
||||
#include <slic3r/GUI/Widgets/TextInput.hpp>
|
||||
|
||||
#ifdef __WXOSX__
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
#endif
|
||||
@@ -34,7 +36,7 @@ enum EditorType
|
||||
etLayerHeight = 4,
|
||||
};
|
||||
|
||||
class LayerRangeEditor : public wxTextCtrl
|
||||
class LayerRangeEditor : public TextInput
|
||||
{
|
||||
bool m_enter_pressed { false };
|
||||
bool m_call_kill_focus { false };
|
||||
@@ -55,6 +57,8 @@ public:
|
||||
|
||||
EditorType type() const {return m_type;}
|
||||
void set_focus_data() const { m_set_focus_data(m_type);}
|
||||
void SetValue(const wxString& value) {GetTextCtrl()->SetValue(value);}
|
||||
wxString GetValue() {return GetTextCtrl()->GetValue();}
|
||||
void msw_rescale();
|
||||
|
||||
private:
|
||||
@@ -65,6 +69,7 @@ class ObjectLayers : public OG_Settings
|
||||
{
|
||||
ScalableBitmap m_bmp_delete;
|
||||
ScalableBitmap m_bmp_add;
|
||||
ScalableBitmap m_bmp_layer;
|
||||
ModelObject* m_object {nullptr};
|
||||
|
||||
wxFlexGridSizer* m_grid_sizer;
|
||||
|
||||
@@ -396,7 +396,7 @@ void Preview::sys_color_changed()
|
||||
// m_layers_slider->sys_color_changed();
|
||||
}
|
||||
|
||||
void Preview::on_tick_changed(Type type)
|
||||
void Preview::on_tick_changed(CustomGCode::Type type)
|
||||
{
|
||||
//if (type == Type::PausePrint) {
|
||||
// m_schedule_background_process();
|
||||
|
||||
@@ -46,6 +46,8 @@
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
using namespace CustomGCode;
|
||||
|
||||
namespace GUI {
|
||||
|
||||
// equal to 25 mm2
|
||||
|
||||
+12
-13
@@ -20,7 +20,6 @@ struct IMGUI_API ImRect;
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
using namespace CustomGCode;
|
||||
class PrintObject;
|
||||
class Layer;
|
||||
|
||||
@@ -89,8 +88,8 @@ public:
|
||||
void SetSliderValues(const std::vector<double> &values);
|
||||
void SetSliderAlternateValues(const std::vector<double> &values) { m_alternate_values = values; }
|
||||
|
||||
Info GetTicksValues() const;
|
||||
void SetTicksValues(const Info &custom_gcode_per_print_z);
|
||||
CustomGCode::Info GetTicksValues() const;
|
||||
void SetTicksValues(const CustomGCode::Info &custom_gcode_per_print_z);
|
||||
void SetLayersTimes(const std::vector<float> &layers_times, float total_time);
|
||||
void SetLayersTimes(const std::vector<double> &layers_times);
|
||||
|
||||
@@ -98,8 +97,8 @@ public:
|
||||
void SetDrawMode(DrawMode mode) { m_draw_mode = mode; }
|
||||
//BBS
|
||||
void SetExtraStyle(long style) { m_extra_style = style; }
|
||||
void SetManipulationMode(Mode mode) { m_mode = mode; }
|
||||
Mode GetManipulationMode() const { return m_mode; }
|
||||
void SetManipulationMode(CustomGCode::Mode mode) { m_mode = mode; }
|
||||
CustomGCode::Mode GetManipulationMode() const { return m_mode; }
|
||||
void SetModeAndOnlyExtruder(const bool is_one_extruder_printed_model, const int only_extruder, bool can_change_color);
|
||||
void SetExtruderColors(const std::vector<std::string> &extruder_colors);
|
||||
|
||||
@@ -117,8 +116,8 @@ public:
|
||||
void UseDefaultColors(bool def_colors_on) { m_ticks.set_default_colors(def_colors_on); }
|
||||
|
||||
void on_mouse_wheel(wxMouseEvent& evt);
|
||||
void post_ticks_changed_event(Type type = Unknown);
|
||||
bool check_ticks_changed_event(Type type);
|
||||
void post_ticks_changed_event(CustomGCode::Type type = CustomGCode::Unknown);
|
||||
bool check_ticks_changed_event(CustomGCode::Type type);
|
||||
bool switch_one_layer_mode();
|
||||
void show_go_to_layer(bool show) { m_show_go_to_layer_dialog = show; }
|
||||
|
||||
@@ -130,9 +129,9 @@ public:
|
||||
bool is_need_post_tick_event() { return m_is_need_post_tick_changed_event; }
|
||||
void reset_post_tick_event(bool val = false) {
|
||||
m_is_need_post_tick_changed_event = val;
|
||||
m_tick_change_event_type = Type::Unknown;
|
||||
m_tick_change_event_type = CustomGCode::Type::Unknown;
|
||||
}
|
||||
Type get_post_tick_event_type() { return m_tick_change_event_type; }
|
||||
CustomGCode::Type get_post_tick_event_type() { return m_tick_change_event_type; }
|
||||
|
||||
float m_scale = 1.0;
|
||||
void set_scale(float scale = 1.0);
|
||||
@@ -143,7 +142,7 @@ public:
|
||||
|
||||
protected:
|
||||
void add_custom_gcode(std::string custom_gcode);
|
||||
void add_code_as_tick(Type type, int selected_extruder = -1);
|
||||
void add_code_as_tick(CustomGCode::Type type, int selected_extruder = -1);
|
||||
void delete_tick(const TickCode& tick);
|
||||
void do_go_to_layer(size_t layer_number); //menu
|
||||
void correct_lower_value();
|
||||
@@ -156,7 +155,7 @@ protected:
|
||||
void render_edit_menu(const TickCode& tick); //menu
|
||||
void draw_background_and_groove(const ImRect& bg_rect, const ImRect& groove);
|
||||
void draw_colored_band(const ImRect& groove, const ImRect& slideable_region);
|
||||
void draw_custom_label_block(const ImVec2 anchor, Type type);
|
||||
void draw_custom_label_block(const ImVec2 anchor, CustomGCode::Type type);
|
||||
void draw_ticks(const ImRect& slideable_region);
|
||||
void draw_tick_on_mouse_position(const ImRect& slideable_region);
|
||||
void show_tooltip(const TickCode& tick); //menu
|
||||
@@ -217,7 +216,7 @@ private:
|
||||
void *m_delete_icon_id;
|
||||
|
||||
DrawMode m_draw_mode = dmRegular;
|
||||
Mode m_mode = SingleExtruder;
|
||||
CustomGCode::Mode m_mode = CustomGCode::SingleExtruder;
|
||||
int m_only_extruder = -1;
|
||||
|
||||
long m_style;
|
||||
@@ -232,7 +231,7 @@ private:
|
||||
bool m_can_change_color;
|
||||
std::string m_print_obj_idxs;
|
||||
bool m_is_need_post_tick_changed_event { false };
|
||||
Type m_tick_change_event_type;
|
||||
CustomGCode::Type m_tick_change_event_type;
|
||||
|
||||
std::vector<double> m_alternate_values;
|
||||
|
||||
|
||||
+90
-119
@@ -1,16 +1,13 @@
|
||||
#include "ImageGrid.h"
|
||||
#include "Printer/PrinterFileSystem.h"
|
||||
#include "Printer/BambuFileGridModel.h"
|
||||
#include "wxExtensions.hpp"
|
||||
#include "Widgets/Label.hpp"
|
||||
#include "I18N.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "GUI.hpp"
|
||||
|
||||
#include <slic3r/GUI/Printer/IFileGridModel.h>
|
||||
#include <utility>
|
||||
#include <boost/smart_ptr/shared_ptr.hpp>
|
||||
#include <boost/smart_ptr/make_shared_object.hpp>
|
||||
#include <wx/colour.h>
|
||||
#include <cstddef>
|
||||
#include <wx/dcclient.h>
|
||||
@@ -79,25 +76,19 @@ ImageGrid::ImageGrid(wxWindow * parent)
|
||||
|
||||
void ImageGrid::SetFileSystem(boost::shared_ptr<PrinterFileSystem> file_sys)
|
||||
{
|
||||
if (m_file_sys) {
|
||||
m_file_sys->Unbind(EVT_MODE_CHANGED, &ImageGrid::changedEvent, this);
|
||||
m_file_sys->Unbind(EVT_FILE_CHANGED, &ImageGrid::changedEvent, this);
|
||||
m_file_sys->Unbind(EVT_THUMBNAIL, &ImageGrid::changedEvent, this);
|
||||
m_file_sys->Unbind(EVT_DOWNLOAD, &ImageGrid::changedEvent, this);
|
||||
}
|
||||
m_file_sys = file_sys;
|
||||
m_model.reset();
|
||||
if (file_sys) {
|
||||
m_model = boost::make_shared<BambuFileGridModel>(file_sys);
|
||||
m_model->SetChangeHandler([this](FileGridChange c) { onModelChange(c); });
|
||||
if (m_file_sys) {
|
||||
m_file_sys->Bind(EVT_MODE_CHANGED, &ImageGrid::changedEvent, this);
|
||||
m_file_sys->Bind(EVT_FILE_CHANGED, &ImageGrid::changedEvent, this);
|
||||
m_file_sys->Bind(EVT_THUMBNAIL, &ImageGrid::changedEvent, this);
|
||||
m_file_sys->Bind(EVT_DOWNLOAD, &ImageGrid::changedEvent, this);
|
||||
}
|
||||
m_row_count = 0;
|
||||
m_col_count = 1;
|
||||
m_row_offset = 0;
|
||||
m_scroll_offset = 0;
|
||||
UpdateFileSystem();
|
||||
}
|
||||
|
||||
void ImageGrid::SetModel(boost::shared_ptr<IFileGridModel> model)
|
||||
{
|
||||
m_file_sys.reset();
|
||||
m_model = std::move(model);
|
||||
if (m_model)
|
||||
m_model->SetChangeHandler([this](FileGridChange c) { onModelChange(c); });
|
||||
m_row_count = 0;
|
||||
m_col_count = 1;
|
||||
m_row_offset = 0;
|
||||
@@ -107,7 +98,7 @@ void ImageGrid::SetModel(boost::shared_ptr<IFileGridModel> model)
|
||||
|
||||
void ImageGrid::SetStatus(ScalableBitmap const & icon, wxString const &msg)
|
||||
{
|
||||
int code = m_model ? m_model->GetLastError() : 1;
|
||||
int code = m_file_sys ? m_file_sys->GetLastError() : 1;
|
||||
m_status_icon = icon;
|
||||
m_status_msg = wxString::Format(msg, code);
|
||||
BOOST_LOG_TRIVIAL(info) << "ImageGrid::SetStatus: " << m_status_msg.ToUTF8().data();
|
||||
@@ -116,26 +107,26 @@ void ImageGrid::SetStatus(ScalableBitmap const & icon, wxString const &msg)
|
||||
|
||||
void Slic3r::GUI::ImageGrid::SetFileType(int type, std::string const &storage)
|
||||
{
|
||||
if (!m_model)
|
||||
if (!m_file_sys)
|
||||
return;
|
||||
m_model->SetFileType((FileGridType) type, storage);
|
||||
m_file_sys->SetFileType((PrinterFileSystem::FileType) type, storage);
|
||||
}
|
||||
|
||||
void Slic3r::GUI::ImageGrid::SetGroupMode(int mode)
|
||||
{
|
||||
if (!m_model)
|
||||
if (!m_file_sys)
|
||||
return;
|
||||
if (m_model->GetCount() == 0) {
|
||||
m_model->SetGroupMode((FileGridGroup) mode);
|
||||
if (m_file_sys->GetCount() == 0) {
|
||||
m_file_sys->SetGroupMode((PrinterFileSystem::GroupMode) mode);
|
||||
return;
|
||||
}
|
||||
wxSize size = GetClientSize();
|
||||
int index = (m_row_offset + 1 < m_row_count || m_row_count == 0)
|
||||
? m_row_offset / 4 * m_col_count
|
||||
: ((m_model->GetCount() + m_col_count - 1) / m_col_count - (size.y + m_border_size.GetHeight() - 1) / m_cell_size.GetHeight()) * m_col_count;
|
||||
time_t time = m_model->GetFile(index).time;
|
||||
m_model->SetGroupMode((FileGridGroup) mode);
|
||||
index = m_model->GetIndexAtTime(time);
|
||||
: ((m_file_sys->GetCount() + m_col_count - 1) / m_col_count - (size.y + m_border_size.GetHeight() - 1) / m_cell_size.GetHeight()) * m_col_count;
|
||||
auto & file = m_file_sys->GetFile(index);
|
||||
m_file_sys->SetGroupMode((PrinterFileSystem::GroupMode) mode);
|
||||
index = m_file_sys->GetIndexAtTime(file.time);
|
||||
// UpdateFileSystem(); call by changed event
|
||||
m_row_offset = index / m_col_count * 4;
|
||||
if (m_row_offset >= m_row_count)
|
||||
@@ -146,8 +137,8 @@ void Slic3r::GUI::ImageGrid::SetGroupMode(int mode)
|
||||
void Slic3r::GUI::ImageGrid::SetSelecting(bool selecting)
|
||||
{
|
||||
m_selecting = selecting;
|
||||
if (m_model)
|
||||
m_model->SelectAll(false);
|
||||
if (m_file_sys)
|
||||
m_file_sys->SelectAll(false);
|
||||
Refresh();
|
||||
}
|
||||
|
||||
@@ -175,14 +166,14 @@ void Slic3r::GUI::ImageGrid::Rescale()
|
||||
void Slic3r::GUI::ImageGrid::Select(size_t index)
|
||||
{
|
||||
if (m_selecting) {
|
||||
m_model->ToggleSelect(index);
|
||||
m_file_sys->ToggleSelect(index);
|
||||
Refresh();
|
||||
return;
|
||||
}
|
||||
if (m_model->GetGroupMode() == FileGridGroup::All) {
|
||||
if (m_file_sys->GetGroupMode() == PrinterFileSystem::G_NONE) {
|
||||
return;
|
||||
}
|
||||
index = m_model->EnterSubGroup(index);
|
||||
index = m_file_sys->EnterSubGroup(index);
|
||||
// UpdateFileSystem(); call by changed event
|
||||
m_row_offset = index / m_col_count * 4;
|
||||
if (m_row_offset >= m_row_count)
|
||||
@@ -202,9 +193,9 @@ void Slic3r::GUI::ImageGrid::DoAction(size_t index, int action)
|
||||
|
||||
void Slic3r::GUI::ImageGrid::UpdateFileSystem()
|
||||
{
|
||||
if (!m_model) return;
|
||||
if (m_model->GetFileType() < FileGridType::Model) {
|
||||
if (m_model->GetGroupMode() == FileGridGroup::All) {
|
||||
if (!m_file_sys) return;
|
||||
if (m_file_sys->GetFileType() < PrinterFileSystem::F_MODEL) {
|
||||
if (m_file_sys->GetGroupMode() == PrinterFileSystem::G_NONE) {
|
||||
m_cell_size.Set(396, 228);
|
||||
m_border_size.Set(384, 216);
|
||||
}
|
||||
@@ -225,10 +216,10 @@ void Slic3r::GUI::ImageGrid::UpdateFileSystem()
|
||||
|
||||
void ImageGrid::UpdateLayout()
|
||||
{
|
||||
if (!m_model) return;
|
||||
if (!m_file_sys) return;
|
||||
wxSize size = GetClientSize();
|
||||
wxSize title_mask_size{0, 60 * em_unit(this) / 10};
|
||||
if (m_model->GetGroupMode() == FileGridGroup::All) {
|
||||
if (m_file_sys->GetGroupMode() == PrinterFileSystem::G_NONE) {
|
||||
title_mask_size.y = 20 * em_unit(this) / 10;
|
||||
size.y -= title_mask_size.y;
|
||||
}
|
||||
@@ -236,7 +227,7 @@ void ImageGrid::UpdateLayout()
|
||||
int cell_height = m_cell_size.GetHeight();
|
||||
int ncol = (size.GetWidth() - cell_width + m_border_size.GetWidth()) / cell_width;
|
||||
if (ncol <= 0) ncol = 1;
|
||||
int total_height = (m_model->GetCount() + ncol - 1) / ncol * cell_height + cell_height - m_border_size.GetHeight();
|
||||
int total_height = (m_file_sys->GetCount() + ncol - 1) / ncol * cell_height + cell_height - m_border_size.GetHeight();
|
||||
int nrow = (total_height - size.GetHeight() + cell_height / 4 - 1) / (cell_height / 4);
|
||||
m_row_offset = m_row_offset * m_col_count / ncol;
|
||||
m_col_count = ncol;
|
||||
@@ -245,7 +236,7 @@ void ImageGrid::UpdateLayout()
|
||||
m_row_offset = m_row_count == 0 ? 0 : m_row_count - 1;
|
||||
m_scroll_offset = 0;
|
||||
// create mask
|
||||
if (m_model->GetGroupMode() == FileGridGroup::All) {
|
||||
if (m_file_sys->GetGroupMode() == PrinterFileSystem::G_NONE) {
|
||||
title_mask_size.x = (m_col_count - 1) * m_cell_size.GetWidth() + m_border_size.GetWidth();
|
||||
}
|
||||
else {
|
||||
@@ -261,7 +252,7 @@ void ImageGrid::UpdateLayout()
|
||||
|
||||
void Slic3r::GUI::ImageGrid::UpdateFocusRange()
|
||||
{
|
||||
if (!m_model) return;
|
||||
if (!m_file_sys) return;
|
||||
wxSize size = GetClientSize();
|
||||
wxPoint off;
|
||||
int index = firstItem(size, off);
|
||||
@@ -270,21 +261,15 @@ void Slic3r::GUI::ImageGrid::UpdateFocusRange()
|
||||
count += m_col_count;
|
||||
off.y += m_cell_size.y;
|
||||
}
|
||||
m_model->SetFocusRange(index, count);
|
||||
}
|
||||
|
||||
bool Slic3r::GUI::ImageGrid::hasSecondAction(const FileGridCard &card) const
|
||||
{
|
||||
return m_show_download || card.downloading ||
|
||||
(m_model->GetFileType() == FileGridType::Model && card.printable);
|
||||
m_file_sys->SetFocusRange(index, count);
|
||||
}
|
||||
|
||||
std::pair<int, size_t> Slic3r::GUI::ImageGrid::HitTest(wxPoint const &pt)
|
||||
{
|
||||
if (!m_model)
|
||||
if (!m_file_sys)
|
||||
return {HIT_NONE, -1};
|
||||
wxSize size = GetClientSize();
|
||||
if (m_model->GetCount() == 0) {
|
||||
if (m_file_sys->GetCount() == 0) {
|
||||
if (wxRect({0, 0}, m_border_size).CenterIn(wxRect({0, 0}, size)).Contains(pt))
|
||||
return {HIT_STATUS, 0};
|
||||
return {HIT_NONE, -1};
|
||||
@@ -302,19 +287,17 @@ std::pair<int, size_t> Slic3r::GUI::ImageGrid::HitTest(wxPoint const &pt)
|
||||
index += m_col_count;
|
||||
off.y -= m_cell_size.GetHeight();
|
||||
}
|
||||
if (index >= m_model->GetCount()) { return {HIT_NONE, -1}; }
|
||||
if (index >= m_file_sys->GetCount()) { return {HIT_NONE, -1}; }
|
||||
if (!m_content_rect.Contains(off)) { return {HIT_NONE, -1}; }
|
||||
if (!m_selecting) {
|
||||
wxRect hover_rect{0, m_content_rect.GetHeight() - m_buttons_background.GetHeight(), m_content_rect.GetWidth(), m_buttons_background.GetHeight()};
|
||||
const FileGridCard &card = m_model->GetFile(index);
|
||||
int btn = card.downloading && card.download_progress >= 0 ? 3 : 2;
|
||||
if (m_model->GetFileType() == FileGridType::Model) {
|
||||
if (m_show_download && card.printable)
|
||||
auto & file = m_file_sys->GetFile(index);
|
||||
int btn = file.IsDownload() && file.DownloadProgress() >= 0 ? 3 : 2;
|
||||
if (m_file_sys->GetFileType() == PrinterFileSystem::F_MODEL) {
|
||||
if (m_show_download)
|
||||
btn = 3;
|
||||
hover_rect.y -= m_content_rect.GetHeight() * 64 / 264;
|
||||
}
|
||||
if (!hasSecondAction(card))
|
||||
btn = 1;
|
||||
if (hover_rect.Contains(off.x, off.y)) {
|
||||
return {HIT_ACTION, index * 4 + off.x * btn / hover_rect.GetWidth()};
|
||||
} // Two buttons
|
||||
@@ -332,12 +315,12 @@ void ImageGrid::mouseMoved(wxMouseEvent& event)
|
||||
m_hit_item = hit.second;
|
||||
if (hit.first == HIT_ITEM) {
|
||||
SetToolTip({});
|
||||
const FileGridCard &card = m_model->GetFile(hit.second);
|
||||
if (auto title = card.title; !title.empty()) {
|
||||
auto tip = wxString::Format(_L("File: %s\nTitle: %s\n"), from_u8(card.name), from_u8(title));
|
||||
auto & file = m_file_sys->GetFile(hit.second);
|
||||
if (auto title = file.Title(); !title.empty()) {
|
||||
auto tip = wxString::Format(_L("File: %s\nTitle: %s\n"), from_u8(file.name), from_u8(title));
|
||||
SetToolTip(tip);
|
||||
} else {
|
||||
SetToolTip(from_u8(card.name));
|
||||
SetToolTip(from_u8(file.name));
|
||||
}
|
||||
} else
|
||||
SetToolTip({});
|
||||
@@ -389,9 +372,9 @@ void ImageGrid::mouseReleased(wxMouseEvent& event)
|
||||
else if (m_hit_type == HIT_ACTION)
|
||||
DoAction(m_hit_item / 4, m_hit_item & 3);
|
||||
else if (m_hit_type == HIT_MODE)
|
||||
SetGroupMode(static_cast<int>(2 - m_hit_item));
|
||||
SetGroupMode(static_cast<PrinterFileSystem::GroupMode>(2 - m_hit_item));
|
||||
else if (m_hit_type == HIT_STATUS)
|
||||
m_model->Retry();
|
||||
m_file_sys->Retry();
|
||||
else
|
||||
Refresh();
|
||||
} else {
|
||||
@@ -420,11 +403,20 @@ void ImageGrid::mouseWheelMoved(wxMouseEvent &event)
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void Slic3r::GUI::ImageGrid::onModelChange(FileGridChange change)
|
||||
void Slic3r::GUI::ImageGrid::changedEvent(wxCommandEvent& evt)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(debug) << "ImageGrid::onModelChange: " << (int) change;
|
||||
if (change == FileGridChange::Files || change == FileGridChange::Mode)
|
||||
evt.Skip();
|
||||
BOOST_LOG_TRIVIAL(debug) << "ImageGrid::changedEvent: " << evt.GetEventType() << " index: " << evt.GetInt()
|
||||
<< " name: " << evt.GetString().ToUTF8().data() << " extra: " << evt.GetExtraLong();
|
||||
if (evt.GetEventType() == EVT_FILE_CHANGED) {
|
||||
if (evt.GetInt() == -1)
|
||||
m_file_sys->DownloadCheckFiles(wxGetApp().app_config->get("download_path"));
|
||||
UpdateFileSystem();
|
||||
}
|
||||
else if (evt.GetEventType() == EVT_MODE_CHANGED)
|
||||
UpdateFileSystem();
|
||||
//else if (evt.GetEventType() == EVT_THUMBNAIL)
|
||||
// RefreshRect(itemRect(evt.GetInt()), false);
|
||||
else
|
||||
Refresh();
|
||||
}
|
||||
@@ -439,7 +431,7 @@ void ImageGrid::paintEvent(wxPaintEvent& evt)
|
||||
size_t Slic3r::GUI::ImageGrid::firstItem(wxSize const &size, wxPoint &off)
|
||||
{
|
||||
int size_y = size.y;
|
||||
if (m_model->GetGroupMode() == FileGridGroup::All)
|
||||
if (m_file_sys->GetGroupMode() == PrinterFileSystem::G_NONE)
|
||||
size_y -= m_title_mask.GetHeight();
|
||||
int offx = (size.x - (m_col_count - 1) * m_cell_size.GetWidth() - m_border_size.GetWidth()) / 2;
|
||||
int offy = (m_row_offset + 1 < m_row_count || m_row_count == 0) ?
|
||||
@@ -447,8 +439,8 @@ size_t Slic3r::GUI::ImageGrid::firstItem(wxSize const &size, wxPoint &off)
|
||||
size_y - (size_y + m_border_size.GetHeight() - 1) / m_cell_size.GetHeight() * m_cell_size.GetHeight();
|
||||
int index = (m_row_offset + 1 < m_row_count || m_row_count == 0) ?
|
||||
m_row_offset / 4 * m_col_count :
|
||||
((m_model->GetCount() + m_col_count - 1) / m_col_count - (size_y + m_border_size.GetHeight() - 1) / m_cell_size.GetHeight()) * m_col_count;
|
||||
if (m_model->GetGroupMode() == FileGridGroup::All)
|
||||
((m_file_sys->GetCount() + m_col_count - 1) / m_col_count - (size_y + m_border_size.GetHeight() - 1) / m_cell_size.GetHeight()) * m_col_count;
|
||||
if (m_file_sys->GetGroupMode() == PrinterFileSystem::G_NONE)
|
||||
offy += m_title_mask.GetHeight();
|
||||
off = wxPoint{offx, offy};
|
||||
return index;
|
||||
@@ -542,7 +534,7 @@ void ImageGrid::render(wxDC& dc)
|
||||
wxSize size = GetClientSize();
|
||||
dc.SetPen(wxPen(GetBackgroundColour()));
|
||||
dc.SetBrush(wxBrush(GetBackgroundColour()));
|
||||
if (!m_model || m_model->GetCount() == 0) {
|
||||
if (!m_file_sys || m_file_sys->GetCount() == 0) {
|
||||
dc.DrawRectangle({ 0, 0, size.x, size.y });
|
||||
if (!m_status_msg.IsEmpty()) {
|
||||
auto si = m_status_icon.GetBmpSize();
|
||||
@@ -570,7 +562,7 @@ void ImageGrid::render(wxDC& dc)
|
||||
{
|
||||
// Draw one line
|
||||
wxPoint pt{off.x, off.y};
|
||||
end = (index + m_col_count) < m_model->GetCount() ? index + m_col_count : m_model->GetCount();
|
||||
end = (index + m_col_count) < m_file_sys->GetCount() ? index + m_col_count : m_file_sys->GetCount();
|
||||
while (index < end) {
|
||||
pt += m_content_rect.GetTopLeft();
|
||||
// Draw content
|
||||
@@ -579,7 +571,7 @@ void ImageGrid::render(wxDC& dc)
|
||||
&ImageGrid::renderContent1,
|
||||
&ImageGrid::renderContent2
|
||||
};
|
||||
(this->*contentRender[static_cast<int>(m_model->GetFileType())])(dc, pt, index, hit_image == index);
|
||||
(this->*contentRender[m_file_sys->GetFileType()])(dc, pt, index, hit_image == index);
|
||||
pt -= m_content_rect.GetTopLeft();
|
||||
// Draw colume spacing at right
|
||||
dc.DrawRectangle({pt.x + m_border_size.GetWidth(), pt.y, m_cell_size.GetWidth() - m_border_size.GetWidth(), m_border_size.GetHeight()});
|
||||
@@ -596,13 +588,13 @@ void ImageGrid::render(wxDC& dc)
|
||||
off.y += m_cell_size.GetHeight();
|
||||
}
|
||||
// Draw floating date range for non-group list
|
||||
if (m_model->GetGroupMode() == FileGridGroup::All && m_model->GetCount() > 0) {
|
||||
if (m_file_sys->GetGroupMode() == PrinterFileSystem::G_NONE && m_file_sys->GetCount() > 0) {
|
||||
//dc.DrawBitmap(m_title_mask, {off.x, 0});
|
||||
dc.DrawRectangle({off.x, 0}, m_title_mask.GetSize());
|
||||
const FileGridCard & file1 = m_model->GetFile(start);
|
||||
const FileGridCard & file2 = m_model->GetFile(end - 1);
|
||||
auto date1 = wxDateTime((time_t) file1.time).Format(_L(TIME_FORMATS[static_cast<int>(m_model->GetGroupMode())]));
|
||||
auto date2 = wxDateTime((time_t) file2.time).Format(_L(TIME_FORMATS[static_cast<int>(m_model->GetGroupMode())]));
|
||||
auto & file1 = m_file_sys->GetFile(start);
|
||||
auto & file2 = m_file_sys->GetFile(end - 1);
|
||||
auto date1 = wxDateTime((time_t) file1.time).Format(_L(TIME_FORMATS[m_file_sys->GetGroupMode()]));
|
||||
auto date2 = wxDateTime((time_t) file2.time).Format(_L(TIME_FORMATS[m_file_sys->GetGroupMode()]));
|
||||
dc.SetFont(Label::Head_16);
|
||||
dc.SetTextForeground(StateColor::darkModeColorFor("#262E30"));
|
||||
dc.DrawText(date1 + " - " + date2, wxPoint{off.x, 2});
|
||||
@@ -612,7 +604,7 @@ void ImageGrid::render(wxDC& dc)
|
||||
dc.DrawRectangle({off.x, off.y, size.x - off.x * 2, size.y - off.y});
|
||||
// Draw position bar
|
||||
if (m_timer.IsRunning()) {
|
||||
int total_height = (m_model->GetCount() + m_col_count - 1) / m_col_count * m_cell_size.GetHeight() + m_cell_size.GetHeight() - m_border_size.GetHeight();
|
||||
int total_height = (m_file_sys->GetCount() + m_col_count - 1) / m_col_count * m_cell_size.GetHeight() + m_cell_size.GetHeight() - m_border_size.GetHeight();
|
||||
if (total_height > size.y) {
|
||||
int offset = (m_row_offset + 1 < m_row_count || m_row_count == 0) ? m_row_offset * (m_cell_size.GetHeight() / 4) : total_height - size.y;
|
||||
wxRect rect = {size.x - 16, offset * size.y / total_height, 8,
|
||||
@@ -626,35 +618,15 @@ void ImageGrid::render(wxDC& dc)
|
||||
void Slic3r::GUI::ImageGrid::renderContent1(wxDC &dc, wxPoint const &pt, int index, bool hit)
|
||||
{
|
||||
bool selected = false;
|
||||
const FileGridCard &card = m_model->GetFile(index, selected);
|
||||
auto &file = m_file_sys->GetFile(index, selected);
|
||||
// Draw thumbnail
|
||||
if (card.thumbnail.IsOk()) {
|
||||
if (m_model->preserve_thumbnail_aspect()) {
|
||||
// Contain: fit the whole thumbnail and letterbox against the tile background.
|
||||
float scale = std::min((float) m_content_rect.GetWidth() / card.thumbnail.GetWidth(),
|
||||
(float) m_content_rect.GetHeight() / card.thumbnail.GetHeight());
|
||||
int thumb_w = (int) (card.thumbnail.GetWidth() * scale);
|
||||
int thumb_h = (int) (card.thumbnail.GetHeight() * scale);
|
||||
int offx = (m_content_rect.GetWidth() - thumb_w) / 2;
|
||||
int offy = (m_content_rect.GetHeight() - thumb_h) / 2;
|
||||
auto brush = dc.GetBrush();
|
||||
auto pen = dc.GetPen();
|
||||
dc.SetBrush(StateColor::darkModeColorFor(0xEEEEEE));
|
||||
dc.SetPen(StateColor::darkModeColorFor(0xEEEEEE));
|
||||
dc.DrawRectangle(pt, m_content_rect.GetSize());
|
||||
dc.SetUserScale(scale, scale);
|
||||
dc.DrawBitmap(card.thumbnail, {(int) ((pt.x + offx) / scale), (int) ((pt.y + offy) / scale)});
|
||||
dc.SetUserScale(1, 1);
|
||||
dc.SetBrush(brush);
|
||||
dc.SetPen(pen);
|
||||
} else {
|
||||
float hs = (float) m_content_rect.GetWidth() / card.thumbnail.GetWidth();
|
||||
float vs = (float) m_content_rect.GetHeight() / card.thumbnail.GetHeight();
|
||||
dc.SetUserScale(hs, vs);
|
||||
dc.DrawBitmap(card.thumbnail, {(int) (pt.x / hs), (int) (pt.y / vs)});
|
||||
dc.SetUserScale(1, 1);
|
||||
}
|
||||
if (m_model->GetGroupMode() != FileGridGroup::All) { dc.DrawBitmap(m_title_mask, pt); }
|
||||
if (file.thumbnail.IsOk()) {
|
||||
float hs = (float) m_content_rect.GetWidth() / file.thumbnail.GetWidth();
|
||||
float vs = (float) m_content_rect.GetHeight() / file.thumbnail.GetHeight();
|
||||
dc.SetUserScale(hs, vs);
|
||||
dc.DrawBitmap(file.thumbnail, {(int) (pt.x / hs), (int) (pt.y / vs)});
|
||||
dc.SetUserScale(1, 1);
|
||||
if (m_file_sys->GetGroupMode() != PrinterFileSystem::G_NONE) { dc.DrawBitmap(m_title_mask, pt); }
|
||||
}
|
||||
bool show_download_state_always = true;
|
||||
// Draw checked icon
|
||||
@@ -662,14 +634,14 @@ void Slic3r::GUI::ImageGrid::renderContent1(wxDC &dc, wxPoint const &pt, int ind
|
||||
dc.DrawBitmap(selected ? m_checked_icon.bmp() : m_unchecked_icon.bmp(), pt + wxPoint{10, 10});
|
||||
// can't handle alpha
|
||||
// dc.GradientFillLinear({pt.x, pt.y, m_border_size.GetWidth(), 60}, wxColour(0x6F, 0x6F, 0x6F, 0x99), wxColour(0x6F, 0x6F, 0x6F, 0), wxBOTTOM);
|
||||
else if (m_model->GetGroupMode() == FileGridGroup::All) {
|
||||
else if (m_file_sys->GetGroupMode() == PrinterFileSystem::G_NONE) {
|
||||
wxString nonHoverText;
|
||||
wxString secondAction = m_show_download ? _L("Download") : "";
|
||||
wxString thirdAction;
|
||||
int states = 0;
|
||||
// Draw download progress
|
||||
if (card.downloading) {
|
||||
int progress = card.download_progress;
|
||||
if (file.IsDownload()) {
|
||||
int progress = file.DownloadProgress();
|
||||
if (progress == -1) {
|
||||
secondAction = _L("Cancel");
|
||||
nonHoverText = _L("Download waiting...");
|
||||
@@ -687,7 +659,7 @@ void Slic3r::GUI::ImageGrid::renderContent1(wxDC &dc, wxPoint const &pt, int ind
|
||||
thirdAction = wxString::Format(L"%d%%...", progress);
|
||||
}
|
||||
}
|
||||
if (m_model->GetFileType() == FileGridType::Model && card.printable) {
|
||||
if (m_file_sys->GetFileType() == PrinterFileSystem::F_MODEL) {
|
||||
if (secondAction != _L("Play"))
|
||||
thirdAction = secondAction;
|
||||
secondAction = _L_CONTEXT("Print", "Verb");
|
||||
@@ -697,8 +669,7 @@ void Slic3r::GUI::ImageGrid::renderContent1(wxDC &dc, wxPoint const &pt, int ind
|
||||
wxArrayString texts;
|
||||
if (hit) {
|
||||
texts.Add(_L("Delete"));
|
||||
if (hasSecondAction(card))
|
||||
texts.Add(secondAction);
|
||||
texts.Add(secondAction);
|
||||
if (!thirdAction.IsEmpty())
|
||||
texts.Add(thirdAction);
|
||||
renderButtons(dc, texts, rect, m_hit_type == HIT_ACTION ? m_hit_item & 3 : -1, states);
|
||||
@@ -708,7 +679,7 @@ void Slic3r::GUI::ImageGrid::renderContent1(wxDC &dc, wxPoint const &pt, int ind
|
||||
}
|
||||
} else {
|
||||
dc.SetTextForeground(*wxWHITE); // time text color
|
||||
auto date = wxDateTime((time_t) card.time).Format(_L(TIME_FORMATS[static_cast<int>(m_model->GetGroupMode())]));
|
||||
auto date = wxDateTime((time_t) file.time).Format(_L(TIME_FORMATS[m_file_sys->GetGroupMode()]));
|
||||
dc.DrawText(date, pt + wxPoint{24, 16});
|
||||
}
|
||||
if (m_selecting && show_download_state_always)
|
||||
@@ -717,7 +688,7 @@ void Slic3r::GUI::ImageGrid::renderContent1(wxDC &dc, wxPoint const &pt, int ind
|
||||
|
||||
void Slic3r::GUI::ImageGrid::renderContent2(wxDC &dc, wxPoint const &pt, int index, bool hit)
|
||||
{
|
||||
const FileGridCard &card = m_model->GetFile(index);
|
||||
auto &file = m_file_sys->GetFile(index);
|
||||
// Draw thumbnail & buttons
|
||||
int h = m_content_rect.GetHeight() * 64 / 264;
|
||||
m_content_rect.SetHeight(m_content_rect.GetHeight() - h);
|
||||
@@ -740,14 +711,14 @@ void Slic3r::GUI::ImageGrid::renderContent2(wxDC &dc, wxPoint const &pt, int ind
|
||||
auto em = em_unit(this);
|
||||
wxRect rect{pt.x, pt.y + m_content_rect.GetHeight() - h, m_content_rect.GetWidth(), h / 2};
|
||||
rect.Deflate(em, 0);
|
||||
renderText2(dc, from_u8(card.name), rect);
|
||||
renderText2(dc, from_u8(file.name), rect);
|
||||
rect.Offset(0, h / 2);
|
||||
rect.SetWidth(rect.GetWidth() / 2 - em);
|
||||
dc.SetFont(Label::Body_13);
|
||||
dc.SetTextForeground(StateColor::darkModeColorFor("#6B6B6B"));
|
||||
renderIconText(dc, m_model_time_icon, card.time_text.empty() ? wxString("0m") : from_u8(card.time_text), rect);
|
||||
renderIconText(dc, m_model_time_icon, file.Metadata("Time", "0m"), rect);
|
||||
rect.Offset(m_content_rect.GetWidth() / 2, 0);
|
||||
renderIconText(dc, m_model_weight_icon, card.weight_text.empty() ? wxString("0g") : from_u8(card.weight_text), rect);
|
||||
renderIconText(dc, m_model_weight_icon, file.Metadata("Weight", "0g"), rect);
|
||||
}
|
||||
|
||||
void Slic3r::GUI::ImageGrid::renderButtons(wxDC &dc, wxArrayString const &texts, wxRect const &rect2, size_t hit, int states)
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
|
||||
#include "Widgets/StateColor.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
#include "Printer/IFileGridModel.h"
|
||||
|
||||
class Button;
|
||||
class Label;
|
||||
@@ -45,8 +44,6 @@ public:
|
||||
|
||||
void SetFileSystem(boost::shared_ptr<PrinterFileSystem> file_sys);
|
||||
|
||||
void SetModel(boost::shared_ptr<IFileGridModel> model);
|
||||
|
||||
void SetStatus(ScalableBitmap const & icon, wxString const &msg);
|
||||
|
||||
boost::shared_ptr<PrinterFileSystem> GetFileSystem() { return m_file_sys; }
|
||||
@@ -79,12 +76,9 @@ protected:
|
||||
|
||||
std::pair<int, size_t> HitTest(wxPoint const &pt);
|
||||
|
||||
// True when the hover bar shows a second action next to Delete.
|
||||
bool hasSecondAction(const FileGridCard &card) const;
|
||||
|
||||
protected:
|
||||
|
||||
void onModelChange(FileGridChange change);
|
||||
void changedEvent(wxCommandEvent& evt);
|
||||
|
||||
void paintEvent(wxPaintEvent& evt);
|
||||
|
||||
@@ -123,7 +117,6 @@ protected:
|
||||
|
||||
private:
|
||||
boost::shared_ptr<PrinterFileSystem> m_file_sys;
|
||||
boost::shared_ptr<IFileGridModel> m_model;
|
||||
ScalableBitmap m_status_icon;
|
||||
wxString m_status_msg;
|
||||
|
||||
|
||||
@@ -12,8 +12,6 @@
|
||||
#include "Job.hpp"
|
||||
#include "slic3r/GUI/DeviceCore/DevStorage.h"
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
@@ -26,9 +24,9 @@ class PrintPrepareData
|
||||
public:
|
||||
bool is_from_plater = true;
|
||||
int plate_idx;
|
||||
fs::path _3mf_path;
|
||||
fs::path _3mf_config_path;
|
||||
fs::path _temp_path;
|
||||
boost::filesystem::path _3mf_path;
|
||||
boost::filesystem::path _3mf_config_path;
|
||||
boost::filesystem::path _temp_path;
|
||||
PrintPrepareData() {
|
||||
plate_idx = 0;
|
||||
}
|
||||
|
||||
@@ -219,40 +219,26 @@ MediaFilePanel::MediaFilePanel(wxWindow * parent)
|
||||
SetSelecting(false);
|
||||
});
|
||||
|
||||
Bind(wxEVT_SHOW, &MediaFilePanel::on_show_hide, this);
|
||||
// A Device sub-tab switch hides the page container (StoragePanel); a main tab
|
||||
// switch hides MonitorPanel inside LazyPage. Neither event reaches the other,
|
||||
// so watch every ancestor below the top-level frame.
|
||||
for (wxWindow* w = GetParent(); w && !w->IsTopLevel(); w = w->GetParent()) {
|
||||
w->Bind(wxEVT_SHOW, &MediaFilePanel::on_show_hide, this);
|
||||
m_show_hosts.push_back(w);
|
||||
}
|
||||
auto onShowHide = [this](auto &e) {
|
||||
e.Skip();
|
||||
if (auto w = dynamic_cast<wxWindow *>(e.GetEventObject()); !w || w->IsBeingDeleted())
|
||||
return;
|
||||
CallAfter([this] {
|
||||
auto fs = m_image_grid ? m_image_grid->GetFileSystem() : nullptr;
|
||||
if (fs) IsShownOnScreen() ? fs->Start() : fs->Stop();
|
||||
});
|
||||
};
|
||||
Bind(wxEVT_SHOW, onShowHide);
|
||||
parent->GetParent()->Bind(wxEVT_SHOW, onShowHide);
|
||||
|
||||
m_lan_user = "bblp";
|
||||
}
|
||||
|
||||
MediaFilePanel::~MediaFilePanel()
|
||||
{
|
||||
Unbind(wxEVT_SHOW, &MediaFilePanel::on_show_hide, this);
|
||||
for (wxWindow* w : m_show_hosts)
|
||||
if (w && !w->IsBeingDeleted())
|
||||
w->Unbind(wxEVT_SHOW, &MediaFilePanel::on_show_hide, this);
|
||||
m_show_hosts.clear();
|
||||
|
||||
UpdateByObj(nullptr);
|
||||
}
|
||||
|
||||
void MediaFilePanel::on_show_hide(wxShowEvent& e)
|
||||
{
|
||||
e.Skip();
|
||||
if (auto w = dynamic_cast<wxWindow*>(e.GetEventObject()); !w || w->IsBeingDeleted())
|
||||
return;
|
||||
CallAfter([this] {
|
||||
auto fs = m_image_grid ? m_image_grid->GetFileSystem() : nullptr;
|
||||
if (fs) IsShownOnScreen() ? fs->Start() : fs->Stop();
|
||||
});
|
||||
}
|
||||
|
||||
void MediaFilePanel::UpdateByObj(MachineObject* obj)
|
||||
{
|
||||
bool sdcard_state_changed = false;
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include <boost/smart_ptr/shared_ptr.hpp>
|
||||
#include <cstddef>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include "GUI_Utils.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
@@ -54,8 +53,6 @@ public:
|
||||
private:
|
||||
void modeChanged(wxCommandEvent & e);
|
||||
|
||||
void on_show_hide(wxShowEvent & e);
|
||||
|
||||
void fetchUrl(boost::weak_ptr<PrinterFileSystem> fs);
|
||||
|
||||
void doAction(size_t index, int action);
|
||||
@@ -102,8 +99,6 @@ private:
|
||||
int m_last_mode = 0;
|
||||
int m_last_type = 0;
|
||||
std::set<int> m_last_errors;
|
||||
|
||||
std::vector<wxWindow*> m_show_hosts;
|
||||
};
|
||||
|
||||
|
||||
|
||||
+10
-10
@@ -15,6 +15,7 @@
|
||||
#include "slic3r/GUI/StatusPanel.hpp"
|
||||
#include "slic3r/GUI/UpgradePanel.hpp"
|
||||
#include "slic3r/GUI/Widgets/SideTools.hpp"
|
||||
#include "slic3r/GUI/Printer/PrinterFileSystem.h"
|
||||
#include <wx/app.h>
|
||||
#include <wx/bookctrl.h>
|
||||
#include <wx/button.h>
|
||||
@@ -43,7 +44,7 @@
|
||||
#include "Plater.hpp"
|
||||
#include "MainFrame.hpp"
|
||||
#include "MediaPlayCtrl.h"
|
||||
#include "StoragePanel.h"
|
||||
#include "MediaFilePanel.h"
|
||||
#include "Plater.hpp"
|
||||
#include "BindDialog.hpp"
|
||||
|
||||
@@ -199,9 +200,9 @@ void MonitorPanel::init_tabpanel()
|
||||
m_tabpanel->SetBackgroundColour(wxColour("#FEFFFF"));
|
||||
m_tabpanel->Bind(wxEVT_BOOKCTRL_PAGE_CHANGED, [this](wxBookCtrlEvent& e) {
|
||||
auto page = m_tabpanel->GetCurrentPage();
|
||||
if (page == m_storage_panel) {
|
||||
if (page == m_media_file_panel) {
|
||||
auto title = m_tabpanel->GetPageText(m_tabpanel->GetSelection());
|
||||
m_storage_panel->SwitchStorage(title == _L("Storage"));
|
||||
m_media_file_panel->SwitchStorage(title == _L("Storage"));
|
||||
}
|
||||
// The first page is selected while the panel is built off screen.
|
||||
if (page->IsShownOnScreen())
|
||||
@@ -215,8 +216,8 @@ void MonitorPanel::init_tabpanel()
|
||||
add_build_steps_of(*m_status_info_panel);
|
||||
m_tabpanel->AddPage(m_status_info_panel, _L("Status"), true);
|
||||
add_build_step([this] {
|
||||
m_storage_panel = new StoragePanel(m_tabpanel);
|
||||
m_tabpanel->AddPage(m_storage_panel, _L("Storage"), false);
|
||||
m_media_file_panel = new MediaFilePanel(m_tabpanel);
|
||||
m_tabpanel->AddPage(m_media_file_panel, _L("Storage"), false);
|
||||
});
|
||||
add_build_step([this] {
|
||||
m_upgrade_panel = new UpgradePanel(m_tabpanel);
|
||||
@@ -265,8 +266,7 @@ void MonitorPanel::on_sys_color_changed()
|
||||
{
|
||||
m_status_info_panel->on_sys_color_changed();
|
||||
m_upgrade_panel->on_sys_color_changed();
|
||||
m_storage_panel->on_sys_color_changed();
|
||||
m_storage_panel->Rescale();
|
||||
m_media_file_panel->Rescale();
|
||||
}
|
||||
|
||||
void MonitorPanel::msw_rescale()
|
||||
@@ -278,7 +278,7 @@ void MonitorPanel::msw_rescale()
|
||||
m_tabpanel->Rescale();
|
||||
//m_status_add_machine_panel->msw_rescale();
|
||||
m_status_info_panel->msw_rescale();
|
||||
m_storage_panel->Rescale();
|
||||
m_media_file_panel->Rescale();
|
||||
m_upgrade_panel->msw_rescale();
|
||||
m_hms_panel->msw_rescale();
|
||||
|
||||
@@ -425,8 +425,8 @@ void MonitorPanel::update_all()
|
||||
}
|
||||
} else if (current_page == m_upgrade_panel) {
|
||||
m_upgrade_panel->update(obj);
|
||||
} else if (current_page == m_storage_panel) {
|
||||
m_storage_panel->UpdateByObj(obj);
|
||||
} else if (current_page == m_media_file_panel) {
|
||||
m_media_file_panel->UpdateByObj(obj);
|
||||
}
|
||||
|
||||
if (current_page == m_hms_panel || (obj->GetHMS()->GetHMSItems().size() != m_hms_panel->temp_hms_list.size())) {
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
class StoragePanel;
|
||||
class MediaFilePanel;
|
||||
|
||||
class AddMachinePanel : public wxPanel
|
||||
{
|
||||
@@ -86,7 +86,7 @@ private:
|
||||
wxSizer* m_main_sizer{ nullptr };
|
||||
|
||||
StatusPanel* m_status_info_panel{ nullptr };
|
||||
StoragePanel* m_storage_panel{ nullptr };
|
||||
MediaFilePanel* m_media_file_panel{ nullptr };
|
||||
UpgradePanel* m_upgrade_panel{ nullptr };
|
||||
HMSPanel* m_hms_panel{ nullptr };
|
||||
|
||||
|
||||
@@ -1,275 +0,0 @@
|
||||
#include "OrcaFilesPanel.h"
|
||||
|
||||
#include "DeviceManager.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "GUI.hpp"
|
||||
#include "I18N.hpp"
|
||||
#include "ImageGrid.h"
|
||||
#include "MsgDialog.hpp"
|
||||
#include "Widgets/Button.hpp"
|
||||
#include "Widgets/Label.hpp"
|
||||
#include "Widgets/StaticBox.hpp"
|
||||
#include "Widgets/StateColor.hpp"
|
||||
#include "slic3r/Utils/NetworkAgent.hpp"
|
||||
#include "slic3r/Utils/bambu_networking.hpp"
|
||||
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <slic3r/GUI/wxExtensions.hpp>
|
||||
#include <slic3r/GUI/Printer/IFileGridModel.h>
|
||||
#include <cstddef>
|
||||
#include <boost/smart_ptr/make_shared_object.hpp>
|
||||
#include <wx/colour.h>
|
||||
#include <wx/panel.h>
|
||||
#include <wx/event.h>
|
||||
#include <wx/gdicmn.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <utility>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
OrcaFilesPanel::OrcaFilesPanel(wxWindow* parent)
|
||||
: wxPanel(parent, wxID_ANY)
|
||||
, m_bmp_loading(this, "media_loading", 0)
|
||||
, m_bmp_failed(this, "media_failed", 0)
|
||||
, m_bmp_empty(this, "media_empty", 0)
|
||||
{
|
||||
const wxColour light_background("#EEEEEE");
|
||||
SetBackgroundColour(wxGetApp().dark_mode() ? StateColor::darkModeColorFor(light_background) : light_background);
|
||||
|
||||
auto* sizer = new wxBoxSizer(wxVERTICAL);
|
||||
auto* toolbar = new wxBoxSizer(wxHORIZONTAL);
|
||||
toolbar->SetMinSize({-1, 75 * em_unit(this) / 10});
|
||||
|
||||
m_root_label = new Label(this, _L("gcodes"));
|
||||
m_root_label->SetFont(Label::Head_16);
|
||||
toolbar->Add(m_root_label, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, 24);
|
||||
|
||||
m_time_panel = new ::StaticBox(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
|
||||
m_time_panel->SetCornerRadius(0);
|
||||
m_button_year = new ::Button(m_time_panel, _L("Year"), "", wxBORDER_NONE);
|
||||
m_button_month = new ::Button(m_time_panel, _L("Month"), "", wxBORDER_NONE);
|
||||
m_button_all = new ::Button(m_time_panel, _L("All Files"), "", wxBORDER_NONE);
|
||||
m_button_year->SetToolTip(_L("Group files by year, recent first."));
|
||||
m_button_month->SetToolTip(_L("Group files by month, recent first."));
|
||||
m_button_all->SetToolTip(_L("Show all files, recent first."));
|
||||
for (auto* button : {m_button_year, m_button_month, m_button_all}) {
|
||||
button->SetBackgroundColor(StateColor(
|
||||
std::make_pair(0xEEEEEE, static_cast<int>(StateColor::Checked)),
|
||||
std::make_pair(*wxLIGHT_GREY, static_cast<int>(StateColor::Hovered)),
|
||||
std::make_pair(*wxWHITE, static_cast<int>(StateColor::Normal))));
|
||||
button->SetTextColor(StateColor(
|
||||
std::make_pair(0x3B4446, static_cast<int>(StateColor::Checked)),
|
||||
std::make_pair(*wxLIGHT_GREY, static_cast<int>(StateColor::Hovered)),
|
||||
std::make_pair(0xABACAC, static_cast<int>(StateColor::Normal))));
|
||||
button->SetCanFocus(false);
|
||||
}
|
||||
auto* time_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
time_sizer->Add(m_button_year, 0, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, 24);
|
||||
time_sizer->Add(m_button_month, 0, wxALIGN_CENTER_VERTICAL);
|
||||
time_sizer->Add(m_button_all, 0, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, 24);
|
||||
m_time_panel->SetSizer(time_sizer);
|
||||
toolbar->AddStretchSpacer(1);
|
||||
toolbar->Add(m_time_panel, 0, wxALIGN_CENTER_VERTICAL);
|
||||
toolbar->AddStretchSpacer(1);
|
||||
|
||||
m_button_refresh = new ::Button(this, _L("Refresh"));
|
||||
m_button_refresh->SetToolTip(_L("Reload file list from printer."));
|
||||
m_button_refresh->SetFont(Label::Body_12);
|
||||
m_button_refresh->SetCornerRadius(12);
|
||||
m_button_refresh->SetPaddingSize({10, 6});
|
||||
m_button_refresh->SetCanFocus(false);
|
||||
m_button_refresh->SetBorderWidth(0);
|
||||
toolbar->Add(m_button_refresh, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 24);
|
||||
sizer->Add(toolbar, 0, wxEXPAND);
|
||||
|
||||
m_image_grid = new ImageGrid(this);
|
||||
// Theme this grid instance without changing the shared Bambu defaults.
|
||||
m_image_grid->SetBackgroundColour(GetBackgroundColour());
|
||||
m_image_grid->SetSelecting(false);
|
||||
m_image_grid->ShowDownload(false);
|
||||
m_image_grid->SetStatus(m_bmp_failed, _L("Please confirm if the printer is connected."));
|
||||
sizer->Add(m_image_grid, 1, wxEXPAND);
|
||||
SetSizer(sizer);
|
||||
applyThemeColors();
|
||||
updateGroupButtons(m_group_mode);
|
||||
|
||||
auto group_clicked = [this](wxCommandEvent& event) {
|
||||
const FileGridGroup mode = event.GetEventObject() == m_button_year ? FileGridGroup::Year :
|
||||
event.GetEventObject() == m_button_month ? FileGridGroup::Month : FileGridGroup::All;
|
||||
m_image_grid->SetGroupMode(static_cast<int>(mode));
|
||||
updateGroupButtons(mode);
|
||||
};
|
||||
m_button_year->Bind(wxEVT_COMMAND_BUTTON_CLICKED, group_clicked);
|
||||
m_button_month->Bind(wxEVT_COMMAND_BUTTON_CLICKED, group_clicked);
|
||||
m_button_all->Bind(wxEVT_COMMAND_BUTTON_CLICKED, group_clicked);
|
||||
|
||||
m_button_refresh->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this](wxCommandEvent& event) {
|
||||
event.Skip();
|
||||
if (m_model)
|
||||
m_model->Refresh();
|
||||
});
|
||||
|
||||
m_image_grid->Bind(EVT_ITEM_ACTION, [this](wxCommandEvent& event) {
|
||||
const int action = event.GetInt();
|
||||
if (!m_model || m_device_id.empty())
|
||||
return;
|
||||
|
||||
const size_t index = static_cast<size_t>(event.GetExtraLong());
|
||||
if (index >= m_model->GetCount())
|
||||
return;
|
||||
const FileGridCard& card = m_model->GetFile(index);
|
||||
if (card.id.empty())
|
||||
return;
|
||||
const std::string path = card.id;
|
||||
const std::string name = card.name;
|
||||
|
||||
if (action == 0) {
|
||||
MessageDialog dlg(this,
|
||||
wxString::Format(_L("Do you want to delete the file '%s' from printer?"), from_u8(name)),
|
||||
_L("Delete file"), wxYES_NO | wxICON_WARNING);
|
||||
if (dlg.ShowModal() != wxID_YES)
|
||||
return;
|
||||
|
||||
m_model->DeleteFile(path, [this](bool ok) {
|
||||
if (ok)
|
||||
return;
|
||||
MessageDialog(this, _L("Failed to delete the file from printer."), _L("Delete file"),
|
||||
wxOK | wxICON_ERROR).ShowModal();
|
||||
});
|
||||
} else if (action == 1) {
|
||||
// OrcaSonar unpacks a .gcode.3mf to its plate G-code before starting the print.
|
||||
MessageDialog dlg(this,
|
||||
wxString::Format(_L("Do you want to print the file '%s' from printer?"), from_u8(name)),
|
||||
_L("Print file"), wxYES_NO | wxICON_WARNING);
|
||||
if (dlg.ShowModal() != wxID_YES)
|
||||
return;
|
||||
|
||||
NetworkAgent* agent = wxGetApp().getAgent();
|
||||
if (!agent)
|
||||
return;
|
||||
|
||||
PrintParams params;
|
||||
params.dev_id = m_device_id;
|
||||
params.dst_file = path;
|
||||
params.connection_type = "lan";
|
||||
if (agent->start_sdcard_print(params, {}, {}) != BAMBU_NETWORK_SUCCESS)
|
||||
MessageDialog(this, _L("Failed to start the print job."), _L("Print file"),
|
||||
wxOK | wxICON_ERROR).ShowModal();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
OrcaFilesPanel::~OrcaFilesPanel()
|
||||
{
|
||||
if (m_model)
|
||||
m_model->SetStatusHandler({});
|
||||
if (m_model)
|
||||
m_model->SetGroupModeHandler({});
|
||||
m_image_grid->SetModel(nullptr);
|
||||
m_model.reset();
|
||||
}
|
||||
|
||||
void OrcaFilesPanel::UpdateByObj(MachineObject* obj)
|
||||
{
|
||||
const std::string device_id = obj ? obj->get_dev_id() : std::string();
|
||||
if (device_id == m_device_id)
|
||||
return;
|
||||
|
||||
m_device_id = device_id;
|
||||
if (m_model)
|
||||
m_model->SetStatusHandler({});
|
||||
if (m_model)
|
||||
m_model->SetGroupModeHandler({});
|
||||
m_image_grid->SetModel(nullptr);
|
||||
m_model.reset();
|
||||
|
||||
if (m_device_id.empty()) {
|
||||
m_button_refresh->Enable(false);
|
||||
m_image_grid->SetStatus(m_bmp_failed, _L("Please confirm if the printer is connected."));
|
||||
return;
|
||||
}
|
||||
|
||||
m_model = boost::make_shared<RemoteFileGridModel>(m_device_id);
|
||||
m_model->SetStatusHandler([this](RemoteFileGridModel::Status status) { updateStatus(status); });
|
||||
m_model->SetGroupModeHandler([this](FileGridGroup mode) { updateGroupButtons(mode); });
|
||||
m_model->SetGroupMode(m_group_mode);
|
||||
m_image_grid->SetModel(m_model);
|
||||
m_image_grid->SetFileType(static_cast<int>(FileGridType::Model), {});
|
||||
m_button_refresh->Enable(true);
|
||||
m_model->Refresh();
|
||||
}
|
||||
|
||||
void OrcaFilesPanel::updateStatus(RemoteFileGridModel::Status status)
|
||||
{
|
||||
switch (status) {
|
||||
case RemoteFileGridModel::Status::Loading:
|
||||
m_image_grid->SetStatus(m_bmp_loading, _L("Loading file list..."));
|
||||
break;
|
||||
case RemoteFileGridModel::Status::Ready:
|
||||
break;
|
||||
case RemoteFileGridModel::Status::Empty:
|
||||
m_image_grid->SetStatus(m_bmp_empty, _L("No files"));
|
||||
break;
|
||||
case RemoteFileGridModel::Status::Failed:
|
||||
m_image_grid->SetStatus(m_bmp_failed, _L("Load failed"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OrcaFilesPanel::Rescale()
|
||||
{
|
||||
m_bmp_loading.msw_rescale();
|
||||
m_bmp_failed.msw_rescale();
|
||||
m_bmp_empty.msw_rescale();
|
||||
|
||||
auto* toolbar = GetSizer()->GetItem(static_cast<size_t>(0))->GetSizer();
|
||||
toolbar->SetMinSize({-1, 75 * em_unit(this) / 10});
|
||||
m_root_label->SetFont(Label::Head_16);
|
||||
m_button_refresh->Rescale();
|
||||
m_button_year->Rescale();
|
||||
m_button_month->Rescale();
|
||||
m_button_all->Rescale();
|
||||
m_image_grid->Rescale();
|
||||
}
|
||||
|
||||
void OrcaFilesPanel::on_sys_color_changed()
|
||||
{
|
||||
applyThemeColors();
|
||||
Layout();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void OrcaFilesPanel::applyThemeColors()
|
||||
{
|
||||
const bool dark = wxGetApp().dark_mode();
|
||||
const wxColour light_background("#EEEEEE");
|
||||
const wxColour light_text("#262E30");
|
||||
const wxColour light_teal("#009688");
|
||||
const wxColour background = dark ? StateColor::darkModeColorFor(light_background) : light_background;
|
||||
|
||||
SetBackgroundColour(background);
|
||||
m_root_label->SetBackgroundColour(background);
|
||||
m_root_label->SetForegroundColour(dark ? StateColor::darkModeColorFor(light_text) : light_text);
|
||||
m_time_panel->SetBackgroundColour(background);
|
||||
m_button_refresh->SetBackgroundColorNormal(dark ? StateColor::darkModeColorFor(light_teal) : light_teal);
|
||||
m_button_refresh->SetTextColorNormal(*wxWHITE);
|
||||
m_image_grid->SetBackgroundColour(background);
|
||||
m_image_grid->Refresh();
|
||||
m_button_year->Refresh();
|
||||
m_button_month->Refresh();
|
||||
m_button_all->Refresh();
|
||||
}
|
||||
|
||||
void OrcaFilesPanel::updateGroupButtons(FileGridGroup mode)
|
||||
{
|
||||
m_group_mode = mode;
|
||||
::Button* buttons[] = {m_button_all, m_button_month, m_button_year};
|
||||
const int selected = static_cast<int>(mode);
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
buttons[i]->SetValue(i == selected);
|
||||
buttons[i]->SetFont(i == selected ? Label::Head_14 : Label::Body_14);
|
||||
}
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,53 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "GUI_Utils.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
#include "Printer/RemoteFileGridModel.h"
|
||||
|
||||
#include <boost/smart_ptr/shared_ptr.hpp>
|
||||
#include <slic3r/GUI/Printer/IFileGridModel.h>
|
||||
#include <string>
|
||||
#include <wx/panel.h>
|
||||
|
||||
class Button;
|
||||
class Label;
|
||||
class StaticBox;
|
||||
|
||||
namespace Slic3r {
|
||||
class MachineObject;
|
||||
|
||||
namespace GUI {
|
||||
|
||||
class ImageGrid;
|
||||
|
||||
class OrcaFilesPanel : public wxPanel
|
||||
{
|
||||
public:
|
||||
explicit OrcaFilesPanel(wxWindow* parent);
|
||||
~OrcaFilesPanel() override;
|
||||
|
||||
void UpdateByObj(MachineObject* obj);
|
||||
void Rescale();
|
||||
void on_sys_color_changed();
|
||||
|
||||
private:
|
||||
void applyThemeColors();
|
||||
void updateGroupButtons(FileGridGroup mode);
|
||||
void updateStatus(RemoteFileGridModel::Status status);
|
||||
|
||||
ScalableBitmap m_bmp_loading;
|
||||
ScalableBitmap m_bmp_failed;
|
||||
ScalableBitmap m_bmp_empty;
|
||||
Label* m_root_label = nullptr;
|
||||
::StaticBox* m_time_panel = nullptr;
|
||||
::Button* m_button_year = nullptr;
|
||||
::Button* m_button_month = nullptr;
|
||||
::Button* m_button_all = nullptr;
|
||||
::Button* m_button_refresh = nullptr;
|
||||
ImageGrid* m_image_grid = nullptr;
|
||||
boost::shared_ptr<RemoteFileGridModel> m_model;
|
||||
std::string m_device_id;
|
||||
FileGridGroup m_group_mode = FileGridGroup::All;
|
||||
};
|
||||
|
||||
}}
|
||||
@@ -6426,10 +6426,9 @@ void Sidebar::sync_ams_list(bool is_from_big_sync_btn)
|
||||
for (const auto &entry : wxGetApp().preset_bundle->filament_ams_list) {
|
||||
const auto &tray = entry.second;
|
||||
const bool has_filament = !tray.opt_string("filament_id", 0u).empty();
|
||||
const bool has_type = !tray.opt_string("filament_type", 0u).empty();
|
||||
const bool is_placeholder = tray.has("filament_slot_placeholder") &&
|
||||
tray.opt_bool("filament_slot_placeholder", 0u);
|
||||
if (!has_filament && !is_placeholder && !has_type) {
|
||||
if (!has_filament && !is_placeholder) {
|
||||
continue;
|
||||
}
|
||||
if (combo_index >= p->combos_filament.size()) {
|
||||
@@ -8112,13 +8111,13 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
||||
preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_TAB, [this](SimpleEvent&) { select_next_view_3D(); });
|
||||
preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_COLLAPSE_SIDEBAR, [this](SimpleEvent&) { this->q->collapse_sidebar(!this->q->is_sidebar_collapsed()); });
|
||||
preview->get_wxglcanvas()->Bind(EVT_CUSTOMEVT_TICKSCHANGED, [this](wxCommandEvent& event) {
|
||||
Type tick_event_type = (Type)event.GetInt();
|
||||
CustomGCode::Type tick_event_type = (CustomGCode::Type)event.GetInt();
|
||||
Model& model = wxGetApp().plater()->model();
|
||||
//BBS: replace model custom gcode with current plate custom gcode
|
||||
model.plates_custom_gcodes[model.curr_plate_index] = preview->get_canvas3d()->get_gcode_viewer().get_layers_slider()->GetTicksValues();
|
||||
|
||||
// BBS set to invalid state only
|
||||
if (tick_event_type == Type::ToolChange || tick_event_type == Type::Custom || tick_event_type == Type::Template || tick_event_type == Type::PausePrint) {
|
||||
if (tick_event_type == CustomGCode::Type::ToolChange || tick_event_type == CustomGCode::Type::Custom || tick_event_type == CustomGCode::Type::Template || tick_event_type == CustomGCode::Type::PausePrint) {
|
||||
PartPlate *plate = this->q->get_partplate_list().get_curr_plate();
|
||||
if (plate) {
|
||||
plate->update_slice_result_valid_state(false);
|
||||
@@ -20545,7 +20544,7 @@ void Plater::on_filaments_delete(size_t num_filaments, size_t filament_id, int r
|
||||
|
||||
// update customize gcode
|
||||
for (auto item = p->model.plates_custom_gcodes.begin(); item != p->model.plates_custom_gcodes.end(); ++item) {
|
||||
auto iter = std::remove_if(item->second.gcodes.begin(), item->second.gcodes.end(), [filament_id](const Item& gcode_item) {
|
||||
auto iter = std::remove_if(item->second.gcodes.begin(), item->second.gcodes.end(), [filament_id](const CustomGCode::Item& gcode_item) {
|
||||
return (gcode_item.type == CustomGCode::Type::ToolChange && gcode_item.extruder == filament_id + 1);
|
||||
});
|
||||
if (replace_filament_id == -1)
|
||||
|
||||
@@ -2177,7 +2177,7 @@ void GUI::CalibrateFilamentComboBox::OnSelect(wxCommandEvent &evt)
|
||||
wxPostEvent(m_parent, e);
|
||||
}
|
||||
|
||||
void PlaterPresetComboBox::sys_color_changed()
|
||||
void GUI::PlaterPresetComboBox::sys_color_changed()
|
||||
{
|
||||
PresetComboBox::sys_color_changed();
|
||||
if (clr_picker) {
|
||||
|
||||
@@ -1752,8 +1752,8 @@ void ElegooPrintHostSendDialog::init() {
|
||||
}
|
||||
|
||||
{
|
||||
auto radioBoxA = new ::RadioBox(this);
|
||||
auto radioBoxB = new ::RadioBox(this);
|
||||
auto radioBoxA = new RadioBox(this);
|
||||
auto radioBoxB = new RadioBox(this);
|
||||
if (m_BedType == BedType::btPC)
|
||||
radioBoxB->SetValue(true);
|
||||
else
|
||||
|
||||
@@ -1,204 +0,0 @@
|
||||
#include "BambuFileGridModel.h"
|
||||
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
|
||||
#include <slic3r/GUI/Printer/IFileGridModel.h>
|
||||
#include <boost/smart_ptr/shared_ptr.hpp>
|
||||
#include <slic3r/GUI/Printer/PrinterFileSystem.h>
|
||||
#include <cstddef>
|
||||
#include <ctime>
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
#include <wx/event.h>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
static const FileGridCard& emptyCard()
|
||||
{
|
||||
static const FileGridCard card;
|
||||
return card;
|
||||
}
|
||||
|
||||
BambuFileGridModel::BambuFileGridModel(boost::shared_ptr<PrinterFileSystem> fs)
|
||||
: m_fs(std::move(fs))
|
||||
{
|
||||
if (m_fs) {
|
||||
m_fs->Bind(EVT_FILE_CHANGED, &BambuFileGridModel::onFileChanged, this);
|
||||
m_fs->Bind(EVT_MODE_CHANGED, &BambuFileGridModel::onModeChanged, this);
|
||||
m_fs->Bind(EVT_THUMBNAIL, &BambuFileGridModel::onThumbnail, this);
|
||||
m_fs->Bind(EVT_DOWNLOAD, &BambuFileGridModel::onDownload, this);
|
||||
}
|
||||
}
|
||||
|
||||
BambuFileGridModel::~BambuFileGridModel()
|
||||
{
|
||||
if (m_fs) {
|
||||
m_fs->Unbind(EVT_FILE_CHANGED, &BambuFileGridModel::onFileChanged, this);
|
||||
m_fs->Unbind(EVT_MODE_CHANGED, &BambuFileGridModel::onModeChanged, this);
|
||||
m_fs->Unbind(EVT_THUMBNAIL, &BambuFileGridModel::onThumbnail, this);
|
||||
m_fs->Unbind(EVT_DOWNLOAD, &BambuFileGridModel::onDownload, this);
|
||||
}
|
||||
}
|
||||
|
||||
void BambuFileGridModel::EnsureCards() const
|
||||
{
|
||||
if (!m_dirty && (!m_fs || m_cards.size() == m_fs->GetCount()))
|
||||
return;
|
||||
m_dirty = false;
|
||||
m_cards.clear();
|
||||
if (!m_fs)
|
||||
return;
|
||||
size_t count = m_fs->GetCount();
|
||||
m_cards.reserve(count);
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
bool selected = false;
|
||||
PrinterFileSystem::File const &file = m_fs->GetFile(i, selected);
|
||||
FileGridCard card;
|
||||
card.id = file.path;
|
||||
card.name = file.name;
|
||||
card.title = file.Title();
|
||||
card.time_text = file.Metadata("Time", "");
|
||||
card.weight_text = file.Metadata("Weight", "");
|
||||
card.time = file.time;
|
||||
card.downloading = file.IsDownload();
|
||||
card.download_progress = file.DownloadProgress();
|
||||
card.selected = selected;
|
||||
card.thumbnail = file.thumbnail;
|
||||
m_cards.push_back(std::move(card));
|
||||
}
|
||||
}
|
||||
|
||||
size_t BambuFileGridModel::GetCount() const
|
||||
{
|
||||
return m_fs ? m_fs->GetCount() : 0;
|
||||
}
|
||||
|
||||
const FileGridCard& BambuFileGridModel::GetFile(size_t index, bool& selected) const
|
||||
{
|
||||
EnsureCards();
|
||||
if (!m_fs || index >= m_cards.size()) {
|
||||
selected = false;
|
||||
return emptyCard();
|
||||
}
|
||||
m_fs->GetFile(index, selected);
|
||||
return m_cards[index];
|
||||
}
|
||||
|
||||
const FileGridCard& BambuFileGridModel::GetFile(size_t index) const
|
||||
{
|
||||
EnsureCards();
|
||||
if (index >= m_cards.size())
|
||||
return emptyCard();
|
||||
return m_cards[index];
|
||||
}
|
||||
|
||||
FileGridType BambuFileGridModel::GetFileType() const
|
||||
{
|
||||
return m_fs ? static_cast<FileGridType>(m_fs->GetFileType()) : FileGridType::Timelapse;
|
||||
}
|
||||
|
||||
void BambuFileGridModel::SetFileType(FileGridType type, const std::string& storage)
|
||||
{
|
||||
if (m_fs)
|
||||
m_fs->SetFileType(static_cast<PrinterFileSystem::FileType>(type), storage);
|
||||
}
|
||||
|
||||
FileGridGroup BambuFileGridModel::GetGroupMode() const
|
||||
{
|
||||
return m_fs ? static_cast<FileGridGroup>(m_fs->GetGroupMode()) : FileGridGroup::All;
|
||||
}
|
||||
|
||||
void BambuFileGridModel::SetGroupMode(FileGridGroup mode)
|
||||
{
|
||||
if (m_fs)
|
||||
m_fs->SetGroupMode(static_cast<PrinterFileSystem::GroupMode>(mode));
|
||||
}
|
||||
|
||||
size_t BambuFileGridModel::GetIndexAtTime(time_t time) const
|
||||
{
|
||||
return m_fs ? m_fs->GetIndexAtTime(static_cast<boost::uint32_t>(time)) : 0;
|
||||
}
|
||||
|
||||
size_t BambuFileGridModel::EnterSubGroup(size_t index)
|
||||
{
|
||||
return m_fs ? m_fs->EnterSubGroup(index) : index;
|
||||
}
|
||||
|
||||
void BambuFileGridModel::ToggleSelect(size_t index)
|
||||
{
|
||||
if (m_fs)
|
||||
m_fs->ToggleSelect(index);
|
||||
}
|
||||
|
||||
void BambuFileGridModel::SelectAll(bool select)
|
||||
{
|
||||
if (m_fs)
|
||||
m_fs->SelectAll(select);
|
||||
}
|
||||
|
||||
void BambuFileGridModel::SetFocusRange(size_t start, size_t count)
|
||||
{
|
||||
if (m_fs)
|
||||
m_fs->SetFocusRange(start, count);
|
||||
}
|
||||
|
||||
void BambuFileGridModel::Retry()
|
||||
{
|
||||
if (m_fs)
|
||||
m_fs->Retry();
|
||||
}
|
||||
|
||||
int BambuFileGridModel::GetLastError() const
|
||||
{
|
||||
return m_fs ? m_fs->GetLastError() : 1;
|
||||
}
|
||||
|
||||
void BambuFileGridModel::DownloadCheckFiles(const std::string& path)
|
||||
{
|
||||
if (m_fs)
|
||||
m_fs->DownloadCheckFiles(path);
|
||||
}
|
||||
|
||||
void BambuFileGridModel::SetChangeHandler(std::function<void(FileGridChange)> handler)
|
||||
{
|
||||
m_handler = std::move(handler);
|
||||
}
|
||||
|
||||
void BambuFileGridModel::notify(FileGridChange change)
|
||||
{
|
||||
if (m_handler)
|
||||
m_handler(change);
|
||||
}
|
||||
|
||||
void BambuFileGridModel::onFileChanged(wxCommandEvent& evt)
|
||||
{
|
||||
evt.Skip();
|
||||
if (evt.GetInt() == -1 && m_fs)
|
||||
m_fs->DownloadCheckFiles(wxGetApp().app_config->get("download_path"));
|
||||
m_dirty = true;
|
||||
notify(FileGridChange::Files);
|
||||
}
|
||||
|
||||
void BambuFileGridModel::onModeChanged(wxCommandEvent& evt)
|
||||
{
|
||||
evt.Skip();
|
||||
m_dirty = true;
|
||||
notify(FileGridChange::Mode);
|
||||
}
|
||||
|
||||
void BambuFileGridModel::onThumbnail(wxCommandEvent& evt)
|
||||
{
|
||||
evt.Skip();
|
||||
m_dirty = true;
|
||||
notify(FileGridChange::Thumbnail);
|
||||
}
|
||||
|
||||
void BambuFileGridModel::onDownload(wxCommandEvent& evt)
|
||||
{
|
||||
evt.Skip();
|
||||
m_dirty = true;
|
||||
notify(FileGridChange::Download);
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,61 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "IFileGridModel.h"
|
||||
#include "PrinterFileSystem.h"
|
||||
|
||||
#include <boost/smart_ptr/shared_ptr.hpp>
|
||||
#include <wx/event.h>
|
||||
#include <cstddef>
|
||||
#include <ctime>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
// IFileGridModel over PrinterFileSystem, behavior-identical to ImageGrid's direct use.
|
||||
class BambuFileGridModel : public wxEvtHandler, public IFileGridModel
|
||||
{
|
||||
public:
|
||||
explicit BambuFileGridModel(boost::shared_ptr<PrinterFileSystem> fs);
|
||||
~BambuFileGridModel() override;
|
||||
|
||||
size_t GetCount() const override;
|
||||
const FileGridCard& GetFile(size_t index, bool& selected) const override;
|
||||
const FileGridCard& GetFile(size_t index) const override;
|
||||
|
||||
FileGridType GetFileType() const override;
|
||||
void SetFileType(FileGridType type, const std::string& storage) override;
|
||||
FileGridGroup GetGroupMode() const override;
|
||||
void SetGroupMode(FileGridGroup mode) override;
|
||||
|
||||
size_t GetIndexAtTime(time_t time) const override;
|
||||
size_t EnterSubGroup(size_t index) override;
|
||||
|
||||
void ToggleSelect(size_t index) override;
|
||||
void SelectAll(bool select) override;
|
||||
void SetFocusRange(size_t start, size_t count) override;
|
||||
|
||||
void Retry() override;
|
||||
int GetLastError() const override;
|
||||
void DownloadCheckFiles(const std::string& path) override;
|
||||
|
||||
void SetChangeHandler(std::function<void(FileGridChange)> handler) override;
|
||||
|
||||
private:
|
||||
void EnsureCards() const;
|
||||
void notify(FileGridChange change);
|
||||
|
||||
void onFileChanged(wxCommandEvent& evt);
|
||||
void onModeChanged(wxCommandEvent& evt);
|
||||
void onThumbnail(wxCommandEvent& evt);
|
||||
void onDownload(wxCommandEvent& evt);
|
||||
|
||||
boost::shared_ptr<PrinterFileSystem> m_fs;
|
||||
std::function<void(FileGridChange)> m_handler;
|
||||
mutable std::vector<FileGridCard> m_cards;
|
||||
mutable bool m_dirty = true;
|
||||
};
|
||||
|
||||
}}
|
||||
@@ -1,67 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <wx/bitmap.h>
|
||||
#include <cstddef>
|
||||
#include <ctime>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
// Mirrors PrinterFileSystem::FileType ordering (F_TIMELAPSE=0, F_VIDEO=1, F_MODEL=2).
|
||||
enum class FileGridType { Timelapse = 0, Video = 1, Model = 2 };
|
||||
// Mirrors PrinterFileSystem::GroupMode ordering (G_NONE=0, G_MONTH=1, G_YEAR=2).
|
||||
enum class FileGridGroup { All = 0, Month = 1, Year = 2 };
|
||||
// Mirrors the PrinterFileSystem wx events ImageGrid listens to.
|
||||
enum class FileGridChange { Files, Mode, Thumbnail, Download };
|
||||
|
||||
// One rendered card. Neutral: no Bambu transfer internals, no filesystem paths beyond id.
|
||||
struct FileGridCard {
|
||||
std::string id;
|
||||
std::string name;
|
||||
std::string title;
|
||||
std::string time_text;
|
||||
std::string weight_text;
|
||||
time_t time = 0;
|
||||
bool downloading = false;
|
||||
int download_progress = 0; // -1 waiting, <0 failed, 0..100 progress
|
||||
bool selected = false;
|
||||
bool printable = true;
|
||||
wxBitmap thumbnail;
|
||||
};
|
||||
|
||||
// Data source behind ImageGrid. Implemented today by BambuFileGridModel (wrapping
|
||||
// PrinterFileSystem); a non-Bambu model can implement the same surface later.
|
||||
class IFileGridModel {
|
||||
public:
|
||||
virtual ~IFileGridModel() = default;
|
||||
|
||||
virtual size_t GetCount() const = 0;
|
||||
virtual const FileGridCard& GetFile(size_t index, bool& selected) const = 0;
|
||||
virtual const FileGridCard& GetFile(size_t index) const = 0;
|
||||
|
||||
virtual FileGridType GetFileType() const = 0;
|
||||
virtual void SetFileType(FileGridType type, const std::string& storage) = 0;
|
||||
virtual FileGridGroup GetGroupMode() const = 0;
|
||||
virtual void SetGroupMode(FileGridGroup mode) = 0;
|
||||
|
||||
// When true, the thumbnail is fitted inside the tile instead of stretched to fill it.
|
||||
virtual bool preserve_thumbnail_aspect() const { return false; }
|
||||
|
||||
virtual size_t GetIndexAtTime(time_t time) const = 0;
|
||||
virtual size_t EnterSubGroup(size_t index) = 0;
|
||||
|
||||
virtual void ToggleSelect(size_t index) = 0;
|
||||
virtual void SelectAll(bool select) = 0;
|
||||
virtual void SetFocusRange(size_t start, size_t count) = 0;
|
||||
|
||||
virtual void Retry() = 0;
|
||||
virtual int GetLastError() const = 0;
|
||||
virtual void DownloadCheckFiles(const std::string& path) = 0;
|
||||
|
||||
// ImageGrid sets one handler; the model invokes it on the UI thread on change.
|
||||
virtual void SetChangeHandler(std::function<void(FileGridChange)>) = 0;
|
||||
};
|
||||
|
||||
}}
|
||||
@@ -1,545 +0,0 @@
|
||||
#include "RemoteFileGridModel.h"
|
||||
|
||||
#include "IPrinterAgent.hpp"
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
#include "slic3r/Utils/NetworkAgent.hpp"
|
||||
|
||||
#include <slic3r/GUI/Printer/IFileGridModel.h>
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <ctime>
|
||||
#include <functional>
|
||||
#include <cstddef>
|
||||
#include <wx/datetime.h>
|
||||
#include <wx/gdicmn.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/mstream.h>
|
||||
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cmath>
|
||||
#include <utility>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
namespace {
|
||||
|
||||
const FileGridCard& emptyCard()
|
||||
{
|
||||
static const FileGridCard card;
|
||||
return card;
|
||||
}
|
||||
|
||||
// Same display format as PrinterFileSystem: "1d2h3m", dropping a leading "0d"/"0h".
|
||||
std::string durationString(long duration)
|
||||
{
|
||||
static boost::regex rx("^0d(0h)?");
|
||||
auto time = boost::format("%1%d%2%h%3%m") % (duration / 86400) % ((duration % 86400) / 3600) % ((duration % 3600) / 60);
|
||||
return boost::regex_replace(time.str(), rx, "");
|
||||
}
|
||||
|
||||
// Case-insensitive suffix test shared by the file filters below.
|
||||
bool ends_with_ci(const std::string& name, const std::string& suffix)
|
||||
{
|
||||
return name.size() >= suffix.size() &&
|
||||
std::equal(suffix.rbegin(), suffix.rend(), name.rbegin(),
|
||||
[](char a, char b) {
|
||||
return std::tolower(static_cast<unsigned char>(a)) ==
|
||||
std::tolower(static_cast<unsigned char>(b));
|
||||
});
|
||||
}
|
||||
|
||||
// .gcode / .3mf only, case-insensitive; a .gcode.3mf name matches via the .3mf suffix.
|
||||
bool is_displayable_file(const std::string& name)
|
||||
{
|
||||
return ends_with_ci(name, ".gcode") || ends_with_ci(name, ".3mf");
|
||||
}
|
||||
|
||||
// .gcode and .gcode.3mf are printable; OrcaSonar unpacks a 3MF to its plate
|
||||
// G-code. A bare .3mf is an unsliced project file, so it stays unprintable.
|
||||
bool is_printable_gcode(const std::string& name)
|
||||
{
|
||||
return ends_with_ci(name, ".gcode") || ends_with_ci(name, ".gcode.3mf");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
RemoteFileGridModel::RemoteFileGridModel(std::string device_id)
|
||||
: m_device_id(std::move(device_id))
|
||||
{
|
||||
}
|
||||
|
||||
RemoteFileGridModel::~RemoteFileGridModel()
|
||||
{
|
||||
m_lifetime.reset();
|
||||
}
|
||||
|
||||
void RemoteFileGridModel::Refresh()
|
||||
{
|
||||
const std::uint64_t request = ++m_request;
|
||||
const std::string device_id = m_device_id;
|
||||
m_thumbnail_cache.clear();
|
||||
m_thumbnail_requested.clear();
|
||||
m_thumbnail_queue.clear();
|
||||
m_metadata_cache.clear();
|
||||
m_metadata_requested.clear();
|
||||
m_metadata_queue.clear();
|
||||
for (FileGridCard& card : m_cards)
|
||||
card.thumbnail = wxBitmap();
|
||||
m_last_error = 0;
|
||||
setStatus(Status::Loading);
|
||||
|
||||
NetworkAgent* agent = wxGetApp().getAgent();
|
||||
if (!agent) {
|
||||
m_last_error = -1;
|
||||
m_cards.clear();
|
||||
m_month.clear();
|
||||
m_year.clear();
|
||||
setStatus(Status::Failed);
|
||||
if (m_change_handler)
|
||||
m_change_handler(FileGridChange::Files);
|
||||
return;
|
||||
}
|
||||
|
||||
std::weak_ptr<int> lifetime = m_lifetime;
|
||||
int result = agent->list_printer_files(device_id,
|
||||
[this, lifetime, request, device_id](int result, std::vector<PrinterFileEntry> files) {
|
||||
if (lifetime.expired())
|
||||
return;
|
||||
onFilesLoaded(request, device_id, result, std::move(files));
|
||||
});
|
||||
|
||||
if (result != 0 && request == m_request && m_status == Status::Loading) {
|
||||
m_last_error = result;
|
||||
m_cards.clear();
|
||||
m_month.clear();
|
||||
m_year.clear();
|
||||
setStatus(Status::Failed);
|
||||
if (m_change_handler)
|
||||
m_change_handler(FileGridChange::Files);
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteFileGridModel::onFilesLoaded(std::uint64_t request, const std::string& device_id, int result,
|
||||
std::vector<PrinterFileEntry> files)
|
||||
{
|
||||
if (request != m_request || device_id != m_device_id)
|
||||
return;
|
||||
|
||||
m_last_error = result;
|
||||
m_cards.clear();
|
||||
if (result == 0) {
|
||||
files.erase(std::remove_if(files.begin(), files.end(),
|
||||
[](const PrinterFileEntry& file) { return !is_displayable_file(file.name); }),
|
||||
files.end());
|
||||
std::sort(files.begin(), files.end(), [](const PrinterFileEntry& lhs, const PrinterFileEntry& rhs) {
|
||||
return lhs.modified > rhs.modified;
|
||||
});
|
||||
m_cards.reserve(files.size());
|
||||
for (const PrinterFileEntry& file : files) {
|
||||
FileGridCard card;
|
||||
card.id = file.path;
|
||||
card.name = file.name;
|
||||
card.time = static_cast<time_t>(file.modified);
|
||||
card.printable = is_printable_gcode(file.name);
|
||||
m_cards.emplace_back(std::move(card));
|
||||
}
|
||||
buildGroups();
|
||||
setStatus(m_cards.empty() ? Status::Empty : Status::Ready);
|
||||
} else {
|
||||
m_month.clear();
|
||||
m_year.clear();
|
||||
setStatus(Status::Failed);
|
||||
}
|
||||
|
||||
if (m_change_handler)
|
||||
m_change_handler(FileGridChange::Files);
|
||||
}
|
||||
|
||||
void RemoteFileGridModel::setStatus(Status status)
|
||||
{
|
||||
m_status = status;
|
||||
if (m_status_handler)
|
||||
m_status_handler(status);
|
||||
}
|
||||
|
||||
void RemoteFileGridModel::SetStatusHandler(std::function<void(Status)> handler)
|
||||
{
|
||||
m_status_handler = std::move(handler);
|
||||
}
|
||||
|
||||
size_t RemoteFileGridModel::GetCount() const
|
||||
{
|
||||
if (m_group_mode == FileGridGroup::Year)
|
||||
return m_year.size();
|
||||
if (m_group_mode == FileGridGroup::Month)
|
||||
return m_month.size();
|
||||
return m_cards.size();
|
||||
}
|
||||
|
||||
const FileGridCard& RemoteFileGridModel::GetFile(size_t index, bool& selected) const
|
||||
{
|
||||
selected = false;
|
||||
const size_t card_index = cardIndexForGroup(index);
|
||||
if (card_index >= m_cards.size())
|
||||
return emptyCard();
|
||||
FileGridCard& card = m_cards[card_index];
|
||||
const auto thumbnail = m_thumbnail_cache.find(card.id);
|
||||
card.thumbnail = thumbnail == m_thumbnail_cache.end() ? wxBitmap() : thumbnail->second;
|
||||
return card;
|
||||
}
|
||||
|
||||
const FileGridCard& RemoteFileGridModel::GetFile(size_t index) const
|
||||
{
|
||||
bool selected = false;
|
||||
return GetFile(index, selected);
|
||||
}
|
||||
|
||||
size_t RemoteFileGridModel::cardIndexForGroup(size_t index) const
|
||||
{
|
||||
if (m_group_mode == FileGridGroup::All)
|
||||
return index;
|
||||
if (m_group_mode == FileGridGroup::Month)
|
||||
return index < m_month.size() ? m_month[index] : m_cards.size();
|
||||
return index < m_year.size() && m_year[index] < m_month.size() ? m_month[m_year[index]] : m_cards.size();
|
||||
}
|
||||
|
||||
FileGridType RemoteFileGridModel::GetFileType() const
|
||||
{
|
||||
return m_file_type;
|
||||
}
|
||||
|
||||
void RemoteFileGridModel::SetFileType(FileGridType type, const std::string&)
|
||||
{
|
||||
m_file_type = type;
|
||||
}
|
||||
|
||||
FileGridGroup RemoteFileGridModel::GetGroupMode() const
|
||||
{
|
||||
return m_group_mode;
|
||||
}
|
||||
|
||||
void RemoteFileGridModel::SetGroupMode(FileGridGroup mode)
|
||||
{
|
||||
if (mode != FileGridGroup::All && mode != FileGridGroup::Month && mode != FileGridGroup::Year)
|
||||
return;
|
||||
if (m_group_mode == mode)
|
||||
return;
|
||||
m_group_mode = mode;
|
||||
if (m_group_mode_handler)
|
||||
m_group_mode_handler(mode);
|
||||
if (m_change_handler)
|
||||
m_change_handler(FileGridChange::Mode);
|
||||
}
|
||||
|
||||
size_t RemoteFileGridModel::GetIndexAtTime(time_t time) const
|
||||
{
|
||||
if (m_cards.empty())
|
||||
return 0;
|
||||
|
||||
size_t low = 0;
|
||||
size_t high = m_cards.size();
|
||||
while (low < high) {
|
||||
const size_t middle = low + (high - low) / 2;
|
||||
if (m_cards[middle].time >= time)
|
||||
low = middle + 1;
|
||||
else
|
||||
high = middle;
|
||||
}
|
||||
const size_t card_index = low == 0 ? 0 : low - 1;
|
||||
if (m_group_mode == FileGridGroup::All)
|
||||
return card_index;
|
||||
|
||||
const auto month = std::upper_bound(m_month.begin(), m_month.end(), card_index);
|
||||
const size_t month_index = month == m_month.begin() ? 0 : static_cast<size_t>(month - m_month.begin() - 1);
|
||||
if (m_group_mode == FileGridGroup::Month)
|
||||
return month_index;
|
||||
|
||||
const auto year = std::upper_bound(m_year.begin(), m_year.end(), card_index,
|
||||
[this](size_t file_index, size_t month_index) {
|
||||
return file_index < m_month[month_index];
|
||||
});
|
||||
return year == m_year.begin() ? 0 : static_cast<size_t>(year - m_year.begin() - 1);
|
||||
}
|
||||
|
||||
size_t RemoteFileGridModel::EnterSubGroup(size_t index)
|
||||
{
|
||||
if (m_group_mode == FileGridGroup::All)
|
||||
return index;
|
||||
if (m_group_mode == FileGridGroup::Year) {
|
||||
if (index >= m_year.size())
|
||||
return 0;
|
||||
index = m_year[index];
|
||||
} else {
|
||||
if (index >= m_month.size())
|
||||
return 0;
|
||||
index = m_month[index];
|
||||
}
|
||||
SetGroupMode(static_cast<FileGridGroup>(static_cast<int>(m_group_mode) - 1));
|
||||
return index;
|
||||
}
|
||||
|
||||
void RemoteFileGridModel::ToggleSelect(size_t)
|
||||
{
|
||||
}
|
||||
|
||||
void RemoteFileGridModel::SelectAll(bool)
|
||||
{
|
||||
}
|
||||
|
||||
void RemoteFileGridModel::SetFocusRange(size_t start, size_t count)
|
||||
{
|
||||
if (m_status == Status::Loading || start >= GetCount())
|
||||
return;
|
||||
const size_t end = start + std::min(count, GetCount() - start);
|
||||
for (size_t i = start; i < end; ++i) {
|
||||
const FileGridCard& card = GetFile(i);
|
||||
if (!card.id.empty()) {
|
||||
requestThumbnail(card.id);
|
||||
requestMetadata(card.id);
|
||||
}
|
||||
}
|
||||
pumpThumbnailQueue();
|
||||
pumpMetadataQueue();
|
||||
}
|
||||
|
||||
void RemoteFileGridModel::Retry()
|
||||
{
|
||||
Refresh();
|
||||
}
|
||||
|
||||
int RemoteFileGridModel::GetLastError() const
|
||||
{
|
||||
return m_last_error;
|
||||
}
|
||||
|
||||
void RemoteFileGridModel::DownloadCheckFiles(const std::string&)
|
||||
{
|
||||
}
|
||||
|
||||
void RemoteFileGridModel::DeleteFile(const std::string& path, std::function<void(bool ok)> done)
|
||||
{
|
||||
NetworkAgent* agent = wxGetApp().getAgent();
|
||||
if (!agent || m_device_id.empty() || path.empty()) {
|
||||
if (done)
|
||||
done(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const std::uint64_t request = m_request;
|
||||
const std::string device_id = m_device_id;
|
||||
const std::weak_ptr<int> lifetime = m_lifetime;
|
||||
const auto completed = std::make_shared<bool>(false);
|
||||
auto finish = [this, lifetime, completed, request, device_id, path, done = std::move(done)](int result) {
|
||||
if (*completed)
|
||||
return;
|
||||
*completed = true;
|
||||
if (lifetime.expired())
|
||||
return;
|
||||
|
||||
const bool ok = result == 0;
|
||||
if (ok && request == m_request && device_id == m_device_id) {
|
||||
m_thumbnail_cache.erase(path);
|
||||
m_thumbnail_requested.erase(path);
|
||||
m_cards.erase(std::remove_if(m_cards.begin(), m_cards.end(),
|
||||
[&path](const FileGridCard& card) { return card.id == path; }),
|
||||
m_cards.end());
|
||||
buildGroups();
|
||||
setStatus(m_cards.empty() ? Status::Empty : Status::Ready);
|
||||
if (m_change_handler)
|
||||
m_change_handler(FileGridChange::Files);
|
||||
}
|
||||
if (done)
|
||||
done(ok);
|
||||
};
|
||||
|
||||
const int result = agent->delete_printer_file(device_id, path, finish);
|
||||
if (result != 0)
|
||||
finish(result);
|
||||
}
|
||||
|
||||
void RemoteFileGridModel::SetChangeHandler(std::function<void(FileGridChange)> handler)
|
||||
{
|
||||
m_change_handler = std::move(handler);
|
||||
}
|
||||
|
||||
void RemoteFileGridModel::SetGroupModeHandler(std::function<void(FileGridGroup)> handler)
|
||||
{
|
||||
m_group_mode_handler = std::move(handler);
|
||||
}
|
||||
|
||||
void RemoteFileGridModel::buildGroups()
|
||||
{
|
||||
m_month.clear();
|
||||
m_year.clear();
|
||||
if (m_cards.empty())
|
||||
return;
|
||||
|
||||
m_month.push_back(0);
|
||||
m_year.push_back(0);
|
||||
wxDateTime previous(static_cast<time_t>(m_cards.front().time));
|
||||
for (size_t i = 1; i < m_cards.size(); ++i) {
|
||||
const wxDateTime current(static_cast<time_t>(m_cards[i].time));
|
||||
if (current.GetYear() != previous.GetYear()) {
|
||||
m_year.push_back(m_month.size());
|
||||
m_month.push_back(i);
|
||||
} else if (current.GetMonth() != previous.GetMonth()) {
|
||||
m_month.push_back(i);
|
||||
}
|
||||
previous = current;
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteFileGridModel::requestThumbnail(const std::string& path)
|
||||
{
|
||||
if (m_thumbnail_cache.find(path) != m_thumbnail_cache.end() || !m_thumbnail_requested.insert(path).second)
|
||||
return;
|
||||
m_thumbnail_queue.push_back(path);
|
||||
}
|
||||
|
||||
void RemoteFileGridModel::pumpThumbnailQueue()
|
||||
{
|
||||
constexpr size_t MAX_THUMBNAIL_REQUESTS = 4;
|
||||
if (m_pumping_thumbnail_queue)
|
||||
return;
|
||||
m_pumping_thumbnail_queue = true;
|
||||
|
||||
NetworkAgent* agent = wxGetApp().getAgent();
|
||||
if (!agent) {
|
||||
while (!m_thumbnail_queue.empty()) {
|
||||
m_thumbnail_cache.emplace(m_thumbnail_queue.front(), wxBitmap());
|
||||
m_thumbnail_queue.pop_front();
|
||||
}
|
||||
m_pumping_thumbnail_queue = false;
|
||||
return;
|
||||
}
|
||||
|
||||
while (!m_thumbnail_queue.empty() && m_thumbnail_requests_in_flight < MAX_THUMBNAIL_REQUESTS) {
|
||||
std::string path = std::move(m_thumbnail_queue.front());
|
||||
m_thumbnail_queue.pop_front();
|
||||
++m_thumbnail_requests_in_flight;
|
||||
|
||||
const std::uint64_t request = m_request;
|
||||
const std::string device_id = m_device_id;
|
||||
const std::weak_ptr<int> lifetime = m_lifetime;
|
||||
const auto completed = std::make_shared<bool>(false);
|
||||
auto finish = [this, lifetime, completed, request, device_id, path](int result, std::string image) {
|
||||
if (*completed)
|
||||
return;
|
||||
*completed = true;
|
||||
if (lifetime.expired())
|
||||
return;
|
||||
onThumbnailLoaded(request, device_id, path, result, std::move(image));
|
||||
};
|
||||
|
||||
const int result = agent->get_printer_file_thumbnail(device_id, path, finish);
|
||||
if (result != 0)
|
||||
finish(result, {});
|
||||
}
|
||||
m_pumping_thumbnail_queue = false;
|
||||
}
|
||||
|
||||
void RemoteFileGridModel::onThumbnailLoaded(std::uint64_t request, const std::string& device_id,
|
||||
const std::string& path, int result, std::string image)
|
||||
{
|
||||
if (m_thumbnail_requests_in_flight > 0)
|
||||
--m_thumbnail_requests_in_flight;
|
||||
|
||||
if (request == m_request && device_id == m_device_id) {
|
||||
wxBitmap bitmap;
|
||||
if (result == 0 && !image.empty()) {
|
||||
wxMemoryInputStream stream(image.data(), image.size());
|
||||
wxImage decoded(stream, wxBITMAP_TYPE_PNG);
|
||||
if (decoded.IsOk())
|
||||
bitmap = wxBitmap(decoded);
|
||||
}
|
||||
m_thumbnail_cache[path] = std::move(bitmap);
|
||||
if (m_change_handler)
|
||||
m_change_handler(FileGridChange::Thumbnail);
|
||||
}
|
||||
|
||||
pumpThumbnailQueue();
|
||||
}
|
||||
|
||||
void RemoteFileGridModel::requestMetadata(const std::string& path)
|
||||
{
|
||||
if (m_metadata_cache.find(path) != m_metadata_cache.end() || !m_metadata_requested.insert(path).second)
|
||||
return;
|
||||
m_metadata_queue.push_back(path);
|
||||
}
|
||||
|
||||
void RemoteFileGridModel::pumpMetadataQueue()
|
||||
{
|
||||
constexpr size_t MAX_METADATA_REQUESTS = 4;
|
||||
if (m_pumping_metadata_queue)
|
||||
return;
|
||||
m_pumping_metadata_queue = true;
|
||||
|
||||
NetworkAgent* agent = wxGetApp().getAgent();
|
||||
if (!agent) {
|
||||
while (!m_metadata_queue.empty()) {
|
||||
m_metadata_cache.emplace(m_metadata_queue.front(), PrinterFileMetadata{});
|
||||
m_metadata_queue.pop_front();
|
||||
}
|
||||
m_pumping_metadata_queue = false;
|
||||
return;
|
||||
}
|
||||
|
||||
while (!m_metadata_queue.empty() && m_metadata_requests_in_flight < MAX_METADATA_REQUESTS) {
|
||||
std::string path = std::move(m_metadata_queue.front());
|
||||
m_metadata_queue.pop_front();
|
||||
++m_metadata_requests_in_flight;
|
||||
|
||||
const std::uint64_t request = m_request;
|
||||
const std::string device_id = m_device_id;
|
||||
const std::weak_ptr<int> lifetime = m_lifetime;
|
||||
const auto completed = std::make_shared<bool>(false);
|
||||
auto finish = [this, lifetime, completed, request, device_id, path](int result, PrinterFileMetadata meta) {
|
||||
if (*completed)
|
||||
return;
|
||||
*completed = true;
|
||||
if (lifetime.expired())
|
||||
return;
|
||||
onMetadataLoaded(request, device_id, path, result, meta);
|
||||
};
|
||||
|
||||
const int result = agent->get_printer_file_metadata(device_id, path, finish);
|
||||
if (result != 0)
|
||||
finish(result, {});
|
||||
}
|
||||
m_pumping_metadata_queue = false;
|
||||
}
|
||||
|
||||
void RemoteFileGridModel::onMetadataLoaded(std::uint64_t request, const std::string& device_id,
|
||||
const std::string& path, int result, PrinterFileMetadata meta)
|
||||
{
|
||||
if (m_metadata_requests_in_flight > 0)
|
||||
--m_metadata_requests_in_flight;
|
||||
|
||||
if (request == m_request && device_id == m_device_id) {
|
||||
m_metadata_cache[path] = meta;
|
||||
if (result == 0) {
|
||||
for (FileGridCard& card : m_cards) {
|
||||
if (card.id != path)
|
||||
continue;
|
||||
card.time_text = meta.estimated_time > 0 ? durationString(meta.estimated_time) : std::string();
|
||||
card.weight_text = meta.filament_weight > 0
|
||||
? std::to_string(int(std::round(meta.filament_weight))) + 'g'
|
||||
: std::string();
|
||||
break;
|
||||
}
|
||||
if (m_change_handler)
|
||||
m_change_handler(FileGridChange::Thumbnail);
|
||||
}
|
||||
}
|
||||
|
||||
pumpMetadataQueue();
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,100 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "IFileGridModel.h"
|
||||
|
||||
#include "slic3r/Utils/IPrinterAgent.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <ctime>
|
||||
#include <deque>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
class RemoteFileGridModel : public IFileGridModel
|
||||
{
|
||||
public:
|
||||
enum class Status { Loading, Ready, Empty, Failed };
|
||||
|
||||
explicit RemoteFileGridModel(std::string device_id);
|
||||
~RemoteFileGridModel() override;
|
||||
|
||||
void Refresh();
|
||||
Status GetStatus() const { return m_status; }
|
||||
void SetStatusHandler(std::function<void(Status)> handler);
|
||||
void SetGroupModeHandler(std::function<void(FileGridGroup)> handler);
|
||||
|
||||
size_t GetCount() const override;
|
||||
const FileGridCard& GetFile(size_t index, bool& selected) const override;
|
||||
const FileGridCard& GetFile(size_t index) const override;
|
||||
|
||||
FileGridType GetFileType() const override;
|
||||
void SetFileType(FileGridType type, const std::string& storage) override;
|
||||
FileGridGroup GetGroupMode() const override;
|
||||
void SetGroupMode(FileGridGroup mode) override;
|
||||
|
||||
size_t GetIndexAtTime(time_t time) const override;
|
||||
size_t EnterSubGroup(size_t index) override;
|
||||
|
||||
void ToggleSelect(size_t index) override;
|
||||
void SelectAll(bool select) override;
|
||||
void SetFocusRange(size_t start, size_t count) override;
|
||||
|
||||
void Retry() override;
|
||||
int GetLastError() const override;
|
||||
void DownloadCheckFiles(const std::string& path) override;
|
||||
bool preserve_thumbnail_aspect() const override { return true; }
|
||||
|
||||
// Delete `path` from the printer; `done` reports success on the UI thread.
|
||||
void DeleteFile(const std::string& path, std::function<void(bool ok)> done);
|
||||
|
||||
void SetChangeHandler(std::function<void(FileGridChange)> handler) override;
|
||||
|
||||
private:
|
||||
void setStatus(Status status);
|
||||
void onFilesLoaded(std::uint64_t request, const std::string& device_id, int result,
|
||||
std::vector<PrinterFileEntry> files);
|
||||
void buildGroups();
|
||||
size_t cardIndexForGroup(size_t index) const;
|
||||
void requestThumbnail(const std::string& path);
|
||||
void pumpThumbnailQueue();
|
||||
void onThumbnailLoaded(std::uint64_t request, const std::string& device_id,
|
||||
const std::string& path, int result, std::string image);
|
||||
void requestMetadata(const std::string& path);
|
||||
void pumpMetadataQueue();
|
||||
void onMetadataLoaded(std::uint64_t request, const std::string& device_id,
|
||||
const std::string& path, int result, PrinterFileMetadata meta);
|
||||
|
||||
std::string m_device_id;
|
||||
mutable std::vector<FileGridCard> m_cards;
|
||||
std::vector<size_t> m_month;
|
||||
std::vector<size_t> m_year;
|
||||
std::function<void(FileGridChange)> m_change_handler;
|
||||
std::function<void(Status)> m_status_handler;
|
||||
std::function<void(FileGridGroup)> m_group_mode_handler;
|
||||
std::shared_ptr<int> m_lifetime = std::make_shared<int>(0);
|
||||
std::unordered_map<std::string, wxBitmap> m_thumbnail_cache;
|
||||
std::unordered_set<std::string> m_thumbnail_requested;
|
||||
std::deque<std::string> m_thumbnail_queue;
|
||||
std::unordered_map<std::string, PrinterFileMetadata> m_metadata_cache;
|
||||
std::unordered_set<std::string> m_metadata_requested;
|
||||
std::deque<std::string> m_metadata_queue;
|
||||
std::uint64_t m_request = 0;
|
||||
size_t m_thumbnail_requests_in_flight = 0;
|
||||
bool m_pumping_thumbnail_queue = false;
|
||||
size_t m_metadata_requests_in_flight = 0;
|
||||
bool m_pumping_metadata_queue = false;
|
||||
int m_last_error = 0;
|
||||
FileGridType m_file_type = FileGridType::Timelapse;
|
||||
FileGridGroup m_group_mode = FileGridGroup::All;
|
||||
Status m_status = Status::Loading;
|
||||
};
|
||||
|
||||
}}
|
||||
@@ -1816,7 +1816,10 @@ void InputIpAddressDialog::set_machine_obj(MachineObject* obj)
|
||||
m_input_printer_name->GetTextCtrl()->SetLabelText(m_obj->get_dev_name());
|
||||
|
||||
std::string img_str = DevPrinterConfigUtil::get_printer_connect_help_img(m_obj->printer_type);
|
||||
auto diagram_bmp = create_scaled_bitmap(img_str + "_en", this, 198);
|
||||
if (img_str.empty()) { img_str = "input_access_code_x1"; }
|
||||
|
||||
std::string language = wxGetApp().app_config->get("language");
|
||||
auto diagram_bmp = create_scaled_bitmap(img_str + (language == "zh_CN" ? "_cn" : "_en"), this, 198);
|
||||
m_img_help->SetBitmap(diagram_bmp);
|
||||
|
||||
|
||||
|
||||
@@ -36,8 +36,6 @@
|
||||
#include "libslic3r/MultiNozzleUtils.hpp" // filament-change-gap model for the best-position popup
|
||||
#include "BackgroundSlicingProcess.hpp" // complete type for background_process().get_current_gcode_result()
|
||||
#include "DeviceCore/DevStorage.h"
|
||||
#include "slic3r/Utils/NetworkAgentFactory.hpp"
|
||||
#include "FilamentMappingUtils.hpp"
|
||||
|
||||
#include <wx/event.h>
|
||||
#include <string>
|
||||
@@ -3568,9 +3566,6 @@ void SelectMachineDialog::navigate_to_timelapse_page()
|
||||
this->EndModal(wxID_CANCEL);
|
||||
}
|
||||
|
||||
// Mapping helpers live in FilamentMappingUtils.hpp (shared with
|
||||
// SendMultiMachinePage); they mirror the agent serializer exactly.
|
||||
|
||||
void SelectMachineDialog::on_send_print()
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << "print_job: on_ok to send";
|
||||
@@ -3625,28 +3620,6 @@ void SelectMachineDialog::on_send_print()
|
||||
|
||||
get_ams_mapping_result(ams_mapping_array,ams_mapping_array2, ams_mapping_info);
|
||||
|
||||
// The policy lives in FilamentMappingUtils.hpp; this dialog only differs
|
||||
// from the multi-device page in how it reports a refusal.
|
||||
switch (prepare_filament_mapping_for_send(obj_, ams_mapping_array2, m_ams_mapping_result)) {
|
||||
case MappingSendError::unsupported:
|
||||
BOOST_LOG_TRIVIAL(warning) << "print_job: connector does not advertise filament_mapping; refusing mapped print";
|
||||
m_status_bar->set_status_text(_L("AMS filament mapping is not available for this printer. Clear the AMS mapping before printing."));
|
||||
Enable_Send_Button(true);
|
||||
return;
|
||||
case MappingSendError::incomplete:
|
||||
BOOST_LOG_TRIVIAL(warning) << "print_job: a used filament has no AMS target; refusing print";
|
||||
m_status_bar->set_status_text(_L("A filament used by this print has no AMS mapping. Assign it before printing."));
|
||||
Enable_Send_Button(true);
|
||||
return;
|
||||
case MappingSendError::none:
|
||||
break;
|
||||
default:
|
||||
// A refusal added without a handler here must not silently send.
|
||||
BOOST_LOG_TRIVIAL(warning) << "print_job: unrecognized mapping refusal; refusing print";
|
||||
Enable_Send_Button(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_print_type == PrintFromType::FROM_NORMAL) {
|
||||
result = m_plater->send_gcode(m_print_plate_idx, [this](int export_stage, int current, int total, bool& cancel) {
|
||||
if (this->m_is_canceled) return;
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
#include "GUI.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "slic3r/Utils/NetworkAgent.hpp"
|
||||
#include "GUI_Preview.hpp"
|
||||
#include "MainFrame.hpp"
|
||||
#include "Widgets/ProgressDialog.hpp"
|
||||
@@ -848,8 +847,8 @@ void SelectMachinePopup::update_machine_list(wxCommandEvent &event)
|
||||
|
||||
void SelectMachinePopup::start_ssdp(bool start)
|
||||
{
|
||||
if (auto* agent = wxGetApp().getAgent())
|
||||
agent->start_discovery(true, start);
|
||||
return;
|
||||
//if (wxGetApp().getAgent()) { wxGetApp().getAgent()->start_discovery(true, start); }
|
||||
}
|
||||
|
||||
void SelectMachinePopup::OnLeftUp(wxMouseEvent &event)
|
||||
|
||||
@@ -61,10 +61,6 @@
|
||||
|
||||
#include "DeviceCore/DevManager.h"
|
||||
#include "DeviceCore/DevStorage.h"
|
||||
|
||||
#include "slic3r/Utils/NetworkAgentFactory.hpp"
|
||||
#include "FilamentMappingUtils.hpp"
|
||||
|
||||
#include "libslic3r/AppConfig.hpp"
|
||||
#include "libslic3r/GCode/GCodeProcessor.hpp"
|
||||
#include "libslic3r/Model.hpp"
|
||||
@@ -763,8 +759,6 @@ bool SendMultiMachinePage::get_ams_mapping_result(std::string &mapping_array_str
|
||||
return true;
|
||||
}
|
||||
|
||||
// Mapping helpers live in FilamentMappingUtils.hpp, shared with SelectMachine.
|
||||
|
||||
void SendMultiMachinePage::on_send(wxCommandEvent& event)
|
||||
{
|
||||
event.Skip();
|
||||
@@ -813,30 +807,6 @@ void SendMultiMachinePage::on_send(wxCommandEvent& event)
|
||||
|
||||
if (!wxGetApp().is_blocking_printing(obj)) {
|
||||
PrintParams params = request_params(obj);
|
||||
switch (prepare_filament_mapping_for_send(obj, params.ams_mapping2, m_ams_mapping_result)) {
|
||||
case MappingSendError::unsupported:
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(warning) << "SendMultiMachinePage: connector does not advertise filament_mapping; refusing mapped print for "
|
||||
<< obj->get_dev_id();
|
||||
MessageDialog unavailable_msg(nullptr, _L("AMS filament mapping is not available for this printer. Clear the AMS mapping before printing."), "", wxICON_WARNING | wxOK);
|
||||
unavailable_msg.ShowModal();
|
||||
return;
|
||||
}
|
||||
case MappingSendError::incomplete:
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(warning) << "SendMultiMachinePage: a used filament has no target; refusing print for " << obj->get_dev_id();
|
||||
MessageDialog incomplete_msg(nullptr, _L("A filament used by this print has no AMS mapping. Assign it before printing."), "", wxICON_WARNING | wxOK);
|
||||
incomplete_msg.ShowModal();
|
||||
return;
|
||||
}
|
||||
case MappingSendError::none:
|
||||
break;
|
||||
default:
|
||||
// A refusal added without a handler here must not silently send.
|
||||
BOOST_LOG_TRIVIAL(warning) << "SendMultiMachinePage: unrecognized mapping refusal for "
|
||||
<< obj->get_dev_id();
|
||||
return;
|
||||
}
|
||||
print_params.push_back(params);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4695,14 +4695,12 @@ void StatusPanel::on_filament_edit(wxCommandEvent &event)
|
||||
}
|
||||
|
||||
m_filament_setting_dlg->m_is_third = !DevFilaSystem::IsBBL_Filament(tray->tag_uid);
|
||||
// The tray's own temps pre-fill the dialog for every tray type; a BBL tray
|
||||
// additionally carries the SN and brand.
|
||||
temp_max = tray->nozzle_temp_max;
|
||||
temp_min = tray->nozzle_temp_min;
|
||||
if (!m_filament_setting_dlg->m_is_third)
|
||||
{
|
||||
sn_number = tray->uuid;
|
||||
filament = tray->sub_brands;
|
||||
temp_max = tray->nozzle_temp_max;
|
||||
temp_min = tray->nozzle_temp_min;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4763,11 +4761,11 @@ void StatusPanel::on_ext_spool_edit(wxCommandEvent &event)
|
||||
}
|
||||
|
||||
m_filament_setting_dlg->m_is_third = !DevFilaSystem::IsBBL_Filament(obj->vt_slot[nozzle_index].tag_uid);
|
||||
temp_max = obj->vt_slot[nozzle_index].nozzle_temp_max;
|
||||
temp_min = obj->vt_slot[nozzle_index].nozzle_temp_min;
|
||||
if (!m_filament_setting_dlg->m_is_third) {
|
||||
sn_number = obj->vt_slot[nozzle_index].uuid;
|
||||
filament = obj->vt_slot[nozzle_index].sub_brands;
|
||||
temp_max = obj->vt_slot[nozzle_index].nozzle_temp_max;
|
||||
temp_min = obj->vt_slot[nozzle_index].nozzle_temp_min;
|
||||
}
|
||||
|
||||
m_filament_setting_dlg->Move(wxPoint(current_position_x,current_position_y));
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
#include "StoragePanel.h"
|
||||
|
||||
#include "DeviceManager.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "MediaFilePanel.h"
|
||||
#include "OrcaFilesPanel.h"
|
||||
#include "Widgets/StateColor.hpp"
|
||||
|
||||
#include <wx/colour.h>
|
||||
#include <wx/panel.h>
|
||||
#include <wx/event.h>
|
||||
#include <wx/sizer.h>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
StoragePanel::StoragePanel(wxWindow* parent)
|
||||
: wxPanel(parent, wxID_ANY)
|
||||
{
|
||||
const wxColour light_background("#EEEEEE");
|
||||
SetBackgroundColour(wxGetApp().dark_mode() ? StateColor::darkModeColorFor(light_background) : light_background);
|
||||
SetSizer(new wxBoxSizer(wxVERTICAL));
|
||||
}
|
||||
|
||||
MediaFilePanel* StoragePanel::ensureBambuPanel()
|
||||
{
|
||||
if (!m_bambu_panel) {
|
||||
m_bambu_panel = new MediaFilePanel(this);
|
||||
m_bambu_panel->Hide();
|
||||
GetSizer()->Add(m_bambu_panel, 1, wxEXPAND);
|
||||
wxGetApp().UpdateDarkUIWin(m_bambu_panel);
|
||||
}
|
||||
return m_bambu_panel;
|
||||
}
|
||||
|
||||
OrcaFilesPanel* StoragePanel::ensureOrcaPanel()
|
||||
{
|
||||
if (!m_orca_panel) {
|
||||
m_orca_panel = new OrcaFilesPanel(this);
|
||||
m_orca_panel->Hide();
|
||||
GetSizer()->Add(m_orca_panel, 1, wxEXPAND);
|
||||
wxGetApp().UpdateDarkUIWin(m_orca_panel);
|
||||
}
|
||||
return m_orca_panel;
|
||||
}
|
||||
|
||||
void StoragePanel::showChild(Child child)
|
||||
{
|
||||
if (m_bambu_panel)
|
||||
m_bambu_panel->Show(child == Child::Bambu);
|
||||
if (m_orca_panel)
|
||||
m_orca_panel->Show(child == Child::Orca);
|
||||
m_active_child = child;
|
||||
Layout();
|
||||
}
|
||||
|
||||
void StoragePanel::UpdateByObj(MachineObject* obj)
|
||||
{
|
||||
// Agent capability controls the page; Bambu remains the fallback for other printers.
|
||||
Child target = m_active_child;
|
||||
if (obj)
|
||||
target = obj->printer_supports_feature("printer_files") ? Child::Orca : Child::Bambu;
|
||||
else if (target == Child::None)
|
||||
target = Child::Bambu;
|
||||
|
||||
if (target != m_active_child) {
|
||||
if (m_active_child == Child::Bambu && m_bambu_panel)
|
||||
m_bambu_panel->UpdateByObj(nullptr);
|
||||
else if (m_active_child == Child::Orca && m_orca_panel)
|
||||
m_orca_panel->UpdateByObj(nullptr);
|
||||
|
||||
if (target == Child::Bambu)
|
||||
ensureBambuPanel();
|
||||
else
|
||||
ensureOrcaPanel();
|
||||
showChild(target);
|
||||
}
|
||||
|
||||
if (target == Child::Bambu)
|
||||
ensureBambuPanel()->UpdateByObj(obj);
|
||||
else if (target == Child::Orca)
|
||||
ensureOrcaPanel()->UpdateByObj(obj);
|
||||
}
|
||||
|
||||
void StoragePanel::SwitchStorage(bool external)
|
||||
{
|
||||
if (m_bambu_panel)
|
||||
m_bambu_panel->SwitchStorage(external);
|
||||
}
|
||||
|
||||
void StoragePanel::Rescale()
|
||||
{
|
||||
if (m_bambu_panel)
|
||||
m_bambu_panel->Rescale();
|
||||
if (m_orca_panel)
|
||||
m_orca_panel->Rescale();
|
||||
}
|
||||
|
||||
void StoragePanel::on_sys_color_changed()
|
||||
{
|
||||
const wxColour light_background("#EEEEEE");
|
||||
SetBackgroundColour(wxGetApp().dark_mode() ? StateColor::darkModeColorFor(light_background) : light_background);
|
||||
if (m_bambu_panel)
|
||||
wxGetApp().UpdateDarkUIWin(m_bambu_panel);
|
||||
if (m_orca_panel)
|
||||
wxGetApp().UpdateDarkUIWin(m_orca_panel);
|
||||
if (m_orca_panel)
|
||||
m_orca_panel->on_sys_color_changed();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,35 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <wx/panel.h>
|
||||
|
||||
namespace Slic3r {
|
||||
class MachineObject;
|
||||
|
||||
namespace GUI {
|
||||
|
||||
class MediaFilePanel;
|
||||
class OrcaFilesPanel;
|
||||
|
||||
class StoragePanel : public wxPanel
|
||||
{
|
||||
public:
|
||||
explicit StoragePanel(wxWindow* parent);
|
||||
|
||||
void UpdateByObj(MachineObject* obj);
|
||||
void SwitchStorage(bool external);
|
||||
void Rescale();
|
||||
void on_sys_color_changed();
|
||||
|
||||
private:
|
||||
enum class Child { None, Bambu, Orca };
|
||||
|
||||
MediaFilePanel* ensureBambuPanel();
|
||||
OrcaFilesPanel* ensureOrcaPanel();
|
||||
void showChild(Child child);
|
||||
|
||||
MediaFilePanel* m_bambu_panel = nullptr;
|
||||
OrcaFilesPanel* m_orca_panel = nullptr;
|
||||
Child m_active_child = Child::None;
|
||||
};
|
||||
|
||||
}}
|
||||
@@ -1427,12 +1427,6 @@ bool SyncAmsInfoDialog::get_ams_mapping_result(std::string &mapping_array_str, s
|
||||
BOOST_LOG_TRIVIAL(error) << "get_ams_mapping_result, plater is nullptr";
|
||||
}
|
||||
|
||||
// mapping_v1_json is built one entry per filament preset, in preset order, so the
|
||||
// array position is the logical filament index the generated G-code toolchange
|
||||
// references (the identifier handed to the Klipper toolchange macro; see
|
||||
// OrcaPrinterAgent::build_filament_mapping and the index-correlation test in
|
||||
// tests/slic3rutils/test_orca_printer_agent.cpp). Never re-densify after dropping
|
||||
// sentinel entries, or a used filament would be aimed at the wrong lane.
|
||||
for (int i = 0; i < wxGetApp().preset_bundle->filament_presets.size(); i++) {
|
||||
int tray_id = -1;
|
||||
json mapping_item_v1;
|
||||
|
||||
@@ -2928,7 +2928,7 @@ void TabPrint::build()
|
||||
optgroup->append_single_option_line("skin_infill_line_width", "strength_settings_patterns#locked-zag");
|
||||
optgroup->append_single_option_line("skeleton_infill_line_width", "strength_settings_patterns#locked-zag");
|
||||
optgroup->append_single_option_line("symmetric_infill_y_axis", "strength_settings_infill#symmetric-infill-y-axis");
|
||||
optgroup->append_single_option_line("infill_complete_top", "strength_settings_infill#infill-complete-top");
|
||||
optgroup->append_single_option_line("infill_complete_top", "strength_settings_patterns#fill-pattern-tops");
|
||||
optgroup->append_single_option_line("infill_shift_step", "strength_settings_patterns#cross-hatch");
|
||||
optgroup->append_single_option_line("lateral_lattice_angle_1", "strength_settings_patterns#lateral-lattice");
|
||||
optgroup->append_single_option_line("lateral_lattice_angle_2", "strength_settings_patterns#lateral-lattice");
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
#include <set>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
using namespace CustomGCode;
|
||||
|
||||
namespace GUI {
|
||||
std::string TickCodeInfo::get_color_for_tick(TickCode tick, Type type, const int extruder)
|
||||
{
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include <vector>
|
||||
|
||||
namespace Slic3r {
|
||||
using namespace CustomGCode;
|
||||
namespace GUI {
|
||||
|
||||
struct TickCode
|
||||
@@ -16,7 +15,7 @@ struct TickCode
|
||||
bool operator>(const TickCode& other) const { return other.tick < this->tick; }
|
||||
|
||||
int tick = 0;
|
||||
Type type = ColorChange;
|
||||
CustomGCode::Type type = CustomGCode::ColorChange;
|
||||
int extruder = 0;
|
||||
std::string color;
|
||||
std::string extra;
|
||||
@@ -31,22 +30,22 @@ class TickCodeInfo
|
||||
|
||||
std::vector<std::string>* m_colors{ nullptr };// reference to IMSlider::m_extruder_colors
|
||||
|
||||
std::string get_color_for_tick(TickCode tick, Type type, const int extruder);
|
||||
std::string get_color_for_tick(TickCode tick, CustomGCode::Type type, const int extruder);
|
||||
|
||||
public:
|
||||
std::set<TickCode> ticks{};
|
||||
Mode mode = Undef;
|
||||
CustomGCode::Mode mode = CustomGCode::Undef;
|
||||
|
||||
bool empty() const { return ticks.empty(); }
|
||||
void set_pause_print_msg(const std::string& message) { pause_print_msg = message; }
|
||||
|
||||
bool add_tick(const int tick, Type type, int extruder, double print_z);
|
||||
bool add_tick(const int tick, CustomGCode::Type type, int extruder, double print_z);
|
||||
bool edit_tick(std::set<TickCode>::iterator it, double print_z);
|
||||
void switch_code(Type type_from, Type type_to);
|
||||
bool switch_code_for_tick(std::set<TickCode>::iterator it, Type type_to, const int extruder);
|
||||
void erase_all_ticks_with_code(Type type);
|
||||
void switch_code(CustomGCode::Type type_from, CustomGCode::Type type_to);
|
||||
bool switch_code_for_tick(std::set<TickCode>::iterator it, CustomGCode::Type type_to, const int extruder);
|
||||
void erase_all_ticks_with_code(CustomGCode::Type type);
|
||||
|
||||
bool has_tick_with_code(Type type);
|
||||
bool has_tick_with_code(CustomGCode::Type type);
|
||||
bool has_tick(int tick);
|
||||
|
||||
void suppress_plus(bool suppress) { m_suppress_plus = suppress; }
|
||||
|
||||
@@ -101,7 +101,6 @@ bool AMSinfo::parse_ams_info(MachineObject *obj, DevAms *ams, bool remain_flag,
|
||||
Caninfo info;
|
||||
// tray is exists
|
||||
if (it != ams->GetTrays().end() && it->second->is_exists) {
|
||||
info.is_empty = it->second->is_empty;
|
||||
if (it->second->is_tray_info_ready()) {
|
||||
info.can_id = it->second->id;
|
||||
info.ctype = it->second->ctype;
|
||||
@@ -169,7 +168,6 @@ void AMSinfo::parse_ext_info(MachineObject* obj, DevAmsTray tray) {
|
||||
this->ams_type = AMSModel::EXT_AMS;
|
||||
Caninfo info;
|
||||
info.can_id = std::to_string(0);
|
||||
info.is_empty = tray.is_empty;
|
||||
this->cans.clear();
|
||||
|
||||
if (tray.id == std::to_string(VIRTUAL_TRAY_MAIN_ID))
|
||||
@@ -1132,9 +1130,9 @@ void AMSLib::render_lite_text(wxDC& dc)
|
||||
dc.SetTextForeground(temp_text_colour);
|
||||
|
||||
auto libsize = GetSize();
|
||||
if (!m_info.is_empty && (m_info.material_state == AMSCanType::AMS_CAN_TYPE_THIRDBRAND
|
||||
if (m_info.material_state == AMSCanType::AMS_CAN_TYPE_THIRDBRAND
|
||||
|| m_info.material_state == AMSCanType::AMS_CAN_TYPE_BRAND
|
||||
|| m_info.material_state == AMSCanType::AMS_CAN_TYPE_VIRTUAL)) {
|
||||
|| m_info.material_state == AMSCanType::AMS_CAN_TYPE_VIRTUAL) {
|
||||
|
||||
if (m_info.material_name.empty()) {
|
||||
auto tsize = dc.GetMultiLineTextExtent("?");
|
||||
@@ -1182,8 +1180,8 @@ void AMSLib::render_lite_text(wxDC& dc)
|
||||
}
|
||||
}
|
||||
|
||||
if (m_info.material_state == AMSCanType::AMS_CAN_TYPE_EMPTY || m_info.is_empty) {
|
||||
auto tsize = dc.GetMultiLineTextExtent(_L("/"));
|
||||
if (m_info.material_state == AMSCanType::AMS_CAN_TYPE_EMPTY) {
|
||||
auto tsize = dc.GetMultiLineTextExtent("/");
|
||||
auto pot = wxPoint((libsize.x - tsize.x) / 2 + FromDIP(2), (libsize.y - tsize.y) / 2 + FromDIP(3));
|
||||
dc.DrawText("/", pot);
|
||||
}
|
||||
@@ -1191,12 +1189,8 @@ void AMSLib::render_lite_text(wxDC& dc)
|
||||
|
||||
void AMSLib::render_generic_text(wxDC &dc)
|
||||
{
|
||||
// K/N is Bambu firmware's flow-dynamics calibration; agents with no printer-side
|
||||
// records (OrcaSonar, Moonraker) must not show a synthesized value.
|
||||
const bool k_supported = !m_obj || m_obj->supports_extrusion_cali();
|
||||
const bool show_kn = m_show_kn && k_supported;
|
||||
bool show_k_value = k_supported;
|
||||
if (!k_supported || m_info.material_name.empty()) {
|
||||
bool show_k_value = true;
|
||||
if (m_info.material_name.empty()) {
|
||||
show_k_value = false;
|
||||
}
|
||||
else if (m_info.cali_idx == -1 || (m_obj && (CalibUtils::get_selected_calib_idx(m_obj->pa_calib_tab, m_info.cali_idx) == -1))) {
|
||||
@@ -1237,9 +1231,9 @@ void AMSLib::render_generic_text(wxDC &dc)
|
||||
}
|
||||
|
||||
auto libsize = GetSize();
|
||||
if (!m_info.is_empty && (m_info.material_state == AMSCanType::AMS_CAN_TYPE_THIRDBRAND
|
||||
if (m_info.material_state == AMSCanType::AMS_CAN_TYPE_THIRDBRAND
|
||||
|| m_info.material_state == AMSCanType::AMS_CAN_TYPE_BRAND
|
||||
|| m_info.material_state == AMSCanType::AMS_CAN_TYPE_VIRTUAL)) {
|
||||
|| m_info.material_state == AMSCanType::AMS_CAN_TYPE_VIRTUAL) {
|
||||
|
||||
if (m_info.material_name.empty() /*&& m_info.material_state != AMSCanType::AMS_CAN_TYPE_VIRTUAL*/) {
|
||||
auto tsize = dc.GetMultiLineTextExtent("?");
|
||||
@@ -1277,7 +1271,7 @@ void AMSLib::render_generic_text(wxDC &dc)
|
||||
auto line_top_tsize = dc.GetMultiLineTextExtent(line_top);
|
||||
auto line_bottom_tsize = dc.GetMultiLineTextExtent(line_bottom);
|
||||
|
||||
if (!show_kn) {
|
||||
if (!m_show_kn) {
|
||||
auto pot_top = wxPoint((libsize.x - line_top_tsize.x) / 2, (libsize.y - line_top_tsize.y) / 2 - line_top_tsize.y + FromDIP(6));
|
||||
dc.DrawText(line_top, pot_top);
|
||||
|
||||
@@ -1308,7 +1302,7 @@ void AMSLib::render_generic_text(wxDC &dc)
|
||||
|
||||
//draw k&n
|
||||
if (m_obj && show_k_value) {
|
||||
if (show_kn) {
|
||||
if (m_show_kn) {
|
||||
wxString str_k = wxString::Format("K %1.3f", m_info.k);
|
||||
wxString str_n = wxString::Format("N %1.3f", m_info.n);
|
||||
dc.SetFont(::Label::Body_11);
|
||||
@@ -1319,7 +1313,7 @@ void AMSLib::render_generic_text(wxDC &dc)
|
||||
}
|
||||
}
|
||||
|
||||
if (m_info.material_state == AMSCanType::AMS_CAN_TYPE_EMPTY || m_info.is_empty) {
|
||||
if (m_info.material_state == AMSCanType::AMS_CAN_TYPE_EMPTY) {
|
||||
auto tsize = dc.GetMultiLineTextExtent(_L("Empty"));
|
||||
auto pot = wxPoint((libsize.x - tsize.x) / 2, (libsize.y - tsize.y) / 2 + FromDIP(3));
|
||||
dc.DrawText(_L("Empty"), pot);
|
||||
@@ -2816,7 +2810,7 @@ void AMSPreview::doRender(wxDC &dc)
|
||||
}
|
||||
else {
|
||||
wxRect rect(left, (size.y - AMS_ITEM_CUBE_SIZE.y) / 2, AMS_ITEM_CUBE_SIZE.x, AMS_ITEM_CUBE_SIZE.y);
|
||||
if (iter->material_state == AMSCanType::AMS_CAN_TYPE_EMPTY || iter->is_empty) {
|
||||
if (iter->material_state == AMSCanType::AMS_CAN_TYPE_EMPTY) {
|
||||
dc.SetPen(wxPen(wxColor(0, 0, 0)));
|
||||
dc.DrawLine(rect.GetRight() - FromDIP(1), rect.GetTop() + FromDIP(1), rect.GetLeft() + FromDIP(1), rect.GetBottom() - FromDIP(1));
|
||||
}
|
||||
|
||||
@@ -200,7 +200,6 @@ struct Caninfo
|
||||
wxString material_name;
|
||||
wxColour material_colour = {*wxWHITE};
|
||||
AMSCanType material_state;
|
||||
bool is_empty = false;
|
||||
int ctype=0;
|
||||
int material_remain = 100;
|
||||
int cali_idx = -1;
|
||||
@@ -216,7 +215,6 @@ public:
|
||||
material_name == other.material_name &&
|
||||
material_colour == other.material_colour &&
|
||||
material_state == other.material_state &&
|
||||
is_empty == other.is_empty &&
|
||||
ctype == other.ctype &&
|
||||
material_remain == other.material_remain &&
|
||||
cali_idx == other.cali_idx &&
|
||||
|
||||
@@ -456,6 +456,13 @@ wxBitmap create_scaled_bitmap( const std::string& bmp_name_in,
|
||||
const vector<std::string>& array_new_color/* = vector<std::string>*/)//used for semi transparent material)
|
||||
{
|
||||
static Slic3r::GUI::BitmapCache cache;
|
||||
|
||||
// An empty name means the caller's icon lookup failed
|
||||
if (bmp_name_in.empty() || bmp_name_in == ".png") {
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": empty bitmap name";
|
||||
return wxNullBitmap;
|
||||
}
|
||||
|
||||
if (bitmap2) {
|
||||
return create_scaled_bitmap2(bmp_name_in, cache, win, px_cnt, grayscale, resize, array_new_color);
|
||||
}
|
||||
|
||||
@@ -31,23 +31,8 @@
|
||||
#include <curl/curl.h>
|
||||
#include <utility>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/ssl.h>
|
||||
#ifdef OPENSSL_CERT_OVERRIDE
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/x509err.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
# ifndef NOMINMAX
|
||||
# define NOMINMAX
|
||||
# endif
|
||||
# include <windows.h>
|
||||
# include <wincrypt.h>
|
||||
// wincrypt.h uses this token for a certificate-name property identifier.
|
||||
# undef X509_NAME
|
||||
#endif
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
@@ -971,50 +956,6 @@ std::string Http::tls_system_cert_store()
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Http::add_platform_root_certificates(SSL_CTX* ssl_context)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
X509_STORE* openssl_store = SSL_CTX_get_cert_store(ssl_context);
|
||||
if (!openssl_store)
|
||||
throw std::runtime_error("unable to get OpenSSL certificate store");
|
||||
|
||||
const auto load_store = [&](DWORD location) {
|
||||
HCERTSTORE windows_store = CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 0, 0,
|
||||
location | CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG,
|
||||
L"ROOT");
|
||||
if (!windows_store)
|
||||
return;
|
||||
|
||||
PCCERT_CONTEXT windows_certificate = nullptr;
|
||||
while ((windows_certificate = CertEnumCertificatesInStore(windows_store, windows_certificate)) != nullptr) {
|
||||
const unsigned char* encoded = windows_certificate->pbCertEncoded;
|
||||
X509* certificate = d2i_X509(nullptr, &encoded, static_cast<long>(windows_certificate->cbCertEncoded));
|
||||
if (!certificate) {
|
||||
ERR_clear_error();
|
||||
continue;
|
||||
}
|
||||
|
||||
ERR_clear_error();
|
||||
if (X509_STORE_add_cert(openssl_store, certificate) != 1)
|
||||
ERR_clear_error();
|
||||
X509_free(certificate);
|
||||
}
|
||||
|
||||
CertCloseStore(windows_store, 0);
|
||||
};
|
||||
|
||||
load_store(CERT_SYSTEM_STORE_CURRENT_USER);
|
||||
load_store(CERT_SYSTEM_STORE_LOCAL_MACHINE);
|
||||
#elif defined(__APPLE__)
|
||||
// macOS ships its system trust roots as a PEM bundle; the bundled OpenSSL's
|
||||
// compiled-in default path is the build directory, so load this explicitly.
|
||||
if (ssl_context && ::access("/etc/ssl/cert.pem", R_OK) == 0)
|
||||
SSL_CTX_load_verify_locations(ssl_context, "/etc/ssl/cert.pem", nullptr);
|
||||
#else
|
||||
(void)ssl_context;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string Http::url_encode(const std::string &str)
|
||||
{
|
||||
::CURL *curl = ::curl_easy_init();
|
||||
|
||||
@@ -13,8 +13,6 @@
|
||||
#include "libslic3r/Exception.hpp"
|
||||
#include "libslic3r_version.h"
|
||||
|
||||
typedef struct ssl_ctx_st SSL_CTX;
|
||||
|
||||
#define MAX_SIZE_TO_FILE 3*1024
|
||||
|
||||
namespace Slic3r {
|
||||
@@ -202,10 +200,6 @@ public:
|
||||
// Return empty string on success or error message on fail.
|
||||
static std::string tls_global_init();
|
||||
static std::string tls_system_cert_store();
|
||||
// Add platform root certificates to a standalone OpenSSL context. This
|
||||
// supplements set_default_verify_paths() on platforms where OpenSSL does
|
||||
// not use the native certificate store.
|
||||
static void add_platform_root_certificates(SSL_CTX* ssl_context);
|
||||
|
||||
// converts the given string to an url_encoded_string
|
||||
static std::string url_encode(const std::string &str);
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <cstdint>
|
||||
#include <cmath>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <boost/format.hpp>
|
||||
@@ -69,34 +68,6 @@ enum class CameraStreamMode {
|
||||
http_snapshot // HTTP endpoint returning one image per request
|
||||
};
|
||||
|
||||
struct PrinterFileEntry {
|
||||
std::string path; // gcodes-root-relative, e.g. "sub/foo.gcode"
|
||||
std::string name; // basename for display
|
||||
std::uint64_t size = 0; // bytes
|
||||
std::int64_t modified = 0; // unix seconds
|
||||
};
|
||||
|
||||
// Moonraker per-file metadata: print time and filament usage. Missing fields are 0.
|
||||
struct PrinterFileMetadata {
|
||||
int estimated_time = 0; // seconds
|
||||
double filament_total = 0; // millimetres
|
||||
double filament_weight = 0; // grams
|
||||
};
|
||||
|
||||
// Async listing of the printer's G-code files. The return value reports whether
|
||||
// the request was dispatched; `callback` is invoked once with the result.
|
||||
using PrinterFileListFn = std::function<void(int result, std::vector<PrinterFileEntry> files)>;
|
||||
|
||||
// Async fetch of one G-code file's embedded thumbnail. `image` is the raw image
|
||||
// bytes (empty when the file has no thumbnail); result reports dispatch/transfer.
|
||||
using PrinterFileThumbnailFn = std::function<void(int result, std::string image)>;
|
||||
|
||||
// Async deletion of one printer G-code file. `result` reports dispatch and outcome.
|
||||
using PrinterFileDeleteFn = std::function<void(int result)>;
|
||||
|
||||
// Async fetch of one G-code file's Moonraker metadata. `meta` fields default to 0.
|
||||
using PrinterFileMetadataFn = std::function<void(int result, PrinterFileMetadata meta)>;
|
||||
|
||||
/**
|
||||
* IPrinterAgent - Interface for printer operations.
|
||||
*
|
||||
@@ -138,16 +109,6 @@ public:
|
||||
*/
|
||||
virtual int send_message(std::string dev_id, std::string json_str, int qos, int flag) = 0;
|
||||
|
||||
// Capability queries are per-device because one agent may own many printers.
|
||||
// Legacy agents keep their existing behavior unless they override these.
|
||||
virtual bool supports_command(const std::string& /*dev_id*/, const std::string& /*command*/) const { return true; }
|
||||
virtual bool supports_feature(const std::string& /*dev_id*/, const std::string& /*feature*/) const { return false; }
|
||||
|
||||
// Whether this agent serializes AMS lane selection into print.gcode_file's
|
||||
// per-print filament_mapping field. A dialect question, not a capability one:
|
||||
// the no-AMS external-spool normalization runs before capabilities are known.
|
||||
virtual bool uses_filament_mapping() const { return false; }
|
||||
|
||||
// why: gcode is firmware dialect, not a waist concept - commands whose body is Bambu-dialect
|
||||
// gcode live on the agent that speaks it; the default is an honest refusal that MachineObject's
|
||||
// publish funnel turns into a dialog.
|
||||
@@ -355,48 +316,6 @@ public:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* List the printer's G-code files, delivered asynchronously via callback.
|
||||
* Agents without a file listing report ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED.
|
||||
*/
|
||||
virtual int list_printer_files(const std::string& dev_id, PrinterFileListFn callback)
|
||||
{
|
||||
(void) dev_id;
|
||||
(void) callback;
|
||||
return ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch one G-code file's embedded thumbnail, delivered asynchronously via
|
||||
* callback. Agents without thumbnail support report ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED.
|
||||
*/
|
||||
virtual int get_printer_file_thumbnail(const std::string& dev_id, const std::string& path, PrinterFileThumbnailFn callback)
|
||||
{
|
||||
(void) dev_id; (void) path; (void) callback;
|
||||
return ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete one G-code file from the printer, delivered asynchronously via
|
||||
* callback. Agents without file deletion report ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED.
|
||||
*/
|
||||
virtual int delete_printer_file(const std::string& dev_id, const std::string& path, PrinterFileDeleteFn callback)
|
||||
{
|
||||
(void) dev_id; (void) path; (void) callback;
|
||||
return ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch one G-code file's Moonraker metadata (print time and filament usage),
|
||||
* delivered asynchronously via callback. Agents without metadata support
|
||||
* report ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED.
|
||||
*/
|
||||
virtual int get_printer_file_metadata(const std::string& dev_id, const std::string& path, PrinterFileMetadataFn callback)
|
||||
{
|
||||
(void) dev_id; (void) path; (void) callback;
|
||||
return ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register callback for fatal HTTP errors.
|
||||
*/
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user