diff --git a/.github/workflows/build_orca.yml b/.github/workflows/build_orca.yml
index f29d7f0cc6..e49e157358 100644
--- a/.github/workflows/build_orca.yml
+++ b/.github/workflows/build_orca.yml
@@ -341,12 +341,12 @@ jobs:
# Notarize main DMG
xcrun notarytool submit "OrcaSlicer_Mac_universal_${{ env.ver }}.dmg" --apple-id "${{ secrets.APPLE_DEV_ACCOUNT }}" --team-id "${{ secrets.TEAM_ID }}" --password "${{ secrets.APP_PWD }}" --wait
- xcrun stapler staple OrcaSlicer_Mac_universal_${{ env.ver }}.dmg
+ retry xcrun stapler staple OrcaSlicer_Mac_universal_${{ env.ver }}.dmg
# Notarize profile validator DMG if it exists
if [ -f "OrcaSlicer_profile_validator_Mac_universal_${{ env.ver }}.dmg" ]; then
xcrun notarytool submit "OrcaSlicer_profile_validator_Mac_universal_${{ env.ver }}.dmg" --apple-id "${{ secrets.APPLE_DEV_ACCOUNT }}" --team-id "${{ secrets.TEAM_ID }}" --password "${{ secrets.APP_PWD }}" --wait
- xcrun stapler staple OrcaSlicer_profile_validator_Mac_universal_${{ env.ver }}.dmg
+ retry xcrun stapler staple OrcaSlicer_profile_validator_Mac_universal_${{ env.ver }}.dmg
fi
- name: Create DMG without notary
@@ -460,10 +460,6 @@ jobs:
- name: Build slicer Win
if: runner.os == 'Windows'
working-directory: ${{ github.workspace }}
- # Orca: Removed Netfabb STL fixing service support in favor of CGAL.
- # env:
- # WindowsSdkDir: 'C:\Program Files (x86)\Windows Kits\10\'
- # WindowsSDKVersion: '10.0.26100.0\'
# --tests builds the unit tests too; the unit_tests_windows_* jobs run them.
run: |
# cache-path is the install directory inside the deps build directory.
diff --git a/.github/workflows/clang_tidy.yml b/.github/workflows/clang_tidy.yml
index 2f27a0eaff..445f294fcc 100644
--- a/.github/workflows/clang_tidy.yml
+++ b/.github/workflows/clang_tidy.yml
@@ -16,6 +16,15 @@ on:
permissions:
contents: read
+ # Listing caches and builds while waiting for a deps cache.
+ actions: read
+
+# Read by scripts/ci_deps_cache.sh.
+env:
+ REPO: ${{ github.repository }}
+ WORKFLOW: build_all.yml
+ BASE_REF: ${{ github.base_ref }}
+ JOB: build_linux (${{ vars.SELF_HOSTED && 'orca-lnx-server' || 'ubuntu-24.04' }})
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
@@ -35,7 +44,7 @@ jobs:
# The PR merge commit plus its first parent, the base it is diffed against.
fetch-depth: 2
- - name: Look for changed C++ files
+ - name: Look for changed files
id: changes
run: |
if git -c core.quotePath=false diff --name-only HEAD^1 -- src tests | grep -qE '\.(cpp|cc|cxx|hpp|h|hxx)$'; then
@@ -43,18 +52,75 @@ jobs:
else
echo "No C++ changes under src/ or tests/."
fi
+ if ! git diff --quiet HEAD^1 -- deps; then
+ echo "deps=true" >> "$GITHUB_OUTPUT"
+ fi
+ echo "deps-key=linux-clang-cache-orcaslicer_deps-build-${{ hashFiles('deps/**') }}" >> "$GITHUB_OUTPUT"
- # Parsing needs the dependency headers, not a build of this PR's deps/, so
- # a PR that changes deps/ falls back to the newest cache main has.
+ # Parsing needs the dependency headers, not a build of this PR's deps/.
+ # Without an exact match the job waits for the build that saves it: this
+ # PR's own when it changes deps/, otherwise a running push build of the
+ # base branch with the same deps. With neither, a PR that keeps deps/
+ # falls back to the newest cache.
- name: Restore cached deps
+ id: deps_cache
if: steps.changes.outputs.cpp == 'true'
uses: actions/cache/restore@v6
with:
path: ${{ github.workspace }}/deps/build/OrcaSlicer_dep
- key: linux-clang-cache-orcaslicer_deps-build-${{ hashFiles('deps/**') }}
+ key: ${{ steps.changes.outputs.deps-key }}
+
+ - name: Look for a build to wait for
+ id: wait_check
+ if: steps.changes.outputs.cpp == 'true' && steps.deps_cache.outputs.cache-hit != 'true'
+ env:
+ GH_TOKEN: ${{ github.token }}
+ HEAD_SHA: ${{ github.event.pull_request.head.sha }}
+ run: bash scripts/ci_deps_cache.sh ${{ steps.changes.outputs.deps == 'true' && 'own' || 'check' }}
+
+ # Linux Build Deps takes about 35 minutes on GitHub-hosted runners. The
+ # wait ends early when the deps job fails.
+ - name: Wait for the deps cache
+ if: steps.wait_check.outputs.wait-for != ''
+ timeout-minutes: 100
+ env:
+ GH_TOKEN: ${{ github.token }}
+ KEY: ${{ steps.changes.outputs.deps-key }}
+ CACHE_REF: ${{ steps.changes.outputs.deps == 'true' && github.ref || format('refs/heads/{0}', github.base_ref) }}
+ KEY_INPUTS: ${{ steps.wait_check.outputs.key-inputs }}
+ WAIT_FOR: ${{ steps.wait_check.outputs.wait-for }}
+ WAIT_SINCE: ${{ steps.wait_check.outputs.wait-since }}
+ WAIT_MINUTES: 90
+ run: bash scripts/ci_deps_cache.sh wait
+
+ - name: Restore the deps cache after waiting
+ id: waited_cache
+ if: steps.wait_check.outputs.wait-for != ''
+ uses: actions/cache/restore@v6
+ with:
+ path: ${{ github.workspace }}/deps/build/OrcaSlicer_dep
+ key: ${{ steps.changes.outputs.deps-key }}
+
+ - name: Fail without this PR's deps cache
+ if: steps.changes.outputs.deps == 'true' && steps.wait_check.outcome == 'success' && steps.waited_cache.outputs.cache-hit != 'true'
+ run: |
+ echo "::error::No deps cache ${{ steps.changes.outputs.deps-key }}. Check this PR's Linux Build Deps job, then rerun clang-tidy."
+ exit 1
+
+ - name: Restore the newest cached deps
+ id: newest_cache
+ if: steps.changes.outputs.deps != 'true' && steps.wait_check.outcome == 'success' && steps.waited_cache.outputs.cache-hit != 'true'
+ uses: actions/cache/restore@v6
+ with:
+ path: ${{ github.workspace }}/deps/build/OrcaSlicer_dep
+ key: ${{ steps.changes.outputs.deps-key }}
restore-keys: linux-clang-cache-orcaslicer_deps-build-
fail-on-cache-miss: true
+ - name: Warn about older deps
+ if: steps.newest_cache.outcome == 'success' && steps.newest_cache.outputs.cache-hit != 'true'
+ run: echo "::warning title=Older deps::No cache matches this PR's deps/, so clang-tidy parsed against ${{ steps.newest_cache.outputs.cache-matched-key }}. If it reports errors in code that uses a dependency, rerun clang-tidy once the base branch's Build all has saved the new deps."
+
- name: Apt-Install Dependencies
if: steps.changes.outputs.cpp == 'true' && !vars.SELF_HOSTED
uses: ./.github/actions/apt-install-deps
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a208c5e7a2..7f1586f222 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -497,47 +497,6 @@ endif()
# Once we get rid of Perl and libslic3r is linked statically, we can get rid of -fPIC
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
-# WIN10SDK_PATH is used to point CMake to the WIN10 SDK installation directory.
-# We pick it from environment if it is not defined in another way
-# ORCA: Removed Netfabb STL fixing service support in favor of CGAL.
-# if(WIN32)
-# if(NOT DEFINED WIN10SDK_PATH)
-# if(DEFINED ENV{WIN10SDK_PATH})
-# set(WIN10SDK_PATH "$ENV{WIN10SDK_PATH}")
-# endif()
-# endif()
-# if(DEFINED WIN10SDK_PATH)
-# #BBS: modify win10sdk_path
-# if (EXISTS "${WIN10SDK_PATH}/winrt/windows.graphics.printing3d.h")
-# set(WIN10SDK_INCLUDE_PATH "${WIN10SDK_PATH}")
-# else()
-# message("WIN10SDK_PATH is invalid: ${WIN10SDK_PATH}")
-# message("${WIN10SDK_PATH}/winrt/windows.graphics.printing3d.h was not found")
-# message("STL fixing by the Netfabb service will not be compiled")
-# unset(WIN10SDK_PATH)
-# endif()
-# else()
-# # Try to use the default Windows 10 SDK path.
-# if (DEFINED ENV{WindowsSdkDir} AND DEFINED ENV{WindowsSDKVersion})
-# set(WIN10SDK_INCLUDE_PATH "$ENV{WindowsSdkDir}/Include/$ENV{WindowsSDKVersion}")
-# else ()
-# set(WIN10SDK_INCLUDE_PATH "C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0")
-# endif ()
-# if (NOT EXISTS "${WIN10SDK_INCLUDE_PATH}/winrt/windows.graphics.printing3d.h")
-# message("${WIN10SDK_INCLUDE_PATH}/winrt/windows.graphics.printing3d.h was not found")
-# message("STL fixing by the Netfabb service will not be compiled")
-# unset(WIN10SDK_INCLUDE_PATH)
-# endif()
-# endif()
-# if(WIN10SDK_INCLUDE_PATH)
-# message("Building with Win10 Netfabb STL fixing service support")
-# add_definitions(-DHAS_WIN10SDK)
-# include_directories(SYSTEM "${WIN10SDK_INCLUDE_PATH}")
-# else()
-# message("Building without Win10 Netfabb STL fixing service support")
-# endif()
-# endif()
-
if (APPLE)
message("OS X SDK Path: ${CMAKE_OSX_SYSROOT}")
if (CMAKE_OSX_DEPLOYMENT_TARGET)
diff --git a/cmake/modules/ClangClShowIncludes.cmake b/cmake/modules/ClangClShowIncludes.cmake
index 91b9a18069..fcc48fe3f7 100644
--- a/cmake/modules/ClangClShowIncludes.cmake
+++ b/cmake/modules/ClangClShowIncludes.cmake
@@ -1,10 +1,18 @@
# ccache does not parse the -clang: arguments CMake uses for clang-cl's gcc-style
# depfile, so a cache hit writes the object and no depfile, and Ninja then records
# no headers for that object. ccache reproduces /showIncludes output on a hit.
+#
+# Clang also records the modification time of every input in a precompiled header
+# and rejects the header once one differs. ccache caches the compile that creates
+# the header, so a tree that regenerates cmake_pch.cxx gets back a header stamped
+# with the old file's time, and every compile that uses it fails. The build system
+# already rebuilds the header when an input changes. This covers the dependencies,
+# such as wxWidgets; PrecompiledHeader.cmake does the same for OrcaSlicer's targets.
foreach (_lang C CXX)
if (CMAKE_${_lang}_COMPILER_ID STREQUAL "Clang" AND
CMAKE_${_lang}_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")
set(CMAKE_DEPFILE_FLAGS_${_lang} "/showIncludes")
set(CMAKE_${_lang}_DEPFILE_FORMAT msvc)
+ list(APPEND CMAKE_${_lang}_COMPILE_OPTIONS_CREATE_PCH -Xclang -fno-pch-timestamp)
endif ()
endforeach ()
diff --git a/docs/HLSD/mesh-repair.md b/docs/HLSD/mesh-repair.md
new file mode 100644
index 0000000000..145c904769
--- /dev/null
+++ b/docs/HLSD/mesh-repair.md
@@ -0,0 +1,135 @@
+# Mesh repair — High Level Design
+
+## Purpose and scope
+
+Mesh repair turns a broken triangle mesh into closed, outward oriented shells that bound a solid, so that the
+mesh slices predictably and the other mesh tools (booleans, cut, painting) get valid input. It runs on demand:
+the *Fix Model* command of the context menu of an object or part and of the warning icon in the object list, *Fix
+All* and *Fix All Plates* in the context menu of a plate, the prompt the Cut tool shows when a cut leaves open edges,
+the *Repair and import* choice of texture import, and the `--repair` option of the command line. It is built on CGAL
+and is the only repair the application has, on every platform.
+
+`repair_mesh()` in `src/libslic3r/MeshRepair.cpp` does the work on one `TriangleMesh`, and `ModelVolume::repair()`
+applies it to a part: it replaces the mesh only when the repair changed it, and remaps or drops the painting of a
+replaced mesh. The GUI side, `fix_model_with_cgal_gui()` in `src/slic3r/Utils/FixModelByCgal.cpp`, runs it on a
+worker thread for each volume of an object, or for one volume, behind a progress dialog. `repair_mesh()` reports its
+progress between stages through a callback, which cancels the repair by throwing.
+
+## What the repaired mesh is
+
+The repair keeps what the slicer would print from the input. The slicer fills a layer where the winding number of
+the input surface is not zero (`MeshSlicingParams::SlicingMode::Regular` uses Clipper's nonzero fill rule), so:
+
+- Shells crossing each other print as their union. The repair keeps them as separate shells, as the parts of an
+ object are kept, and makes each of them an outward oriented solid.
+- A shell inside a solid that is oriented like it adds nothing, and the repair removes it.
+- A shell inside a solid that is oriented inward is a cavity, and stays one.
+- A whole mesh turned inside out prints as a solid, and the repair turns it outward.
+
+On top of that, it closes holes and cracks, gives inconsistently oriented triangles the orientation of their
+neighbours, drops degenerate, duplicate and stray flat geometry, and removes small self-intersections inside a shell,
+such as slivers and folds. Where none of this applies, it reports the mesh as unmodified and the caller keeps the
+original mesh, its painting and its object id.
+
+A volume is repaired in place and is never split into several parts: splitting by connectivity would turn a cavity
+into a separate solid part and fill it. Each solid of the result is a shell of its own, so *Split to parts* still
+separates them. Open pieces of the input whose borders meet exactly, which are pieces of one surface rather than
+solids, come out as the one shell they form.
+
+## Pipeline
+
+The input is treated as a triangle soup. Every stage after the first only runs on what the previous ones could
+not settle, so a valid mesh passes through quickly.
+
+### Valid parts first
+
+Parts of the input that are connected by vertex indices and are already closed, consistently oriented 2-manifolds
+skip the soup stages and go straight to the shell stages. Merging their points with coincident points of other
+parts would only make non-manifold junctions out of solids that touch, for example parts of an assembly exported
+together or voxels written as separate cubes.
+
+### Soup clean-up
+
+The rest of the soup has its coincident points merged. Triangles with repeated corners are dropped. Coincident
+triangles of opposite orientation are a wall between two solids touching face to face, so they cancel in pairs;
+of the remaining copies of a triangle one is kept. A connected region that would vanish entirely through
+cancelling is a two-sided export instead (every face written in both orientations), and keeps one copy of each
+triangle.
+
+Open edges then get their vertices welded within a tolerance of 1e-4 of the bounding box diagonal, which closes the
+cracks some exporters leave between triangles that should share corners. A vertex is never welded further than a
+quarter of its shortest edge, so welding cannot collapse fine detail. A soup that stays mostly open after welding has
+cracks wider than that tolerance, and is welded again with ten and then a hundred times the tolerance.
+
+### Work units
+
+The soup is cut into units repaired independently and in parallel: its connected parts, except that open parts whose
+bounding boxes touch share a unit, so that cracks and T-junctions between separately exported patches still close.
+
+### Building the mesh
+
+A unit whose edges are each shared by at most two triangles, running in opposite directions, and whose vertices each
+have a single fan of triangles, becomes a `Surface_mesh` directly. Any other unit is oriented first. Triangles are
+flipped so that neighbours across an edge shared by two of them agree, each part keeping the orientation the
+majority of its area had, which keeps inward oriented cavities inward. Edges where that is impossible or that more
+than two triangles share are cut, and each fan of triangles around a vertex gets its own copy of the vertex. If that
+still leaves an invalid mesh, CGAL's `orient_polygon_soup()` orients the unit instead, and the parts it flipped
+against their majority are reversed back. The linear pass exists because `orient_polygon_soup()` is several times
+slower on large soups that need only a few fixes.
+
+### Closing
+
+Compatible borders are stitched, parts that can be stitched once reversed are merged, and borders still open are
+snapped onto each other within the weld tolerance, which closes T-junctions. Exactly degenerate faces are removed.
+
+Holes are filled last. Planar border loops that face each other in one plane, one inside the other, bound a single
+region, such as a missing annulus at the end of a tube or a cap with features standing on it. Such a group is
+triangulated at once with a 2D constrained Delaunay triangulation that fills only the faces at odd nesting depth,
+so the openings inside the region stay open. The patch is used only if it closes every loop with the orientation
+of the triangles around it. Every other loop is filled on its own with `triangulate_hole()`, which uses a 2D
+constrained Delaunay triangulation when the loop is planar. Otherwise it searches the best triangulation among all
+triangles over the loop for loops of up to 100 edges, and among the triangles of a 3D Delaunay triangulation for
+longer ones, as the full search is cubic in the length of the loop. Beyond 200 edges the full search is not even
+used as a fallback, and a fan around the loop's centroid closes a loop nothing else could.
+
+The closed unit is split into its shells. The largest stays in place and the others are copied out, as converting
+the whole mesh again costs seconds on large models.
+
+### Shells
+
+The shells of all units, together with the valid parts set aside at the start, are handled independently and in
+parallel. Shells enclosing no volume, which hole filling makes out of stray flat patches, are dropped.
+
+Self-intersections inside a shell are removed locally with `experimental::remove_self_intersections()`, which
+remeshes the region around them. It is used only for local defects: a shell whose intersections involve more than
+5 % of its faces is left as it is, and a result that changes the enclosed volume by more than 0.1 % is undone. On
+heavily overlapping ornamental models the remeshing otherwise cuts parts down to slivers, while on genuine defects
+it changes the volume by thousandths of a percent. Overlaps left in place slice correctly. Remeshing can cut
+small pieces off a shell, so a shell it changed is split again and its pieces enclosing no volume are dropped.
+
+Shells crossing others are found through their bounding boxes and an AABB tree per shell, and are made outward
+oriented solids. For every other shell the winding number just outside it is summed from the orientation of the
+shells containing it, tested from a point on its largest face. The shell bounds the solid only if the winding
+number is zero on exactly one of its sides; it is then oriented so that the solid is inside, or dropped otherwise.
+
+Crossing shells are not united. Slicing unites them anyway, uniting them exactly costs tens of seconds on models
+made of many overlapping pieces, and it would fuse parts that *Split to parts* should keep apart.
+
+## Robustness
+
+The repair avoids `experimental::autorefine_and_remove_self_intersections()` and corefinement, which can crash on
+messy input, and uses only steps whose failures it can detect. A step that fails keeps its input. CGAL precondition
+failures surface as `repair_mesh()` returning false with the message as the error. The output is written in float,
+as every mesh in the application is.
+
+The result does not depend on thread scheduling. `libslic3r_cgal` is built with `CGAL_LINKED_WITH_TBB`. Units and
+shells are processed in parallel, but each on its own data, and their results are gathered in a fixed order;
+sorts compare complete keys, and the detected self-intersections are put in order before they are used. Snapping
+stays sequential, as its parallel version gives different results from run to run. Holes are filled with the full
+search wherever it is affordable, because the search among Delaunay triangles can choose between equally good fills
+differently from run to run, so only non-planar holes of more than 100 edges may still vary. On some inputs
+`experimental::remove_self_intersections()` itself places a few vertices differently from run to run.
+
+## Verification
+
+`tests/libslic3r/test_mesh_repair.cpp` covers each kind of defect above on small meshes with known volumes.
diff --git a/localization/i18n/pt_BR/OrcaSlicer_pt_BR.po b/localization/i18n/pt_BR/OrcaSlicer_pt_BR.po
index 57860cf67d..b4d3f0f85b 100644
--- a/localization/i18n/pt_BR/OrcaSlicer_pt_BR.po
+++ b/localization/i18n/pt_BR/OrcaSlicer_pt_BR.po
@@ -4,7 +4,7 @@ msgstr ""
"Project-Id-Version: Orca Slicer\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-10-11 16:21+0800\n"
-"PO-Revision-Date: 2026-07-26 11:14-0300\n"
+"PO-Revision-Date: 2026-10-11 16:22-0300\n"
"Last-Translator: Alexandre Folle de Menezes\n"
"Language-Team: Portuguese, Brazilian\n"
"Language: pt_BR\n"
@@ -251,7 +251,6 @@ msgstr "Padrão"
msgid "TPU High Flow"
msgstr "TPU Alto fluxo"
-# AI Translated
msgid "E3D High Flow"
msgstr "E3D Alto Fluxo"
@@ -519,7 +518,6 @@ msgstr "Pintar"
msgid "Choose filament"
msgstr "Escolher filamento"
-# AI Translated
msgid "Edge detection"
msgstr "Detecção de arestas"
@@ -1569,19 +1567,15 @@ msgstr "O traço da forma (%1%) é muito fino (largura mínima é %2% mm)."
msgid "Stroke of shape (%1%) contains unsupported: %2%."
msgstr "O traço da forma (%1%) contém não suportado: %2%."
-# AI Translated
msgid "Not valid state please report reproduction steps on github"
msgstr "Estado inválido, informe os passos para reproduzir no GitHub"
-# AI Translated
msgid "No embossed file"
msgstr "Nenhum arquivo em relevo"
-# AI Translated
msgid "Missing svg file in embossed shape"
msgstr "Arquivo SVG ausente na forma em relevo"
-# AI Translated
msgid "Missing data of svg file"
msgstr "Dados do arquivo SVG ausentes"
@@ -1671,7 +1665,6 @@ msgstr "Espelhar horizontalmente"
msgid "Change SVG Type"
msgstr "Alterar tipo de SVG"
-# AI Translated
msgid "SVG shape"
msgstr "Forma SVG"
@@ -1704,14 +1697,12 @@ msgstr "Sem recurso"
msgid "Vertex"
msgstr "Vértice"
-# AI Translated
msgid "Edge"
msgstr "Aresta"
msgid "Plane"
msgstr "Plano"
-# AI Translated
msgid "Point on edge"
msgstr "Ponto na aresta"
@@ -1721,7 +1712,6 @@ msgstr "Ponto no círculo"
msgid "Point on plane"
msgstr "Ponto no plano"
-# AI Translated
msgid "Center of edge"
msgstr "Centro da aresta"
@@ -1946,7 +1936,6 @@ msgstr ""
"\n"
"Abra apenas anexos de projetos em que você confia. Abrir mesmo assim?"
-# AI Translated
msgid "Open attachment"
msgstr "Abrir anexo"
@@ -3445,10 +3434,9 @@ msgstr "Verificar o estado dos serviços de sistema atuais"
msgid "code"
msgstr "código"
-# AI Translated
#. TRN Short for "description" of a connection error
msgid "desc"
-msgstr "desc."
+msgstr "descr"
#. TRN Short for "additional information" about a connection error
msgid "info"
@@ -4808,7 +4796,7 @@ msgid ""
msgstr ""
"A torre de purga não funciona quando a Altura de Camada Adaptativa ou a Altura de Camada de Suporte Independente está ativada.\n"
"Qual você deseja manter?\n"
-"SIM — Manter a Torre de Preparo\n"
+"SIM — Manter a Torre de Purga\n"
"NÃO — Manter a Altura de Camada Adaptativa e a Altura de Camada de Suporte Independente"
msgid ""
@@ -4819,7 +4807,7 @@ msgid ""
msgstr ""
"A torre de purga não funciona quando a Altura de Camada Adaptativa está ativa.\n"
"Qual você deseja manter?\n"
-"SIM — Manter a Torre de Preparo\n"
+"SIM — Manter a Torre de Purga\n"
"NÃO — Manter a Altura de Camada Adaptativa"
msgid ""
@@ -4830,7 +4818,7 @@ msgid ""
msgstr ""
"A torre de purga não funciona quando a Altura da Camada de Suporte Independente está ativa.\n"
"Qual você deseja manter?\n"
-"SIM — Manter a Torre de Preparo\n"
+"SIM — Manter a Torre de Purga\n"
"NÃO — Manter a Altura da Camada de Suporte Independente"
msgid ""
@@ -5777,7 +5765,7 @@ msgid "Printed up to layer %1%"
msgstr ""
msgid "Weight"
-msgstr ""
+msgstr "Peso"
msgid "Volume"
msgstr "Volume"
@@ -5868,7 +5856,6 @@ msgctxt "Axis"
msgid "Y"
msgstr "Y"
-# AI Translated
msgctxt "Axis"
msgid "Z"
msgstr "Z"
@@ -8159,7 +8146,7 @@ msgid "Tools"
msgstr "Ferramentas"
msgid "G-code"
-msgstr ""
+msgstr "G-code"
msgid "How the mode is labeled in the plate's IDEX/IQEX mode selector. Required — a mode with no name cannot be selected."
msgstr ""
@@ -8461,7 +8448,7 @@ msgid "Enabling traditional timelapse photography may cause surface imperfection
msgstr "A habilitação da fotografia tradicional em timelapse pode causar imperfeições na superfície. É recomendado mudar para o modo suave."
msgid "Smooth mode for timelapse is enabled, but the prime tower is off, which may cause print defects. Please enable the prime tower, re-slice and print again."
-msgstr "O modo suave para timelapse está ativado, mas a torre de purga está desativada, o que pode causar defeitos na impressão. Ative a torre de purga, fatie novamente e imprima de novo."
+msgstr "O modo suave para timelapse está ativado, mas a torre de purga está desativada, o que pode causar defeitos na impressão. Ative a torre de purga, refatie e imprima de novo."
msgid "Expand sidebar"
msgstr "Expandir barra lateral"
@@ -9073,7 +9060,7 @@ msgid "Unable to log in to the Flashforge printer."
msgstr "Não é possível fazer login na impressora Flashforge."
msgid "Is the printer ready? Is the print sheet in place, empty and clean?"
-msgstr "A impressora está pronta? O folha de impressão está no lugar, vazia e limpa?"
+msgstr "A impressora está pronta? A placa de impressão está no lugar, vazia e limpa?"
msgid "Upload and Print"
msgstr "Enviar e Imprimir"
@@ -9600,7 +9587,7 @@ msgid "Auto slice after changes"
msgstr "Fatiar automaticamente após mudanças"
msgid "If enabled, OrcaSlicer will re-slice automatically whenever slicing-related settings change."
-msgstr "Se ativado, o OrcaSlicer irá re-fatiar automaticamente sempre que as configurações relacionadas ao fatiamento forem alteradas."
+msgstr "Se ativado, o OrcaSlicer irá refatiar automaticamente sempre que as configurações relacionadas ao fatiamento forem alteradas."
msgid "Delay in seconds before auto slicing starts, allowing multiple edits to be grouped. Use 0 to slice immediately."
msgstr "Atraso em segundos antes do início do fatiamento automático, permitindo que várias edições sejam agrupadas. Use 0 para fatiar imediatamente."
@@ -10749,15 +10736,12 @@ msgstr "Descrição do erro"
msgid "Extra info"
msgstr "Informação extra"
-# AI Translated
msgid "The Filament Track Switch installed on the printer does not match the slicing file. Please re-slice to avoid print quality issues."
-msgstr "O Filament Track Switch instalado na impressora não corresponde ao arquivo de fatiamento. Por favor, refaça o fatiamento para evitar problemas de qualidade de impressão."
+msgstr "O Filament Track Switch instalado na impressora não corresponde ao arquivo de fatiamento. Por favor, refatie para evitar problemas de qualidade de impressão."
-# AI Translated
msgid "This print requires a Filament Track Switch. Please install it first."
msgstr "Esta impressão requer um Filament Track Switch. Por favor, instale-o primeiro."
-# AI Translated
msgid "The Filament Track Switch has not been setup. Please setup it first."
msgstr "O Filament Track Switch não foi configurado. Por favor, configure-o primeiro."
@@ -10798,7 +10782,6 @@ msgstr "O filamento não corresponde ao filamento no espaço do AMS. Atualize o
msgid "The selected printer (%s) is incompatible with the print file configuration (%s). Please adjust the printer preset in the prepare page or choose a compatible printer on this page."
msgstr "A impressora selecionada (%s) é incompatível com a configuração do arquivo de impressão (%s). Ajuste a predefinição da impressora na página de preparo ou escolha uma impressora compatível nesta página."
-# AI Translated
#, c-format, boost-format
msgid "The selected printer (%s) has an unknown model, so compatibility with the print file configuration (%s) cannot be verified. Please verify the printer preset before sending."
msgstr "A impressora selecionada (%s) tem um modelo desconhecido, então a compatibilidade com a configuração do arquivo de impressão (%s) não pode ser verificada. Verifique a predefinição da impressora antes de enviar."
@@ -10876,11 +10859,9 @@ msgstr "Limpar"
msgid "Preparing print job"
msgstr "Preparando trabalho de impressão"
-# AI Translated
msgid "Failed to upload the file to the printer's storage. Please try again."
msgstr "Falha ao enviar o arquivo para o armazenamento da impressora. Tente novamente."
-# AI Translated
msgid "Send Failed"
msgstr "Falha no envio"
@@ -10891,11 +10872,9 @@ msgstr "O comprimento do nome excede o limite."
msgid "Cost %dg filament and %d changes more than optimal grouping."
msgstr "O custo de %dg de filamento e %d muda mais do que o agrupamento ideal."
-# AI Translated
msgid "Right-Ext"
msgstr "Ext-Direita"
-# AI Translated
msgid "Left-Ext"
msgstr "Ext-Esquerda"
@@ -10916,7 +10895,7 @@ msgid "Please refresh the nozzle information and try again."
msgstr "Por favor, atualize as informações do bico e tente novamente."
msgid "Please re-slice to avoid filament waste."
-msgstr "Por favor, fatie novamente para evitar desperdício de filamento."
+msgstr "Por favor, refatie para evitar desperdício de filamento."
msgid "The reported hotend information may be unreliable."
msgstr "As informações reportadas sobre o hotend podem não ser confiáveis."
@@ -11060,7 +11039,6 @@ msgstr "Não é possível enviar um trabalho de impressão para uma placa vazia.
msgid "Storage needs to be inserted to record timelapse."
msgstr "O armazenamento precisa estar inserido para gravar o timelapse."
-# AI Translated
msgid "The selected printer model could not be identified, so compatibility with the print file configuration cannot be verified. Please verify the printer preset before sending."
msgstr "O modelo da impressora selecionada não pôde ser identificado, então a compatibilidade com a configuração do arquivo de impressão não pode ser verificada. Verifique a predefinição da impressora antes de enviar."
@@ -11128,7 +11106,6 @@ msgstr "A impressora deve estar na mesma LAN do OrcaSlicer."
msgid "The printer does not support sending to printer storage."
msgstr "A impressora não suporta envio para o armazenamento da impressora."
-# AI Translated
msgid "Failed to initialize the printer file transfer. Please check the connection and try again."
msgstr "Falha ao inicializar a transferência de arquivos da impressora. Verifique a conexão e tente novamente."
@@ -11284,13 +11261,13 @@ msgid "A prime tower is required for clumping detection. There may be flaws on t
msgstr "Uma torre de purga é necessária para a detecção de aglomeração. Podem ocorrer falhas no modelo sem a torre de purga. Tem certeza de que deseja desativar a torre de purga?"
msgid "Enabling both precise Z height and the prime tower may cause slicing errors. Do you still want to enable?"
-msgstr "Habilitar a altura Z precisa e a torre de preparação juntas pode causar erros de fatiamento. Deseja habilitar mesmo assim?"
+msgstr "Habilitar a altura Z precisa e a torre de purga juntas pode causar erros de fatiamento. Deseja habilitar mesmo assim?"
msgid "A prime tower is required for clumping detection. There may be flaws on the model without prime tower. Do you still want to enable clumping detection?"
msgstr "Uma torre de purga é necessária para a detecção de aglomeração. Podem ocorrer falhas no modelo sem o Prime Tower. Tem certeza de que deseja ativar a detecção de aglomeração?"
msgid "Enabling both precise Z height and the prime tower may cause slicing errors. Do you still want to enable precise Z height?"
-msgstr "Habilitar a altura Z precisa e a torre de preparação juntas pode causar erros de fatiamento. Deseja habilitar a altura Z precisa mesmo assim?"
+msgstr "Habilitar a altura Z precisa e a torre de purga juntas pode causar erros de fatiamento. Deseja habilitar a altura Z precisa mesmo assim?"
msgid "Smooth timelapse needs a prime tower on every layer, which is not compatible with \"No sparse layers\". \"No sparse layers\" has been turned off."
msgstr "O timelapse suave precisa de uma torre de purga em todas as camadas, o que não é compatível com \"Sem camadas esparsas\". \"Sem camadas esparsas\" foi desativado."
@@ -11404,10 +11381,9 @@ msgstr "Informação adicional:"
msgid "vendor"
msgstr "fornecedor"
-# AI Translated
#. TRN Short for "version"
msgid "ver"
-msgstr "versão"
+msgstr "ver"
msgid "printer model"
msgstr "modelo de impressora"
@@ -12526,11 +12502,9 @@ msgstr "[Ação Necessária] "
msgid "[Action Required]"
msgstr "[Ação Necessária]"
-# AI Translated
msgid "Printer update service is unavailable."
msgstr "O serviço de atualização de impressoras não está disponível."
-# AI Translated
msgid "Failed to check for new printers."
msgstr "Falha ao verificar novas impressoras."
@@ -12546,12 +12520,10 @@ msgstr "Mover Vista"
msgid "Rotate View"
msgstr "Rotacionar Vista"
-# AI Translated
#, c-format, boost-format
msgid "Use %s or %s, or a key that does not type a character."
msgstr "Use %s ou %s, ou uma tecla que não digite um caractere."
-# AI Translated
msgctxt "Keyboard Shortcut"
msgid "Key"
msgstr "Tecla"
@@ -12559,15 +12531,12 @@ msgstr "Tecla"
msgid "Left mouse"
msgstr "Mouse esquerdo"
-# AI Translated
msgid "Available anywhere in the window, even while typing in a text field."
msgstr "Disponível em qualquer lugar da janela, mesmo ao digitar em um campo de texto."
-# AI Translated
msgid "Run favorite 1 to 10"
msgstr "Executar favorito 1 a 10"
-# AI Translated
msgid "Pin or unpin the selected action"
msgstr "Fixar ou desafixar a ação selecionada"
@@ -12575,11 +12544,9 @@ msgctxt "Keyboard Shortcut"
msgid "Tab"
msgstr "Tab"
-# AI Translated
msgid "Switch to the next main tab"
msgstr "Mudar para a próxima aba principal"
-# AI Translated
msgid "Available while the 3D view on the Prepare tab has focus."
msgstr "Disponível enquanto a vista 3D da aba Preparar estiver em foco."
@@ -12610,11 +12577,9 @@ msgstr "Mouse direito"
msgid "Zoom View"
msgstr "Aproximar Vista"
-# AI Translated
msgid "Painting"
msgstr "Pintura"
-# AI Translated
msgid "Available while a painting gizmo is open: supports, seam, fuzzy skin or color painting."
msgstr "Disponível enquanto um gizmo de pintura estiver aberto: suportes, costura, textura difusa ou pintura de cores."
@@ -12627,7 +12592,6 @@ msgstr "Suporte/Pintura em cores: ajustar o raio da caneta"
msgid "Objects list"
msgstr "Lista de objetos"
-# AI Translated
msgid "Available while the object list has focus."
msgstr "Disponível enquanto a lista de objetos estiver em foco."
@@ -12647,43 +12611,35 @@ msgstr "Clique do mouse"
msgid "Select the object/part and mouse click to change the name"
msgstr "Selecione o objeto/peça e clique do mouse para mudar o nome"
-# AI Translated
msgid "Available while the 3D view on the Preview tab has focus."
msgstr "Disponível enquanto a vista 3D da aba Pré-visualizar estiver em foco."
msgid "Move slider 5x faster"
-msgstr "Mover o controle deslizante 5 vezes mais rápido"
+msgstr "Mover o controle deslizante 5x mais rápido"
-# AI Translated
msgid "Scroll slider 5x faster"
-msgstr "Rolar o controle deslizante 5 vezes mais rápido"
+msgstr "Rolar o controle deslizante 5x mais rápido"
msgid "Not customizable"
msgstr "Não personalizável"
-# AI Translated
#, c-format, boost-format
msgid "%s is assigned to %s. Reassign it to %s?"
msgstr "%s está atribuído a %s. Reatribuí-lo a %s?"
-# AI Translated
#, c-format, boost-format
msgid "The default %s is assigned to %s. Reassign it to %s?"
msgstr "O %s padrão está atribuído a %s. Reatribuí-lo a %s?"
-# AI Translated
msgid "Global shortcuts also apply while typing."
msgstr "Os atalhos globais também funcionam durante a digitação."
-# AI Translated
msgid "A key that types a character cannot be a global shortcut."
msgstr "Uma tecla que digita um caractere não pode ser um atalho global."
-# AI Translated
msgid "Esc cancels, Enter confirms."
msgstr "Esc cancela, Enter confirma."
-# AI Translated
#, c-format, boost-format
msgid ""
"Press the new shortcut for\n"
@@ -12692,20 +12648,16 @@ msgstr ""
"Pressione o novo atalho para\n"
"\"%s\""
-# AI Translated
msgid "Unbind"
msgstr "Desvincular"
-# AI Translated
msgid "The system uses this shortcut, so it cannot be assigned."
msgstr "O sistema usa este atalho, então ele não pode ser atribuído."
-# AI Translated
#, c-format, boost-format
msgid "Shift and Ctrl with this key belong to %s and cannot be assigned."
msgstr "Shift e Ctrl com esta tecla pertencem a %s e não podem ser atribuídos."
-# AI Translated
#, c-format, boost-format
msgid "Already assigned to %s. Press OK to reassign it."
msgstr "Já atribuído a %s. Pressione OK para reatribuí-lo."
@@ -12785,9 +12737,8 @@ msgstr "Abrir arquivo de certificado CA"
msgid "HTTPS CA file is optional. It is only needed if you use HTTPS with a self-signed certificate."
msgstr "O arquivo CA HTTPS é opcional. É necessário apenas se você usar HTTPS com um certificado autoassinado."
-# AI Translated
msgid "This system uses HTTPS certificates from the system Certificate Store or Keychain. To use a custom CA file, import it there."
-msgstr "Este sistema usa certificados HTTPS do repositório de certificados do sistema ou do Keychain. Para usar um arquivo CA personalizado, importe-o lá."
+msgstr "Este sistema usa certificados HTTPS do Repositório de Certificados ou Chaveiro do sistema. Para usar um arquivo CA personalizado, importe-o lá."
msgid "Printer model"
msgstr "Modelo de impressora"
@@ -12862,18 +12813,15 @@ msgstr "Laser 40W"
msgid "Cutting Module"
msgstr "Módulo de Corte"
-# AI Translated
msgid "Active Cutting Module"
msgstr "Módulo de Corte Ativo"
-# AI Translated
msgid "Ultrasonic Cutting Module"
msgstr "Módulo de Corte Ultrassônico"
msgid "Auto Fire Extinguishing System"
msgstr "Sistema Automático de Extinção de Incêndio"
-# AI Translated
msgid "Filament Track Switch"
msgstr "Filament Track Switch"
@@ -13018,32 +12966,26 @@ msgstr "Erro de agrupamento: %1% não pode ser colocado no bico direito"
msgid "Group error in manual mode. Please check nozzle count or regroup."
msgstr "Erro de agrupamento no modo manual. Por favor, verifique o número de bicos ou reagrupe."
-# AI Translated
#, boost-format
msgid "failed to process some intersections (%1%)"
msgstr "falha ao processar algumas interseções (%1%)"
-# AI Translated
#, boost-format
msgid "multiple intersections with a perimeter, only one was used (%1%)"
msgstr "múltiplas interseções com um perímetro, apenas uma foi usada (%1%)"
-# AI Translated
#, boost-format
msgid "a perimeter is fully inside a modifier, the modifier was not applied to it (%1%)"
-msgstr "um perímetro está totalmente dentro de um modificador; o modificador não foi aplicado a ele (%1%)"
+msgstr "um perímetro está totalmente dentro de um modificador, o modificador não foi aplicado a ele (%1%)"
-# AI Translated
#, boost-format
msgid "modifier \"%1%\" of \"%2%\" had no effect on the seam (it might not reach the centerline of the printed perimeter)"
msgstr "o modificador \"%1%\" de \"%2%\" não teve efeito na costura (talvez não alcance a linha central do perímetro impresso)"
-# AI Translated
#, boost-format
msgid "modifier \"%1%\" of \"%2%\" (%3% in total) had no effect on the seam (it might not reach the centerline of the printed perimeter)"
msgstr "o modificador \"%1%\" de \"%2%\" (%3% no total) não teve efeito na costura (talvez não alcance a linha central do perímetro impresso)"
-# AI Translated
msgid "Seam placement may differ from expected."
msgstr "A posição da costura pode diferir do esperado."
@@ -13185,7 +13127,7 @@ msgid " is too close to clumping detection area, there may be collisions when pr
msgstr " está muito perto da área de detecção de aglomeração, podendo haver colisões durante a impressão."
msgid "Prime Tower"
-msgstr "Torre de Preparo"
+msgstr "Torre de Purga"
msgid " is too close to others, and collisions may be caused.\n"
msgstr " está muito perto de outros, e colisões podem ocorrer.\n"
@@ -13267,7 +13209,7 @@ msgid "The project contains multiple managed belt purge towers. Reload the plate
msgstr ""
msgid "Enabling both precise Z height and the prime tower may cause slicing errors."
-msgstr "Habilitar a altura Z precisa e a torre de preparação juntas pode causar erros de fatiamento."
+msgstr "Habilitar a altura Z precisa e a torre de purga juntas pode causar erros de fatiamento."
msgid "A prime tower is required for clumping detection; otherwise, there may be flaws on the model."
msgstr "Uma torre de purga é necessária para a detecção de aglomeração, podem ocorrer falhas no modelo."
@@ -14323,9 +14265,8 @@ msgstr "Combine várias bordas em uma só quando estiverem próximas umas das ou
msgid "Brim ears"
msgstr "Orelhas da borda"
-# AI Translated
msgid "Only draw brim over the sharp edges of the model."
-msgstr "Desenhe a borda apenas sobre as arestas afiadas do modelo."
+msgstr "Desenhe a borda apenas sobre as arestas vivas do modelo."
msgid "Brim ear max angle"
msgstr "Ângulo máximo da orelha da borda"
@@ -14913,19 +14854,15 @@ msgstr ""
"\n"
"A taxa de fluxo final do objeto é este valor multiplicado pela taxa de fluxo do filamento."
-# AI Translated
msgid "Enable pressure advance"
msgstr "Habilitar Pressure Advance"
-# AI Translated
msgid "Enable pressure advance, auto calibration result will be overwritten once enabled."
msgstr "Habilitar Pressure Advance, o resultado da calibração automática será sobrescrito uma vez habilitado."
-# AI Translated
msgid "Pressure advance (Klipper) AKA Linear advance factor (Marlin)."
-msgstr "Pressure Advance (Klipper), também conhecido como fator de Linear Advance (Marlin)."
+msgstr "Pressure Advance (Klipper), também conhecido como Fator de Linear Advance (Marlin)."
-# AI Translated
msgid "Enable adaptive pressure advance (beta)"
msgstr "Habilitar Pressure Advance adaptativo (beta)"
@@ -14946,7 +14883,6 @@ msgstr ""
"Quando habilitado, o valor do Pressure Advance acima é substituído. No entanto, um valor padrão razoável acima é fortemente recomendado para atuar como um fallback e para quando a ferramenta for trocada.\n"
"\n"
-# AI Translated
msgid "Adaptive pressure advance measurements (beta)"
msgstr "Medidas do Pressure Advance adaptativo (beta)"
@@ -14975,7 +14911,6 @@ msgstr ""
"2. Anote o valor de PA ideal para cada velocidade e aceleração de fluxo volumétrico. Você pode encontrar o número do fluxo selecionando fluxo no menu suspenso do esquema de cores e movendo o controle deslizante horizontal sobre as linhas do padrão de PA. O número deve estar visível na parte inferior da página. O valor de PA ideal deve diminuir quanto maior for o fluxo volumétrico. Se não estiver, confirme se sua extrusora está funcionando corretamente. Quanto mais lento e com menos aceleração você imprimir, maior será o intervalo de valores de PA aceitáveis. Se nenhuma diferença for visível, use o valor de PA do teste mais rápido\n"
"3. Insira os tripletos de valores de PA, Fluxo e Acelerações na caixa de texto aqui e salve seu perfil de filamento."
-# AI Translated
msgid "Enable adaptive pressure advance within features (beta)"
msgstr "Habilitar Pressure Advance adaptativo nos recursos (beta)"
@@ -14992,9 +14927,8 @@ msgstr ""
"\n"
"Esta é uma opção experimental, pois se o perfil de PA não for definido com precisão, causará problemas de uniformidade."
-# AI Translated
msgid "Static pressure advance for bridges"
-msgstr "Pressure Advance estático para pontes"
+msgstr "Pressure advance estático para pontes"
# AI Translated
msgid ""
@@ -15254,13 +15188,13 @@ msgid "Interface layer pre-extrusion distance"
msgstr "Distância de pré-extrusão da camada de interface"
msgid "Pre-extrusion distance for prime tower interface layer (where different materials meet)."
-msgstr "Distância de pré-extrusão para a camada de interface da torre de preparação (onde diferentes materiais se encontram)."
+msgstr "Distância de pré-extrusão para a camada de interface da torre de purga (onde diferentes materiais se encontram)."
msgid "Interface layer pre-extrusion length"
msgstr "Comprimento de pré-extrusão da camada de interface"
msgid "Pre-extrusion length for prime tower interface layer (where different materials meet)."
-msgstr "Comprimento de pré-extrusão para a camada de interface da torre de preparação (onde diferentes materiais se encontram)."
+msgstr "Comprimento de pré-extrusão para a camada de interface da torre de purga (onde diferentes materiais se encontram)."
msgid "Tower ironing area"
msgstr "Area de alisamento da torre"
@@ -15275,13 +15209,13 @@ msgid "Interface layer purge length"
msgstr "Comprimento de purga da camada de interface"
msgid "Purge length for prime tower interface layer (where different materials meet)."
-msgstr "Comprimento de purga para a camada de interface da torre de preparação (onde diferentes materiais se encontram)."
+msgstr "Comprimento de purga para a camada de interface da torre de purga (onde diferentes materiais se encontram)."
msgid "Interface layer print temperature"
msgstr "Temperatura de impressão da camada de interface"
msgid "Print temperature for prime tower interface layer (where different materials meet). If set to -1, use max recommended nozzle temperature."
-msgstr "Temperatura de impressão para a camada de interface da torre de preparação (onde diferentes materiais se encontram). Se definida como -1, use a temperatura máxima recomendada do bico."
+msgstr "Temperatura de impressão para a camada de interface da torre de purga (onde diferentes materiais se encontram). Se definida como -1, use a temperatura máxima recomendada do bico."
msgid "Speed of the last cooling move"
msgstr "Velocidade do último movimento de resfriamento"
@@ -15534,10 +15468,10 @@ msgid "Linear"
msgstr "Linear"
msgid "Quadratic"
-msgstr ""
+msgstr "Quadrático"
msgid "Exponential"
-msgstr ""
+msgstr "Exponencial"
msgid "Z-buckling bias optimization (experimental)"
msgstr "Otimização de tendência à flambagem em Z (experimental)"
@@ -16252,11 +16186,9 @@ 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."
-# AI Translated
msgid "Fill pattern tops"
msgstr "Preencher os topos do padrão"
-# AI Translated
msgid "Choose this option if you want to completely fill in the tops of the infill pattern"
msgstr "Escolha esta opção se quiser preencher completamente os topos do padrão de preenchimento"
@@ -17295,7 +17227,6 @@ msgstr "Bowden"
msgid "Hybrid"
msgstr "Híbrido"
-# AI Translated
msgid "Extra High Flow"
msgstr "Fluxo Extra Alto"
@@ -17708,7 +17639,6 @@ msgstr "Passos de pré-aquecimento"
msgid "Insert multiple preheat commands (e.g. M104.1). Only useful for Prusa XL. For other printers, please set it to 1."
msgstr "Insire múltiplos comandos de pré-aquecimento (ex.: M104.1). Útil apenas para Prusa XL. Para outras impressoras, defina como 1."
-# AI Translated
msgid "G-code written at the very top of the output file, before any other content. Useful for adding metadata that printer firmware reads from the first lines of the file (e.g. estimated print time, filament usage). Supports placeholders like {print_time_total_sec}, {print_time_day}, {print_time_hour}, {print_time_minute}, {print_time_sec} and {used_filament_length}."
msgstr "G-code escrito no início do arquivo de saída, antes de qualquer outro conteúdo. Útil para adicionar metadados que o firmware da impressora lê nas primeiras linhas do arquivo (ex.: tempo estimado de impressão, uso de filamento). Suporta marcadores como {print_time_total_sec}, {print_time_day}, {print_time_hour}, {print_time_minute}, {print_time_sec} e {used_filament_length}."
@@ -17865,7 +17795,6 @@ msgstr "Sem camadas esparsas (beta)"
msgid "If enabled, the wipe tower will not be printed on layers with no tool changes. On layers with a tool change, extruder will travel downward to print the wipe tower, so the tower ends up below the model and the toolhead has to reach down to it. Layouts where that would collide with an already printed object are rejected. Has no effect with smooth timelapse or clumping detection, which need a tower on every layer."
msgstr "Se ativado, a torre de purga não será impressa nas camadas sem mudanças de ferramenta. Nas camadas com mudança de ferramenta, a extrusora descerá para imprimir a torre de purga, de modo que a torre fica abaixo do modelo e a cabeça da ferramenta precisa descer até ela. Disposições em que isso colidiria com um objeto já impresso são rejeitadas. Não tem efeito com o timelapse suave nem com a detecção de aglomeração no bico, que precisam de uma torre em todas as camadas."
-# AI Translated
msgid "Combine sparse layers"
msgstr "Combinar camadas esparsas"
@@ -18662,11 +18591,9 @@ msgstr "Largura da nervura"
msgid "Rib width is always less than half the prime tower side length."
msgstr "A largura da nervura sempre é menor do que a metade da largura da torre de purga."
-# AI Translated
msgid "Fillet wall"
msgstr "Parede com filete"
-# AI Translated
msgid "The wall of prime tower will fillet."
msgstr "A parede da torre de purga terá um filete."
@@ -19246,11 +19173,9 @@ msgstr "Permitir rotações ao arranjar"
msgid "If enabled, Arrange will allow rotation when placing objects."
msgstr "Se habilitado, o arranjo permitirá rotações ao posicionar objetos."
-# AI Translated
msgid "Align to Y axis when arranging"
msgstr "Alinhar ao eixo Y ao organizar"
-# AI Translated
msgid "If enabled, Arrange will turn each object so its long side runs along the Y axis before placing it. When not given, it is on for i3 printers and off for the others, as in the GUI."
msgstr "Se ativado, Organizar girará cada objeto para que seu lado mais longo fique ao longo do eixo Y antes de colocá-lo. Quando não informado, fica ativado para impressoras i3 e desativado para as demais, como na interface gráfica."
@@ -19440,42 +19365,33 @@ msgstr "Fil. usado"
msgid "Total length of filament used in the print."
msgstr "Comprimento total de filamento usado na impressão."
-# AI Translated
msgid "Print time (total seconds)"
msgstr "Tempo de impressão (total em segundos)"
msgid "Total estimated print time in seconds. Replaced with actual value during post-processing."
msgstr "Tempo total estimado de impressão em segundos. Substituído pelo valor real durante o pós-processamento."
-# AI Translated
msgid "Print time (days component)"
msgstr "Tempo de impressão (componente de dias)"
-# AI Translated
msgid "Estimated print time day component (normal mode). Replaced with actual value during post-processing."
msgstr "Componente de dias do tempo estimado de impressão (modo normal). Substituído pelo valor real durante o pós-processamento."
-# AI Translated
msgid "Print time (hours component)"
msgstr "Tempo de impressão (componente de horas)"
-# AI Translated
msgid "Estimated print time hour component (normal mode). Replaced with actual value during post-processing."
msgstr "Componente de horas do tempo estimado de impressão (modo normal). Substituído pelo valor real durante o pós-processamento."
-# AI Translated
msgid "Print time (minutes component)"
msgstr "Tempo de impressão (componente de minutos)"
-# AI Translated
msgid "Estimated print time minute component (normal mode). Replaced with actual value during post-processing."
msgstr "Componente de minutos do tempo estimado de impressão (modo normal). Substituído pelo valor real durante o pós-processamento."
-# AI Translated
msgid "Print time (seconds component)"
msgstr "Tempo de impressão (componente de segundos)"
-# AI Translated
msgid "Estimated print time second component (normal mode). Replaced with actual value during post-processing."
msgstr "Componente de segundos do tempo estimado de impressão (modo normal). Substituído pelo valor real durante o pós-processamento."
@@ -19935,20 +19851,17 @@ msgstr "material com significativa contração/expansão térmica, como…"
msgid "materials with inaccurate filament diameter"
msgstr "materiais com diâmetro de filamento impreciso"
-# AI Translated
#, boost-format
msgid "%1% Flow Rate Calibrated"
-msgstr "%1% Taxa de fluxo calibrada"
+msgstr "%1% Taxa de Fluxo Calibrada"
-# AI Translated
#, boost-format
msgid "%1% Temperature Calibrated"
-msgstr "%1% Temperatura calibrada"
+msgstr "%1% Temperatura Calibrada"
-# AI Translated
#, boost-format
msgid "%1% Max Vol Speed Calibrated"
-msgstr "%1% Vel. vol. máx. calibrada"
+msgstr "%1% Vel. Vol. Máx. Calibrada"
msgid "We found the best Flow Dynamics Calibration Factor"
msgstr "Encontramos o melhor Fator de Calibração de Dinâmica de Fluxo"
@@ -20309,7 +20222,6 @@ msgstr "Temp. final: "
msgid "Temp step: "
msgstr "Passo de Temperatura: "
-# AI Translated
#. TRN %s is the temperature unit
#, c-format, boost-format
msgid "Supported range: 170%s - 500%s"
@@ -20696,7 +20608,6 @@ msgstr "Calibrar antes da impressão"
msgid "Filament Mapping:"
msgstr "Mapeamnto de Filamnto:"
-# AI Translated
#. TRN External spool slot, followed by its filament type
#, c-format, boost-format
msgid "Ext - %s"
@@ -20777,23 +20688,19 @@ msgstr "Testar bing.com:"
msgid "Log Info"
msgstr "Informações do Registro"
-# AI Translated
#. TRN %s is the name of the tested website
#, c-format, boost-format
msgid "test %s start..."
msgstr "iniciando teste de %s..."
-# AI Translated
#, c-format, boost-format
msgid "test %s ip resolved = %s"
msgstr "teste de %s: IP resolvido = %s"
-# AI Translated
#, c-format, boost-format
msgid "test %s failed"
msgstr "teste de %s falhou"
-# AI Translated
#, c-format, boost-format
msgid "test %s ok"
msgstr "teste de %s ok"
@@ -21338,15 +21245,12 @@ msgstr "Sessão válida não detectada. Prosseguir com o login no 3DPrinterOS?"
msgid "Success!"
msgstr "Sucesso!"
-# AI Translated
msgid "Generate API Key"
msgstr "Gerar Chave da API"
-# AI Translated
msgid "API Key created. Go to the physical printer and hit \"authorize\" on the screen, then run \"Test\" again."
msgstr "Chave da API criada. Vá até a impressora física e toque em \"authorize\" (autorizar) na tela; depois execute \"Testar\" novamente."
-# AI Translated
msgid "API Key created."
msgstr "Chave da API criada."
@@ -21361,10 +21265,10 @@ msgstr "Substituir a aba do dispositivo do BambuLab pela webui do host de impres
#, c-format, boost-format
msgid "On this system, %s uses HTTPS certificates from the system Certificate Store or Keychain."
-msgstr "Neste sistema, %s usa certificados HTTPS da loja de certificados do sistema ou do Keychain."
+msgstr "Neste sistema, %s usa certificados HTTPS do Repositório de Certificados ou Chaveiro do sistema."
msgid "To use a custom CA file, please import your CA file into Certificate Store / Keychain."
-msgstr "Para usar um arquivo CA personalizado, importe seu arquivo CA para a loja de certificados / Keychain."
+msgstr "Para usar um arquivo CA personalizado, importe seu arquivo CA para o Repositório de Certificados / Chaveiro."
msgid "Login/Test"
msgstr "Login/Teste"
@@ -21376,9 +21280,8 @@ msgid "Detect Creality K-series printer"
msgstr "Detectar impressora Creality da série K"
msgid "Click Scan to look for K-series printers on your network."
-msgstr "Clique para buscar impressora Creality da série K na sua rede."
+msgstr "Clique em Buscar para procurar impressoras Creality da série K na sua rede."
-# AI Translated
msgid "Scan"
msgstr "Buscar"
@@ -21388,7 +21291,6 @@ msgstr "Usar Selecionada"
msgid "Scanning the LAN for K-series printers... this takes a few seconds."
msgstr "Buscando impressoras série K na rede… isso leva alguns segundos."
-# AI Translated
msgid "(unknown K-series)"
msgstr "(série K desconhecida)"
@@ -21492,7 +21394,6 @@ msgstr "log(s)"
msgid "Choose where to save the exported JSON file"
msgstr "Escolha onde salvar o arquivo JSON exportado"
-# AI Translated
msgid "JSON files (*.json)|*.json"
msgstr "Arquivos JSON (*.json)|*.json"
@@ -21766,7 +21667,6 @@ msgstr "Nome da tarefa"
msgid "Actions"
msgstr "Ações"
-# AI Translated
#. TRN Button that jumps to the page number typed next to it
msgid "Go"
msgstr "Ir"
@@ -21877,7 +21777,6 @@ msgstr " para definir o número de bicos"
msgid "Set the physical nozzle count..."
msgstr "Definir o número de bicos físicos…"
-# AI Translated
#, c-format, boost-format
msgid "(Std: %d, HF: %d)"
msgstr "(Pad.: %d, AF: %d)"
@@ -22313,7 +22212,6 @@ msgstr ""
msgid "Save preset bundle"
msgstr "Salvar pacote de predefinições"
-# AI Translated
msgid "Orca Preset Bundle (*.orca_bundle)|*.orca_bundle"
msgstr "Pacote de predefinições Orca (*.orca_bundle)|*.orca_bundle"
@@ -22860,7 +22758,6 @@ msgstr "Referência / Curva (plano / eixo / sist. coord. / hélice / projeção)
msgid "Reference plane (offset / tilt / midplane / tangent / two edges / coincident)"
msgstr "Plano de referência (deslocamento / inclinado / plano médio / tangente / duas arestas / coincidente)"
-# AI Translated
msgid "Axis"
msgstr "Eixo"
@@ -23606,17 +23503,14 @@ msgstr "Arestas"
msgid "Size (r/dist)"
msgstr "Tamanho (r/dist)"
-# AI Translated
msgctxt "Axis"
msgid "XY"
msgstr "XY"
-# AI Translated
msgctxt "Axis"
msgid "XZ"
msgstr "XZ"
-# AI Translated
msgctxt "Axis"
msgid "YZ"
msgstr "YZ"
@@ -24110,9 +24004,8 @@ msgstr "Expressão"
msgid "Field"
msgstr "Campo"
-# AI Translated
msgid "Expr"
-msgstr "Expr."
+msgstr "Expr"
# AI Translated
msgid "(no bindings)"
@@ -25118,11 +25011,9 @@ msgstr "Fixo"
msgid "Revolute"
msgstr "De revolução"
-# AI Translated
msgid "Slider"
-msgstr "Deslizante"
+msgstr "Controle Deslizante"
-# AI Translated
msgid "Cylindrical"
msgstr "Cilíndrico"
@@ -25301,89 +25192,68 @@ msgstr "recurso %d"
msgid "Deleted %s, the feature this body was made from — Ctrl+Z restores it"
msgstr "Recurso excluído: %s, aquele a partir do qual este corpo foi criado — Ctrl+Z o restaura"
-# AI Translated
msgid "Select the FEATURE that created this body (or use New Design)"
msgstr "Selecione o RECURSO que criou este corpo (ou use Novo design)"
-# AI Translated
msgid "Select a feature in the tree first"
-msgstr "Selecione primeiro um recurso na árvore"
+msgstr "Selecione um recurso na árvore primeiro"
-# AI Translated
#, c-format, boost-format
msgid "Body %d shown"
msgstr "Corpo %d exibido"
-# AI Translated
#, c-format, boost-format
msgid "Body %d hidden"
msgstr "Corpo %d oculto"
-# AI Translated
msgid "Feature shown"
msgstr "Recurso exibido"
-# AI Translated
msgid "Feature hidden"
msgstr "Recurso oculto"
-# AI Translated
msgid "Draw a sketch first, then Constrain"
-msgstr "Desenhe primeiro um esboço e depois use Restringir"
+msgstr "Desenhe um esboço primeiro e depois use Restringir"
-# AI Translated
msgid "Select a sketch in the tree first"
-msgstr "Selecione primeiro um esboço na árvore"
+msgstr "Selecione um esboço na árvore primeiro"
-# AI Translated
msgid "Selected feature is not a sketch"
msgstr "O recurso selecionado não é um esboço"
-# AI Translated
msgid "Pick 1-2 lines, then a constraint; right-click exits"
msgstr "Selecione 1-2 linhas e depois uma restrição; clique com o botão direito para sair"
-# AI Translated
msgid "Pick 1-2 entities, then a constraint or dimension; right-click exits"
msgstr "Selecione 1-2 entidades e depois uma restrição ou cota; clique com o botão direito para sair"
-# AI Translated
msgid "Pick an entity first"
-msgstr "Selecione primeiro uma entidade"
+msgstr "Selecione uma entidade primeiro"
-# AI Translated
msgid "Pick two entities first"
-msgstr "Selecione primeiro duas entidades"
+msgstr "Selecione duas entidades primeiro"
-# AI Translated
msgid "Horizontal and Vertical apply to a line"
msgstr "Horizontal e Vertical se aplicam a uma linha"
-# AI Translated
msgid "Angle applies between two lines"
msgstr "Ângulo se aplica entre duas linhas"
-# AI Translated
msgid "Collinear needs two lines"
msgstr "Colinear precisa de duas linhas"
-# AI Translated
msgid "Parallel, perpendicular and equal length apply to two lines"
msgstr "Paralelo, perpendicular e comprimento igual se aplicam a duas linhas"
-# AI Translated
msgid "Equal radius needs two circles or arcs"
-msgstr "Raio igual precisa de dois círculos ou arcos"
+msgstr "Mesmo raio precisa de dois círculos ou arcos"
-# AI Translated
msgid "Concentric needs two circles or arcs"
msgstr "Concêntrico precisa de dois círculos ou arcos"
-# AI Translated
msgid "Tangent needs a line and a circle/arc, or two circles/arcs"
msgstr "Tangente precisa de uma linha e um círculo/arco, ou de dois círculos/arcos"
-# AI Translated
msgid "This constraint needs two entities with a point to join"
msgstr "Esta restrição precisa de duas entidades com um ponto para unir"
@@ -25391,37 +25261,29 @@ msgstr "Esta restrição precisa de duas entidades com um ponto para unir"
msgid "This dimension needs two entities with a point to measure between"
msgstr "Esta cota precisa de duas entidades com pontos entre os quais medir"
-# AI Translated
msgid "Midpoint needs a point and a line"
msgstr "Ponto médio precisa de um ponto e uma linha"
-# AI Translated
msgid "Symmetric needs two points or two lines + an axis"
msgstr "Simétrico precisa de dois pontos ou duas linhas + um eixo"
-# AI Translated
msgid "Symmetric needs two points or two lines"
msgstr "Simétrico precisa de dois pontos ou duas linhas"
-# AI Translated
msgid "Symmetric: pick two entities, then an axis line"
msgstr "Simétrico: selecione duas entidades e depois uma linha de eixo"
-# AI Translated
msgid "Radius/Diameter needs a circle or arc"
msgstr "Raio/Diâmetro precisa de um círculo ou arco"
-# AI Translated
msgid "Unsupported constraint"
msgstr "Restrição não suportada"
-# AI Translated
msgid "Constraint rejected (over-constrained)"
-msgstr "Restrição rejeitada (esboço superrestrito)"
+msgstr "Restrição rejeitada (restrito demais)"
-# AI Translated
msgid "Applied constraint · its badge is on the sketch — click the badge to remove it"
-msgstr "Restrição aplicada · o ícone dela está no esboço — clique no ícone para removê-la"
+msgstr "Restrição aplicada · o distintivo dela está no esboço — clique no distintivo para removê-la"
# AI Translated
#, c-format, boost-format
@@ -25430,26 +25292,21 @@ msgid_plural "%s — %d selected. Press Esc for the Select tool, click one lin
msgstr[0] "%s — %d selecionado. Pressione Esc para a ferramenta Selecionar, clique em uma linha e depois Shift+clique ou Ctrl+clique na outra."
msgstr[1] "%s — %d selecionados. Pressione Esc para a ferramenta Selecionar, clique em uma linha e depois Shift+clique ou Ctrl+clique na outra."
-# AI Translated
msgid "Applied constraint"
msgstr "Restrição aplicada"
-# AI Translated
#. TRN Design sketch: abbreviation of "center", appended to a point tag such as "L3·Ctr"
msgid "·Ctr"
-msgstr "·Ctr"
+msgstr "·Cntr"
-# AI Translated
#, c-format, boost-format
msgid "Fix %s"
msgstr "Fixar %s"
-# AI Translated
#, c-format, boost-format
msgid "Lock X %s"
msgstr "Travar X %s"
-# AI Translated
#, c-format, boost-format
msgid "Lock Y %s"
msgstr "Travar Y %s"
@@ -25458,71 +25315,55 @@ msgctxt "Sketch Constraint"
msgid "Equal"
msgstr "Igual"
-# AI Translated
#, c-format, boost-format
msgid "Symmetric %s — %s / %s"
msgstr "Simétrico %s — %s / %s"
-# AI Translated
#, c-format, boost-format
msgid "Symmetric about Y axis %s — %s"
msgstr "Simétrico em relação ao eixo Y %s — %s"
-# AI Translated
#, c-format, boost-format
msgid "Symmetric about X axis %s — %s"
msgstr "Simétrico em relação ao eixo X %s — %s"
-# AI Translated
msgid "On line"
msgstr "Na linha"
-# AI Translated
msgid "On edge"
msgstr "Na aresta"
-# AI Translated
msgid "Constraint"
msgstr "Restrição"
-# AI Translated
#, c-format, boost-format
msgid "Constraints (%d)"
msgstr "Restrições (%d)"
-# AI Translated
msgid "No constraints yet"
msgstr "Nenhuma restrição ainda"
-# AI Translated
msgid "Delete constraint"
msgstr "Excluir restrição"
-# AI Translated
msgid "Constraint deleted"
msgstr "Restrição excluída"
-# AI Translated
msgid "Press Constrain on a sketch first"
msgstr "Pressione Restringir em um esboço primeiro"
-# AI Translated
msgid "Pick the entity, then a mirror-axis line"
msgstr "Selecione a entidade e depois uma linha de eixo de espelhamento"
-# AI Translated
msgid "Mirror axis must be a line"
msgstr "O eixo de espelhamento deve ser uma linha"
-# AI Translated
msgid "Mirror produced nothing"
msgstr "O espelhamento não produziu nada"
-# AI Translated
msgid "Offset distance (+left / -right of direction)"
msgstr "Distância de deslocamento (+esquerda / -direita da direção)"
-# AI Translated
msgid "Offset collapsed the entity"
msgstr "O deslocamento colapsou a entidade"
@@ -25542,19 +25383,15 @@ msgstr "Raio do filete"
msgid "Fillet failed (parallel lines or radius too large)"
msgstr "Falha no filete (linhas paralelas ou raio grande demais)"
-# AI Translated
msgid "Pick two lines to chamfer"
msgstr "Selecione duas linhas para o chanfro"
-# AI Translated
msgid "Chamfer needs two lines"
msgstr "O chanfro precisa de duas linhas"
-# AI Translated
msgid "Chamfer distance"
msgstr "Distância do chanfro"
-# AI Translated
msgid "Chamfer failed (parallel lines or distance too large)"
msgstr "Falha no chanfro (linhas paralelas ou distância grande demais)"
@@ -26048,30 +25885,24 @@ msgctxt "Design"
msgid "Loft"
msgstr "Loft"
-# AI Translated
msgctxt "Design"
msgid "Thicken"
msgstr "Espessar"
-# AI Translated
msgctxt "Design"
msgid "Join"
msgstr "Unir"
-# AI Translated
msgid "Fuse the tool body into the target — one solid, no seam"
-msgstr "Fundir o corpo da ferramenta ao alvo — um único sólido, sem emenda"
+msgstr "Fundir o corpo da ferramenta ao alvo — um único sólido, sem costura"
-# AI Translated
msgctxt "Design"
msgid "Subtract"
msgstr "Subtrair"
-# AI Translated
msgid "Cut the tool body out of the target"
msgstr "Recortar o corpo da ferramenta do alvo"
-# AI Translated
msgctxt "Design"
msgid "Intersect"
msgstr "Intersectar"
@@ -26802,10 +26633,10 @@ msgid "Horizontal slider - Move active thumb Right"
msgstr "Controle deslizante horizontal - Mover o polegar ativo para a direita"
msgid "Horizontal slider - Move to start position"
-msgstr "Barra deslizante horizontal — Mover para a posição inicial"
+msgstr "Controle deslizante horizontal — Mover para a posição inicial"
msgid "Horizontal slider - Move to last position"
-msgstr "Barra deslizante horizontal — Mover para a última posição"
+msgstr "Controle deslizante horizontal — Mover para a última posição"
msgid "Camera view - Default"
msgstr "Vista da câmera - Padrão"
@@ -28020,19 +27851,15 @@ msgstr "*Dicas: se você mudou a posição do carretel na máquina, feche esta p
msgid "Summary: This is currently the most suitable position for placement."
msgstr "Resumo: esta é atualmente a posição mais adequada para o posicionamento."
-# AI Translated
msgid "?"
msgstr "?"
-# AI Translated
msgid "Wiki->"
msgstr "Wiki->"
-# AI Translated
msgid "Note:"
-msgstr "Observação:"
+msgstr "Nota:"
-# AI Translated
msgctxt "Texture Displacement"
msgid "Bake"
msgstr "Assar"
@@ -28051,11 +27878,11 @@ msgstr "Pintar deslocamento de textura"
# AI Translated
msgid "Mark texture seam"
-msgstr "Marcar emenda da textura"
+msgstr "Marcar costura da textura"
# AI Translated
msgid "Mark texture seam path"
-msgstr "Marcar caminho de emenda da textura"
+msgstr "Marcar caminho de costura da textura"
# AI Translated
#, boost-format
@@ -28070,7 +27897,6 @@ msgstr "Escala média das ilhas"
msgid "Select an island in the UV editor first."
msgstr "Selecione primeiro uma ilha no editor UV."
-# AI Translated
msgid "Cut texture island"
msgstr "Cortar ilha da textura"
@@ -28078,31 +27904,24 @@ msgstr "Cortar ilha da textura"
msgid "This island has no neighbour it shares an edge with."
msgstr "Esta ilha não tem nenhuma vizinha com a qual compartilhe uma aresta."
-# AI Translated
msgid "Join texture island"
msgstr "Unir ilha da textura"
-# AI Translated
msgid "Unjoin texture island"
msgstr "Desunir ilha da textura"
-# AI Translated
msgid "Clear texture seams"
-msgstr "Limpar emendas da textura"
+msgstr "Limpar costuras da textura"
-# AI Translated
msgid "Clear texture UV edits"
msgstr "Limpar edições UV da textura"
-# AI Translated
msgid "Apply texture projection frame"
msgstr "Aplicar moldura de projeção da textura"
-# AI Translated
msgid "Move texture island"
msgstr "Mover ilha da textura"
-# AI Translated
msgid "Edit texture UV"
msgstr "Editar UV da textura"
@@ -28130,29 +27949,23 @@ msgstr "Imagens (*.png;*.jpg;*.jpeg;*.bmp)|*.png;*.jpg;*.jpeg;*.bmp"
msgid "Choose a texture image (height map)"
msgstr "Escolha uma imagem de textura (mapa de altura)"
-# AI Translated
msgid "Choose a texture"
msgstr "Escolha uma textura"
-# AI Translated
msgid "Remove from My textures"
msgstr "Remover de Minhas texturas"
-# AI Translated
msgid "Built-in"
msgstr "Integradas"
-# AI Translated
msgid "No textures found."
msgstr "Nenhuma textura encontrada."
-# AI Translated
msgid "My textures"
msgstr "Minhas texturas"
-# AI Translated
msgid "Import your own image as a height map. It is converted to the format the slicer bakes from and saved to your personal texture folder, kept separate from the textures shipped with OrcaSlicer."
-msgstr "Importe sua própria imagem como mapa de altura. Ela é convertida para o formato a partir do qual o fatiador assa e salva na sua pasta pessoal de texturas, separada das texturas fornecidas com o OrcaSlicer."
+msgstr "Importe sua própria imagem como mapa de altura. Ela é convertida para o formato a partir do qual o fatiador assa e salva na sua pasta pessoal de texturas, mantida separada das texturas fornecidas com o OrcaSlicer."
# AI Translated
msgid "PNG, JPG or BMP - converted to a height map on import. Hover one of yours to remove it."
@@ -28213,111 +28026,84 @@ msgstr "Pinte primeiro a área que deseja suavizar - a suavização só afeta a
msgid "Nothing to smooth - the painted area is only one triangle deep, so with \"Ignore outer ring\" on there are no interior vertices to relax."
msgstr "Nada a suavizar - a área pintada tem apenas um triângulo de profundidade, então, com \"Ignorar anel externo\" ativado, não há vértices internos para relaxar."
-# AI Translated
msgid "Smooth texture displacement"
msgstr "Suavizar deslocamento de textura"
-# AI Translated
msgid "Remesh model for texture displacement"
msgstr "Remalhar modelo para deslocamento de textura"
-# AI Translated
msgid "Remeshing did not change the model. It may be non-manifold (open edges or edges shared by more than two triangles), or the target edge length may already be met."
msgstr "O remalhamento não alterou o modelo. Ele pode ser não-manifold (arestas abertas ou arestas compartilhadas por mais de dois triângulos), ou o comprimento de aresta alvo pode já ter sido atingido."
-# AI Translated
msgid "Nothing is painted, there is nothing to bake."
msgstr "Nada está pintado, não há nada para assar."
-# AI Translated
msgid "Bake texture displacement"
msgstr "Assar deslocamento de textura"
-# AI Translated
msgid "Nothing is painted, so there are no bake stages to capture."
msgstr "Nada está pintado, então não há etapas de assamento para capturar."
-# AI Translated
msgid "Bake stages (debug)"
msgstr "Etapas do assamento (depuração)"
-# AI Translated
msgid "Capturing..."
msgstr "Capturando..."
-# AI Translated
msgid "Capture stages"
msgstr "Capturar etapas"
-# AI Translated
msgid "Run the same bake the Bake button runs, keeping the mesh after every stage, and step through them here. Nothing is committed to the model - this is for finding which stage a bad result came from."
msgstr "Executa o mesmo assamento que o botão Assar executa, mantendo a malha após cada etapa, e permite percorrê-las aqui. Nada é aplicado ao modelo - serve para descobrir de qual etapa veio um resultado ruim."
-# AI Translated
msgid "Check topology"
msgstr "Verificar topologia"
-# AI Translated
msgid "Count open and non-manifold edges after each stage, which is how a stage that tore the mesh is spotted. It scans every edge, so it adds noticeably to the capture on a fine bake."
msgstr "Conta as arestas abertas e não-manifold após cada etapa, que é como se identifica uma etapa que rasgou a malha. Analisa todas as arestas, então aumenta consideravelmente a captura em um assamento fino."
-# AI Translated
msgid "< Previous"
msgstr "< Anterior"
-# AI Translated
msgid "Next >"
msgstr "Próximo >"
-# AI Translated
msgid "triangles"
msgstr "triângulos"
-# AI Translated
msgid "vertices"
msgstr "vértices"
-# AI Translated
msgid "Open edges"
msgstr "Arestas abertas"
-# AI Translated
msgid "Non-manifold"
msgstr "Não-manifold"
-# AI Translated
msgid "Degenerate"
msgstr "Degenerados"
-# AI Translated
msgid "Write stage meshes"
msgstr "Gravar malhas das etapas"
-# AI Translated
msgid "Wrote the stage meshes as OBJ files to:"
msgstr "As malhas das etapas foram gravadas como arquivos OBJ em:"
-# AI Translated
msgid "Could not write the stage meshes."
msgstr "Não foi possível gravar as malhas das etapas."
-# AI Translated
msgid "Write every captured stage out as an OBJ file, so they can be opened side by side in a mesh viewer."
msgstr "Grava cada etapa capturada como um arquivo OBJ, para que possam ser abertas lado a lado em um visualizador de malhas."
-# AI Translated
msgid "The painted area could not be carried onto the remeshed model, so nothing was changed. Switch to Pro mode and remesh before painting."
msgstr "A área pintada não pôde ser transferida para o modelo remalhado, então nada foi alterado. Mude para o modo Pro e remalhe antes de pintar."
-# AI Translated
msgid "Pro"
msgstr "Pro"
-# AI Translated
msgid "Standard - pick a texture, paint where it goes, press Bake. Everything the mesh needs is done for you in that one step."
msgstr "Padrão - escolha uma textura, pinte onde ela vai e pressione Assar. Tudo o que a malha precisa é feito por você nessa única etapa."
-# AI Translated
msgid "Pro - the mesh preparation is yours to run: Remesh, Subdivide and Bake as separate steps, with every setting on show. For when Standard's result is not what you wanted and you know why."
msgstr "Pro - a preparação da malha fica por sua conta: Remalhar, Subdividir e Assar como etapas separadas, com todas as configurações à mostra. Para quando o resultado do Padrão não é o que você queria e você sabe por quê."
@@ -28358,7 +28144,6 @@ msgstr "Pincel - pinte sobre a superfície arrastando"
msgid "Face - click individual triangles"
msgstr "Face - clique em triângulos individuais"
-# AI Translated
msgid "Connected area"
msgstr "Área conectada"
@@ -28366,7 +28151,6 @@ msgstr "Área conectada"
msgid "Connected area - flood-fill the region reachable without crossing an edge sharper than the angle threshold"
msgstr "Área conectada - preenche a região alcançável sem cruzar uma aresta mais acentuada que o limiar de ângulo"
-# AI Translated
msgid "Wait for the bake to finish."
msgstr "Aguarde o assamento terminar."
@@ -28410,14 +28194,12 @@ msgstr "Esfera - pinta apenas dentro de uma esfera ao redor do ponto sob o curso
msgid "Angle threshold - the fill stops at edges sharper than this"
msgstr "Limiar de ângulo - o preenchimento para em arestas mais acentuadas que isto"
-# AI Translated
msgid "Click a triangle to paint it"
msgstr "Clique em um triângulo para pintá-lo"
msgid "Only for a layer mapped with Unwrap (LSCM) - set the active layer's Mapping to Unwrap to use this view."
msgstr ""
-# AI Translated
msgid "Normal - the real geometry, exactly what Bake will produce. Slower to update"
msgstr "Normal - a geometria real, exatamente o que Assar vai produzir. Atualiza mais devagar"
@@ -28425,14 +28207,12 @@ msgstr "Normal - a geometria real, exatamente o que Assar vai produzir. Atualiza
msgid "Fast - the relief is only shaded on, not built, and only for the layer you are editing. Updates instantly while you paint"
msgstr "Rápido - o relevo é apenas sombreado, não construído, e só para a camada que você está editando. Atualiza instantaneamente enquanto você pinta"
-# AI Translated
msgid "Checker"
msgstr "Xadrez"
msgid "Checker - a test grid instead of the texture. Where the squares stay square the texture is undistorted; where they stretch, it will too. Opens the UV editor if it is closed"
msgstr ""
-# AI Translated
msgid "Distortion"
msgstr "Distorção"
@@ -28447,7 +28227,6 @@ msgstr "Malha - sobrepõe as arestas da malha; independente da vista acima"
msgid "Rebuilds the preview as soon as anything changes. Turn it off on a heavy model if painting or dragging a slider starts to stutter - the preview then waits until you let go."
msgstr "Reconstrói a pré-visualização assim que algo muda. Desative em um modelo pesado se pintar ou arrastar um controle deslizante começar a travar - a pré-visualização então espera até você soltar."
-# AI Translated
msgid "Texture layers"
msgstr "Camadas de textura"
@@ -28559,37 +28338,31 @@ msgstr ""
msgid "The most mixed filaments a bake may add. They are picked from the texture's colors, and only the ones the bake actually uses are created."
msgstr ""
-# AI Translated
#, boost-format
msgid "%1% printable colors from %2% filaments"
msgstr "%1% cores imprimíveis a partir de %2% filamentos"
-# AI Translated
msgid "Denoise"
-msgstr "Reduzir ruído"
+msgstr "Reduzir Ruído"
# AI Translated
msgid "Cleans up single stray triangles of the wrong color, which detail finer than the mesh leaves behind. Raise it if the result looks speckled, lower it if small features are being swallowed."
msgstr "Remove triângulos isolados com a cor errada, deixados por detalhes mais finos que a malha. Aumente se o resultado parecer salpicado; diminua se pequenos detalhes estiverem sendo engolidos."
-# AI Translated
msgctxt "Texture Displacement"
msgid "Mapping"
msgstr "Mapeamento"
-# AI Translated
msgid "Triplanar (blended)"
msgstr "Triplanar (mesclado)"
-# AI Translated
msgid "Triplanar - projects the texture from all three axes at once and blends between them, so a patch wrapping around a sharp edge has no seam."
-msgstr "Triplanar - projeta a textura a partir dos três eixos ao mesmo tempo e mescla entre eles, de modo que uma área que envolve uma aresta viva não tenha emenda."
+msgstr "Triplanar - projeta a textura a partir dos três eixos ao mesmo tempo e mescla entre eles, de modo que uma área que envolve uma aresta viva não tenha costura."
# AI Translated
msgid "Cylindrical - wraps the texture around the painted area's own center, for round shapes."
msgstr "Cilíndrico - envolve a textura ao redor do próprio centro da área pintada, para formas redondas."
-# AI Translated
msgid "Spherical"
msgstr "Esférico"
@@ -28597,15 +28370,12 @@ msgstr "Esférico"
msgid "Spherical - wraps the texture around the painted area's own center in both directions."
msgstr "Esférico - envolve a textura ao redor do próprio centro da área pintada, nas duas direções."
-# AI Translated
msgid "Unwrap (LSCM)"
msgstr "Desdobrar (LSCM)"
-# AI Translated
msgid "Unwrap - flattens the painted area and maps the texture onto it with as little stretching as possible. The area is cut into pieces at its sharp edges first (see Seam angle), so each piece can lie flat on its own."
-msgstr "Desdobrar - achata a área pintada e mapeia a textura sobre ela com o mínimo de estiramento possível. Primeiro a área é cortada em pedaços nas suas arestas vivas (veja Ângulo de emenda), para que cada pedaço possa ficar plano por conta própria."
+msgstr "Desdobrar - achata a área pintada e mapeia a textura sobre ela com o mínimo de estiramento possível. Primeiro a área é cortada em pedaços nas suas arestas vivas (veja Ângulo de costura), para que cada pedaço possa ficar plano por conta própria."
-# AI Translated
msgid "From view"
msgstr "Da vista"
@@ -28613,13 +28383,12 @@ msgstr "Da vista"
msgid "From view - projects straight onto the painted area from where you are looking, like a slide projector."
msgstr "Da vista - projeta diretamente sobre a área pintada a partir de onde você está olhando, como um projetor de slides."
-# AI Translated
msgid "Open UV editor"
msgstr "Abrir editor UV"
# AI Translated
msgid "Opens the UV editor, where you can see how the texture is laid out over the painted area, cut seams and move the pieces around."
-msgstr "Abre o editor UV, onde você vê como a textura está distribuída sobre a área pintada, corta emendas e move os pedaços."
+msgstr "Abre o editor UV, onde você vê como a textura está distribuída sobre a área pintada, corta costuras e move os pedaços."
# AI Translated
msgid "Not unwrapped yet"
@@ -28786,9 +28555,8 @@ msgstr "Seguir detalhes da textura"
msgid "Spends the triangles where the texture actually bends - packed along ridges and edges, sparse over flat ground - instead of spreading them evenly. The same detail for fewer triangles on most textures."
msgstr "Gasta os triângulos onde a textura realmente se curva - concentrados ao longo de cristas e arestas, esparsos em áreas planas - em vez de distribuí-los uniformemente. O mesmo detalhe com menos triângulos na maioria das texturas."
-# AI Translated
msgid "Max edge"
-msgstr "Aresta máx."
+msgstr "Aresta máx"
# AI Translated
msgid "Target edge"
@@ -28810,9 +28578,8 @@ msgstr "Detalhe"
msgid "How far the mesh may sit from the shape the texture describes, in millimetres. Smaller follows fine detail and costs triangles; larger only chases the big features."
msgstr "Quanto a malha pode se afastar da forma descrita pela textura, em milímetros. Menor segue detalhes finos e custa triângulos; maior só acompanha as formas grandes."
-# AI Translated
msgid "Min edge"
-msgstr "Aresta mín."
+msgstr "Aresta mín"
# AI Translated
msgid "A floor on triangle size, so a sharp step in the texture cannot be chased forever. Lower it for finer relief, raise it if the count runs away at hard edges."
@@ -28863,19 +28630,15 @@ msgstr "Pré-visualizar subdivisão"
msgid "Shows what the refinement would produce as a wireframe, without touching the model."
msgstr "Mostra o que o refinamento produziria como malha, sem alterar o modelo."
-# AI Translated
msgid "Subdivide"
msgstr "Subdividir"
-# AI Translated
msgid "Refines the painted area to the target edge length and carries your paint onto the finer mesh. The rest of the model is left as it is."
msgstr "Refina a área pintada até o comprimento de aresta alvo e transfere sua pintura para a malha mais fina. O restante do modelo fica como está."
-# AI Translated
msgid "Replaces the model's geometry with the subdivided mesh and clears any not-yet-baked paint on it (already-baked relief is unaffected)."
msgstr "Substitui a geometria do modelo pela malha subdividida e limpa qualquer pintura ainda não assada nela (o relevo já assado não é afetado)."
-# AI Translated
msgid "Remeshing"
msgstr "Remalhamento"
@@ -28883,23 +28646,18 @@ msgstr "Remalhamento"
msgid "Triangle size the whole model is rebuilt with, in millimetres. Displacement works best on an even mesh; this is what makes one out of an uneven import."
msgstr "Tamanho dos triângulos com que o modelo inteiro é reconstruído, em milímetros. O deslocamento funciona melhor em uma malha uniforme; isto cria uma a partir de uma importação irregular."
-# AI Translated
msgid "Keep sharp edges"
msgstr "Manter arestas vivas"
-# AI Translated
msgid "Holds hard edges and open borders in place while the rest is remeshed. Without it the remesher slides vertices along the surface and rounds every crisp edge off - a cube comes back with wobbly edges."
-msgstr "Mantém arestas vivas e bordas abertas no lugar enquanto o restante é remalhado. Sem isso, o remalhador desliza os vértices ao longo da superfície e arredonda toda aresta nítida - um cubo volta com arestas onduladas."
+msgstr "Mantém arestas vivas e bordas abertas fixas enquanto o restante remalhado. Sem isso, o remalhador desliza os vértices ao longo da superfície e arredonda todas as arestas nítidas - um cubo voltaria com arestas onduladas."
-# AI Translated
msgid "How sharp a fold has to be, in degrees, before the remesher treats it as an edge worth keeping. Lower protects more of the model's shape; higher rebuilds more of it evenly."
-msgstr "Quão acentuada uma dobra precisa ser, em graus, para que o remalhador a trate como uma aresta a ser mantida. Menor protege mais da forma do modelo; maior reconstrói mais dele de forma uniforme."
+msgstr "Quão acentuada uma dobra precisa ser, em graus, para que o remalhador a trate como uma aresta a ser mantida. Menor protege mais da forma do modelo; maior reconstrói mais dele uniformemente."
-# AI Translated
msgid "Remesh"
msgstr "Remalhar"
-# AI Translated
msgid "Rebuilds the whole model with triangles close to this edge length - splitting the big ones and merging the small ones - so displacement has an even density to work with. Replaces the geometry; your paint is carried onto the new triangles spatially, so it survives (already-baked relief is kept too)."
msgstr "Reconstrói o modelo inteiro com triângulos próximos deste comprimento de aresta - dividindo os grandes e mesclando os pequenos - para que o deslocamento tenha uma densidade uniforme para trabalhar. Substitui a geometria; sua pintura é transferida espacialmente para os novos triângulos, então ela sobrevive (o relevo já assado também é mantido)."
@@ -28944,19 +28702,15 @@ msgstr "Ignorar anel externo"
msgid "Keeps the outer ring of the painted area out of the smoothing. Its neighbours outside the paint never move, so smoothing it drags the relief down and leaves the pattern half-melted at the border."
msgstr "Mantém o anel externo da área pintada fora da suavização. Seus vizinhos fora da pintura nunca se movem, então suavizá-lo puxa o relevo para baixo e deixa o padrão meio derretido na borda."
-# AI Translated
msgid "Smooth baked mesh now"
msgstr "Suavizar malha assada agora"
-# AI Translated
msgid "Applies the smoothing above to the model itself, right now, within the painted area. For relief that is already baked in - anything not yet baked is smoothed by Bake."
msgstr "Aplica a suavização acima ao próprio modelo, agora mesmo, dentro da área pintada. Para relevo que já foi assado - o que ainda não foi assado é suavizado por Assar."
-# AI Translated
msgid "Experimental: classic bake pipeline"
msgstr "Experimental: pipeline de assamento clássico"
-# AI Translated
msgid "Bake by moving the vertices the mesh already has, after preparing it (remesh, adaptive subdivision, and a cut along sharp steps in the texture). Keeps the topology, which is what colors need. The default pipeline instead refines, cleans up sliver triangles, displaces and simplifies in one run; nothing needs preparing first, but it does not produce colors yet."
msgstr "Assa movendo os vértices que a malha já tem, depois de prepará-la (remalhamento, subdivisão adaptativa e um corte ao longo dos degraus bruscos da textura). Mantém a topologia, que é o que as cores precisam. O pipeline padrão, em vez disso, refina, limpa triângulos estreitos, desloca e simplifica de uma só vez; nada precisa ser preparado antes, mas ainda não produz cores."
@@ -28970,9 +28724,8 @@ msgstr "Orçamento"
msgid "%d k (auto)"
msgstr "%d k (automático)"
-# AI Translated
msgid "How many thousand triangles this bake may spend on the area you painted. Relief already baked into the rest of the model is kept on top of it, so a second bake somewhere else gets the same budget as the first. Raise it if the warning below Resolution says the detail will not fit; 0 keeps every triangle the refinement produced, however many that is."
-msgstr "Quantos milhares de triângulos este assamento pode gastar na área que você pintou. O relevo já assado no restante do modelo é mantido além disso, então um segundo assamento em outro lugar recebe o mesmo orçamento que o primeiro. Aumente se o aviso abaixo de Resolução disser que o detalhe não cabe; 0 mantém todos os triângulos que o refinamento produziu, quantos forem."
+msgstr "Quantos milhares de triângulos este assamento pode gastar na área que você pintou. O relevo já assado no restante do modelo é mantido além disso, então um segundo assamento em outro lugar recebe o mesmo orçamento que o primeiro. Aumente se o aviso abaixo de Resolução disser que o detalhe não cabe; 0 preserva todos os triângulos produzidos pelo refinamento, independentemente de quantos sejam."
# AI Translated
msgid "Align mesh to texture edges"
@@ -29004,16 +28757,13 @@ msgstr "%.2f mm (automático)"
msgid "Chosen from the size of the model: %1$.2f mm triangles, budget %2% k. Untick Auto to set them yourself."
msgstr "Escolhido pelo tamanho do modelo: triângulos de %1$.2f mm, orçamento de %2% k. Desmarque Auto para defini-los você mesmo."
-# AI Translated
msgid "How fine the mesh is made under the paint, in millimetres. It has to be smaller than the detail you want out of the texture - a 0.5 mm groove needs triangles well under 0.5 mm. Smaller costs triangles fast: halving it needs four times as many, and once they no longer fit the budget the bake simplifies back down and the detail goes with it."
-msgstr "Quão fina a malha fica sob a pintura, em milímetros. Precisa ser menor que o detalhe que você quer tirar da textura - um sulco de 0,5 mm precisa de triângulos bem abaixo de 0,5 mm. Menor custa triângulos rapidamente: reduzir pela metade exige quatro vezes mais, e quando eles não cabem mais no orçamento, o assamento simplifica de volta e o detalhe vai junto."
+msgstr "Quão fina a malha fica sob a pintura, em milímetros. Precisa ser menor que o detalhe que você quer tirar da textura - um sulco de 0,5 mm precisa de triângulos bem abaixo de 0,5 mm. Menor custa triângulos rapidamente: reduzir pela metade exige quatro vezes mais e quando eles não cabem mais no orçamento o assamento simplifica de volta e o detalhe vai junto."
-# AI Translated
#, boost-format
msgid "Needs about %1% triangles, budget %2% - the bake will simplify back down and lose detail."
msgstr "Precisa de cerca de %1% triângulos, orçamento de %2% - o assamento vai simplificar de volta e perder detalhes."
-# AI Translated
msgid "How many thousand triangles the refinement may add to the model. The triangle that fits worst is always split first, so even a run that spends the lot has spent it where it shows most. Raise it if the relief still looks coarse."
msgstr "Quantos milhares de triângulos o refinamento pode adicionar ao modelo. O triângulo que se ajusta pior é sempre dividido primeiro, então mesmo uma execução que gaste tudo terá gasto onde mais aparece. Aumente se o relevo ainda parecer grosseiro."
@@ -29021,25 +28771,20 @@ msgstr "Quantos milhares de triângulos o refinamento pode adicionar ao modelo.
msgid "Preparing..."
msgstr "Preparando..."
-# AI Translated
msgid "Baking..."
msgstr "Assando..."
-# AI Translated
msgid "Nothing is painted yet. The UV editor's seam tool is on, so strokes on the model mark seams instead of painting - turn it off in the pane to paint."
-msgstr "Nada foi pintado ainda. A ferramenta de emenda do editor UV está ativa, então os traços no modelo marcam emendas em vez de pintar - desative-a no painel para pintar."
+msgstr "Nada foi pintado ainda. A ferramenta de costura do editor UV está ativa, então os traços no modelo marcam costuras em vez de pintar - desative-a no painel para pintar."
-# AI Translated
msgid "Nothing is painted yet."
msgstr "Nada foi pintado ainda."
-# AI Translated
msgid "Turn the painted height maps into real geometry, by moving the vertices that are already there. Use Subdivide first if the mesh is too coarse to show the detail."
msgstr "Transforma os mapas de altura pintados em geometria real, movendo os vértices que já existem. Use Subdividir antes se a malha for grosseira demais para mostrar o detalhe."
-# AI Translated
msgid "Turn the painted height maps into real geometry. The mesh is remeshed to an even density and refined where the texture bends first, so the detail has vertices to land on - all in one step."
-msgstr "Transforma os mapas de altura pintados em geometria real. Primeiro a malha é remalhada para uma densidade uniforme e refinada onde a textura se curva, para que o detalhe tenha vértices onde cair - tudo em uma etapa."
+msgstr "Transforma os mapas de altura pintados em geometria real. A malha é remalhada para uma densidade uniforme e refinada onde a textura se curva primeiro, para que o detalhe tenha vértices onde cair - tudo em uma etapa."
# AI Translated
msgid "Stops the bake. Whatever it had already finished stays on the model, and can be undone."
@@ -29049,22 +28794,18 @@ msgstr "Interrompe o assamento. O que já tiver sido concluído permanece no mod
msgid "Closes the tool without baking. Your paint, layers and settings stay with the model."
msgstr "Fecha a ferramenta sem assar. Sua pintura, camadas e configurações permanecem com o modelo."
-# AI Translated
#, boost-format
msgid "%1% k"
msgstr "%1% k"
-# AI Translated
#, boost-format
msgid "Model: %1% triangles - the bake refines to the resolution above, up to its budget"
msgstr "Modelo: %1% triângulos - o assamento refina até a resolução acima, dentro do seu orçamento"
-# AI Translated
#, boost-format
msgid "Bake moves existing vertices - the model stays at %1% triangles"
msgstr "Assar move os vértices existentes - o modelo continua com %1% triângulos"
-# AI Translated
#, boost-format
msgid "Bake result up to ~%1% k triangles"
msgstr "Resultado do assamento até ~%1% k triângulos"
@@ -29091,43 +28832,33 @@ msgstr "Saindo da pintura de deslocamento de textura"
msgid "Texture displacement editing"
msgstr "Edição de deslocamento de textura"
-# AI Translated
msgid "Choose SLA archive:"
msgstr "Escolha o arquivo SLA:"
-# AI Translated
msgid "Import file"
msgstr "Importar arquivo"
-# AI Translated
msgid "Import model and profile"
msgstr "Importar modelo e perfil"
-# AI Translated
msgid "Import profile only"
msgstr "Importar apenas o perfil"
-# AI Translated
msgid "Import model only"
msgstr "Importar apenas o modelo"
-# AI Translated
msgid "Accurate"
msgstr "Precisa"
-# AI Translated
msgid "Balanced"
msgstr "Equilibrada"
-# AI Translated
msgid "Quick"
msgstr "Rápida"
-# AI Translated
msgid "Baking texture displacement"
msgstr "Assando deslocamento de textura"
-# AI Translated
msgid "The bake produced no displacement, so nothing was changed and the paint was kept. Check that the painted layer has a texture and a non-zero depth."
msgstr "O assamento não produziu deslocamento, então nada foi alterado e a pintura foi mantida. Verifique se a camada pintada tem uma textura e uma profundidade diferente de zero."
@@ -29136,7 +28867,6 @@ msgstr "O assamento não produziu deslocamento, então nada foi alterado e a pin
msgid "The triangle budget limited the detail: this resolution needs %1% triangles, the budget kept %2%. Raise Budget or use a coarser Resolution for the full detail."
msgstr "O orçamento de triângulos limitou o detalhe: esta resolução precisa de %1% triângulos, o orçamento manteve %2%. Aumente Orçamento ou use uma Resolução mais grosseira para obter o detalhe completo."
-# AI Translated
msgid "Capturing bake stages"
msgstr "Capturando etapas do assamento"
@@ -30169,7 +29899,7 @@ msgstr "Desdobrar"
# AI Translated
msgid "Seam angle"
-msgstr "Ângulo de emenda"
+msgstr "Ângulo de costura"
# AI Translated
msgid "Edges sharper than this are cut, and the pieces either side of them are flattened separately. Lower it to cut more: each piece then lies flat with less stretching, at the cost of the texture not running continuously across the cut. Takes effect at the next Unwrap."
@@ -30194,15 +29924,13 @@ msgstr ""
# AI Translated
msgid "Mark seams - click edges on the model to cut the unwrap along them. The edge under the cursor is highlighted yellow; click to mark it red, click a red edge again to unmark it. Painting is paused while this is on."
-msgstr "Marcar emendas - clique em arestas no modelo para cortar o desdobramento ao longo delas. A aresta sob o cursor fica destacada em amarelo; clique para marcá-la em vermelho, clique novamente em uma aresta vermelha para desmarcá-la. A pintura fica pausada enquanto isto estiver ativo."
+msgstr "Marcar costuras - clique em arestas no modelo para cortar o desdobramento ao longo delas. A aresta sob o cursor fica destacada em amarelo; clique para marcá-la em vermelho, clique novamente em uma aresta vermelha para desmarcá-la. A pintura fica pausada enquanto isto estiver ativo."
-# AI Translated
msgid "Path - instead of clicking every edge, click a start point and then an end point: the whole shortest path between them is seamed at once. Available while marking seams."
-msgstr "Caminho - em vez de clicar em cada aresta, clique em um ponto inicial e depois em um ponto final: todo o caminho mais curto entre eles recebe a emenda de uma vez. Disponível ao marcar emendas."
+msgstr "Caminho - em vez de clicar em cada aresta, clique em um ponto inicial e depois em um ponto final: todo o caminho mais curto entre eles recebe a costura de uma vez. Disponível ao marcar costuras."
-# AI Translated
msgid "Clear seams - remove every seam marked on this layer"
-msgstr "Limpar emendas - remove todas as emendas marcadas nesta camada"
+msgstr "Limpar costuras - remove todas as costuras marcadas nesta camada"
# AI Translated
msgid "Average scale - give every island the same texel density"
@@ -30236,11 +29964,9 @@ msgstr ""
msgid "What is selected, and the exact figures of the move, rotation or scale while you drag one."
msgstr ""
-# AI Translated
msgid "No layer mapped with Unwrap"
msgstr "Nenhuma camada mapeada com Desdobrar"
-# AI Translated
#, c-format, boost-format
msgid "%.1f mm tile"
msgstr "ladrilho de %.1f mm"
@@ -30250,11 +29976,10 @@ msgstr ""
# AI Translated
msgid "Out of date - the paint, the seams or the seam angle changed since this unwrap was made. Press to unwrap again."
-msgstr "Desatualizado - a pintura, as emendas ou o ângulo de emenda mudaram desde que este desdobramento foi feito. Pressione para desdobrar novamente."
+msgstr "Desatualizado - a pintura, as costuras ou o ângulo de costura mudaram desde que este desdobramento foi feito. Pressione para desdobrar novamente."
-# AI Translated
msgid "Flatten the painted area into UV islands. It is computed only when you press this, not on every edit - so paint, change the seam angle or mark seams first, then press Unwrap."
-msgstr "Achata a área pintada em ilhas UV. Só é calculado quando você pressiona isto, não a cada edição - então pinte, altere o ângulo de emenda ou marque emendas primeiro e depois pressione Desdobrar."
+msgstr "Achata a área pintada em ilhas UV. Só é calculado quando você pressiona isso, não a cada edição - então pinte, altere o ângulo de costura ou marque costuras primeiro e depois pressione Desdobrar."
msgid "Turn Mark seams on first - Path is a quicker way of marking them."
msgstr ""
@@ -30685,7 +30410,6 @@ msgstr ""
"O plugin de pós-processamento %1% falhou.\n"
"Erro: %2%"
-# AI Translated
#, boost-format
msgid ""
"Post-processing plugin %1% failed.\n"
@@ -30695,19 +30419,16 @@ msgid ""
msgstr ""
"O plugin de pós-processamento %1% falhou.\n"
"\n"
-"Espera-se que o plugin de pós-processamento modifique o arquivo G-code %2% no próprio local, mas o arquivo G-code foi excluído.\n"
+"É esperado que o plugin de pós-processamento modifique o arquivo G-code %2% diretamente, mas o arquivo G-code foi excluído.\n"
"Verifique a implementação do plugin.\n"
-# AI Translated
#, boost-format
msgid "Failed making a temporary copy of G-code file %1% before running a post-processing script: %2%"
msgstr "Falha ao criar uma cópia temporária do arquivo G-code %1% antes de executar um script de pós-processamento: %2%"
-# AI Translated
msgid "Post-processor can't find exported gcode file"
msgstr "O pós-processador não consegue encontrar o arquivo G-code exportado"
-# AI Translated
#, boost-format
msgid ""
"Post-processing script %1% on file %2% failed.\n"
@@ -30716,7 +30437,6 @@ msgstr ""
"O script de pós-processamento %1% no arquivo %2% falhou.\n"
"Código de erro: %3%"
-# AI Translated
#, boost-format
msgid ""
"Post-processing script %1% on file %2% failed.\n"
@@ -30729,7 +30449,6 @@ msgstr ""
"Saída:\n"
"%4%"
-# AI Translated
#, boost-format
msgid ""
"Post-processing script %1% failed.\n"
@@ -30739,36 +30458,29 @@ msgid ""
msgstr ""
"O script de pós-processamento %1% falhou.\n"
"\n"
-"Espera-se que o script de pós-processamento altere o arquivo G-code %2% no próprio local, mas o arquivo G-code foi excluído e provavelmente salvo com um novo nome.\n"
-"Ajuste o script de pós-processamento para alterar o G-code no próprio local e consulte o manual para saber como, opcionalmente, renomear o arquivo G-code pós-processado.\n"
+"Espera-se que o script de pós-processamento altere o arquivo G-code %2% diretamente, mas o arquivo G-code foi excluído e provavelmente salvo com um novo nome.\n"
+"Ajuste o script de pós-processamento para alterar o G-code diretamente e consulte o manual para saber como renomear opcionalmente o arquivo G-code pós-processado.\n"
-# AI Translated
msgid "Unable to parse desired new path from output name file"
msgstr "Não foi possível analisar o novo caminho desejado a partir do arquivo de nome de saída"
-# AI Translated
#, boost-format
msgid "Output directory does not exist: %1%"
msgstr "O diretório de saída não existe: %1%"
-# AI Translated
#, boost-format
msgid "Failed reading a file %1% carrying the final name / path of a G-code file: %2%"
-msgstr "Falha ao ler o arquivo %1% que contém o nome / caminho final de um arquivo G-code: %2%"
+msgstr "Falha ao ler o arquivo %1% que contém o nome/caminho final de um arquivo G-code: %2%"
-# AI Translated
msgid "The printing task exceeds the limit, supporting a maximum of 6 printers."
-msgstr "A tarefa de impressão excede o limite; são suportadas no máximo 6 impressoras."
+msgstr "A tarefa de impressão excede o limite, são suportadas no máximo 6 impressoras."
-# AI Translated
msgid "Elapsed time:"
msgstr "Tempo decorrido:"
-# AI Translated
msgid "Estimated time:"
msgstr "Tempo estimado:"
-# AI Translated
msgid "Remaining time:"
msgstr "Tempo restante:"
@@ -30982,8 +30694,7 @@ msgstr ""
"Divida suas impressões em placas\n"
"Você sabia que pode dividir um modelo que tem diversas peças em placas individuais distintas prontas para imprimir? Isso simplifica o processo de manter o controle de todas as peças."
-#: resources/data/hints.ini: [hint:Speed up your print with Adaptive Layer
-#: Height]
+#: resources/data/hints.ini: [hint:Speed up your print with Adaptive Layer Height]
msgid ""
"Speed up your print with Adaptive Layer Height\n"
"Did you know that you can print a model even faster by using the Adaptive Layer Height option? Check it out!"
@@ -31055,8 +30766,7 @@ msgstr ""
"Melhorar a resistência\n"
"Você sabia que pode usar mais voltas de parede e maior densidade de preenchimento esparso mais alta para melhorar a resistência do modelo?"
-#: resources/data/hints.ini: [hint:When do you need to print with the printer
-#: door opened]
+#: resources/data/hints.ini: [hint:When do you need to print with the printer door opened]
msgid ""
"When do you need to print with the printer door opened?\n"
"Did you know that opening the printer door can reduce the probability of extruder/hotend clogging when printing lower temperature filament with a higher enclosure temperature? There is more info about this in the Wiki."
@@ -31104,10 +30814,6 @@ msgstr ""
#~ msgid "The 3MF was created by BambuStudio. Some settings may differ from OrcaSlicer."
#~ msgstr "O arquivo 3MF foi criado pelo Bambu Studio. Algumas configurações podem ser diferentes do OrcaSlicer."
-# AI Translated
-#~ msgid "Cannot undo or redo while an operation is running. Stop it first."
-#~ msgstr "Não é possível desfazer ou refazer enquanto uma operação está em andamento. Interrompa-a primeiro."
-
#, c-format, boost-format
#~ msgid "%s: %s"
#~ msgstr "%s: %s"
@@ -31129,340 +30835,9 @@ msgstr ""
#~ msgid "Video tutorial"
#~ msgstr "Tutorial em vídeo"
-# AI Translated
-#~ msgid "Primitive"
-#~ msgstr "Primitivo"
-
-# AI Translated
-#~ msgid "Empty mesh generated"
-#~ msgstr "Malha vazia gerada"
-
-# AI Translated
-#~ msgid "Box"
-#~ msgstr "Caixa"
-
-# AI Translated
-#~ msgid "Quick:"
-#~ msgstr "Rápido:"
-
-# AI Translated
-#~ msgid "Width (X)"
-#~ msgstr "Largura (X)"
-
-# AI Translated
-#~ msgid "Depth (Y)"
-#~ msgstr "Profundidade (Y)"
-
-# AI Translated
-#~ msgid "Height (Z)"
-#~ msgstr "Altura (Z)"
-
-# AI Translated
-#~ msgid "Bottom R"
-#~ msgstr "R inferior"
-
-# AI Translated
-#~ msgid "Top R"
-#~ msgstr "R superior"
-
-# AI Translated
-#~ msgid "Major R"
-#~ msgstr "R maior"
-
-# AI Translated
-#~ msgid "Minor R"
-#~ msgstr "R menor"
-
-# AI Translated
-#~ msgid "All edges"
-#~ msgstr "Todas as arestas"
-
-# AI Translated
-#~ msgid "Top edges"
-#~ msgstr "Arestas superiores"
-
-# AI Translated
-#~ msgid "Bottom edges"
-#~ msgstr "Arestas inferiores"
-
-# AI Translated
-#~ msgid "Lateral edges"
-#~ msgstr "Arestas laterais"
-
-# AI Translated
-#~ msgid "Mesh resolution"
-#~ msgstr "Resolução da malha"
-
-# AI Translated
-#~ msgid "Add Shape"
-#~ msgstr "Adicionar forma"
-
-# AI Translated
-#~ msgid "No outer profile"
-#~ msgstr "Nenhum perfil externo"
-
-# AI Translated
-#~ msgid "Failed to make outer face"
-#~ msgstr "Falha ao criar a face externa"
-
-# AI Translated
-#~ msgid "Failed to build face with holes"
-#~ msgstr "Falha ao construir a face com furos"
-
-# AI Translated
-#~ msgid "Revolve failed"
-#~ msgstr "Falha na revolução"
-
-# AI Translated
-#~ msgid "Profile"
-#~ msgstr "Perfil"
-
-# AI Translated
-#~ msgid "Start new profile (for holes)"
-#~ msgstr "Iniciar novo perfil (para furos)"
-
-# AI Translated
-#~ msgid "Segments"
-#~ msgstr "Segmentos"
-
-# AI Translated
-#~ msgid "Sides"
-#~ msgstr "Lados"
-
-# AI Translated
-#~ msgid "Click on canvas to draw"
-#~ msgstr "Clique na tela para desenhar"
-
-# AI Translated
-#~ msgid "Snap to grid"
-#~ msgstr "Ajustar à grade"
-
-# AI Translated
-#~ msgid "Grid step"
-#~ msgstr "Passo da grade"
-
-# AI Translated
-#~ msgid "Outer"
-#~ msgstr "Externo"
-
-# AI Translated
-#~ msgid "closed"
-#~ msgstr "fechado"
-
-# AI Translated
-#, boost-format
-#~ msgid "%1% %2%: %3% points %4%"
-#~ msgstr "%1% %2%: %3% pontos %4%"
-
-# AI Translated
-#~ msgid "XY (Top)"
-#~ msgstr "XY (Topo)"
-
-# AI Translated
-#~ msgid "XZ (Front)"
-#~ msgstr "XZ (Frente)"
-
-# AI Translated
-#~ msgid "YZ (Side)"
-#~ msgstr "YZ (Lateral)"
-
-# AI Translated
-#~ msgid "Revolve deg"
-#~ msgstr "Revolução (graus)"
-
-# AI Translated
-#~ msgid "Set to 0 for extrude, >0 for revolve"
-#~ msgstr "Defina como 0 para extrusão, >0 para revolução"
-
-# AI Translated
-#~ msgid "Pocket (cut)"
-#~ msgstr "Cavidade (corte)"
-
-# AI Translated
-#, c-format
-#~ msgid "%zu closed profile"
-#~ msgid_plural "%zu closed profiles"
-#~ msgstr[0] "%zu perfil fechado"
-#~ msgstr[1] "%zu perfis fechados"
-
-# AI Translated
-#~ msgid "Draw a closed profile to enable"
-#~ msgstr "Desenhe um perfil fechado para ativar"
-
-# AI Translated
-#~ msgid "Empty result"
-#~ msgstr "Resultado vazio"
-
-# AI Translated
-#, boost-format
-#~ msgid "Extrude: %1%"
-#~ msgstr "Extrusão: %1%"
-
-# AI Translated
-#, boost-format
-#~ msgid "Revolve: %1%"
-#~ msgstr "Revolução: %1%"
-
-# AI Translated
-#~ msgid "No object selected"
-#~ msgstr "Nenhum objeto selecionado"
-
-# AI Translated
-#~ msgid "Face failed"
-#~ msgstr "Falha na face"
-
-# AI Translated
-#~ msgid "Face with holes failed"
-#~ msgstr "Falha na face com furos"
-
-# AI Translated
-#~ msgid "Tool mesh empty"
-#~ msgstr "Malha da ferramenta vazia"
-
-# AI Translated
-#~ msgid "Pocket added (negative volume)"
-#~ msgstr "Cavidade adicionada (volume negativo)"
-
-# AI Translated
-#, boost-format
-#~ msgid "Pocket: %1%"
-#~ msgstr "Cavidade: %1%"
-
-# AI Translated
-#~ msgid "Needs the active layer mapped with Unwrap (LSCM)."
-#~ msgstr "Requer a camada ativa mapeada com Desdobrar (LSCM)."
-
-# AI Translated
-#~ msgid "Checker - a test grid instead of the texture. Where the squares stay square the texture is undistorted; where they stretch, it will too"
-#~ msgstr "Xadrez - uma grade de teste no lugar da textura. Onde os quadrados continuam quadrados, a textura não está distorcida; onde eles esticam, ela também vai esticar"
-
-# AI Translated
-#~ msgid "Distortion - blue-to-red stretch heatmap over the unwrap"
-#~ msgstr "Distorção - mapa de calor de estiramento, de azul a vermelho, sobre o desdobramento"
-
-# AI Translated
-#~ msgid "Mix by"
-#~ msgstr "Misturar por"
-
-# AI Translated
-#~ msgctxt "Texture Displacement"
-#~ msgid "Surface"
-#~ msgstr "Superfície"
-
-# AI Translated
-#~ msgid ""
-#~ "Layers: the two filaments alternate between print layers, which blends smoothly on upright surfaces but disappears on flat-facing ones, where a whole layer is a single band.\n"
-#~ "Surface: a fine checkerboard across the surface, which works at any angle but can read as texture rather than as a blend.\n"
-#~ "Automatic: layers on upright faces; flat-facing faces take the nearer single filament, since a checkerboard there shows as a pattern."
-#~ msgstr ""
-#~ "Camadas: os dois filamentos se alternam entre as camadas de impressão, o que mistura suavemente em superfícies verticais, mas desaparece nas horizontais, onde uma camada inteira é uma única faixa.\n"
-#~ "Superfície: um xadrez fino sobre a superfície, que funciona em qualquer ângulo, mas pode parecer textura em vez de mistura.\n"
-#~ "Automático: camadas nas faces verticais; as faces horizontais recebem o filamento único mais próximo, já que ali um xadrez aparece como padrão."
-
-# AI Translated
-#~ msgid "Island - move, rotate and scale whole islands"
-#~ msgstr "Ilha - mover, girar e escalar ilhas inteiras"
-
-# AI Translated
-#~ msgid "Vertex - drag vertices to reshape; Shift/Ctrl to multi-select"
-#~ msgstr "Vértice - arraste vértices para remodelar; Shift/Ctrl para seleção múltipla"
-
-# AI Translated
-#~ msgid "Edge - drag edges to reshape; Shift/Ctrl to multi-select"
-#~ msgstr "Aresta - arraste arestas para remodelar; Shift/Ctrl para seleção múltipla"
-
-# AI Translated
-#~ msgid "Frame all islands (Home)"
-#~ msgstr "Enquadrar todas as ilhas (Home)"
-
#~ msgid "(Experimental) Use printer agents instead of print hosts"
#~ msgstr "(Experimental) Usar agentes de impressora em vez de hosts de impressão"
-# AI Translated
-#~ msgid "FEATURES"
-#~ msgstr "RECURSOS"
-
-# AI Translated
-#~ msgid "Click a face or a reference plane in the viewport, then a sketch tool"
-#~ msgstr "Clique em uma face ou em um plano de referência na janela de visualização e depois em uma ferramenta de esboço"
-
-# AI Translated
-#~ msgid "Click a face or a reference plane, then a sketch tool."
-#~ msgstr "Clique em uma face ou em um plano de referência e depois em uma ferramenta de esboço."
-
-# AI Translated
-#, c-format, boost-format
-#~ msgid "%s plane selected — right-click for the drawing tools"
-#~ msgstr "Plano %s selecionado — clique com o botão direito para ver as ferramentas de desenho"
-
-# AI Translated
-#~ msgid ""
-#~ "Nothing yet — import a STEP or a mesh from the toolbar,\n"
-#~ "or click a reference plane and right-click it to start a sketch."
-#~ msgstr ""
-#~ "Nada ainda — importe um STEP ou uma malha pela barra de ferramentas,\n"
-#~ "ou clique em um plano de referência e clique nele com o botão direito para iniciar um esboço."
-
-# AI Translated
-#~ msgid "Click a face or a reference plane, then pick a drawing tool"
-#~ msgstr "Clique em uma face ou em um plano de referência e depois escolha uma ferramenta de desenho"
-
-# AI Translated
-#~ msgid "XY"
-#~ msgstr "XY"
-
-# AI Translated
-#~ msgid "XZ"
-#~ msgstr "XZ"
-
-# AI Translated
-#~ msgid "YZ"
-#~ msgstr "YZ"
-
-# AI Translated
-#~ msgid "Equal"
-#~ msgstr "Igual"
-
-# AI Translated
-#~ msgid "Perpendicular"
-#~ msgstr "Perpendicular"
-
-# AI Translated
-#~ msgid "Midpoint"
-#~ msgstr "Ponto médio"
-
-# AI Translated
-#~ msgid "Equal length"
-#~ msgstr "Comprimento igual"
-
-# AI Translated
-#~ msgid "Equal radius"
-#~ msgstr "Raio igual"
-
-# AI Translated
-#~ msgid "Collinear"
-#~ msgstr "Colinear"
-
-# AI Translated
-#~ msgid "Symmetric about the vertical axis"
-#~ msgstr "Simétrico em relação ao eixo vertical"
-
-# AI Translated
-#~ msgid "Symmetric about the horizontal axis"
-#~ msgstr "Simétrico em relação ao eixo horizontal"
-
-# AI Translated
-#~ msgid "Fix point (anchor in place)"
-#~ msgstr "Fixar ponto (ancorar no lugar)"
-
-# AI Translated
-#~ msgid "Horizontal distance"
-#~ msgstr "Distância horizontal"
-
-# AI Translated
-#~ msgid "Vertical distance"
-#~ msgstr "Distância vertical"
-
#~ msgid "Face recognition"
#~ msgstr "Reconhecimento facial"
@@ -31500,10 +30875,6 @@ msgstr ""
#~ msgid "Please resolve the slicing errors and publish again."
#~ msgstr "Por favor, resolva os erros de fatiamento e publique novamente."
-# AI Translated
-#~ msgid "Treat sketch endpoints within 0.001 mm as one joint and weld the loop shut. Off: only exactly coincident endpoints join, so a loop with a tiny gap is shown as open instead of being closed for you."
-#~ msgstr "Trata extremidades do esboço a menos de 0,001 mm umas das outras como uma só junção e fecha o laço. Desativado: somente extremidades exatamente coincidentes se unem, então um laço com uma pequena folga é mostrado como aberto em vez de ser fechado para você."
-
#~ msgid "Slice all plates to obtain time and filament estimation"
#~ msgstr "Fatiar todas as placas para obter estimativa de tempo e filamento"
@@ -31751,860 +31122,21 @@ msgstr ""
#~ msgid "Standard profile for 0.8mm nozzle, prioritizing speed."
#~ msgstr "Perfil padrão para bico de 0,8 mm, priorizando a velocidade."
-# AI Translated
-#~ msgid "Slot — two centerline ends, then end radius"
-#~ msgstr "Rasgo — as duas extremidades da linha central e depois o raio da extremidade"
-
-# AI Translated
-#~ msgid "Isometric view, fitted"
-#~ msgstr "Vista isométrica, ajustada"
-
-# AI Translated
-#~ msgid "Coord Sys"
-#~ msgstr "Sist. coord."
-
-# AI Translated
-#~ msgid "Assembly: align two CoordSys features (fastened, planar, revolute, slider, cylindrical)"
-#~ msgstr "Montagem: alinhar dois recursos de sistema de coordenadas (fixo, planar, de revolução, deslizante, cilíndrico)"
-
-# AI Translated
-#~ msgid "Click points; click the first point to close the loop, right-click to end the chain"
-#~ msgstr "Clique nos pontos; clique no primeiro ponto para fechar o laço, clique com o botão direito para encerrar a cadeia"
-
-# AI Translated
-#~ msgid "Click two centerline ends, then a point for the end radius"
-#~ msgstr "Clique nas duas extremidades da linha central e depois em um ponto para o raio da extremidade"
-
-# AI Translated
-#~ msgid "Click control points; double-click or right-click to finish"
-#~ msgstr "Clique nos pontos de controle; clique duplo ou clique com o botão direito para terminar"
-
-# AI Translated
-#~ msgid "Click a segment to trim it back to its nearest intersection; right-click exits"
-#~ msgstr "Clique em um segmento para apará-lo até a interseção mais próxima; clique com o botão direito para sair"
-
-# AI Translated
-#~ msgid "Click a line or arc to extend it to the nearest entity; right-click exits"
-#~ msgstr "Clique em uma linha ou arco para estendê-lo até a entidade mais próxima; clique com o botão direito para sair"
-
-# AI Translated
-#~ msgid "✓ Confirm"
-#~ msgstr "✓ Confirmar"
-
-# AI Translated
-#~ msgid "✗ Cancel"
-#~ msgstr "✗ Cancelar"
-
-# AI Translated
-#~ msgid "Undo (Ctrl+Z)"
-#~ msgstr "Desfazer (Ctrl+Z)"
-
-# AI Translated
-#~ msgid "Redo (Ctrl+Shift+Z)"
-#~ msgstr "Refazer (Ctrl+Shift+Z)"
-
-# AI Translated
-#~ msgid "Taper °"
-#~ msgstr "Conicidade °"
-
-# AI Translated
-#~ msgid "Total angle°"
-#~ msgstr "Ângulo total°"
-
-# AI Translated
-#~ msgid "Union (join)"
-#~ msgstr "Unir (juntar)"
-
-# AI Translated
-#~ msgid "Subtract (cut)"
-#~ msgstr "Subtrair (cortar)"
-
-# AI Translated
-#~ msgid "Angle°"
-#~ msgstr "Ângulo°"
-
-# AI Translated
-#~ msgid "CS A (fixed)"
-#~ msgstr "SC A (fixo)"
-
-# AI Translated
-#~ msgid "CS B (moves)"
-#~ msgstr "SC B (móvel)"
-
-# AI Translated
-#~ msgid "Move body"
-#~ msgstr "Mover corpo"
-
-# AI Translated
-#~ msgid "Select a body row first, then move it"
-#~ msgstr "Selecione primeiro a linha de um corpo e depois mova-o"
-
-# AI Translated
-#~ msgid "+"
-#~ msgstr "+"
-
-# AI Translated
-#, c-format, boost-format
-#~ msgid "Body %d: edge %d selected — Fillet/Chamfer to dress it, or click again for the whole body"
-#~ msgstr "Corpo %d: aresta %d selecionada — Filete/Chanfro para arredondá-la ou chanfrá-la, ou clique novamente para o corpo inteiro"
-
-# AI Translated
-#, c-format, boost-format
-#~ msgid "Edge %d selected — Fillet/Chamfer to dress it, or click again for the whole body"
-#~ msgstr "Aresta %d selecionada — Filete/Chanfro para arredondá-la ou chanfrá-la, ou clique novamente para o corpo inteiro"
-
-# AI Translated
-#~ msgid "Text to insert:"
-#~ msgstr "Texto a inserir:"
-
-# AI Translated
-#~ msgid "STEP import failed: "
-#~ msgstr "Falha ao importar STEP: "
-
-# AI Translated
-#~ msgid "Could not read the OBJ file: "
-#~ msgstr "Não foi possível ler o arquivo OBJ: "
-
-# AI Translated
-#~ msgid "Mesh conversion failed: "
-#~ msgstr "Falha na conversão da malha: "
-
-# AI Translated
-#~ msgid "Mesh import failed: "
-#~ msgstr "Falha ao importar a malha: "
-
-# AI Translated
-#~ msgid "Drag a corner to scale, the center to move — right-click when done"
-#~ msgstr "Arraste um canto para dimensionar, o centro para mover — clique com o botão direito ao terminar"
-
-# AI Translated
-#~ msgid "Recompute error: "
-#~ msgstr "Erro de recálculo: "
-
-# AI Translated
-#~ msgid "Mate needs two CoordSys features — create them first"
-#~ msgstr "O posicionamento precisa de dois recursos de sistema de coordenadas — crie-os primeiro"
-
-# AI Translated
-#~ msgid "Mate: CS A and CS B must be different CoordSys features"
-#~ msgstr "Posicionamento: SC A e SC B devem ser recursos de sistema de coordenadas diferentes"
-
-# AI Translated
-#~ msgid "No interference — need at least two solid bodies to check"
-#~ msgstr "Sem interferência — são necessários pelo menos dois corpos sólidos para verificar"
-
-# AI Translated
-#, c-format
-#~ msgid "%zu interference pair, worst %.2f mm³"
-#~ msgid_plural "%zu interference pairs, worst %.2f mm³"
-#~ msgstr[0] "%zu par com interferência, pior %.2f mm³"
-#~ msgstr[1] "%zu pares com interferência, pior %.2f mm³"
-
-# AI Translated
-#~ msgid ""
-#~ "Interference pairs:\n"
-#~ "\n"
-#~ msgstr ""
-#~ "Pares com interferência:\n"
-#~ "\n"
-
-# AI Translated
-#~ msgid "Interference"
-#~ msgstr "Interferência"
-
-# AI Translated
-#~ msgid "Select a solid body first — its mass properties are what is reported"
-#~ msgstr "Selecione primeiro um corpo sólido — são as propriedades de massa dele que são informadas"
-
-# AI Translated
-#~ msgid "Mass properties could not be computed for this body"
-#~ msgstr "Não foi possível calcular as propriedades de massa deste corpo"
-
-# AI Translated
-#, c-format, boost-format
-#~ msgid "%s: sheet body — %.2f cm² of surface, no volume"
-#~ msgstr "%s: corpo de superfície — %.2f cm² de superfície, sem volume"
-
-# AI Translated
-#, c-format, boost-format
-#~ msgid ""
-#~ "%s\n"
-#~ "\n"
-#~ "Sheet body (open shell)\n"
-#~ "Surface area: %.2f cm²\n"
-#~ "\n"
-#~ "A sheet encloses no material, so it has no volume. Thicken it into a solid to get one."
-#~ msgstr ""
-#~ "%s\n"
-#~ "\n"
-#~ "Corpo de superfície (casca aberta)\n"
-#~ "Área de superfície: %.2f cm²\n"
-#~ "\n"
-#~ "Uma superfície não envolve material, então não tem volume. Espesse-a para transformá-la em um sólido e obter um volume."
-
-# AI Translated
-#~ msgid "Mass properties"
-#~ msgstr "Propriedades de massa"
-
-# AI Translated
-#, c-format, boost-format
-#~ msgid "%s: %.3f cm³, %.2f cm²"
-#~ msgstr "%s: %.3f cm³, %.2f cm²"
-
-# AI Translated
-#, c-format, boost-format
-#~ msgid ""
-#~ "%s\n"
-#~ "\n"
-#~ "Volume: %.3f cm³\n"
-#~ "Surface area: %.2f cm²"
-#~ msgstr ""
-#~ "%s\n"
-#~ "\n"
-#~ "Volume: %.3f cm³\n"
-#~ "Área de superfície: %.2f cm²"
-
-# AI Translated
-#~ msgid "Boolean needs two solid bodies — add or import a second one"
-#~ msgstr "A operação booleana precisa de dois corpos sólidos — adicione ou importe um segundo"
-
-# AI Translated
-#~ msgid "Line — click the end point, or type the length"
-#~ msgstr "Linha — clique no ponto final ou digite o comprimento"
-
-# AI Translated
-#~ msgid "Polyline — click the next point · click the start point to close it · right-click to end the chain"
-#~ msgstr "Polilinha — clique no próximo ponto · clique no ponto inicial para fechá-la · clique com o botão direito para encerrar a cadeia"
-
-# AI Translated
-#~ msgid "Circle — click to set the radius, or type it"
-#~ msgstr "Círculo — clique para definir o raio ou digite-o"
-
-# AI Translated
-#~ msgid "Spline — click the next control point · right-click to finish the curve"
-#~ msgstr "Spline — clique no próximo ponto de controle · clique com o botão direito para terminar a curva"
-
-# AI Translated
-#~ msgid "Trim — click a segment where it crosses another entity · right-click to exit"
-#~ msgstr "Aparar — clique em um segmento onde ele cruza outra entidade · clique com o botão direito para sair"
-
-# AI Translated
-#~ msgid "Extend — click a line or arc to grow it out to the nearest entity · right-click to exit"
-#~ msgstr "Estender — clique em uma linha ou arco para prolongá-lo até a entidade mais próxima · clique com o botão direito para sair"
-
-# AI Translated
-#~ msgid "Fillet — drag the arrow, or click the number to type the radius · click empty space to apply · right-click cancels"
-#~ msgstr "Filete — arraste a seta ou clique no número para digitar o raio · clique em um espaço vazio para aplicar · o botão direito cancela"
-
-# AI Translated
-#~ msgid "Chamfer — drag the arrow, or click the number to type the setback · click empty space to apply · right-click cancels"
-#~ msgstr "Chanfro — arraste a seta ou clique no número para digitar o recuo · clique em um espaço vazio para aplicar · o botão direito cancela"
-
-# AI Translated
-#~ msgid "Offset — click the entity to offset"
-#~ msgstr "Deslocamento — clique na entidade a deslocar"
-
-# AI Translated
-#~ msgid "Offset — drag the arrow to either side, or click the number to type the distance · click empty space to apply · right-click cancels"
-#~ msgstr "Deslocamento — arraste a seta para qualquer lado ou clique no número para digitar a distância · clique em um espaço vazio para aplicar · o botão direito cancela"
-
-# AI Translated
-#~ msgid "Mirror — axis set · now click the entities to mirror · right-click cancels"
-#~ msgstr "Espelhar — eixo definido · agora clique nas entidades a espelhar · o botão direito cancela"
-
-# AI Translated
-#, c-format, boost-format
-#~ msgid "Mirror — axis set · %d to mirror · click another to add or remove it · click empty space to apply"
-#~ msgstr "Espelhar — eixo definido · %d a espelhar · clique em outra para adicioná-la ou removê-la · clique em um espaço vazio para aplicar"
-
-# AI Translated
-#~ msgid "Move — drag the handle, or click the number to type the distance · click empty space to apply"
-#~ msgstr "Mover — arraste a alça ou clique no número para digitar a distância · clique em um espaço vazio para aplicar"
-
-# AI Translated
-#~ msgid "Rotate — drag the handle, or click the number to type the angle · click empty space to apply"
-#~ msgstr "Rotacionar — arraste a alça ou clique no número para digitar o ângulo · clique em um espaço vazio para aplicar"
-
-# AI Translated
-#~ msgid "Scale — drag the handle, or click the number to type the factor · click empty space to apply"
-#~ msgstr "Dimensionar — arraste a alça ou clique no número para digitar o fator · clique em um espaço vazio para aplicar"
-
-# AI Translated
-#~ msgid "Array — drag the handle to set the step, click the count to type it · click empty space to apply"
-#~ msgstr "Matriz — arraste a alça para definir o passo, clique na quantidade para digitá-la · clique em um espaço vazio para aplicar"
-
-# AI Translated
-#~ msgid "Polar array — drag the handle to set the sweep, click the count to type it · click empty space to apply"
-#~ msgstr "Matriz polar — arraste a alça para definir o ângulo total, clique na quantidade para digitá-la · clique em um espaço vazio para aplicar"
-
-# AI Translated
-#~ msgid "Drag a corner to scale, the center to move · right-click when done"
-#~ msgstr "Arraste um canto para dimensionar, o centro para mover · clique com o botão direito ao terminar"
-
-# AI Translated
-#~ msgid "Coord Sys added"
-#~ msgstr "Sist. coord. adicionado"
-
-# AI Translated
-#~ msgid "Could not restore the CAD model: "
-#~ msgstr "Não foi possível restaurar o modelo CAD: "
-
-# AI Translated
-#~ msgid "Boolean needs two bodies — create or import a second solid"
-#~ msgstr "A operação booleana precisa de dois corpos — crie ou importe um segundo sólido"
-
-# AI Translated
-#~ msgid "Edit rejected: "
-#~ msgstr "Edição rejeitada: "
-
-# AI Translated
-#, c-format, boost-format
-#~ msgid ""
-#~ "Delete %s?\n"
-#~ "\n"
-#~ "That is the feature this body was made from. Features built on it may be removed or stop working."
-#~ msgstr ""
-#~ "Excluir %s?\n"
-#~ "\n"
-#~ "Esse é o recurso a partir do qual este corpo foi criado. Os recursos construídos sobre ele podem ser removidos ou parar de funcionar."
-
-# AI Translated
-#~ msgid "Delete body"
-#~ msgstr "Excluir corpo"
-
-# AI Translated
-#~ msgid "STEP export failed: "
-#~ msgstr "Falha ao exportar STEP: "
-
-# AI Translated
-#~ msgid "Coord Sys ready"
-#~ msgstr "Sist. coord. pronto"
-
-# AI Translated
-#~ msgid "Mate needs at least two CoordSys features"
-#~ msgstr "O posicionamento precisa de pelo menos dois recursos de sistema de coordenadas"
-
-# AI Translated
-#~ msgid "Mate: CS A and CS B must be different"
-#~ msgstr "Posicionamento: SC A e SC B devem ser diferentes"
-
-# AI Translated
-#~ msgid "Invalid: "
-#~ msgstr "Inválido: "
-
-# AI Translated
-#~ msgid "Variable name:"
-#~ msgstr "Nome da variável:"
-
-# AI Translated
-#, c-format, boost-format
-#~ msgid "Expression for '%s':"
-#~ msgstr "Expressão para '%s':"
-
-# AI Translated
-#~ msgid "Seg"
-#~ msgstr "Seg."
-
-# AI Translated
-#~ msgid "CLOSED"
-#~ msgstr "FECHADO"
-
-# AI Translated
-#, boost-format
-#~ msgid "%1% %2%: %3% pts %4%"
-#~ msgstr "%1% %2%: %3% pts %4%"
-
-# AI Translated
-#~ msgid "Pocket (Cut)"
-#~ msgstr "Cavidade (Corte)"
-
-# AI Translated
-#~ msgid "Clear All"
-#~ msgstr "Limpar tudo"
-
-# AI Translated
-#~ msgid "Hollow this object"
-#~ msgstr "Esvaziar este objeto"
-
-# AI Translated
-#~ msgid "Preview hollowed and drilled model"
-#~ msgstr "Pré-visualizar modelo esvaziado e perfurado"
-
-# AI Translated
-#~ msgid "Closing distance"
-#~ msgstr "Distância de fechamento"
-
-# AI Translated
-#~ msgid "Hole diameter"
-#~ msgstr "Diâmetro do furo"
-
-# AI Translated
-#~ msgid "Hole depth"
-#~ msgstr "Profundidade do furo"
-
-# AI Translated
-#~ msgid "Remove selected holes"
-#~ msgstr "Remover furos selecionados"
-
-# AI Translated
-#~ msgid "Remove all holes"
-#~ msgstr "Remover todos os furos"
-
-# AI Translated
-#~ msgid "Clipping of view"
-#~ msgstr "Recorte da vista"
-
#~ msgid "Reset direction"
#~ msgstr "Redefinir direção"
-# AI Translated
-#~ msgid "Show supports"
-#~ msgstr "Mostrar suportes"
-
-# AI Translated
-#~ msgid "Hollow and drill"
-#~ msgstr "Esvaziar e perfurar"
-
#~ msgid "Head diameter"
#~ msgstr "Diâmetro da cabeça"
-# AI Translated
-#~ msgid "Lock supports under new islands"
-#~ msgstr "Travar suportes sob novas ilhas"
-
#~ msgid "Remove selected points"
#~ msgstr "Remover pontos selecionados"
-# AI Translated
-#~ msgid "Remove all points"
-#~ msgstr "Remover todos os pontos"
-
-# AI Translated
-#~ msgid "Apply changes"
-#~ msgstr "Aplicar alterações"
-
-# AI Translated
-#~ msgid "Discard changes"
-#~ msgstr "Descartar alterações"
-
-# AI Translated
-#~ msgid "Minimal points distance"
-#~ msgstr "Distância mínima entre pontos"
-
-# AI Translated
-#~ msgid "Support points density"
-#~ msgstr "Densidade dos pontos de suporte"
-
-#~ msgid "Auto-generate points"
-#~ msgstr "Pontos gerados automaticamente"
-
-# AI Translated
-#~ msgid "Manual editing"
-#~ msgstr "Edição manual"
-
-# AI Translated
-#~ msgid "SLA Support Points"
-#~ msgstr "Pontos de Suporte SLA"
-
-# AI Translated
-#~ msgid "Do you want to save your manually edited support points?"
-#~ msgstr "Deseja salvar os pontos de suporte editados manualmente?"
-
-# AI Translated
-#~ msgid "Save support points?"
-#~ msgstr "Salvar pontos de suporte?"
-
-# AI Translated
-#~ msgid "Autogeneration will erase all manually edited points."
-#~ msgstr "A geração automática apagará todos os pontos editados manualmente."
-
-# AI Translated
-#~ msgid "Are you sure you want to do it?"
-#~ msgstr "Tem certeza de que deseja fazer isso?"
-
-# AI Translated
-#~ msgid "SLA gizmo keyboard shortcuts"
-#~ msgstr "Atalhos de teclado do gizmo SLA"
-
-# AI Translated
-#~ msgid "Note: some shortcuts work in (non)editing mode only."
-#~ msgstr "Observação: alguns atalhos funcionam apenas dentro ou apenas fora do modo de edição."
-
#~ msgid "Left click"
#~ msgstr "Clique esquerdo"
-# AI Translated
-#~ msgid "Add point"
-#~ msgstr "Adicionar ponto"
-
#~ msgid "Right click"
#~ msgstr "Clique direito"
-# AI Translated
-#~ msgid "Remove point"
-#~ msgstr "Remover ponto"
-
-# AI Translated
-#~ msgid "Move point"
-#~ msgstr "Mover ponto"
-
-# AI Translated
-#~ msgid "Add point to selection"
-#~ msgstr "Adicionar ponto à seleção"
-
-# AI Translated
-#~ msgid "Remove point from selection"
-#~ msgstr "Remover ponto da seleção"
-
-# AI Translated
-#~ msgid "Select by rectangle"
-#~ msgstr "Selecionar por retângulo"
-
-# AI Translated
-#~ msgid "Deselect by rectangle"
-#~ msgstr "Desmarcar por retângulo"
-
-# AI Translated
-#~ msgid "Select all points"
-#~ msgstr "Selecionar todos os pontos"
-
-# AI Translated
-#~ msgid "Move clipping plane"
-#~ msgstr "Mover plano de recorte"
-
-# AI Translated
-#~ msgid "Reset clipping plane"
-#~ msgstr "Redefinir plano de recorte"
-
-# AI Translated
-#~ msgid "Switch to editing mode"
-#~ msgstr "Mudar para o modo de edição"
-
-# AI Translated
-#~ msgctxt "Design"
-#~ msgid "Union"
-#~ msgstr "Unir"
-
-# AI Translated
-#~ msgid "target is not a sheet body"
-#~ msgstr "o alvo não é um corpo de superfície"
-
-# AI Translated
-#~ msgid "Drill a hole, centred on a picked face or placed on a plane"
-#~ msgstr "Fazer um furo, centralizado em uma face selecionada ou colocado em um plano"
-
-# AI Translated
-#~ msgid "Shell needs a solid body"
-#~ msgstr "A casca precisa de um corpo sólido"
-
-# AI Translated
-#~ msgid "Split needs a solid body"
-#~ msgstr "A divisão precisa de um corpo sólido"
-
-# AI Translated
-#~ msgid "Pattern on curve needs a body and a curve"
-#~ msgstr "O padrão em curva precisa de um corpo e de uma curva"
-
-# AI Translated
-#~ msgid "A mate needs two coordinate systems"
-#~ msgstr "Um posicionamento precisa de dois sistemas de coordenadas"
-
-# AI Translated
-#~ msgid "Align needs a body"
-#~ msgstr "O alinhamento precisa de um corpo"
-
-# AI Translated
-#~ msgctxt "Design"
-#~ msgid "Coord Sys"
-#~ msgstr "Sist. coord."
-
-# AI Translated
-#~ msgctxt "Design"
-#~ msgid "Mass"
-#~ msgstr "Massa"
-
-# AI Translated
-#~ msgctxt "Design"
-#~ msgid "Colour"
-#~ msgstr "Cor"
-
-# AI Translated
-#~ msgid "Set the selected body's display colour"
-#~ msgstr "Definir a cor de exibição do corpo selecionado"
-
-# AI Translated
-#~ msgctxt "Design"
-#~ msgid "Centre rectangle"
-#~ msgstr "Retângulo pelo centro"
-
-# AI Translated
-#~ msgctxt "Design"
-#~ msgid "Centre circle"
-#~ msgstr "Círculo pelo centro"
-
-# AI Translated
-#~ msgctxt "Design"
-#~ msgid "Centre-point arc"
-#~ msgstr "Arco pelo centro"
-
-# AI Translated
-#~ msgid "Triangle — click centre, then a vertex"
-#~ msgstr "Triângulo — clique no centro e depois em um vértice"
-
-# AI Translated
-#~ msgid "Square — click centre, then a vertex"
-#~ msgstr "Quadrado — clique no centro e depois em um vértice"
-
-# AI Translated
-#~ msgid "Pentagon — click centre, then a vertex"
-#~ msgstr "Pentágono — clique no centro e depois em um vértice"
-
-# AI Translated
-#~ msgid "Hexagon — click centre, then a vertex"
-#~ msgstr "Hexágono — clique no centro e depois em um vértice"
-
-# AI Translated
-#~ msgid "Octagon — click centre, then a vertex"
-#~ msgstr "Octógono — clique no centro e depois em um vértice"
-
-# AI Translated
-#~ msgid "Dodecagon — click centre, then a vertex"
-#~ msgstr "Dodecágono — clique no centro e depois em um vértice"
-
-# AI Translated
-#~ msgid "Type text; its outline is added to this sketch as editable lines"
-#~ msgstr "Digite um texto; o contorno dele é adicionado a este esboço como linhas editáveis"
-
-# AI Translated
-#~ msgid "Major"
-#~ msgstr "Eixo maior"
-
-# AI Translated
-#~ msgid "Minor"
-#~ msgstr "Eixo menor"
-
-# AI Translated
-#~ msgid "Extend: click a line/arc that can reach another live entity"
-#~ msgstr "Estender: clique em uma linha/arco que possa alcançar outra entidade ativa"
-
-# AI Translated
-#~ msgid "Trim: click a segment where it crosses another live entity"
-#~ msgstr "Aparar: clique em um segmento onde ele cruza outra entidade ativa"
-
-# AI Translated
-#~ msgid "closed profile(s)"
-#~ msgstr "perfil(is) fechado(s)"
-
-#~ msgid "Failed to generate cali G-code"
-#~ msgstr "Falha ao gerar o G-code de calibração"
-
-# AI Translated
-#~ msgid "Multiply"
-#~ msgstr "Multiplicar"
-
-# AI Translated
-#~ msgid " and "
-#~ msgstr " e "
-
-# AI Translated
-#~ msgid "cannot be mixed. Please select the same filament type."
-#~ msgstr "não podem ser misturados. Selecione o mesmo tipo de filamento."
-
-# AI Translated
-#~ 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 "
-#~ msgstr "Carregar %s em "
-
-# AI Translated
-#~ msgid "In the Design tab, draw a mate connector as a small face instead of the conventional disc with a roll quadrant. A face's orientation is read without being learned. Turn this off for the conventional CAD representation."
-#~ msgstr "Na aba Design, desenha um conector de posicionamento como uma pequena face em vez do disco convencional com um quadrante de giro. A orientação de uma face é lida sem precisar ser aprendida. Desative para a representação CAD convencional."
-
-# AI Translated
-#~ msgid "Expert"
-#~ msgstr "Especialista"
-
-# AI Translated
-#~ msgid "Simple"
-#~ msgstr "Simples"
-
-# AI Translated
-#~ msgid "Click points; click first / right-click to close the loop"
-#~ msgstr "Clique nos pontos; clique no primeiro / clique com o botão direito para fechar o laço"
-
-# AI Translated
-#~ msgid "X hint X"
-#~ msgstr "Dica de X: X"
-
-# AI Translated
-#~ msgid "X hint Y"
-#~ msgstr "Dica de X: Y"
-
-# AI Translated
-#~ msgid "X hint Z"
-#~ msgstr "Dica de X: Z"
-
-# AI Translated
-#~ msgid " — the eye suppresses this mate"
-#~ msgstr " — o olho suprime este posicionamento"
-
-# AI Translated
-#~ msgid "Del"
-#~ msgstr "Excl."
-
-# AI Translated
-#~ msgid "Sketch kept — Finish to commit it, Cancel to discard"
-#~ msgstr "Esboço mantido — Terminar para confirmá-lo, Cancelar para descartá-lo"
-
-# AI Translated
-#, c-format, boost-format
-#~ msgid "Editing: Sketch %d · N = look normal to the plane · Finish or Cancel in the toolbar"
-#~ msgstr "Editando: Esboço %d · N = olhar normal ao plano · Terminar ou Cancelar na barra de ferramentas"
-
-# AI Translated
-#~ msgid "Editing sketch — drag a handle or click a quote to edit"
-#~ msgstr "Editando esboço — arraste uma alça ou clique em uma cota para editar"
-
-# AI Translated
-#, c-format, boost-format
-#~ msgid "Showing %s actions"
-#~ msgstr "Mostrando %s ações"
-
-# AI Translated
-#, c-format, boost-format
-#~ msgid "%s actions"
-#~ msgstr "%s ações"
-
-# AI Translated
-#, c-format, boost-format
-#~ msgid "%s tabs"
-#~ msgstr "%s abas"
-
-# AI Translated
-#, c-format, boost-format
-#~ msgid "%s matches"
-#~ msgstr "%s correspondências"
-
-# AI Translated
-#, c-format, boost-format
-#~ msgid "%s · on %s"
-#~ msgstr "%s · em %s"
-
-# AI Translated
-#, c-format, boost-format
-#~ msgid "Sketching on %s — pick a tool"
-#~ msgstr "Esboçando em %s — escolha uma ferramenta"
-
-# AI Translated
-#, c-format, boost-format
-#~ msgid ""
-#~ "Drawing on %s.\n"
-#~ "Pick a tool, or press Menu for the list."
-#~ msgstr ""
-#~ "Desenhando em %s.\n"
-#~ "Escolha uma ferramenta ou pressione Menu para ver a lista."
-
-# AI Translated
-#~ msgid "Colour"
-#~ msgstr "Cor"
-
-# AI Translated
-#, c-format, boost-format
-#~ msgid "Body %d "
-#~ msgstr "Corpo %d "
-
-# AI Translated
-#~ msgid "vertex selected — click again for the whole body"
-#~ msgstr "vértice selecionado — clique novamente para o corpo inteiro"
-
-# AI Translated
-#~ msgid "selected (whole body) — right-click for what applies to it"
-#~ msgstr "selecionado (corpo inteiro) — clique com o botão direito para ver o que se aplica a ele"
-
-# AI Translated
-#, c-format, boost-format
-#~ msgid "face %d selected — right-click to push/pull it, or click again for the whole body"
-#~ msgstr "face %d selecionada — clique com o botão direito para empurrá-la/puxá-la, ou clique novamente para o corpo inteiro"
-
-# AI Translated
-#, c-format, boost-format
-#~ msgid "edge %d selected — Fillet/Chamfer to dress it, or click again for the whole body"
-#~ msgstr "aresta %d selecionada — Filete/Chanfro para arredondá-la ou chanfrá-la, ou clique novamente para o corpo inteiro"
-
-# AI Translated
-#, c-format, boost-format
-#~ msgid "placed (%.1f, %.1f, %.1f) mm — drag arrows to move, rings to rotate"
-#~ msgstr "colocado em (%.1f, %.1f, %.1f) mm — arraste as setas para mover, os anéis para rotacionar"
-
-# AI Translated
-#, c-format, boost-format
-#~ msgid "%d degrees of freedom"
-#~ msgstr "%d graus de liberdade"
-
-# AI Translated
-#, c-format, boost-format
-#~ msgid "Imported %d solid(s) — pick a face or edge, then Fillet / Cut / Shell to modify"
-#~ msgstr "%d sólido(s) importado(s) — selecione uma face ou aresta e depois Filete / Cortar / Casca para modificar"
-
-# AI Translated
-#, c-format, boost-format
-#~ msgid "Imported as an open shell (not watertight): %d boundary edge(s), %d non-manifold edge(s) — %d triangles → %d faces. The source mesh has holes or duplicated geometry; boolean features may fail on it"
-#~ msgstr "Importado como uma casca aberta (não estanque): %d aresta(s) de borda, %d aresta(s) não-manifold — %d triângulos → %d faces. A malha de origem tem furos ou geometria duplicada; recursos booleanos podem falhar nela"
-
-# AI Translated
-#, c-format, boost-format
-#~ msgid "Sketch added on %s — select it, then right-click to Extrude"
-#~ msgstr "Esboço adicionado em %s — selecione-o e clique com o botão direito para extrudar"
-
-# AI Translated
-#, c-format
-#~ msgid "%zu interference pairs, worst %.2f mm³"
-#~ msgstr "%zu pares com interferência, pior %.2f mm³"
-
-# AI Translated
-#, c-format, boost-format
-#~ msgid "the picked face of Body %d"
-#~ msgstr "a face selecionada do Corpo %d"
-
-# AI Translated
-#~ msgid "the picked face"
-#~ msgstr "a face selecionada"
-
-# AI Translated
-#, c-format, boost-format
-#~ msgid "%d selected · Del removes them · Shift-click adds · double-click takes the whole loop"
-#~ msgstr "%d selecionado(s) · Del os remove · Shift+clique adiciona · clique duplo seleciona o laço inteiro"
-
-# AI Translated
-#, c-format, boost-format
-#~ msgid "Section view — showing the %s half"
-#~ msgstr "Vista de seção — mostrando a metade %s"
-
-# AI Translated
-#~ msgid "upper"
-#~ msgstr "superior"
-
-# AI Translated
-#~ msgid "lower"
-#~ msgstr "inferior"
-
-# AI Translated
-#, c-format
-#~ msgid "Redo (%zu more)"
-#~ msgstr "Refazer (mais %zu)"
-
-# AI Translated
-#, c-format
-#~ msgid "Undo (%zu more)"
-#~ msgstr "Desfazer (mais %zu)"
-
#~ msgid "Section View"
#~ msgstr "Vista de Seção"
@@ -32617,10 +31149,6 @@ msgstr ""
#~ msgid "Switch Camera View"
#~ msgstr "Trocar Vista da Câmera"
-# AI Translated
-#~ msgid "Renders cast shadows on the plate, other objects, and each object onto itself in realistic view."
-#~ msgstr "Renderiza sombras projetadas na mesa, em outros objetos e de cada objeto sobre si mesmo na visualização realista."
-
#~ msgid "Support/Color Painting: adjust section position"
#~ msgstr "Suporte/Pintura em cores: ajustar a posição da seção"
@@ -32630,14 +31158,6 @@ msgstr ""
#~ msgid "Displays current viewport FPS in the top-right corner."
#~ msgstr "Exibe o FPS atual da janela de visualização no canto superior direito."
-# AI Translated
-#~ msgid "Publish 3MF Wiki"
-#~ msgstr "Documentação de Publicar 3MF"
-
-# AI Translated
-#~ msgid "Publish 3MF Video Guide"
-#~ msgstr "Guia em vídeo de Publicar 3MF"
-
#~ msgid "Toolbar"
#~ msgstr "Barra de Ferramentas"
@@ -32722,18 +31242,6 @@ msgstr ""
#~ msgid " minimum drying temperature is "
#~ msgstr " temperatura mínima de secagem é "
-# AI Translated
-#~ msgid "needs"
-#~ msgstr "precisa de"
-
-# AI Translated
-#~ msgid "not enabled"
-#~ msgstr "não ativado"
-
-# AI Translated
-#~ msgid "material not published"
-#~ msgstr "material não publicado"
-
#~ msgid "Select the language"
#~ msgstr "Selecione o idioma"
@@ -32918,7 +31426,7 @@ msgstr ""
#~ msgstr "O conteúdo da predefinição é muito grande para ser sincronizado com a nuvem (excede 1 MB). Reduza o tamanho da predefinição removendo configurações personalizadas ou use-o apenas localmente."
#~ msgid "Enable adaptive pressure advance for overhangs (beta)"
-#~ msgstr "Habilitar pressure advance adaptativo para saliências (beta)"
+#~ msgstr "Habilitar Pressure Advance adaptativo para saliências (beta)"
#~ msgid "Pressure advance for bridges"
#~ msgstr "Pressure advance para pontes"
@@ -32928,7 +31436,7 @@ msgstr ""
#~ "\n"
#~ "A lower PA value when printing bridges helps reduce the appearance of slight under extrusion immediately after bridges. This is caused by the pressure drop in the nozzle when printing in the air and a lower PA helps counteract this."
#~ msgstr ""
-#~ "Valor do pressure advance para pontes. Defina como 0 para desabilitar.\n"
+#~ "Valor do Pressure Advance para pontes. Defina como 0 para desabilitar.\n"
#~ "\n"
#~ "Um valor de PA mais baixo ao imprimir pontes ajuda a reduzir a aparência de leve subextrusão imediatamente após as pontes. Isso é causado pela queda de pressão no bico ao imprimir no ar e um PA mais baixo ajuda a neutralizar isso."
@@ -33137,7 +31645,7 @@ msgstr ""
#~ msgstr ""
#~ "Habilite esta opção para desacelerar a impressão em áreas onde os perímetros podem ter se curvado para cima. Por exemplo, uma desaceleração adicional será aplicada ao imprimir saliências em cantos afiados, como a parte frontal do casco Benchy, reduzindo a curvatura que se acumula por várias camadas.\n"
#~ "\n"
-#~ "Geralmente, é recomendável ter esta opção ativada, a menos que o resfriamento da impressora seja potente o suficiente ou a velocidade de impressão lenta o suficiente para que a curvatura do perímetro não aconteça. Se estiver imprimindo com uma alta velocidade de perímetro externo, este parâmetro pode introduzir pequenos artefatos ao desacelerar devido à grande variação nas velocidades de impressão. Se você notar artefatos, certifique-se de que seu pressure advance esteja ajustado corretamente.\n"
+#~ "Geralmente, é recomendável ter esta opção ativada, a menos que o resfriamento da impressora seja potente o suficiente ou a velocidade de impressão lenta o suficiente para que a curvatura do perímetro não aconteça. Se estiver imprimindo com uma alta velocidade de perímetro externo, este parâmetro pode introduzir pequenos artefatos ao desacelerar devido à grande variação nas velocidades de impressão. Se você notar artefatos, certifique-se de que seu Pressure Advance esteja ajustado corretamente.\n"
#~ "\n"
#~ "Nota: quando esta opção estiver habilitada, os perímetros de saliência são tratados como saliências, o que significa que a velocidade de saliência é aplicada mesmo se o perímetro de saliência for parte de uma ponte. Por exemplo, quando os perímetros estiverem 100% salientes, sem nenhuma parede apoiando-os por baixo, a velocidade de saliência de 100% será aplicada."
@@ -33424,7 +31932,7 @@ msgstr ""
#~ msgstr "A posição da torre de purga ultrapassou os limites da placa de impressão e foi reposicionada para a borda válida mais próxima."
#~ msgid "Enabling both precise Z height and the prime tower may cause the size of prime tower to increase. Do you still want to enable?"
-#~ msgstr "Habilitar a altura Z precisa e a torre de preparação juntas pode causar o aumento de tamanho da torre de purga. Deseja habilitar mesmo assim?"
+#~ msgstr "Habilitar a altura Z precisa e a torre de purga juntas pode causar o aumento de tamanho da torre de purga. Deseja habilitar mesmo assim?"
#~ msgid "Missing BambuSource component registered for media playing! Please re-install BambuStudio or seek after-sales help."
#~ msgstr "Componente BambuSource ausente registrado para reprodução de mídia! Reinstale o Bambu Studio ou procure ajuda pós-venda."
@@ -34351,7 +32859,7 @@ msgstr ""
#~ msgstr "Diâmetros de bico diferentes e diâmetros de filamento diferentes não são permitidos quando a torre de purga está ativa."
#~ msgid "Ooze prevention is currently not supported with the prime tower enabled."
-#~ msgstr "A prevenção de vazamento atualmente não é suportada com a torre de prepao ativa."
+#~ msgstr "A prevenção de vazamento atualmente não é suportada com a torre de purga ativa."
#~ msgid "Interlocking depth of a segmented region. Zero disables this feature."
#~ msgstr "Profundidade de intertravamento de uma região segmentada. Zero desativa essa funcionalidade."
diff --git a/resources/images/score_star_outline.svg b/resources/images/score_star_outline.svg
new file mode 100644
index 0000000000..eb52be9e82
--- /dev/null
+++ b/resources/images/score_star_outline.svg
@@ -0,0 +1,3 @@
+
diff --git a/resources/profiles/BBL.json b/resources/profiles/BBL.json
index 6c6567d37d..da56f36ccd 100644
--- a/resources/profiles/BBL.json
+++ b/resources/profiles/BBL.json
@@ -1,7 +1,7 @@
{
"name": "Bambulab",
"url": "http://www.bambulab.com/Parameters/vendor/BBL.json",
- "version": "02.08.00.14",
+ "version": "02.08.00.15",
"force_update": "0",
"description": "the initial version of BBL configurations",
"machine_model_list": [
diff --git a/resources/profiles/BBL/machine/Bambu Lab H2C 0.4 nozzle template machine_start_gcode.json b/resources/profiles/BBL/machine/Bambu Lab H2C 0.4 nozzle template machine_start_gcode.json
index 5132ccee2e..8d620f168d 100644
--- a/resources/profiles/BBL/machine/Bambu Lab H2C 0.4 nozzle template machine_start_gcode.json
+++ b/resources/profiles/BBL/machine/Bambu Lab H2C 0.4 nozzle template machine_start_gcode.json
@@ -2,5 +2,5 @@
"type": "machine",
"name": "Bambu Lab H2C 0.4 nozzle template machine_start_gcode",
"instantiation": "false",
- "machine_start_gcode": ";===== machine: H2C =========================\n;===== date: 20260608 =====================\n\n;M1002 set_flag extrude_cali_flag=1\n;M1002 set_flag g29_before_print_flag=1\n;M1002 set_flag auto_cali_toolhead_offset_flag=1\n;M1002 set_flag build_plate_detect_flag=1\n\nM993 A0 B0 C0 ; nozzle cam detection not allowed.\n\nM400\n;M73 P99\n\nM960 S10 P1 ; ext fan led\n\n;=====printer start sound ===================\nM17\nM400 S1\nM1006 S1\nM1006 A53 B9 L99 C53 D9 M99 E53 F9 N99\nM1006 A56 B9 L99 C56 D9 M99 E56 F9 N99\nM1006 A61 B9 L99 C61 D9 M99 E61 F9 N99\nM1006 A53 B9 L99 C53 D9 M99 E53 F9 N99\nM1006 A56 B9 L99 C56 D9 M99 E56 F9 N99\nM1006 A61 B18 L99 C61 D18 M99 E61 F18 N99\nM1006 W\n;=====printer start sound ===================\n\n;===== reset machine status =================\nM204 S10000\nM630 S0 P0\n\nG90\nM17 D ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM1002 set_gcode_claim_speed_level 5 ;Reset speed level\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nG29.1 Z{+0.0} ; clear z-trim value first\nM983.1 M1\nM901 D4\nM481 S0 ; turn off cutter pos comp\nG28.140 D0; reset pre-extrude z pos\n;===== reset machine status =================\n\nM620 M ;enable remap\nM620 N ;enable hotend remap\nM620 T0 ;print tmpr\nM620 T1 ;sn -> pos\nM620 T2 ;filament_id\n\n;===== start to heat heatbed & hotend==========\n\n M104 O-80 A\n M140 D[bed_temperature_initial_layer_single]\n\n;===== start to heat heatbead & hotend==========\n\n;===== avoid end stop =================\nG91\nG380 S2 Z42 F1200\nG380 S2 Z-12 F1200\nG90\n;===== avoid end stop =================\n\n;==== set airduct mode ====\n\n{if (overall_chamber_temperature >= 40)}\n\n M145 P1 ; set airduct mode to heating mode for heating\n M106 P2 S0 ; turn off auxiliary fan\n M106 P3 S0 ; turn off chamber fan\n\n{else}\n M145 P0 ; set airduct mode to cooling mode for cooling\n M106 P2 S178 ; turn on auxiliary fan for cooling\n M106 P3 S127 ; turn on chamber fan for cooling\n\n M1002 gcode_claim_action : 29\n M191 S0 ; wait for chamber temp\n M106 P2 S0 ; turn off auxiliary fan\n {if (min_vitrification_temperature <= 50)}\n {if (nozzle_diameter_at_nozzle_id[initial_nozzle_id] == 0.2)}\n M142 P1 R30 S35 T40 U0.3 V0.5 W0.8 O40 ; set PLA/TPU ND0.2 chamber autocooling\n {else}\n M142 P1 R30 S40 T45 U0.3 V0.5 W0.8 O45; set PLA/TPU ND0.4 chamber autocooling\n {endif}\n {else}\n {if (!is_all_bbl_filament)}\n M142 P1 R35 S40 T45 U0.3 V0.5 W0.8 O45 L1 ; set third-party PETG chamber autocooling\n {else}\n {if (nozzle_diameter_at_nozzle_id[initial_nozzle_id] == 0.2)}\n M142 P1 R35 S45 T50 U0.3 V0.5 W0.8 O50 L1 ; set PETG ND0.2 chamber autocooling\n {else}\n M142 P1 R35 S50 T55 U0.3 V0.5 W0.8 O55 L1 ; set PETG ND0.4 chamber autocooling\n {endif}\n {endif}\n {endif}\n{if(cooling_filter_enabled)}\nM145.2 P0 F0\n{else}\nM145.2 P0 F1\n{endif}\n{endif}\n;==== set airduct mode ====\n\n\n;====== cog noise reduction=================\nM982.2 S1 ; turn on cog noise reduction\n\n;===== first homing start =====\nM1002 gcode_claim_action : 13\n\nM640 S\nM640.1 R\nM641\nG28 X T300\nT1000\n\nG150.3\nM972 S24 P0 T2000 ; live-view camera foolproof\nM972 S46 P0 T5000 ; vortek anti-collision\nM640.1 S\nM640.4\n{if (first_non_support_filaments[0] != -1)}\nM640 S\nM640.8 T A{first_non_support_filaments[0]} H{first_non_support_hotend[0]}\nM640.7 L\nM641\n{endif}\n\n\n{if wipe_tower_center_pos_valid}\n M620.14 X[wipe_tower_center_pos_x] Y[wipe_tower_center_pos_y]\n{else}\n M620.14 X95.5 Y336\n{endif}\n\n\nG150.1 F18000 ; wipe mouth to avoid filament stick to heatbed\nG150.3 F18000\nM400 P200\n\nM1002 gcode_claim_action : 74 ; Heatbed surface foreign object detection\nM104 S0\n{if curr_bed_type==\"Textured PEI Plate\"}\nM972 S26 P0 C0\n{else}\nM972 S36 P0 C0 X1\n{endif}\nM972 S35 P0 C0\n\nM972 S41 P0 T5000 ; trash can anti-collision\n\nM1009 Q1 L1\nG91\nG380 S2 Z30 F1200 ; lower heatbed to move toolhead\nG90\nG1 X175 Y160 F30000\nG28 Z P0 T250\nM1009 Q1 L0\n\n\n;===== first homing end =====\n\n;===== detection start =====\n\nM1002 judge_flag build_plate_detect_flag\nM104 S0\nM622 S1\n ;M1002 gcode_claim_action : 11 ; Indentifying build plate type\n M972 S19 P0 C0 ; heatbed presence detection\n M972 S31 P0 T5000 ; toolhead camera dirty detection\n ;M1002 gcode_claim_action : 73 ; Build plate alignment detection\n M972 S34 P0 T5000 ; heatbed plate offset detection\nM623\n\nM1002 gcode_claim_action : 72 ; Hotend Type Detection\nT1001\nM972 S14 P0 T5000 ; nozzle type detection\n\nM104 S{nozzle_temperature_initial_layer[initial_no_support_filament_id]} T{filament_map[initial_no_support_filament_id] % 2} ; rise temp in advance\n\nG151 P{filament_map[initial_no_support_filament_id] % 2} M ; plug the heat nozzle\n\n{if max_print_z >= 145}\nM1002 gcode_claim_action : 75 ; Heatbed underside foreign object detection\nG3811 Z{max_print_z} ; Detect obstacles at the bottom of the heated bed\n{endif}\n\n;===== detection end =====\n\nM400\n;M73 P99\n\n;===== prepare print temperature and material ==========\nM400\nM211 X0 Y0 Z0 ;turn off soft endstop\nM975 S1 ; turn on input shaping\n\nG29.2 S0 ; avoid invalid abl data\n\n{if ((filament_type[initial_no_support_filament_id] == \"PLA\") || (filament_type[initial_no_support_filament_id] == \"PLA-CF\") || (filament_type[initial_no_support_filament_id] == \"PETG\")) && (nozzle_diameter_at_nozzle_id[initial_nozzle_id] == 0.2)}\nM620.10 A0 F74.8347 H{nozzle_diameter_at_nozzle_id[initial_nozzle_id]} T{flush_temperatures[initial_no_support_filament_id]} P{nozzle_temperature_initial_layer[initial_no_support_filament_id]} S1\nM620.10 A1 F74.8347 H{nozzle_diameter_at_nozzle_id[initial_nozzle_id]} T{flush_temperatures[initial_no_support_filament_id]} P{nozzle_temperature_initial_layer[initial_no_support_filament_id]} S1\n{else}\nM620.10 A0 F{flush_volumetric_speeds[initial_no_support_filament_id]/2.4053*60*0.8} H{nozzle_diameter_at_nozzle_id[initial_nozzle_id]} T{flush_temperatures[initial_no_support_filament_id]} P{nozzle_temperature_initial_layer[initial_no_support_filament_id]} S1\nM620.10 A1 F{flush_volumetric_speeds[initial_no_support_filament_id]/2.4053*60*0.8} H{nozzle_diameter_at_nozzle_id[initial_nozzle_id]} T{flush_temperatures[initial_no_support_filament_id]} P{nozzle_temperature_initial_layer[initial_no_support_filament_id]} S1\n{endif}\n\nM620.11 P1 I[initial_no_support_filament_id] B[initial_no_support_hotend] E0\n\n{if long_retraction_when_ec }\nM620.11 K1 I[initial_no_support_filament_id] B[initial_no_support_hotend] R{retraction_distance_when_ec} F{max((flush_volumetric_speeds[initial_no_support_filament_id]/2.4053*60), 200)}\n{else}\nM620.11 K0 I[initial_no_support_filament_id] B[initial_no_support_hotend] R0\n{endif}\n\nM628 S1\n{if filament_type[initial_no_support_filament_id] == \"TPU\"}\n M620.11 S0 L0 I[initial_no_support_filament_id] B[initial_no_support_hotend] E-{retraction_distances_when_cut[initial_no_support_filament_id]} F{flush_volumetric_speeds[initial_no_support_filament_id]/2.4053*60}\n{else}\n{if (filament_type[initial_no_support_filament_id] == \"PA\") || (filament_type[initial_no_support_filament_id] == \"PA-GF\")}\n M620.11 S1 L0 I[initial_no_support_filament_id] B[initial_no_support_hotend] R4 D2 E-{retraction_distances_when_cut[initial_no_support_filament_id]} F{flush_volumetric_speeds[initial_no_support_filament_id]/2.4053*60}\n{else}\n M620.11 S1 L0 I[initial_no_support_filament_id] B[initial_no_support_hotend] R10 D8 E-{retraction_distances_when_cut[initial_no_support_filament_id]} F{flush_volumetric_speeds[initial_no_support_filament_id]/2.4053*60}\n{endif}\n{endif}\nM629\n\nM620 S[initial_no_support_filament_id]A H[initial_no_support_hotend] ; switch material if AMS exist\nM1002 gcode_claim_action : 4\nM1002 set_filament_type:UNKNOWN\nM400\nT[initial_no_support_filament_id] H[initial_no_support_hotend]\nM400\nM628 S0\nM629\nM400\nM1002 set_filament_type:{filament_type[initial_no_support_filament_id]}\nM621 S[initial_no_support_filament_id]A\n\nM104 S{nozzle_temperature_initial_layer[initial_no_support_filament_id]}\nM400\nM106 P1 S0\n\nG91\nG1 Y-16 F60000\nG90\n\nG29.2 S1\n;===== prepare print temperature and material ==========\n\n\nM400\n;M73 P99\n\n;===== xy ofst cali start =====\n\nM1002 judge_flag auto_cali_toolhead_offset_flag\n\nM622 J2\n M1002 gcode_claim_action : 54\n M190 D[bed_temperature_initial_layer_single]\n\n M1002 gcode_claim_action : 39\n M620 D[initial_no_support_hotend]\n G383.3 U140 L{initial_no_support_filament_id}\nM623\n\nM622 J1\n M1002 gcode_claim_action : 54\n M190 D[bed_temperature_initial_layer_single]\n\n M1002 gcode_claim_action : 39\n M620 D[initial_no_support_hotend]\n G383 O2 U140 L{initial_no_support_filament_id}\nM623\n\n;===== xy ofst cali end =====\n\n;===== start to heat heatbed & hotend==========\n\n M1002 set_filament_type:{filament_type[initial_no_support_filament_id]}\n G150.3\n M104 S{nozzle_temperature_initial_layer[initial_no_support_filament_id]}\n M140 S[bed_temperature_initial_layer_single]\n\n ;===== set chamber temperature ==========\n {if (overall_chamber_temperature >= 40)}\n M145 P1 ; set airduct mode to heating mode\n M141 S[overall_chamber_temperature] ; Let Chamber begin to heat\n {endif}\n ;===== set chamber temperature ==========\n\n;===== start to heat heatbead & hotend==========\n\n\n\nM400\n;M73 P99\n\n;===== auto extrude cali start =========================\nM975 S1\nM1002 judge_flag extrude_cali_flag\n\nM622 J0\n M983.3 F{filament_max_volumetric_speed[initial_no_support_filament_id]/2.4} A0.4 ; cali dynamic extrusion compensation\nM623\n\nM622 J1\n M1002 set_filament_type:{filament_type[initial_no_support_filament_id]}\n M1002 gcode_claim_action : 8\n\n M109 S{nozzle_temperature[initial_no_support_filament_id]}\n\n G90\n M83\n M983.3 F{filament_max_volumetric_speed[initial_no_support_filament_id]/2.4} A0.4 ; cali dynamic extrusion compensation\n\n M400\n M106 P1 S255\n M400 S5\n M106 P1 S0\n G150.3\nM623\n\nM622 J2\n M1002 set_filament_type:{filament_type[initial_no_support_filament_id]}\n M1002 gcode_claim_action : 8\n\n M109 S{nozzle_temperature[initial_no_support_filament_id]}\n\n G90\n M83\n M983.3 F{filament_max_volumetric_speed[initial_no_support_filament_id]/2.4} A0.4 ; cali dynamic extrusion compensation\n\n M400\n M106 P1 S255\n M400 S5\n M106 P1 S0\n G150.3\nM623\n\n;===== auto extrude cali end =========================\n\n{if filament_type[initial_no_support_filament_id] == \"TPU\"}\n G150.2\n G150.1\n G150.2\n G150.1\n G150.2\n G150.1\n{else}\n G150.3\n M106 P1 S0\n M400 S2\n M109 S{nozzle_temperature[initial_no_support_filament_id]} ; wait tmpr to extrude\n M83\n {if(nozzle_diameter_at_nozzle_id[initial_nozzle_id] == 0.8)}\n G1 E60 F{filament_max_volumetric_speed[initial_no_support_filament_id]/2.4053*60}\n {else}\n G1 E45 F{filament_max_volumetric_speed[initial_no_support_filament_id]/2.4053*60}\n {endif}\n G1 E-3 F1800\n M400 P500\n G150.2\n G150.1\n{endif}\n\nG91\nG1 Y-16 F12000 ; move away from the trash bin\nG90\n\nM400\n;M73 P99\n\n;===== wipe right nozzle start =====\n\nM1002 gcode_claim_action : 14\n G150 T{nozzle_temperature_initial_layer[initial_no_support_filament_id]}\n {if (overall_chamber_temperature >= 40)}\n G150 T{nozzle_temperature_initial_layer[initial_no_support_filament_id] - 80}\n {endif}\nM106 S255 ; turn on fan to cool the nozzle\n\n;===== wipe left nozzle end =====\n\nM400\n;M73 P99\n\nM1002 judge_flag auto_cali_toolhead_offset_flag\nM622 J0\n G91\n G1 Z5 F1200\n G90\n M1012.7\n G383.7 U140 J0\nM623\n\n{if (overall_chamber_temperature >= 40)}\n M1002 gcode_claim_action : 49\n M191 S[overall_chamber_temperature] ; wait for chamber temp\n{endif}\n\nM400\n;M73 P99\n\n;===== bed leveling ==================================\n\nM1002 judge_flag g29_before_print_flag\n\nM190 S[bed_temperature_initial_layer_single]; ensure bed temp\nM109 S140 A\nM106 S0 ; turn off fan , too noisy\n\nG91\nG1 Z10 F1200\n{if (first_non_support_filaments[0] != -1) && filament_type[initial_no_support_filament_id] != \"TPU\"}\nM640 S\nM640.7 U\nM640.7 L\nM640.2 R1\nM641\n{endif}\nG90\nG1 X175 Y160 F30000\n\nM622 J1\n M1002 gcode_claim_action : 1\n G29.20 A3\n G29 A1 O X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]} R\n M400\nM623\n\nM622 J2\n M1002 gcode_claim_action : 1\n {if has_tpu_in_first_layer}\n G29.20 A3\n G29 A1 O X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]} R\n {else}\n G29.20 A4\n G29 A2 O X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]} R\n {endif}\n M400\nM623\n\nM622 J0\n G28 R\nM623\n\n;===== bed leveling end ================================\n\nG39.1 ; cali nozzle wrapped detection pos\n\nG90\nG1 Z5 F1200\nG1 X270 Y-0.5 F60000\nG28.140 S0 ; cali pre-extrude z pos\n\n;============switch again==================\nM211 X0 Y0 Z0 ;turn off soft endstop\nG91\nG1 Z6 F1200\nG90\nM1002 set_filament_type:{filament_type[initial_no_support_filament_id]}\nM620 S[initial_no_support_filament_id]A H[initial_no_support_hotend]\nM400\nT[initial_no_support_filament_id] H[initial_no_support_hotend]\nM400\nM628 S0\nM629\nM400\nM621 S[initial_no_support_filament_id]A\n\n;============switch again==================\n\nM400\n;M73 P99\n\nM141 S[overall_chamber_temperature]\n\n;===== mech mode sweep start =====\n M1002 gcode_claim_action : 3\n\n G90\n G1 Z5 F1200\n G1 X165 Y160 F20000\n M400 P200\n\n M970.3 Q1 A5 K0 O1\n M974 Q1 S2 P0\n\n M970.3 Q0 A5 K0 O1\n M974 Q0 S2 P0\n\n M970.2 Q2 K0 W38 Z0.01\n M974 Q2 S2 P0\n\n M975 S1\n;===== mech mode sweep end =====\n\n;===== wait temperature reaching the reference value =======\n\nM140 S[bed_temperature_initial_layer_single]\nM190 S[bed_temperature_initial_layer_single]\n\n ;========turn off light and fans =============\n M960 S1 P0 ; turn off laser\n M960 S2 P0 ; turn off laser\n M106 S0 ; turn off fan\n M106 P2 S0 ; turn off big fan\n ;==== set ext toodhead cooling fan ====\n {if (min_vitrification_temperature <= 50)}\n M106 P9 S255\n {endif}\n ;============set motor current==================\n M400 S1\n\n;===== wait temperature reaching the reference value =======\n\nM400\n;M73 P99\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n {if curr_bed_type==\"Textured PEI Plate\"}\n {if nozzle_diameter_at_nozzle_id[initial_nozzle_id] == 0.2}\n G29.1 Z{-0.01} ; for Textured PEI Plate\n {else}\n G29.1 Z{-0.02} ; for Textured PEI Plate\n {endif}\n {else}\n {if nozzle_diameter_at_nozzle_id[initial_nozzle_id] == 0.2}\n G29.1 Z{0.01}\n {endif}\n {endif}\nG150.1\n\nM975 S1 ; turn on mech mode supression\nM983.4 S1 ; turn on deformation compensation\nG29.2 S1 ; turn on pos comp\nG29.7 S1\n\nG90\nG1 Z5 F1200\nG1 Y295 F30000\nG1 Y265 F18000\n\n;===== nozzle load line ===============================\n G29.2 S1 ; ensure z comp turn on\n G90\n M83\n G1 Z5 F1200\n G1 X270 Y-0.5 F60000\n G28.14 R0\n G29.2 S0\n G91\n G1 Z0.8 F1200\n G90\n G1 X250 F60000\n M104 S{nozzle_temperature_initial_layer[initial_no_support_filament_id]}\n\n ========== record data ==========\n M1026\n M1012.8\n M1012.9\n G29.9\n ========== record data ==========\n\n M400 P50\n M500 D1\n M400 S3\n M109 S{nozzle_temperature_initial_layer[initial_no_support_filament_id]}\n M83\n{if nozzle_diameter_at_nozzle_id[initial_nozzle_id] == 0.8}\n G1 E5 F{filament_max_volumetric_speed[initial_no_support_filament_id]/2.4053*60}\n{endif}\n{if (filament_type[initial_no_support_filament_id] == \"TPU\")}\n G1 E5 F{filament_max_volumetric_speed[initial_no_support_filament_id]/2.4053*60}\n{endif}\n G1 E5 F{filament_max_volumetric_speed[initial_no_support_filament_id]/2.4053*60}\n G1 X290 E10 F{filament_max_volumetric_speed[initial_no_support_filament_id]/2.4053*60}\n G91\n G3 Z0.4 I1.217 J0 P1 F60000\n G90\n M83\n G29.2 S1 ; ensure z comp turn on\n;===== noozle load line end ===========================\n\nM400\n;M73 P99\n\nM993 A1 B1 C1 ; nozzle cam detection allowed.\n\n{if (filament_type[initial_no_support_filament_id] == \"TPU\")}\nM1015.3 S1;enable tpu clog detect\n{else}\nM1015.3 S0;disable tpu clog detect\n{endif}\n\n{if (filament_type[initial_no_support_filament_id] == \"PLA\") || (filament_type[initial_no_support_filament_id] == \"PETG\")\n || (filament_type[initial_no_support_filament_id] == \"PLA-CF\") || (filament_type[initial_no_support_filament_id] == \"PETG-CF\")}\nM1015.4 S1 K1 H{nozzle_diameter_at_nozzle_id[initial_nozzle_id]} ;enable E air printing detect\n{else}\nM1015.4 S0 K0 H{nozzle_diameter_at_nozzle_id[initial_nozzle_id]} ;disable E air printing detect\n{endif}\n\nM620.6 I[initial_no_support_filament_id] H[initial_no_support_hotend] W1 ;enable ams air printing detect\nM620 O1\n\nM211 Z1\nG29.99\nM1002 gcode_claim_action : 0\nM400\n"
+ "machine_start_gcode": ";===== machine: H2C =========================\n;===== date: 20260608 =====================\n\n;M1002 set_flag extrude_cali_flag=1\n;M1002 set_flag g29_before_print_flag=1\n;M1002 set_flag auto_cali_toolhead_offset_flag=1\n;M1002 set_flag build_plate_detect_flag=1\n\nM993 A0 B0 C0 ; nozzle cam detection not allowed.\n\nM400\n;M73 P99\n\nM960 S10 P1 ; ext fan led\n\n;=====printer start sound ===================\nM17\nM400 S1\nM1006 S1\nM1006 A53 B9 L99 C53 D9 M99 E53 F9 N99\nM1006 A56 B9 L99 C56 D9 M99 E56 F9 N99\nM1006 A61 B9 L99 C61 D9 M99 E61 F9 N99\nM1006 A53 B9 L99 C53 D9 M99 E53 F9 N99\nM1006 A56 B9 L99 C56 D9 M99 E56 F9 N99\nM1006 A61 B18 L99 C61 D18 M99 E61 F18 N99\nM1006 W\n;=====printer start sound ===================\n\n;===== reset machine status =================\nM204 S10000\nM630 S0 P0\n\nG90\nM17 D ; reset motor current to default\nM960 S5 P1 ; turn on logo lamp\nG90\nM1002 set_gcode_claim_speed_level 5 ;Reset speed level\nM220 S100 ;Reset Feedrate\nM221 S100 ;Reset Flowrate\nM73.2 R1.0 ;Reset left time magnitude\nG29.1 Z{+0.0} ; clear z-trim value first\nM983.1 M1\nM901 D4\nM481 S0 ; turn off cutter pos comp\nG28.140 D0; reset pre-extrude z pos\n;===== reset machine status =================\n\nM620 M ;enable remap\nM620 N ;enable hotend remap\nM620 T0 ;print tmpr\nM620 T1 ;sn -> pos\nM620 T2 ;filament_id\n\n;===== start to heat heatbed & hotend==========\n\n M104 O-80 A\n M140 D[bed_temperature_initial_layer_single]\n\n;===== start to heat heatbead & hotend==========\n\n;===== avoid end stop =================\nG91\nG380 S2 Z42 F1200\nG380 S2 Z-12 F1200\nG90\n;===== avoid end stop =================\n\n;==== set airduct mode ====\n\n{if (overall_chamber_temperature >= 40)}\n\n M145 P1 ; set airduct mode to heating mode for heating\n M106 P2 S0 ; turn off auxiliary fan\n M106 P3 S0 ; turn off chamber fan\n\n{else}\n M145 P0 ; set airduct mode to cooling mode for cooling\n M106 P2 S178 ; turn on auxiliary fan for cooling\n M106 P3 S127 ; turn on chamber fan for cooling\n\n M1002 gcode_claim_action : 29\n M191 S0 ; wait for chamber temp\n M106 P2 S0 ; turn off auxiliary fan\n {if (min_vitrification_temperature <= 50)}\n {if (nozzle_diameter_at_nozzle_id[initial_nozzle_id] == 0.2)}\n M142 P1 R30 S35 T40 U0.3 V0.5 W0.8 O40 ; set PLA/TPU ND0.2 chamber autocooling\n {else}\n M142 P1 R30 S40 T45 U0.3 V0.5 W0.8 O45; set PLA/TPU ND0.4 chamber autocooling\n {endif}\n {else}\n {if (!is_all_bbl_filament)}\n M142 P1 R35 S40 T45 U0.3 V0.5 W0.8 O45 L1 ; set third-party PETG chamber autocooling\n {else}\n {if (nozzle_diameter_at_nozzle_id[initial_nozzle_id] == 0.2)}\n M142 P1 R35 S45 T50 U0.3 V0.5 W0.8 O50 L1 ; set PETG ND0.2 chamber autocooling\n {else}\n M142 P1 R35 S50 T55 U0.3 V0.5 W0.8 O55 L1 ; set PETG ND0.4 chamber autocooling\n {endif}\n {endif}\n {endif}\n{if(cooling_filter_enabled)}\nM145.2 P0 F0\n{else}\nM145.2 P0 F1\n{endif}\n{endif}\n;==== set airduct mode ====\n\n\n;====== cog noise reduction=================\nM982.2 S1 ; turn on cog noise reduction\n\n;===== first homing start =====\nM1002 gcode_claim_action : 13\n\nM640 S\nM640.1 R\nM641\nG28 X T300\nT1000\n\nG150.3\nM972 S24 P0 T2000 ; live-view camera foolproof\nM972 S46 P0 T5000 ; vortek anti-collision\nM640.1 S\nM640.4\n{if (first_non_support_filaments[0] != -1)}\nM640 S\nM640.8 T A{first_non_support_filaments[0]} H{first_non_support_hotend[0]}\nM640.7 L\nM641\n{endif}\n\n\n{if wipe_tower_center_pos_valid}\n M620.14 X[wipe_tower_center_pos_x] Y[wipe_tower_center_pos_y]\n{else}\n M620.14 X95.5 Y336\n{endif}\n\n\nG150.1 F18000 ; wipe mouth to avoid filament stick to heatbed\nG150.3 F18000\nM400 P200\n\nM1002 gcode_claim_action : 74 ; Heatbed surface foreign object detection\nM104 S0\n{if curr_bed_type==\"Textured PEI Plate\"}\nM972 S26 P0 C0\n{else}\nM972 S36 P0 C0 X1\n{endif}\nM972 S35 P0 C0\n\nM972 S41 P0 T5000 ; trash can anti-collision\n\nM1009 Q1 L1\nG91\nG380 S2 Z30 F1200 ; lower heatbed to move toolhead\nG90\nG1 X175 Y160 F30000\nG28 Z P0 T250\nM1009 Q1 L0\n\n\n;===== first homing end =====\n\n;===== detection start =====\n\nM1002 judge_flag build_plate_detect_flag\nM104 S0\nM622 S1\n ;M1002 gcode_claim_action : 11 ; Indentifying build plate type\n M972 S19 P0 C0 ; heatbed presence detection\n M972 S31 P0 T5000 ; toolhead camera dirty detection\n ;M1002 gcode_claim_action : 73 ; Build plate alignment detection\n M972 S34 P0 T5000 ; heatbed plate offset detection\nM623\n\nM1002 gcode_claim_action : 72 ; Hotend Type Detection\nT1001\nM972 S14 P0 T5000 ; nozzle type detection\n\nM104 S{nozzle_temperature_initial_layer[initial_no_support_filament_id]} T{filament_map[initial_no_support_filament_id] % 2} ; rise temp in advance\n\nG151 P{filament_map[initial_no_support_filament_id] % 2} M ; plug the heat nozzle\n\n{if max_print_z >= 145}\nM1002 gcode_claim_action : 75 ; Heatbed underside foreign object detection\nG3811 Z{max_print_z} ; Detect obstacles at the bottom of the heated bed\n{endif}\n\n;===== detection end =====\n\nM400\n;M73 P99\n\n;===== prepare print temperature and material ==========\nM400\nM211 X0 Y0 Z0 ;turn off soft endstop\nM975 S1 ; turn on input shaping\n\nG29.2 S0 ; avoid invalid abl data\n\n{if ((filament_type[initial_no_support_filament_id] == \"PLA\") || (filament_type[initial_no_support_filament_id] == \"PLA-CF\") || (filament_type[initial_no_support_filament_id] == \"PETG\")) && (nozzle_diameter_at_nozzle_id[initial_nozzle_id] == 0.2)}\nM620.10 A0 F74.8347 H{nozzle_diameter_at_nozzle_id[initial_nozzle_id]} T{flush_temperatures[initial_no_support_filament_id]} P{nozzle_temperature_initial_layer[initial_no_support_filament_id]} S1\nM620.10 A1 F74.8347 H{nozzle_diameter_at_nozzle_id[initial_nozzle_id]} T{flush_temperatures[initial_no_support_filament_id]} P{nozzle_temperature_initial_layer[initial_no_support_filament_id]} S1\n{else}\nM620.10 A0 F{flush_volumetric_speeds[initial_no_support_filament_id]/2.4053*60*0.8} H{nozzle_diameter_at_nozzle_id[initial_nozzle_id]} T{flush_temperatures[initial_no_support_filament_id]} P{nozzle_temperature_initial_layer[initial_no_support_filament_id]} S1\nM620.10 A1 F{flush_volumetric_speeds[initial_no_support_filament_id]/2.4053*60*0.8} H{nozzle_diameter_at_nozzle_id[initial_nozzle_id]} T{flush_temperatures[initial_no_support_filament_id]} P{nozzle_temperature_initial_layer[initial_no_support_filament_id]} S1\n{endif}\n\nM620.11 P1 I[initial_no_support_filament_id] B[initial_no_support_hotend] E0\n\n{if long_retraction_when_ec }\nM620.11 K1 I[initial_no_support_filament_id] B[initial_no_support_hotend] R{retraction_distance_when_ec} F{max((flush_volumetric_speeds[initial_no_support_filament_id]/2.4053*60), 200)}\n{else}\nM620.11 K0 I[initial_no_support_filament_id] B[initial_no_support_hotend] R0\n{endif}\n\nM628 S1\n{if filament_type[initial_no_support_filament_id] == \"TPU\"}\n M620.11 S0 L0 I[initial_no_support_filament_id] B[initial_no_support_hotend] E-{retraction_distances_when_cut[initial_no_support_filament_id]} F{flush_volumetric_speeds[initial_no_support_filament_id]/2.4053*60}\n{else}\n{if (filament_type[initial_no_support_filament_id] == \"PA\") || (filament_type[initial_no_support_filament_id] == \"PA-GF\")}\n M620.11 S1 L0 I[initial_no_support_filament_id] B[initial_no_support_hotend] R4 D2 E-{retraction_distances_when_cut[initial_no_support_filament_id]} F{flush_volumetric_speeds[initial_no_support_filament_id]/2.4053*60}\n{else}\n M620.11 S1 L0 I[initial_no_support_filament_id] B[initial_no_support_hotend] R10 D8 E-{retraction_distances_when_cut[initial_no_support_filament_id]} F{flush_volumetric_speeds[initial_no_support_filament_id]/2.4053*60}\n{endif}\n{endif}\nM629\n\nM620 S[initial_no_support_filament_id]A H[initial_no_support_hotend] ; switch material if AMS exist\nM1002 gcode_claim_action : 4\nM1002 set_filament_type:UNKNOWN\nM400\nT[initial_no_support_filament_id] H[initial_no_support_hotend]\nM400\nM628 S0\nM629\nM400\nM1002 set_filament_type:{filament_type[initial_no_support_filament_id]}\nM621 S[initial_no_support_filament_id]A\n\nM104 S{nozzle_temperature_initial_layer[initial_no_support_filament_id]}\nM400\nM106 P1 S0\n\nG91\nG1 Y-16 F60000\nG90\n\nG29.2 S1\n;===== prepare print temperature and material ==========\n\n\nM400\n;M73 P99\n\n;===== xy ofst cali start =====\n\nM1002 judge_flag auto_cali_toolhead_offset_flag\n\nM622 J2\n M1002 gcode_claim_action : 54\n M190 D[bed_temperature_initial_layer_single]\n\n M1002 gcode_claim_action : 39\n M620 D[initial_no_support_hotend]\n G383.3 U140 L{initial_no_support_filament_id}\nM623\n\nM622 J1\n M1002 gcode_claim_action : 54\n M190 D[bed_temperature_initial_layer_single]\n\n M1002 gcode_claim_action : 39\n M620 D[initial_no_support_hotend]\n G383 O2 U140 L{initial_no_support_filament_id}\nM623\n\n;===== xy ofst cali end =====\n\n;===== start to heat heatbed & hotend==========\n\n M1002 set_filament_type:{filament_type[initial_no_support_filament_id]}\n G150.3\n M104 S{nozzle_temperature_initial_layer[initial_no_support_filament_id]}\n M140 S[bed_temperature_initial_layer_single]\n\n ;===== set chamber temperature ==========\n {if (overall_chamber_temperature >= 40)}\n M145 P1 ; set airduct mode to heating mode\n M141 S[overall_chamber_temperature] ; Let Chamber begin to heat\n {endif}\n ;===== set chamber temperature ==========\n\n;===== start to heat heatbead & hotend==========\n\n\n\nM400\n;M73 P99\n\n;===== auto extrude cali start =========================\nM975 S1\nM1002 judge_flag extrude_cali_flag\n\nM622 J0\n M983.3 F{filament_max_volumetric_speed[initial_no_support_filament_id]/2.4} A0.4 ; cali dynamic extrusion compensation\nM623\n\nM622 J1\n M1002 set_filament_type:{filament_type[initial_no_support_filament_id]}\n M1002 gcode_claim_action : 8\n\n M109 S{nozzle_temperature[initial_no_support_filament_id]}\n\n G90\n M83\n M983.3 F{filament_max_volumetric_speed[initial_no_support_filament_id]/2.4} A0.4 ; cali dynamic extrusion compensation\n\n M400\n M106 P1 S255\n M400 S5\n M106 P1 S0\n G150.3\nM623\n\nM622 J2\n M1002 set_filament_type:{filament_type[initial_no_support_filament_id]}\n M1002 gcode_claim_action : 8\n\n M109 S{nozzle_temperature[initial_no_support_filament_id]}\n\n G90\n M83\n M983.3 F{filament_max_volumetric_speed[initial_no_support_filament_id]/2.4} A0.4 ; cali dynamic extrusion compensation\n\n M400\n M106 P1 S255\n M400 S5\n M106 P1 S0\n G150.3\nM623\n\n;===== auto extrude cali end =========================\n\n{if filament_type[initial_no_support_filament_id] == \"TPU\"}\n G150.2\n G150.1\n G150.2\n G150.1\n G150.2\n G150.1\n{else}\n G150.3\n M106 P1 S0\n M400 S2\n M109 S{nozzle_temperature[initial_no_support_filament_id]} ; wait tmpr to extrude\n M83\n {if(nozzle_diameter_at_nozzle_id[initial_nozzle_id] == 0.8)}\n G1 E60 F{filament_max_volumetric_speed[initial_no_support_filament_id]/2.4053*60}\n {else}\n G1 E45 F{filament_max_volumetric_speed[initial_no_support_filament_id]/2.4053*60}\n {endif}\n G1 E-3 F1800\n M400 P500\n G150.2\n G150.1\n{endif}\n\nG91\nG1 Y-16 F12000 ; move away from the trash bin\nG90\n\nM400\n;M73 P99\n\n;===== wipe right nozzle start =====\n\nM1002 gcode_claim_action : 14\n G150 T{nozzle_temperature_initial_layer[initial_no_support_filament_id]}\n {if (overall_chamber_temperature >= 40)}\n G150 T{nozzle_temperature_initial_layer[initial_no_support_filament_id] - 80}\n {endif}\nM106 S255 ; turn on fan to cool the nozzle\n\n;===== wipe left nozzle end =====\n\nM400\n;M73 P99\n\nM1002 judge_flag auto_cali_toolhead_offset_flag\nM622 J0\n G91\n G1 Z5 F1200\n G90\n M1012.7\n G383.7 U140 J0\nM623\n\n{if (overall_chamber_temperature >= 40)}\n M1002 gcode_claim_action : 49\n M191 S[overall_chamber_temperature] ; wait for chamber temp\n{endif}\n\nM400\n;M73 P99\n\n;===== bed leveling ==================================\n\nM1002 judge_flag g29_before_print_flag\n\nM190 S[bed_temperature_initial_layer_single]; ensure bed temp\nM109 S140 A\nM106 S0 ; turn off fan , too noisy\n\nG91\nG1 Z10 F1200\n{if (first_non_support_filaments[0] != -1) && filament_type[initial_no_support_filament_id] != \"TPU\"}\nM640 S\nM640.7 U\nM640.7 L\nM640.2 R1\nM641\n{endif}\nG90\nG1 X175 Y160 F30000\n\nM622 J1\n M1002 gcode_claim_action : 1\n G29.20 A3\n G29 A1 O X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]} R\n M400\nM623\n\nM622 J2\n M1002 gcode_claim_action : 1\n {if has_tpu_in_first_layer}\n G29.20 A3\n G29 A1 O X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]} R\n {else}\n G29.20 A4\n G29 A2 O X{first_layer_print_min[0]} Y{first_layer_print_min[1]} I{first_layer_print_size[0]} J{first_layer_print_size[1]} R\n {endif}\n M400\nM623\n\nM622 J0\n G28 R\nM623\n\n;===== bed leveling end ================================\n\nG39.1 ; cali nozzle wrapped detection pos\n\nG90\nG1 Z5 F1200\nG1 X270 Y-0.5 F60000\nG28.140 S0 ; cali pre-extrude z pos\n\n;============switch again==================\nM211 X0 Y0 Z0 ;turn off soft endstop\nG91\nG1 Z6 F1200\nG90\nM1002 set_filament_type:{filament_type[initial_no_support_filament_id]}\nM620 S[initial_no_support_filament_id]A H[initial_no_support_hotend]\nM400\nT[initial_no_support_filament_id] H[initial_no_support_hotend]\nM400\nM628 S0\nM629\nM400\nM621 S[initial_no_support_filament_id]A\n\n;============switch again==================\n\nM400\n;M73 P99\n\nM141 S[overall_chamber_temperature]\n\n;===== mech mode sweep start =====\n M1002 gcode_claim_action : 3\n\n G90\n G1 Z5 F1200\n G1 X165 Y160 F20000\n M400 P200\n\n M970.3 Q1 A5 K0 O1\n M974 Q1 S2 P0\n\n M970.3 Q0 A5 K0 O1\n M974 Q0 S2 P0\n\n M970.2 Q2 K0 W38 Z0.01\n M974 Q2 S2 P0\n\n M975 S1\n;===== mech mode sweep end =====\n\n;===== wait temperature reaching the reference value =======\n\nM140 S[bed_temperature_initial_layer_single]\nM190 S[bed_temperature_initial_layer_single]\n\n ;========turn off light and fans =============\n M960 S1 P0 ; turn off laser\n M960 S2 P0 ; turn off laser\n M106 S0 ; turn off fan\n M106 P2 S0 ; turn off big fan\n ;==== set ext toodhead cooling fan ====\n {if (min_vitrification_temperature <= 50)}\n M106 P9 S255\n {endif}\n ;============set motor current==================\n M400 S1\n\n;===== wait temperature reaching the reference value =======\n\nM400\n;M73 P99\n\n;===== for Textured PEI Plate , lower the nozzle as the nozzle was touching topmost of the texture when homing ==\n {if curr_bed_type==\"Textured PEI Plate\"}\n {if nozzle_diameter_at_nozzle_id[initial_nozzle_id] == 0.2}\n G29.1 Z{-0.01} ; for Textured PEI Plate\n {else}\n G29.1 Z{-0.02} ; for Textured PEI Plate\n {endif}\n {else}\n {if nozzle_diameter_at_nozzle_id[initial_nozzle_id] == 0.2}\n G29.1 Z{0.01}\n {endif}\n {endif}\nG150.1\n\nM975 S1 ; turn on mech mode supression\nM983.4 S1 ; turn on deformation compensation\nG29.2 S1 ; turn on pos comp\nG29.7 S1\n\nG90\nG1 Z5 F1200\nG1 Y295 F30000\nG1 Y265 F18000\n\n;===== nozzle load line ===============================\n G29.2 S1 ; ensure z comp turn on\n G90\n M83\n G1 Z5 F1200\n G1 X270 Y-0.5 F60000\n G28.14 R0\n G29.2 S0\n G91\n G1 Z0.8 F1200\n G90\n G1 X250 F60000\n M104 S{nozzle_temperature_initial_layer[initial_no_support_filament_id]}\n\n ;========== record data ==========\n M1026\n M1012.8\n M1012.9\n G29.9\n ;========== record data ==========\n\n M400 P50\n M500 D1\n M400 S3\n M109 S{nozzle_temperature_initial_layer[initial_no_support_filament_id]}\n M83\n{if nozzle_diameter_at_nozzle_id[initial_nozzle_id] == 0.8}\n G1 E5 F{filament_max_volumetric_speed[initial_no_support_filament_id]/2.4053*60}\n{endif}\n{if (filament_type[initial_no_support_filament_id] == \"TPU\")}\n G1 E5 F{filament_max_volumetric_speed[initial_no_support_filament_id]/2.4053*60}\n{endif}\n G1 E5 F{filament_max_volumetric_speed[initial_no_support_filament_id]/2.4053*60}\n G1 X290 E10 F{filament_max_volumetric_speed[initial_no_support_filament_id]/2.4053*60}\n G91\n G3 Z0.4 I1.217 J0 P1 F60000\n G90\n M83\n G29.2 S1 ; ensure z comp turn on\n;===== noozle load line end ===========================\n\nM400\n;M73 P99\n\nM993 A1 B1 C1 ; nozzle cam detection allowed.\n\n{if (filament_type[initial_no_support_filament_id] == \"TPU\")}\nM1015.3 S1;enable tpu clog detect\n{else}\nM1015.3 S0;disable tpu clog detect\n{endif}\n\n{if (filament_type[initial_no_support_filament_id] == \"PLA\") || (filament_type[initial_no_support_filament_id] == \"PETG\")\n || (filament_type[initial_no_support_filament_id] == \"PLA-CF\") || (filament_type[initial_no_support_filament_id] == \"PETG-CF\")}\nM1015.4 S1 K1 H{nozzle_diameter_at_nozzle_id[initial_nozzle_id]} ;enable E air printing detect\n{else}\nM1015.4 S0 K0 H{nozzle_diameter_at_nozzle_id[initial_nozzle_id]} ;disable E air printing detect\n{endif}\n\nM620.6 I[initial_no_support_filament_id] H[initial_no_support_hotend] W1 ;enable ams air printing detect\nM620 O1\n\nM211 Z1\nG29.99\nM1002 gcode_claim_action : 0\nM400\n"
}
diff --git a/resources/profiles/Qidi.json b/resources/profiles/Qidi.json
index 4b6496df31..dcb39ee957 100644
--- a/resources/profiles/Qidi.json
+++ b/resources/profiles/Qidi.json
@@ -1,6 +1,6 @@
{
"name": "Qidi",
- "version": "02.04.00.16",
+ "version": "02.04.00.17",
"force_update": "0",
"description": "Qidi configurations",
"machine_model_list": [
diff --git a/resources/profiles/Qidi/machine/Qidi Q1 Pro 0.4 nozzle.json b/resources/profiles/Qidi/machine/Qidi Q1 Pro 0.4 nozzle.json
index bd2398ae7a..30db0fc68b 100644
--- a/resources/profiles/Qidi/machine/Qidi Q1 Pro 0.4 nozzle.json
+++ b/resources/profiles/Qidi/machine/Qidi Q1 Pro 0.4 nozzle.json
@@ -83,7 +83,7 @@
"extruder_clearance_height_to_lid": "120",
"layer_change_gcode": ";BEFORE_LAYER_CHANGE\n;[layer_z]\nLOG_Z\nG92 E0\n",
"machine_end_gcode": "M141 S0\nM104 S0\nM140 S0\nG1 E-3 F1800\nG0 Z{min(max_print_height, max_layer_z + 3)} F600\nG0 X0 Y0 F12000\n{if max_layer_z < max_print_height / 2}G1 Z{max_print_height / 2 + 10} F600{else}G1 Z{min(max_print_height, max_layer_z + 3)}{endif}",
- "machine_start_gcode": "PRINT_START BED=[hot_plate_temp_initial_layer] HOTEND=[nozzle_temperature_initial_layer] CHAMBER=[chamber_temperature]\nM83\nM140 S[hot_plate_temp_initial_layer]\nM104 S[nozzle_temperature_initial_layer]\nG4 P3000\nG0 X{max((min(print_bed_max[0], first_layer_print_min[0] + 80) - 85),0)} Y{max((min(print_bed_max[1] - 5, first_layer_print_min[1] + 80) - 85), 0)} Z5 F6000\nG0 Z[initial_layer_print_height] F600\nG1 E3 F1800\nG1 X{(min(print_bed_max[0], first_layer_print_min[0] + 80))} E{85 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\nG1 Y{max((min(print_bed_max[1] - 5, first_layer_print_min[1] + 80) - 85), 0) + 2} E{2 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\nG1 X{max((min(print_bed_max[0], first_layer_print_min[0] + 80) - 85), 0)} E{85 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\nG1 Y{max((min(print_bed_max[1] - 5, first_layer_print_min[1] + 80) - 85), 0) + 85} E{83 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\nG1 X{max((min(print_bed_max[0], first_layer_print_min[0] + 80) - 85), 0) + 2} E{2 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\nG1 Y{max((min(print_bed_max[1] - 5, first_layer_print_min[1] + 80) - 85), 0) + 3} E{82 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\nG1 X{max((min(print_bed_max[0], first_layer_print_min[0] + 80) - 85), 0) + 3} Z0\nG1 X{max((min(print_bed_max[0], first_layer_print_min[0] + 80) - 85), 0) + 6}\nG1 Z1 F600\n",
+ "machine_start_gcode": "PRINT_START BED=[bed_temperature_initial_layer_single] HOTEND=[nozzle_temperature_initial_layer] CHAMBER=[chamber_temperature]\nM83\nM140 S[bed_temperature_initial_layer_single]\nM104 S[nozzle_temperature_initial_layer]\nG4 P3000\nG0 X{max((min(print_bed_max[0], first_layer_print_min[0] + 80) - 85),0)} Y{max((min(print_bed_max[1] - 5, first_layer_print_min[1] + 80) - 85), 0)} Z5 F6000\nG0 Z[initial_layer_print_height] F600\nG1 E3 F1800\nG1 X{(min(print_bed_max[0], first_layer_print_min[0] + 80))} E{85 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\nG1 Y{max((min(print_bed_max[1] - 5, first_layer_print_min[1] + 80) - 85), 0) + 2} E{2 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\nG1 X{max((min(print_bed_max[0], first_layer_print_min[0] + 80) - 85), 0)} E{85 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\nG1 Y{max((min(print_bed_max[1] - 5, first_layer_print_min[1] + 80) - 85), 0) + 85} E{83 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\nG1 X{max((min(print_bed_max[0], first_layer_print_min[0] + 80) - 85), 0) + 2} E{2 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\nG1 Y{max((min(print_bed_max[1] - 5, first_layer_print_min[1] + 80) - 85), 0) + 3} E{82 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\nG1 X{max((min(print_bed_max[0], first_layer_print_min[0] + 80) - 85), 0) + 3} Z0\nG1 X{max((min(print_bed_max[0], first_layer_print_min[0] + 80) - 85), 0) + 6}\nG1 Z1 F600\n",
"thumbnails_format": "PNG",
"default_filament_profile": [
"Generic PLA @Qidi Q1 Pro 0.4 nozzle"
diff --git a/resources/profiles/Qidi/machine/Qidi X-CF Pro 0.4 nozzle.json b/resources/profiles/Qidi/machine/Qidi X-CF Pro 0.4 nozzle.json
index a41e2b6a11..968f7f63a9 100644
--- a/resources/profiles/Qidi/machine/Qidi X-CF Pro 0.4 nozzle.json
+++ b/resources/profiles/Qidi/machine/Qidi X-CF Pro 0.4 nozzle.json
@@ -100,7 +100,7 @@
"default_filament_profile": [
"Generic PLA @Qidi"
],
- "machine_start_gcode": "G28\nM140 S[hot_plate_temp_initial_layer]\nM190 S[hot_plate_temp_initial_layer]\nM109 S[nozzle_temperature_initial_layer]\nG92 E-19\nG0 Y5 Z0.3 F3600\nG1 X5 E0 F2400\n",
+ "machine_start_gcode": "G28\nM140 S[bed_temperature_initial_layer_single]\nM190 S[bed_temperature_initial_layer_single]\nM109 S[nozzle_temperature_initial_layer]\nG92 E-19\nG0 Y5 Z0.3 F3600\nG1 X5 E0 F2400\n",
"machine_end_gcode": "M104 S0\nM140 S0\n;Retract the filament\nG92 E0\nG1 E-3 F300\nG28\nM84\n",
"scan_first_layer": "0"
}
diff --git a/resources/profiles/Qidi/machine/fdm_qidi_x3_common.json b/resources/profiles/Qidi/machine/fdm_qidi_x3_common.json
index 9796856379..8fe450c3c6 100644
--- a/resources/profiles/Qidi/machine/fdm_qidi_x3_common.json
+++ b/resources/profiles/Qidi/machine/fdm_qidi_x3_common.json
@@ -24,7 +24,7 @@
"210x210/COLPIC",
"110x110/PNG"
],
- "machine_start_gcode": "PRINT_START\nG28\nM141 S0\nG0 Z50 F600\nM190 S[hot_plate_temp_initial_layer]\nG28 Z\nG29; mesh bed leveling ,comment this code to close it\nG0 X0 Y0 Z50 F6000\nM141 S{overall_chamber_temperature}\nM109 S[nozzle_temperature_initial_layer]\nM106 P3 S255\nM83\nG4 P3000\nG0 X{max((min(print_bed_max[0], first_layer_print_min[0] + 80) - 85),0)} Y{max((min(print_bed_max[1], first_layer_print_min[1] + 80) - 85),0)} Z5 F6000\nG0 Z[initial_layer_print_height] F600\nG1 E3 F1800\nG1 X{(min(print_bed_max[0], first_layer_print_min[0] + 80))} E{85 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\nG1 Y{max((min(print_bed_max[1], first_layer_print_min[1] + 80) - 85),0) + 2} E{2 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\nG1 X{max((min(print_bed_max[0], first_layer_print_min[0] + 80) - 85),0)} E{85 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\nG1 Y{max((min(print_bed_max[1], first_layer_print_min[1] + 80) - 85),0) + 85} E{83 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\nG1 X{max((min(print_bed_max[0], first_layer_print_min[0] + 80) - 85),0) + 2} E{2 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\nG1 Y{max((min(print_bed_max[1], first_layer_print_min[1] + 80) - 85),0) + 3} E{82 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\nG1 X{max((min(print_bed_max[0], first_layer_print_min[0] + 80) - 85),0) + 12} E{-10 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\nG1 E{10 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\n",
+ "machine_start_gcode": "PRINT_START\nG28\nM141 S0\nG0 Z50 F600\nM190 S[bed_temperature_initial_layer_single]\nG28 Z\nG29; mesh bed leveling ,comment this code to close it\nG0 X0 Y0 Z50 F6000\nM141 S{overall_chamber_temperature}\nM109 S[nozzle_temperature_initial_layer]\nM106 P3 S255\nM83\nG4 P3000\nG0 X{max((min(print_bed_max[0], first_layer_print_min[0] + 80) - 85),0)} Y{max((min(print_bed_max[1], first_layer_print_min[1] + 80) - 85),0)} Z5 F6000\nG0 Z[initial_layer_print_height] F600\nG1 E3 F1800\nG1 X{(min(print_bed_max[0], first_layer_print_min[0] + 80))} E{85 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\nG1 Y{max((min(print_bed_max[1], first_layer_print_min[1] + 80) - 85),0) + 2} E{2 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\nG1 X{max((min(print_bed_max[0], first_layer_print_min[0] + 80) - 85),0)} E{85 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\nG1 Y{max((min(print_bed_max[1], first_layer_print_min[1] + 80) - 85),0) + 85} E{83 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\nG1 X{max((min(print_bed_max[0], first_layer_print_min[0] + 80) - 85),0) + 2} E{2 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\nG1 Y{max((min(print_bed_max[1], first_layer_print_min[1] + 80) - 85),0) + 3} E{82 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\nG1 X{max((min(print_bed_max[0], first_layer_print_min[0] + 80) - 85),0) + 12} E{-10 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\nG1 E{10 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\n",
"machine_end_gcode": "M141 S0\nM104 S0\nM140 S0\nG1 E-3 F1800\nG0 Z{min(max_print_height, max_layer_z + 3)} F600\nG0 X0 Y0 F12000\n{if max_layer_z < max_print_height / 2}G1 Z{max_print_height / 2 + 10} F600{else}G1 Z{min(max_print_height, max_layer_z + 3)}{endif}",
"scan_first_layer": "0"
}
diff --git a/resources/shaders/110/texture_displacement_shaded.fs b/resources/shaders/110/texture_displacement_shaded.fs
index 0b9192749c..93449af5d4 100644
--- a/resources/shaders/110/texture_displacement_shaded.fs
+++ b/resources/shaders/110/texture_displacement_shaded.fs
@@ -72,17 +72,21 @@ varying float weight;
varying float island_active;
varying vec2 vertex_uv;
-// The cylinder's own frame, built exactly as libslic3r's project_cylindrical() builds it - including
-// the handedness, which comes out left-handed for an axis of +Z. Copied rather than "corrected", so
-// the preview wraps the texture the same way round as the bake.
+// The cylinder's own frame, built exactly as libslic3r's project_cylindrical() builds it - right
+// handed, so the angle taken from it grows anticlockwise about the axis, which seen from outside the
+// cylinder is to the viewer's right rather than mirrored.
void cylinder_frame(out vec3 up, out vec3 right, out vec3 fwd)
{
up = (length(patch_axis) > 1e-8) ? normalize(patch_axis) : vec3(0.0, 0.0, 1.0);
vec3 arbitrary = (abs(up.z) < 0.9) ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
right = normalize(cross(up, arbitrary));
- fwd = normalize(cross(right, up));
+ fwd = normalize(cross(up, right));
}
+// Which side of a world plane a face is on, with zero counting as the positive side. Not GLSL's own
+// sign(), which returns 0 there and would collapse the coordinate onto a line.
+float box_face_sign(float n) { return n >= 0.0 ? 1.0 : -1.0; }
+
// The raw, millimetre-valued projection of `p` (a position in the texture frame), before the layer's
// tiling/rotation/aspect/offset - a term-for-term transcription of libslic3r's project_planar(),
// project_cylindrical() and project_spherical(). `n` is read by the planar mode only.
@@ -94,7 +98,7 @@ vec2 projection_raw(vec3 p, vec3 n)
vec3 rel = p - patch_center;
float x = dot(rel, right);
float y = dot(rel, fwd);
- return vec2(atan(y, x) * sqrt(x * x + y * y), dot(rel, up));
+ return vec2(atan(y, x) * sqrt(x * x + y * y), -dot(rel, up));
}
if (projection_mode == 2) { // Spherical: (longitude, latitude) * radius
vec3 rel = p - patch_center;
@@ -102,10 +106,18 @@ vec2 projection_raw(vec3 p, vec3 n)
if (radius < 1e-8)
return vec2(0.0);
vec3 dir = rel / radius;
- return vec2(atan(dir.y, dir.x), asin(clamp(dir.z, -1.0, 1.0))) * radius;
+ return vec2(atan(dir.y, dir.x), -asin(clamp(dir.z, -1.0, 1.0))) * radius;
}
- vec3 an = abs(n); // Triplanar: drop the dominant normal axis
- return (an.x >= an.y && an.x >= an.z) ? p.yz : ((an.y >= an.x && an.y >= an.z) ? p.xz : p.xy);
+ // Triplanar: drop the dominant normal axis. v is negated so the image's first pixel row (v = 0)
+ // sits at the top of the model instead of upside down, and u is flipped on the far side of each
+ // plane so the two faces sharing it are not mirror images. libslic3r's box_plane_yz() and its two
+ // siblings, term for term.
+ vec3 an = abs(n);
+ if (an.x >= an.y && an.x >= an.z)
+ return vec2(box_face_sign(n.x) * p.y, -p.z);
+ if (an.y >= an.x && an.y >= an.z)
+ return vec2(-box_face_sign(n.y) * p.x, -p.z);
+ return vec2(box_face_sign(n.z) * p.x, -p.y);
}
// The two surface directions projection_raw()'s u and v run along at `p`, plus how many raw units one
@@ -124,7 +136,7 @@ void projection_axes(vec3 p, vec3 n, out vec3 t, out vec3 b, out vec2 units_per_
vec2 xy = vec2(dot(rel, right), dot(rel, fwd));
float r = length(xy);
t = (r > 1e-6) ? (fwd * xy.x - right * xy.y) / r : right; // circumferential: u runs along it
- b = up; // v is the distance along the axis
+ b = -up; // v is the distance *against* the axis
return;
}
if (projection_mode == 2) {
@@ -133,20 +145,20 @@ void projection_axes(vec3 p, vec3 n, out vec3 t, out vec3 b, out vec2 units_per_
vec3 dir = (r > 1e-8) ? rel / r : vec3(0.0, 0.0, 1.0);
float c = length(dir.xy); // cos(latitude)
t = (c > 1e-6) ? vec3(-dir.y, dir.x, 0.0) / c : vec3(1.0, 0.0, 0.0);
- b = cross(dir, t); // increasing latitude, unit length
+ b = -cross(dir, t); // v grows away from the pole, unit length
units_per_mm = vec2(1.0 / max(c, 1e-3), 1.0);
return;
}
- vec3 an = abs(n);
- if (an.x >= an.y && an.x >= an.z) { // planar = p.yz
- t = vec3(0.0, 1.0, 0.0);
- b = vec3(0.0, 0.0, 1.0);
- } else if (an.y >= an.x && an.y >= an.z) { // planar = p.xz
- t = vec3(1.0, 0.0, 0.0);
- b = vec3(0.0, 0.0, 1.0);
- } else { // planar = p.xy
- t = vec3(1.0, 0.0, 0.0);
- b = vec3(0.0, 1.0, 0.0);
+ vec3 an = abs(n); // the same signed basis projection_raw() uses
+ if (an.x >= an.y && an.x >= an.z) { // planar = (+-y, -z)
+ t = vec3(0.0, box_face_sign(n.x), 0.0);
+ b = vec3(0.0, 0.0, -1.0);
+ } else if (an.y >= an.x && an.y >= an.z) { // planar = (+-x, -z)
+ t = vec3(-box_face_sign(n.y), 0.0, 0.0);
+ b = vec3(0.0, 0.0, -1.0);
+ } else { // planar = (+-x, -y)
+ t = vec3(box_face_sign(n.z), 0.0, 0.0);
+ b = vec3(0.0, -1.0, 0.0);
}
}
diff --git a/resources/shaders/110/texture_displacement_uvcheck.fs b/resources/shaders/110/texture_displacement_uvcheck.fs
index f9e998adc2..37fd1826f2 100644
--- a/resources/shaders/110/texture_displacement_uvcheck.fs
+++ b/resources/shaders/110/texture_displacement_uvcheck.fs
@@ -36,14 +36,20 @@ varying vec4 world_pos;
varying float distortion;
varying vec2 vertex_uv;
+// Right handed (up x right), like libslic3r's project_cylindrical(), so the angle taken from it grows
+// anticlockwise about the axis - to the viewer's right when seen from outside the cylinder.
void cylinder_frame(out vec3 up, out vec3 right, out vec3 fwd)
{
up = (length(patch_axis) > 1e-8) ? normalize(patch_axis) : vec3(0.0, 0.0, 1.0);
vec3 arbitrary = (abs(up.z) < 0.9) ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
right = normalize(cross(up, arbitrary));
- fwd = normalize(cross(right, up));
+ fwd = normalize(cross(up, right));
}
+// Which side of a world plane a face is on, with zero counting as the positive side. Not GLSL's own
+// sign(), which returns 0 there and would collapse the coordinate onto a line.
+float box_face_sign(float n) { return n >= 0.0 ? 1.0 : -1.0; }
+
// Term for term libslic3r's project_planar() / project_cylindrical() / project_spherical(), in mm.
vec2 projection_raw(vec3 p, vec3 n)
{
@@ -53,7 +59,7 @@ vec2 projection_raw(vec3 p, vec3 n)
vec3 rel = p - patch_center;
float x = dot(rel, right);
float y = dot(rel, fwd);
- return vec2(atan(y, x) * sqrt(x * x + y * y), dot(rel, up));
+ return vec2(atan(y, x) * sqrt(x * x + y * y), -dot(rel, up));
}
if (projection_mode == 2) {
vec3 rel = p - patch_center;
@@ -61,10 +67,16 @@ vec2 projection_raw(vec3 p, vec3 n)
if (radius < 1e-8)
return vec2(0.0);
vec3 dir = rel / radius;
- return vec2(atan(dir.y, dir.x), asin(clamp(dir.z, -1.0, 1.0))) * radius;
+ return vec2(atan(dir.y, dir.x), -asin(clamp(dir.z, -1.0, 1.0))) * radius;
}
+ // v negated so the image's first pixel row sits at the top of the model, u flipped on the far side
+ // of each plane so the two faces sharing it are not mirror images - see libslic3r's box_plane_yz().
vec3 an = abs(n);
- return (an.x >= an.y && an.x >= an.z) ? p.yz : ((an.y >= an.x && an.y >= an.z) ? p.xz : p.xy);
+ if (an.x >= an.y && an.x >= an.z)
+ return vec2(box_face_sign(n.x) * p.y, -p.z);
+ if (an.y >= an.x && an.y >= an.z)
+ return vec2(-box_face_sign(n.y) * p.x, -p.z);
+ return vec2(box_face_sign(n.z) * p.x, -p.y);
}
vec2 project_uv(vec3 p, vec3 n)
diff --git a/resources/shaders/140/texture_displacement_shaded.fs b/resources/shaders/140/texture_displacement_shaded.fs
index 911a919aaf..9398b21102 100644
--- a/resources/shaders/140/texture_displacement_shaded.fs
+++ b/resources/shaders/140/texture_displacement_shaded.fs
@@ -138,17 +138,21 @@ in vec2 vertex_uv;
out vec4 out_color;
-// The cylinder's own frame, built exactly as libslic3r's project_cylindrical() builds it - including
-// the handedness, which comes out left-handed for an axis of +Z. Copied rather than "corrected", so
-// the preview wraps the texture the same way round as the bake.
+// The cylinder's own frame, built exactly as libslic3r's project_cylindrical() builds it - right
+// handed, so the angle taken from it grows anticlockwise about the axis, which seen from outside the
+// cylinder is to the viewer's right rather than mirrored.
void cylinder_frame(out vec3 up, out vec3 right, out vec3 fwd)
{
up = (length(patch_axis) > 1e-8) ? normalize(patch_axis) : vec3(0.0, 0.0, 1.0);
vec3 arbitrary = (abs(up.z) < 0.9) ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
right = normalize(cross(up, arbitrary));
- fwd = normalize(cross(right, up));
+ fwd = normalize(cross(up, right));
}
+// Which side of a world plane a face is on, with zero counting as the positive side. Not GLSL's own
+// sign(), which returns 0 there and would collapse the coordinate onto a line.
+float box_face_sign(float n) { return n >= 0.0 ? 1.0 : -1.0; }
+
// The raw, millimetre-valued projection of `p` (a position in the texture frame), before the layer's
// tiling/rotation/aspect/offset - a term-for-term transcription of libslic3r's project_planar(),
// project_cylindrical() and project_spherical(). `n` is read by the planar mode only.
@@ -160,7 +164,7 @@ vec2 projection_raw(vec3 p, vec3 n)
vec3 rel = p - patch_center;
float x = dot(rel, right);
float y = dot(rel, fwd);
- return vec2(atan(y, x) * sqrt(x * x + y * y), dot(rel, up));
+ return vec2(atan(y, x) * sqrt(x * x + y * y), -dot(rel, up));
}
if (projection_mode == 2) { // Spherical: (longitude, latitude) * radius
vec3 rel = p - patch_center;
@@ -168,10 +172,18 @@ vec2 projection_raw(vec3 p, vec3 n)
if (radius < 1e-8)
return vec2(0.0);
vec3 dir = rel / radius;
- return vec2(atan(dir.y, dir.x), asin(clamp(dir.z, -1.0, 1.0))) * radius;
+ return vec2(atan(dir.y, dir.x), -asin(clamp(dir.z, -1.0, 1.0))) * radius;
}
- vec3 an = abs(n); // Triplanar: drop the dominant normal axis
- return (an.x >= an.y && an.x >= an.z) ? p.yz : ((an.y >= an.x && an.y >= an.z) ? p.xz : p.xy);
+ // Triplanar: drop the dominant normal axis. v is negated so the image's first pixel row (v = 0)
+ // sits at the top of the model instead of upside down, and u is flipped on the far side of each
+ // plane so the two faces sharing it are not mirror images. libslic3r's box_plane_yz() and its two
+ // siblings, term for term.
+ vec3 an = abs(n);
+ if (an.x >= an.y && an.x >= an.z)
+ return vec2(box_face_sign(n.x) * p.y, -p.z);
+ if (an.y >= an.x && an.y >= an.z)
+ return vec2(-box_face_sign(n.y) * p.x, -p.z);
+ return vec2(box_face_sign(n.z) * p.x, -p.y);
}
// The two surface directions projection_raw()'s u and v run along at `p`, plus how many raw units one
@@ -190,7 +202,7 @@ void projection_axes(vec3 p, vec3 n, out vec3 t, out vec3 b, out vec2 units_per_
vec2 xy = vec2(dot(rel, right), dot(rel, fwd));
float r = length(xy);
t = (r > 1e-6) ? (fwd * xy.x - right * xy.y) / r : right; // circumferential: u runs along it
- b = up; // v is the distance along the axis
+ b = -up; // v is the distance *against* the axis
return;
}
if (projection_mode == 2) {
@@ -199,20 +211,20 @@ void projection_axes(vec3 p, vec3 n, out vec3 t, out vec3 b, out vec2 units_per_
vec3 dir = (r > 1e-8) ? rel / r : vec3(0.0, 0.0, 1.0);
float c = length(dir.xy); // cos(latitude)
t = (c > 1e-6) ? vec3(-dir.y, dir.x, 0.0) / c : vec3(1.0, 0.0, 0.0);
- b = cross(dir, t); // increasing latitude, unit length
+ b = -cross(dir, t); // v grows away from the pole, unit length
units_per_mm = vec2(1.0 / max(c, 1e-3), 1.0);
return;
}
- vec3 an = abs(n);
- if (an.x >= an.y && an.x >= an.z) { // planar = p.yz
- t = vec3(0.0, 1.0, 0.0);
- b = vec3(0.0, 0.0, 1.0);
- } else if (an.y >= an.x && an.y >= an.z) { // planar = p.xz
- t = vec3(1.0, 0.0, 0.0);
- b = vec3(0.0, 0.0, 1.0);
- } else { // planar = p.xy
- t = vec3(1.0, 0.0, 0.0);
- b = vec3(0.0, 1.0, 0.0);
+ vec3 an = abs(n); // the same signed basis projection_raw() uses
+ if (an.x >= an.y && an.x >= an.z) { // planar = (+-y, -z)
+ t = vec3(0.0, box_face_sign(n.x), 0.0);
+ b = vec3(0.0, 0.0, -1.0);
+ } else if (an.y >= an.x && an.y >= an.z) { // planar = (+-x, -z)
+ t = vec3(-box_face_sign(n.y), 0.0, 0.0);
+ b = vec3(0.0, 0.0, -1.0);
+ } else { // planar = (+-x, -y)
+ t = vec3(box_face_sign(n.z), 0.0, 0.0);
+ b = vec3(0.0, -1.0, 0.0);
}
}
diff --git a/resources/shaders/140/texture_displacement_uvcheck.fs b/resources/shaders/140/texture_displacement_uvcheck.fs
index e6fc8036da..34f80df2bd 100644
--- a/resources/shaders/140/texture_displacement_uvcheck.fs
+++ b/resources/shaders/140/texture_displacement_uvcheck.fs
@@ -47,14 +47,20 @@ in vec2 vertex_uv;
out vec4 out_color;
+// Right handed (up x right), like libslic3r's project_cylindrical(), so the angle taken from it grows
+// anticlockwise about the axis - to the viewer's right when seen from outside the cylinder.
void cylinder_frame(out vec3 up, out vec3 right, out vec3 fwd)
{
up = (length(patch_axis) > 1e-8) ? normalize(patch_axis) : vec3(0.0, 0.0, 1.0);
vec3 arbitrary = (abs(up.z) < 0.9) ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
right = normalize(cross(up, arbitrary));
- fwd = normalize(cross(right, up));
+ fwd = normalize(cross(up, right));
}
+// Which side of a world plane a face is on, with zero counting as the positive side. Not GLSL's own
+// sign(), which returns 0 there and would collapse the coordinate onto a line.
+float box_face_sign(float n) { return n >= 0.0 ? 1.0 : -1.0; }
+
// Term for term libslic3r's project_planar() / project_cylindrical() / project_spherical(), in mm.
vec2 projection_raw(vec3 p, vec3 n)
{
@@ -64,7 +70,7 @@ vec2 projection_raw(vec3 p, vec3 n)
vec3 rel = p - patch_center;
float x = dot(rel, right);
float y = dot(rel, fwd);
- return vec2(atan(y, x) * sqrt(x * x + y * y), dot(rel, up));
+ return vec2(atan(y, x) * sqrt(x * x + y * y), -dot(rel, up));
}
if (projection_mode == 2) {
vec3 rel = p - patch_center;
@@ -72,10 +78,16 @@ vec2 projection_raw(vec3 p, vec3 n)
if (radius < 1e-8)
return vec2(0.0);
vec3 dir = rel / radius;
- return vec2(atan(dir.y, dir.x), asin(clamp(dir.z, -1.0, 1.0))) * radius;
+ return vec2(atan(dir.y, dir.x), -asin(clamp(dir.z, -1.0, 1.0))) * radius;
}
+ // v negated so the image's first pixel row sits at the top of the model, u flipped on the far side
+ // of each plane so the two faces sharing it are not mirror images - see libslic3r's box_plane_yz().
vec3 an = abs(n);
- return (an.x >= an.y && an.x >= an.z) ? p.yz : ((an.y >= an.x && an.y >= an.z) ? p.xz : p.xy);
+ if (an.x >= an.y && an.x >= an.z)
+ return vec2(box_face_sign(n.x) * p.y, -p.z);
+ if (an.y >= an.x && an.y >= an.z)
+ return vec2(-box_face_sign(n.y) * p.x, -p.z);
+ return vec2(box_face_sign(n.z) * p.x, -p.y);
}
vec2 project_uv(vec3 p, vec3 n)
diff --git a/scripts/ci_deps_cache.sh b/scripts/ci_deps_cache.sh
index a27b7e2522..0c3ae85415 100644
--- a/scripts/ci_deps_cache.sh
+++ b/scripts/ci_deps_cache.sh
@@ -1,21 +1,27 @@
#!/usr/bin/env bash
-# Lets a pull request's macOS deps build wait for a push build of the base
-# branch that builds the same deps, from a Linux job. `check` runs after a cache
-# miss and names a queued or running base build with the same deps/ and .github/
-# to wait for, unless the pull request changes either. `wait` waits until that
-# build saves KEY. actions/cache then confirms the entry can be restored.
+# Lets a pull request's macOS deps build, or its clang-tidy job, wait for a
+# build that saves the deps cache it needs, from a Linux job. `check` runs after
+# a cache miss and names a queued or running push build of the base branch with
+# the same deps/ and .github/ to wait for, unless the pull request changes either.
+# `own` names the pull request's own build instead, for clang-tidy when the pull
+# request changes deps/. `wait` waits until that build saves KEY under CACHE_REF,
+# or its deps job fails. actions/cache then confirms the entry can be restored.
#
-# Environment: GH_TOKEN, REPO, WORKFLOW_REF and BASE_REF, plus KEY_INPUTS,
-# WAIT_FOR, WAIT_SINCE, WAIT_MINUTES, KEY and ARCH for `wait`.
+# Environment: GH_TOKEN, REPO, WORKFLOW_REF (or WORKFLOW, the build workflow's
+# file name) and BASE_REF, plus HEAD_SHA for `own`, and KEY_INPUTS, WAIT_FOR,
+# WAIT_SINCE, WAIT_MINUTES, KEY, CACHE_REF (default the base branch) and ARCH
+# (or JOB, the matrix job's name) for `wait`.
# Writes key-inputs, wait-for and wait-since to $GITHUB_OUTPUT.
set -uo pipefail
-workflow=${WORKFLOW_REF%%@*}
-workflow=${workflow##*/}
+workflow=${WORKFLOW_REF:-}
+workflow=${workflow%%@*}
+workflow=${WORKFLOW:-${workflow##*/}}
# Must match the job names in build_all.yml, build_check_cache.yml and build_deps.yml.
-check_job_name="build_macos_arch (${ARCH:-}) / Check Cache"
-deps_job_name="build_macos_arch (${ARCH:-}) / Build Deps / Build Deps"
+job=${JOB:-build_macos_arch (${ARCH:-})}
+check_job_name="$job / Check Cache"
+deps_job_name="$job / Build Deps / Build Deps"
out() { echo "$1" >> "${GITHUB_OUTPUT:-/dev/stdout}"; }
@@ -63,8 +69,27 @@ check() {
fi
}
+own() {
+ out "key-inputs=$(local_key_inputs HEAD)"
+ local id
+ # The build can be created a moment after this job.
+ for _ in 1 2 3 4 5; do
+ id=$(gh api -X GET "repos/$REPO/actions/workflows/$workflow/runs" \
+ -f head_sha="$HEAD_SHA" -f event=pull_request -f per_page=1 --jq '.workflow_runs[0].id // empty' < /dev/null)
+ [ -n "$id" ] && break
+ sleep 30
+ done
+ if [ -n "$id" ]; then
+ echo "Waiting for the deps cache of build $id of this pull request."
+ out "wait-for=$id"
+ out "wait-since=$(date +%s)"
+ else
+ echo "No build of this pull request is building its deps."
+ fi
+}
+
key_saved() {
- gh cache list -R "$REPO" --ref "refs/heads/$BASE_REF" --key "$KEY" --json key < /dev/null \
+ gh cache list -R "$REPO" --ref "${CACHE_REF:-refs/heads/$BASE_REF}" --key "$KEY" --json key < /dev/null \
| jq -e --arg key "$KEY" 'any(.[]; .key == $key)' > /dev/null
}
@@ -87,11 +112,11 @@ wait_for() {
key_saved && { echo "Found $KEY."; return; }
sleep 20
done
- echo "Build $id of $BASE_REF finished its deps without saving $KEY."
+ echo "Build $id finished its deps without saving $KEY."
return ;;
"completed cancelled") ;;
completed*)
- echo "The deps job of build $id of $BASE_REF did not succeed."
+ echo "The deps job of build $id did not succeed."
return ;;
# The deps job exists only once the build's cache check has succeeded.
"")
@@ -100,7 +125,7 @@ wait_for() {
completed*)
check=$(jq -r --arg name "$check_job_name" 'first(.jobs[] | select(.name == $name) | .conclusion) // ""' <<< "$jobs")
if [ -z "$warned" ] && { [ -z "$check" ] || [ "$check" = success ]; }; then
- echo "::warning title=Deps wait::Build $id of $BASE_REF has no job named \"$deps_job_name\". If the build jobs were renamed, update scripts/ci_deps_cache.sh. This does not affect this pull request."
+ echo "::warning title=Deps wait::Build $id has no job named \"$deps_job_name\". If the build jobs were renamed, update scripts/ci_deps_cache.sh. This does not affect this pull request."
warned=1
fi ;;
*)
@@ -118,11 +143,12 @@ wait_for() {
seen="$seen $id"
echo "Following build $id of $BASE_REF."
done
- echo "No build of $BASE_REF saved $KEY."
+ echo "No build saved $KEY."
}
case "${1:-}" in
check) check ;;
+ own) own ;;
wait) wait_for ;;
- *) echo "usage: $0 check|wait" >&2; exit 2 ;;
+ *) echo "usage: $0 check|own|wait" >&2; exit 2 ;;
esac
diff --git a/src/OrcaSlicer.cpp b/src/OrcaSlicer.cpp
index 1b764fe468..2a158f4b12 100644
--- a/src/OrcaSlicer.cpp
+++ b/src/OrcaSlicer.cpp
@@ -99,6 +99,7 @@
#include "libslic3r/Preset.hpp"
#include "libslic3r/Geometry.hpp"
#include "libslic3r/GCode.hpp"
+#include "libslic3r/MeshRepair.hpp"
#include "libslic3r/Model.hpp"
#include "libslic3r/ModelArrange.hpp"
#include "libslic3r/Platform.hpp"
@@ -206,7 +207,7 @@ std::map cli_errors = {
{CLI_OBJECT_ORIENT_FAILED, "An error occurred when auto-orienting object(s)."},
{CLI_MODIFIED_PARAMS_TO_PRINTER, "Found modified parameter in printer preset in the 3mf file, which should not be changed."},
{CLI_FILE_VERSION_NOT_SUPPORTED, "Unsupported 3MF version. Please make sure the 3MF file was created with the official version of Bambu Studio, not a beta version."},
- {CLI_NO_SUITABLE_OBJECTS, "One of the plate is empty or has no object fully inside it. Please check that the 3mf contains no empty plate in Orca Slicer before uploading."},
+ {CLI_NO_SUITABLE_OBJECTS, "The plate has nothing to slice: it is empty, or no object on it is both printable and fully inside the print volume."},
{CLI_VALIDATE_ERROR, "There are some incorrect slicing parameters in the 3mf. Please verify the slicing of all plates in Orca Slicer before uploading."},
{CLI_OBJECTS_PARTLY_INSIDE, "Some objects are located over the boundary of the heated bed."},
{CLI_EXPORT_CACHE_DIRECTORY_CREATE_FAILED, "Failed creating directory when exporting cache data."},
@@ -1463,7 +1464,7 @@ int CLI::run(int argc, char **argv)
//int arrange_option;
int plate_to_slice = 0, filament_count = 0, duplicate_count = 0, real_duplicate_count = 0, current_extruder_count = 1, new_extruder_count = 1, current_printer_variant_count = 1, current_print_variant_count = 1, new_printer_variant_count = 1;
bool first_file = true, is_bbl_3mf = false, need_arrange = true, has_thumbnails = false, up_config_to_date = false, normative_check = true, duplicate_single_object = false, use_first_fila_as_default = false, minimum_save = false, enable_timelapse = false;
- bool allow_rotations = true, skip_modified_gcodes = false, avoid_extrusion_cali_region = false, skip_useless_pick = false, allow_newer_file = false, current_is_multi_extruder = false, new_is_multi_extruder = false, allow_mix_temp = false, enable_wrapping_detect = false;
+ bool allow_rotations = false, skip_modified_gcodes = false, avoid_extrusion_cali_region = false, skip_useless_pick = false, allow_newer_file = false, current_is_multi_extruder = false, new_is_multi_extruder = false, allow_mix_temp = false, enable_wrapping_detect = false;
Semver file_version;
std::map orients_requirement;
std::vector project_presets;
@@ -5130,9 +5131,19 @@ int CLI::run(int argc, char **argv)
}
}
} else if (opt_key == "repair") {
- // Models are repaired by default.
- //for (auto &model : m_models)
- // model.repair();
+ if (m_config.opt_bool(opt_key))
+ for (Model &model : m_models)
+ for (ModelObject *object : model.objects) {
+ for (ModelVolume *volume : object->volumes) {
+ MeshRepairStats stats;
+ std::string error;
+ if (!volume->repair(true, &stats, &error))
+ BOOST_LOG_TRIVIAL(warning) << "repair of " << object->name << " / " << volume->name << " failed: " << error;
+ else if (stats.modified)
+ BOOST_LOG_TRIVIAL(info) << "repaired " << object->name << " / " << volume->name;
+ }
+ object->invalidate_bounding_box();
+ }
} else {
boost::nowide::cerr << "error: option not implemented yet: " << opt_key << std::endl;
record_exit_reson(outfile_dir, CLI_UNSUPPORTED_OPERATION, 0, cli_errors[CLI_UNSUPPORTED_OPERATION], sliced_info);
@@ -5142,6 +5153,7 @@ int CLI::run(int argc, char **argv)
BOOST_LOG_TRIVIAL(info) << "finished model pre-process commands\n";
bool oriented_or_arranged = false;
+ bool arranged_without_rotations = false;
//BBS: add orient and arrange logic here
for (auto& model : m_models)
{
@@ -5409,6 +5421,7 @@ int CLI::run(int argc, char **argv)
BOOST_LOG_TRIVIAL(info) << boost::format("start plate %1%'s arranging...") % (i + 1);
arrangement::arrange(selected, unselected, beds, arrange_cfg);
//arrangement::arrange(unprintable, {}, beds, arrange_cfg);
+ arranged_without_rotations |= !arrange_cfg.allow_rotations;
BOOST_LOG_TRIVIAL(info) << boost::format("finished plate %1%'s arranging") % (i + 1);
//step-4: postprocess the bed index and result
@@ -5881,6 +5894,7 @@ int CLI::run(int argc, char **argv)
BOOST_LOG_TRIVIAL(info) << boost::format("start %1% th arranging...")%arrange_count;
arrangement::arrange(selected, unselected, beds, arrange_cfg);
arrangement::arrange(unprintable, {}, beds, arrange_cfg);
+ arranged_without_rotations |= !arrange_cfg.allow_rotations;
BOOST_LOG_TRIVIAL(info) << boost::format("finished %1% th arranging...")%arrange_count;
//Step-4:postprocess by partplate list&&apply the result
@@ -6425,7 +6439,15 @@ int CLI::run(int argc, char **argv)
if (count == 0) {
BOOST_LOG_TRIVIAL(error) << "plate "<< index+1<< ": Nothing to be sliced, Either the print is empty or no object is fully inside the print volume before apply." << std::endl;
- record_exit_reson(outfile_dir, CLI_NO_SUITABLE_OBJECTS, index+1, cli_errors[CLI_NO_SUITABLE_OBJECTS], sliced_info);
+ std::string no_objects_reason = cli_errors[CLI_NO_SUITABLE_OBJECTS];
+ if (arranged_without_rotations) {
+ //ORCA: result.json is only written on Linux, so also print the reason to stderr.
+ no_objects_reason = "No object is fully inside the print volume. Arrange ran without rotations."
+ " If an object only fits the bed when rotated, pass --allow-rotations."
+ " Otherwise the plate is empty or an object is larger than the printable area or height.";
+ boost::nowide::cerr << "plate " << index+1 << ": " << no_objects_reason << std::endl;
+ }
+ record_exit_reson(outfile_dir, CLI_NO_SUITABLE_OBJECTS, index+1, no_objects_reason, sliced_info);
flush_and_exit(CLI_NO_SUITABLE_OBJECTS);
}
else if ((plate_to_slice != 0) || pre_check) {
diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt
index 1a7080d5c7..afa3b61bc1 100644
--- a/src/libslic3r/CMakeLists.txt
+++ b/src/libslic3r/CMakeLists.txt
@@ -625,6 +625,7 @@ add_library(libslic3r_cgal STATIC
CutSurface.hpp CutSurface.cpp
IntersectionPoints.hpp IntersectionPoints.cpp
MeshBoolean.hpp MeshBoolean.cpp
+ MeshRepair.hpp MeshRepair.cpp
TryCatchSignal.hpp TryCatchSignal.cpp
Triangulation.hpp Triangulation.cpp
)
@@ -652,7 +653,9 @@ if (IS_CLANG_CL)
target_compile_options(libslic3r_cgal PRIVATE -Wno-overriding-option)
endif ()
-target_link_libraries(libslic3r_cgal PRIVATE ${_cgal_tgt} admesh libigl mcut boost_libs)
+# Lets CGAL algorithms given CGAL::Parallel_if_available_tag run on TBB.
+target_compile_definitions(libslic3r_cgal PRIVATE CGAL_LINKED_WITH_TBB)
+target_link_libraries(libslic3r_cgal PRIVATE ${_cgal_tgt} admesh libigl mcut boost_libs TBB::tbb)
if (MSVC AND "${CMAKE_SIZEOF_VOID_P}" STREQUAL "4") # 32 bit MSVC workaround
target_compile_definitions(libslic3r_cgal PRIVATE CGAL_DO_NOT_USE_MPZF)
diff --git a/src/libslic3r/Format/STEP.cpp b/src/libslic3r/Format/STEP.cpp
index 962c4cffb9..4f40093c73 100644
--- a/src/libslic3r/Format/STEP.cpp
+++ b/src/libslic3r/Format/STEP.cpp
@@ -236,19 +236,29 @@ static void getNamedSolids(const TopLoc_Location& location,
int i = 0;
switch (shape_type) {
case TopAbs_COMPOUND:
- if (!isSplitCompound) {
- namedSolids.emplace_back(TopoDS::Compound(transform.Shape()), fullName);
- break;
- }
case TopAbs_COMPSOLID:
if (!isSplitCompound) {
- namedSolids.emplace_back(TopoDS::CompSolid(transform.Shape()), fullName);
+ namedSolids.emplace_back(transform.Shape(), fullName);
} else {
for (explorer.Init(transform.Shape(), TopAbs_SOLID); explorer.More(); explorer.Next()) {
i++;
const TopoDS_Shape& currentShape = explorer.Current();
namedSolids.emplace_back(TopoDS::Solid(currentShape), fullName + "-SOLID-" + std::to_string(i));
}
+ // Surface models have no solids: each shell outside a solid is a part, and loose faces stay together.
+ i = 0;
+ for (explorer.Init(transform.Shape(), TopAbs_SHELL, TopAbs_SOLID); explorer.More(); explorer.Next())
+ namedSolids.emplace_back(explorer.Current(), fullName + "-SHELL-" + std::to_string(++i));
+ TopoDS_Compound loose_faces;
+ TopoDS_Builder builder;
+ builder.MakeCompound(loose_faces);
+ bool has_loose_faces = false;
+ for (explorer.Init(transform.Shape(), TopAbs_FACE, TopAbs_SHELL); explorer.More(); explorer.Next()) {
+ builder.Add(loose_faces, explorer.Current());
+ has_loose_faces = true;
+ }
+ if (has_loose_faces)
+ namedSolids.emplace_back(loose_faces, fullName);
}
break;
case TopAbs_SOLID:
diff --git a/src/libslic3r/Format/bbs_3mf.cpp b/src/libslic3r/Format/bbs_3mf.cpp
index 8a22201c51..24c2c027e5 100644
--- a/src/libslic3r/Format/bbs_3mf.cpp
+++ b/src/libslic3r/Format/bbs_3mf.cpp
@@ -22,6 +22,7 @@
#include "libslic3r/BrimEarsPoint.hpp"
#include "libslic3r/Config.hpp"
#include "libslic3r/CustomGCode.hpp"
+#include "libslic3r/TextureDisplacement.hpp"
#include "libslic3r_version.h"
#include "bbs_3mf.hpp"
@@ -354,6 +355,13 @@ static constexpr const char* CUSTOM_SUPPORTS_ATTR = "paint_supports";
static constexpr const char* CUSTOM_FUZZY_SKIN_ATTR = "paint_fuzzy_skin";
static constexpr const char* CUSTOM_SEAM_ATTR = "paint_seam";
static constexpr const char* MMU_SEGMENTATION_ATTR = "paint_color";
+// Texture displacement. One paint mask per layer slot, mirroring paint_color; the layer stack itself is
+// a JSON file in the archive, named by the volume metadata key below (see add_texture_displacement()).
+static constexpr const char* TEXTURE_DISPLACEMENT_ATTRS[Slic3r::TEXTURE_DISPLACEMENT_MAX_LAYERS] = {
+ "paint_texture_0", "paint_texture_1", "paint_texture_2", "paint_texture_3",
+ "paint_texture_4", "paint_texture_5", "paint_texture_6", "paint_texture_7" };
+static constexpr const char* TEXTURE_DISPLACEMENT_KEY = "texture_displacement";
+static constexpr const char* TEXTURE_DISPLACEMENT_DIR = "Metadata/texture_displacement/";
// BBS
static constexpr const char* FACE_PROPERTY_ATTR = "face_property";
@@ -847,6 +855,9 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
std::vector custom_seam;
std::vector mmu_segmentation;
std::vector fuzzy_skin;
+ // One per texture displacement layer slot, indexed like `triangles` but stored only as far as the
+ // slot's last painted triangle: empty when the slot has no paint, which is nearly every file.
+ std::vector texture_displacement[TEXTURE_DISPLACEMENT_MAX_LAYERS];
// BBS
std::vector face_properties;
@@ -867,6 +878,8 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
custom_seam.clear();
mmu_segmentation.clear();
fuzzy_skin.clear();
+ for (std::vector &slot : texture_displacement)
+ slot.clear();
}
};
@@ -1200,6 +1213,11 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
/*IdToSlaSupportPointsMap m_sla_support_points;
IdToSlaDrainHolesMap m_sla_drain_holes;*/
PathToEmbossShapeFileMap m_path_to_emboss_shape_files;
+ // Texture displacement: every file under Metadata/texture_displacement/, by archive path. Volumes
+ // are built only after the whole archive has been walked, so by the time a volume names its JSON
+ // every file it could refer to is already in here, whatever order the archive happened to be in.
+ std::map m_texture_displacement_files;
+ void _apply_texture_displacement(ModelVolume &volume, const std::string &json_path);
std::string m_curr_metadata_name;
std::string m_curr_characters;
std::string m_name;
@@ -1729,8 +1747,8 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
//plate->pattern_file = it->second->pattern_file;
plate->no_light_thumbnail_file = it->second->no_light_thumbnail_file;
plate->top_file = it->second->top_file;
- plate->pick_file = it->second->pick_file.empty();
- plate->pattern_bbox_file = it->second->pattern_bbox_file.empty();
+ plate->pick_file = it->second->pick_file;
+ plate->pattern_bbox_file = it->second->pattern_bbox_file;
plate->config = it->second->config;
if (!plate->thumbnail_file.empty())
@@ -2073,6 +2091,13 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
else if (_is_svg_shape_file(name)) {
_extract_embossed_svg_shape_file(name, archive, stat);
}
+ else if (boost::algorithm::istarts_with(name, TEXTURE_DISPLACEMENT_DIR)) {
+ std::string contents(stat.m_uncomp_size, '\0');
+ if (mz_zip_reader_extract_to_mem(&archive, stat.m_file_index, contents.data(), stat.m_uncomp_size, 0))
+ m_texture_displacement_files.emplace(name, std::move(contents));
+ else
+ add_error("Error while reading texture displacement data");
+ }
else if (!dont_load_config && boost::algorithm::iequals(name, SLICE_INFO_CONFIG_FILE)) {
m_parsing_slice_info = true;
//extract slice info from archive
@@ -3310,6 +3335,45 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
}
}*/
+ // Restores one volume's texture displacement stack from the JSON it named. Called while the volume is
+ // being built, which is after the whole archive has been walked - so every file it can refer to is
+ // already extracted, and no deferral is needed.
+ //
+ // A missing or malformed JSON leaves the volume with no layers but keeps the paint mask it already
+ // loaded, which is the same state as a project saved by a build without the feature: recoverable by
+ // picking the texture again rather than a hard failure.
+ void _BBS_3MF_Importer::_apply_texture_displacement(ModelVolume &volume, const std::string &json_path)
+ {
+ const auto json = m_texture_displacement_files.find(json_path);
+ if (json == m_texture_displacement_files.end()) {
+ add_error("Missing texture displacement data: " + json_path);
+ return;
+ }
+ std::vector layers;
+ TextureDisplacementOptions options;
+ if (!texture_displacement_layers_from_json(json->second, layers, options)) {
+ add_error("Malformed texture displacement data: " + json_path);
+ return;
+ }
+ // The archive is the only source of a layer's pixels. `path` comes from the project file, so loading
+ // the project must never read the file it names: that would let whoever made the project pick any
+ // local (or, on Windows, network) file to read, and the next save would embed it in the archive.
+ // `path` stays a label of where the texture came from; a layer the archive carries no image for
+ // loads without one, its settings intact, until the user picks a texture again.
+ for (TextureDisplacementLayer &layer : layers) {
+ if (layer.path_in_3mf.empty())
+ continue;
+ const auto image = m_texture_displacement_files.find(layer.path_in_3mf);
+ if (image == m_texture_displacement_files.end()) {
+ add_error("Missing texture displacement image: " + layer.path_in_3mf);
+ continue;
+ }
+ layer.image_data = std::make_shared>(image->second.begin(), image->second.end());
+ }
+ volume.texture_displacement_layers = std::move(layers);
+ volume.texture_displacement_options = options;
+ }
+
void _BBS_3MF_Importer::_extract_embossed_svg_shape_file(const std::string &filename, mz_zip_archive &archive, const mz_zip_archive_file_stat &stat){
assert(m_path_to_emboss_shape_files.find(filename) == m_path_to_emboss_shape_files.end());
auto file = std::make_unique(stat.m_uncomp_size, '\0');
@@ -3966,6 +4030,12 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
m_curr_object->geometry.custom_seam.push_back(bbs_get_attribute_value_string(attributes, num_attributes, CUSTOM_SEAM_ATTR));
m_curr_object->geometry.mmu_segmentation.push_back(bbs_get_attribute_value_string(attributes, num_attributes, MMU_SEGMENTATION_ATTR));
m_curr_object->geometry.fuzzy_skin.push_back(bbs_get_attribute_value_string(attributes, num_attributes, CUSTOM_FUZZY_SKIN_ATTR));
+ for (int slot = 0; slot < int(TEXTURE_DISPLACEMENT_MAX_LAYERS); ++slot)
+ if (const char *paint = bbs_get_attribute_value_charptr(attributes, num_attributes, TEXTURE_DISPLACEMENT_ATTRS[slot])) {
+ std::vector &mask = m_curr_object->geometry.texture_displacement[slot];
+ mask.resize(m_curr_object->geometry.triangles.size());
+ mask.back() = paint;
+ }
// BBS
m_curr_object->geometry.face_properties.push_back(bbs_get_attribute_value_string(attributes, num_attributes, FACE_PROPERTY_ATTR));
}
@@ -5317,6 +5387,18 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
volume->mmu_segmentation_facets.touch();
volume->fuzzy_skin_facets.shrink_to_fit();
volume->fuzzy_skin_facets.touch();
+ for (int slot = 0; slot < int(TEXTURE_DISPLACEMENT_MAX_LAYERS); ++slot) {
+ const std::vector &mask = sub_object->geometry.texture_displacement[slot];
+ if (mask.empty())
+ continue; // no triangle painted on this slot
+ FacetsAnnotation &facets = volume->texture_displacement_facet(slot);
+ facets.reserve(triangles_count);
+ for (size_t i = 0; i < triangles_count && i < mask.size(); ++i)
+ if (!mask[i].empty())
+ facets.set_triangle_from_string(i, mask[i]);
+ facets.shrink_to_fit();
+ facets.touch();
+ }
}
volume->set_type(volume_data->part_type);
@@ -5332,6 +5414,8 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
for (const Metadata& metadata : volume_data->metadata) {
if (metadata.key == NAME_KEY)
volume->name = metadata.value;
+ else if (metadata.key == TEXTURE_DISPLACEMENT_KEY)
+ _apply_texture_displacement(*volume, metadata.value);
//else if ((metadata.key == MODIFIER_KEY) && (metadata.value == "1"))
// volume->set_type(ModelVolumeType::PARAMETER_MODIFIER);
//for old format
@@ -5496,12 +5580,28 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
volume->seam_facets.shrink_to_fit();
volume->mmu_segmentation_facets.shrink_to_fit();
+ for (int slot = 0; slot < int(TEXTURE_DISPLACEMENT_MAX_LAYERS); ++slot) {
+ const std::vector &mask = geometry.texture_displacement[slot];
+ if (mask.empty())
+ continue; // written by a build without the feature
+ FacetsAnnotation &facets = volume->texture_displacement_facet(slot);
+ facets.reserve(triangles_count);
+ for (size_t i = 0; i < triangles_count; ++i) {
+ const size_t index = volume_data.first_triangle_id + i;
+ if (index < mask.size() && !mask[index].empty())
+ facets.set_triangle_from_string(i, mask[index]);
+ }
+ facets.shrink_to_fit();
+ facets.touch();
+ }
volume->set_type(volume_data.part_type);
// apply the remaining volume's metadata
for (const Metadata& metadata : volume_data.metadata) {
if (metadata.key == NAME_KEY)
volume->name = metadata.value;
+ else if (metadata.key == TEXTURE_DISPLACEMENT_KEY)
+ _apply_texture_displacement(*volume, metadata.value);
//else if ((metadata.key == MODIFIER_KEY) && (metadata.value == "1"))
// volume->set_type(ModelVolumeType::PARAMETER_MODIFIER);
//for old format
@@ -5805,6 +5905,12 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
current_object->geometry.custom_seam.push_back(bbs_get_attribute_value_string(attributes, num_attributes, CUSTOM_SEAM_ATTR));
current_object->geometry.mmu_segmentation.push_back(bbs_get_attribute_value_string(attributes, num_attributes, MMU_SEGMENTATION_ATTR));
current_object->geometry.fuzzy_skin.push_back(bbs_get_attribute_value_string(attributes, num_attributes, CUSTOM_FUZZY_SKIN_ATTR));
+ for (int slot = 0; slot < int(TEXTURE_DISPLACEMENT_MAX_LAYERS); ++slot)
+ if (const char *paint = bbs_get_attribute_value_charptr(attributes, num_attributes, TEXTURE_DISPLACEMENT_ATTRS[slot])) {
+ std::vector &mask = current_object->geometry.texture_displacement[slot];
+ mask.resize(current_object->geometry.triangles.size());
+ mask.back() = paint;
+ }
// BBS
current_object->geometry.face_properties.push_back(bbs_get_attribute_value_string(attributes, num_attributes, FACE_PROPERTY_ATTR));
}
@@ -6808,6 +6914,9 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
stream << " \n";
stream << " \n";
stream << " \n";
+ stream << " \n";
+ stream << " \n";
+ stream << " \n";
stream << " \n";
stream << "";
@@ -7232,10 +7341,14 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
if (iter != m_shared_meshes.end())
{
const ModelVolume* shared_volume = iter->second.second;
+ bool same_texture_paint = true;
+ for (int slot = 0; slot < int(TEXTURE_DISPLACEMENT_MAX_LAYERS) && same_texture_paint; ++slot)
+ same_texture_paint = shared_volume->texture_displacement_facet(slot).equals(volume->texture_displacement_facet(slot));
if ((shared_volume->supported_facets.equals(volume->supported_facets))
&& (shared_volume->seam_facets.equals(volume->seam_facets))
&& (shared_volume->mmu_segmentation_facets.equals(volume->mmu_segmentation_facets))
- && (shared_volume->fuzzy_skin_facets.equals(volume->fuzzy_skin_facets)))
+ && (shared_volume->fuzzy_skin_facets.equals(volume->fuzzy_skin_facets))
+ && same_texture_paint)
{
auto data = iter->second.first;
const_cast<_BBS_3MF_Exporter *>(this)->m_volume_paths.insert({volume, {data->sub_path, data->volumes_objectID.find(iter->second.second)->second}});
@@ -7651,6 +7764,20 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
output_buffer += "\"";
}
+ // One attribute per texture displacement layer slot. Older readers ignore attributes they do
+ // not know, so a project written here still opens in a build without the feature - it just
+ // loses the paint, which is also all it could have done with it.
+ for (int slot = 0; slot < TEXTURE_DISPLACEMENT_MAX_LAYERS; ++slot) {
+ const std::string texture_paint = volume->texture_displacement_facet(slot).get_triangle_as_string(i);
+ if (texture_paint.empty())
+ continue;
+ output_buffer += " ";
+ output_buffer += TEXTURE_DISPLACEMENT_ATTRS[slot];
+ output_buffer += "=\"";
+ output_buffer += texture_paint;
+ output_buffer += "\"";
+ }
+
// BBS
if (i < its.properties.size()) {
std::string prop_str = its.properties[i].to_string();
@@ -8100,7 +8227,42 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
return file_path;
}
- bool _BBS_3MF_Exporter::_add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model, PlateDataPtrs& plate_data_list, const ObjectToObjectDataMap &objects_data, const DynamicPrintConfig& config, int export_plate_idx, bool save_gcode, bool use_loaded_id)
+ // Writes a volume's texture displacement stack into the archive and points the volume's metadata at it.
+// The layer settings go in as JSON and each layer's texture as the image file it was loaded from, both
+// referenced by path - the same split EmbossShape makes for its SVG. The image deliberately stays out of
+// the XML: it is binary and routinely megabytes, and base64 in an attribute would bloat the one file
+// every reader has to parse just to list the objects.
+static void add_texture_displacement(std::stringstream &stream, const ModelVolume &volume, mz_zip_archive &archive,
+ const std::string &id)
+{
+ if (volume.texture_displacement_layers.empty())
+ return;
+
+ // A copy, because path_in_3mf is only meaningful inside the archive being written and the volume
+ // being exported is const (and may be saved again, elsewhere, with different paths).
+ std::vector layers = volume.texture_displacement_layers;
+ for (TextureDisplacementLayer &layer : layers) {
+ layer.path_in_3mf.clear();
+ if (!layer.image_data || layer.image_data->empty())
+ continue;
+ // Always .png: the importer converts whatever the user picked (jpg, bmp, ...) to an 8-bit
+ // greyscale PNG, so image_data is PNG whatever layer.path happens to be named.
+ const std::string path = std::string(TEXTURE_DISPLACEMENT_DIR) + id + "_" + std::to_string(layer.slot) + ".png";
+ // No deflate: a PNG is already compressed, so a second pass only costs time.
+ if (mz_zip_writer_add_mem(&archive, path.c_str(), layer.image_data->data(), layer.image_data->size(),
+ MZ_NO_COMPRESSION))
+ layer.path_in_3mf = path;
+ }
+
+ const std::string json = texture_displacement_layers_to_json(layers, volume.texture_displacement_options);
+ const std::string json_path = std::string(TEXTURE_DISPLACEMENT_DIR) + id + ".json";
+ if (!mz_zip_writer_add_mem(&archive, json_path.c_str(), json.data(), json.size(), MZ_DEFAULT_COMPRESSION))
+ return;
+ stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << TEXTURE_DISPLACEMENT_KEY << "\" "
+ << VALUE_ATTR << "=\"" << xml_escape(json_path) << "\"/>\n";
+}
+
+bool _BBS_3MF_Exporter::_add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model, PlateDataPtrs& plate_data_list, const ObjectToObjectDataMap &objects_data, const DynamicPrintConfig& config, int export_plate_idx, bool save_gcode, bool use_loaded_id)
{
std::stringstream stream;
// Store mesh transformation in full precision, as the volumes are stored transformed and they need to be transformed back
@@ -8211,6 +8373,8 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
if (const std::optional &es = volume->emboss_shape; es.has_value()) {
to_xml(stream, *es, *volume, archive, m_fullpath_sources);
}
+
+ add_texture_displacement(stream, *volume, archive, std::to_string(volume->id().id));
if (const std::optional &tc = volume->text_configuration;
tc.has_value())
diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp
index cab75d5034..f423681c9d 100644
--- a/src/libslic3r/GCode.cpp
+++ b/src/libslic3r/GCode.cpp
@@ -1033,6 +1033,15 @@ static std::vector get_path_of_change_filament(const Print& print)
return buf;
}
+ // FanMover consumes these markers (and drops them) to avoid splitting a G1 inside custom gcode.
+ // Only written when FanMover runs, the same gate as its construction in GCode::process_layers.
+ static std::string wrap_custom_gcode_for_fan_mover(const FullPrintConfig &config, const std::string &gcode)
+ {
+ if (config.fan_speedup_time.value == 0 && config.fan_kickstart.value <= 0)
+ return gcode;
+ return ";_FAN_MOVER_SKIP_START\n" + gcode + ";_FAN_MOVER_SKIP_END\n";
+ }
+
std::string WipeTowerIntegration::append_tcr(GCode& gcodegen, const WipeTower::ToolChangeResult& tcr, int new_filament_id, double z) const
{
if (new_filament_id != -1 && new_filament_id != tcr.new_tool)
@@ -1384,6 +1393,9 @@ static std::vector get_path_of_change_filament(const Print& print)
toolchange_gcode_str = gcodegen.placeholder_parser_process("change_filament_gcode", change_filament_gcode, new_filament_id, &config);
check_add_eol(toolchange_gcode_str);
+ // Type1 wipe tower path (every BBL printer): bracket the same way set_extruder() does,
+ // so FanMover doesn't split a G1 inside this custom gcode either.
+ toolchange_gcode_str = wrap_custom_gcode_for_fan_mover(gcodegen.config(), toolchange_gcode_str);
//BBS
{
@@ -3295,7 +3307,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
m_is_role_based_fan_on.fill(false);
m_role_based_fan_marker_layer.fill(-1);
- m_fan_mover.release();
+ m_fan_mover.reset();
m_ordering_cache.clear();
// Belt printer: initialize belt-specific writer via virtual hook.
@@ -4250,7 +4262,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
config.set_key_value("nozzle_diameter_at_nozzle_id", new ConfigOptionFloats(get_nozzle_diameters_by_nozzle_id(group_result.get())));
config.set_key_value("nozzle_volume_types", new ConfigOptionStrings(get_nozzle_volume_types_by_nozzle_id(group_result.get())));
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
- std::string filament_start_gcode = this->placeholder_parser_process("filament_start_gcode", print.config().filament_start_gcode.values.at(initial_non_support_extruder_id), initial_non_support_extruder_id,&config);
+ std::string filament_start_gcode = this->placeholder_parser_process("filament_start_gcode", print.config().filament_start_gcode.get_at(initial_non_support_extruder_id), initial_non_support_extruder_id,&config);
file.writeln(filament_start_gcode);
// Mark the first filament used in print. Multi-nozzle printers (H2C) get ";VT%d H%d" where
// H = dynamic ? nozzle_id : -1; existing single-nozzle printers keep the bare ";VT%d" so their
@@ -10895,7 +10907,8 @@ std::string GCode::set_extruder(unsigned int new_filament_id, double print_z, bo
toolchange_gcode_parsed = placeholder_parser_process("change_filament_gcode", change_filament_gcode, new_filament_id, &dyn_config);
check_add_eol(toolchange_gcode_parsed);
- gcode += toolchange_gcode_parsed;
+ // toolchange_gcode_parsed is still read below (get_last_z_from_gcode, custom_gcode_changes_tool).
+ gcode += wrap_custom_gcode_for_fan_mover(m_config, toolchange_gcode_parsed);
//BBS
{
diff --git a/src/libslic3r/GCode/FanMover.cpp b/src/libslic3r/GCode/FanMover.cpp
index d303cbbac6..d49ca8b114 100644
--- a/src/libslic3r/GCode/FanMover.cpp
+++ b/src/libslic3r/GCode/FanMover.cpp
@@ -445,6 +445,11 @@ void FanMover::_process_gcode_line(GCodeReader& reader, const GCodeReader::GCode
std::string extrusion_string = line.raw().substr(6, line.raw().size() - 6);
current_role = ExtrusionEntity::string_to_role(extrusion_string);
}
+ if (line.raw().rfind(";_FAN_MOVER_SKIP_", 0) == 0) {
+ // Internal markers: read here, then dropped from the output.
+ m_is_custom_gcode = line.raw().rfind(";_FAN_MOVER_SKIP_START", 0) == 0;
+ time = -1;
+ }
if (line.raw().size() > 16) {
if (line.raw().rfind("; custom gcode", 0) != std::string::npos) {
if (line.raw().rfind("; custom gcode end", 0) != std::string::npos)
diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp
index 8e7d5e7557..9d166805a5 100644
--- a/src/libslic3r/GCode/GCodeProcessor.cpp
+++ b/src/libslic3r/GCode/GCodeProcessor.cpp
@@ -2602,12 +2602,13 @@ void GCodeProcessorResult::reset() {
//BBS: add mutex for protection of gcode result
lock();
- moves.clear();
+ // moves and lines_ends grow with the print: free them, as no reset result reuses the capacity.
+ clear_and_shrink(moves);
plate_mass = {};
object_masses.clear();
body_masses.clear();
support_masses.clear();
- lines_ends.clear();
+ clear_and_shrink(lines_ends);
printable_area = Pointfs();
//BBS: add bed exclude area
bed_exclude_area = Pointfs();
@@ -3598,6 +3599,10 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
if (has_scarf_joint_seam != nullptr)
m_detect_layer_based_on_tag = m_detect_layer_based_on_tag || has_scarf_joint_seam->value;
+ const ConfigOptionBool* manual_filament_change = config.option("manual_filament_change");
+ if (manual_filament_change != nullptr)
+ m_manual_filament_change = manual_filament_change->value;
+
const ConfigOptionEnumGeneric *bed_type = config.option("curr_bed_type");
if (bed_type != nullptr)
m_result.bed_type = (BedType)bed_type->value;
diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp
index f5b9985f0e..270aceb1c3 100644
--- a/src/libslic3r/GCode/GCodeProcessor.hpp
+++ b/src/libslic3r/GCode/GCodeProcessor.hpp
@@ -1228,7 +1228,7 @@ inline constexpr float DEFAULT_FILAMENT_DENSITY = 1.245f;
// m_result.nozzle_group_result, which is handed over only after the stream for the
// pre-heat injector's second pass and gates the richer change-time model.
std::shared_ptr m_nozzle_group_result;
- bool m_manual_filament_change;
+ bool m_manual_filament_change{ false };
//BBS: x, y offset for gcode generated
double m_x_offset{ 0 };
diff --git a/src/libslic3r/JumpPointSearch.cpp b/src/libslic3r/JumpPointSearch.cpp
deleted file mode 100644
index 9eb18017fb..0000000000
--- a/src/libslic3r/JumpPointSearch.cpp
+++ /dev/null
@@ -1,349 +0,0 @@
-#include "JumpPointSearch.hpp"
-#include "BoundingBox.hpp"
-#include "ExPolygon.hpp"
-#include "Point.hpp"
-#include "libslic3r/AStar.hpp"
-#include "libslic3r/KDTreeIndirect.hpp"
-#include "libslic3r/Polygon.hpp"
-#include "libslic3r/Polyline.hpp"
-#include "libslic3r/libslic3r.h"
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-
-//#define DEBUG_FILES
-#ifdef DEBUG_FILES
-#include "libslic3r/SVG.hpp"
-#endif
-
-namespace Slic3r {
-
-// execute fn for each pixel on the line. If fn returns false, terminate the iteration
-template void dda(coord_t x0, coord_t y0, coord_t x1, coord_t y1, const PointFn &fn)
-{
- coord_t dx = abs(x1 - x0);
- coord_t dy = abs(y1 - y0);
- coord_t x = x0;
- coord_t y = y0;
- coord_t n = 1 + dx + dy;
- coord_t x_inc = (x1 > x0) ? 1 : -1;
- coord_t y_inc = (y1 > y0) ? 1 : -1;
- coord_t error = dx - dy;
- dx *= 2;
- dy *= 2;
-
- for (; n > 0; --n) {
- if (!fn(x, y)) return;
-
- if (error > 0) {
- x += x_inc;
- error -= dy;
- } else {
- y += y_inc;
- error += dx;
- }
- }
-}
-
-// will draw the line twice, second time with and offset of 1 in the direction of normal
-// may call the fn on the same coordiantes multiple times!
-template void double_dda_with_offset(coord_t x0, coord_t y0, coord_t x1, coord_t y1, const PointFn &fn)
-{
- Vec2d normal = Point{y1 - y0, x1 - x0}.cast().normalized();
- normal.x() = ceil(normal.x());
- normal.y() = ceil(normal.y());
- Point start_offset = Point(x0, y0) + (normal).cast();
- Point end_offset = Point(x1, y1) + (normal).cast();
-
- dda(x0, y0, x1, y1, fn);
- dda(start_offset.x(), start_offset.y(), end_offset.x(), end_offset.y(), fn);
-}
-
-template class JPSTracer
-{
-public:
- // Use incoming_dir [0,0] for starting points, so that all directions are checked from that point
- struct Node
- {
- CellPositionType position;
- CellPositionType incoming_dir;
- };
-
- JPSTracer(CellPositionType target, CellQueryFn is_passable) : target(target), is_passable(is_passable) {}
-
-private:
- CellPositionType target;
- CellQueryFn is_passable; // should return boolean whether the cell is passable or not
-
- CellPositionType find_jump_point(CellPositionType start, CellPositionType forward_dir) const
- {
- CellPositionType next = start + forward_dir;
- while (next != target && is_passable(next) && !(is_jump_point(next, forward_dir))) { next = next + forward_dir; }
-
- if (is_passable(next)) {
- return next;
- } else {
- return start;
- }
- }
-
- bool is_jump_point(CellPositionType pos, CellPositionType forward_dir) const
- {
- if (abs(forward_dir.x()) + abs(forward_dir.y()) == 2) {
- // diagonal
- CellPositionType horizontal_check_dir = CellPositionType{forward_dir.x(), 0};
- CellPositionType vertical_check_dir = CellPositionType{0, forward_dir.y()};
-
- if (!is_passable(pos - horizontal_check_dir) && is_passable(pos + forward_dir - 2 * horizontal_check_dir)) { return true; }
-
- if (!is_passable(pos - vertical_check_dir) && is_passable(pos + forward_dir - 2 * vertical_check_dir)) { return true; }
-
- if (find_jump_point(pos, horizontal_check_dir) != pos) { return true; }
-
- if (find_jump_point(pos, vertical_check_dir) != pos) { return true; }
-
- return false;
- } else { // horizontal or vertical
- CellPositionType side_dir = CellPositionType(forward_dir.y(), forward_dir.x());
-
- if (!is_passable(pos + side_dir) && is_passable(pos + forward_dir + side_dir)) { return true; }
-
- if (!is_passable(pos - side_dir) && is_passable(pos + forward_dir - side_dir)) { return true; }
-
- return false;
- }
- }
-
-public:
- template void foreach_reachable(const Node &from, Fn &&fn) const
- {
- const CellPositionType & pos = from.position;
- const CellPositionType & forward_dir = from.incoming_dir;
- std::vector dirs_to_check{};
-
- if (abs(forward_dir.x()) + abs(forward_dir.y()) == 0) { // special case for starting point
- dirs_to_check = all_directions;
- } else if (abs(forward_dir.x()) + abs(forward_dir.y()) == 2) {
- // diagonal
- CellPositionType horizontal_check_dir = CellPositionType{forward_dir.x(), 0};
- CellPositionType vertical_check_dir = CellPositionType{0, forward_dir.y()};
-
- if (!is_passable(pos - horizontal_check_dir) && is_passable(pos + forward_dir - 2 * horizontal_check_dir)) {
- dirs_to_check.push_back(forward_dir - 2 * horizontal_check_dir);
- }
-
- if (!is_passable(pos - vertical_check_dir) && is_passable(pos + forward_dir - 2 * vertical_check_dir)) {
- dirs_to_check.push_back(forward_dir - 2 * vertical_check_dir);
- }
-
- dirs_to_check.push_back(horizontal_check_dir);
- dirs_to_check.push_back(vertical_check_dir);
- dirs_to_check.push_back(forward_dir);
-
- } else { // horizontal or vertical
- CellPositionType side_dir = CellPositionType(forward_dir.y(), forward_dir.x());
-
- if (!is_passable(pos + side_dir) && is_passable(pos + forward_dir + side_dir)) { dirs_to_check.push_back(forward_dir + side_dir); }
-
- if (!is_passable(pos - side_dir) && is_passable(pos + forward_dir - side_dir)) { dirs_to_check.push_back(forward_dir - side_dir); }
- dirs_to_check.push_back(forward_dir);
- }
-
- for (const CellPositionType &dir : dirs_to_check) {
- CellPositionType jp = find_jump_point(pos, dir);
- if (jp != pos) fn(Node{jp, dir});
- }
- }
-
- float distance(Node a, Node b) const { return (a.position - b.position).template cast().norm(); }
-
- float goal_heuristic(Node n) const { return n.position == target ? -1.f : (target - n.position).template cast().norm(); }
-
- size_t unique_id(Node n) const { return (static_cast(uint16_t(n.position.x())) << 16) + static_cast(uint16_t(n.position.y())); }
-
- const std::vector all_directions{{1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}, {-1, -1}, {0, -1}, {1, -1}};
-};
-
-void JPSPathFinder::clear()
-{
- inpassable.clear();
- max_search_box.max = Pixel(std::numeric_limits::min(), std::numeric_limits::min());
- max_search_box.min = Pixel(std::numeric_limits::max(), std::numeric_limits::max());
- add_obstacles(bed_shape);
-}
-
-void JPSPathFinder::add_obstacles(const Lines &obstacles)
-{
- auto store_obstacle = [&](coord_t x, coord_t y) {
- max_search_box.max.x() = std::max(max_search_box.max.x(), x);
- max_search_box.max.y() = std::max(max_search_box.max.y(), y);
- max_search_box.min.x() = std::min(max_search_box.min.x(), x);
- max_search_box.min.y() = std::min(max_search_box.min.y(), y);
- inpassable.insert(Pixel{x, y});
- return true;
- };
-
- for (const Line &l : obstacles) {
- Pixel start = pixelize(l.a);
- Pixel end = pixelize(l.b);
- double_dda_with_offset(start.x(), start.y(), end.x(), end.y(), store_obstacle);
- }
-}
-
-Polyline JPSPathFinder::find_path(const Point &p0, const Point &p1)
-{
- Pixel start = pixelize(p0);
- Pixel end = pixelize(p1);
- if (inpassable.empty() || (start - end).cast().norm() < 3.0) { return Polyline{p0, p1}; }
-
- if (inpassable.find(start) != inpassable.end()) {
- dda(start.x(), start.y(), end.x(), end.y(), [&](coord_t x, coord_t y) {
- if (inpassable.find(Pixel(x, y)) == inpassable.end() || start == end) { // new start not found yet, and xy passable
- start = Pixel(x, y);
- return false;
- }
- return true;
- });
- }
-
- if (inpassable.find(end) != inpassable.end()) {
- dda(end.x(), end.y(), start.x(), start.y(), [&](coord_t x, coord_t y) {
- if (inpassable.find(Pixel(x, y)) == inpassable.end() || start == end) { // new start not found yet, and xy passable
- end = Pixel(x, y);
- return false;
- }
- return true;
- });
- }
-
- BoundingBox search_box = max_search_box;
- search_box.max -= Pixel(1, 1);
- search_box.min += Pixel(1, 1);
-
- BoundingBox bounding_square(Points{start, end});
- bounding_square.max += Pixel(5, 5);
- bounding_square.min -= Pixel(5, 5);
- coord_t bounding_square_size = 2 * std::max(bounding_square.size().x(), bounding_square.size().y());
- bounding_square.max.x() += (bounding_square_size - bounding_square.size().x()) / 2;
- bounding_square.min.x() -= (bounding_square_size - bounding_square.size().x()) / 2;
- bounding_square.max.y() += (bounding_square_size - bounding_square.size().y()) / 2;
- bounding_square.min.y() -= (bounding_square_size - bounding_square.size().y()) / 2;
-
- // Intersection - limit the search box to a square area around the start and end, to fasten the path searching
- search_box.max = search_box.max.cwiseMin(bounding_square.max);
- search_box.min = search_box.min.cwiseMax(bounding_square.min);
-
- auto cell_query = [&](Pixel pixel) { return search_box.contains(pixel) && (pixel == start || pixel == end || inpassable.find(pixel) == inpassable.end()); };
-
- JPSTracer tracer(end, cell_query);
- using QNode = astar::QNode>;
-
- std::unordered_map astar_cache{};
- std::vector> out_path;
- std::vector out_nodes;
-
- if (!astar::search_route(tracer, {start, {0, 0}}, std::back_inserter(out_nodes), astar_cache)) {
- // path not found - just reconstruct the best path from astar cache.
- // Note that astar_cache is NOT empty - at least the starting point should always be there
- auto coordiante_func = [&astar_cache](size_t idx, size_t dim) { return float(astar_cache[idx].node.position[dim]); };
- std::vector keys;
- keys.reserve(astar_cache.size());
- for (const auto &pair : astar_cache) { keys.push_back(pair.first); }
- KDTreeIndirect<2, float, decltype(coordiante_func)> kd_tree(coordiante_func, keys);
- size_t closest_qnode = find_closest_point(kd_tree, end.cast());
-
- out_path.push_back(end);
- while (closest_qnode != astar::Unassigned) {
- out_path.push_back(astar_cache[closest_qnode].node.position);
- closest_qnode = astar_cache[closest_qnode].parent;
- }
- } else {
- for (const auto &node : out_nodes) { out_path.push_back(node.position); }
- out_path.push_back(start);
- }
-
-#ifdef DEBUG_FILES
- auto scaled_points = [](const Points &ps) {
- Points r;
- for (const Point &p : ps) { r.push_back(Point::new_scale(p.x(), p.y())); }
- return r;
- };
- auto scaled_point = [](const Point &p) { return Point::new_scale(p.x(), p.y()); };
- ::Slic3r::SVG svg(debug_out_path(("path_jps" + std::to_string(print_z) + "_" + std::to_string(rand() % 1000)).c_str()).c_str(),
- BoundingBox(scaled_point(search_box.min), scaled_point(search_box.max)));
- for (const auto &p : inpassable) { svg.draw(scaled_point(p), "black", scale_(0.4)); }
- for (const auto &qn : astar_cache) { svg.draw(scaled_point(qn.second.node.position), "blue", scale_(0.3)); }
- svg.draw(Polyline(scaled_points(out_path)), "yellow", scale_(0.25));
- svg.draw(scaled_point(end), "purple", scale_(0.4));
- svg.draw(scaled_point(start), "green", scale_(0.4));
-#endif
-
- std::vector> tmp_path;
- tmp_path.reserve(out_path.size());
- // Some path found, reverse and remove points that do not change direction
- std::reverse(out_path.begin(), out_path.end());
- {
- tmp_path.push_back(out_path.front()); // first point
- for (size_t i = 1; i < out_path.size() - 1; i++) {
- if ((out_path[i] - out_path[i - 1]).cast().normalized() != (out_path[i + 1] - out_path[i]).cast().normalized()) { tmp_path.push_back(out_path[i]); }
- }
- tmp_path.push_back(out_path.back()); // last_point
- out_path = tmp_path;
- }
-
-#ifdef DEBUG_FILES
- svg.draw(Polyline(scaled_points(out_path)), "orange", scale_(0.20));
-#endif
-
- tmp_path.clear();
- // remove redundant jump points - there are points that change direction but are not needed - this inefficiency arises from the
- // usage of grid search The removal alg tries to find the longest Px Px+k path without obstacles. If Px Px+k+1 is blocked, it will
- // insert the Px+k point to result and continue search from Px+k
- {
- tmp_path.push_back(out_path.front()); // first point
- size_t index_of_last_stored_point = 0;
- for (size_t i = 1; i < out_path.size(); i++) {
- if (i - index_of_last_stored_point < 2) continue;
- bool passable = true;
- auto store_obstacle = [&](coord_t x, coord_t y) {
- if (Pixel(x, y) != start && Pixel(x, y) != end && inpassable.find(Pixel(x, y)) != inpassable.end()) {
- passable = false;
- return false;
- }
- return true;
- };
- dda(tmp_path.back().x(), tmp_path.back().y(), out_path[i].x(), out_path[i].y(), store_obstacle);
- if (!passable) {
- tmp_path.push_back(out_path[i - 1]);
- index_of_last_stored_point = i - 1;
- }
- }
- tmp_path.push_back(out_path.back()); // last_point
- out_path = tmp_path;
- }
-
-#ifdef DEBUG_FILES
- svg.draw(Polyline(scaled_points(out_path)), "red", scale_(0.15));
- svg.Close();
-#endif
-
- // before returing the path, transform it from pixels back to points.
- // Also replace the first and last pixel by input points so that result path patches input params exactly.
- for (Pixel &p : out_path) { p = unpixelize(p); }
- out_path.front() = p0;
- out_path.back() = p1;
-
- return Polyline(out_path);
-}
-
-} // namespace Slic3r
diff --git a/src/libslic3r/JumpPointSearch.hpp b/src/libslic3r/JumpPointSearch.hpp
deleted file mode 100644
index b5fbf6aaf0..0000000000
--- a/src/libslic3r/JumpPointSearch.hpp
+++ /dev/null
@@ -1,39 +0,0 @@
-#pragma once
-#include "Line.hpp"
-#ifndef SRC_LIBSLIC3R_JUMPPOINTSEARCH_HPP_
-#define SRC_LIBSLIC3R_JUMPPOINTSEARCH_HPP_
-
-#include "BoundingBox.hpp"
-#include "Polygon.hpp"
-#include "libslic3r/Layer.hpp"
-#include "libslic3r/Point.hpp"
-#include "libslic3r/Polyline.hpp"
-#include "libslic3r/libslic3r.h"
-#include
-#include
-
-namespace Slic3r {
-
-class JPSPathFinder
-{
- using Pixel = Point;
- std::unordered_set inpassable;
- coordf_t print_z;
- BoundingBox max_search_box;
- Lines bed_shape;
-
- const coord_t resolution = scaled(1.5);
- Pixel pixelize(const Point &p) { return p / resolution; }
- Point unpixelize(const Pixel &p) { return p * resolution; }
-
-public:
- JPSPathFinder() = default;
- void init_bed_shape(const Points &bed_shape) { this->bed_shape = (to_lines(Polygon{bed_shape})); };
- void clear();
- void add_obstacles(const Lines &obstacles);
- Polyline find_path(const Point &start, const Point &end);
-};
-
-} // namespace Slic3r
-
-#endif /* SRC_LIBSLIC3R_JUMPPOINTSEARCH_HPP_ */
diff --git a/src/libslic3r/MeshBoolean.cpp b/src/libslic3r/MeshBoolean.cpp
index 37e3c84b3f..074eff3121 100644
--- a/src/libslic3r/MeshBoolean.cpp
+++ b/src/libslic3r/MeshBoolean.cpp
@@ -29,8 +29,6 @@
#include
#include
#include
-#include
-#include
#include
#include