diff --git a/.github/workflows/build_all.yml b/.github/workflows/build_all.yml index 376ef74b1f..49e6f58fd6 100644 --- a/.github/workflows/build_all.yml +++ b/.github/workflows/build_all.yml @@ -122,54 +122,73 @@ jobs: arch: universal macos-combine-only: true secrets: inherit - unit_tests: - name: Unit Tests - # Tests are built on the aarch64 leg by default (faster GitHub arm runner), - # so run them there; self-hosted builds them on the amd64 server instead. - runs-on: ${{ vars.SELF_HOSTED && 'orca-lnx-server' || 'ubuntu-24.04-arm' }} + # One test job per built arch, on the runner that built it. + unit_tests_linux_x86_64: + name: Linux x86_64 needs: build_linux if: ${{ !cancelled() && success() }} + uses: ./.github/workflows/unit_tests.yml + with: + os: ${{ vars.SELF_HOSTED && 'orca-lnx-server' || 'ubuntu-24.04' }} + artifact: ${{ github.sha }}-tests-linux-x86_64 + unit_tests_linux_aarch64: + name: Linux aarch64 + needs: build_linux + if: ${{ !cancelled() && success() }} + uses: ./.github/workflows/unit_tests.yml + with: + os: ubuntu-24.04-arm + artifact: ${{ github.sha }}-tests-linux-aarch64 + unit_tests_windows_x64: + name: Windows x64 + needs: build_windows + if: ${{ !cancelled() && success() }} + uses: ./.github/workflows/unit_tests.yml + with: + os: ${{ vars.SELF_HOSTED && 'orca-win-server' || 'windows-latest' }} + artifact: ${{ github.sha }}-tests-windows-x64 + unit_tests_windows_arm64: + name: Windows arm64 + needs: build_windows + if: ${{ !cancelled() && success() }} + uses: ./.github/workflows/unit_tests.yml + with: + os: windows-11-arm + artifact: ${{ github.sha }}-tests-windows-arm64 + test-dir: build-arm64/tests + unit_tests_macos_arm64: + name: macOS arm64 + needs: build_macos_arch + if: ${{ !cancelled() && success() }} + uses: ./.github/workflows/unit_tests.yml + with: + os: ${{ vars.SELF_HOSTED && 'orca-macos-arm64' || 'macos-14' }} + artifact: ${{ github.sha }}-tests-macos-arm64 + test-dir: build/arm64/tests + publish_test_results: + name: Publish Test Results + needs: [unit_tests_linux_x86_64, unit_tests_linux_aarch64, unit_tests_windows_x64, unit_tests_windows_arm64, unit_tests_macos_arm64] + if: ${{ !cancelled() }} + runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@v7 - with: - sparse-checkout: | - .github - scripts - tests - - name: Apt-Install Dependencies - if: ${{ !vars.SELF_HOSTED }} - uses: ./.github/actions/apt-install-deps - - name: Restore Test Artifact + - name: Download Test Results uses: actions/download-artifact@v8 with: - name: ${{ github.sha }}-tests - - uses: lukka/get-cmake@latest - with: - cmakeVersion: "~4.3.0" # use most recent 4.3.x version - useLocalCache: true # <--= Use the local cache (default is 'false'). - useCloudCache: true - - name: Unpackage and Run Unit Tests - timeout-minutes: 20 - run: | - tar -xvf build_tests.tar - scripts/run_unit_tests.sh - - name: Upload Test Logs - uses: actions/upload-artifact@v7 - if: ${{ failure() }} - with: - name: unit-test-logs - path: build/tests/**/*.log + pattern: test-results-* + path: test-results + # Best-effort: a read-only token (e.g. fork PRs) can't write the check, so + # don't let a publish failure fail the run. The test jobs gate correctness. - name: Publish Test Results - if: always() + continue-on-error: true uses: EnricoMi/publish-unit-test-result-action@v2 with: - files: "ctest_results.xml" - - name: Delete Test Artifact + files: "test-results/**/*.xml" + - name: Delete Test Results if: success() uses: geekyeggo/delete-artifact@v6 with: - name: ${{ github.sha }}-tests + name: test-results-* + failOnError: false flatpak: name: "Flatpak" container: diff --git a/.github/workflows/build_orca.yml b/.github/workflows/build_orca.yml index ffe4c35f8d..21c65283a9 100644 --- a/.github/workflows/build_orca.yml +++ b/.github/workflows/build_orca.yml @@ -141,8 +141,26 @@ jobs: - name: Build slicer mac if: runner.os == 'macOS' && !inputs.macos-combine-only working-directory: ${{ github.workspace }} + # arm64 only: build the tests here; the unit_tests_macos job runs them. + env: + ORCA_TESTS_BUILD_ONLY: ${{ inputs.arch == 'arm64' && '1' || '' }} run: | - ./build_release_macos.sh -s -n -x ${{ !vars.SELF_HOSTED && '-1' || '' }} -a ${{ inputs.arch }} -t 10.15 + ./build_release_macos.sh -s -n -x ${{ !vars.SELF_HOSTED && '-1' || '' }} -a ${{ inputs.arch }} -t 10.15 ${{ inputs.arch == 'arm64' && '-T' || '' }} + + - name: Pack unit tests mac + if: runner.os == 'macOS' && !inputs.macos-combine-only && inputs.arch == 'arm64' + working-directory: ${{ github.workspace }} + run: tar -cvf build_tests.tar build/arm64/tests + + - name: Upload Test Artifact mac + if: runner.os == 'macOS' && !inputs.macos-combine-only && inputs.arch == 'arm64' + uses: actions/upload-artifact@v7 + with: + name: ${{ github.sha }}-tests-macos-arm64 + overwrite: true + path: build_tests.tar + retention-days: 5 + if-no-files-found: error - name: Pack macOS app bundle ${{ inputs.arch }} if: runner.os == 'macOS' && !inputs.macos-combine-only @@ -335,11 +353,28 @@ jobs: # 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: | $arch = "${{ inputs.arch }}" - if ($arch -eq "arm64") { .\build_release_vs.bat slicer arm64 } else { .\build_release_vs.bat slicer } + if ($arch -eq "arm64") { .\build_release_vs.bat slicer arm64 tests } else { .\build_release_vs.bat slicer tests } shell: pwsh + - name: Pack unit tests Win + if: runner.os == 'Windows' + working-directory: ${{ github.workspace }} + shell: pwsh + run: tar -cvf build_tests.tar ${{ env.BUILD_DIR }}/tests + + - name: Upload Test Artifact Win + if: runner.os == 'Windows' + uses: actions/upload-artifact@v7 + with: + name: ${{ github.sha }}-tests-windows-${{ inputs.arch }} + overwrite: true + path: build_tests.tar + retention-days: 5 + if-no-files-found: error + # NSIS is x86-only; it runs (and the installer it emits runs) under ARM64's # x86 emulation, packaging the native arm64 payload from build-arm64. - name: Create installer Win @@ -452,26 +487,22 @@ jobs: if: runner.os == 'Linux' shell: bash run: | - # Build + tar the unit tests (-t) only on the leg that runs them: the - # aarch64 leg by default (faster GitHub arm runner), or amd64 when using - # self-hosted runners (no arm self-hosted server). unit_tests downloads - # this tarball. The profile validator is built with -s, so amd64 keeps it. - tests=${{ (!vars.SELF_HOSTED && inputs.arch == 'aarch64') || (vars.SELF_HOSTED && inputs.arch != 'aarch64') }} - if $tests; then flags=-istrlL; else flags=-isrlL; fi - ./build_linux.sh "$flags" + # Build + tar the unit tests (-t) on both Linux legs so each arch + # (x86_64 + aarch64) gets tested by its own unit_tests_linux_* job. + ./build_linux.sh -istrlL ./scripts/check_appimage_libs.sh ./build/package ./build/package/bin/orca-slicer appimage=./build/OrcaSlicer_Linux_AppImage${{ env.ubuntu-ver-str }}${{ env.arch_suffix }}_${{ env.ver }}.AppImage mv -n ./build/OrcaSlicer_Linux_V${{ env.ver_pure }}.AppImage "$appimage" chmod +x "$appimage" - if $tests; then tar -cvpf build_tests.tar build/tests; fi + tar -cvf build_tests.tar build/tests # Use tar because upload-artifacts won't always preserve directory structure # and doesn't preserve file permissions - name: Upload Test Artifact - if: runner.os == 'Linux' && ((!vars.SELF_HOSTED && inputs.arch == 'aarch64') || (vars.SELF_HOSTED && inputs.arch != 'aarch64')) + if: runner.os == 'Linux' uses: actions/upload-artifact@v7 with: - name: ${{ github.sha }}-tests + name: ${{ github.sha }}-tests-linux-${{ inputs.arch == 'aarch64' && 'aarch64' || 'x86_64' }} overwrite: true path: build_tests.tar retention-days: 5 diff --git a/.github/workflows/dedupe-issues.yml b/.github/workflows/dedupe-issues.yml index cb0a9c0931..a8c21edd01 100644 --- a/.github/workflows/dedupe-issues.yml +++ b/.github/workflows/dedupe-issues.yml @@ -27,7 +27,7 @@ jobs: with: prompt: "/dedupe ${{ github.repository }}/issues/${{ github.event.issue.number || inputs.issue_number }}" claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} - claude_args: "--model claude-sonnet-4-5-20250929" + model: "claude-sonnet-4-5-20250929" claude_env: | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml new file mode 100644 index 0000000000..0fe91c7440 --- /dev/null +++ b/.github/workflows/unit_tests.yml @@ -0,0 +1,73 @@ +name: Unit Tests + +# Download a platform's test artifact, run ctest, and upload the JUnit +# results for aggregation. Called once per arch from build_all.yml. +on: + workflow_call: + inputs: + os: + required: true + type: string + artifact: + description: Test artifact uploaded by the build leg + required: true + type: string + test-dir: + description: Built tests dir; defaults to build/tests, override for arch-separated builds + required: false + type: string + default: build/tests + +jobs: + unit_tests: + # Static "Unit Tests"; the per-arch label is the caller's job name, so the + # graph shows e.g. "Windows x64 / Unit Tests". + name: Unit Tests + runs-on: ${{ inputs.os }} + steps: + - name: Checkout + uses: actions/checkout@v7 + with: + # tests/data is referenced by absolute path (TEST_DATA_DIR). + sparse-checkout: | + .github + scripts + tests + - name: Apt-Install Dependencies + if: runner.os == 'Linux' && !vars.SELF_HOSTED + uses: ./.github/actions/apt-install-deps + - name: Restore Test Artifact + uses: actions/download-artifact@v8 + with: + name: ${{ inputs.artifact }} + - uses: lukka/get-cmake@latest + with: + cmakeVersion: "~4.3.0" # use most recent 4.3.x version + useLocalCache: true + useCloudCache: true + - name: Unpackage and Run Unit Tests + timeout-minutes: 20 + shell: bash + run: | + tar -xvf build_tests.tar + # Multi-config generators (Windows/macOS) need a config; Linux is single-config. + scripts/run_unit_tests.sh "${{ inputs.test-dir }}" "${{ runner.os != 'Linux' && 'Release' || '' }}" + - name: Upload Test Logs + if: ${{ failure() }} + uses: actions/upload-artifact@v7 + with: + name: unit-test-logs-${{ inputs.artifact }} + path: ${{ inputs.test-dir }}/**/*.log + - name: Upload Test Results + if: always() + uses: actions/upload-artifact@v7 + with: + name: test-results-${{ inputs.artifact }} + path: ctest_results.xml + retention-days: 5 + if-no-files-found: warn + - name: Delete Test Artifact + if: success() + uses: geekyeggo/delete-artifact@v6 + with: + name: ${{ inputs.artifact }} diff --git a/CMakeLists.txt b/CMakeLists.txt index 8dcd4cf004..2bd97d61cb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -710,7 +710,7 @@ endif () set(L10N_DIR "${SLIC3R_RESOURCES_DIR}/i18n") set(BBL_L18N_DIR "${CMAKE_CURRENT_SOURCE_DIR}/localization/i18n") add_custom_target(gettext_make_pot - COMMAND xgettext --keyword=L --keyword=_L --keyword=_u8L --keyword=L_CONTEXT:1,2c --keyword=_L_PLURAL:1,2 --add-comments=TRN --from-code=UTF-8 --no-location --debug --boost + COMMAND xgettext --keyword=L --keyword=_L --keyword=_u8L --keyword=L_CONTEXT:1,2c --keyword=_CTX:1,2c --keyword=_CTX_utf8:1,2c --keyword=_L_PLURAL:1,2 --add-comments=TRN --from-code=UTF-8 --no-location --debug --boost -f "${BBL_L18N_DIR}/list.txt" -o "${BBL_L18N_DIR}/OrcaSlicer.pot" COMMAND hintsToPot ${SLIC3R_RESOURCES_DIR} ${BBL_L18N_DIR} diff --git a/build_release_macos.sh b/build_release_macos.sh index 8d417695ad..1a86d2c515 100755 --- a/build_release_macos.sh +++ b/build_release_macos.sh @@ -59,7 +59,7 @@ while getopts ":dpa:snt:xbc:i:1Tuh" opt; do echo " -c: Set CMake build configuration, default is Release" echo " -i: Add a prefix to ignore during CMake dependency discovery (repeatable), defaults to /opt/local:/usr/local:/opt/homebrew" echo " -1: Use single job for building" - echo " -T: Build and run tests" + echo " -T: Build and run tests (set ORCA_TESTS_BUILD_ONLY=1 to build without running)" exit 0 ;; * ) @@ -209,13 +209,10 @@ function build_slicer() { cmake --build . --config "$BUILD_CONFIG" --target "$SLICER_BUILD_TARGET" ) - if [ "1." == "$BUILD_TESTS". ]; then - echo "Running tests for $_ARCH..." - ( - set -x - cd "$PROJECT_BUILD_DIR" - ctest --build-config "$BUILD_CONFIG" --output-on-failure - ) + # -T also runs the tests; ORCA_TESTS_BUILD_ONLY=1 builds them without + # running, so CI can build here and run them in a dedicated job. + if [ "1." == "$BUILD_TESTS". ] && [ "1." != "$ORCA_TESTS_BUILD_ONLY". ]; then + "$PROJECT_DIR/scripts/run_unit_tests.sh" "build/$_ARCH/tests" "$BUILD_CONFIG" fi echo "Verify localization with gettext..." diff --git a/build_release_vs.bat b/build_release_vs.bat index 0c1334d5f7..3288beda4c 100644 --- a/build_release_vs.bat +++ b/build_release_vs.bat @@ -20,6 +20,12 @@ for %%a in (%*) do ( if "%%a"=="-x" set USE_NINJA=1 ) +@REM Check for unit-tests option ("tests") +set BUILD_TESTS=OFF +for %%a in (%*) do ( + if /I "%%a"=="tests" set BUILD_TESTS=ON +) + if "%USE_NINJA%"=="1" ( echo Using Ninja Multi-Config generator set CMAKE_GENERATOR="Ninja Multi-Config" @@ -145,10 +151,10 @@ cd %build_dir% echo on set CMAKE_POLICY_VERSION_MINIMUM=3.5 if "%USE_NINJA%"=="1" ( - cmake .. -G %CMAKE_GENERATOR% -DORCA_TOOLS=ON %SIG_FLAG% -DCMAKE_BUILD_TYPE=%build_type% + cmake .. -G %CMAKE_GENERATOR% -DORCA_TOOLS=ON %SIG_FLAG% -DBUILD_TESTS=%BUILD_TESTS% -DCMAKE_BUILD_TYPE=%build_type% cmake --build . --config %build_type% --target ALL_BUILD ) else ( - cmake .. -G %CMAKE_GENERATOR% -A %arch% -DORCA_TOOLS=ON %SIG_FLAG% -DCMAKE_BUILD_TYPE=%build_type% + cmake .. -G %CMAKE_GENERATOR% -A %arch% -DORCA_TOOLS=ON %SIG_FLAG% -DBUILD_TESTS=%BUILD_TESTS% -DCMAKE_BUILD_TYPE=%build_type% cmake --build . --config %build_type% --target ALL_BUILD -- -m ) @echo off diff --git a/localization/i18n/OrcaSlicer.pot b/localization/i18n/OrcaSlicer.pot index 0a6697b152..34f91c9592 100644 --- a/localization/i18n/OrcaSlicer.pot +++ b/localization/i18n/OrcaSlicer.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-07-06 12:57-0300\n" +"POT-Creation-Date: 2026-07-12 12:27-0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -163,6 +163,12 @@ msgstr "" msgid "Gap Fill" msgstr "" +msgid "Vertical" +msgstr "" + +msgid "Horizontal" +msgstr "" + #, possible-boost-format msgid "Allows painting only on facets selected by: \"%1%\"" msgstr "" @@ -255,12 +261,6 @@ msgstr "" msgid "Height Range" msgstr "" -msgid "Vertical" -msgstr "" - -msgid "Horizontal" -msgstr "" - msgid "Remove painted color" msgstr "" @@ -325,6 +325,7 @@ msgstr "" msgid "Optimize orientation" msgstr "" +msgctxt "Verb" msgid "Scale" msgstr "" @@ -334,6 +335,7 @@ msgstr "" msgid "Error: Please close all toolbar menus first" msgstr "" +msgctxt "inches" msgid "in" msgstr "" @@ -367,6 +369,9 @@ msgstr "" msgid "Object operations" msgstr "" +msgid "Scale" +msgstr "" + msgid "Volume operations" msgstr "" @@ -412,6 +417,10 @@ msgstr "" msgid "Reset current rotation to real zeros." msgstr "" +msgctxt "Noun" +msgid "Scale" +msgstr "" + #. TRN - Input label. Be short as possible msgid "Size" msgstr "" @@ -3498,6 +3507,7 @@ msgstr "" msgid "Save" msgstr "" +msgctxt "Navigation" msgid "Back" msgstr "" @@ -4780,6 +4790,7 @@ msgstr "" msgid "Color change" msgstr "" +msgctxt "Noun" msgid "Print" msgstr "" @@ -4935,11 +4946,15 @@ msgstr "" msgid "Align to Y axis" msgstr "" -msgctxt "Camera" +msgctxt "Camera View" +msgid "Back" +msgstr "" + +msgctxt "Camera View" msgid "Left" msgstr "" -msgctxt "Camera" +msgctxt "Camera View" msgid "Right" msgstr "" @@ -5256,6 +5271,10 @@ msgstr "" msgid "Export G-code file" msgstr "" +msgctxt "Verb" +msgid "Print" +msgstr "" + msgid "Export plate sliced file" msgstr "" @@ -5429,15 +5448,6 @@ msgstr "" msgid "Export" msgstr "" -msgid "Sync Presets" -msgstr "" - -msgid "Pull and apply the latest presets from OrcaCloud" -msgstr "" - -msgid "You must be logged in to sync presets from cloud." -msgstr "" - msgid "Quit" msgstr "" @@ -5552,6 +5562,15 @@ msgstr "" msgid "Preset Bundle" msgstr "" +msgid "Sync Presets" +msgstr "" + +msgid "Pull and apply the latest presets from OrcaCloud" +msgstr "" + +msgid "You must be logged in to sync presets from cloud." +msgstr "" + msgid "Syncing presets from cloud…" msgstr "" @@ -9832,11 +9851,7 @@ msgstr "" msgid "Successfully synchronized nozzle and AMS number information." msgstr "" -msgid "Continue to sync filaments" -msgstr "" - -msgctxt "Sync_Nozzle_AMS" -msgid "Cancel" +msgid "Do you want to continue to sync filaments?" msgstr "" msgid "Successfully synchronized filament color from printer." @@ -11072,7 +11087,7 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." @@ -11086,7 +11101,7 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." @@ -11710,6 +11725,42 @@ msgstr "" msgid "Density of top surface layer. A value of 100% creates a fully solid, smooth top layer. Reducing this value results in a textured top surface, according to the chosen top surface pattern. A value of 0% will result in only the walls on the top layer being created. Intended for aesthetic or functional purposes, not to fix issues such as over-extrusion." msgstr "" +msgid "Top surface expansion" +msgstr "" + +msgid "" +"Expands the top surfaces by this distance to connect distinct top surfaces and fill gaps.\n" +"Useful for cases where the top surface is interrupted by a raised feature, such as text on a plane.Expanding it removes the holes beneath these features and creates a continuous path with a better finish for printing on top.The expansion is applied to the original top surface, before any other processing such as bridging or overhang detection." +msgstr "" + +msgid "Top expansion wall margin" +msgstr "" + +msgid "" +"Using “Top surface expansion” may cause a surface that did not previously touch the model's outer walls to now do so.\n" +"This can cause contraction marks (such as the hull line) on the outer walls.\n" +"By adding a small margin, this contraction will not occur directly on the walls, thereby preventing a visible mark." +msgstr "" + +msgid "Top expansion direction" +msgstr "" + +msgid "" +"Direction in which the top surface expansion grows.\n" +" - Inward grows into the holes and gaps left by features rising from the middle of a top surface.\n" +" - Outward grows the outer edge of the surface, connecting surfaces separated by features that can divide a surface, such as a lattice pattern.\n" +" - Inward and Outward does both." +msgstr "" + +msgid "Inward and Outward" +msgstr "" + +msgid "Inward" +msgstr "" + +msgid "Outward" +msgstr "" + msgid "Bottom surface pattern" msgstr "" @@ -12310,12 +12361,12 @@ msgstr "" msgid "Density of internal sparse infill, 100% turns all sparse infill into solid infill and internal solid infill pattern will be used." msgstr "" -msgid "Align infill direction to model" +msgid "Align directions to model" msgstr "" msgid "" -"Aligns infill, bridge, ironing and surface fill directions to follow the model's orientation on the build plate.\n" -"When enabled, directions rotate with the model to maintain optimal strength characteristics." +"Aligns infill, bridge, ironing, and top/bottom surface directions to follow the model's orientation on the build plate.\n" +"When enabled, these directions rotate together with the model so the printed features keep their intended orientation relative to the part, preserving optimal strength and surface characteristics regardless of how the model is placed." msgstr "" msgid "Insert solid layers" @@ -13919,6 +13970,9 @@ msgstr "" msgid "Aligned back" msgstr "" +msgid "Back" +msgstr "" + msgid "Random" msgstr "" @@ -14253,6 +14307,18 @@ msgstr "" msgid "If enabled, all printing extruders will be primed at the front edge of the print bed at the start of the print." msgstr "" +msgid "Toolchange ordering" +msgstr "" + +msgid "" +"Determines the order of tool changes on each layer.\n" +"- Default: Starts with the last used extruder to minimize tool changes.\n" +"- Cyclic: Uses a fixed tool sequence each layer. This sacrifices speed for better surface quality, as the extra toolchanges allow layers more time to cool." +msgstr "" + +msgid "Cyclic" +msgstr "" + msgid "Slice gap closing radius" msgstr "" @@ -14656,6 +14722,45 @@ msgstr "" msgid "The number of top solid layers is increased when slicing if the thickness calculated by top shell layers is thinner than this value. This can avoid having too thin a shell when layer height is small. 0 means that this setting is disabled and thickness of top shell is determined simply by the number of top shell layers." msgstr "" +msgid "Anisotropic surfaces" +msgstr "" + +msgid "" +"Anisotropic patterns on the top and bottom surfaces.\n" +"Co-directional printing mode will be applied. For certain patterns, omni-directional filling provides color dispersion when using multi-colored or silk plastics.\n" +"This option disable the gap fill.\n" +"This option can increase a printing time." +msgstr "" + +msgid "Separated infills" +msgstr "" + +msgid "" +"Centers the internal infill of each part on itself, as if it were sliced on its own, instead of on the whole assembly. Parts that touch or overlap are treated as one body and share a center; separate parts (or distinct 3D objects) each get their own.\n" +"Useful when an assembly groups several objects that should each keep a consistent, self-centered infill.\n" +"Affects line and grid patterns and rotation-template infills.\n" +"Patterns locked to global coordinates (Gyroid, Honeycomb, TPMS, ...) are unaffected." +msgstr "" + +msgid "Center surface pattern on" +msgstr "" + +msgid "" +"Chooses where the centering point of centered top/bottom surface patterns (Archimedean Chords, Octagram Spiral) is placed.\n" +" - Each Surface: centers the pattern on every individual surface region, so each island is symmetric on its own.\n" +" - Each Model: centers the pattern on each connected body. Parts that touch or overlap share one center; parts detached from the rest each get their own.\n" +" - Each Assembly: uses a single shared center for the whole object or assembly." +msgstr "" + +msgid "Each Surface" +msgstr "" + +msgid "Each Model" +msgstr "" + +msgid "Each Assembly" +msgstr "" + msgid "This is the speed at which traveling is done." msgstr "" diff --git a/localization/i18n/ca/OrcaSlicer_ca.po b/localization/i18n/ca/OrcaSlicer_ca.po index 0e9564c9e3..aeccdefcc1 100644 --- a/localization/i18n/ca/OrcaSlicer_ca.po +++ b/localization/i18n/ca/OrcaSlicer_ca.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-07-06 12:57-0300\n" +"POT-Creation-Date: 2026-07-12 12:27-0300\n" "PO-Revision-Date: 2025-03-15 10:55+0100\n" "Last-Translator: \n" "Language-Team: \n" @@ -167,6 +167,12 @@ msgstr "Farcir" msgid "Gap Fill" msgstr "Farcir el buit" +msgid "Vertical" +msgstr "" + +msgid "Horizontal" +msgstr "Horitzontal" + #, boost-format msgid "Allows painting only on facets selected by: \"%1%\"" msgstr "Permet pintar només les facetes seleccionades per: \"%1%\"" @@ -262,12 +268,6 @@ msgstr "" msgid "Height Range" msgstr "Rang d'alçada" -msgid "Vertical" -msgstr "" - -msgid "Horizontal" -msgstr "Horitzontal" - msgid "Remove painted color" msgstr "Elimina el color pintat" @@ -332,6 +332,7 @@ msgstr "Gizmo-Rotació" msgid "Optimize orientation" msgstr "Optimitzar l'orientació" +msgctxt "Verb" msgid "Scale" msgstr "Escalar" @@ -341,8 +342,9 @@ msgstr "Gizmo-Escalar" msgid "Error: Please close all toolbar menus first" msgstr "Error: Tanqueu primer tots els menús de la barra d'eines" +msgctxt "inches" msgid "in" -msgstr "polç" +msgstr "" msgid "mm" msgstr "mm" @@ -375,6 +377,9 @@ msgstr "Ràtios d'escala" msgid "Object operations" msgstr "Operacions amb objectes" +msgid "Scale" +msgstr "Escalar" + # TODO: Review, changed by lang refactor. PR 14254 msgid "Volume operations" msgstr "Operacions de volum" @@ -426,6 +431,10 @@ msgstr "Restableix la rotació actual al valor d'quan s'ha obert l'eina de rotac msgid "Reset current rotation to real zeros." msgstr "Restableix la rotació actual a zeros reals." +msgctxt "Noun" +msgid "Scale" +msgstr "Escalar" + #. TRN - Input label. Be short as possible msgid "Size" msgstr "Mida" @@ -3651,7 +3660,7 @@ msgstr "Calibratge completat. Trobeu la línia d'extrusió més uniforme al vost msgid "Save" msgstr "Desar" -# TODO: Review, changed by lang refactor. PR 14254 +msgctxt "Navigation" msgid "Back" msgstr "Darrera" @@ -5034,6 +5043,7 @@ msgstr "Canvis d'eina" msgid "Color change" msgstr "Canvi de color" +msgctxt "Noun" msgid "Print" msgstr "Imprimir" @@ -5197,11 +5207,15 @@ msgstr "Evitar la regió de calibratge d'extrusió" msgid "Align to Y axis" msgstr "Alinear a l'eix Y" -msgctxt "Camera" +msgctxt "Camera View" +msgid "Back" +msgstr "Darrera" + +msgctxt "Camera View" msgid "Left" msgstr "Esquerra" -msgctxt "Camera" +msgctxt "Camera View" msgid "Right" msgstr "Dreta" @@ -5530,6 +5544,10 @@ msgstr "Imprimir placa d'impressió" msgid "Export G-code file" msgstr "Exportar el fitxer del Codi-G" +msgctxt "Verb" +msgid "Print" +msgstr "Imprimir" + msgid "Export plate sliced file" msgstr "Exportar fitxer de la placa laminada" @@ -5703,15 +5721,6 @@ msgstr "Exportar la configuració actual a fitxers" msgid "Export" msgstr "Exportar" -msgid "Sync Presets" -msgstr "" - -msgid "Pull and apply the latest presets from OrcaCloud" -msgstr "" - -msgid "You must be logged in to sync presets from cloud." -msgstr "" - msgid "Quit" msgstr "Surt" @@ -5828,6 +5837,15 @@ msgstr "Vista" msgid "Preset Bundle" msgstr "" +msgid "Sync Presets" +msgstr "" + +msgid "Pull and apply the latest presets from OrcaCloud" +msgstr "" + +msgid "You must be logged in to sync presets from cloud." +msgstr "" + msgid "Syncing presets from cloud…" msgstr "" @@ -10328,12 +10346,8 @@ msgstr "Informació del broquet sincronitzada correctament." msgid "Successfully synchronized nozzle and AMS number information." msgstr "Informació del broquet i nombre d'AMS sincronitzats correctament." -msgid "Continue to sync filaments" -msgstr "Continua sincronitzant filaments" - -msgctxt "Sync_Nozzle_AMS" -msgid "Cancel" -msgstr "Cancel·la" +msgid "Do you want to continue to sync filaments?" +msgstr "" msgid "Successfully synchronized filament color from printer." msgstr "Color del filament sincronitzat correctament de la impressora." @@ -11658,7 +11672,7 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." @@ -11672,7 +11686,7 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." @@ -12404,6 +12418,42 @@ msgstr "Densitat de la superfície superior" msgid "Density of top surface layer. A value of 100% creates a fully solid, smooth top layer. Reducing this value results in a textured top surface, according to the chosen top surface pattern. A value of 0% will result in only the walls on the top layer being created. Intended for aesthetic or functional purposes, not to fix issues such as over-extrusion." msgstr "Densitat de la capa de superfície superior. Un valor del 100% crea una capa superior completament sòlida i llisa. Reduir aquest valor resulta en una superfície superior texturada, segons el patró de superfície superior triat. Un valor del 0% resultarà en la creació de només les parets a la capa superior. Destinat a fins estètics o funcionals, no per solucionar problemes com la sobreextrusió." +msgid "Top surface expansion" +msgstr "" + +msgid "" +"Expands the top surfaces by this distance to connect distinct top surfaces and fill gaps.\n" +"Useful for cases where the top surface is interrupted by a raised feature, such as text on a plane.Expanding it removes the holes beneath these features and creates a continuous path with a better finish for printing on top.The expansion is applied to the original top surface, before any other processing such as bridging or overhang detection." +msgstr "" + +msgid "Top expansion wall margin" +msgstr "" + +msgid "" +"Using “Top surface expansion” may cause a surface that did not previously touch the model's outer walls to now do so.\n" +"This can cause contraction marks (such as the hull line) on the outer walls.\n" +"By adding a small margin, this contraction will not occur directly on the walls, thereby preventing a visible mark." +msgstr "" + +msgid "Top expansion direction" +msgstr "" + +msgid "" +"Direction in which the top surface expansion grows.\n" +" - Inward grows into the holes and gaps left by features rising from the middle of a top surface.\n" +" - Outward grows the outer edge of the surface, connecting surfaces separated by features that can divide a surface, such as a lattice pattern.\n" +" - Inward and Outward does both." +msgstr "" + +msgid "Inward and Outward" +msgstr "" + +msgid "Inward" +msgstr "" + +msgid "Outward" +msgstr "" + msgid "Bottom surface pattern" msgstr "Patró de superfície inferior" @@ -13069,12 +13119,12 @@ msgstr "Densitat de farciment poc dens" msgid "Density of internal sparse infill, 100% turns all sparse infill into solid infill and internal solid infill pattern will be used." msgstr "Densitat de farciment poc dens, converteix el 100% tu el teu farciment poc dens en farciment sòlid i s'utilitzarà el patró de farciment sòlid intern" -msgid "Align infill direction to model" -msgstr "Alinea la direcció del farciment al model" +msgid "Align directions to model" +msgstr "" msgid "" -"Aligns infill, bridge, ironing and surface fill directions to follow the model's orientation on the build plate.\n" -"When enabled, directions rotate with the model to maintain optimal strength characteristics." +"Aligns infill, bridge, ironing, and top/bottom surface directions to follow the model's orientation on the build plate.\n" +"When enabled, these directions rotate together with the model so the printed features keep their intended orientation relative to the part, preserving optimal strength and surface characteristics regardless of how the model is placed." msgstr "" msgid "Insert solid layers" @@ -14807,6 +14857,10 @@ msgstr "Alineat" msgid "Aligned back" msgstr "Alineat al darrere" +# TODO: Review, changed by lang refactor. PR 14254 +msgid "Back" +msgstr "Darrera" + msgid "Random" msgstr "Aleatori" @@ -15165,6 +15219,18 @@ msgstr "Purgar tots els extrusors d'impressió" msgid "If enabled, all printing extruders will be primed at the front edge of the print bed at the start of the print." msgstr "Si està habilitat, tots els extrusors d'impressió seran purgats a la vora frontal del llit d'impressió al començament de la impressió." +msgid "Toolchange ordering" +msgstr "" + +msgid "" +"Determines the order of tool changes on each layer.\n" +"- Default: Starts with the last used extruder to minimize tool changes.\n" +"- Cyclic: Uses a fixed tool sequence each layer. This sacrifices speed for better surface quality, as the extra toolchanges allow layers more time to cool." +msgstr "" + +msgid "Cyclic" +msgstr "" + msgid "Slice gap closing radius" msgstr "Radi de tancament dels buits en laminar" @@ -15611,6 +15677,45 @@ msgstr "Gruix mínim de la carcassa superior" msgid "The number of top solid layers is increased when slicing if the thickness calculated by top shell layers is thinner than this value. This can avoid having too thin a shell when layer height is small. 0 means that this setting is disabled and thickness of top shell is determined simply by the number of top shell layers." msgstr "El nombre de capes sòlides superiors augmenta quan es tallen si el gruix calculat per les capes de closca superior és més prim que aquest valor. Això pot evitar tenir una closca massa fina quan l'alçada de la capa és petita. 0 significa que aquesta configuració està desactivada i que el gruix de la carcassa superior està absolutament determinat per les capes de la carcassa superior" +msgid "Anisotropic surfaces" +msgstr "" + +msgid "" +"Anisotropic patterns on the top and bottom surfaces.\n" +"Co-directional printing mode will be applied. For certain patterns, omni-directional filling provides color dispersion when using multi-colored or silk plastics.\n" +"This option disable the gap fill.\n" +"This option can increase a printing time." +msgstr "" + +msgid "Separated infills" +msgstr "" + +msgid "" +"Centers the internal infill of each part on itself, as if it were sliced on its own, instead of on the whole assembly. Parts that touch or overlap are treated as one body and share a center; separate parts (or distinct 3D objects) each get their own.\n" +"Useful when an assembly groups several objects that should each keep a consistent, self-centered infill.\n" +"Affects line and grid patterns and rotation-template infills.\n" +"Patterns locked to global coordinates (Gyroid, Honeycomb, TPMS, ...) are unaffected." +msgstr "" + +msgid "Center surface pattern on" +msgstr "" + +msgid "" +"Chooses where the centering point of centered top/bottom surface patterns (Archimedean Chords, Octagram Spiral) is placed.\n" +" - Each Surface: centers the pattern on every individual surface region, so each island is symmetric on its own.\n" +" - Each Model: centers the pattern on each connected body. Parts that touch or overlap share one center; parts detached from the rest each get their own.\n" +" - Each Assembly: uses a single shared center for the whole object or assembly." +msgstr "" + +msgid "Each Surface" +msgstr "" + +msgid "Each Model" +msgstr "" + +msgid "Each Assembly" +msgstr "" + # TODO: Review, changed by lang refactor. PR 14254 msgid "This is the speed at which traveling is done." msgstr "Velocitat de desplaçament més ràpida i sense extrusió" @@ -19646,6 +19751,22 @@ msgstr "" "Evitar la deformació( warping )\n" "Sabíeu que quan imprimiu materials propensos a deformar-se, com ara l'ABS, augmentar adequadament la temperatura del llit pot reduir la probabilitat de deformació?" +#~ msgid "Continue to sync filaments" +#~ msgstr "Continua sincronitzant filaments" + +#~ msgctxt "Sync_Nozzle_AMS" +#~ msgid "Cancel" +#~ msgstr "Cancel·la" + +#~ msgid "Align infill direction to model" +#~ msgstr "Alinea la direcció del farciment al model" + +#~ msgid "Print" +#~ msgstr "Imprimir" + +#~ msgid "in" +#~ msgstr "polç" + #~ msgid "Object coordinates" #~ msgstr "Coordenades de l'objecte" @@ -21099,10 +21220,6 @@ msgstr "" #~ msgid "Unselect" #~ msgstr "Desmarcar" -#~ msgctxt "Verb" -#~ msgid "Scale" -#~ msgstr "Escalar" - #~ msgid "Lift Z Enforcement" #~ msgstr "Forçar elevació Z" diff --git a/localization/i18n/cs/OrcaSlicer_cs.po b/localization/i18n/cs/OrcaSlicer_cs.po index eec080338a..34dd852619 100644 --- a/localization/i18n/cs/OrcaSlicer_cs.po +++ b/localization/i18n/cs/OrcaSlicer_cs.po @@ -3,7 +3,7 @@ msgid "" msgstr "" "Project-Id-Version: Orca Slicer\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-07-06 12:57-0300\n" +"POT-Creation-Date: 2026-07-12 12:27-0300\n" "PO-Revision-Date: \n" "Last-Translator: Jakub Hencl\n" "Language-Team: \n" @@ -162,6 +162,12 @@ msgstr "Výplň" msgid "Gap Fill" msgstr "Vyplnění mezery" +msgid "Vertical" +msgstr "Vertikální" + +msgid "Horizontal" +msgstr "Vodorovně" + #, boost-format msgid "Allows painting only on facets selected by: \"%1%\"" msgstr "Umožňuje malování pouze na plochách vybraných podle: \"%1%\"" @@ -257,12 +263,6 @@ msgstr "Trojúhelník" msgid "Height Range" msgstr "Rozsah výšky" -msgid "Vertical" -msgstr "Vertikální" - -msgid "Horizontal" -msgstr "Vodorovně" - msgid "Remove painted color" msgstr "Odstranit nanesenou barvu" @@ -327,6 +327,7 @@ msgstr "Gizmo-Otočit" msgid "Optimize orientation" msgstr "Optimalizovat orientaci" +msgctxt "Verb" msgid "Scale" msgstr "Měřítko" @@ -336,8 +337,9 @@ msgstr "Gizmo-Měřítko" msgid "Error: Please close all toolbar menus first" msgstr "Nejprve prosím zavřete všechna menu nástrojové lišty" +msgctxt "inches" msgid "in" -msgstr "v" +msgstr "" msgid "mm" msgstr "mm" @@ -370,6 +372,9 @@ msgstr "Poměry měřítka" msgid "Object operations" msgstr "Operace s objektem" +msgid "Scale" +msgstr "Měřítko" + # TODO: Review, changed by lang refactor. PR 14254 msgid "Volume operations" msgstr "Operace s hlasitostí" @@ -421,6 +426,10 @@ msgstr "Obnovit aktuální rotaci na hodnotu při otevření nástroje pro rotac msgid "Reset current rotation to real zeros." msgstr "Obnovit aktuální rotaci na skutečné nuly." +msgctxt "Noun" +msgid "Scale" +msgstr "Měřítko" + #. TRN - Input label. Be short as possible msgid "Size" msgstr "Velikost" @@ -3650,7 +3659,7 @@ msgstr "Kalibrace byla dokončena. Najděte na vyhřívané podložce nejrovnom msgid "Save" msgstr "Uložit" -# TODO: Review, changed by lang refactor. PR 14254 +msgctxt "Navigation" msgid "Back" msgstr "Zpět" @@ -5031,6 +5040,7 @@ msgstr "Výměny nástrojů" msgid "Color change" msgstr "Změna barvy" +msgctxt "Noun" msgid "Print" msgstr "Tisk" @@ -5194,11 +5204,15 @@ msgstr "Vyhněte se kalibrační oblasti extruze" msgid "Align to Y axis" msgstr "Zarovnat na osu Y" -msgctxt "Camera" +msgctxt "Camera View" +msgid "Back" +msgstr "Zpět" + +msgctxt "Camera View" msgid "Left" msgstr "Levý" -msgctxt "Camera" +msgctxt "Camera View" msgid "Right" msgstr "Pravý" @@ -5526,6 +5540,10 @@ msgstr "Tisková deska" msgid "Export G-code file" msgstr "Exportovat G-code soubor" +msgctxt "Verb" +msgid "Print" +msgstr "Tisk" + msgid "Export plate sliced file" msgstr "Exportovat nařezaný soubor desky" @@ -5699,15 +5717,6 @@ msgstr "Exportovat aktuální konfiguraci do souborů" msgid "Export" msgstr "" -msgid "Sync Presets" -msgstr "" - -msgid "Pull and apply the latest presets from OrcaCloud" -msgstr "" - -msgid "You must be logged in to sync presets from cloud." -msgstr "" - msgid "Quit" msgstr "Ukončit" @@ -5824,6 +5833,15 @@ msgstr "Zobrazit" msgid "Preset Bundle" msgstr "Balík předvoleb" +msgid "Sync Presets" +msgstr "" + +msgid "Pull and apply the latest presets from OrcaCloud" +msgstr "" + +msgid "You must be logged in to sync presets from cloud." +msgstr "" + msgid "Syncing presets from cloud…" msgstr "" @@ -10333,11 +10351,7 @@ msgstr "" msgid "Successfully synchronized nozzle and AMS number information." msgstr "" -msgid "Continue to sync filaments" -msgstr "" - -msgctxt "Sync_Nozzle_AMS" -msgid "Cancel" +msgid "Do you want to continue to sync filaments?" msgstr "" msgid "Successfully synchronized filament color from printer." @@ -11664,7 +11678,7 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." @@ -11678,7 +11692,7 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." @@ -12408,6 +12422,42 @@ msgstr "Hustota horního povrchu" msgid "Density of top surface layer. A value of 100% creates a fully solid, smooth top layer. Reducing this value results in a textured top surface, according to the chosen top surface pattern. A value of 0% will result in only the walls on the top layer being created. Intended for aesthetic or functional purposes, not to fix issues such as over-extrusion." msgstr "Hustota horní povrchové vrstvy. Hodnota 100 % vytvoří zcela plnou, hladkou horní vrstvu. Snížením této hodnoty vznikne texturovaný horní povrch podle zvoleného vzoru horního povrchu. Hodnota 0 % znamená, že na horní vrstvě budou vytvořeny pouze stěny. Určeno pro estetické nebo funkční účely, nikoli k řešení problémů jako je nadměrná extruze." +msgid "Top surface expansion" +msgstr "" + +msgid "" +"Expands the top surfaces by this distance to connect distinct top surfaces and fill gaps.\n" +"Useful for cases where the top surface is interrupted by a raised feature, such as text on a plane.Expanding it removes the holes beneath these features and creates a continuous path with a better finish for printing on top.The expansion is applied to the original top surface, before any other processing such as bridging or overhang detection." +msgstr "" + +msgid "Top expansion wall margin" +msgstr "" + +msgid "" +"Using “Top surface expansion” may cause a surface that did not previously touch the model's outer walls to now do so.\n" +"This can cause contraction marks (such as the hull line) on the outer walls.\n" +"By adding a small margin, this contraction will not occur directly on the walls, thereby preventing a visible mark." +msgstr "" + +msgid "Top expansion direction" +msgstr "" + +msgid "" +"Direction in which the top surface expansion grows.\n" +" - Inward grows into the holes and gaps left by features rising from the middle of a top surface.\n" +" - Outward grows the outer edge of the surface, connecting surfaces separated by features that can divide a surface, such as a lattice pattern.\n" +" - Inward and Outward does both." +msgstr "" + +msgid "Inward and Outward" +msgstr "" + +msgid "Inward" +msgstr "" + +msgid "Outward" +msgstr "" + msgid "Bottom surface pattern" msgstr "Vzor spodního povrchu" @@ -13075,12 +13125,12 @@ msgstr "Hustota řídké výplně" msgid "Density of internal sparse infill, 100% turns all sparse infill into solid infill and internal solid infill pattern will be used." msgstr "Hustota vnitřní řídké výplně, 100 % přemění veškerou řídkou výplň na plnou a použije se vzor vnitřní plné výplně." -msgid "Align infill direction to model" -msgstr "Zarovnat směr výplně podle modelu" +msgid "Align directions to model" +msgstr "" msgid "" -"Aligns infill, bridge, ironing and surface fill directions to follow the model's orientation on the build plate.\n" -"When enabled, directions rotate with the model to maintain optimal strength characteristics." +"Aligns infill, bridge, ironing, and top/bottom surface directions to follow the model's orientation on the build plate.\n" +"When enabled, these directions rotate together with the model so the printed features keep their intended orientation relative to the part, preserving optimal strength and surface characteristics regardless of how the model is placed." msgstr "" msgid "Insert solid layers" @@ -14854,6 +14904,10 @@ msgstr "Zarovnáno" msgid "Aligned back" msgstr "Zarovnat zpět" +# TODO: Review, changed by lang refactor. PR 14254 +msgid "Back" +msgstr "Zpět" + msgid "Random" msgstr "Náhodně" @@ -15214,6 +15268,18 @@ msgstr "Připravit všechny tiskové extrudery" msgid "If enabled, all printing extruders will be primed at the front edge of the print bed at the start of the print." msgstr "Pokud je povoleno, všechny tiskové extrudery budou na začátku tisku připraveny na předním okraji tiskové podložky." +msgid "Toolchange ordering" +msgstr "" + +msgid "" +"Determines the order of tool changes on each layer.\n" +"- Default: Starts with the last used extruder to minimize tool changes.\n" +"- Cyclic: Uses a fixed tool sequence each layer. This sacrifices speed for better surface quality, as the extra toolchanges allow layers more time to cool." +msgstr "" + +msgid "Cyclic" +msgstr "" + msgid "Slice gap closing radius" msgstr "Poloměr uzavření mezery řezu" @@ -15653,6 +15719,45 @@ msgstr "Tloušťka horního pláště" msgid "The number of top solid layers is increased when slicing if the thickness calculated by top shell layers is thinner than this value. This can avoid having too thin a shell when layer height is small. 0 means that this setting is disabled and thickness of top shell is determined simply by the number of top shell layers." msgstr "Počet horních pevných vrstev bude při slicování zvýšen, pokud tloušťka vypočtená podle horních vrstev bude menší než tato hodnota. Tím lze předejít příliš tenké skořepině při malé výšce vrstvy. 0 znamená, že je nastavení vypnuté a tloušťka horní skořepiny je určena pouze počtem horních vrstev." +msgid "Anisotropic surfaces" +msgstr "" + +msgid "" +"Anisotropic patterns on the top and bottom surfaces.\n" +"Co-directional printing mode will be applied. For certain patterns, omni-directional filling provides color dispersion when using multi-colored or silk plastics.\n" +"This option disable the gap fill.\n" +"This option can increase a printing time." +msgstr "" + +msgid "Separated infills" +msgstr "" + +msgid "" +"Centers the internal infill of each part on itself, as if it were sliced on its own, instead of on the whole assembly. Parts that touch or overlap are treated as one body and share a center; separate parts (or distinct 3D objects) each get their own.\n" +"Useful when an assembly groups several objects that should each keep a consistent, self-centered infill.\n" +"Affects line and grid patterns and rotation-template infills.\n" +"Patterns locked to global coordinates (Gyroid, Honeycomb, TPMS, ...) are unaffected." +msgstr "" + +msgid "Center surface pattern on" +msgstr "" + +msgid "" +"Chooses where the centering point of centered top/bottom surface patterns (Archimedean Chords, Octagram Spiral) is placed.\n" +" - Each Surface: centers the pattern on every individual surface region, so each island is symmetric on its own.\n" +" - Each Model: centers the pattern on each connected body. Parts that touch or overlap share one center; parts detached from the rest each get their own.\n" +" - Each Assembly: uses a single shared center for the whole object or assembly." +msgstr "" + +msgid "Each Surface" +msgstr "" + +msgid "Each Model" +msgstr "" + +msgid "Each Assembly" +msgstr "" + # TODO: Review, changed by lang refactor. PR 14254 msgid "This is the speed at which traveling is done." msgstr "Rychlost přejezdu bez extruze." @@ -19680,6 +19785,15 @@ msgstr "" "Zamezte kroucení\n" "Víte, že při tisku materiálů náchylných ke kroucení, jako je ABS, může vhodné zvýšení teploty vyhřívané desky snížit pravděpodobnost kroucení?" +#~ msgid "Align infill direction to model" +#~ msgstr "Zarovnat směr výplně podle modelu" + +#~ msgid "Print" +#~ msgstr "Tisk" + +#~ msgid "in" +#~ msgstr "v" + #~ msgid "Object coordinates" #~ msgstr "Souřadnice objektu" diff --git a/localization/i18n/de/OrcaSlicer_de.po b/localization/i18n/de/OrcaSlicer_de.po index f4e05815dd..8ebfd41042 100644 --- a/localization/i18n/de/OrcaSlicer_de.po +++ b/localization/i18n/de/OrcaSlicer_de.po @@ -3,7 +3,7 @@ msgid "" msgstr "" "Project-Id-Version: Orca Slicer\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-07-06 12:57-0300\n" +"POT-Creation-Date: 2026-07-12 12:27-0300\n" "PO-Revision-Date: \n" "Last-Translator: Heiko Liebscher \n" "Language-Team: \n" @@ -162,6 +162,12 @@ msgstr "Ausfüllen" msgid "Gap Fill" msgstr "Lücken füllen" +msgid "Vertical" +msgstr "Vertikal" + +msgid "Horizontal" +msgstr "Horizontal" + #, boost-format msgid "Allows painting only on facets selected by: \"%1%\"" msgstr "Erlaubt das malen nur auf Seiten, welche ausgewählt wurden durch: \"%1%\"" @@ -257,12 +263,6 @@ msgstr "Dreieck" msgid "Height Range" msgstr "Höhenbereich" -msgid "Vertical" -msgstr "Vertikal" - -msgid "Horizontal" -msgstr "Horizontal" - msgid "Remove painted color" msgstr "Gemalte Farbe entfernen" @@ -327,6 +327,7 @@ msgstr "Gizmo-Drehen" msgid "Optimize orientation" msgstr "Optimiere Ausrichtung" +msgctxt "Verb" msgid "Scale" msgstr "Skalieren" @@ -336,8 +337,9 @@ msgstr "Gizmo-Skalieren" msgid "Error: Please close all toolbar menus first" msgstr "Fehler: Bitte schließen sie zuerst alle Werkzeugleistenmenüs" +msgctxt "inches" msgid "in" -msgstr "in" +msgstr "" msgid "mm" msgstr "mm" @@ -370,6 +372,9 @@ msgstr "Skalierungsverhältnisse" msgid "Object operations" msgstr "Objekt-Operationen" +msgid "Scale" +msgstr "Skalieren" + # TODO: Review, changed by lang refactor. PR 14254 msgid "Volume operations" msgstr "Volumen Operationen" @@ -421,6 +426,10 @@ msgstr "Setze die aktuelle Rotation auf den Wert zurück, als das Rotationswerkz msgid "Reset current rotation to real zeros." msgstr "Setze die aktuelle Rotation auf die realen Nullen zurück." +msgctxt "Noun" +msgid "Scale" +msgstr "Skalieren" + #. TRN - Input label. Be short as possible msgid "Size" msgstr "Größe" @@ -3653,7 +3662,7 @@ msgstr "Kalibrierung abgeschlossen. Bitte suchen Sie die gleichmäßigste Extrus msgid "Save" msgstr "Speichern" -# TODO: Review, changed by lang refactor. PR 14254 +msgctxt "Navigation" msgid "Back" msgstr "Zurück" @@ -5035,6 +5044,7 @@ msgstr "Werkzeugwechsel" msgid "Color change" msgstr "Farbwechsel" +msgctxt "Noun" msgid "Print" msgstr "aktuelle Platte drucken" @@ -5198,11 +5208,15 @@ msgstr "Vermeiden Sie den Bereich der Extrusionskalibrierung" msgid "Align to Y axis" msgstr "An Y-Achse ausrichten" -msgctxt "Camera" +msgctxt "Camera View" +msgid "Back" +msgstr "Zurück" + +msgctxt "Camera View" msgid "Left" msgstr "links" -msgctxt "Camera" +msgctxt "Camera View" msgid "Right" msgstr "rechts" @@ -5528,6 +5542,10 @@ msgstr "Aktuelle Platte drucken" msgid "Export G-code file" msgstr "G-Code als Datei exportieren" +msgctxt "Verb" +msgid "Print" +msgstr "aktuelle Platte drucken" + msgid "Export plate sliced file" msgstr "Exportiere aktuelle Platte als STL Datei" @@ -5701,15 +5719,6 @@ msgstr "Aktuelle Konfiguration in Dateien exportieren" msgid "Export" msgstr "Exportieren" -msgid "Sync Presets" -msgstr "Presets synchronisieren" - -msgid "Pull and apply the latest presets from OrcaCloud" -msgstr "Die neuesten Presets von OrcaCloud abrufen und anwenden" - -msgid "You must be logged in to sync presets from cloud." -msgstr "Sie müssen angemeldet sein, um Presets aus der Cloud zu synchronisieren." - msgid "Quit" msgstr "Beenden" @@ -5826,6 +5835,15 @@ msgstr "Ansicht" msgid "Preset Bundle" msgstr "Vorlagen-Bundle" +msgid "Sync Presets" +msgstr "Presets synchronisieren" + +msgid "Pull and apply the latest presets from OrcaCloud" +msgstr "Die neuesten Presets von OrcaCloud abrufen und anwenden" + +msgid "You must be logged in to sync presets from cloud." +msgstr "Sie müssen angemeldet sein, um Presets aus der Cloud zu synchronisieren." + msgid "Syncing presets from cloud…" msgstr "Synchronisiere Presets aus der Cloud…" @@ -10362,12 +10380,8 @@ msgstr "Düseninformationen erfolgreich synchronisiert." msgid "Successfully synchronized nozzle and AMS number information." msgstr "Düsen und AMS Nummer erfolgreich synchronisiert." -msgid "Continue to sync filaments" -msgstr "Weiter mit dem Synchronisieren der Filamente" - -msgctxt "Sync_Nozzle_AMS" -msgid "Cancel" -msgstr "Abbrechen" +msgid "Do you want to continue to sync filaments?" +msgstr "" msgid "Successfully synchronized filament color from printer." msgstr "Farbe des Filaments erfolgreich vom Drucker synchronisiert." @@ -11697,19 +11711,11 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." msgstr "" -"Externe Brückenwinkelüberschreibung.\n" -"Wenn auf Null gelassen, wird der Brückenwinkel automatisch für jede spezifische Brücke berechnet.\n" -"Ansonsten wird der angegebene Winkel wie folgt verwendet:\n" -" - Die absoluten Koordinaten\n" -" - Die absoluten Koordinaten + Modellrotation: Wenn 'Füllrichtung an Modell ausrichten' aktiviert ist\n" -" - Der optimale automatische Winkel + dieser Wert: Wenn 'Relativer Brückenwinkel' aktiviert ist\n" -"\n" -"Verwenden Sie 180° für einen absoluten Winkel von Null." msgid "Internal bridge infill direction" msgstr "Interne Brücken Füllrichtung" @@ -11719,19 +11725,11 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." msgstr "" -"Interne Brückenwinkelüberschreibung.\n" -"Wenn auf Null gelassen, wird der Brückenwinkel automatisch für jede spezifische Brücke berechnet.\n" -"Ansonsten wird der angegebene Winkel wie folgt verwendet:\n" -" - Die absoluten Koordinaten\n" -" - Die absoluten Koordinaten + Modellrotation: Wenn 'Füllrichtung an Modell ausrichten' aktiviert ist\n" -" - Der optimale automatische Winkel + dieser Wert: Wenn 'Relativer Brückenwinkel' aktiviert ist\n" -"\n" -"Verwenden Sie 180° für einen absoluten Winkel von Null." msgid "Relative bridge angle" msgstr "Relativer Brückenwinkel" @@ -12514,6 +12512,42 @@ msgstr "Dichte der oberen Oberfläche" msgid "Density of top surface layer. A value of 100% creates a fully solid, smooth top layer. Reducing this value results in a textured top surface, according to the chosen top surface pattern. A value of 0% will result in only the walls on the top layer being created. Intended for aesthetic or functional purposes, not to fix issues such as over-extrusion." msgstr "Dichte der oberen Oberflächenschicht. Ein Wert von 100 % erzeugt eine vollständig massive, glatte obere Schicht. Eine Reduzierung dieses Wertes führt zu einer strukturierten oberen Oberfläche, abhängig vom gewählten Oberflächenmuster. Ein Wert von 0 % führt dazu, dass nur die Wände der oberen Schicht erstellt werden. Diese Einstellung dient ästhetischen oder funktionalen Zwecken und nicht zur Behebung von Problemen wie Überextrusion." +msgid "Top surface expansion" +msgstr "" + +msgid "" +"Expands the top surfaces by this distance to connect distinct top surfaces and fill gaps.\n" +"Useful for cases where the top surface is interrupted by a raised feature, such as text on a plane.Expanding it removes the holes beneath these features and creates a continuous path with a better finish for printing on top.The expansion is applied to the original top surface, before any other processing such as bridging or overhang detection." +msgstr "" + +msgid "Top expansion wall margin" +msgstr "" + +msgid "" +"Using “Top surface expansion” may cause a surface that did not previously touch the model's outer walls to now do so.\n" +"This can cause contraction marks (such as the hull line) on the outer walls.\n" +"By adding a small margin, this contraction will not occur directly on the walls, thereby preventing a visible mark." +msgstr "" + +msgid "Top expansion direction" +msgstr "" + +msgid "" +"Direction in which the top surface expansion grows.\n" +" - Inward grows into the holes and gaps left by features rising from the middle of a top surface.\n" +" - Outward grows the outer edge of the surface, connecting surfaces separated by features that can divide a surface, such as a lattice pattern.\n" +" - Inward and Outward does both." +msgstr "" + +msgid "Inward and Outward" +msgstr "" + +msgid "Inward" +msgstr "" + +msgid "Outward" +msgstr "" + msgid "Bottom surface pattern" msgstr "Muster der unteren Fläche" @@ -13179,15 +13213,13 @@ msgstr "Fülldichte" msgid "Density of internal sparse infill, 100% turns all sparse infill into solid infill and internal solid infill pattern will be used." msgstr "Dichte der internen Füllung, 100% verwandelt alle interne Füllung in massive Füllung und das interne massive Füllmuster wird verwendet." -msgid "Align infill direction to model" -msgstr "Füllrichtung am Modell ausrichten" +msgid "Align directions to model" +msgstr "" msgid "" -"Aligns infill, bridge, ironing and surface fill directions to follow the model's orientation on the build plate.\n" -"When enabled, directions rotate with the model to maintain optimal strength characteristics." +"Aligns infill, bridge, ironing, and top/bottom surface directions to follow the model's orientation on the build plate.\n" +"When enabled, these directions rotate together with the model so the printed features keep their intended orientation relative to the part, preserving optimal strength and surface characteristics regardless of how the model is placed." msgstr "" -"Richtet die Richtungen von Füllung, Brücke, Glättung und Oberflächenfüllung so aus, dass sie der Orientierung des Modells auf der Bauplatte folgen.\n" -"Wenn aktiviert, drehen sich die Richtungen mit dem Modell, um optimale Festigkeitseigenschaften zu erhalten." msgid "Insert solid layers" msgstr "Massive Schichten einfügen" @@ -14961,6 +14993,10 @@ msgstr "Ausgerichtet" msgid "Aligned back" msgstr "Ausgerichtet hinten" +# TODO: Review, changed by lang refactor. PR 14254 +msgid "Back" +msgstr "Zurück" + msgid "Random" msgstr "Zufall" @@ -15333,6 +15369,18 @@ msgstr "Reinige alle Druckextruder" msgid "If enabled, all printing extruders will be primed at the front edge of the print bed at the start of the print." msgstr "Wenn aktiviert, werden alle Druckextruder am vorderen Rand des Druckbetts am Anfang des Drucks gereinigt." +msgid "Toolchange ordering" +msgstr "" + +msgid "" +"Determines the order of tool changes on each layer.\n" +"- Default: Starts with the last used extruder to minimize tool changes.\n" +"- Cyclic: Uses a fixed tool sequence each layer. This sacrifices speed for better surface quality, as the extra toolchanges allow layers more time to cool." +msgstr "" + +msgid "Cyclic" +msgstr "" + msgid "Slice gap closing radius" msgstr "Slice-Lückenschlussradius" @@ -15780,6 +15828,45 @@ msgstr "Dicke der oberen Schale" msgid "The number of top solid layers is increased when slicing if the thickness calculated by top shell layers is thinner than this value. This can avoid having too thin a shell when layer height is small. 0 means that this setting is disabled and thickness of top shell is determined simply by the number of top shell layers." msgstr "Die Anzahl der oberen festen Schichten wird beim Slicen erhöht, wenn die obere Schalenstärke dünner als dieser Wert ist. Dies kann verhindern, dass die Schale zu dünn wird, wenn eine geringe Schichthöhe verwendet wird. 0 bedeutet, dass diese Einstellung deaktiviert ist und die Dicke der oberen Schale absolut durch die oberen Schalenschichten bestimmt wird." +msgid "Anisotropic surfaces" +msgstr "" + +msgid "" +"Anisotropic patterns on the top and bottom surfaces.\n" +"Co-directional printing mode will be applied. For certain patterns, omni-directional filling provides color dispersion when using multi-colored or silk plastics.\n" +"This option disable the gap fill.\n" +"This option can increase a printing time." +msgstr "" + +msgid "Separated infills" +msgstr "" + +msgid "" +"Centers the internal infill of each part on itself, as if it were sliced on its own, instead of on the whole assembly. Parts that touch or overlap are treated as one body and share a center; separate parts (or distinct 3D objects) each get their own.\n" +"Useful when an assembly groups several objects that should each keep a consistent, self-centered infill.\n" +"Affects line and grid patterns and rotation-template infills.\n" +"Patterns locked to global coordinates (Gyroid, Honeycomb, TPMS, ...) are unaffected." +msgstr "" + +msgid "Center surface pattern on" +msgstr "" + +msgid "" +"Chooses where the centering point of centered top/bottom surface patterns (Archimedean Chords, Octagram Spiral) is placed.\n" +" - Each Surface: centers the pattern on every individual surface region, so each island is symmetric on its own.\n" +" - Each Model: centers the pattern on each connected body. Parts that touch or overlap share one center; parts detached from the rest each get their own.\n" +" - Each Assembly: uses a single shared center for the whole object or assembly." +msgstr "" + +msgid "Each Surface" +msgstr "" + +msgid "Each Model" +msgstr "" + +msgid "Each Assembly" +msgstr "" + # TODO: Review, changed by lang refactor. PR 14254 msgid "This is the speed at which traveling is done." msgstr "Eilgeschwindigkeit, wenn nicht extrudiert wird." @@ -19821,6 +19908,68 @@ msgstr "" "Verwerfungen vermeiden\n" "Wussten Sie, dass beim Drucken von Materialien, die zu Verwerfungen neigen, wie z.B. ABS, durch eine entsprechende Erhöhung der Heizbetttemperatur die Wahrscheinlichkeit von Verwerfungen verringert werden kann?" +#~ msgid "Continue to sync filaments" +#~ msgstr "Weiter mit dem Synchronisieren der Filamente" + +#~ msgctxt "Sync_Nozzle_AMS" +#~ msgid "Cancel" +#~ msgstr "Abbrechen" + +#, no-c-format, no-boost-format +#~ msgid "" +#~ "External Bridging angle override.\n" +#~ "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" +#~ "Otherwise the provided angle will be used according to:\n" +#~ " - The absolute coordinates\n" +#~ " - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +#~ " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" +#~ "\n" +#~ "Use 180° for zero absolute angle." +#~ msgstr "" +#~ "Externe Brückenwinkelüberschreibung.\n" +#~ "Wenn auf Null gelassen, wird der Brückenwinkel automatisch für jede spezifische Brücke berechnet.\n" +#~ "Ansonsten wird der angegebene Winkel wie folgt verwendet:\n" +#~ " - Die absoluten Koordinaten\n" +#~ " - Die absoluten Koordinaten + Modellrotation: Wenn 'Füllrichtung an Modell ausrichten' aktiviert ist\n" +#~ " - Der optimale automatische Winkel + dieser Wert: Wenn 'Relativer Brückenwinkel' aktiviert ist\n" +#~ "\n" +#~ "Verwenden Sie 180° für einen absoluten Winkel von Null." + +#~ msgid "" +#~ "Internal Bridging angle override.\n" +#~ "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" +#~ "Otherwise the provided angle will be used according to:\n" +#~ " - The absolute coordinates\n" +#~ " - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +#~ " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" +#~ "\n" +#~ "Use 180° for zero absolute angle." +#~ msgstr "" +#~ "Interne Brückenwinkelüberschreibung.\n" +#~ "Wenn auf Null gelassen, wird der Brückenwinkel automatisch für jede spezifische Brücke berechnet.\n" +#~ "Ansonsten wird der angegebene Winkel wie folgt verwendet:\n" +#~ " - Die absoluten Koordinaten\n" +#~ " - Die absoluten Koordinaten + Modellrotation: Wenn 'Füllrichtung an Modell ausrichten' aktiviert ist\n" +#~ " - Der optimale automatische Winkel + dieser Wert: Wenn 'Relativer Brückenwinkel' aktiviert ist\n" +#~ "\n" +#~ "Verwenden Sie 180° für einen absoluten Winkel von Null." + +#~ msgid "Align infill direction to model" +#~ msgstr "Füllrichtung am Modell ausrichten" + +#~ msgid "" +#~ "Aligns infill, bridge, ironing and surface fill directions to follow the model's orientation on the build plate.\n" +#~ "When enabled, directions rotate with the model to maintain optimal strength characteristics." +#~ msgstr "" +#~ "Richtet die Richtungen von Füllung, Brücke, Glättung und Oberflächenfüllung so aus, dass sie der Orientierung des Modells auf der Bauplatte folgen.\n" +#~ "Wenn aktiviert, drehen sich die Richtungen mit dem Modell, um optimale Festigkeitseigenschaften zu erhalten." + +#~ msgid "Print" +#~ msgstr "aktuelle Platte drucken" + +#~ msgid "in" +#~ msgstr "in" + #~ msgid "Object coordinates" #~ msgstr "Objektkoordinaten" @@ -21726,10 +21875,6 @@ msgstr "" #~ msgid "Unselect" #~ msgstr "Abwählen" -#~ msgctxt "Verb" -#~ msgid "Scale" -#~ msgstr "Skalieren" - #~ msgid "Lift Z Enforcement" #~ msgstr "Z-Höhe einhalten" diff --git a/localization/i18n/en/OrcaSlicer_en.po b/localization/i18n/en/OrcaSlicer_en.po index aad88dc670..53412a51fe 100644 --- a/localization/i18n/en/OrcaSlicer_en.po +++ b/localization/i18n/en/OrcaSlicer_en.po @@ -3,7 +3,7 @@ msgid "" msgstr "" "Project-Id-Version: Orca Slicer\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-07-06 12:57-0300\n" +"POT-Creation-Date: 2026-07-12 12:27-0300\n" "PO-Revision-Date: 2026-06-17 15:44-0300\n" "Last-Translator: Alexandre Folle de Menezes\n" "Language-Team: \n" @@ -159,6 +159,12 @@ msgstr "" msgid "Gap Fill" msgstr "" +msgid "Vertical" +msgstr "" + +msgid "Horizontal" +msgstr "" + #, boost-format msgid "Allows painting only on facets selected by: \"%1%\"" msgstr "" @@ -251,12 +257,6 @@ msgstr "" msgid "Height Range" msgstr "" -msgid "Vertical" -msgstr "" - -msgid "Horizontal" -msgstr "" - msgid "Remove painted color" msgstr "" @@ -321,6 +321,7 @@ msgstr "" msgid "Optimize orientation" msgstr "" +msgctxt "Verb" msgid "Scale" msgstr "" @@ -330,6 +331,7 @@ msgstr "" msgid "Error: Please close all toolbar menus first" msgstr "" +msgctxt "inches" msgid "in" msgstr "" @@ -363,6 +365,9 @@ msgstr "" msgid "Object operations" msgstr "" +msgid "Scale" +msgstr "" + msgid "Volume operations" msgstr "" @@ -408,6 +413,10 @@ msgstr "" msgid "Reset current rotation to real zeros." msgstr "" +msgctxt "Noun" +msgid "Scale" +msgstr "" + #. TRN - Input label. Be short as possible msgid "Size" msgstr "" @@ -3494,6 +3503,7 @@ msgstr "" msgid "Save" msgstr "" +msgctxt "Navigation" msgid "Back" msgstr "" @@ -4776,6 +4786,7 @@ msgstr "" msgid "Color change" msgstr "" +msgctxt "Noun" msgid "Print" msgstr "" @@ -4931,11 +4942,15 @@ msgstr "" msgid "Align to Y axis" msgstr "" -msgctxt "Camera" +msgctxt "Camera View" +msgid "Back" +msgstr "" + +msgctxt "Camera View" msgid "Left" msgstr "" -msgctxt "Camera" +msgctxt "Camera View" msgid "Right" msgstr "" @@ -5252,6 +5267,10 @@ msgstr "" msgid "Export G-code file" msgstr "" +msgctxt "Verb" +msgid "Print" +msgstr "" + msgid "Export plate sliced file" msgstr "" @@ -5425,15 +5444,6 @@ msgstr "" msgid "Export" msgstr "" -msgid "Sync Presets" -msgstr "" - -msgid "Pull and apply the latest presets from OrcaCloud" -msgstr "" - -msgid "You must be logged in to sync presets from cloud." -msgstr "" - msgid "Quit" msgstr "" @@ -5548,6 +5558,15 @@ msgstr "" msgid "Preset Bundle" msgstr "" +msgid "Sync Presets" +msgstr "" + +msgid "Pull and apply the latest presets from OrcaCloud" +msgstr "" + +msgid "You must be logged in to sync presets from cloud." +msgstr "" + msgid "Syncing presets from cloud…" msgstr "" @@ -9828,11 +9847,7 @@ msgstr "" msgid "Successfully synchronized nozzle and AMS number information." msgstr "" -msgid "Continue to sync filaments" -msgstr "" - -msgctxt "Sync_Nozzle_AMS" -msgid "Cancel" +msgid "Do you want to continue to sync filaments?" msgstr "" msgid "Successfully synchronized filament color from printer." @@ -11068,7 +11083,7 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." @@ -11082,7 +11097,7 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." @@ -11706,6 +11721,42 @@ msgstr "" msgid "Density of top surface layer. A value of 100% creates a fully solid, smooth top layer. Reducing this value results in a textured top surface, according to the chosen top surface pattern. A value of 0% will result in only the walls on the top layer being created. Intended for aesthetic or functional purposes, not to fix issues such as over-extrusion." msgstr "" +msgid "Top surface expansion" +msgstr "" + +msgid "" +"Expands the top surfaces by this distance to connect distinct top surfaces and fill gaps.\n" +"Useful for cases where the top surface is interrupted by a raised feature, such as text on a plane.Expanding it removes the holes beneath these features and creates a continuous path with a better finish for printing on top.The expansion is applied to the original top surface, before any other processing such as bridging or overhang detection." +msgstr "" + +msgid "Top expansion wall margin" +msgstr "" + +msgid "" +"Using “Top surface expansion” may cause a surface that did not previously touch the model's outer walls to now do so.\n" +"This can cause contraction marks (such as the hull line) on the outer walls.\n" +"By adding a small margin, this contraction will not occur directly on the walls, thereby preventing a visible mark." +msgstr "" + +msgid "Top expansion direction" +msgstr "" + +msgid "" +"Direction in which the top surface expansion grows.\n" +" - Inward grows into the holes and gaps left by features rising from the middle of a top surface.\n" +" - Outward grows the outer edge of the surface, connecting surfaces separated by features that can divide a surface, such as a lattice pattern.\n" +" - Inward and Outward does both." +msgstr "" + +msgid "Inward and Outward" +msgstr "" + +msgid "Inward" +msgstr "" + +msgid "Outward" +msgstr "" + msgid "Bottom surface pattern" msgstr "" @@ -12306,12 +12357,12 @@ msgstr "" msgid "Density of internal sparse infill, 100% turns all sparse infill into solid infill and internal solid infill pattern will be used." msgstr "" -msgid "Align infill direction to model" +msgid "Align directions to model" msgstr "" msgid "" -"Aligns infill, bridge, ironing and surface fill directions to follow the model's orientation on the build plate.\n" -"When enabled, directions rotate with the model to maintain optimal strength characteristics." +"Aligns infill, bridge, ironing, and top/bottom surface directions to follow the model's orientation on the build plate.\n" +"When enabled, these directions rotate together with the model so the printed features keep their intended orientation relative to the part, preserving optimal strength and surface characteristics regardless of how the model is placed." msgstr "" msgid "Insert solid layers" @@ -13915,6 +13966,9 @@ msgstr "" msgid "Aligned back" msgstr "" +msgid "Back" +msgstr "" + msgid "Random" msgstr "" @@ -14249,6 +14303,18 @@ msgstr "" msgid "If enabled, all printing extruders will be primed at the front edge of the print bed at the start of the print." msgstr "" +msgid "Toolchange ordering" +msgstr "" + +msgid "" +"Determines the order of tool changes on each layer.\n" +"- Default: Starts with the last used extruder to minimize tool changes.\n" +"- Cyclic: Uses a fixed tool sequence each layer. This sacrifices speed for better surface quality, as the extra toolchanges allow layers more time to cool." +msgstr "" + +msgid "Cyclic" +msgstr "" + msgid "Slice gap closing radius" msgstr "" @@ -14652,6 +14718,45 @@ msgstr "" msgid "The number of top solid layers is increased when slicing if the thickness calculated by top shell layers is thinner than this value. This can avoid having too thin a shell when layer height is small. 0 means that this setting is disabled and thickness of top shell is determined simply by the number of top shell layers." msgstr "" +msgid "Anisotropic surfaces" +msgstr "" + +msgid "" +"Anisotropic patterns on the top and bottom surfaces.\n" +"Co-directional printing mode will be applied. For certain patterns, omni-directional filling provides color dispersion when using multi-colored or silk plastics.\n" +"This option disable the gap fill.\n" +"This option can increase a printing time." +msgstr "" + +msgid "Separated infills" +msgstr "" + +msgid "" +"Centers the internal infill of each part on itself, as if it were sliced on its own, instead of on the whole assembly. Parts that touch or overlap are treated as one body and share a center; separate parts (or distinct 3D objects) each get their own.\n" +"Useful when an assembly groups several objects that should each keep a consistent, self-centered infill.\n" +"Affects line and grid patterns and rotation-template infills.\n" +"Patterns locked to global coordinates (Gyroid, Honeycomb, TPMS, ...) are unaffected." +msgstr "" + +msgid "Center surface pattern on" +msgstr "" + +msgid "" +"Chooses where the centering point of centered top/bottom surface patterns (Archimedean Chords, Octagram Spiral) is placed.\n" +" - Each Surface: centers the pattern on every individual surface region, so each island is symmetric on its own.\n" +" - Each Model: centers the pattern on each connected body. Parts that touch or overlap share one center; parts detached from the rest each get their own.\n" +" - Each Assembly: uses a single shared center for the whole object or assembly." +msgstr "" + +msgid "Each Surface" +msgstr "" + +msgid "Each Model" +msgstr "" + +msgid "Each Assembly" +msgstr "" + msgid "This is the speed at which traveling is done." msgstr "" diff --git a/localization/i18n/es/OrcaSlicer_es.po b/localization/i18n/es/OrcaSlicer_es.po index 23e1d1a874..64b5290e75 100644 --- a/localization/i18n/es/OrcaSlicer_es.po +++ b/localization/i18n/es/OrcaSlicer_es.po @@ -3,7 +3,7 @@ msgid "" msgstr "" "Project-Id-Version: Orca Slicer\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-07-06 12:57-0300\n" +"POT-Creation-Date: 2026-07-12 12:27-0300\n" "PO-Revision-Date: \n" "Last-Translator: Ian A. Bassi <>\n" "Language-Team: \n" @@ -159,6 +159,12 @@ msgstr "Llenar" msgid "Gap Fill" msgstr "Rellenar huecos" +msgid "Vertical" +msgstr "Vertical" + +msgid "Horizontal" +msgstr "Horizontal" + #, boost-format msgid "Allows painting only on facets selected by: \"%1%\"" msgstr "Permite pintar solo las facetas seleccionadas por: \"%1%\"" @@ -251,12 +257,6 @@ msgstr "Triángulo" msgid "Height Range" msgstr "Rango de altura" -msgid "Vertical" -msgstr "Vertical" - -msgid "Horizontal" -msgstr "Horizontal" - msgid "Remove painted color" msgstr "Eliminar color pintado" @@ -321,6 +321,7 @@ msgstr "Herramienta de rotación" msgid "Optimize orientation" msgstr "Optimizar orientación" +msgctxt "Verb" msgid "Scale" msgstr "Escalar" @@ -330,8 +331,9 @@ msgstr "Ejes de escalado" msgid "Error: Please close all toolbar menus first" msgstr "Error: Por favor, cierre primero todos los menús de la barra de herramientas" +msgctxt "inches" msgid "in" -msgstr "pulg" +msgstr "\"" msgid "mm" msgstr "mm" @@ -363,6 +365,9 @@ msgstr "Factor de escalado" msgid "Object operations" msgstr "Operaciones con objetos" +msgid "Scale" +msgstr "Escalar" + msgid "Volume operations" msgstr "Operaciones de volumen" @@ -408,6 +413,10 @@ msgstr "Restablecer la rotación actual al valor que tenía al abrir la herramie msgid "Reset current rotation to real zeros." msgstr "Restablecer la rotación actual a ceros reales." +msgctxt "Noun" +msgid "Scale" +msgstr "Escala" + #. TRN - Input label. Be short as possible msgid "Size" msgstr "Tamaño" @@ -1863,22 +1872,30 @@ msgstr "Conflicto de sincronización con la nube para el perfil \"%s\":" msgid "" "This preset has a newer version in OrcaCloud.\n" "Pull downloads the cloud copy. Force push overwrites it with your local preset." -msgstr "Este perfil tiene una versión más reciente en OrcaCloud.\nDescargar obtiene la copia de la nube. Forzar envío la sobrescribe con tu perfil local." +msgstr "" +"Este perfil tiene una versión más reciente en OrcaCloud.\n" +"Descargar obtiene la copia de la nube. Forzar envío la sobrescribe con tu perfil local." msgid "" "A preset with this name already exists in OrcaCloud.\n" "Pull downloads the cloud copy. Force push overwrites it with your local preset." -msgstr "Ya existe un perfil con este nombre en OrcaCloud.\nDescargar obtiene la copia de la nube. Forzar envío la sobrescribe con tu perfil local." +msgstr "" +"Ya existe un perfil con este nombre en OrcaCloud.\n" +"Descargar obtiene la copia de la nube. Forzar envío la sobrescribe con tu perfil local." msgid "" "A preset with the same name was previously deleted from the cloud.\n" "Delete will delete your local preset. Force push overwrites it with your local preset." -msgstr "Un perfil con el mismo nombre se eliminó anteriormente de la nube.\nEliminar borrará tu perfil local. Forzar envío la sobrescribe con tu perfil local." +msgstr "" +"Un perfil con el mismo nombre se eliminó anteriormente de la nube.\n" +"Eliminar borrará tu perfil local. Forzar envío la sobrescribe con tu perfil local." msgid "" "There was an unexpected or unidentified preset conflict.\n" "Pull downloads the cloud copy. Force push overwrites it with your local preset." -msgstr "Se produjo un conflicto de perfil inesperado o no identificado.\nDescargar obtiene la copia de la nube. Forzar envío la sobrescribe con tu perfil local." +msgstr "" +"Se produjo un conflicto de perfil inesperado o no identificado.\n" +"Descargar obtiene la copia de la nube. Forzar envío la sobrescribe con tu perfil local." msgid "" "Force push will overwrite the cloud copy with your local preset changes.\n" @@ -1891,7 +1908,9 @@ msgstr "" msgid "" "Force push will overwrite the cloud copy of preset \"%s\" with your local changes.\n" "Do you want to continue?" -msgstr "Forzar envío sobrescribirá la copia en la nube del perfil \"%s\" con tus cambios locales.\n¿Quieres continuar?" +msgstr "" +"Forzar envío sobrescribirá la copia en la nube del perfil \"%s\" con tus cambios locales.\n" +"¿Quieres continuar?" msgid "Resolve cloud sync conflict" msgstr "Resolver conflictos de sincronización con la nube" @@ -3569,6 +3588,7 @@ msgstr "Calibración completada. Por favor, observe cual es línea de extrusión msgid "Save" msgstr "Guardar" +msgctxt "Navigation" msgid "Back" msgstr "Atrás" @@ -4698,7 +4718,7 @@ msgid "Support interface" msgstr "Interfaz de soporte" msgid "Prime tower" -msgstr "Torre de Purga" +msgstr "Torre de purga" msgid "Bottom surface" msgstr "Relleno sólido inferior" @@ -4919,8 +4939,9 @@ msgstr "Cambios de herramienta" msgid "Color change" msgstr "Cambio de color" +msgctxt "Noun" msgid "Print" -msgstr "Imprimir" +msgstr "Impresión" msgid "Printer" msgstr "Impresora" @@ -5078,11 +5099,15 @@ msgstr "Evitar la zona de calibración del extrusor" msgid "Align to Y axis" msgstr "Alinear con el eje Y" -msgctxt "Camera" +msgctxt "Camera View" +msgid "Back" +msgstr "Posterior" + +msgctxt "Camera View" msgid "Left" msgstr "Izquierda" -msgctxt "Camera" +msgctxt "Camera View" msgid "Right" msgstr "Derecha" @@ -5405,6 +5430,10 @@ msgstr "Imprimir cama" msgid "Export G-code file" msgstr "Exportar archivo G-Code" +msgctxt "Verb" +msgid "Print" +msgstr "Imprimir" + msgid "Export plate sliced file" msgstr "Exportar los objetos laminados de la cama a un archivo" @@ -5477,10 +5506,10 @@ msgid "Front View" msgstr "Vista frontal" msgid "Rear" -msgstr "Trasera" +msgstr "Posterior" msgid "Rear View" -msgstr "Vista trasera" +msgstr "Vista posterior" msgid "Left View" msgstr "Vista izquierda" @@ -5578,15 +5607,6 @@ msgstr "Exportar configuración actual a archivos" msgid "Export" msgstr "Exportar" -msgid "Sync Presets" -msgstr "Sincronizar perfiles" - -msgid "Pull and apply the latest presets from OrcaCloud" -msgstr "Descarga y aplica los últimos ajustes preestablecidos de OrcaCloud" - -msgid "You must be logged in to sync presets from cloud." -msgstr "Debes haber iniciado sesión para sincronizar los ajustes preestablecidos desde la nube." - msgid "Quit" msgstr "Salir del programa" @@ -5701,6 +5721,15 @@ msgstr "Vista" msgid "Preset Bundle" msgstr "Paquete de perfiles" +msgid "Sync Presets" +msgstr "Sincronizar perfiles" + +msgid "Pull and apply the latest presets from OrcaCloud" +msgstr "Descarga y aplica los últimos ajustes preestablecidos de OrcaCloud" + +msgid "You must be logged in to sync presets from cloud." +msgstr "Debes haber iniciado sesión para sincronizar los ajustes preestablecidos desde la nube." + msgid "Syncing presets from cloud…" msgstr "Sincronizando perfiles desde la nube…" @@ -7905,7 +7934,11 @@ msgid "" "Smaller values produce higher-quality meshes but increase processing time.\n" "Used as the default in the import dialog, or directly when the import dialog is disabled.\n" "Default: 0.003 mm." -msgstr "Deflexión lineal utilizada al mallar los archivos STEP importados.\nLos valores más pequeños producen mallas de mayor calidad pero aumentan el tiempo de procesamiento.\nSe usa como valor predeterminado en el diálogo de importación, o directamente cuando el diálogo de importación está desactivado.\nPredeterminado: 0.003 mm." +msgstr "" +"Deflexión lineal utilizada al mallar los archivos STEP importados.\n" +"Los valores más pequeños producen mallas de mayor calidad pero aumentan el tiempo de procesamiento.\n" +"Se usa como valor predeterminado en el diálogo de importación, o directamente cuando el diálogo de importación está desactivado.\n" +"Predeterminado: 0.003 mm." msgid "STEP importing: angle deflection" msgstr "Importación STEP: deflexión angular" @@ -7915,7 +7948,11 @@ msgid "" "Smaller values produce higher-quality meshes but increase processing time.\n" "Used as the default in the import dialog, or directly when the import dialog is disabled.\n" "Default: 0.5." -msgstr "Deflexión angular utilizada al mallar los archivos STEP importados.\nLos valores más pequeños producen mallas de mayor calidad pero aumentan el tiempo de procesamiento.\nSe usa como valor predeterminado en el diálogo de importación, o directamente cuando el diálogo de importación está desactivado.\nPredeterminado: 0.5." +msgstr "" +"Deflexión angular utilizada al mallar los archivos STEP importados.\n" +"Los valores más pequeños producen mallas de mayor calidad pero aumentan el tiempo de procesamiento.\n" +"Se usa como valor predeterminado en el diálogo de importación, o directamente cuando el diálogo de importación está desactivado.\n" +"Predeterminado: 0.5." msgid "STEP importing: Split into multiple objects" msgstr "Importación STEP: Separar en múltiples objetos" @@ -7924,7 +7961,10 @@ msgid "" "If enabled, compound and compsolid shapes in imported STEP files are split into multiple objects.\n" "Used as the default in the import dialog, or directly when the import dialog is disabled.\n" "Default: disabled." -msgstr "Si está activado, las formas compound y compsolid de los archivos STEP importados se separan en múltiples objetos.\nSe usa como valor predeterminado en el diálogo de importación, o directamente cuando el diálogo de importación está desactivado.\nPredeterminado: desactivado." +msgstr "" +"Si está activado, las formas compound y compsolid de los archivos STEP importados se separan en múltiples objetos.\n" +"Se usa como valor predeterminado en el diálogo de importación, o directamente cuando el diálogo de importación está desactivado.\n" +"Predeterminado: desactivado." msgid "Quality level for Draco export" msgstr "Nivel de calidad para exportación Draco" @@ -9168,7 +9208,7 @@ msgstr "Característica experimental: Retraer y cortar el filamento a mayor dist msgid "" "When recording timelapse without toolhead, it is recommended to add a \"Timelapse Wipe Tower\" \n" "by right-click the empty position of build plate and choose \"Add Primitive\"->\"Timelapse Wipe Tower\"." -msgstr "Cuando se graba un timelapse sin cabezal, se recomienda añadir una \"Torre de Purga de Timelapse\" haciendo clic con el botón derecho del ratón en una posición vacía de la cama de impresión y seleccionando \"Añadir Primitivo\"->Torre de Purga de Timelapse\"." +msgstr "Cuando se graba un timelapse sin cabezal, se recomienda añadir una \"Torre de purga de Timelapse\" haciendo clic con el botón derecho del ratón en una posición vacía de la cama de impresión y seleccionando \"Añadir Primitivo\"->\"Torre de purga de Timelapse\"." msgid "A copy of the current system preset will be created, which will be detached from the system preset." msgstr "Se creará una copia de el perfil de sistema actual, que quedará separado del perfil de sistema." @@ -10151,12 +10191,8 @@ msgstr "Información de boquilla sincronizada con éxito." msgid "Successfully synchronized nozzle and AMS number information." msgstr "Información de boquilla y número AMS sincronizada con éxito." -msgid "Continue to sync filaments" -msgstr "Continuar sincronizando filamentos" - -msgctxt "Sync_Nozzle_AMS" -msgid "Cancel" -msgstr "Cancelar" +msgid "Do you want to continue to sync filaments?" +msgstr "" msgid "Successfully synchronized filament color from printer." msgstr "Color de filamento sincronizado desde la impresora con éxito." @@ -10874,7 +10910,7 @@ msgid " is too close to clumping detection area, there may be collisions when pr msgstr " está demasiado cerca del área de detección de aglomeraciones, puede haber colisiones durante la impresión." msgid "Prime Tower" -msgstr "Torre de Purga" +msgstr "Torre de purga" msgid " is too close to others, and collisions may be caused.\n" msgstr " está demasiado cerca de otros, y se pueden producir colisiones.\n" @@ -11424,19 +11460,11 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." msgstr "" -"Anulación del ángulo de puente externo.\n" -"Si se deja en cero, el ángulo de puente se calculará automáticamente para cada puente concreto.\n" -"De lo contrario, se utilizará el ángulo indicado según:\n" -" - Las coordenadas absolutas\n" -" - Las coordenadas absolutas + rotación del modelo: si está activada la opción «Alinear la dirección de relleno al modelo»\n" -" - El ángulo automático óptimo + este valor: si está activada la opción «Ángulo de puente relativo»\n" -"\n" -"Utiliza 180° para un ángulo absoluto de cero." msgid "Internal bridge infill direction" msgstr "Dirección de relleno de puentes internos" @@ -11446,19 +11474,11 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." msgstr "" -"Anulación del ángulo de puente interno.\n" -"Si se deja en cero, el ángulo de puente se calculará automáticamente para cada puente concreto.\n" -"De lo contrario, se utilizará el ángulo indicado según:\n" -" - Las coordenadas absolutas\n" -" - Las coordenadas absolutas + rotación del modelo: si está activada la opción «Alinear la dirección de relleno al modelo»\n" -" - El ángulo automático óptimo + este valor: si está activada la opción «Ángulo de puente relativo»\n" -"\n" -"Utiliza 180° para un ángulo absoluto de cero." msgid "Relative bridge angle" msgstr "Ángulo de puente relativo" @@ -12231,6 +12251,42 @@ msgstr "Densidad de la superficie superior" msgid "Density of top surface layer. A value of 100% creates a fully solid, smooth top layer. Reducing this value results in a textured top surface, according to the chosen top surface pattern. A value of 0% will result in only the walls on the top layer being created. Intended for aesthetic or functional purposes, not to fix issues such as over-extrusion." msgstr "Densidad de la capa superficial superior. Un valor de 100% crea una capa superior totalmente sólida y lisa. Reducir este valor produce una superficie superior texturada, según el patrón elegido. Un valor de 0% provocará que sólo se creen las paredes en la capa superior. Destinado a fines estéticos o funcionales, no para corregir problemas como la sobreextrusión." +msgid "Top surface expansion" +msgstr "" + +msgid "" +"Expands the top surfaces by this distance to connect distinct top surfaces and fill gaps.\n" +"Useful for cases where the top surface is interrupted by a raised feature, such as text on a plane.Expanding it removes the holes beneath these features and creates a continuous path with a better finish for printing on top.The expansion is applied to the original top surface, before any other processing such as bridging or overhang detection." +msgstr "" + +msgid "Top expansion wall margin" +msgstr "" + +msgid "" +"Using “Top surface expansion” may cause a surface that did not previously touch the model's outer walls to now do so.\n" +"This can cause contraction marks (such as the hull line) on the outer walls.\n" +"By adding a small margin, this contraction will not occur directly on the walls, thereby preventing a visible mark." +msgstr "" + +msgid "Top expansion direction" +msgstr "" + +msgid "" +"Direction in which the top surface expansion grows.\n" +" - Inward grows into the holes and gaps left by features rising from the middle of a top surface.\n" +" - Outward grows the outer edge of the surface, connecting surfaces separated by features that can divide a surface, such as a lattice pattern.\n" +" - Inward and Outward does both." +msgstr "" + +msgid "Inward and Outward" +msgstr "" + +msgid "Inward" +msgstr "" + +msgid "Outward" +msgstr "" + msgid "Bottom surface pattern" msgstr "Patrón de relleno de cubierta inferior" @@ -12477,7 +12533,12 @@ msgid "" "Not compatible with Prusa printers as they pause to process PA changes, which causes delays and defects.\n" "\n" "This is an experimental option, as if the PA profile is not set accurately, it will cause uniformity issues." -msgstr "Activa el PA adaptativo siempre que haya cambios de flujo en una característica, como cambios de ancho de línea en una esquina o en voladizos.\n\nNo es compatible con las impresoras Prusa, ya que se pausan para procesar los cambios de PA, lo que provoca retrasos y defectos.\n\nEsta es una opción experimental, ya que si el perfil de PA no se configura con precisión, causará problemas de uniformidad." +msgstr "" +"Activa el PA adaptativo siempre que haya cambios de flujo en una característica, como cambios de ancho de línea en una esquina o en voladizos.\n" +"\n" +"No es compatible con las impresoras Prusa, ya que se pausan para procesar los cambios de PA, lo que provoca retrasos y defectos.\n" +"\n" +"Esta es una opción experimental, ya que si el perfil de PA no se configura con precisión, causará problemas de uniformidad." msgid "Static pressure advance for bridges" msgstr "Pressure Advance estático para puentes" @@ -12487,7 +12548,11 @@ msgid "" "equivalent walls (using adaptive settings if enabled).\n" "\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 de Pressure Advance estático para los puentes. Establécelo a 0 para aplicar el mismo Pressure Advance que en los \nperímetros equivalentes (usando los ajustes adaptativos si están activados).\n\nUn valor de PA más bajo al imprimir puentes ayuda a reducir la aparición de una ligera subextrusión justo después de los puentes. Esto se debe a la caída de presión en la boquilla al imprimir en el aire, y un PA más bajo ayuda a contrarrestarlo." +msgstr "" +"Valor de Pressure Advance estático para los puentes. Establécelo a 0 para aplicar el mismo Pressure Advance que en los \n" +"perímetros equivalentes (usando los ajustes adaptativos si están activados).\n" +"\n" +"Un valor de PA más bajo al imprimir puentes ayuda a reducir la aparición de una ligera subextrusión justo después de los puentes. Esto se debe a la caída de presión en la boquilla al imprimir en el aire, y un PA más bajo ayuda a contrarrestarlo." msgid "Default line width if other line widths are set to 0. If expressed as a %, it will be computed over the nozzle diameter." msgstr "Ancho de línea por defecto si otros anchos de línea están a 0. Si se expresa cómo %, se calculará en base al diámetro de la boquilla." @@ -12719,7 +12784,7 @@ msgid "After a tool change, the exact position of the newly loaded filament insi msgstr "Tras un cambio de cabezal, es posible que no se conozca la posición exacta del filamento recién cargado dentro de la boquilla y que la presión del filamento aún no sea estable. Antes de purgar el cabezal de impresión en un relleno o en un objeto de sacrificio, OrcaSlicer siempre cebará esta cantidad de material en la torre de purga para producir sucesivas extrusiones de relleno u objetos de sacrificio de forma fiable." msgid "Wipe tower cooling" -msgstr "Refrigeración de Torre de Purga" +msgstr "Refrigeración de torre de purga" msgid "Temperature drop before entering filament tower" msgstr "Descenso de temperatura antes de entrar en la torre de filamentos" @@ -12865,7 +12930,9 @@ msgstr "Dirección de la capa superior" msgid "" "Fixed angle for the top solid infill and ironing lines.\n" "Set to -1 to follow the default solid infill direction." -msgstr "Ángulo fijo para el relleno sólido superior y las líneas de alisado.\nEstablécelo a -1 para seguir la dirección predeterminada del relleno sólido." +msgstr "" +"Ángulo fijo para el relleno sólido superior y las líneas de alisado.\n" +"Establécelo a -1 para seguir la dirección predeterminada del relleno sólido." msgid "Bottom layer direction" msgstr "Dirección de la capa inferior" @@ -12873,7 +12940,9 @@ msgstr "Dirección de la capa inferior" msgid "" "Fixed angle for the bottom solid infill lines.\n" "Set to -1 to follow the default solid infill direction." -msgstr "Ángulo fijo para las líneas del relleno sólido inferior.\nEstablécelo a -1 para seguir la dirección predeterminada del relleno sólido." +msgstr "" +"Ángulo fijo para las líneas del relleno sólido inferior.\n" +"Establécelo a -1 para seguir la dirección predeterminada del relleno sólido." msgid "Sparse infill density" msgstr "Densidad de relleno de baja densidad" @@ -12882,15 +12951,13 @@ msgstr "Densidad de relleno de baja densidad" msgid "Density of internal sparse infill, 100% turns all sparse infill into solid infill and internal solid infill pattern will be used." msgstr "Densidad del relleno de baja densidad interno, el 100% convierte el relleno de baja densidad en relleno sólido y se utilizará el patrón de relleno sólido interno." -msgid "Align infill direction to model" -msgstr "Alinear la dirección de relleno al modelo" +msgid "Align directions to model" +msgstr "" msgid "" -"Aligns infill, bridge, ironing and surface fill directions to follow the model's orientation on the build plate.\n" -"When enabled, directions rotate with the model to maintain optimal strength characteristics." +"Aligns infill, bridge, ironing, and top/bottom surface directions to follow the model's orientation on the build plate.\n" +"When enabled, these directions rotate together with the model so the printed features keep their intended orientation relative to the part, preserving optimal strength and surface characteristics regardless of how the model is placed." msgstr "" -"Alinea las direcciones de relleno, puente, alisado y relleno superficial para que sigan la orientación del modelo sobre la placa de impresión.\n" -"Cuando está activada, las direcciones giran junto con el modelo para mantener sus características de resistencia óptimas." msgid "Insert solid layers" msgstr "Insertar capas sólidas" @@ -13090,7 +13157,12 @@ msgid "" "If \"Full fan speed at layer\" is also set, the fan ramps smoothly from this value on the first layer up to your target by the chosen layer.\n" "Only available when \"No cooling for the first\" is 0.\n" "Set to -1 to disable it." -msgstr "Establece una velocidad exacta del ventilador para la primera capa, anulando el resto de ajustes de refrigeración. Útil para proteger las piezas del cabezal impresas en 3D (por ejemplo, los conductos de ABS/ASA tipo Voron) de una cama caliente. Una pequeña cantidad de flujo de aire enfría los conductos, sin usar la refrigeración completa que en ciertas condiciones puede perjudicar la adhesión de la primera capa.\nA partir de la segunda capa, se reanuda la refrigeración normal.\nSi también se ha establecido \"Velocidad máxima del ventilador en la capa\", el ventilador sube suavemente desde este valor en la primera capa hasta tu objetivo en la capa elegida.\nSolo disponible cuando \"No refrigerar las primeras\" es 0.\nEstablécelo a -1 para desactivarlo." +msgstr "" +"Establece una velocidad exacta del ventilador para la primera capa, anulando el resto de ajustes de refrigeración. Útil para proteger las piezas del cabezal impresas en 3D (por ejemplo, los conductos de ABS/ASA tipo Voron) de una cama caliente. Una pequeña cantidad de flujo de aire enfría los conductos, sin usar la refrigeración completa que en ciertas condiciones puede perjudicar la adhesión de la primera capa.\n" +"A partir de la segunda capa, se reanuda la refrigeración normal.\n" +"Si también se ha establecido \"Velocidad máxima del ventilador en la capa\", el ventilador sube suavemente desde este valor en la primera capa hasta tu objetivo en la capa elegida.\n" +"Solo disponible cuando \"No refrigerar las primeras\" es 0.\n" +"Establécelo a -1 para desactivarlo." msgid "Support interface fan speed" msgstr "Velocidad de ventilador en la interfaz de los soportes" @@ -14617,6 +14689,9 @@ msgstr "Alineado" msgid "Aligned back" msgstr "Alineado atrás" +msgid "Back" +msgstr "Atrás" + msgid "Random" msgstr "Aleatorio" @@ -14972,6 +15047,18 @@ msgstr "Purgar todos los extrusores" msgid "If enabled, all printing extruders will be primed at the front edge of the print bed at the start of the print." msgstr "Sí se activa, todos los extrusores serán purgados en el frontal de la cama de impresión al inicio de la impresión." +msgid "Toolchange ordering" +msgstr "" + +msgid "" +"Determines the order of tool changes on each layer.\n" +"- Default: Starts with the last used extruder to minimize tool changes.\n" +"- Cyclic: Uses a fixed tool sequence each layer. This sacrifices speed for better surface quality, as the extra toolchanges allow layers more time to cool." +msgstr "" + +msgid "Cyclic" +msgstr "" + msgid "Slice gap closing radius" msgstr "Radio de cierre de laminado" @@ -15408,6 +15495,45 @@ msgstr "Espesor mínimo de la cubierta superior" msgid "The number of top solid layers is increased when slicing if the thickness calculated by top shell layers is thinner than this value. This can avoid having too thin a shell when layer height is small. 0 means that this setting is disabled and thickness of top shell is determined simply by the number of top shell layers." msgstr "El número de capas sólidas superiores se incrementa al laminar si el espesor calculado por las capas de la cubierta es más delgado que este valor. Esto puede evitar tener una cubierta demasiado fina cuando la altura de la capa es pequeña. 0 significa que este ajuste está desactivado y el grosor de la capa superior está absolutamente determinado por las capas de la cubierta superior." +msgid "Anisotropic surfaces" +msgstr "" + +msgid "" +"Anisotropic patterns on the top and bottom surfaces.\n" +"Co-directional printing mode will be applied. For certain patterns, omni-directional filling provides color dispersion when using multi-colored or silk plastics.\n" +"This option disable the gap fill.\n" +"This option can increase a printing time." +msgstr "" + +msgid "Separated infills" +msgstr "" + +msgid "" +"Centers the internal infill of each part on itself, as if it were sliced on its own, instead of on the whole assembly. Parts that touch or overlap are treated as one body and share a center; separate parts (or distinct 3D objects) each get their own.\n" +"Useful when an assembly groups several objects that should each keep a consistent, self-centered infill.\n" +"Affects line and grid patterns and rotation-template infills.\n" +"Patterns locked to global coordinates (Gyroid, Honeycomb, TPMS, ...) are unaffected." +msgstr "" + +msgid "Center surface pattern on" +msgstr "" + +msgid "" +"Chooses where the centering point of centered top/bottom surface patterns (Archimedean Chords, Octagram Spiral) is placed.\n" +" - Each Surface: centers the pattern on every individual surface region, so each island is symmetric on its own.\n" +" - Each Model: centers the pattern on each connected body. Parts that touch or overlap share one center; parts detached from the rest each get their own.\n" +" - Each Assembly: uses a single shared center for the whole object or assembly." +msgstr "" + +msgid "Each Surface" +msgstr "" + +msgid "Each Model" +msgstr "" + +msgid "Each Assembly" +msgstr "" + msgid "This is the speed at which traveling is done." msgstr "Velocidad de desplazamiento más rápida y sin extrusión." @@ -15650,7 +15776,9 @@ msgstr "Número máximo de aristas de poliorificio" msgid "" "Maximum number of polyhole edges\n" "This setting limits the amount of edges a polyhole can have" -msgstr "Número máximo de aristas de un poliorificio\nEste ajuste limita la cantidad de aristas que puede tener un poliorificio" +msgstr "" +"Número máximo de aristas de un poliorificio\n" +"Este ajuste limita la cantidad de aristas que puede tener un poliorificio" msgid "G-code thumbnails" msgstr "Miniaturas de G-Code" @@ -18126,7 +18254,9 @@ msgstr "Elige dónde guardar el archivo JSON exportado" msgid "" "Export failed\n" "Please check write permissions or file in use by another application" -msgstr "La exportación ha fallado\nComprueba los permisos de escritura o si el archivo está siendo usado por otra aplicación" +msgstr "" +"La exportación ha fallado\n" +"Comprueba los permisos de escritura o si el archivo está siendo usado por otra aplicación" msgid "Choose where to save the exported ZIP file" msgstr "Elige dónde guardar el archivo ZIP exportado" @@ -19385,6 +19515,68 @@ msgstr "" "Evita la deformación\n" "¿Sabías que al imprimir materiales propensos a la deformación como el ABS, aumentar adecuadamente la temperatura de la cama térmica puede reducir la probabilidad de deformaciones?" +#~ msgid "Continue to sync filaments" +#~ msgstr "Continuar sincronizando filamentos" + +#~ msgctxt "Sync_Nozzle_AMS" +#~ msgid "Cancel" +#~ msgstr "Cancelar" + +#, no-c-format, no-boost-format +#~ msgid "" +#~ "External Bridging angle override.\n" +#~ "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" +#~ "Otherwise the provided angle will be used according to:\n" +#~ " - The absolute coordinates\n" +#~ " - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +#~ " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" +#~ "\n" +#~ "Use 180° for zero absolute angle." +#~ msgstr "" +#~ "Anulación del ángulo de puente externo.\n" +#~ "Si se deja en cero, el ángulo de puente se calculará automáticamente para cada puente concreto.\n" +#~ "De lo contrario, se utilizará el ángulo indicado según:\n" +#~ " - Las coordenadas absolutas\n" +#~ " - Las coordenadas absolutas + rotación del modelo: si está activada la opción «Alinear la dirección de relleno al modelo»\n" +#~ " - El ángulo automático óptimo + este valor: si está activada la opción «Ángulo de puente relativo»\n" +#~ "\n" +#~ "Utiliza 180° para un ángulo absoluto de cero." + +#~ msgid "" +#~ "Internal Bridging angle override.\n" +#~ "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" +#~ "Otherwise the provided angle will be used according to:\n" +#~ " - The absolute coordinates\n" +#~ " - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +#~ " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" +#~ "\n" +#~ "Use 180° for zero absolute angle." +#~ msgstr "" +#~ "Anulación del ángulo de puente interno.\n" +#~ "Si se deja en cero, el ángulo de puente se calculará automáticamente para cada puente concreto.\n" +#~ "De lo contrario, se utilizará el ángulo indicado según:\n" +#~ " - Las coordenadas absolutas\n" +#~ " - Las coordenadas absolutas + rotación del modelo: si está activada la opción «Alinear la dirección de relleno al modelo»\n" +#~ " - El ángulo automático óptimo + este valor: si está activada la opción «Ángulo de puente relativo»\n" +#~ "\n" +#~ "Utiliza 180° para un ángulo absoluto de cero." + +#~ msgid "Align infill direction to model" +#~ msgstr "Alinear la dirección de relleno al modelo" + +#~ msgid "" +#~ "Aligns infill, bridge, ironing and surface fill directions to follow the model's orientation on the build plate.\n" +#~ "When enabled, directions rotate with the model to maintain optimal strength characteristics." +#~ msgstr "" +#~ "Alinea las direcciones de relleno, puente, alisado y relleno superficial para que sigan la orientación del modelo sobre la placa de impresión.\n" +#~ "Cuando está activada, las direcciones giran junto con el modelo para mantener sus características de resistencia óptimas." + +#~ msgid "Print" +#~ msgstr "Imprimir" + +#~ msgid "in" +#~ msgstr "pulg" + #~ msgid "Object coordinates" #~ msgstr "Coordenadas de objeto" @@ -20965,10 +21157,6 @@ msgstr "" #~ msgid "Unselect" #~ msgstr "Deseleccionar" -#~ msgctxt "Verb" -#~ msgid "Scale" -#~ msgstr "Escala" - #~ msgid "Lift Z Enforcement" #~ msgstr "Forzar elevación Z" diff --git a/localization/i18n/fr/OrcaSlicer_fr.po b/localization/i18n/fr/OrcaSlicer_fr.po index 326357d249..8e4c5fabc6 100644 --- a/localization/i18n/fr/OrcaSlicer_fr.po +++ b/localization/i18n/fr/OrcaSlicer_fr.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: Orca Slicer\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-07-06 12:57-0300\n" +"POT-Creation-Date: 2026-07-12 12:27-0300\n" "PO-Revision-Date: \n" "Last-Translator: \n" "Language-Team: Guislain Cyril, Thomas Lété\n" @@ -162,6 +162,12 @@ msgstr "Remplir" msgid "Gap Fill" msgstr "Remplissage des espaces" +msgid "Vertical" +msgstr "Vertical" + +msgid "Horizontal" +msgstr "Horizontal" + #, boost-format msgid "Allows painting only on facets selected by: \"%1%\"" msgstr "Permet de peindre uniquement sur les facettes sélectionnées par : \"%1%\"" @@ -254,12 +260,6 @@ msgstr "Triangle" msgid "Height Range" msgstr "Plage de hauteur" -msgid "Vertical" -msgstr "Vertical" - -msgid "Horizontal" -msgstr "Horizontal" - msgid "Remove painted color" msgstr "Supprimer la couleur peinte" @@ -324,6 +324,7 @@ msgstr "Gizmo-Pivoter" msgid "Optimize orientation" msgstr "Optimiser l'orientation" +msgctxt "Verb" msgid "Scale" msgstr "Redimensionner" @@ -333,8 +334,9 @@ msgstr "Gizmo-Redimensionner" msgid "Error: Please close all toolbar menus first" msgstr "Erreur : Veuillez d'abord fermer tous les menus de la barre d'outils" +msgctxt "inches" msgid "in" -msgstr "dans" +msgstr "" msgid "mm" msgstr "mm" @@ -366,6 +368,9 @@ msgstr "Rapports d'échelle" msgid "Object operations" msgstr "Opérations sur les objets" +msgid "Scale" +msgstr "Redimensionner" + msgid "Volume operations" msgstr "Opérations sur les volumes" @@ -411,6 +416,10 @@ msgstr "Réinitialiser la rotation actuelle à la valeur lors de l'ouverture de msgid "Reset current rotation to real zeros." msgstr "Réinitialiser la rotation actuelle à zéro." +msgctxt "Noun" +msgid "Scale" +msgstr "Redimensionner" + #. TRN - Input label. Be short as possible msgid "Size" msgstr "Taille" @@ -3568,6 +3577,7 @@ msgstr "Calibrage terminé. Veuillez trouver la ligne d'extrusion la plus unifor msgid "Save" msgstr "Enregistrer" +msgctxt "Navigation" msgid "Back" msgstr "Arrière" @@ -4915,6 +4925,7 @@ msgstr "Changements d’outil" msgid "Color change" msgstr "Changement de couleur" +msgctxt "Noun" msgid "Print" msgstr "Imprimer" @@ -5074,11 +5085,15 @@ msgstr "Éviter la région de calibration de l'extrusion" msgid "Align to Y axis" msgstr "Aligner sur l’axe Y" -msgctxt "Camera" +msgctxt "Camera View" +msgid "Back" +msgstr "Arrière" + +msgctxt "Camera View" msgid "Left" msgstr "Gauche" -msgctxt "Camera" +msgctxt "Camera View" msgid "Right" msgstr "Droite" @@ -5401,6 +5416,10 @@ msgstr "Imprimer le plateau" msgid "Export G-code file" msgstr "Exporter le fichier G-code" +msgctxt "Verb" +msgid "Print" +msgstr "Imprimer" + msgid "Export plate sliced file" msgstr "Exporter le fichier découpé du plateau" @@ -5574,15 +5593,6 @@ msgstr "Exporter la configuration actuelle vers des fichiers" msgid "Export" msgstr "Exporter" -msgid "Sync Presets" -msgstr "Synchroniser les préréglages" - -msgid "Pull and apply the latest presets from OrcaCloud" -msgstr "Récupérer et appliquer les derniers préréglages depuis OrcaCloud" - -msgid "You must be logged in to sync presets from cloud." -msgstr "Vous devez être connecté pour synchroniser les préréglages depuis le cloud." - msgid "Quit" msgstr "Quitter" @@ -5697,6 +5707,15 @@ msgstr "Affichage" msgid "Preset Bundle" msgstr "Paquet de préréglages" +msgid "Sync Presets" +msgstr "Synchroniser les préréglages" + +msgid "Pull and apply the latest presets from OrcaCloud" +msgstr "Récupérer et appliquer les derniers préréglages depuis OrcaCloud" + +msgid "You must be logged in to sync presets from cloud." +msgstr "Vous devez être connecté pour synchroniser les préréglages depuis le cloud." + msgid "Syncing presets from cloud…" msgstr "Synchronisation des préréglages depuis le cloud…" @@ -10147,12 +10166,8 @@ msgstr "Informations de buse synchronisées avec succès." msgid "Successfully synchronized nozzle and AMS number information." msgstr "Informations de buse et de nombre d'AMS synchronisées avec succès." -msgid "Continue to sync filaments" -msgstr "Continuer la synchronisation des filaments" - -msgctxt "Sync_Nozzle_AMS" -msgid "Cancel" -msgstr "Annuler" +msgid "Do you want to continue to sync filaments?" +msgstr "" msgid "Successfully synchronized filament color from printer." msgstr "Couleur de filament synchronisée avec succès depuis l'imprimante." @@ -11429,19 +11444,11 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." msgstr "" -"Remplacement de l’angle des ponts externes.\n" -"Si laissé à zéro, l’angle des ponts est calculé automatiquement pour chaque pont.\n" -"Sinon, l’angle fourni est utilisé selon :\n" -" - les coordonnées absolues\n" -" - les coordonnées absolues + la rotation du modèle : si « Aligner la direction du remplissage sur le modèle » est activé\n" -" - l’angle automatique optimal + cette valeur : si « Angle de pont relatif » est activé\n" -"\n" -"Utilisez 180° pour un angle absolu nul." msgid "Internal bridge infill direction" msgstr "Direction du remplissage du pont interne" @@ -11451,19 +11458,11 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." msgstr "" -"Remplacement de l’angle des ponts internes.\n" -"Si laissé à zéro, l’angle des ponts est calculé automatiquement pour chaque pont.\n" -"Sinon, l’angle fourni est utilisé selon :\n" -" - les coordonnées absolues\n" -" - les coordonnées absolues + la rotation du modèle : si « Aligner la direction du remplissage sur le modèle » est activé\n" -" - l’angle automatique optimal + cette valeur : si « Angle de pont relatif » est activé\n" -"\n" -"Utilisez 180° pour un angle absolu nul." msgid "Relative bridge angle" msgstr "Angle de pont relatif" @@ -12233,6 +12232,42 @@ msgstr "Densité de la surface supérieure" msgid "Density of top surface layer. A value of 100% creates a fully solid, smooth top layer. Reducing this value results in a textured top surface, according to the chosen top surface pattern. A value of 0% will result in only the walls on the top layer being created. Intended for aesthetic or functional purposes, not to fix issues such as over-extrusion." msgstr "Densité de la couche de surface supérieure. Une valeur de 100 % crée une couche supérieure entièrement solide et lisse. Réduire cette valeur donne une surface supérieure texturée, selon le motif de surface supérieure choisi. Une valeur de 0 % ne créera que les parois sur la couche supérieure. Destiné à des fins esthétiques ou fonctionnelles, pas pour corriger des problèmes comme la surextrusion." +msgid "Top surface expansion" +msgstr "" + +msgid "" +"Expands the top surfaces by this distance to connect distinct top surfaces and fill gaps.\n" +"Useful for cases where the top surface is interrupted by a raised feature, such as text on a plane.Expanding it removes the holes beneath these features and creates a continuous path with a better finish for printing on top.The expansion is applied to the original top surface, before any other processing such as bridging or overhang detection." +msgstr "" + +msgid "Top expansion wall margin" +msgstr "" + +msgid "" +"Using “Top surface expansion” may cause a surface that did not previously touch the model's outer walls to now do so.\n" +"This can cause contraction marks (such as the hull line) on the outer walls.\n" +"By adding a small margin, this contraction will not occur directly on the walls, thereby preventing a visible mark." +msgstr "" + +msgid "Top expansion direction" +msgstr "" + +msgid "" +"Direction in which the top surface expansion grows.\n" +" - Inward grows into the holes and gaps left by features rising from the middle of a top surface.\n" +" - Outward grows the outer edge of the surface, connecting surfaces separated by features that can divide a surface, such as a lattice pattern.\n" +" - Inward and Outward does both." +msgstr "" + +msgid "Inward and Outward" +msgstr "" + +msgid "Inward" +msgstr "" + +msgid "Outward" +msgstr "" + msgid "Bottom surface pattern" msgstr "Motif de surface inférieure" @@ -12884,15 +12919,13 @@ msgstr "Densité de remplissage" msgid "Density of internal sparse infill, 100% turns all sparse infill into solid infill and internal solid infill pattern will be used." msgstr "Densité du remplissage interne, 100% transforme tous les remplissages en remplissages pleins et le modèle de remplissage interne sera utilisé" -msgid "Align infill direction to model" -msgstr "Aligner la direction du remplissage sur le modèle" +msgid "Align directions to model" +msgstr "" msgid "" -"Aligns infill, bridge, ironing and surface fill directions to follow the model's orientation on the build plate.\n" -"When enabled, directions rotate with the model to maintain optimal strength characteristics." +"Aligns infill, bridge, ironing, and top/bottom surface directions to follow the model's orientation on the build plate.\n" +"When enabled, these directions rotate together with the model so the printed features keep their intended orientation relative to the part, preserving optimal strength and surface characteristics regardless of how the model is placed." msgstr "" -"Aligne les directions du remplissage, des ponts, du lissage et des surfaces sur l’orientation du modèle sur le plateau.\n" -"Lorsque cette option est activée, les directions pivotent avec le modèle afin de conserver des caractéristiques de résistance optimales." msgid "Insert solid layers" msgstr "Insérer des couches solides" @@ -14627,6 +14660,9 @@ msgstr "Alignée" msgid "Aligned back" msgstr "Aligné à l'arrière" +msgid "Back" +msgstr "Arrière" + msgid "Random" msgstr "Aléatoire" @@ -14984,6 +15020,18 @@ msgstr "Amorcer tous les extrudeurs d’impression" msgid "If enabled, all printing extruders will be primed at the front edge of the print bed at the start of the print." msgstr "Si cette option est activée, tous les extrudeurs d’impression seront amorcés sur le bord avant du plateau au début de l’impression." +msgid "Toolchange ordering" +msgstr "" + +msgid "" +"Determines the order of tool changes on each layer.\n" +"- Default: Starts with the last used extruder to minimize tool changes.\n" +"- Cyclic: Uses a fixed tool sequence each layer. This sacrifices speed for better surface quality, as the extra toolchanges allow layers more time to cool." +msgstr "" + +msgid "Cyclic" +msgstr "" + msgid "Slice gap closing radius" msgstr "Rayon de fermeture de l’écart des tranches" @@ -15416,6 +15464,45 @@ msgstr "Épaisseur de la coque supérieure" msgid "The number of top solid layers is increased when slicing if the thickness calculated by top shell layers is thinner than this value. This can avoid having too thin a shell when layer height is small. 0 means that this setting is disabled and thickness of top shell is determined simply by the number of top shell layers." msgstr "Le nombre de couches solides supérieures est augmenté lors du découpage si l'épaisseur calculée par les couches de coque supérieures est inférieure à cette valeur. Cela peut éviter d'avoir une coque trop fine lorsque la hauteur de couche est faible. 0 signifie que ce paramètre est désactivé et que l'épaisseur de la coque supérieure est simplement déterminée par le nombre de couches de coque supérieures." +msgid "Anisotropic surfaces" +msgstr "" + +msgid "" +"Anisotropic patterns on the top and bottom surfaces.\n" +"Co-directional printing mode will be applied. For certain patterns, omni-directional filling provides color dispersion when using multi-colored or silk plastics.\n" +"This option disable the gap fill.\n" +"This option can increase a printing time." +msgstr "" + +msgid "Separated infills" +msgstr "" + +msgid "" +"Centers the internal infill of each part on itself, as if it were sliced on its own, instead of on the whole assembly. Parts that touch or overlap are treated as one body and share a center; separate parts (or distinct 3D objects) each get their own.\n" +"Useful when an assembly groups several objects that should each keep a consistent, self-centered infill.\n" +"Affects line and grid patterns and rotation-template infills.\n" +"Patterns locked to global coordinates (Gyroid, Honeycomb, TPMS, ...) are unaffected." +msgstr "" + +msgid "Center surface pattern on" +msgstr "" + +msgid "" +"Chooses where the centering point of centered top/bottom surface patterns (Archimedean Chords, Octagram Spiral) is placed.\n" +" - Each Surface: centers the pattern on every individual surface region, so each island is symmetric on its own.\n" +" - Each Model: centers the pattern on each connected body. Parts that touch or overlap share one center; parts detached from the rest each get their own.\n" +" - Each Assembly: uses a single shared center for the whole object or assembly." +msgstr "" + +msgid "Each Surface" +msgstr "" + +msgid "Each Model" +msgstr "" + +msgid "Each Assembly" +msgstr "" + msgid "This is the speed at which traveling is done." msgstr "Vitesse de déplacement plus rapide et sans extrusion" @@ -19396,6 +19483,68 @@ msgstr "" "Éviter la déformation\n" "Saviez-vous que lors de l’impression de matériaux susceptibles de se déformer, tels que l’ABS, une augmentation appropriée de la température du plateau chauffant peut réduire la probabilité de déformation?" +#~ msgid "Continue to sync filaments" +#~ msgstr "Continuer la synchronisation des filaments" + +#~ msgctxt "Sync_Nozzle_AMS" +#~ msgid "Cancel" +#~ msgstr "Annuler" + +#, no-c-format, no-boost-format +#~ msgid "" +#~ "External Bridging angle override.\n" +#~ "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" +#~ "Otherwise the provided angle will be used according to:\n" +#~ " - The absolute coordinates\n" +#~ " - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +#~ " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" +#~ "\n" +#~ "Use 180° for zero absolute angle." +#~ msgstr "" +#~ "Remplacement de l’angle des ponts externes.\n" +#~ "Si laissé à zéro, l’angle des ponts est calculé automatiquement pour chaque pont.\n" +#~ "Sinon, l’angle fourni est utilisé selon :\n" +#~ " - les coordonnées absolues\n" +#~ " - les coordonnées absolues + la rotation du modèle : si « Aligner la direction du remplissage sur le modèle » est activé\n" +#~ " - l’angle automatique optimal + cette valeur : si « Angle de pont relatif » est activé\n" +#~ "\n" +#~ "Utilisez 180° pour un angle absolu nul." + +#~ msgid "" +#~ "Internal Bridging angle override.\n" +#~ "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" +#~ "Otherwise the provided angle will be used according to:\n" +#~ " - The absolute coordinates\n" +#~ " - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +#~ " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" +#~ "\n" +#~ "Use 180° for zero absolute angle." +#~ msgstr "" +#~ "Remplacement de l’angle des ponts internes.\n" +#~ "Si laissé à zéro, l’angle des ponts est calculé automatiquement pour chaque pont.\n" +#~ "Sinon, l’angle fourni est utilisé selon :\n" +#~ " - les coordonnées absolues\n" +#~ " - les coordonnées absolues + la rotation du modèle : si « Aligner la direction du remplissage sur le modèle » est activé\n" +#~ " - l’angle automatique optimal + cette valeur : si « Angle de pont relatif » est activé\n" +#~ "\n" +#~ "Utilisez 180° pour un angle absolu nul." + +#~ msgid "Align infill direction to model" +#~ msgstr "Aligner la direction du remplissage sur le modèle" + +#~ msgid "" +#~ "Aligns infill, bridge, ironing and surface fill directions to follow the model's orientation on the build plate.\n" +#~ "When enabled, directions rotate with the model to maintain optimal strength characteristics." +#~ msgstr "" +#~ "Aligne les directions du remplissage, des ponts, du lissage et des surfaces sur l’orientation du modèle sur le plateau.\n" +#~ "Lorsque cette option est activée, les directions pivotent avec le modèle afin de conserver des caractéristiques de résistance optimales." + +#~ msgid "Print" +#~ msgstr "Imprimer" + +#~ msgid "in" +#~ msgstr "dans" + #~ msgid "Object coordinates" #~ msgstr "Coordonnées de l’objet" @@ -21103,10 +21252,6 @@ msgstr "" #~ msgid "Unselect" #~ msgstr "Désélectionner" -#~ msgctxt "Verb" -#~ msgid "Scale" -#~ msgstr "Redimensionner" - #~ msgid "Lift Z Enforcement" #~ msgstr "Exécution du décalage en Z" diff --git a/localization/i18n/hu/OrcaSlicer_hu.po b/localization/i18n/hu/OrcaSlicer_hu.po index 50c1f60314..7c10c269e4 100644 --- a/localization/i18n/hu/OrcaSlicer_hu.po +++ b/localization/i18n/hu/OrcaSlicer_hu.po @@ -3,7 +3,7 @@ msgid "" msgstr "" "Project-Id-Version: Orca Slicer\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-07-06 12:57-0300\n" +"POT-Creation-Date: 2026-07-12 12:27-0300\n" "Language: hu\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -159,6 +159,12 @@ msgstr "Kitöltés" msgid "Gap Fill" msgstr "Hézagok kitöltése" +msgid "Vertical" +msgstr "Függőleges" + +msgid "Horizontal" +msgstr "Vízszintes" + #, boost-format msgid "Allows painting only on facets selected by: \"%1%\"" msgstr "Csak a(z) \"%1%\" által kijelölt felületeken történik festés" @@ -254,12 +260,6 @@ msgstr "Háromszög" msgid "Height Range" msgstr "Magasságtartomány" -msgid "Vertical" -msgstr "Függőleges" - -msgid "Horizontal" -msgstr "Vízszintes" - msgid "Remove painted color" msgstr "Festett szín eltávolítása" @@ -324,6 +324,7 @@ msgstr "Gizmo-Forgatás" msgid "Optimize orientation" msgstr "Orientáció optimalizálása" +msgctxt "Verb" msgid "Scale" msgstr "Átméretezés" @@ -333,8 +334,9 @@ msgstr "Gizmo-Átméretezés" msgid "Error: Please close all toolbar menus first" msgstr "Hiba: Kérlek, először zárd be az összes eszköztár menüt" +msgctxt "inches" msgid "in" -msgstr "in" +msgstr "" msgid "mm" msgstr "mm" @@ -367,6 +369,9 @@ msgstr "Méretarányok" msgid "Object operations" msgstr "Objektum műveletek" +msgid "Scale" +msgstr "Átméretezés" + # TODO: Review, changed by lang refactor. PR 14254 msgid "Volume operations" msgstr "Térfogat műveletek" @@ -418,6 +423,10 @@ msgstr "Az aktuális forgatás visszaállítása a forgatás eszköz megnyitása msgid "Reset current rotation to real zeros." msgstr "Az aktuális forgatás visszaállítása valódi nullára." +msgctxt "Noun" +msgid "Scale" +msgstr "Átméretezés" + #. TRN - Input label. Be short as possible msgid "Size" msgstr "Méret" @@ -3644,7 +3653,7 @@ msgstr "A kalibrálás befejeződött. Kérlek, válaszd ki az alábbi képen l msgid "Save" msgstr "Mentés" -# TODO: Review, changed by lang refactor. PR 14254 +msgctxt "Navigation" msgid "Back" msgstr "Hátul" @@ -5025,6 +5034,7 @@ msgstr "Szerszámváltások" msgid "Color change" msgstr "Színváltás" +msgctxt "Noun" msgid "Print" msgstr "Nyomtatás" @@ -5188,11 +5198,15 @@ msgstr "Extrudáláskalibráció környékének elkerülése" msgid "Align to Y axis" msgstr "Igazítás az Y-tengelyhez" -msgctxt "Camera" +msgctxt "Camera View" +msgid "Back" +msgstr "Hátul" + +msgctxt "Camera View" msgid "Left" msgstr "Bal" -msgctxt "Camera" +msgctxt "Camera View" msgid "Right" msgstr "Jobb" @@ -5520,6 +5534,10 @@ msgstr "Nyomtatótálca" msgid "Export G-code file" msgstr "G-kód fájl exportálása" +msgctxt "Verb" +msgid "Print" +msgstr "Nyomtatás" + msgid "Export plate sliced file" msgstr "Szeletelt tálca exportálása" @@ -5693,15 +5711,6 @@ msgstr "Aktuális konfiguráció exportálása fájlokba" msgid "Export" msgstr "Exportálás" -msgid "Sync Presets" -msgstr "Beállítások szinkronizálása" - -msgid "Pull and apply the latest presets from OrcaCloud" -msgstr "Hívd le és alkalmazd az OrcaCloud legújabb beállításait" - -msgid "You must be logged in to sync presets from cloud." -msgstr "A beállítások felhőből történő szinkronizálásához be kell jelentkezz." - msgid "Quit" msgstr "Kilépés" @@ -5818,6 +5827,15 @@ msgstr "Nézet" msgid "Preset Bundle" msgstr "Beállításcsomag" +msgid "Sync Presets" +msgstr "Beállítások szinkronizálása" + +msgid "Pull and apply the latest presets from OrcaCloud" +msgstr "Hívd le és alkalmazd az OrcaCloud legújabb beállításait" + +msgid "You must be logged in to sync presets from cloud." +msgstr "A beállítások felhőből történő szinkronizálásához be kell jelentkezz." + msgid "Syncing presets from cloud…" msgstr "Beállítások szinkronizálása a felhőből…" @@ -10342,12 +10360,8 @@ msgstr "A fúvókainformációk szinkronizálása sikerült." msgid "Successfully synchronized nozzle and AMS number information." msgstr "A fúvóka- és AMS-száminformációk szinkronizálása sikerült." -msgid "Continue to sync filaments" -msgstr "Filamentek szinkronizálásának folytatása" - -msgctxt "Sync_Nozzle_AMS" -msgid "Cancel" -msgstr "Mégse" +msgid "Do you want to continue to sync filaments?" +msgstr "" msgid "Successfully synchronized filament color from printer." msgstr "A filament színének szinkronizálása a nyomtatóról sikerült." @@ -11676,7 +11690,7 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." @@ -11690,7 +11704,7 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." @@ -12425,6 +12439,42 @@ msgstr "Felső felületi sűrűség" msgid "Density of top surface layer. A value of 100% creates a fully solid, smooth top layer. Reducing this value results in a textured top surface, according to the chosen top surface pattern. A value of 0% will result in only the walls on the top layer being created. Intended for aesthetic or functional purposes, not to fix issues such as over-extrusion." msgstr "A felső felületi réteg sűrűsége. A 100%-os érték teljesen tömör, sima felső réteget hoz létre. Ennek az értéknek a csökkentése a kiválasztott felső felületi mintázatnak megfelelően texturált felső felületet eredményez. A 0%-os érték azt eredményezi, hogy a felső rétegen csak a falak jönnek létre. Esztétikai vagy funkcionális célokra szolgál, nem pedig olyan problémák javítására, mint a túlextrudálás." +msgid "Top surface expansion" +msgstr "" + +msgid "" +"Expands the top surfaces by this distance to connect distinct top surfaces and fill gaps.\n" +"Useful for cases where the top surface is interrupted by a raised feature, such as text on a plane.Expanding it removes the holes beneath these features and creates a continuous path with a better finish for printing on top.The expansion is applied to the original top surface, before any other processing such as bridging or overhang detection." +msgstr "" + +msgid "Top expansion wall margin" +msgstr "" + +msgid "" +"Using “Top surface expansion” may cause a surface that did not previously touch the model's outer walls to now do so.\n" +"This can cause contraction marks (such as the hull line) on the outer walls.\n" +"By adding a small margin, this contraction will not occur directly on the walls, thereby preventing a visible mark." +msgstr "" + +msgid "Top expansion direction" +msgstr "" + +msgid "" +"Direction in which the top surface expansion grows.\n" +" - Inward grows into the holes and gaps left by features rising from the middle of a top surface.\n" +" - Outward grows the outer edge of the surface, connecting surfaces separated by features that can divide a surface, such as a lattice pattern.\n" +" - Inward and Outward does both." +msgstr "" + +msgid "Inward and Outward" +msgstr "" + +msgid "Inward" +msgstr "" + +msgid "Outward" +msgstr "" + msgid "Bottom surface pattern" msgstr "Alsó felület mintázata" @@ -13092,12 +13142,12 @@ msgstr "Kitöltés sűrűsége" msgid "Density of internal sparse infill, 100% turns all sparse infill into solid infill and internal solid infill pattern will be used." msgstr "A belső ritka kitöltés sűrűsége. A 100% minden ritka kitöltést tömör kitöltéssé alakít, és a belső tömör kitöltési minta kerül használatra." -msgid "Align infill direction to model" -msgstr "Kitöltési irány igazítása a modellhez" +msgid "Align directions to model" +msgstr "" msgid "" -"Aligns infill, bridge, ironing and surface fill directions to follow the model's orientation on the build plate.\n" -"When enabled, directions rotate with the model to maintain optimal strength characteristics." +"Aligns infill, bridge, ironing, and top/bottom surface directions to follow the model's orientation on the build plate.\n" +"When enabled, these directions rotate together with the model so the printed features keep their intended orientation relative to the part, preserving optimal strength and surface characteristics regardless of how the model is placed." msgstr "" msgid "Insert solid layers" @@ -14879,6 +14929,10 @@ msgstr "Igazított" msgid "Aligned back" msgstr "Hátulra igazítva" +# TODO: Review, changed by lang refactor. PR 14254 +msgid "Back" +msgstr "Hátul" + msgid "Random" msgstr "Véletlenszerû" @@ -15243,6 +15297,18 @@ msgstr "Az összes nyomtató extruder előkészítése" msgid "If enabled, all printing extruders will be primed at the front edge of the print bed at the start of the print." msgstr "Ha engedélyezve van, akkor a nyomtatás kezdetén az összes nyomtató extruder előkészítésre kerül a tárgyasztal elülső szélénél." +msgid "Toolchange ordering" +msgstr "" + +msgid "" +"Determines the order of tool changes on each layer.\n" +"- Default: Starts with the last used extruder to minimize tool changes.\n" +"- Cyclic: Uses a fixed tool sequence each layer. This sacrifices speed for better surface quality, as the extra toolchanges allow layers more time to cool." +msgstr "" + +msgid "Cyclic" +msgstr "" + msgid "Slice gap closing radius" msgstr "Szeletelési hézag lezárási sugara" @@ -15690,6 +15756,45 @@ msgstr "Felső héj vastagság" msgid "The number of top solid layers is increased when slicing if the thickness calculated by top shell layers is thinner than this value. This can avoid having too thin a shell when layer height is small. 0 means that this setting is disabled and thickness of top shell is determined simply by the number of top shell layers." msgstr "A felső szilárd rétegek száma szeleteléskor megnő, ha a felső héjrétegekből számított vastagság kisebb ennél az értéknél. Ezzel elkerülhető, hogy túl vékony legyen a héj kis rétegmagasságnál. A 0 azt jelenti, hogy ez a beállítás ki van kapcsolva, és a felső héj vastagságát egyszerűen a felső héjrétegek száma határozza meg." +msgid "Anisotropic surfaces" +msgstr "" + +msgid "" +"Anisotropic patterns on the top and bottom surfaces.\n" +"Co-directional printing mode will be applied. For certain patterns, omni-directional filling provides color dispersion when using multi-colored or silk plastics.\n" +"This option disable the gap fill.\n" +"This option can increase a printing time." +msgstr "" + +msgid "Separated infills" +msgstr "" + +msgid "" +"Centers the internal infill of each part on itself, as if it were sliced on its own, instead of on the whole assembly. Parts that touch or overlap are treated as one body and share a center; separate parts (or distinct 3D objects) each get their own.\n" +"Useful when an assembly groups several objects that should each keep a consistent, self-centered infill.\n" +"Affects line and grid patterns and rotation-template infills.\n" +"Patterns locked to global coordinates (Gyroid, Honeycomb, TPMS, ...) are unaffected." +msgstr "" + +msgid "Center surface pattern on" +msgstr "" + +msgid "" +"Chooses where the centering point of centered top/bottom surface patterns (Archimedean Chords, Octagram Spiral) is placed.\n" +" - Each Surface: centers the pattern on every individual surface region, so each island is symmetric on its own.\n" +" - Each Model: centers the pattern on each connected body. Parts that touch or overlap share one center; parts detached from the rest each get their own.\n" +" - Each Assembly: uses a single shared center for the whole object or assembly." +msgstr "" + +msgid "Each Surface" +msgstr "" + +msgid "Each Model" +msgstr "" + +msgid "Each Assembly" +msgstr "" + # TODO: Review, changed by lang refactor. PR 14254 msgid "This is the speed at which traveling is done." msgstr "Mozgási sebesség, amikor nem történik extrudálás" @@ -19711,6 +19816,22 @@ msgstr "" "Kunkorodás elkerülése\n" "Tudtad, hogy a kunkorodásra hajlamos anyagok (például ABS) nyomtatásakor a tárgyasztal hőmérsékletének növelése csökkentheti a kunkorodás valószínűségét?" +#~ msgid "Continue to sync filaments" +#~ msgstr "Filamentek szinkronizálásának folytatása" + +#~ msgctxt "Sync_Nozzle_AMS" +#~ msgid "Cancel" +#~ msgstr "Mégse" + +#~ msgid "Align infill direction to model" +#~ msgstr "Kitöltési irány igazítása a modellhez" + +#~ msgid "Print" +#~ msgstr "Nyomtatás" + +#~ msgid "in" +#~ msgstr "in" + #~ msgid "Object coordinates" #~ msgstr "Objektum koordináták" diff --git a/localization/i18n/it/OrcaSlicer_it.po b/localization/i18n/it/OrcaSlicer_it.po index 98cbe6de17..d927747e09 100644 --- a/localization/i18n/it/OrcaSlicer_it.po +++ b/localization/i18n/it/OrcaSlicer_it.po @@ -3,7 +3,7 @@ msgid "" msgstr "" "Project-Id-Version: Orca Slicer\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-07-06 12:57-0300\n" +"POT-Creation-Date: 2026-07-12 12:27-0300\n" "PO-Revision-Date: \n" "Last-Translator: \n" "Language-Team: \n" @@ -162,6 +162,12 @@ msgstr "Riempi" msgid "Gap Fill" msgstr "Riempi spazio vuoto" +msgid "Vertical" +msgstr "Verticale" + +msgid "Horizontal" +msgstr "Orizzontale" + #, boost-format msgid "Allows painting only on facets selected by: \"%1%\"" msgstr "Consente di dipingere solo sulle facce selezionate da: \"%1%\"" @@ -257,12 +263,6 @@ msgstr "Triangolo" msgid "Height Range" msgstr "Interv. altezza" -msgid "Vertical" -msgstr "Verticale" - -msgid "Horizontal" -msgstr "Orizzontale" - msgid "Remove painted color" msgstr "Rimuovi colore dipinto" @@ -327,6 +327,7 @@ msgstr "Strumento di rotazione" msgid "Optimize orientation" msgstr "Ottimizza orientamento" +msgctxt "Verb" msgid "Scale" msgstr "Ridimensiona" @@ -336,8 +337,9 @@ msgstr "Strumento di ridimensionamento" msgid "Error: Please close all toolbar menus first" msgstr "Errore: chiudi prima tutti i menu della barra degli strumenti" +msgctxt "inches" msgid "in" -msgstr "in" +msgstr "" msgid "mm" msgstr "mm" @@ -370,6 +372,9 @@ msgstr "Rapporti di scala" msgid "Object operations" msgstr "Operazioni sugli oggetti" +msgid "Scale" +msgstr "Ridimensiona" + # TODO: Review, changed by lang refactor. PR 14254 msgid "Volume operations" msgstr "Operazioni volume" @@ -421,6 +426,10 @@ msgstr "Reimposta la rotazione corrente al valore di apertura dello strumento." msgid "Reset current rotation to real zeros." msgstr "Reimposta la rotazione corrente a zero reale." +msgctxt "Noun" +msgid "Scale" +msgstr "Ridimensiona" + #. TRN - Input label. Be short as possible msgid "Size" msgstr "Dimensioni" @@ -3645,7 +3654,7 @@ msgstr "Calibrazione completata. Trova la linea di estrusione più uniforme sul msgid "Save" msgstr "Salva" -# TODO: Review, changed by lang refactor. PR 14254 +msgctxt "Navigation" msgid "Back" msgstr "Posteriore" @@ -5026,6 +5035,7 @@ msgstr "Cambi testina" msgid "Color change" msgstr "Cambio colore" +msgctxt "Noun" msgid "Print" msgstr "Stampa" @@ -5189,11 +5199,15 @@ msgstr "Evitare la regione di calibrazione dell'estrusione" msgid "Align to Y axis" msgstr "Allinea all'asse Y" -msgctxt "Camera" +msgctxt "Camera View" +msgid "Back" +msgstr "Posteriore" + +msgctxt "Camera View" msgid "Left" msgstr "Sinistra" -msgctxt "Camera" +msgctxt "Camera View" msgid "Right" msgstr "Destra" @@ -5521,6 +5535,10 @@ msgstr "Piatto di stampa" msgid "Export G-code file" msgstr "Esporta file G-code" +msgctxt "Verb" +msgid "Print" +msgstr "Stampa" + msgid "Export plate sliced file" msgstr "Esporta il file del piatto elaborato" @@ -5694,15 +5712,6 @@ msgstr "Esporta la configurazione corrente in un file" msgid "Export" msgstr "Esporta" -msgid "Sync Presets" -msgstr "" - -msgid "Pull and apply the latest presets from OrcaCloud" -msgstr "" - -msgid "You must be logged in to sync presets from cloud." -msgstr "" - msgid "Quit" msgstr "Esci" @@ -5819,6 +5828,15 @@ msgstr "Vista" msgid "Preset Bundle" msgstr "Pacchetto profili" +msgid "Sync Presets" +msgstr "" + +msgid "Pull and apply the latest presets from OrcaCloud" +msgstr "" + +msgid "You must be logged in to sync presets from cloud." +msgstr "" + msgid "Syncing presets from cloud…" msgstr "" @@ -10324,12 +10342,8 @@ msgstr "Informazioni ugello sincronizzate con successo." msgid "Successfully synchronized nozzle and AMS number information." msgstr "Informazioni ugello e numero AMS sincronizzate con successo." -msgid "Continue to sync filaments" -msgstr "Continua la sincronizzazione dei filamenti" - -msgctxt "Sync_Nozzle_AMS" -msgid "Cancel" -msgstr "Annulla" +msgid "Do you want to continue to sync filaments?" +msgstr "" msgid "Successfully synchronized filament color from printer." msgstr "Colore del filamento sincronizzato con successo dalla stampante." @@ -11658,7 +11672,7 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." @@ -11672,7 +11686,7 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." @@ -12408,6 +12422,42 @@ msgstr "Densità superficie superiore" msgid "Density of top surface layer. A value of 100% creates a fully solid, smooth top layer. Reducing this value results in a textured top surface, according to the chosen top surface pattern. A value of 0% will result in only the walls on the top layer being created. Intended for aesthetic or functional purposes, not to fix issues such as over-extrusion." msgstr "Densità dello strato superficiale superiore. Un valore del 100% crea uno strato superiore completamente solido e liscio. La riduzione di questo valore produce una superficie superiore texturizzata, secondo il pattern di superficie superiore scelto. Un valore dello 0% risulterà nella creazione delle sole pareti sullo strato superiore. Destinato a scopi estetici o funzionali, non per risolvere problemi come la sovraestrusione." +msgid "Top surface expansion" +msgstr "" + +msgid "" +"Expands the top surfaces by this distance to connect distinct top surfaces and fill gaps.\n" +"Useful for cases where the top surface is interrupted by a raised feature, such as text on a plane.Expanding it removes the holes beneath these features and creates a continuous path with a better finish for printing on top.The expansion is applied to the original top surface, before any other processing such as bridging or overhang detection." +msgstr "" + +msgid "Top expansion wall margin" +msgstr "" + +msgid "" +"Using “Top surface expansion” may cause a surface that did not previously touch the model's outer walls to now do so.\n" +"This can cause contraction marks (such as the hull line) on the outer walls.\n" +"By adding a small margin, this contraction will not occur directly on the walls, thereby preventing a visible mark." +msgstr "" + +msgid "Top expansion direction" +msgstr "" + +msgid "" +"Direction in which the top surface expansion grows.\n" +" - Inward grows into the holes and gaps left by features rising from the middle of a top surface.\n" +" - Outward grows the outer edge of the surface, connecting surfaces separated by features that can divide a surface, such as a lattice pattern.\n" +" - Inward and Outward does both." +msgstr "" + +msgid "Inward and Outward" +msgstr "" + +msgid "Inward" +msgstr "" + +msgid "Outward" +msgstr "" + msgid "Bottom surface pattern" msgstr "Motivo superficie inferiore" @@ -13075,12 +13125,12 @@ msgstr "Densità riempimento sparso" msgid "Density of internal sparse infill, 100% turns all sparse infill into solid infill and internal solid infill pattern will be used." msgstr "Densità del riempimento sparso interno. 100% trasforma il riempimento sparso in riempimento solido e verrà utilizzato il motivo del riempimento solido interno." -msgid "Align infill direction to model" -msgstr "Allinea direzione riempimento al modello" +msgid "Align directions to model" +msgstr "" msgid "" -"Aligns infill, bridge, ironing and surface fill directions to follow the model's orientation on the build plate.\n" -"When enabled, directions rotate with the model to maintain optimal strength characteristics." +"Aligns infill, bridge, ironing, and top/bottom surface directions to follow the model's orientation on the build plate.\n" +"When enabled, these directions rotate together with the model so the printed features keep their intended orientation relative to the part, preserving optimal strength and surface characteristics regardless of how the model is placed." msgstr "" msgid "Insert solid layers" @@ -14853,6 +14903,10 @@ msgstr "Allineato" msgid "Aligned back" msgstr "Allineato dietro" +# TODO: Review, changed by lang refactor. PR 14254 +msgid "Back" +msgstr "Posteriore" + msgid "Random" msgstr "Casuale" @@ -15213,6 +15267,18 @@ msgstr "Prepara tutti gli estrusori di stampa" msgid "If enabled, all printing extruders will be primed at the front edge of the print bed at the start of the print." msgstr "Se abilitata, tutti gli estrusori di stampa verranno preparati nel bordo frontale del piano di stampa all'inizio della stampa." +msgid "Toolchange ordering" +msgstr "" + +msgid "" +"Determines the order of tool changes on each layer.\n" +"- Default: Starts with the last used extruder to minimize tool changes.\n" +"- Cyclic: Uses a fixed tool sequence each layer. This sacrifices speed for better surface quality, as the extra toolchanges allow layers more time to cool." +msgstr "" + +msgid "Cyclic" +msgstr "" + msgid "Slice gap closing radius" msgstr "Raggio di chiusura spazi vuoti" @@ -15658,6 +15724,45 @@ msgstr "Spessore guscio superiore" msgid "The number of top solid layers is increased when slicing if the thickness calculated by top shell layers is thinner than this value. This can avoid having too thin a shell when layer height is small. 0 means that this setting is disabled and thickness of top shell is determined simply by the number of top shell layers." msgstr "Il numero di strati solidi superiori viene aumentato durante l'elaborazione se lo spessore calcolato dagli strati del guscio superiore è più sottile di questo valore. In questo modo si evita di avere un guscio troppo sottile quando l'altezza degli strati è piccola. Il valore 0 indica che questa impostazione è disattivata e che lo spessore del guscio superiore è determinato in modo assoluto dagli strati del guscio superiore." +msgid "Anisotropic surfaces" +msgstr "" + +msgid "" +"Anisotropic patterns on the top and bottom surfaces.\n" +"Co-directional printing mode will be applied. For certain patterns, omni-directional filling provides color dispersion when using multi-colored or silk plastics.\n" +"This option disable the gap fill.\n" +"This option can increase a printing time." +msgstr "" + +msgid "Separated infills" +msgstr "" + +msgid "" +"Centers the internal infill of each part on itself, as if it were sliced on its own, instead of on the whole assembly. Parts that touch or overlap are treated as one body and share a center; separate parts (or distinct 3D objects) each get their own.\n" +"Useful when an assembly groups several objects that should each keep a consistent, self-centered infill.\n" +"Affects line and grid patterns and rotation-template infills.\n" +"Patterns locked to global coordinates (Gyroid, Honeycomb, TPMS, ...) are unaffected." +msgstr "" + +msgid "Center surface pattern on" +msgstr "" + +msgid "" +"Chooses where the centering point of centered top/bottom surface patterns (Archimedean Chords, Octagram Spiral) is placed.\n" +" - Each Surface: centers the pattern on every individual surface region, so each island is symmetric on its own.\n" +" - Each Model: centers the pattern on each connected body. Parts that touch or overlap share one center; parts detached from the rest each get their own.\n" +" - Each Assembly: uses a single shared center for the whole object or assembly." +msgstr "" + +msgid "Each Surface" +msgstr "" + +msgid "Each Model" +msgstr "" + +msgid "Each Assembly" +msgstr "" + # TODO: Review, changed by lang refactor. PR 14254 msgid "This is the speed at which traveling is done." msgstr "Indica la velocità di spostamento più rapida e senza estrusione." @@ -19691,6 +19796,22 @@ msgstr "" "Evita le deformazioni\n" "Sapevi che quando si stampano materiali soggetti a deformazioni come l'ABS, aumentare in modo appropriato la temperatura del piano riscaldato può ridurre la probabilità di deformazione?" +#~ msgid "Continue to sync filaments" +#~ msgstr "Continua la sincronizzazione dei filamenti" + +#~ msgctxt "Sync_Nozzle_AMS" +#~ msgid "Cancel" +#~ msgstr "Annulla" + +#~ msgid "Align infill direction to model" +#~ msgstr "Allinea direzione riempimento al modello" + +#~ msgid "Print" +#~ msgstr "Stampa" + +#~ msgid "in" +#~ msgstr "in" + #~ msgid "Object coordinates" #~ msgstr "Coordinate oggetto" @@ -21204,10 +21325,6 @@ msgstr "" #~ msgid "Unselect" #~ msgstr "Deseleziona" -#~ msgctxt "Verb" -#~ msgid "Scale" -#~ msgstr "Ridimensiona" - #~ msgid "Lift Z Enforcement" #~ msgstr "Applicazione dell'ascensore Z" diff --git a/localization/i18n/ja/OrcaSlicer_ja.po b/localization/i18n/ja/OrcaSlicer_ja.po index 44639958da..ab274e1e80 100644 --- a/localization/i18n/ja/OrcaSlicer_ja.po +++ b/localization/i18n/ja/OrcaSlicer_ja.po @@ -3,7 +3,7 @@ msgid "" msgstr "" "Project-Id-Version: Orca Slicer\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-07-06 12:57-0300\n" +"POT-Creation-Date: 2026-07-12 12:27-0300\n" "PO-Revision-Date: \n" "Last-Translator: \n" "Language-Team: \n" @@ -162,6 +162,12 @@ msgstr "塗りつぶし" msgid "Gap Fill" msgstr "隙間充填" +msgid "Vertical" +msgstr "垂直" + +msgid "Horizontal" +msgstr "水平" + #, boost-format msgid "Allows painting only on facets selected by: \"%1%\"" msgstr "%1%で選択した面だけをペイントする" @@ -257,12 +263,6 @@ msgstr "三角形" msgid "Height Range" msgstr "高さ範囲" -msgid "Vertical" -msgstr "垂直" - -msgid "Horizontal" -msgstr "水平" - msgid "Remove painted color" msgstr "塗った色を消去" @@ -327,6 +327,7 @@ msgstr "ギズモ-回転" msgid "Optimize orientation" msgstr "向きを最適化" +msgctxt "Verb" msgid "Scale" msgstr "スケール" @@ -336,8 +337,9 @@ msgstr "ギズモ-縮尺" msgid "Error: Please close all toolbar menus first" msgstr "エラー: ツールバーを閉じてください" +msgctxt "inches" msgid "in" -msgstr "に" +msgstr "" msgid "mm" msgstr "mm" @@ -370,6 +372,9 @@ msgstr "倍率" msgid "Object operations" msgstr "オブジェクト操作" +msgid "Scale" +msgstr "スケール" + # TODO: Review, changed by lang refactor. PR 14254 msgid "Volume operations" msgstr "操作" @@ -421,6 +426,10 @@ msgstr "回転ツールを開いた時の値にリセットします。" msgid "Reset current rotation to real zeros." msgstr "現在の回転を0にリセットします。" +msgctxt "Noun" +msgid "Scale" +msgstr "スケール" + #. TRN - Input label. Be short as possible msgid "Size" msgstr "サイズ" @@ -3628,7 +3637,7 @@ msgstr "キャリブレーションが完了しました。下の写真のよう msgid "Save" msgstr "保存" -# TODO: Review, changed by lang refactor. PR 14254 +msgctxt "Navigation" msgid "Back" msgstr "背面" @@ -4999,6 +5008,7 @@ msgstr "ツールチェンジ" msgid "Color change" msgstr "色変更" +msgctxt "Noun" msgid "Print" msgstr "造形する" @@ -5162,11 +5172,15 @@ msgstr "押出しキャリブレーション領域を避ける" msgid "Align to Y axis" msgstr "Y軸に整列" -msgctxt "Camera" +msgctxt "Camera View" +msgid "Back" +msgstr "背面" + +msgctxt "Camera View" msgid "Left" msgstr "左" -msgctxt "Camera" +msgctxt "Camera View" msgid "Right" msgstr "右" @@ -5488,6 +5502,10 @@ msgstr "造形開始" msgid "Export G-code file" msgstr "G-codeをエクスポート" +msgctxt "Verb" +msgid "Print" +msgstr "造形する" + msgid "Export plate sliced file" msgstr "エクスポート" @@ -5661,15 +5679,6 @@ msgstr "現在の構成をエクスポート" msgid "Export" msgstr "エクスポート" -msgid "Sync Presets" -msgstr "" - -msgid "Pull and apply the latest presets from OrcaCloud" -msgstr "" - -msgid "You must be logged in to sync presets from cloud." -msgstr "" - msgid "Quit" msgstr "終了" @@ -5786,6 +5795,15 @@ msgstr "表示" msgid "Preset Bundle" msgstr "" +msgid "Sync Presets" +msgstr "" + +msgid "Pull and apply the latest presets from OrcaCloud" +msgstr "" + +msgid "You must be logged in to sync presets from cloud." +msgstr "" + msgid "Syncing presets from cloud…" msgstr "" @@ -10257,12 +10275,8 @@ msgstr "ノズル情報の同期に成功しました。" msgid "Successfully synchronized nozzle and AMS number information." msgstr "ノズルとAMS数の情報の同期に成功しました。" -msgid "Continue to sync filaments" -msgstr "フィラメントの同期を続行" - -msgctxt "Sync_Nozzle_AMS" -msgid "Cancel" -msgstr "キャンセル" +msgid "Do you want to continue to sync filaments?" +msgstr "" msgid "Successfully synchronized filament color from printer." msgstr "プリンターからフィラメントの色を正常に同期しました。" @@ -11555,7 +11569,7 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." @@ -11569,7 +11583,7 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." @@ -12213,6 +12227,42 @@ msgstr "上面密度" msgid "Density of top surface layer. A value of 100% creates a fully solid, smooth top layer. Reducing this value results in a textured top surface, according to the chosen top surface pattern. A value of 0% will result in only the walls on the top layer being created. Intended for aesthetic or functional purposes, not to fix issues such as over-extrusion." msgstr "" +msgid "Top surface expansion" +msgstr "" + +msgid "" +"Expands the top surfaces by this distance to connect distinct top surfaces and fill gaps.\n" +"Useful for cases where the top surface is interrupted by a raised feature, such as text on a plane.Expanding it removes the holes beneath these features and creates a continuous path with a better finish for printing on top.The expansion is applied to the original top surface, before any other processing such as bridging or overhang detection." +msgstr "" + +msgid "Top expansion wall margin" +msgstr "" + +msgid "" +"Using “Top surface expansion” may cause a surface that did not previously touch the model's outer walls to now do so.\n" +"This can cause contraction marks (such as the hull line) on the outer walls.\n" +"By adding a small margin, this contraction will not occur directly on the walls, thereby preventing a visible mark." +msgstr "" + +msgid "Top expansion direction" +msgstr "" + +msgid "" +"Direction in which the top surface expansion grows.\n" +" - Inward grows into the holes and gaps left by features rising from the middle of a top surface.\n" +" - Outward grows the outer edge of the surface, connecting surfaces separated by features that can divide a surface, such as a lattice pattern.\n" +" - Inward and Outward does both." +msgstr "" + +msgid "Inward and Outward" +msgstr "" + +msgid "Inward" +msgstr "" + +msgid "Outward" +msgstr "" + msgid "Bottom surface pattern" msgstr "底面パターン" @@ -12836,12 +12886,12 @@ msgstr "充填密度" msgid "Density of internal sparse infill, 100% turns all sparse infill into solid infill and internal solid infill pattern will be used." msgstr "" -msgid "Align infill direction to model" -msgstr "インフィル方向をモデルに合わせる" +msgid "Align directions to model" +msgstr "" msgid "" -"Aligns infill, bridge, ironing and surface fill directions to follow the model's orientation on the build plate.\n" -"When enabled, directions rotate with the model to maintain optimal strength characteristics." +"Aligns infill, bridge, ironing, and top/bottom surface directions to follow the model's orientation on the build plate.\n" +"When enabled, these directions rotate together with the model so the printed features keep their intended orientation relative to the part, preserving optimal strength and surface characteristics regardless of how the model is placed." msgstr "" msgid "Insert solid layers" @@ -14501,6 +14551,10 @@ msgstr "整列" msgid "Aligned back" msgstr "" +# TODO: Review, changed by lang refactor. PR 14254 +msgid "Back" +msgstr "背面" + msgid "Random" msgstr "ランダム" @@ -14843,6 +14897,18 @@ msgstr "全てのエクストルーダーでプライムを実施" msgid "If enabled, all printing extruders will be primed at the front edge of the print bed at the start of the print." msgstr "有効にすると、すべてのプリントエクストルーダーは、プリント開始時にプリントベッドの前端で準備されます。" +msgid "Toolchange ordering" +msgstr "" + +msgid "" +"Determines the order of tool changes on each layer.\n" +"- Default: Starts with the last used extruder to minimize tool changes.\n" +"- Cyclic: Uses a fixed tool sequence each layer. This sacrifices speed for better surface quality, as the extra toolchanges allow layers more time to cool." +msgstr "" + +msgid "Cyclic" +msgstr "" + msgid "Slice gap closing radius" msgstr "隙間充填半径" @@ -15271,6 +15337,45 @@ msgstr "トップ面厚さ" msgid "The number of top solid layers is increased when slicing if the thickness calculated by top shell layers is thinner than this value. This can avoid having too thin a shell when layer height is small. 0 means that this setting is disabled and thickness of top shell is determined simply by the number of top shell layers." msgstr "トップ面の厚さです、トップ面層数で決まった厚みがこの値より小さい場合、層数を増やします。この値が0にする場合、この設定が無効となり、設定した層数で造形します。" +msgid "Anisotropic surfaces" +msgstr "" + +msgid "" +"Anisotropic patterns on the top and bottom surfaces.\n" +"Co-directional printing mode will be applied. For certain patterns, omni-directional filling provides color dispersion when using multi-colored or silk plastics.\n" +"This option disable the gap fill.\n" +"This option can increase a printing time." +msgstr "" + +msgid "Separated infills" +msgstr "" + +msgid "" +"Centers the internal infill of each part on itself, as if it were sliced on its own, instead of on the whole assembly. Parts that touch or overlap are treated as one body and share a center; separate parts (or distinct 3D objects) each get their own.\n" +"Useful when an assembly groups several objects that should each keep a consistent, self-centered infill.\n" +"Affects line and grid patterns and rotation-template infills.\n" +"Patterns locked to global coordinates (Gyroid, Honeycomb, TPMS, ...) are unaffected." +msgstr "" + +msgid "Center surface pattern on" +msgstr "" + +msgid "" +"Chooses where the centering point of centered top/bottom surface patterns (Archimedean Chords, Octagram Spiral) is placed.\n" +" - Each Surface: centers the pattern on every individual surface region, so each island is symmetric on its own.\n" +" - Each Model: centers the pattern on each connected body. Parts that touch or overlap share one center; parts detached from the rest each get their own.\n" +" - Each Assembly: uses a single shared center for the whole object or assembly." +msgstr "" + +msgid "Each Surface" +msgstr "" + +msgid "Each Model" +msgstr "" + +msgid "Each Assembly" +msgstr "" + # TODO: Review, changed by lang refactor. PR 14254 msgid "This is the speed at which traveling is done." msgstr "移動完了時の速度です。" @@ -19159,6 +19264,22 @@ msgstr "" "反りを避ける\n" "ABSのような反りやすい素材を印刷する場合、ヒートベッドの温度を適切に上げることで、反りが発生する確率を下げることができることをご存知ですか?" +#~ msgid "Continue to sync filaments" +#~ msgstr "フィラメントの同期を続行" + +#~ msgctxt "Sync_Nozzle_AMS" +#~ msgid "Cancel" +#~ msgstr "キャンセル" + +#~ msgid "Align infill direction to model" +#~ msgstr "インフィル方向をモデルに合わせる" + +#~ msgid "Print" +#~ msgstr "造形する" + +#~ msgid "in" +#~ msgstr "に" + #~ msgid "Object coordinates" #~ msgstr "オブジェクト座標" @@ -20102,10 +20223,6 @@ msgstr "" #~ msgid "Unselect" #~ msgstr "選択解除" -#~ msgctxt "Verb" -#~ msgid "Scale" -#~ msgstr "スケール" - #~ msgid "Z-hop when retract" #~ msgstr "リトラクト時にZ方向調整" diff --git a/localization/i18n/ko/OrcaSlicer_ko.po b/localization/i18n/ko/OrcaSlicer_ko.po index c90d27048d..512161c0b5 100644 --- a/localization/i18n/ko/OrcaSlicer_ko.po +++ b/localization/i18n/ko/OrcaSlicer_ko.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Orca Slicer\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-07-06 12:57-0300\n" +"POT-Creation-Date: 2026-07-12 12:27-0300\n" "PO-Revision-Date: 2025-06-02 17:12+0900\n" "Last-Translator: crwusiz \n" "Language-Team: \n" @@ -166,6 +166,12 @@ msgstr "채우기" msgid "Gap Fill" msgstr "간격 채우기" +msgid "Vertical" +msgstr "수직" + +msgid "Horizontal" +msgstr "수평" + #, boost-format msgid "Allows painting only on facets selected by: \"%1%\"" msgstr "\"%1%\"에서 선택한 영역에만 칠하기 허용" @@ -261,12 +267,6 @@ msgstr "삼각형" msgid "Height Range" msgstr "높이 범위" -msgid "Vertical" -msgstr "수직" - -msgid "Horizontal" -msgstr "수평" - msgid "Remove painted color" msgstr "칠한 색 제거" @@ -331,6 +331,7 @@ msgstr "변형도구 - 회전" msgid "Optimize orientation" msgstr "방향 최적화" +msgctxt "Verb" msgid "Scale" msgstr "배율" @@ -340,8 +341,9 @@ msgstr "변형도구 - 배율" msgid "Error: Please close all toolbar menus first" msgstr "오류: 먼저 모든 도구 모음 메뉴를 닫으십시오." +msgctxt "inches" msgid "in" -msgstr "인치" +msgstr "" msgid "mm" msgstr "mm" @@ -374,6 +376,9 @@ msgstr "배율비" msgid "Object operations" msgstr "객체 작업" +msgid "Scale" +msgstr "배율" + # TODO: Review, changed by lang refactor. PR 14254 msgid "Volume operations" msgstr "용량 작업" @@ -425,6 +430,10 @@ msgstr "회전 도구를 열었을 때의 값으로 현재 회전을 초기화 msgid "Reset current rotation to real zeros." msgstr "현재 회전을 0으로 초기화합니다." +msgctxt "Noun" +msgid "Scale" +msgstr "배율" + #. TRN - Input label. Be short as possible msgid "Size" msgstr "크기" @@ -3643,7 +3652,7 @@ msgstr "교정이 완료되었습니다. 당신의 고온 베드에서 아래 msgid "Save" msgstr "저장" -# TODO: Review, changed by lang refactor. PR 14254 +msgctxt "Navigation" msgid "Back" msgstr "뒷면" @@ -5025,6 +5034,7 @@ msgstr "" msgid "Color change" msgstr "색 변경" +msgctxt "Noun" msgid "Print" msgstr "출력" @@ -5188,11 +5198,15 @@ msgstr "압출 교정 영역을 피하세요" msgid "Align to Y axis" msgstr "Y축에 정렬" -msgctxt "Camera" +msgctxt "Camera View" +msgid "Back" +msgstr "뒷면" + +msgctxt "Camera View" msgid "Left" msgstr "왼쪽" -msgctxt "Camera" +msgctxt "Camera View" msgid "Right" msgstr "오른쪽" @@ -5516,6 +5530,10 @@ msgstr "플레이트 출력" msgid "Export G-code file" msgstr "Gcode 파일 내보내기" +msgctxt "Verb" +msgid "Print" +msgstr "출력" + msgid "Export plate sliced file" msgstr "플레이트 슬라이스 파일 내보내기" @@ -5689,15 +5707,6 @@ msgstr "현재 설정을 파일로 내보내기" msgid "Export" msgstr "내보내기" -msgid "Sync Presets" -msgstr "" - -msgid "Pull and apply the latest presets from OrcaCloud" -msgstr "" - -msgid "You must be logged in to sync presets from cloud." -msgstr "" - msgid "Quit" msgstr "종료" @@ -5814,6 +5823,15 @@ msgstr "시점" msgid "Preset Bundle" msgstr "" +msgid "Sync Presets" +msgstr "" + +msgid "Pull and apply the latest presets from OrcaCloud" +msgstr "" + +msgid "You must be logged in to sync presets from cloud." +msgstr "" + msgid "Syncing presets from cloud…" msgstr "" @@ -10290,12 +10308,8 @@ msgstr "노즐 정보를 성공적으로 동기화했습니다." msgid "Successfully synchronized nozzle and AMS number information." msgstr "노즐 및 AMS 번호 정보를 성공적으로 동기화했습니다." -msgid "Continue to sync filaments" -msgstr "필라멘트 동기화 계속하기" - -msgctxt "Sync_Nozzle_AMS" -msgid "Cancel" -msgstr "취소" +msgid "Do you want to continue to sync filaments?" +msgstr "" msgid "Successfully synchronized filament color from printer." msgstr "" @@ -11617,7 +11631,7 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." @@ -11631,7 +11645,7 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." @@ -12336,6 +12350,42 @@ msgstr "상단 표면 밀도" msgid "Density of top surface layer. A value of 100% creates a fully solid, smooth top layer. Reducing this value results in a textured top surface, according to the chosen top surface pattern. A value of 0% will result in only the walls on the top layer being created. Intended for aesthetic or functional purposes, not to fix issues such as over-extrusion." msgstr "" +msgid "Top surface expansion" +msgstr "" + +msgid "" +"Expands the top surfaces by this distance to connect distinct top surfaces and fill gaps.\n" +"Useful for cases where the top surface is interrupted by a raised feature, such as text on a plane.Expanding it removes the holes beneath these features and creates a continuous path with a better finish for printing on top.The expansion is applied to the original top surface, before any other processing such as bridging or overhang detection." +msgstr "" + +msgid "Top expansion wall margin" +msgstr "" + +msgid "" +"Using “Top surface expansion” may cause a surface that did not previously touch the model's outer walls to now do so.\n" +"This can cause contraction marks (such as the hull line) on the outer walls.\n" +"By adding a small margin, this contraction will not occur directly on the walls, thereby preventing a visible mark." +msgstr "" + +msgid "Top expansion direction" +msgstr "" + +msgid "" +"Direction in which the top surface expansion grows.\n" +" - Inward grows into the holes and gaps left by features rising from the middle of a top surface.\n" +" - Outward grows the outer edge of the surface, connecting surfaces separated by features that can divide a surface, such as a lattice pattern.\n" +" - Inward and Outward does both." +msgstr "" + +msgid "Inward and Outward" +msgstr "" + +msgid "Inward" +msgstr "" + +msgid "Outward" +msgstr "" + msgid "Bottom surface pattern" msgstr "하단 표면 패턴" @@ -12990,12 +13040,12 @@ msgstr "드문 채우기 밀도" msgid "Density of internal sparse infill, 100% turns all sparse infill into solid infill and internal solid infill pattern will be used." msgstr "내부 드문 채우기의 밀도, 100%는 모든 드문 채우기를 꽉찬 내부 채우기로 변경하고 채우기에는 패턴이 사용됩니다" -msgid "Align infill direction to model" +msgid "Align directions to model" msgstr "" msgid "" -"Aligns infill, bridge, ironing and surface fill directions to follow the model's orientation on the build plate.\n" -"When enabled, directions rotate with the model to maintain optimal strength characteristics." +"Aligns infill, bridge, ironing, and top/bottom surface directions to follow the model's orientation on the build plate.\n" +"When enabled, these directions rotate together with the model so the printed features keep their intended orientation relative to the part, preserving optimal strength and surface characteristics regardless of how the model is placed." msgstr "" msgid "Insert solid layers" @@ -14719,6 +14769,10 @@ msgstr "정렬" msgid "Aligned back" msgstr "" +# TODO: Review, changed by lang refactor. PR 14254 +msgid "Back" +msgstr "뒷면" + msgid "Random" msgstr "무작위" @@ -15081,6 +15135,18 @@ msgstr "모든 활성화된 압출기 프라이밍" msgid "If enabled, all printing extruders will be primed at the front edge of the print bed at the start of the print." msgstr "활성화되면 모든 활성화된 압출기는 출력 시작 시 출력 베드의 앞쪽 가장자리에서 프라이밍합니다." +msgid "Toolchange ordering" +msgstr "" + +msgid "" +"Determines the order of tool changes on each layer.\n" +"- Default: Starts with the last used extruder to minimize tool changes.\n" +"- Cyclic: Uses a fixed tool sequence each layer. This sacrifices speed for better surface quality, as the extra toolchanges allow layers more time to cool." +msgstr "" + +msgid "Cyclic" +msgstr "" + msgid "Slice gap closing radius" msgstr "슬라이스 간격 폐쇄 반경" @@ -15520,6 +15586,45 @@ msgstr "상단 쉘 두께" msgid "The number of top solid layers is increased when slicing if the thickness calculated by top shell layers is thinner than this value. This can avoid having too thin a shell when layer height is small. 0 means that this setting is disabled and thickness of top shell is determined simply by the number of top shell layers." msgstr "상단 쉘 레이어로 계산된 두께가 이 값보다 얇은 경우 슬라이싱할 때 상단 꽉찬 레이어의 수가 증가합니다. 이렇게 하면 레이어 높이가 작을 때 쉘이 너무 얇아지는 것을 방지할 수 있습니다. 0은 이 설정이 비활성화되고 상단 쉘의 두께가 절대적으로 상단 쉘 레이어에 의해 결정됨을 의미합니다" +msgid "Anisotropic surfaces" +msgstr "" + +msgid "" +"Anisotropic patterns on the top and bottom surfaces.\n" +"Co-directional printing mode will be applied. For certain patterns, omni-directional filling provides color dispersion when using multi-colored or silk plastics.\n" +"This option disable the gap fill.\n" +"This option can increase a printing time." +msgstr "" + +msgid "Separated infills" +msgstr "" + +msgid "" +"Centers the internal infill of each part on itself, as if it were sliced on its own, instead of on the whole assembly. Parts that touch or overlap are treated as one body and share a center; separate parts (or distinct 3D objects) each get their own.\n" +"Useful when an assembly groups several objects that should each keep a consistent, self-centered infill.\n" +"Affects line and grid patterns and rotation-template infills.\n" +"Patterns locked to global coordinates (Gyroid, Honeycomb, TPMS, ...) are unaffected." +msgstr "" + +msgid "Center surface pattern on" +msgstr "" + +msgid "" +"Chooses where the centering point of centered top/bottom surface patterns (Archimedean Chords, Octagram Spiral) is placed.\n" +" - Each Surface: centers the pattern on every individual surface region, so each island is symmetric on its own.\n" +" - Each Model: centers the pattern on each connected body. Parts that touch or overlap share one center; parts detached from the rest each get their own.\n" +" - Each Assembly: uses a single shared center for the whole object or assembly." +msgstr "" + +msgid "Each Surface" +msgstr "" + +msgid "Each Model" +msgstr "" + +msgid "Each Assembly" +msgstr "" + # TODO: Review, changed by lang refactor. PR 14254 msgid "This is the speed at which traveling is done." msgstr "압출이 없을 때의 이동 속도" @@ -19527,6 +19632,19 @@ msgstr "" "뒤틀림 방지\n" "ABS와 같이 뒤틀림이 발생하기 쉬운 소재를 출력할 때, 히트베드 온도를 적절하게 높이면 뒤틀림 가능성을 줄일 수 있다는 사실을 알고 계셨나요?" +#~ msgid "Continue to sync filaments" +#~ msgstr "필라멘트 동기화 계속하기" + +#~ msgctxt "Sync_Nozzle_AMS" +#~ msgid "Cancel" +#~ msgstr "취소" + +#~ msgid "Print" +#~ msgstr "출력" + +#~ msgid "in" +#~ msgstr "인치" + #~ msgid "Object coordinates" #~ msgstr "객체 좌표" @@ -21015,10 +21133,6 @@ msgstr "" #~ msgid "Unselect" #~ msgstr "선택 취소" -#~ msgctxt "Verb" -#~ msgid "Scale" -#~ msgstr "규모" - #~ msgid "Lift Z Enforcement" #~ msgstr "강제 Z 올리기" diff --git a/localization/i18n/lt/OrcaSlicer_lt.po b/localization/i18n/lt/OrcaSlicer_lt.po index 09b4ccc365..909c087630 100644 --- a/localization/i18n/lt/OrcaSlicer_lt.po +++ b/localization/i18n/lt/OrcaSlicer_lt.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-07-06 12:57-0300\n" +"POT-Creation-Date: 2026-07-12 12:27-0300\n" "PO-Revision-Date: 2026-07-02 14:13+0300\n" "Last-Translator: Gintaras Kučinskas \n" "Language-Team: \n" @@ -164,6 +164,12 @@ msgstr "Užpildymas" msgid "Gap Fill" msgstr "Plyšių užpildymas" +msgid "Vertical" +msgstr "Vertikaliai" + +msgid "Horizontal" +msgstr "Horizontaliai" + #, boost-format msgid "Allows painting only on facets selected by: \"%1%\"" msgstr "Leidžia piešti tik ant paviršių, kuriuos pasirinko: „%1%“" @@ -256,12 +262,6 @@ msgstr "Trikampis" msgid "Height Range" msgstr "Aukščio diapazonas" -msgid "Vertical" -msgstr "Vertikaliai" - -msgid "Horizontal" -msgstr "Horizontaliai" - msgid "Remove painted color" msgstr "Pašalinti dažytą spalvą" @@ -326,6 +326,7 @@ msgstr "Manipuliatorius – Pasukimas" msgid "Optimize orientation" msgstr "Optimizuoti orientaciją" +msgctxt "Verb" msgid "Scale" msgstr "Mastelis" @@ -335,8 +336,9 @@ msgstr "Manipuliatorius – Mastelio keitimas" msgid "Error: Please close all toolbar menus first" msgstr "Klaida: Prašome pirmiau uždaryti visus įrankių juostos meniu" +msgctxt "inches" msgid "in" -msgstr "col." +msgstr "" msgid "mm" msgstr "mm." @@ -368,6 +370,9 @@ msgstr "Mastelio koeficientai" msgid "Object operations" msgstr "" +msgid "Scale" +msgstr "Mastelis" + msgid "Volume operations" msgstr "" @@ -413,6 +418,10 @@ msgstr "Atkurti dabartinį pasukimą iki vertės, buvusios atidarius pasukimo į msgid "Reset current rotation to real zeros." msgstr "Atstatyti dabartinį sukimąsi į tikrąsias nulines vertes." +msgctxt "Noun" +msgid "Scale" +msgstr "Mastelis" + #. TRN - Input label. Be short as possible msgid "Size" msgstr "Dydis" @@ -3575,6 +3584,7 @@ msgstr "Kalibravimas baigtas. Raskite tolygiausią ekstruzijos liniją ant kaiti msgid "Save" msgstr "Išsaugoti" +msgctxt "Navigation" msgid "Back" msgstr "Atgal" @@ -4905,6 +4915,7 @@ msgstr "Įrankio keitimai" msgid "Color change" msgstr "Spalvos keitimas" +msgctxt "Noun" msgid "Print" msgstr "Spausdinti" @@ -5068,11 +5079,15 @@ msgstr "Vengti ekstruzijos kalibravimo srities" msgid "Align to Y axis" msgstr "Išlygiuoti pagal Y ašį" -msgctxt "Camera" +msgctxt "Camera View" +msgid "Back" +msgstr "Atgal" + +msgctxt "Camera View" msgid "Left" msgstr "Kairė" -msgctxt "Camera" +msgctxt "Camera View" msgid "Right" msgstr "Dešinė" @@ -5395,6 +5410,10 @@ msgstr "Spausdinti plokštę" msgid "Export G-code file" msgstr "Eksportuoti G-kodo failą" +msgctxt "Verb" +msgid "Print" +msgstr "Spausdinti" + msgid "Export plate sliced file" msgstr "Eksportuoti supjaustytos plokštės failą" @@ -5568,15 +5587,6 @@ msgstr "Eksportuoti dabartinę konfigūraciją į failus" msgid "Export" msgstr "Eksportuoti" -msgid "Sync Presets" -msgstr "Sinchronizuoti profilius" - -msgid "Pull and apply the latest presets from OrcaCloud" -msgstr "Atsisiųsti ir pritaikyti naujausius profilius iš „OrcaCloud“" - -msgid "You must be logged in to sync presets from cloud." -msgstr "Norėdami sinchronizuoti profilius iš debesies, turite būti prisijungę." - msgid "Quit" msgstr "Išeiti" @@ -5691,6 +5701,15 @@ msgstr "Vaizdas" msgid "Preset Bundle" msgstr "Profilių rinkinys" +msgid "Sync Presets" +msgstr "Sinchronizuoti profilius" + +msgid "Pull and apply the latest presets from OrcaCloud" +msgstr "Atsisiųsti ir pritaikyti naujausius profilius iš „OrcaCloud“" + +msgid "You must be logged in to sync presets from cloud." +msgstr "Norėdami sinchronizuoti profilius iš debesies, turite būti prisijungę." + msgid "Syncing presets from cloud…" msgstr "Sinchronizuojami profiliai iš debesies…" @@ -10142,12 +10161,8 @@ msgstr "Purkštuko informacija sėkmingai sinchronizuota." msgid "Successfully synchronized nozzle and AMS number information." msgstr "Purkštuko ir AMS skaičiaus informacija sėkmingai sinchronizuota." -msgid "Continue to sync filaments" -msgstr "Tęsti gijų sinchronizavimą" - -msgctxt "Sync_Nozzle_AMS" -msgid "Cancel" -msgstr "Atšaukti" +msgid "Do you want to continue to sync filaments?" +msgstr "" msgid "Successfully synchronized filament color from printer." msgstr "Gijos spalva sėkmingai sinchronizuota iš spausdintuvo." @@ -11424,19 +11439,11 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." msgstr "" -"Išorinių tiltelių kampo perrašymas.\n" -"Palikus 0, tiltelio kampas bus apskaičiuojamas automatiškai kiekvienam konkrečiam tilteliui.\n" -"Kitu atveju nurodytas kampas bus naudojamas pagal:\n" -" - absoliučiąsias koordinates;\n" -" - absoliučiąsias koordinates + modelio pasukimą: jei įjungta „Sulygiuoti užpildo kryptį su modeliu“;\n" -" - optimalų automatinį kampą + šią reikšmę: jei įjungta „Santykinis tiltelio kampas“.\n" -"\n" -"Naudokite 180° nulinėms absoliučiosioms koordinatėms." msgid "Internal bridge infill direction" msgstr "Vidinio tilto užpildo kryptis" @@ -11446,19 +11453,11 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." msgstr "" -"Vidinių tiltelių kampo perrašymas.\n" -"Palikus 0, tiltelio kampas bus apskaičiuojamas automatiškai kiekvienam konkrečiam tilteliui.\n" -"Kitu atveju nurodytas kampas bus naudojamas pagal:\n" -" - absoliučiąsias koordinates;\n" -" - absoliučiąsias koordinates + modelio pasukimą: jei įjungta „Sulygiuoti užpildo kryptį su modeliu“;\n" -" - optimalų automatinį kampą + šią reikšmę: jei įjungta „Santykinis tiltelio kampas“.\n" -"\n" -"Naudokite 180° nulinėms absoliučiosioms koordinatėms." msgid "Relative bridge angle" msgstr "Santykinis tiltelio kampas" @@ -12227,6 +12226,42 @@ msgstr "Viršutinio paviršiaus tankis" msgid "Density of top surface layer. A value of 100% creates a fully solid, smooth top layer. Reducing this value results in a textured top surface, according to the chosen top surface pattern. A value of 0% will result in only the walls on the top layer being created. Intended for aesthetic or functional purposes, not to fix issues such as over-extrusion." msgstr "Viršutinio paviršiaus sluoksnio tankis. Nustačius 100 %, sukuriamas visiškai vientisas ir lygus viršutinis sluoksnis. Sumažinus šią reikšmę, gaunamas tekstūruotas viršutinis paviršius pagal pasirinktą raštą. Nustačius 0 %, viršutiniame sluoksnyje bus spausdinamos tik sienelės. Funkcija skirta estetiniais arba funkciniais tikslais, o ne tokioms problemoms kaip perteklinė ekstruzija (over-extrusion) spręsti." +msgid "Top surface expansion" +msgstr "" + +msgid "" +"Expands the top surfaces by this distance to connect distinct top surfaces and fill gaps.\n" +"Useful for cases where the top surface is interrupted by a raised feature, such as text on a plane.Expanding it removes the holes beneath these features and creates a continuous path with a better finish for printing on top.The expansion is applied to the original top surface, before any other processing such as bridging or overhang detection." +msgstr "" + +msgid "Top expansion wall margin" +msgstr "" + +msgid "" +"Using “Top surface expansion” may cause a surface that did not previously touch the model's outer walls to now do so.\n" +"This can cause contraction marks (such as the hull line) on the outer walls.\n" +"By adding a small margin, this contraction will not occur directly on the walls, thereby preventing a visible mark." +msgstr "" + +msgid "Top expansion direction" +msgstr "" + +msgid "" +"Direction in which the top surface expansion grows.\n" +" - Inward grows into the holes and gaps left by features rising from the middle of a top surface.\n" +" - Outward grows the outer edge of the surface, connecting surfaces separated by features that can divide a surface, such as a lattice pattern.\n" +" - Inward and Outward does both." +msgstr "" + +msgid "Inward and Outward" +msgstr "" + +msgid "Inward" +msgstr "" + +msgid "Outward" +msgstr "" + msgid "Bottom surface pattern" msgstr "Apatinio paviršiaus raštas" @@ -12877,15 +12912,13 @@ msgstr "Reto užpildo tankis" msgid "Density of internal sparse infill, 100% turns all sparse infill into solid infill and internal solid infill pattern will be used." msgstr "Vidinio reto užpildo tankis. 100% paverčia visą retą užpildą vientisu užpildu ir tuomet bus naudojamas vidinio vientiso užpildo raštas." -msgid "Align infill direction to model" -msgstr "Suderinti užpildo kryptį su modeliu" +msgid "Align directions to model" +msgstr "" msgid "" -"Aligns infill, bridge, ironing and surface fill directions to follow the model's orientation on the build plate.\n" -"When enabled, directions rotate with the model to maintain optimal strength characteristics." +"Aligns infill, bridge, ironing, and top/bottom surface directions to follow the model's orientation on the build plate.\n" +"When enabled, these directions rotate together with the model so the printed features keep their intended orientation relative to the part, preserving optimal strength and surface characteristics regardless of how the model is placed." msgstr "" -"Sulygiuoja užpildo, tiltelių, lyginimo ir paviršiaus užpildymo kryptis pagal modelio orientaciją ant pagrindo.\n" -"Kai įjungta, kryptys sukasi kartu su modeliu, kad būtų išlaikytos optimalios tvirtumo charakteristikos." msgid "Insert solid layers" msgstr "Įterpti vientisus sluoksnius" @@ -14603,6 +14636,9 @@ msgstr "Sulygiuota" msgid "Aligned back" msgstr "Sulygiuota gale" +msgid "Back" +msgstr "Atgal" + msgid "Random" msgstr "Atsitiktinė" @@ -14960,6 +14996,18 @@ msgstr "Paruošti (prime) visus spausdinimo ekstruderius" msgid "If enabled, all printing extruders will be primed at the front edge of the print bed at the start of the print." msgstr "Jei įjungta, visi spausdinimo ekstruderiai spausdinimo pradžioje bus paruošti (primed) prie priekinio spausdinimo pagrindo krašto." +msgid "Toolchange ordering" +msgstr "" + +msgid "" +"Determines the order of tool changes on each layer.\n" +"- Default: Starts with the last used extruder to minimize tool changes.\n" +"- Cyclic: Uses a fixed tool sequence each layer. This sacrifices speed for better surface quality, as the extra toolchanges allow layers more time to cool." +msgstr "" + +msgid "Cyclic" +msgstr "" + msgid "Slice gap closing radius" msgstr "Sluoksniavimo tarpo uždarymo spindulys" @@ -15387,6 +15435,45 @@ msgstr "Viršutinio apvalkalo storis" msgid "The number of top solid layers is increased when slicing if the thickness calculated by top shell layers is thinner than this value. This can avoid having too thin a shell when layer height is small. 0 means that this setting is disabled and thickness of top shell is determined simply by the number of top shell layers." msgstr "" +msgid "Anisotropic surfaces" +msgstr "" + +msgid "" +"Anisotropic patterns on the top and bottom surfaces.\n" +"Co-directional printing mode will be applied. For certain patterns, omni-directional filling provides color dispersion when using multi-colored or silk plastics.\n" +"This option disable the gap fill.\n" +"This option can increase a printing time." +msgstr "" + +msgid "Separated infills" +msgstr "" + +msgid "" +"Centers the internal infill of each part on itself, as if it were sliced on its own, instead of on the whole assembly. Parts that touch or overlap are treated as one body and share a center; separate parts (or distinct 3D objects) each get their own.\n" +"Useful when an assembly groups several objects that should each keep a consistent, self-centered infill.\n" +"Affects line and grid patterns and rotation-template infills.\n" +"Patterns locked to global coordinates (Gyroid, Honeycomb, TPMS, ...) are unaffected." +msgstr "" + +msgid "Center surface pattern on" +msgstr "" + +msgid "" +"Chooses where the centering point of centered top/bottom surface patterns (Archimedean Chords, Octagram Spiral) is placed.\n" +" - Each Surface: centers the pattern on every individual surface region, so each island is symmetric on its own.\n" +" - Each Model: centers the pattern on each connected body. Parts that touch or overlap share one center; parts detached from the rest each get their own.\n" +" - Each Assembly: uses a single shared center for the whole object or assembly." +msgstr "" + +msgid "Each Surface" +msgstr "" + +msgid "Each Model" +msgstr "" + +msgid "Each Assembly" +msgstr "" + msgid "This is the speed at which traveling is done." msgstr "" @@ -19345,6 +19432,68 @@ msgstr "" "Venkite deformacijų (warping)\n" "Ar žinojote, kad spausdinant medžiagas, kurios yra linkusios trauktis ir riestis (pvz., ABS), tinkamas kaitinamojo pagrindo temperatūros padidinimas gali sumažinti deformacijų (warping) tikimybę?" +#~ msgid "Continue to sync filaments" +#~ msgstr "Tęsti gijų sinchronizavimą" + +#~ msgctxt "Sync_Nozzle_AMS" +#~ msgid "Cancel" +#~ msgstr "Atšaukti" + +#, no-c-format, no-boost-format +#~ msgid "" +#~ "External Bridging angle override.\n" +#~ "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" +#~ "Otherwise the provided angle will be used according to:\n" +#~ " - The absolute coordinates\n" +#~ " - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +#~ " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" +#~ "\n" +#~ "Use 180° for zero absolute angle." +#~ msgstr "" +#~ "Išorinių tiltelių kampo perrašymas.\n" +#~ "Palikus 0, tiltelio kampas bus apskaičiuojamas automatiškai kiekvienam konkrečiam tilteliui.\n" +#~ "Kitu atveju nurodytas kampas bus naudojamas pagal:\n" +#~ " - absoliučiąsias koordinates;\n" +#~ " - absoliučiąsias koordinates + modelio pasukimą: jei įjungta „Sulygiuoti užpildo kryptį su modeliu“;\n" +#~ " - optimalų automatinį kampą + šią reikšmę: jei įjungta „Santykinis tiltelio kampas“.\n" +#~ "\n" +#~ "Naudokite 180° nulinėms absoliučiosioms koordinatėms." + +#~ msgid "" +#~ "Internal Bridging angle override.\n" +#~ "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" +#~ "Otherwise the provided angle will be used according to:\n" +#~ " - The absolute coordinates\n" +#~ " - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +#~ " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" +#~ "\n" +#~ "Use 180° for zero absolute angle." +#~ msgstr "" +#~ "Vidinių tiltelių kampo perrašymas.\n" +#~ "Palikus 0, tiltelio kampas bus apskaičiuojamas automatiškai kiekvienam konkrečiam tilteliui.\n" +#~ "Kitu atveju nurodytas kampas bus naudojamas pagal:\n" +#~ " - absoliučiąsias koordinates;\n" +#~ " - absoliučiąsias koordinates + modelio pasukimą: jei įjungta „Sulygiuoti užpildo kryptį su modeliu“;\n" +#~ " - optimalų automatinį kampą + šią reikšmę: jei įjungta „Santykinis tiltelio kampas“.\n" +#~ "\n" +#~ "Naudokite 180° nulinėms absoliučiosioms koordinatėms." + +#~ msgid "Align infill direction to model" +#~ msgstr "Suderinti užpildo kryptį su modeliu" + +#~ msgid "" +#~ "Aligns infill, bridge, ironing and surface fill directions to follow the model's orientation on the build plate.\n" +#~ "When enabled, directions rotate with the model to maintain optimal strength characteristics." +#~ msgstr "" +#~ "Sulygiuoja užpildo, tiltelių, lyginimo ir paviršiaus užpildymo kryptis pagal modelio orientaciją ant pagrindo.\n" +#~ "Kai įjungta, kryptys sukasi kartu su modeliu, kad būtų išlaikytos optimalios tvirtumo charakteristikos." + +#~ msgid "Print" +#~ msgstr "Spausdinti" + +#~ msgid "in" +#~ msgstr "col." + #~ msgid "Perform" #~ msgstr "Atlikti" diff --git a/localization/i18n/nl/OrcaSlicer_nl.po b/localization/i18n/nl/OrcaSlicer_nl.po index 42c6c2cefe..852f877f5f 100644 --- a/localization/i18n/nl/OrcaSlicer_nl.po +++ b/localization/i18n/nl/OrcaSlicer_nl.po @@ -3,7 +3,7 @@ msgid "" msgstr "" "Project-Id-Version: Orca Slicer\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-07-06 12:57-0300\n" +"POT-Creation-Date: 2026-07-12 12:27-0300\n" "PO-Revision-Date: \n" "Last-Translator: \n" "Language-Team: \n" @@ -162,6 +162,12 @@ msgstr "Vullen" msgid "Gap Fill" msgstr "Gatvulling" +msgid "Vertical" +msgstr "Verticaal" + +msgid "Horizontal" +msgstr "Horizontaal" + #, boost-format msgid "Allows painting only on facets selected by: \"%1%\"" msgstr "Staat alleen schilderen toe op facetten geselecteerd met: \"%1%\"" @@ -257,12 +263,6 @@ msgstr "Driehoek" msgid "Height Range" msgstr "Hoogtebereik" -msgid "Vertical" -msgstr "Verticaal" - -msgid "Horizontal" -msgstr "Horizontaal" - msgid "Remove painted color" msgstr "Geschilderd kleur verwijderen" @@ -327,6 +327,7 @@ msgstr "Roteren" msgid "Optimize orientation" msgstr "Oriëntatie optimaliseren" +msgctxt "Verb" msgid "Scale" msgstr "Schalen" @@ -336,8 +337,9 @@ msgstr "Verschalen" msgid "Error: Please close all toolbar menus first" msgstr "Fout: sluit eerst alle openstaande hulpmiddelmenu's" +msgctxt "inches" msgid "in" -msgstr "in" +msgstr "" msgid "mm" msgstr "mm" @@ -370,6 +372,9 @@ msgstr "Schaalverhoudingen" msgid "Object operations" msgstr "Objectbewerkingen" +msgid "Scale" +msgstr "Schalen" + # TODO: Review, changed by lang refactor. PR 14254 msgid "Volume operations" msgstr "Volumebewerkingen" @@ -421,6 +426,10 @@ msgstr "" msgid "Reset current rotation to real zeros." msgstr "" +msgctxt "Noun" +msgid "Scale" +msgstr "Schalen" + #. TRN - Input label. Be short as possible msgid "Size" msgstr "Maat" @@ -3610,7 +3619,7 @@ msgstr "Kalibratie voltooid. Zoek de meest uniforme extrusielijn op uw hotbed, z msgid "Save" msgstr "Bewaar" -# TODO: Review, changed by lang refactor. PR 14254 +msgctxt "Navigation" msgid "Back" msgstr "Achterzijde" @@ -4970,6 +4979,7 @@ msgstr "Toolwisselingen" msgid "Color change" msgstr "Kleur veranderen" +msgctxt "Noun" msgid "Print" msgstr "" @@ -5128,11 +5138,15 @@ msgstr "Vermijd het extrusie kalibratie gebied" msgid "Align to Y axis" msgstr "Uitlijnen op Y-as" -msgctxt "Camera" +msgctxt "Camera View" +msgid "Back" +msgstr "Achterzijde" + +msgctxt "Camera View" msgid "Left" msgstr "Links" -msgctxt "Camera" +msgctxt "Camera View" msgid "Right" msgstr "Rechts" @@ -5456,6 +5470,10 @@ msgstr "Printplaat" msgid "Export G-code file" msgstr "G-codebestand exporteren" +msgctxt "Verb" +msgid "Print" +msgstr "" + msgid "Export plate sliced file" msgstr "Exporteer plate sliced bestand" @@ -5629,15 +5647,6 @@ msgstr "Huidige configuratie exporteren naar bestanden" msgid "Export" msgstr "Exporteren" -msgid "Sync Presets" -msgstr "" - -msgid "Pull and apply the latest presets from OrcaCloud" -msgstr "" - -msgid "You must be logged in to sync presets from cloud." -msgstr "" - msgid "Quit" msgstr "Stop" @@ -5754,6 +5763,15 @@ msgstr "Weergave" msgid "Preset Bundle" msgstr "" +msgid "Sync Presets" +msgstr "" + +msgid "Pull and apply the latest presets from OrcaCloud" +msgstr "" + +msgid "You must be logged in to sync presets from cloud." +msgstr "" + msgid "Syncing presets from cloud…" msgstr "" @@ -10184,13 +10202,9 @@ msgstr "" msgid "Successfully synchronized nozzle and AMS number information." msgstr "" -msgid "Continue to sync filaments" +msgid "Do you want to continue to sync filaments?" msgstr "" -msgctxt "Sync_Nozzle_AMS" -msgid "Cancel" -msgstr "Annuleren" - msgid "Successfully synchronized filament color from printer." msgstr "" @@ -11487,7 +11501,7 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." @@ -11501,7 +11515,7 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." @@ -12145,6 +12159,42 @@ msgstr "" msgid "Density of top surface layer. A value of 100% creates a fully solid, smooth top layer. Reducing this value results in a textured top surface, according to the chosen top surface pattern. A value of 0% will result in only the walls on the top layer being created. Intended for aesthetic or functional purposes, not to fix issues such as over-extrusion." msgstr "" +msgid "Top surface expansion" +msgstr "" + +msgid "" +"Expands the top surfaces by this distance to connect distinct top surfaces and fill gaps.\n" +"Useful for cases where the top surface is interrupted by a raised feature, such as text on a plane.Expanding it removes the holes beneath these features and creates a continuous path with a better finish for printing on top.The expansion is applied to the original top surface, before any other processing such as bridging or overhang detection." +msgstr "" + +msgid "Top expansion wall margin" +msgstr "" + +msgid "" +"Using “Top surface expansion” may cause a surface that did not previously touch the model's outer walls to now do so.\n" +"This can cause contraction marks (such as the hull line) on the outer walls.\n" +"By adding a small margin, this contraction will not occur directly on the walls, thereby preventing a visible mark." +msgstr "" + +msgid "Top expansion direction" +msgstr "" + +msgid "" +"Direction in which the top surface expansion grows.\n" +" - Inward grows into the holes and gaps left by features rising from the middle of a top surface.\n" +" - Outward grows the outer edge of the surface, connecting surfaces separated by features that can divide a surface, such as a lattice pattern.\n" +" - Inward and Outward does both." +msgstr "" + +msgid "Inward and Outward" +msgstr "" + +msgid "Inward" +msgstr "" + +msgid "Outward" +msgstr "" + msgid "Bottom surface pattern" msgstr "Bodem oppvlakte patroon" @@ -12761,12 +12811,12 @@ msgstr "Vulling percentage" msgid "Density of internal sparse infill, 100% turns all sparse infill into solid infill and internal solid infill pattern will be used." msgstr "" -msgid "Align infill direction to model" +msgid "Align directions to model" msgstr "" msgid "" -"Aligns infill, bridge, ironing and surface fill directions to follow the model's orientation on the build plate.\n" -"When enabled, directions rotate with the model to maintain optimal strength characteristics." +"Aligns infill, bridge, ironing, and top/bottom surface directions to follow the model's orientation on the build plate.\n" +"When enabled, these directions rotate together with the model so the printed features keep their intended orientation relative to the part, preserving optimal strength and surface characteristics regardless of how the model is placed." msgstr "" msgid "Insert solid layers" @@ -14426,6 +14476,10 @@ msgstr "Uitgelijnd" msgid "Aligned back" msgstr "" +# TODO: Review, changed by lang refactor. PR 14254 +msgid "Back" +msgstr "Achterzijde" + msgid "Random" msgstr "Willekeurig" @@ -14769,6 +14823,18 @@ msgstr "Veeg alle printextruders af" msgid "If enabled, all printing extruders will be primed at the front edge of the print bed at the start of the print." msgstr "Alle extruders worden afgeveegd aan de voorzijde van het printbed aan het begin van de print als dit is ingeschakeld." +msgid "Toolchange ordering" +msgstr "" + +msgid "" +"Determines the order of tool changes on each layer.\n" +"- Default: Starts with the last used extruder to minimize tool changes.\n" +"- Cyclic: Uses a fixed tool sequence each layer. This sacrifices speed for better surface quality, as the extra toolchanges allow layers more time to cool." +msgstr "" + +msgid "Cyclic" +msgstr "" + msgid "Slice gap closing radius" msgstr "Sluitingsradius van de gap" @@ -15198,6 +15264,45 @@ msgstr "Dikte bovenkant" msgid "The number of top solid layers is increased when slicing if the thickness calculated by top shell layers is thinner than this value. This can avoid having too thin a shell when layer height is small. 0 means that this setting is disabled and thickness of top shell is determined simply by the number of top shell layers." msgstr "Het aantal bovenste solide lagen wordt verhoogd tijdens het slicen als de totale dikte van de bovenste lagen lager is dan deze waarde. Dit zorgt ervoor dat de schaal niet te dun is bij een lage laaghoogte. 0 betekend dat deze instelling niet actief is en dat de dikte van de bovenkant bepaald wordt door het aantal bodem lagen." +msgid "Anisotropic surfaces" +msgstr "" + +msgid "" +"Anisotropic patterns on the top and bottom surfaces.\n" +"Co-directional printing mode will be applied. For certain patterns, omni-directional filling provides color dispersion when using multi-colored or silk plastics.\n" +"This option disable the gap fill.\n" +"This option can increase a printing time." +msgstr "" + +msgid "Separated infills" +msgstr "" + +msgid "" +"Centers the internal infill of each part on itself, as if it were sliced on its own, instead of on the whole assembly. Parts that touch or overlap are treated as one body and share a center; separate parts (or distinct 3D objects) each get their own.\n" +"Useful when an assembly groups several objects that should each keep a consistent, self-centered infill.\n" +"Affects line and grid patterns and rotation-template infills.\n" +"Patterns locked to global coordinates (Gyroid, Honeycomb, TPMS, ...) are unaffected." +msgstr "" + +msgid "Center surface pattern on" +msgstr "" + +msgid "" +"Chooses where the centering point of centered top/bottom surface patterns (Archimedean Chords, Octagram Spiral) is placed.\n" +" - Each Surface: centers the pattern on every individual surface region, so each island is symmetric on its own.\n" +" - Each Model: centers the pattern on each connected body. Parts that touch or overlap share one center; parts detached from the rest each get their own.\n" +" - Each Assembly: uses a single shared center for the whole object or assembly." +msgstr "" + +msgid "Each Surface" +msgstr "" + +msgid "Each Model" +msgstr "" + +msgid "Each Assembly" +msgstr "" + # TODO: Review, changed by lang refactor. PR 14254 msgid "This is the speed at which traveling is done." msgstr "Dit is de snelheid waarmee verplaatsingen zullen worden gedaan." @@ -19114,6 +19219,13 @@ msgstr "" "Kromtrekken voorkomen\n" "Wist je dat bij het printen van materialen die gevoelig zijn voor kromtrekken, zoals ABS, een juiste verhoging van de temperatuur van het warmtebed de kans op kromtrekken kan verkleinen?" +#~ msgctxt "Sync_Nozzle_AMS" +#~ msgid "Cancel" +#~ msgstr "Annuleren" + +#~ msgid "in" +#~ msgstr "in" + #~ msgid "Object coordinates" #~ msgstr "Objectcoördinaten" @@ -20317,10 +20429,6 @@ msgstr "" #~ msgid "Thick bridges" #~ msgstr "Dikke bruggen" -#~ msgctxt "Verb" -#~ msgid "Scale" -#~ msgstr "Schalen" - #~ msgid "Z-hop when retract" #~ msgstr "Z-hop tijdens terugtrekken (retraction)" diff --git a/localization/i18n/pl/OrcaSlicer_pl.po b/localization/i18n/pl/OrcaSlicer_pl.po index 1c8d2c9a48..bfc8834795 100644 --- a/localization/i18n/pl/OrcaSlicer_pl.po +++ b/localization/i18n/pl/OrcaSlicer_pl.po @@ -3,7 +3,7 @@ msgid "" msgstr "" "Project-Id-Version: OrcaSlicer 2.3.0-rc\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-07-06 12:57-0300\n" +"POT-Creation-Date: 2026-07-12 12:27-0300\n" "PO-Revision-Date: \n" "Last-Translator: Krzysztof Morga <>\n" "Language-Team: \n" @@ -163,6 +163,13 @@ msgstr "Wypełnienie" msgid "Gap Fill" msgstr "Wypełnienie szczelin" +# +++++++++++++++++++++ +msgid "Vertical" +msgstr "Pionowa linia" + +msgid "Horizontal" +msgstr "Pozioma linia" + #, boost-format msgid "Allows painting only on facets selected by: \"%1%\"" msgstr "Pozwala malować tylko na wybranych powierzchniach za pomocą: „%1%”" @@ -258,13 +265,6 @@ msgstr "Trójkąt" msgid "Height Range" msgstr "Przedział" -# +++++++++++++++++++++ -msgid "Vertical" -msgstr "Pionowa linia" - -msgid "Horizontal" -msgstr "Pozioma linia" - msgid "Remove painted color" msgstr "Usuń pomalowany kolor" @@ -329,6 +329,7 @@ msgstr "Uchwyt-Obróć" msgid "Optimize orientation" msgstr "Optymalizuj orientację" +msgctxt "Verb" msgid "Scale" msgstr "Skaluj" @@ -338,8 +339,9 @@ msgstr "Uchwyt-Skaluj" msgid "Error: Please close all toolbar menus first" msgstr "Błąd: Proszę najpierw zamknąć wszystkie paski narzędziowe" +msgctxt "inches" msgid "in" -msgstr "cal" +msgstr "" msgid "mm" msgstr "mm" @@ -372,6 +374,9 @@ msgstr "Współczynniki skali" msgid "Object operations" msgstr "Operacje na obiekcie" +msgid "Scale" +msgstr "Skaluj" + # TODO: Review, changed by lang refactor. PR 14254 msgid "Volume operations" msgstr "Operacje na objętości" @@ -423,6 +428,10 @@ msgstr "Zresetuj bieżący obrót do wartości ustawionej przy otwarciu narzędz msgid "Reset current rotation to real zeros." msgstr "Zresetuj bieżący obrót do wartości zerowej." +msgctxt "Noun" +msgid "Scale" +msgstr "Skaluj" + #. TRN - Input label. Be short as possible msgid "Size" msgstr "Rozmiar" @@ -3648,7 +3657,7 @@ msgstr "Kalibracja zakończona. Proszę znaleźć na płycie roboczej, linie eks msgid "Save" msgstr "Zapisz" -# TODO: Review, changed by lang refactor. PR 14254 +msgctxt "Navigation" msgid "Back" msgstr "Tył" @@ -5022,6 +5031,7 @@ msgstr "Zmiany narzędzi" msgid "Color change" msgstr "Zmiana koloru" +msgctxt "Noun" msgid "Print" msgstr "Drukuj" @@ -5185,11 +5195,15 @@ msgstr "Unikaj obszaru kalibracji ekstruzji" msgid "Align to Y axis" msgstr "Wyrównaj do osi Y" -msgctxt "Camera" +msgctxt "Camera View" +msgid "Back" +msgstr "Tył" + +msgctxt "Camera View" msgid "Left" msgstr "Lewy" -msgctxt "Camera" +msgctxt "Camera View" msgid "Right" msgstr "Prawy" @@ -5517,6 +5531,10 @@ msgstr "Drukuj aktualną płytę" msgid "Export G-code file" msgstr "Eksportuj plik G-code" +msgctxt "Verb" +msgid "Print" +msgstr "Drukuj" + msgid "Export plate sliced file" msgstr "Eksportuj plik pociętej płyty" @@ -5690,15 +5708,6 @@ msgstr "Eksportuj bieżącą konfigurację do plików" msgid "Export" msgstr "Eksportuj" -msgid "Sync Presets" -msgstr "" - -msgid "Pull and apply the latest presets from OrcaCloud" -msgstr "" - -msgid "You must be logged in to sync presets from cloud." -msgstr "" - msgid "Quit" msgstr "Zakończ" @@ -5815,6 +5824,15 @@ msgstr "Widok" msgid "Preset Bundle" msgstr "" +msgid "Sync Presets" +msgstr "" + +msgid "Pull and apply the latest presets from OrcaCloud" +msgstr "" + +msgid "You must be logged in to sync presets from cloud." +msgstr "" + msgid "Syncing presets from cloud…" msgstr "" @@ -10307,12 +10325,8 @@ msgstr "Pomyślnie zsynchronizowano informacje o dyszy." msgid "Successfully synchronized nozzle and AMS number information." msgstr "Pomyślnie zsynchronizowano dyszę z informacjami numeru AMS." -msgid "Continue to sync filaments" -msgstr "Kontynuuj aby zsynchronizować filamenty" - -msgctxt "Sync_Nozzle_AMS" -msgid "Cancel" -msgstr "Anuluj" +msgid "Do you want to continue to sync filaments?" +msgstr "" msgid "Successfully synchronized filament color from printer." msgstr "" @@ -11632,7 +11646,7 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." @@ -11646,7 +11660,7 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." @@ -12355,6 +12369,42 @@ msgstr "Gęstość górnej powierzchni" msgid "Density of top surface layer. A value of 100% creates a fully solid, smooth top layer. Reducing this value results in a textured top surface, according to the chosen top surface pattern. A value of 0% will result in only the walls on the top layer being created. Intended for aesthetic or functional purposes, not to fix issues such as over-extrusion." msgstr "" +msgid "Top surface expansion" +msgstr "" + +msgid "" +"Expands the top surfaces by this distance to connect distinct top surfaces and fill gaps.\n" +"Useful for cases where the top surface is interrupted by a raised feature, such as text on a plane.Expanding it removes the holes beneath these features and creates a continuous path with a better finish for printing on top.The expansion is applied to the original top surface, before any other processing such as bridging or overhang detection." +msgstr "" + +msgid "Top expansion wall margin" +msgstr "" + +msgid "" +"Using “Top surface expansion” may cause a surface that did not previously touch the model's outer walls to now do so.\n" +"This can cause contraction marks (such as the hull line) on the outer walls.\n" +"By adding a small margin, this contraction will not occur directly on the walls, thereby preventing a visible mark." +msgstr "" + +msgid "Top expansion direction" +msgstr "" + +msgid "" +"Direction in which the top surface expansion grows.\n" +" - Inward grows into the holes and gaps left by features rising from the middle of a top surface.\n" +" - Outward grows the outer edge of the surface, connecting surfaces separated by features that can divide a surface, such as a lattice pattern.\n" +" - Inward and Outward does both." +msgstr "" + +msgid "Inward and Outward" +msgstr "" + +msgid "Inward" +msgstr "" + +msgid "Outward" +msgstr "" + msgid "Bottom surface pattern" msgstr "Wzór dolnej powierzchni" @@ -13005,12 +13055,12 @@ msgstr "Gęstość wypełnienia" msgid "Density of internal sparse infill, 100% turns all sparse infill into solid infill and internal solid infill pattern will be used." msgstr "Gęstość wewnętrznego rzadkiego wypełnienia, 100% przekształca całe rzadkie wypełnienie w wypełnienie pełne, a użyty zostanie wzór wewnętrznego pełnego wypełnienia" -msgid "Align infill direction to model" +msgid "Align directions to model" msgstr "" msgid "" -"Aligns infill, bridge, ironing and surface fill directions to follow the model's orientation on the build plate.\n" -"When enabled, directions rotate with the model to maintain optimal strength characteristics." +"Aligns infill, bridge, ironing, and top/bottom surface directions to follow the model's orientation on the build plate.\n" +"When enabled, these directions rotate together with the model so the printed features keep their intended orientation relative to the part, preserving optimal strength and surface characteristics regardless of how the model is placed." msgstr "" msgid "Insert solid layers" @@ -14737,6 +14787,10 @@ msgstr "Wyrównany" msgid "Aligned back" msgstr "" +# TODO: Review, changed by lang refactor. PR 14254 +msgid "Back" +msgstr "Tył" + msgid "Random" msgstr "Losowo" @@ -15099,6 +15153,18 @@ msgstr "Wyczyść wszystkie używane ekstrudery" msgid "If enabled, all printing extruders will be primed at the front edge of the print bed at the start of the print." msgstr "Jeśli włączone, wszystkie extrudery do drukowania będą przygotowane na przedniej krawędzi stołu drukującego na początku druku." +msgid "Toolchange ordering" +msgstr "" + +msgid "" +"Determines the order of tool changes on each layer.\n" +"- Default: Starts with the last used extruder to minimize tool changes.\n" +"- Cyclic: Uses a fixed tool sequence each layer. This sacrifices speed for better surface quality, as the extra toolchanges allow layers more time to cool." +msgstr "" + +msgid "Cyclic" +msgstr "" + msgid "Slice gap closing radius" msgstr "Promień zamykania szpar" @@ -15537,6 +15603,45 @@ msgstr "Grubość górnej powłoki" msgid "The number of top solid layers is increased when slicing if the thickness calculated by top shell layers is thinner than this value. This can avoid having too thin a shell when layer height is small. 0 means that this setting is disabled and thickness of top shell is determined simply by the number of top shell layers." msgstr "Liczba górnych zwartych warstw jest zwiększana podczas cięcia, jeśli grubość obliczona przez górną warstwe powłoki jest cieńsza niż ta wartość. Można w ten sposób uniknąć zbyt cienkiej powłoki, gdy wysokość warstwy jest mała. 0 oznacza, że to ustawienie jest wyłączone, a grubość górnej powłoki jest absolutnie określona przez górne warstwy powłoki" +msgid "Anisotropic surfaces" +msgstr "" + +msgid "" +"Anisotropic patterns on the top and bottom surfaces.\n" +"Co-directional printing mode will be applied. For certain patterns, omni-directional filling provides color dispersion when using multi-colored or silk plastics.\n" +"This option disable the gap fill.\n" +"This option can increase a printing time." +msgstr "" + +msgid "Separated infills" +msgstr "" + +msgid "" +"Centers the internal infill of each part on itself, as if it were sliced on its own, instead of on the whole assembly. Parts that touch or overlap are treated as one body and share a center; separate parts (or distinct 3D objects) each get their own.\n" +"Useful when an assembly groups several objects that should each keep a consistent, self-centered infill.\n" +"Affects line and grid patterns and rotation-template infills.\n" +"Patterns locked to global coordinates (Gyroid, Honeycomb, TPMS, ...) are unaffected." +msgstr "" + +msgid "Center surface pattern on" +msgstr "" + +msgid "" +"Chooses where the centering point of centered top/bottom surface patterns (Archimedean Chords, Octagram Spiral) is placed.\n" +" - Each Surface: centers the pattern on every individual surface region, so each island is symmetric on its own.\n" +" - Each Model: centers the pattern on each connected body. Parts that touch or overlap share one center; parts detached from the rest each get their own.\n" +" - Each Assembly: uses a single shared center for the whole object or assembly." +msgstr "" + +msgid "Each Surface" +msgstr "" + +msgid "Each Model" +msgstr "" + +msgid "Each Assembly" +msgstr "" + # TODO: Review, changed by lang refactor. PR 14254 msgid "This is the speed at which traveling is done." msgstr "Prędkość przemieszczania, która jest szybsza i bez ekstruzji" @@ -19541,6 +19646,19 @@ msgstr "" "Unikaj odkształceń\n" "Czy wiesz, że podczas drukowania filamentami podatnymi na odkształcenia, takimi jak ABS, odpowiednie zwiększenie temperatury podgrzewanej płyty może zmniejszyć prawdopodobieństwo odkształceń?" +#~ msgid "Continue to sync filaments" +#~ msgstr "Kontynuuj aby zsynchronizować filamenty" + +#~ msgctxt "Sync_Nozzle_AMS" +#~ msgid "Cancel" +#~ msgstr "Anuluj" + +#~ msgid "Print" +#~ msgstr "Drukuj" + +#~ msgid "in" +#~ msgstr "cal" + #~ msgid "Object coordinates" #~ msgstr "Koordynaty obiektu" @@ -20996,10 +21114,6 @@ msgstr "" #~ msgid "Unselect" #~ msgstr "Odznacz" -#~ msgctxt "Verb" -#~ msgid "Scale" -#~ msgstr "Skala" - #~ msgid "Lift Z Enforcement" #~ msgstr "Wymuszenie podniesienia osi Z" diff --git a/localization/i18n/pt_BR/OrcaSlicer_pt_BR.po b/localization/i18n/pt_BR/OrcaSlicer_pt_BR.po index 3303ebe36e..6bbb8ad5a6 100644 --- a/localization/i18n/pt_BR/OrcaSlicer_pt_BR.po +++ b/localization/i18n/pt_BR/OrcaSlicer_pt_BR.po @@ -3,7 +3,7 @@ msgid "" msgstr "" "Project-Id-Version: Orca Slicer\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-07-06 12:57-0300\n" +"POT-Creation-Date: 2026-07-12 12:27-0300\n" "PO-Revision-Date: 2026-07-04 11:51-0300\n" "Last-Translator: Alexandre Folle de Menezes\n" "Language-Team: Portuguese, Brazilian\n" @@ -164,6 +164,12 @@ msgstr "Preencher" msgid "Gap Fill" msgstr "Preencher vão" +msgid "Vertical" +msgstr "Vertical" + +msgid "Horizontal" +msgstr "Horizontal" + #, boost-format msgid "Allows painting only on facets selected by: \"%1%\"" msgstr "Permite pintura apenas em facetas selecionadas por: \"%1%\"" @@ -256,12 +262,6 @@ msgstr "Triângulo" msgid "Height Range" msgstr "Intervalo de Altura" -msgid "Vertical" -msgstr "Vertical" - -msgid "Horizontal" -msgstr "Horizontal" - msgid "Remove painted color" msgstr "Remover cor pintada" @@ -326,6 +326,7 @@ msgstr "Gizmo-Rotacionar" msgid "Optimize orientation" msgstr "Otimizar orientação" +msgctxt "Verb" msgid "Scale" msgstr "Escala" @@ -335,8 +336,9 @@ msgstr "Gizmo-Dimensionar" msgid "Error: Please close all toolbar menus first" msgstr "Erro: Por favor, feche todos os menus da barra de ferramentas primeiro" +msgctxt "inches" msgid "in" -msgstr "pol" +msgstr "" msgid "mm" msgstr "mm" @@ -368,6 +370,9 @@ msgstr "Proporções de escala" msgid "Object operations" msgstr "Operações de objeto" +msgid "Scale" +msgstr "Escala" + msgid "Volume operations" msgstr "Operações de volume" @@ -413,6 +418,10 @@ msgstr "Redefinir rotação para o valor de abertura da ferramenta de rotação. msgid "Reset current rotation to real zeros." msgstr "Redefinir rotação atual para zeros reais." +msgctxt "Noun" +msgid "Scale" +msgstr "Escala" + #. TRN - Input label. Be short as possible msgid "Size" msgstr "Tamanho" @@ -3579,6 +3588,7 @@ msgstr "Calibração concluída. Por favor, encontre a linha de extrusão mais u msgid "Save" msgstr "Salvar" +msgctxt "Navigation" msgid "Back" msgstr "Atrás" @@ -4939,6 +4949,7 @@ msgstr "Trocas de ferramenta" msgid "Color change" msgstr "Mudança de cor" +msgctxt "Noun" msgid "Print" msgstr "Imprimir" @@ -5101,11 +5112,15 @@ msgstr "Evitar a região de calibração da extrusão" msgid "Align to Y axis" msgstr "Alinhar com o eixo Y" -msgctxt "Camera" +msgctxt "Camera View" +msgid "Back" +msgstr "Atrás" + +msgctxt "Camera View" msgid "Left" msgstr "Esquerda" -msgctxt "Camera" +msgctxt "Camera View" msgid "Right" msgstr "Direita" @@ -5432,6 +5447,10 @@ msgstr "Imprimir placa" msgid "Export G-code file" msgstr "Exportar arquivo G-code" +msgctxt "Verb" +msgid "Print" +msgstr "Imprimir" + msgid "Export plate sliced file" msgstr "Exportar arquivo de placa fatiada" @@ -5605,15 +5624,6 @@ msgstr "Exportar configuração atual para arquivos" msgid "Export" msgstr "Exportar" -msgid "Sync Presets" -msgstr "Sincronizar Predefinições" - -msgid "Pull and apply the latest presets from OrcaCloud" -msgstr "Baixar e aplicar as predefinições mais recentes do OrcaCloud" - -msgid "You must be logged in to sync presets from cloud." -msgstr "Você precisa estar logado para sincronizar as predefinições da nuvem." - msgid "Quit" msgstr "Sair" @@ -5730,6 +5740,15 @@ msgstr "Visualizar" msgid "Preset Bundle" msgstr "Pacote de Predefinições" +msgid "Sync Presets" +msgstr "Sincronizar Predefinições" + +msgid "Pull and apply the latest presets from OrcaCloud" +msgstr "Baixar e aplicar as predefinições mais recentes do OrcaCloud" + +msgid "You must be logged in to sync presets from cloud." +msgstr "Você precisa estar logado para sincronizar as predefinições da nuvem." + msgid "Syncing presets from cloud…" msgstr "Sincronizando predefinições da nuvem…" @@ -10228,12 +10247,8 @@ msgstr "Informações do bico sincronizadas com sucesso." msgid "Successfully synchronized nozzle and AMS number information." msgstr "Informações do bico e do número de AMS sincronizadas com sucesso." -msgid "Continue to sync filaments" -msgstr "Continue a sincronizar os filamentos" - -msgctxt "Sync_Nozzle_AMS" -msgid "Cancel" -msgstr "Cancelar" +msgid "Do you want to continue to sync filaments?" +msgstr "" msgid "Successfully synchronized filament color from printer." msgstr "Cor de filamento da impressora sincronizado com sucesso." @@ -11539,7 +11554,7 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." @@ -11553,7 +11568,7 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." @@ -12285,6 +12300,42 @@ msgstr "Densidade da superfície superior" msgid "Density of top surface layer. A value of 100% creates a fully solid, smooth top layer. Reducing this value results in a textured top surface, according to the chosen top surface pattern. A value of 0% will result in only the walls on the top layer being created. Intended for aesthetic or functional purposes, not to fix issues such as over-extrusion." msgstr "Densidade da camada superior. Um valor de 100% cria uma camada superior totalmente sólida e lisa. Reduzir esse valor resulta em uma superfície superior texturizada, de acordo com o padrão de superfície superior escolhido. Um valor de 0% resultará na criação apenas das paredes da camada superior. Destinado a fins estéticos ou funcionais, não para corrigir problemas como extrusão excessiva." +msgid "Top surface expansion" +msgstr "" + +msgid "" +"Expands the top surfaces by this distance to connect distinct top surfaces and fill gaps.\n" +"Useful for cases where the top surface is interrupted by a raised feature, such as text on a plane.Expanding it removes the holes beneath these features and creates a continuous path with a better finish for printing on top.The expansion is applied to the original top surface, before any other processing such as bridging or overhang detection." +msgstr "" + +msgid "Top expansion wall margin" +msgstr "" + +msgid "" +"Using “Top surface expansion” may cause a surface that did not previously touch the model's outer walls to now do so.\n" +"This can cause contraction marks (such as the hull line) on the outer walls.\n" +"By adding a small margin, this contraction will not occur directly on the walls, thereby preventing a visible mark." +msgstr "" + +msgid "Top expansion direction" +msgstr "" + +msgid "" +"Direction in which the top surface expansion grows.\n" +" - Inward grows into the holes and gaps left by features rising from the middle of a top surface.\n" +" - Outward grows the outer edge of the surface, connecting surfaces separated by features that can divide a surface, such as a lattice pattern.\n" +" - Inward and Outward does both." +msgstr "" + +msgid "Inward and Outward" +msgstr "" + +msgid "Inward" +msgstr "" + +msgid "Outward" +msgstr "" + msgid "Bottom surface pattern" msgstr "Padrão de superfície inferior" @@ -12934,15 +12985,13 @@ msgstr "Densidade do preenchimento esparso" msgid "Density of internal sparse infill, 100% turns all sparse infill into solid infill and internal solid infill pattern will be used." msgstr "Densidade do preenchimento esparso interno, 100% transforma todo o preenchimento esparso em preenchimento sólido e será usado o padrão de preenchimento sólido interno." -msgid "Align infill direction to model" -msgstr "Alinhar direção do preenchimento ao modelo" +msgid "Align directions to model" +msgstr "" msgid "" -"Aligns infill, bridge, ironing and surface fill directions to follow the model's orientation on the build plate.\n" -"When enabled, directions rotate with the model to maintain optimal strength characteristics." +"Aligns infill, bridge, ironing, and top/bottom surface directions to follow the model's orientation on the build plate.\n" +"When enabled, these directions rotate together with the model so the printed features keep their intended orientation relative to the part, preserving optimal strength and surface characteristics regardless of how the model is placed." msgstr "" -"Alinha as direções do preenchimento, das pontes, do alisamento e do preenchimento de superfícies à orientação do modelo na mesa de impressão.\n" -"Quando ativado, as direções giram com o modelo para manter características ideais de resistência." msgid "Insert solid layers" msgstr "Inserir camadas sólidas" @@ -14719,6 +14768,9 @@ msgstr "Alinhada" msgid "Aligned back" msgstr "Alinhada atrás" +msgid "Back" +msgstr "Atrás" + msgid "Random" msgstr "Aleatória" @@ -15085,6 +15137,18 @@ msgstr "Preparar todas as extrusoras de impressão" msgid "If enabled, all printing extruders will be primed at the front edge of the print bed at the start of the print." msgstr "Se ativado, todos as extrusoras de impressão serão preparados na borda frontal da mesa de impressão no início da impressão." +msgid "Toolchange ordering" +msgstr "" + +msgid "" +"Determines the order of tool changes on each layer.\n" +"- Default: Starts with the last used extruder to minimize tool changes.\n" +"- Cyclic: Uses a fixed tool sequence each layer. This sacrifices speed for better surface quality, as the extra toolchanges allow layers more time to cool." +msgstr "" + +msgid "Cyclic" +msgstr "" + msgid "Slice gap closing radius" msgstr "Raio de fechamento de vãos de fatiamento" @@ -15512,6 +15576,45 @@ msgstr "Espessura da casca do topo" msgid "The number of top solid layers is increased when slicing if the thickness calculated by top shell layers is thinner than this value. This can avoid having too thin a shell when layer height is small. 0 means that this setting is disabled and thickness of top shell is determined simply by the number of top shell layers." msgstr "O número de camadas sólidas superiores é aumentado ao fatiar se a espessura calculada pelas camadas da casca do topo for menor do que este valor. Isso pode evitar que a casca seja muito fina quando a altura da camada é pequena. 0 significa que esta configuração está desativada e a espessura da casca do topo é determinada apenas pelo número de camadas da casca do topo." +msgid "Anisotropic surfaces" +msgstr "" + +msgid "" +"Anisotropic patterns on the top and bottom surfaces.\n" +"Co-directional printing mode will be applied. For certain patterns, omni-directional filling provides color dispersion when using multi-colored or silk plastics.\n" +"This option disable the gap fill.\n" +"This option can increase a printing time." +msgstr "" + +msgid "Separated infills" +msgstr "" + +msgid "" +"Centers the internal infill of each part on itself, as if it were sliced on its own, instead of on the whole assembly. Parts that touch or overlap are treated as one body and share a center; separate parts (or distinct 3D objects) each get their own.\n" +"Useful when an assembly groups several objects that should each keep a consistent, self-centered infill.\n" +"Affects line and grid patterns and rotation-template infills.\n" +"Patterns locked to global coordinates (Gyroid, Honeycomb, TPMS, ...) are unaffected." +msgstr "" + +msgid "Center surface pattern on" +msgstr "" + +msgid "" +"Chooses where the centering point of centered top/bottom surface patterns (Archimedean Chords, Octagram Spiral) is placed.\n" +" - Each Surface: centers the pattern on every individual surface region, so each island is symmetric on its own.\n" +" - Each Model: centers the pattern on each connected body. Parts that touch or overlap share one center; parts detached from the rest each get their own.\n" +" - Each Assembly: uses a single shared center for the whole object or assembly." +msgstr "" + +msgid "Each Surface" +msgstr "" + +msgid "Each Model" +msgstr "" + +msgid "Each Assembly" +msgstr "" + # TODO: Review, changed by lang refactor. PR 14254 msgid "This is the speed at which traveling is done." msgstr "Essa é a velocidade em que o deslocamento é feito." @@ -19488,6 +19591,29 @@ msgstr "" "Evitar empenamento\n" "Você sabia que ao imprimir materiais propensos ao empenamento como ABS, aumentar adequadamente a temperatura da mesa aquecida pode reduzir a probabilidade de empenamento?" +#~ msgid "Continue to sync filaments" +#~ msgstr "Continue a sincronizar os filamentos" + +#~ msgctxt "Sync_Nozzle_AMS" +#~ msgid "Cancel" +#~ msgstr "Cancelar" + +#~ msgid "Align infill direction to model" +#~ msgstr "Alinhar direção do preenchimento ao modelo" + +#~ msgid "" +#~ "Aligns infill, bridge, ironing and surface fill directions to follow the model's orientation on the build plate.\n" +#~ "When enabled, directions rotate with the model to maintain optimal strength characteristics." +#~ msgstr "" +#~ "Alinha as direções do preenchimento, das pontes, do alisamento e do preenchimento de superfícies à orientação do modelo na mesa de impressão.\n" +#~ "Quando ativado, as direções giram com o modelo para manter características ideais de resistência." + +#~ msgid "Print" +#~ msgstr "Imprimir" + +#~ msgid "in" +#~ msgstr "pol" + #~ msgid "Object coordinates" #~ msgstr "Coordenadas do objeto" diff --git a/localization/i18n/ru/OrcaSlicer_ru.po b/localization/i18n/ru/OrcaSlicer_ru.po index f60bd6a42d..8d6ce4607c 100644 --- a/localization/i18n/ru/OrcaSlicer_ru.po +++ b/localization/i18n/ru/OrcaSlicer_ru.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: OrcaSlicer V2.5.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-07-06 12:57-0300\n" +"POT-Creation-Date: 2026-07-12 12:27-0300\n" "PO-Revision-Date: 2026-02-25 13:38+0300\n" "Last-Translator: Felix14_v2\n" "Language-Team: Felix14_v2 (ДС/ТГ: @felix14_v2, почта: aleks111001@list.ru), Andylg \n" @@ -173,6 +173,12 @@ msgstr "Заливка" msgid "Gap Fill" msgstr "Заливка вкраплений" +msgid "Vertical" +msgstr "Вертикальная линия" + +msgid "Horizontal" +msgstr "Горизонтальная линия" + #, boost-format msgid "Allows painting only on facets selected by: \"%1%\"" msgstr "Ограничить область работы инструмента настройкой «%1%»" @@ -267,12 +273,6 @@ msgstr "Треугольник" msgid "Height Range" msgstr "Диапазон высот" -msgid "Vertical" -msgstr "Вертикальная линия" - -msgid "Horizontal" -msgstr "Горизонтальная линия" - msgid "Remove painted color" msgstr "Удаление окрашенного участка" @@ -337,6 +337,7 @@ msgstr "Инструмент вращения" msgid "Optimize orientation" msgstr "Оптимизация положения модели" +msgctxt "Verb" msgid "Scale" msgstr "Масштаб" @@ -346,8 +347,9 @@ msgstr "Инструмент изменения размера" msgid "Error: Please close all toolbar menus first" msgstr "Ошибка: сначала закройте текущий инструмент." +msgctxt "inches" msgid "in" -msgstr "дюйм" +msgstr "" msgid "mm" msgstr "мм" @@ -379,6 +381,9 @@ msgstr "Коэф. масштаба" msgid "Object operations" msgstr "Операции с моделями" +msgid "Scale" +msgstr "Масштаб" + msgid "Volume operations" msgstr "Булевы операции с телами" @@ -424,6 +429,10 @@ msgstr "Сбросить последние изменения ориентац msgid "Reset current rotation to real zeros." msgstr "Сбросить ориентацию до изначальной" +msgctxt "Noun" +msgid "Scale" +msgstr "Масштаб" + #. TRN - Input label. Be short as possible msgid "Size" msgstr "Размер" @@ -3656,9 +3665,9 @@ msgstr "Калибровка завершена. Теперь найдите н msgid "Save" msgstr "Сохранить" -# Используется в нескольких местах: в 2 местах в значении расположения (шва и камеры), в одном – на кнопке "назад" (калибровка бамбу) +msgctxt "Navigation" msgid "Back" -msgstr "Сзади" +msgstr "Назад" msgid "Example" msgstr "Пример" @@ -5064,6 +5073,7 @@ msgstr "Смена инструмента" msgid "Color change" msgstr "Смена цвета" +msgctxt "Noun" msgid "Print" msgstr "Печать" @@ -5226,11 +5236,15 @@ msgstr "Избегать зону калибровки экструзии" msgid "Align to Y axis" msgstr "Выравнивать по оси Y" -msgctxt "Camera" +msgctxt "Camera View" +msgid "Back" +msgstr "Сзади" + +msgctxt "Camera View" msgid "Left" msgstr "Слева" -msgctxt "Camera" +msgctxt "Camera View" msgid "Right" msgstr "Справа" @@ -5588,6 +5602,10 @@ msgstr "Распечатать стол" msgid "Export G-code file" msgstr "Экспорт в G-код" +msgctxt "Verb" +msgid "Print" +msgstr "Печать" + msgid "Export plate sliced file" msgstr "Экспорт стола в файл проекта" @@ -5763,15 +5781,6 @@ msgstr "Экспортировать текущую конфигурацию в msgid "Export" msgstr "Экспорт" -msgid "Sync Presets" -msgstr "" - -msgid "Pull and apply the latest presets from OrcaCloud" -msgstr "" - -msgid "You must be logged in to sync presets from cloud." -msgstr "" - msgid "Quit" msgstr "Выход" @@ -5886,6 +5895,15 @@ msgstr "Вид" msgid "Preset Bundle" msgstr "" +msgid "Sync Presets" +msgstr "" + +msgid "Pull and apply the latest presets from OrcaCloud" +msgstr "" + +msgid "You must be logged in to sync presets from cloud." +msgstr "" + msgid "Syncing presets from cloud…" msgstr "" @@ -10424,12 +10442,8 @@ msgstr "Информация о сопле успешно синхронизир msgid "Successfully synchronized nozzle and AMS number information." msgstr "Информация о сопле и количестве AMS успешно синхронизирована." -msgid "Continue to sync filaments" -msgstr "Продолжить синхронизацию филаментов" - -msgctxt "Sync_Nozzle_AMS" -msgid "Cancel" -msgstr "Отмена" +msgid "Do you want to continue to sync filaments?" +msgstr "" msgid "Successfully synchronized filament color from printer." msgstr "Цвет материала успешно синхронизирован с принтером." @@ -11718,7 +11732,7 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." @@ -11732,7 +11746,7 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." @@ -12489,6 +12503,42 @@ msgstr "Плотность верхней поверхности" msgid "Density of top surface layer. A value of 100% creates a fully solid, smooth top layer. Reducing this value results in a textured top surface, according to the chosen top surface pattern. A value of 0% will result in only the walls on the top layer being created. Intended for aesthetic or functional purposes, not to fix issues such as over-extrusion." msgstr "Плотность верхней поверхности. Если установить 100%, поверхность будет сплошной и гладкой. Уменьшение этого параметра создаст текстурированную поверхность в соответствии с выбранным шаблоном заполнения верхней поверхности. При значении 0% останутся только стенки верхнего слоя. Эта функция предназначена для улучшения внешнего вида или функциональности объекта, но не для решения проблем, таких как чрезмерная экструзия." +msgid "Top surface expansion" +msgstr "" + +msgid "" +"Expands the top surfaces by this distance to connect distinct top surfaces and fill gaps.\n" +"Useful for cases where the top surface is interrupted by a raised feature, such as text on a plane.Expanding it removes the holes beneath these features and creates a continuous path with a better finish for printing on top.The expansion is applied to the original top surface, before any other processing such as bridging or overhang detection." +msgstr "" + +msgid "Top expansion wall margin" +msgstr "" + +msgid "" +"Using “Top surface expansion” may cause a surface that did not previously touch the model's outer walls to now do so.\n" +"This can cause contraction marks (such as the hull line) on the outer walls.\n" +"By adding a small margin, this contraction will not occur directly on the walls, thereby preventing a visible mark." +msgstr "" + +msgid "Top expansion direction" +msgstr "" + +msgid "" +"Direction in which the top surface expansion grows.\n" +" - Inward grows into the holes and gaps left by features rising from the middle of a top surface.\n" +" - Outward grows the outer edge of the surface, connecting surfaces separated by features that can divide a surface, such as a lattice pattern.\n" +" - Inward and Outward does both." +msgstr "" + +msgid "Inward and Outward" +msgstr "" + +msgid "Inward" +msgstr "" + +msgid "Outward" +msgstr "" + msgid "Bottom surface pattern" msgstr "Шаблон заполнения нижней поверхности" @@ -13211,12 +13261,12 @@ msgstr "Плотность заполнения" msgid "Density of internal sparse infill, 100% turns all sparse infill into solid infill and internal solid infill pattern will be used." msgstr "Плотность внутреннего заполнения, выраженная в процентах. 100% означает сплошное заполнение." -msgid "Align infill direction to model" -msgstr "Вращать заполнение с моделью" +msgid "Align directions to model" +msgstr "" msgid "" -"Aligns infill, bridge, ironing and surface fill directions to follow the model's orientation on the build plate.\n" -"When enabled, directions rotate with the model to maintain optimal strength characteristics." +"Aligns infill, bridge, ironing, and top/bottom surface directions to follow the model's orientation on the build plate.\n" +"When enabled, these directions rotate together with the model so the printed features keep their intended orientation relative to the part, preserving optimal strength and surface characteristics regardless of how the model is placed." msgstr "" msgid "Insert solid layers" @@ -15085,6 +15135,10 @@ msgstr "В углах" msgid "Aligned back" msgstr "В углах сзади" +# Используется в нескольких местах: в 2 местах в значении расположения (шва и камеры), в одном – на кнопке "назад" (калибровка бамбу) +msgid "Back" +msgstr "Сзади" + msgid "Random" msgstr "Случайная" @@ -15486,6 +15540,18 @@ msgstr "Подготовка всех печатающих экструдеро msgid "If enabled, all printing extruders will be primed at the front edge of the print bed at the start of the print." msgstr "Если этот параметр включён, все печатающие экструдеры в начале печати будут подготавливаться на переднем крае стола." +msgid "Toolchange ordering" +msgstr "" + +msgid "" +"Determines the order of tool changes on each layer.\n" +"- Default: Starts with the last used extruder to minimize tool changes.\n" +"- Cyclic: Uses a fixed tool sequence each layer. This sacrifices speed for better surface quality, as the extra toolchanges allow layers more time to cool." +msgstr "" + +msgid "Cyclic" +msgstr "" + msgid "Slice gap closing radius" msgstr "Радиус закрытия зазоров полигональной сетки" @@ -15969,6 +16035,45 @@ msgstr "Толщина оболочки сверху" msgid "The number of top solid layers is increased when slicing if the thickness calculated by top shell layers is thinner than this value. This can avoid having too thin a shell when layer height is small. 0 means that this setting is disabled and thickness of top shell is determined simply by the number of top shell layers." msgstr "Минимальная толщина оболочки сверху в мм. Если толщина оболочки, рассчитанная по количеству сплошных слоёв сверху, меньше этого значения, количество сплошных слоёв сверху будет автоматически увеличено при нарезке, для удовлетворения минимальной толщины оболочки. Это позволяет избежать слишком тонкой оболочки при небольшой высоте слоя. 0 означает, что этот параметр отключён, а толщина оболочки сверху задаётся количеством сплошных слоёв сверху." +msgid "Anisotropic surfaces" +msgstr "" + +msgid "" +"Anisotropic patterns on the top and bottom surfaces.\n" +"Co-directional printing mode will be applied. For certain patterns, omni-directional filling provides color dispersion when using multi-colored or silk plastics.\n" +"This option disable the gap fill.\n" +"This option can increase a printing time." +msgstr "" + +msgid "Separated infills" +msgstr "" + +msgid "" +"Centers the internal infill of each part on itself, as if it were sliced on its own, instead of on the whole assembly. Parts that touch or overlap are treated as one body and share a center; separate parts (or distinct 3D objects) each get their own.\n" +"Useful when an assembly groups several objects that should each keep a consistent, self-centered infill.\n" +"Affects line and grid patterns and rotation-template infills.\n" +"Patterns locked to global coordinates (Gyroid, Honeycomb, TPMS, ...) are unaffected." +msgstr "" + +msgid "Center surface pattern on" +msgstr "" + +msgid "" +"Chooses where the centering point of centered top/bottom surface patterns (Archimedean Chords, Octagram Spiral) is placed.\n" +" - Each Surface: centers the pattern on every individual surface region, so each island is symmetric on its own.\n" +" - Each Model: centers the pattern on each connected body. Parts that touch or overlap share one center; parts detached from the rest each get their own.\n" +" - Each Assembly: uses a single shared center for the whole object or assembly." +msgstr "" + +msgid "Each Surface" +msgstr "" + +msgid "Each Model" +msgstr "" + +msgid "Each Assembly" +msgstr "" + msgid "This is the speed at which traveling is done." msgstr "Ограничение скорости холостых перемещений печатающей головы." @@ -20095,6 +20200,22 @@ msgstr "" "Предотвращение коробления материала\n" "Знаете ли вы, что при печати материалами, склонными к короблению, таких как ABS, повышение температуры подогреваемого стола может снизить эту вероятность?" +#~ msgid "Continue to sync filaments" +#~ msgstr "Продолжить синхронизацию филаментов" + +#~ msgctxt "Sync_Nozzle_AMS" +#~ msgid "Cancel" +#~ msgstr "Отмена" + +#~ msgid "Align infill direction to model" +#~ msgstr "Вращать заполнение с моделью" + +#~ msgid "Print" +#~ msgstr "Печать" + +#~ msgid "in" +#~ msgstr "дюйм" + #~ msgid "Object coordinates" #~ msgstr "Относительно модели" diff --git a/localization/i18n/sv/OrcaSlicer_sv.po b/localization/i18n/sv/OrcaSlicer_sv.po index 15726721ac..ce0496c88e 100644 --- a/localization/i18n/sv/OrcaSlicer_sv.po +++ b/localization/i18n/sv/OrcaSlicer_sv.po @@ -3,7 +3,7 @@ msgid "" msgstr "" "Project-Id-Version: Orca Slicer\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-07-06 12:57-0300\n" +"POT-Creation-Date: 2026-07-12 12:27-0300\n" "Language: sv\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -159,6 +159,12 @@ msgstr "Fyll" msgid "Gap Fill" msgstr "Gap Fyllning" +msgid "Vertical" +msgstr "Vertikal" + +msgid "Horizontal" +msgstr "Horisontell" + #, boost-format msgid "Allows painting only on facets selected by: \"%1%\"" msgstr "Tillåter målning endast på fasetter som valts av: ”%1%”" @@ -254,12 +260,6 @@ msgstr "Triangel" msgid "Height Range" msgstr "Höjd intervall" -msgid "Vertical" -msgstr "Vertikal" - -msgid "Horizontal" -msgstr "Horisontell" - msgid "Remove painted color" msgstr "Ta bort färgläggning" @@ -324,6 +324,7 @@ msgstr "" msgid "Optimize orientation" msgstr "Optimisera placering" +msgctxt "Verb" msgid "Scale" msgstr "Skala" @@ -333,8 +334,9 @@ msgstr "" msgid "Error: Please close all toolbar menus first" msgstr "FEL: Stäng alla verktygsmenyer först" +msgctxt "inches" msgid "in" -msgstr "i" +msgstr "" msgid "mm" msgstr "mm" @@ -367,6 +369,9 @@ msgstr "Skalnings förhållande" msgid "Object operations" msgstr "Objekt Åtgärder" +msgid "Scale" +msgstr "Skala" + # TODO: Review, changed by lang refactor. PR 14254 msgid "Volume operations" msgstr "Volym Åtgärder" @@ -417,6 +422,10 @@ msgstr "" msgid "Reset current rotation to real zeros." msgstr "" +msgctxt "Noun" +msgid "Scale" +msgstr "Skala" + #. TRN - Input label. Be short as possible msgid "Size" msgstr "Storlek" @@ -3602,7 +3611,7 @@ msgstr "Kalibreringen klar. Vänligen hitta den mest enhetliga extruderingslinje msgid "Save" msgstr "Spara" -# TODO: Review, changed by lang refactor. PR 14254 +msgctxt "Navigation" msgid "Back" msgstr "Tillbaka" @@ -4960,6 +4969,7 @@ msgstr "" msgid "Color change" msgstr "Färg byte" +msgctxt "Noun" msgid "Print" msgstr "Skriv ut" @@ -5119,11 +5129,15 @@ msgstr "Undvik kalibrerings området" msgid "Align to Y axis" msgstr "Justera mot Y-axeln" -msgctxt "Camera" +msgctxt "Camera View" +msgid "Back" +msgstr "Tillbaka" + +msgctxt "Camera View" msgid "Left" msgstr "Vänster" -msgctxt "Camera" +msgctxt "Camera View" msgid "Right" msgstr "Höger" @@ -5447,6 +5461,10 @@ msgstr "Skriv ut byggplattan" msgid "Export G-code file" msgstr "Exportera G-kod filen" +msgctxt "Verb" +msgid "Print" +msgstr "Skriv ut" + msgid "Export plate sliced file" msgstr "Exportera byggplattans beredda fil" @@ -5620,15 +5638,6 @@ msgstr "Exportera aktuell konfiguration till filer" msgid "Export" msgstr "Exportera" -msgid "Sync Presets" -msgstr "" - -msgid "Pull and apply the latest presets from OrcaCloud" -msgstr "" - -msgid "You must be logged in to sync presets from cloud." -msgstr "" - msgid "Quit" msgstr "Avsluta" @@ -5745,6 +5754,15 @@ msgstr "Vy" msgid "Preset Bundle" msgstr "" +msgid "Sync Presets" +msgstr "" + +msgid "Pull and apply the latest presets from OrcaCloud" +msgstr "" + +msgid "You must be logged in to sync presets from cloud." +msgstr "" + msgid "Syncing presets from cloud…" msgstr "" @@ -10163,13 +10181,9 @@ msgstr "" msgid "Successfully synchronized nozzle and AMS number information." msgstr "" -msgid "Continue to sync filaments" +msgid "Do you want to continue to sync filaments?" msgstr "" -msgctxt "Sync_Nozzle_AMS" -msgid "Cancel" -msgstr "Avbryt" - msgid "Successfully synchronized filament color from printer." msgstr "" @@ -11463,7 +11477,7 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." @@ -11477,7 +11491,7 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." @@ -12119,6 +12133,42 @@ msgstr "" msgid "Density of top surface layer. A value of 100% creates a fully solid, smooth top layer. Reducing this value results in a textured top surface, according to the chosen top surface pattern. A value of 0% will result in only the walls on the top layer being created. Intended for aesthetic or functional purposes, not to fix issues such as over-extrusion." msgstr "" +msgid "Top surface expansion" +msgstr "" + +msgid "" +"Expands the top surfaces by this distance to connect distinct top surfaces and fill gaps.\n" +"Useful for cases where the top surface is interrupted by a raised feature, such as text on a plane.Expanding it removes the holes beneath these features and creates a continuous path with a better finish for printing on top.The expansion is applied to the original top surface, before any other processing such as bridging or overhang detection." +msgstr "" + +msgid "Top expansion wall margin" +msgstr "" + +msgid "" +"Using “Top surface expansion” may cause a surface that did not previously touch the model's outer walls to now do so.\n" +"This can cause contraction marks (such as the hull line) on the outer walls.\n" +"By adding a small margin, this contraction will not occur directly on the walls, thereby preventing a visible mark." +msgstr "" + +msgid "Top expansion direction" +msgstr "" + +msgid "" +"Direction in which the top surface expansion grows.\n" +" - Inward grows into the holes and gaps left by features rising from the middle of a top surface.\n" +" - Outward grows the outer edge of the surface, connecting surfaces separated by features that can divide a surface, such as a lattice pattern.\n" +" - Inward and Outward does both." +msgstr "" + +msgid "Inward and Outward" +msgstr "" + +msgid "Inward" +msgstr "" + +msgid "Outward" +msgstr "" + msgid "Bottom surface pattern" msgstr "Botten ytans mönster" @@ -12734,12 +12784,12 @@ msgstr "Sparsam ifyllnads densitet" msgid "Density of internal sparse infill, 100% turns all sparse infill into solid infill and internal solid infill pattern will be used." msgstr "" -msgid "Align infill direction to model" +msgid "Align directions to model" msgstr "" msgid "" -"Aligns infill, bridge, ironing and surface fill directions to follow the model's orientation on the build plate.\n" -"When enabled, directions rotate with the model to maintain optimal strength characteristics." +"Aligns infill, bridge, ironing, and top/bottom surface directions to follow the model's orientation on the build plate.\n" +"When enabled, these directions rotate together with the model so the printed features keep their intended orientation relative to the part, preserving optimal strength and surface characteristics regardless of how the model is placed." msgstr "" msgid "Insert solid layers" @@ -14399,6 +14449,10 @@ msgstr "Linjerad" msgid "Aligned back" msgstr "" +# TODO: Review, changed by lang refactor. PR 14254 +msgid "Back" +msgstr "Tillbaka" + msgid "Random" msgstr "Slumpmässig" @@ -14742,6 +14796,18 @@ msgstr "" msgid "If enabled, all printing extruders will be primed at the front edge of the print bed at the start of the print." msgstr "" +msgid "Toolchange ordering" +msgstr "" + +msgid "" +"Determines the order of tool changes on each layer.\n" +"- Default: Starts with the last used extruder to minimize tool changes.\n" +"- Cyclic: Uses a fixed tool sequence each layer. This sacrifices speed for better surface quality, as the extra toolchanges allow layers more time to cool." +msgstr "" + +msgid "Cyclic" +msgstr "" + msgid "Slice gap closing radius" msgstr "Bered spaltens stängningsradie" @@ -15169,6 +15235,45 @@ msgstr "Övre skalets tjocklek" msgid "The number of top solid layers is increased when slicing if the thickness calculated by top shell layers is thinner than this value. This can avoid having too thin a shell when layer height is small. 0 means that this setting is disabled and thickness of top shell is determined simply by the number of top shell layers." msgstr "Antal solida övre lager ökas när tjockleken kalkyleras och övre skalet är tunnare än detta värde. Detta kan undvika att ha för tunt skal när lagerhöjden är liten. 0 betyder att den här inställningen är inaktiverad och tjockleken på det övre skalet bestäms av de övre skal lagerna" +msgid "Anisotropic surfaces" +msgstr "" + +msgid "" +"Anisotropic patterns on the top and bottom surfaces.\n" +"Co-directional printing mode will be applied. For certain patterns, omni-directional filling provides color dispersion when using multi-colored or silk plastics.\n" +"This option disable the gap fill.\n" +"This option can increase a printing time." +msgstr "" + +msgid "Separated infills" +msgstr "" + +msgid "" +"Centers the internal infill of each part on itself, as if it were sliced on its own, instead of on the whole assembly. Parts that touch or overlap are treated as one body and share a center; separate parts (or distinct 3D objects) each get their own.\n" +"Useful when an assembly groups several objects that should each keep a consistent, self-centered infill.\n" +"Affects line and grid patterns and rotation-template infills.\n" +"Patterns locked to global coordinates (Gyroid, Honeycomb, TPMS, ...) are unaffected." +msgstr "" + +msgid "Center surface pattern on" +msgstr "" + +msgid "" +"Chooses where the centering point of centered top/bottom surface patterns (Archimedean Chords, Octagram Spiral) is placed.\n" +" - Each Surface: centers the pattern on every individual surface region, so each island is symmetric on its own.\n" +" - Each Model: centers the pattern on each connected body. Parts that touch or overlap share one center; parts detached from the rest each get their own.\n" +" - Each Assembly: uses a single shared center for the whole object or assembly." +msgstr "" + +msgid "Each Surface" +msgstr "" + +msgid "Each Model" +msgstr "" + +msgid "Each Assembly" +msgstr "" + # TODO: Review, changed by lang refactor. PR 14254 msgid "This is the speed at which traveling is done." msgstr "Förflyttnings hastighet" @@ -19054,6 +19159,16 @@ msgstr "" "Undvik vridning\n" "Visste du att när du skriver ut material som är benägna att vrida, såsom ABS, kan en lämplig ökning av värmebäddens temperatur minska sannolikheten för vridning?" +#~ msgctxt "Sync_Nozzle_AMS" +#~ msgid "Cancel" +#~ msgstr "Avbryt" + +#~ msgid "Print" +#~ msgstr "Skriv ut" + +#~ msgid "in" +#~ msgstr "i" + #~ msgid "World coordinates" #~ msgstr "Världskoordinater" @@ -20224,10 +20339,6 @@ msgstr "" #~ msgid "Thick bridges" #~ msgstr "Tjocka bridges" -#~ msgctxt "Verb" -#~ msgid "Scale" -#~ msgstr "Skala" - #~ msgid "Z-hop when retract" #~ msgstr "Z-hopp vid retraktion" diff --git a/localization/i18n/th/OrcaSlicer_th.po b/localization/i18n/th/OrcaSlicer_th.po index e90b5cd4de..7459512c18 100644 --- a/localization/i18n/th/OrcaSlicer_th.po +++ b/localization/i18n/th/OrcaSlicer_th.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Orca Slicer\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-07-06 12:57-0300\n" +"POT-Creation-Date: 2026-07-12 12:27-0300\n" "PO-Revision-Date: 2026-06-19 13:40+0700\n" "Last-Translator: Icezaza\n" "Language-Team: Thai\n" @@ -162,6 +162,12 @@ msgstr "เติม" msgid "Gap Fill" msgstr "เติมช่องว่าง" +msgid "Vertical" +msgstr "แนวตั้ง" + +msgid "Horizontal" +msgstr "แนวนอน" + #, boost-format msgid "Allows painting only on facets selected by: \"%1%\"" msgstr "อนุญาตให้วาดภาพเฉพาะด้านที่เลือกโดย: \"%1%\"" @@ -254,12 +260,6 @@ msgstr "สามเหลี่ยม" msgid "Height Range" msgstr "ช่วงความสูง" -msgid "Vertical" -msgstr "แนวตั้ง" - -msgid "Horizontal" -msgstr "แนวนอน" - msgid "Remove painted color" msgstr "ลบสีที่ทาสี" @@ -324,6 +324,7 @@ msgstr "Gizmo-หมุน" msgid "Optimize orientation" msgstr "ปรับการวางแนวให้เหมาะสม" +msgctxt "Verb" msgid "Scale" msgstr "ปรับขนาด" @@ -333,8 +334,9 @@ msgstr "Gizmo-ขนาด" msgid "Error: Please close all toolbar menus first" msgstr "ข้อผิดพลาด: โปรดปิดเมนูแถบเครื่องมือทั้งหมดก่อน" +msgctxt "inches" msgid "in" -msgstr "นิ้ว" +msgstr "" msgid "mm" msgstr "มม." @@ -366,6 +368,9 @@ msgstr "อัตราส่วนการปรับขนาด" msgid "Object operations" msgstr "การทำงานกับวัตถุ" +msgid "Scale" +msgstr "ปรับขนาด" + msgid "Volume operations" msgstr "การทำงานกับวอลลุ่ม" @@ -411,6 +416,10 @@ msgstr "รีเซ็ตการหมุนปัจจุบันเป็ msgid "Reset current rotation to real zeros." msgstr "รีเซ็ตการหมุนปัจจุบันให้เป็นศูนย์จริง" +msgctxt "Noun" +msgid "Scale" +msgstr "ปรับขนาด" + #. TRN - Input label. Be short as possible msgid "Size" msgstr "ขนาด" @@ -3558,6 +3567,7 @@ msgstr "การสอบเทียบเสร็จสิ้น โปร msgid "Save" msgstr "บันทึก" +msgctxt "Navigation" msgid "Back" msgstr "กลับ" @@ -4906,6 +4916,7 @@ msgstr "การเปลี่ยนแปลงเครื่องมือ msgid "Color change" msgstr "เปลี่ยนสี" +msgctxt "Noun" msgid "Print" msgstr "พิมพ์" @@ -5065,11 +5076,15 @@ msgstr "หลีกเลี่ยงบริเวณการสอบเท msgid "Align to Y axis" msgstr "จัดแนวตามแกน Y" -msgctxt "Camera" +msgctxt "Camera View" +msgid "Back" +msgstr "กลับ" + +msgctxt "Camera View" msgid "Left" msgstr "ซ้าย" -msgctxt "Camera" +msgctxt "Camera View" msgid "Right" msgstr "ขวา" @@ -5392,6 +5407,10 @@ msgstr "พิมพ์ฐานพิมพ์" msgid "Export G-code file" msgstr "ส่งออกไฟล์ G-code" +msgctxt "Verb" +msgid "Print" +msgstr "พิมพ์" + msgid "Export plate sliced file" msgstr "ส่งออกไฟล์แผ่นสไลซ์บาง ๆ" @@ -5565,15 +5584,6 @@ msgstr "ส่งออกการกำหนดค่าปัจจุบั msgid "Export" msgstr "ส่งออก" -msgid "Sync Presets" -msgstr "ซิงค์พรีเซ็ต" - -msgid "Pull and apply the latest presets from OrcaCloud" -msgstr "ดึงและใช้ค่าที่ตั้งล่วงหน้าล่าสุดจาก OrcaCloud" - -msgid "You must be logged in to sync presets from cloud." -msgstr "คุณต้องเข้าสู่ระบบเพื่อซิงค์ค่าที่ตั้งล่วงหน้าจากคลาวด์" - msgid "Quit" msgstr "ออก" @@ -5688,6 +5698,15 @@ msgstr "มุมมอง" msgid "Preset Bundle" msgstr "ชุดที่ตั้งไว้ล่วงหน้า" +msgid "Sync Presets" +msgstr "ซิงค์พรีเซ็ต" + +msgid "Pull and apply the latest presets from OrcaCloud" +msgstr "ดึงและใช้ค่าที่ตั้งล่วงหน้าล่าสุดจาก OrcaCloud" + +msgid "You must be logged in to sync presets from cloud." +msgstr "คุณต้องเข้าสู่ระบบเพื่อซิงค์ค่าที่ตั้งล่วงหน้าจากคลาวด์" + msgid "Syncing presets from cloud…" msgstr "กำลังซิงค์ค่าที่ตั้งล่วงหน้าจากคลาวด์..." @@ -10122,12 +10141,8 @@ msgstr "ซิงโครไนซ์ข้อมูลหัวฉีดสำ msgid "Successfully synchronized nozzle and AMS number information." msgstr "ซิงโครไนซ์ข้อมูลหัวฉีดและหมายเลข AMS เรียบร้อยแล้ว" -msgid "Continue to sync filaments" -msgstr "ทำการซิงค์ฟิลาเมนต์ต่อไป" - -msgctxt "Sync_Nozzle_AMS" -msgid "Cancel" -msgstr "ยกเลิก" +msgid "Do you want to continue to sync filaments?" +msgstr "" msgid "Successfully synchronized filament color from printer." msgstr "ซิงโครไนซ์สีฟิลาเมนต์จากเครื่องพิมพ์สำเร็จแล้ว" @@ -11399,19 +11414,11 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." msgstr "" -"แทนที่มุมสะพานด้านนอก\n" -"หากปล่อยเป็นศูนย์ มุมสะพานจะคำนวณอัตโนมัติสำหรับสะพานแต่ละจุด\n" -"มิฉะนั้นจะใช้มุมที่กำหนดตาม:\n" -" - พิกัดสัมบูรณ์\n" -" - พิกัดสัมบูรณ์ + การหมุนโมเดล: หากเปิดใช้งานจัดทิศทางไส้ในให้สอดคล้องกับโมเดล\n" -" - มุมอัตโนมัติที่เหมาะสม + ค่านี้: หากเปิดใช้งาน 'มุมสะพานแบบสัมพันธ์'\n" -"\n" -"ใช้ 180° สำหรับมุมสัมบูรณ์ศูนย์" msgid "Internal bridge infill direction" msgstr "ทิศทางไส้ในสะพานภายใน" @@ -11421,19 +11428,11 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." msgstr "" -"แทนที่มุมสะพานด้านใน\n" -"หากปล่อยเป็นศูนย์ มุมสะพานจะคำนวณอัตโนมัติสำหรับสะพานแต่ละจุด\n" -"มิฉะนั้นจะใช้มุมที่กำหนดตาม:\n" -" - พิกัดสัมบูรณ์\n" -" - พิกัดสัมบูรณ์ + การหมุนโมเดล: หากเปิดใช้งานจัดทิศทางไส้ในให้สอดคล้องกับโมเดล\n" -" - มุมอัตโนมัติที่เหมาะสม + ค่านี้: หากเปิดใช้งาน 'มุมสะพานแบบสัมพันธ์'\n" -"\n" -"ใช้ 180° สำหรับมุมสัมบูรณ์ศูนย์" msgid "Relative bridge angle" msgstr "มุมสะพานแบบสัมพันธ์" @@ -12203,6 +12202,42 @@ msgstr "ความหนาแน่นผิวด้านบน" msgid "Density of top surface layer. A value of 100% creates a fully solid, smooth top layer. Reducing this value results in a textured top surface, according to the chosen top surface pattern. A value of 0% will result in only the walls on the top layer being created. Intended for aesthetic or functional purposes, not to fix issues such as over-extrusion." msgstr "ความหนาแน่นของชั้นผิวด้านบน ค่า 100% จะสร้างชั้นบนสุดที่เรียบและแข็งเต็มที่ การลดค่านี้ส่งผลให้พื้นผิวด้านบนมีพื้นผิวตามรูปแบบพื้นผิวด้านบนที่เลือก ค่า 0% จะส่งผลให้มีการสร้างเฉพาะผนังชั้นบนสุดเท่านั้น มีวัตถุประสงค์เพื่อความสวยงามหรือการใช้งาน ไม่ใช่เพื่อแก้ไขปัญหา เช่น การอัดขึ้นรูปมากเกินไป" +msgid "Top surface expansion" +msgstr "" + +msgid "" +"Expands the top surfaces by this distance to connect distinct top surfaces and fill gaps.\n" +"Useful for cases where the top surface is interrupted by a raised feature, such as text on a plane.Expanding it removes the holes beneath these features and creates a continuous path with a better finish for printing on top.The expansion is applied to the original top surface, before any other processing such as bridging or overhang detection." +msgstr "" + +msgid "Top expansion wall margin" +msgstr "" + +msgid "" +"Using “Top surface expansion” may cause a surface that did not previously touch the model's outer walls to now do so.\n" +"This can cause contraction marks (such as the hull line) on the outer walls.\n" +"By adding a small margin, this contraction will not occur directly on the walls, thereby preventing a visible mark." +msgstr "" + +msgid "Top expansion direction" +msgstr "" + +msgid "" +"Direction in which the top surface expansion grows.\n" +" - Inward grows into the holes and gaps left by features rising from the middle of a top surface.\n" +" - Outward grows the outer edge of the surface, connecting surfaces separated by features that can divide a surface, such as a lattice pattern.\n" +" - Inward and Outward does both." +msgstr "" + +msgid "Inward and Outward" +msgstr "" + +msgid "Inward" +msgstr "" + +msgid "Outward" +msgstr "" + msgid "Bottom surface pattern" msgstr "รูปแบบผิวด้านล่าง" @@ -12853,15 +12888,13 @@ msgstr "ความหนาแน่นไส้ในแบบโปร่ง msgid "Density of internal sparse infill, 100% turns all sparse infill into solid infill and internal solid infill pattern will be used." msgstr "ความหนาแน่นของไส้ในแบบโปร่งภายใน 100% จะเปลี่ยนไส้ในแบบโปร่งทั้งหมดให้เป็นไส้ในแบบทึบ และจะใช้รูปแบบไส้ในแบบทึบภายใน" -msgid "Align infill direction to model" -msgstr "จัดทิศทาง ไส้ใน ให้ตรงกับโมเดล" +msgid "Align directions to model" +msgstr "" msgid "" -"Aligns infill, bridge, ironing and surface fill directions to follow the model's orientation on the build plate.\n" -"When enabled, directions rotate with the model to maintain optimal strength characteristics." +"Aligns infill, bridge, ironing, and top/bottom surface directions to follow the model's orientation on the build plate.\n" +"When enabled, these directions rotate together with the model so the printed features keep their intended orientation relative to the part, preserving optimal strength and surface characteristics regardless of how the model is placed." msgstr "" -"จัดทิศทางไส้ใน สะพาน การรีดเรียบ และการเติมผิวให้สอดคล้องกับการวางแนวของโมเดลบนฐานรองพิมพ์\n" -"เมื่อเปิดใช้งาน ทิศทางจะหมุนตามโมเดลเพื่อรักษาคุณสมบัติความแข็งแรงที่เหมาะสม" msgid "Insert solid layers" msgstr "แทรกชั้นทึบ" @@ -14590,6 +14623,9 @@ msgstr "จัดตำแหน่ง" msgid "Aligned back" msgstr "จัดแนวกลับ" +msgid "Back" +msgstr "กลับ" + msgid "Random" msgstr "สุ่ม" @@ -14947,6 +14983,18 @@ msgstr "ใช้ชุดดันเส้นการพิมพ์ทั้ msgid "If enabled, all printing extruders will be primed at the front edge of the print bed at the start of the print." msgstr "หากเปิดใช้งาน ชุดดันเส้นการพิมพ์ทั้งหมดจะถูกลงสีพื้นที่ขอบด้านหน้าของฐานพิมพ์เมื่อเริ่มต้นการพิมพ์" +msgid "Toolchange ordering" +msgstr "" + +msgid "" +"Determines the order of tool changes on each layer.\n" +"- Default: Starts with the last used extruder to minimize tool changes.\n" +"- Cyclic: Uses a fixed tool sequence each layer. This sacrifices speed for better surface quality, as the extra toolchanges allow layers more time to cool." +msgstr "" + +msgid "Cyclic" +msgstr "" + msgid "Slice gap closing radius" msgstr "รัศมีการปิดช่องว่างของ Slice" @@ -15370,6 +15418,45 @@ msgstr "ความหนาผนังด้านบน" msgid "The number of top solid layers is increased when slicing if the thickness calculated by top shell layers is thinner than this value. This can avoid having too thin a shell when layer height is small. 0 means that this setting is disabled and thickness of top shell is determined simply by the number of top shell layers." msgstr "จำนวนชั้นทึบด้านบนจะเพิ่มขึ้นเมื่อสไลซ์หากความหนาที่คำนวณโดยชั้นเปลือกด้านบนบางกว่าค่านี้ วิธีนี้สามารถหลีกเลี่ยงไม่ให้เปลือกบางเกินไปเมื่อชั้นมีความสูงน้อย 0 หมายความว่าการตั้งค่านี้ถูกปิดใช้งาน และความหนาของเปลือกด้านบนถูกกำหนดโดยชั้นเปลือกด้านบนอย่างแน่นอน" +msgid "Anisotropic surfaces" +msgstr "" + +msgid "" +"Anisotropic patterns on the top and bottom surfaces.\n" +"Co-directional printing mode will be applied. For certain patterns, omni-directional filling provides color dispersion when using multi-colored or silk plastics.\n" +"This option disable the gap fill.\n" +"This option can increase a printing time." +msgstr "" + +msgid "Separated infills" +msgstr "" + +msgid "" +"Centers the internal infill of each part on itself, as if it were sliced on its own, instead of on the whole assembly. Parts that touch or overlap are treated as one body and share a center; separate parts (or distinct 3D objects) each get their own.\n" +"Useful when an assembly groups several objects that should each keep a consistent, self-centered infill.\n" +"Affects line and grid patterns and rotation-template infills.\n" +"Patterns locked to global coordinates (Gyroid, Honeycomb, TPMS, ...) are unaffected." +msgstr "" + +msgid "Center surface pattern on" +msgstr "" + +msgid "" +"Chooses where the centering point of centered top/bottom surface patterns (Archimedean Chords, Octagram Spiral) is placed.\n" +" - Each Surface: centers the pattern on every individual surface region, so each island is symmetric on its own.\n" +" - Each Model: centers the pattern on each connected body. Parts that touch or overlap share one center; parts detached from the rest each get their own.\n" +" - Each Assembly: uses a single shared center for the whole object or assembly." +msgstr "" + +msgid "Each Surface" +msgstr "" + +msgid "Each Model" +msgstr "" + +msgid "Each Assembly" +msgstr "" + msgid "This is the speed at which traveling is done." msgstr "ความเร็วที่ใช้ในการเคลื่อนที่แบบไม่อัดเส้น" @@ -19344,6 +19431,68 @@ msgstr "" "หลีกเลี่ยงการบิดเบี้ยว\n" "คุณรู้หรือไม่ว่าเมื่อพิมพ์วัสดุที่มีแนวโน้มที่จะเกิดการบิดเบี้ยว เช่น ABS การเพิ่มอุณหภูมิฐานพิมพ์อย่างเหมาะสมสามารถลดความน่าจะเป็นของการบิดเบี้ยวได้" +#~ msgid "Continue to sync filaments" +#~ msgstr "ทำการซิงค์ฟิลาเมนต์ต่อไป" + +#~ msgctxt "Sync_Nozzle_AMS" +#~ msgid "Cancel" +#~ msgstr "ยกเลิก" + +#, no-c-format, no-boost-format +#~ msgid "" +#~ "External Bridging angle override.\n" +#~ "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" +#~ "Otherwise the provided angle will be used according to:\n" +#~ " - The absolute coordinates\n" +#~ " - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +#~ " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" +#~ "\n" +#~ "Use 180° for zero absolute angle." +#~ msgstr "" +#~ "แทนที่มุมสะพานด้านนอก\n" +#~ "หากปล่อยเป็นศูนย์ มุมสะพานจะคำนวณอัตโนมัติสำหรับสะพานแต่ละจุด\n" +#~ "มิฉะนั้นจะใช้มุมที่กำหนดตาม:\n" +#~ " - พิกัดสัมบูรณ์\n" +#~ " - พิกัดสัมบูรณ์ + การหมุนโมเดล: หากเปิดใช้งานจัดทิศทางไส้ในให้สอดคล้องกับโมเดล\n" +#~ " - มุมอัตโนมัติที่เหมาะสม + ค่านี้: หากเปิดใช้งาน 'มุมสะพานแบบสัมพันธ์'\n" +#~ "\n" +#~ "ใช้ 180° สำหรับมุมสัมบูรณ์ศูนย์" + +#~ msgid "" +#~ "Internal Bridging angle override.\n" +#~ "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" +#~ "Otherwise the provided angle will be used according to:\n" +#~ " - The absolute coordinates\n" +#~ " - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +#~ " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" +#~ "\n" +#~ "Use 180° for zero absolute angle." +#~ msgstr "" +#~ "แทนที่มุมสะพานด้านใน\n" +#~ "หากปล่อยเป็นศูนย์ มุมสะพานจะคำนวณอัตโนมัติสำหรับสะพานแต่ละจุด\n" +#~ "มิฉะนั้นจะใช้มุมที่กำหนดตาม:\n" +#~ " - พิกัดสัมบูรณ์\n" +#~ " - พิกัดสัมบูรณ์ + การหมุนโมเดล: หากเปิดใช้งานจัดทิศทางไส้ในให้สอดคล้องกับโมเดล\n" +#~ " - มุมอัตโนมัติที่เหมาะสม + ค่านี้: หากเปิดใช้งาน 'มุมสะพานแบบสัมพันธ์'\n" +#~ "\n" +#~ "ใช้ 180° สำหรับมุมสัมบูรณ์ศูนย์" + +#~ msgid "Align infill direction to model" +#~ msgstr "จัดทิศทาง ไส้ใน ให้ตรงกับโมเดล" + +#~ msgid "" +#~ "Aligns infill, bridge, ironing and surface fill directions to follow the model's orientation on the build plate.\n" +#~ "When enabled, directions rotate with the model to maintain optimal strength characteristics." +#~ msgstr "" +#~ "จัดทิศทางไส้ใน สะพาน การรีดเรียบ และการเติมผิวให้สอดคล้องกับการวางแนวของโมเดลบนฐานรองพิมพ์\n" +#~ "เมื่อเปิดใช้งาน ทิศทางจะหมุนตามโมเดลเพื่อรักษาคุณสมบัติความแข็งแรงที่เหมาะสม" + +#~ msgid "Print" +#~ msgstr "พิมพ์" + +#~ msgid "in" +#~ msgstr "นิ้ว" + #~ msgid "Object coordinates" #~ msgstr "พิกัดวัตถุ" diff --git a/localization/i18n/tr/OrcaSlicer_tr.po b/localization/i18n/tr/OrcaSlicer_tr.po index 20b6999bf6..e3ae82aa5c 100644 --- a/localization/i18n/tr/OrcaSlicer_tr.po +++ b/localization/i18n/tr/OrcaSlicer_tr.po @@ -3,7 +3,7 @@ msgid "" msgstr "" "Project-Id-Version: Orca Slicer\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-07-06 12:57-0300\n" +"POT-Creation-Date: 2026-07-12 12:27-0300\n" "PO-Revision-Date: 2026-04-08 23:59+0300\n" "Last-Translator: GlauTech\n" "Language-Team: \n" @@ -162,6 +162,12 @@ msgstr "Doldur" msgid "Gap Fill" msgstr "Boşluk doldurma" +msgid "Vertical" +msgstr "Dikey" + +msgid "Horizontal" +msgstr "Yatay" + #, boost-format msgid "Allows painting only on facets selected by: \"%1%\"" msgstr "Yalnızca şu kişi tarafından seçilen yüzeylerde boyamaya izin verir: \"%1%\"" @@ -257,12 +263,6 @@ msgstr "Üçgen" msgid "Height Range" msgstr "Yükseklik Aralığı" -msgid "Vertical" -msgstr "Dikey" - -msgid "Horizontal" -msgstr "Yatay" - msgid "Remove painted color" msgstr "Boyalı rengi kaldır" @@ -327,6 +327,7 @@ msgstr "Gizmo-Döndür" msgid "Optimize orientation" msgstr "Yönü optimize edin" +msgctxt "Verb" msgid "Scale" msgstr "Ölçeklendir" @@ -336,8 +337,9 @@ msgstr "Gizmo-Ölçeklendir" msgid "Error: Please close all toolbar menus first" msgstr "Hata: Lütfen önce tüm araç çubuğu menülerini kapatın" +msgctxt "inches" msgid "in" -msgstr "in" +msgstr "" msgid "mm" msgstr "mm" @@ -370,6 +372,9 @@ msgstr "Ölçek oranları" msgid "Object operations" msgstr "Nesne İşlemleri" +msgid "Scale" +msgstr "Ölçeklendir" + # TODO: Review, changed by lang refactor. PR 14254 msgid "Volume operations" msgstr "Hacim İşlemleri" @@ -421,6 +426,10 @@ msgstr "Döndürme aracını açtığınızda mevcut döndürme değerini sıfı msgid "Reset current rotation to real zeros." msgstr "Mevcut dönüşü gerçek sıfırlara sıfırla." +msgctxt "Noun" +msgid "Scale" +msgstr "Ölçeklendir" + #. TRN - Input label. Be short as possible msgid "Size" msgstr "Boyut" @@ -3643,7 +3652,7 @@ msgstr "Kalibrasyon tamamlandı. Lütfen sıcak yatağınızdaki en düzgün eks msgid "Save" msgstr "Kaydet" -# TODO: Review, changed by lang refactor. PR 14254 +msgctxt "Navigation" msgid "Back" msgstr "Arka" @@ -5026,6 +5035,7 @@ msgstr "Takım değişiklikleri" msgid "Color change" msgstr "Renk değişimi" +msgctxt "Noun" msgid "Print" msgstr "Yazdır" @@ -5189,11 +5199,15 @@ msgstr "Ekstrüzyon kalibrasyon bölgesinden kaçın" msgid "Align to Y axis" msgstr "Y eksenine hizala" -msgctxt "Camera" +msgctxt "Camera View" +msgid "Back" +msgstr "Arka" + +msgctxt "Camera View" msgid "Left" msgstr "Sol" -msgctxt "Camera" +msgctxt "Camera View" msgid "Right" msgstr "Sağ" @@ -5521,6 +5535,10 @@ msgstr "Plakayı Yazdır" msgid "Export G-code file" msgstr "G-kod dosyasını dışa aktar" +msgctxt "Verb" +msgid "Print" +msgstr "Yazdır" + msgid "Export plate sliced file" msgstr "Dilimlenmiş plaka dosyasını dışa aktar" @@ -5694,15 +5712,6 @@ msgstr "Geçerli yapılandırmayı dosyalara aktar" msgid "Export" msgstr "Dışa Aktar" -msgid "Sync Presets" -msgstr "" - -msgid "Pull and apply the latest presets from OrcaCloud" -msgstr "" - -msgid "You must be logged in to sync presets from cloud." -msgstr "" - msgid "Quit" msgstr "Çıkış" @@ -5819,6 +5828,15 @@ msgstr "Görünüm" msgid "Preset Bundle" msgstr "" +msgid "Sync Presets" +msgstr "" + +msgid "Pull and apply the latest presets from OrcaCloud" +msgstr "" + +msgid "You must be logged in to sync presets from cloud." +msgstr "" + msgid "Syncing presets from cloud…" msgstr "" @@ -10307,12 +10325,8 @@ msgstr "Püskürtme ucu bilgileri başarıyla senkronize edildi." msgid "Successfully synchronized nozzle and AMS number information." msgstr "Nozul ve AMS numarası bilgileri başarıyla senkronize edildi." -msgid "Continue to sync filaments" -msgstr "Filamentleri senkronize etmeye devam edin" - -msgctxt "Sync_Nozzle_AMS" -msgid "Cancel" -msgstr "İptal etmek" +msgid "Do you want to continue to sync filaments?" +msgstr "" msgid "Successfully synchronized filament color from printer." msgstr "Filament rengi yazıcıdan başarıyla senkronize edildi." @@ -11637,7 +11651,7 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." @@ -11651,7 +11665,7 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." @@ -12377,6 +12391,42 @@ msgstr "Üst yüzey yoğunluğu" msgid "Density of top surface layer. A value of 100% creates a fully solid, smooth top layer. Reducing this value results in a textured top surface, according to the chosen top surface pattern. A value of 0% will result in only the walls on the top layer being created. Intended for aesthetic or functional purposes, not to fix issues such as over-extrusion." msgstr "Üst yüzey katmanının yoğunluğu. %100 değeri, tamamen sağlam ve pürüzsüz bir üst katman oluşturur. Bu değerin düşürülmesi, seçilen üst yüzey desenine göre dokulu bir üst yüzey elde edilmesini sağlar. %0 değeri ise yalnızca üst katmandaki duvarların oluşturulmasını sağlar. Estetik veya işlevsel amaçlar için tasarlanmıştır, aşırı ekstrüzyon gibi sorunları gidermek için değildir." +msgid "Top surface expansion" +msgstr "" + +msgid "" +"Expands the top surfaces by this distance to connect distinct top surfaces and fill gaps.\n" +"Useful for cases where the top surface is interrupted by a raised feature, such as text on a plane.Expanding it removes the holes beneath these features and creates a continuous path with a better finish for printing on top.The expansion is applied to the original top surface, before any other processing such as bridging or overhang detection." +msgstr "" + +msgid "Top expansion wall margin" +msgstr "" + +msgid "" +"Using “Top surface expansion” may cause a surface that did not previously touch the model's outer walls to now do so.\n" +"This can cause contraction marks (such as the hull line) on the outer walls.\n" +"By adding a small margin, this contraction will not occur directly on the walls, thereby preventing a visible mark." +msgstr "" + +msgid "Top expansion direction" +msgstr "" + +msgid "" +"Direction in which the top surface expansion grows.\n" +" - Inward grows into the holes and gaps left by features rising from the middle of a top surface.\n" +" - Outward grows the outer edge of the surface, connecting surfaces separated by features that can divide a surface, such as a lattice pattern.\n" +" - Inward and Outward does both." +msgstr "" + +msgid "Inward and Outward" +msgstr "" + +msgid "Inward" +msgstr "" + +msgid "Outward" +msgstr "" + msgid "Bottom surface pattern" msgstr "Alt yüzey deseni" @@ -13039,12 +13089,12 @@ msgstr "Dolgu yoğunluğu" msgid "Density of internal sparse infill, 100% turns all sparse infill into solid infill and internal solid infill pattern will be used." msgstr "İç seyrek dolgunun yoğunluğu, %100 tüm seyrek dolguyu katı dolguya dönüştürür ve iç katı dolgu modeli kullanılacaktır." -msgid "Align infill direction to model" -msgstr "Dolgu yönünü modele hizalayın" +msgid "Align directions to model" +msgstr "" msgid "" -"Aligns infill, bridge, ironing and surface fill directions to follow the model's orientation on the build plate.\n" -"When enabled, directions rotate with the model to maintain optimal strength characteristics." +"Aligns infill, bridge, ironing, and top/bottom surface directions to follow the model's orientation on the build plate.\n" +"When enabled, these directions rotate together with the model so the printed features keep their intended orientation relative to the part, preserving optimal strength and surface characteristics regardless of how the model is placed." msgstr "" msgid "Insert solid layers" @@ -14775,6 +14825,10 @@ msgstr "Hizalı" msgid "Aligned back" msgstr "Arkaya hizalı" +# TODO: Review, changed by lang refactor. PR 14254 +msgid "Back" +msgstr "Arka" + msgid "Random" msgstr "Rastgele" @@ -15135,6 +15189,18 @@ msgstr "Tüm ekstruderleri temizle" msgid "If enabled, all printing extruders will be primed at the front edge of the print bed at the start of the print." msgstr "Etkinleştirilirse, tüm baskı ekstruderleri baskının başlangıcında baskı yatağının ön kenarında temizlenecektir." +msgid "Toolchange ordering" +msgstr "" + +msgid "" +"Determines the order of tool changes on each layer.\n" +"- Default: Starts with the last used extruder to minimize tool changes.\n" +"- Cyclic: Uses a fixed tool sequence each layer. This sacrifices speed for better surface quality, as the extra toolchanges allow layers more time to cool." +msgstr "" + +msgid "Cyclic" +msgstr "" + msgid "Slice gap closing radius" msgstr "Dilim aralığı kapanma yarıçapı" @@ -15580,6 +15646,45 @@ msgstr "Üst katman kalınlığı" msgid "The number of top solid layers is increased when slicing if the thickness calculated by top shell layers is thinner than this value. This can avoid having too thin a shell when layer height is small. 0 means that this setting is disabled and thickness of top shell is determined simply by the number of top shell layers." msgstr "Üst kabuk katmanları tarafından hesaplanan kalınlık bu değerden daha ince ise dilimleme sırasında üst katı katmanların sayısı artırılır. Bu, katman yüksekliği küçük olduğunda kabuğun çok ince olmasını önleyebilir. 0, bu ayarın devre dışı olduğu ve üst kabuğun kalınlığının kesinlikle üst kabuk katmanları tarafından belirlendiği anlamına gelir." +msgid "Anisotropic surfaces" +msgstr "" + +msgid "" +"Anisotropic patterns on the top and bottom surfaces.\n" +"Co-directional printing mode will be applied. For certain patterns, omni-directional filling provides color dispersion when using multi-colored or silk plastics.\n" +"This option disable the gap fill.\n" +"This option can increase a printing time." +msgstr "" + +msgid "Separated infills" +msgstr "" + +msgid "" +"Centers the internal infill of each part on itself, as if it were sliced on its own, instead of on the whole assembly. Parts that touch or overlap are treated as one body and share a center; separate parts (or distinct 3D objects) each get their own.\n" +"Useful when an assembly groups several objects that should each keep a consistent, self-centered infill.\n" +"Affects line and grid patterns and rotation-template infills.\n" +"Patterns locked to global coordinates (Gyroid, Honeycomb, TPMS, ...) are unaffected." +msgstr "" + +msgid "Center surface pattern on" +msgstr "" + +msgid "" +"Chooses where the centering point of centered top/bottom surface patterns (Archimedean Chords, Octagram Spiral) is placed.\n" +" - Each Surface: centers the pattern on every individual surface region, so each island is symmetric on its own.\n" +" - Each Model: centers the pattern on each connected body. Parts that touch or overlap share one center; parts detached from the rest each get their own.\n" +" - Each Assembly: uses a single shared center for the whole object or assembly." +msgstr "" + +msgid "Each Surface" +msgstr "" + +msgid "Each Model" +msgstr "" + +msgid "Each Assembly" +msgstr "" + # TODO: Review, changed by lang refactor. PR 14254 msgid "This is the speed at which traveling is done." msgstr "Daha hızlı ve ekstrüzyonsuz seyahat hızı." @@ -19609,6 +19714,22 @@ msgstr "" "Eğilmeyi önleyin\n" "ABS gibi bükülmeye yatkın malzemelere baskı yaparken, ısıtma yatağı sıcaklığının uygun şekilde arttırılmasının bükülme olasılığını azaltabileceğini biliyor muydunuz?" +#~ msgid "Continue to sync filaments" +#~ msgstr "Filamentleri senkronize etmeye devam edin" + +#~ msgctxt "Sync_Nozzle_AMS" +#~ msgid "Cancel" +#~ msgstr "İptal etmek" + +#~ msgid "Align infill direction to model" +#~ msgstr "Dolgu yönünü modele hizalayın" + +#~ msgid "Print" +#~ msgstr "Yazdır" + +#~ msgid "in" +#~ msgstr "in" + #~ msgid "Object coordinates" #~ msgstr "Nesne koordinatları" diff --git a/localization/i18n/uk/OrcaSlicer_uk.po b/localization/i18n/uk/OrcaSlicer_uk.po index f8f130de68..313d526f7d 100644 --- a/localization/i18n/uk/OrcaSlicer_uk.po +++ b/localization/i18n/uk/OrcaSlicer_uk.po @@ -3,7 +3,7 @@ msgid "" msgstr "" "Project-Id-Version: orcaslicerua\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-07-06 12:57-0300\n" +"POT-Creation-Date: 2026-07-12 12:27-0300\n" "PO-Revision-Date: 2025-03-07 09:30+0200\n" "Last-Translator: \n" "Language-Team: Ukrainian\n" @@ -167,6 +167,12 @@ msgstr "Заповнення" msgid "Gap Fill" msgstr "Заповнення прогалин" +msgid "Vertical" +msgstr "Вертикальний" + +msgid "Horizontal" +msgstr "Горизонтальний" + #, boost-format msgid "Allows painting only on facets selected by: \"%1%\"" msgstr "Малювання лише на вибраних гранях: \"%1%\"" @@ -262,12 +268,6 @@ msgstr "Трикутник" msgid "Height Range" msgstr "Діапазон висот" -msgid "Vertical" -msgstr "Вертикальний" - -msgid "Horizontal" -msgstr "Горизонтальний" - msgid "Remove painted color" msgstr "Видалити зафарбований колір" @@ -332,6 +332,7 @@ msgstr "Gizmo обертання" msgid "Optimize orientation" msgstr "Оптимізувати орієнтацію" +msgctxt "Verb" msgid "Scale" msgstr "Масштаб" @@ -341,8 +342,9 @@ msgstr "Gizmo масштабування" msgid "Error: Please close all toolbar menus first" msgstr "Помилка: будь ласка, спочатку закрийте все меню панелі інструментів" +msgctxt "inches" msgid "in" -msgstr "в" +msgstr "" msgid "mm" msgstr "мм" @@ -375,6 +377,9 @@ msgstr "Коефіцієнти масштабування" msgid "Object operations" msgstr "Операції з об'єктами" +msgid "Scale" +msgstr "Масштаб" + # TODO: Review, changed by lang refactor. PR 14254 msgid "Volume operations" msgstr "Операції з об’ємом" @@ -426,6 +431,10 @@ msgstr "Скинути поточне обертання до значення msgid "Reset current rotation to real zeros." msgstr "Скинути поточне обертання до нульових значень." +msgctxt "Noun" +msgid "Scale" +msgstr "Масштаб" + #. TRN - Input label. Be short as possible msgid "Size" msgstr "Розмір" @@ -3659,7 +3668,7 @@ msgstr "Калібрування завершено. Тепер знайдіть msgid "Save" msgstr "Зберегти" -# TODO: Review, changed by lang refactor. PR 14254 +msgctxt "Navigation" msgid "Back" msgstr "Ззаду" @@ -5029,6 +5038,7 @@ msgstr "Зміна інструменту" msgid "Color change" msgstr "Зміна кольору" +msgctxt "Noun" msgid "Print" msgstr "Друк" @@ -5190,11 +5200,15 @@ msgstr "Уникайте області калібрування екструз msgid "Align to Y axis" msgstr "Розташувати вздовж осі Y" -msgctxt "Camera" +msgctxt "Camera View" +msgid "Back" +msgstr "Ззаду" + +msgctxt "Camera View" msgid "Left" msgstr "Ліво" -msgctxt "Camera" +msgctxt "Camera View" msgid "Right" msgstr "Право" @@ -5522,6 +5536,10 @@ msgstr "Друкувати пластину" msgid "Export G-code file" msgstr "Експорт файлу G-коду" +msgctxt "Verb" +msgid "Print" +msgstr "Друк" + msgid "Export plate sliced file" msgstr "Експортувати файл нарізки пластини" @@ -5695,15 +5713,6 @@ msgstr "Експорт поточної конфігурації до файлі msgid "Export" msgstr "Експорт" -msgid "Sync Presets" -msgstr "" - -msgid "Pull and apply the latest presets from OrcaCloud" -msgstr "" - -msgid "You must be logged in to sync presets from cloud." -msgstr "" - msgid "Quit" msgstr "Вихід" @@ -5820,6 +5829,15 @@ msgstr "Вид" msgid "Preset Bundle" msgstr "" +msgid "Sync Presets" +msgstr "" + +msgid "Pull and apply the latest presets from OrcaCloud" +msgstr "" + +msgid "You must be logged in to sync presets from cloud." +msgstr "" + msgid "Syncing presets from cloud…" msgstr "" @@ -10313,13 +10331,9 @@ msgstr "" msgid "Successfully synchronized nozzle and AMS number information." msgstr "" -msgid "Continue to sync filaments" +msgid "Do you want to continue to sync filaments?" msgstr "" -msgctxt "Sync_Nozzle_AMS" -msgid "Cancel" -msgstr "Скасувати" - msgid "Successfully synchronized filament color from printer." msgstr "" @@ -11647,7 +11661,7 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." @@ -11661,7 +11675,7 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." @@ -12362,6 +12376,42 @@ msgstr "" msgid "Density of top surface layer. A value of 100% creates a fully solid, smooth top layer. Reducing this value results in a textured top surface, according to the chosen top surface pattern. A value of 0% will result in only the walls on the top layer being created. Intended for aesthetic or functional purposes, not to fix issues such as over-extrusion." msgstr "" +msgid "Top surface expansion" +msgstr "" + +msgid "" +"Expands the top surfaces by this distance to connect distinct top surfaces and fill gaps.\n" +"Useful for cases where the top surface is interrupted by a raised feature, such as text on a plane.Expanding it removes the holes beneath these features and creates a continuous path with a better finish for printing on top.The expansion is applied to the original top surface, before any other processing such as bridging or overhang detection." +msgstr "" + +msgid "Top expansion wall margin" +msgstr "" + +msgid "" +"Using “Top surface expansion” may cause a surface that did not previously touch the model's outer walls to now do so.\n" +"This can cause contraction marks (such as the hull line) on the outer walls.\n" +"By adding a small margin, this contraction will not occur directly on the walls, thereby preventing a visible mark." +msgstr "" + +msgid "Top expansion direction" +msgstr "" + +msgid "" +"Direction in which the top surface expansion grows.\n" +" - Inward grows into the holes and gaps left by features rising from the middle of a top surface.\n" +" - Outward grows the outer edge of the surface, connecting surfaces separated by features that can divide a surface, such as a lattice pattern.\n" +" - Inward and Outward does both." +msgstr "" + +msgid "Inward and Outward" +msgstr "" + +msgid "Inward" +msgstr "" + +msgid "Outward" +msgstr "" + msgid "Bottom surface pattern" msgstr "Шаблон нижньої поверхні" @@ -13021,12 +13071,12 @@ msgstr "Щільність часткового заповнення" msgid "Density of internal sparse infill, 100% turns all sparse infill into solid infill and internal solid infill pattern will be used." msgstr "Щільність внутрішнього часткового заповнення, 100% перетворює все часткове заповнення на суцільне заповнення, і буде застосовано шаблон внутрішнього суцільного заповнення" -msgid "Align infill direction to model" +msgid "Align directions to model" msgstr "" msgid "" -"Aligns infill, bridge, ironing and surface fill directions to follow the model's orientation on the build plate.\n" -"When enabled, directions rotate with the model to maintain optimal strength characteristics." +"Aligns infill, bridge, ironing, and top/bottom surface directions to follow the model's orientation on the build plate.\n" +"When enabled, these directions rotate together with the model so the printed features keep their intended orientation relative to the part, preserving optimal strength and surface characteristics regardless of how the model is placed." msgstr "" msgid "Insert solid layers" @@ -14752,6 +14802,10 @@ msgstr "Вирівняне" msgid "Aligned back" msgstr "" +# TODO: Review, changed by lang refactor. PR 14254 +msgid "Back" +msgstr "Ззаду" + msgid "Random" msgstr "Випадкове" @@ -15116,6 +15170,18 @@ msgstr "Підготовка всіх друкуючих екструдерів" msgid "If enabled, all printing extruders will be primed at the front edge of the print bed at the start of the print." msgstr "Якщо увімкнено, усі друкуючі екструдери будуть отестовані на передньому краї друкарського столу перед початком друку." +msgid "Toolchange ordering" +msgstr "" + +msgid "" +"Determines the order of tool changes on each layer.\n" +"- Default: Starts with the last used extruder to minimize tool changes.\n" +"- Cyclic: Uses a fixed tool sequence each layer. This sacrifices speed for better surface quality, as the extra toolchanges allow layers more time to cool." +msgstr "" + +msgid "Cyclic" +msgstr "" + msgid "Slice gap closing radius" msgstr "Радіус закриття пробілів під час нарізування" @@ -15557,6 +15623,45 @@ msgstr "Товщина верхньої оболонки" msgid "The number of top solid layers is increased when slicing if the thickness calculated by top shell layers is thinner than this value. This can avoid having too thin a shell when layer height is small. 0 means that this setting is disabled and thickness of top shell is determined simply by the number of top shell layers." msgstr "Кількість верхніх суцільних шарів збільшується при розрізанні, якщо товщина, обчислена шарами верхньої оболонки, тонша за це значення. Це дозволяє уникнути занадто тонкої оболонки при невеликій висоті шару. 0 означає, що це налаштування вимкнено і товщина верхньої оболонки повністюобмежена верхніми шарами оболонки" +msgid "Anisotropic surfaces" +msgstr "" + +msgid "" +"Anisotropic patterns on the top and bottom surfaces.\n" +"Co-directional printing mode will be applied. For certain patterns, omni-directional filling provides color dispersion when using multi-colored or silk plastics.\n" +"This option disable the gap fill.\n" +"This option can increase a printing time." +msgstr "" + +msgid "Separated infills" +msgstr "" + +msgid "" +"Centers the internal infill of each part on itself, as if it were sliced on its own, instead of on the whole assembly. Parts that touch or overlap are treated as one body and share a center; separate parts (or distinct 3D objects) each get their own.\n" +"Useful when an assembly groups several objects that should each keep a consistent, self-centered infill.\n" +"Affects line and grid patterns and rotation-template infills.\n" +"Patterns locked to global coordinates (Gyroid, Honeycomb, TPMS, ...) are unaffected." +msgstr "" + +msgid "Center surface pattern on" +msgstr "" + +msgid "" +"Chooses where the centering point of centered top/bottom surface patterns (Archimedean Chords, Octagram Spiral) is placed.\n" +" - Each Surface: centers the pattern on every individual surface region, so each island is symmetric on its own.\n" +" - Each Model: centers the pattern on each connected body. Parts that touch or overlap share one center; parts detached from the rest each get their own.\n" +" - Each Assembly: uses a single shared center for the whole object or assembly." +msgstr "" + +msgid "Each Surface" +msgstr "" + +msgid "Each Model" +msgstr "" + +msgid "Each Assembly" +msgstr "" + # TODO: Review, changed by lang refactor. PR 14254 msgid "This is the speed at which traveling is done." msgstr "Швидкість переміщення, яка є швидше і без екструзії" @@ -19553,6 +19658,16 @@ msgstr "" "Уникнення деформації\n" "Чи знаєте ви, що при друку матеріалами, схильними до деформації, такими як ABS, відповідне підвищення температури гарячого ліжка може зменшити ймовірність деформації?" +#~ msgctxt "Sync_Nozzle_AMS" +#~ msgid "Cancel" +#~ msgstr "Скасувати" + +#~ msgid "Print" +#~ msgstr "Друк" + +#~ msgid "in" +#~ msgstr "в" + #~ msgid "Object coordinates" #~ msgstr "Координати об'єкта" diff --git a/localization/i18n/vi/OrcaSlicer_vi.po b/localization/i18n/vi/OrcaSlicer_vi.po index 4ecd4fc170..2de15a856f 100644 --- a/localization/i18n/vi/OrcaSlicer_vi.po +++ b/localization/i18n/vi/OrcaSlicer_vi.po @@ -3,7 +3,7 @@ msgid "" msgstr "" "Project-Id-Version: Orca Slicer\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-07-06 12:57-0300\n" +"POT-Creation-Date: 2026-07-12 12:27-0300\n" "PO-Revision-Date: 2025-10-02 17:43+0700\n" "Last-Translator: \n" "Language-Team: hainguyen.ts13@gmail.com\n" @@ -163,6 +163,12 @@ msgstr "Tô" msgid "Gap Fill" msgstr "Lấp khe" +msgid "Vertical" +msgstr "Dọc" + +msgid "Horizontal" +msgstr "Ngang" + #, boost-format msgid "Allows painting only on facets selected by: \"%1%\"" msgstr "Chỉ cho phép vẽ trên mặt được chọn bởi: \"%1%\"" @@ -258,12 +264,6 @@ msgstr "Tam giác" msgid "Height Range" msgstr "Phạm vi chiều cao" -msgid "Vertical" -msgstr "Dọc" - -msgid "Horizontal" -msgstr "Ngang" - msgid "Remove painted color" msgstr "Xóa màu đã vẽ" @@ -328,6 +328,7 @@ msgstr "Gizmo - Xoay" msgid "Optimize orientation" msgstr "Tối ưu định hướng" +msgctxt "Verb" msgid "Scale" msgstr "Tỷ lệ" @@ -337,8 +338,9 @@ msgstr "Gizmo - Tỷ lệ" msgid "Error: Please close all toolbar menus first" msgstr "Lỗi: Vui lòng đóng tất cả menu thanh công cụ trước" +msgctxt "inches" msgid "in" -msgstr "in" +msgstr "" msgid "mm" msgstr "mm" @@ -371,6 +373,9 @@ msgstr "Tỷ lệ co giãn" msgid "Object operations" msgstr "Thao tác vật thể" +msgid "Scale" +msgstr "Tỷ lệ" + # TODO: Review, changed by lang refactor. PR 14254 msgid "Volume operations" msgstr "Thao tác thể tích" @@ -422,6 +427,10 @@ msgstr "Đặt lại xoay hiện tại về giá trị khi mở công cụ xoay. msgid "Reset current rotation to real zeros." msgstr "Đặt lại xoay hiện tại về số không thực." +msgctxt "Noun" +msgid "Scale" +msgstr "Tỷ lệ" + #. TRN - Input label. Be short as possible msgid "Size" msgstr "Kích thước" @@ -3629,7 +3638,7 @@ msgstr "Hiệu chỉnh hoàn tất. Vui lòng tìm đường đùn đồng đề msgid "Save" msgstr "Lưu" -# TODO: Review, changed by lang refactor. PR 14254 +msgctxt "Navigation" msgid "Back" msgstr "Sau" @@ -5000,6 +5009,7 @@ msgstr "" msgid "Color change" msgstr "Đổi màu" +msgctxt "Noun" msgid "Print" msgstr "In" @@ -5161,11 +5171,15 @@ msgstr "Tránh vùng hiệu chỉnh đùn" msgid "Align to Y axis" msgstr "Căn theo trục Y" -msgctxt "Camera" +msgctxt "Camera View" +msgid "Back" +msgstr "Sau" + +msgctxt "Camera View" msgid "Left" msgstr "Trái" -msgctxt "Camera" +msgctxt "Camera View" msgid "Right" msgstr "Phải" @@ -5489,6 +5503,10 @@ msgstr "In plate" msgid "Export G-code file" msgstr "Xuất file G-code" +msgctxt "Verb" +msgid "Print" +msgstr "In" + msgid "Export plate sliced file" msgstr "Xuất file plate đã slice" @@ -5662,15 +5680,6 @@ msgstr "Xuất cấu hình hiện tại ra file" msgid "Export" msgstr "Xuất" -msgid "Sync Presets" -msgstr "" - -msgid "Pull and apply the latest presets from OrcaCloud" -msgstr "" - -msgid "You must be logged in to sync presets from cloud." -msgstr "" - msgid "Quit" msgstr "Thoát" @@ -5787,6 +5796,15 @@ msgstr "Xem" msgid "Preset Bundle" msgstr "" +msgid "Sync Presets" +msgstr "" + +msgid "Pull and apply the latest presets from OrcaCloud" +msgstr "" + +msgid "You must be logged in to sync presets from cloud." +msgstr "" + msgid "Syncing presets from cloud…" msgstr "" @@ -10230,13 +10248,9 @@ msgstr "" msgid "Successfully synchronized nozzle and AMS number information." msgstr "" -msgid "Continue to sync filaments" +msgid "Do you want to continue to sync filaments?" msgstr "" -msgctxt "Sync_Nozzle_AMS" -msgid "Cancel" -msgstr "Hủy" - msgid "Successfully synchronized filament color from printer." msgstr "" @@ -11560,7 +11574,7 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." @@ -11574,7 +11588,7 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." @@ -12273,6 +12287,42 @@ msgstr "Mật độ bề mặt trên" msgid "Density of top surface layer. A value of 100% creates a fully solid, smooth top layer. Reducing this value results in a textured top surface, according to the chosen top surface pattern. A value of 0% will result in only the walls on the top layer being created. Intended for aesthetic or functional purposes, not to fix issues such as over-extrusion." msgstr "Mật độ lớp bề mặt trên. Giá trị 100% tạo ra lớp trên hoàn toàn đặc, mịn . Giảm giá trị này dẫn đến bề mặt trên có kết cấu, theo mẫu bề mặt trên được chọn. Giá trị 0% sẽ dẫn đến chỉ thành trên lớp trên được tạo. Dành cho mục đích thẩm mỹ hoặc chức năng , không phải để sửa các vấn đề như đùn dư." +msgid "Top surface expansion" +msgstr "" + +msgid "" +"Expands the top surfaces by this distance to connect distinct top surfaces and fill gaps.\n" +"Useful for cases where the top surface is interrupted by a raised feature, such as text on a plane.Expanding it removes the holes beneath these features and creates a continuous path with a better finish for printing on top.The expansion is applied to the original top surface, before any other processing such as bridging or overhang detection." +msgstr "" + +msgid "Top expansion wall margin" +msgstr "" + +msgid "" +"Using “Top surface expansion” may cause a surface that did not previously touch the model's outer walls to now do so.\n" +"This can cause contraction marks (such as the hull line) on the outer walls.\n" +"By adding a small margin, this contraction will not occur directly on the walls, thereby preventing a visible mark." +msgstr "" + +msgid "Top expansion direction" +msgstr "" + +msgid "" +"Direction in which the top surface expansion grows.\n" +" - Inward grows into the holes and gaps left by features rising from the middle of a top surface.\n" +" - Outward grows the outer edge of the surface, connecting surfaces separated by features that can divide a surface, such as a lattice pattern.\n" +" - Inward and Outward does both." +msgstr "" + +msgid "Inward and Outward" +msgstr "" + +msgid "Inward" +msgstr "" + +msgid "Outward" +msgstr "" + msgid "Bottom surface pattern" msgstr "Mẫu bề mặt dưới" @@ -12933,12 +12983,12 @@ msgstr "Mật độ infill thưa" msgid "Density of internal sparse infill, 100% turns all sparse infill into solid infill and internal solid infill pattern will be used." msgstr "Mật độ của infill thưa bên trong, 100% biến tất cả infill thưa thành infill đặc và mẫu infill đặc bên trong sẽ được sử dụng." -msgid "Align infill direction to model" -msgstr "Căn chỉnh hướng infill với model" +msgid "Align directions to model" +msgstr "" msgid "" -"Aligns infill, bridge, ironing and surface fill directions to follow the model's orientation on the build plate.\n" -"When enabled, directions rotate with the model to maintain optimal strength characteristics." +"Aligns infill, bridge, ironing, and top/bottom surface directions to follow the model's orientation on the build plate.\n" +"When enabled, these directions rotate together with the model so the printed features keep their intended orientation relative to the part, preserving optimal strength and surface characteristics regardless of how the model is placed." msgstr "" msgid "Insert solid layers" @@ -14667,6 +14717,10 @@ msgstr "Căn chỉnh" msgid "Aligned back" msgstr "Căn chỉnh sau" +# TODO: Review, changed by lang refactor. PR 14254 +msgid "Back" +msgstr "Sau" + msgid "Random" msgstr "Ngẫu nhiên" @@ -15027,6 +15081,18 @@ msgstr "Nạp tất cả extruder in" msgid "If enabled, all printing extruders will be primed at the front edge of the print bed at the start of the print." msgstr "Nếu được bật, tất cả extruder in sẽ được nạp ở mép trước của bàn in lúc bắt đầu in." +msgid "Toolchange ordering" +msgstr "" + +msgid "" +"Determines the order of tool changes on each layer.\n" +"- Default: Starts with the last used extruder to minimize tool changes.\n" +"- Cyclic: Uses a fixed tool sequence each layer. This sacrifices speed for better surface quality, as the extra toolchanges allow layers more time to cool." +msgstr "" + +msgid "Cyclic" +msgstr "" + msgid "Slice gap closing radius" msgstr "Bán kính đóng khe slice" @@ -15468,6 +15534,45 @@ msgstr "Độ dày vỏ trên" msgid "The number of top solid layers is increased when slicing if the thickness calculated by top shell layers is thinner than this value. This can avoid having too thin a shell when layer height is small. 0 means that this setting is disabled and thickness of top shell is determined simply by the number of top shell layers." msgstr "Số lượng lớp đặc trên được tăng lên khi slice nếu độ dày được tính bởi lớp vỏ trên mỏng hơn giá trị này. Điều này có thể tránh vỏ quá mỏng khi chiều cao lớp nhỏ. 0 có nghĩa là cài đặt này bị tắt và độ dày vỏ trên được xác định tuyệt đối bởi lớp vỏ trên." +msgid "Anisotropic surfaces" +msgstr "" + +msgid "" +"Anisotropic patterns on the top and bottom surfaces.\n" +"Co-directional printing mode will be applied. For certain patterns, omni-directional filling provides color dispersion when using multi-colored or silk plastics.\n" +"This option disable the gap fill.\n" +"This option can increase a printing time." +msgstr "" + +msgid "Separated infills" +msgstr "" + +msgid "" +"Centers the internal infill of each part on itself, as if it were sliced on its own, instead of on the whole assembly. Parts that touch or overlap are treated as one body and share a center; separate parts (or distinct 3D objects) each get their own.\n" +"Useful when an assembly groups several objects that should each keep a consistent, self-centered infill.\n" +"Affects line and grid patterns and rotation-template infills.\n" +"Patterns locked to global coordinates (Gyroid, Honeycomb, TPMS, ...) are unaffected." +msgstr "" + +msgid "Center surface pattern on" +msgstr "" + +msgid "" +"Chooses where the centering point of centered top/bottom surface patterns (Archimedean Chords, Octagram Spiral) is placed.\n" +" - Each Surface: centers the pattern on every individual surface region, so each island is symmetric on its own.\n" +" - Each Model: centers the pattern on each connected body. Parts that touch or overlap share one center; parts detached from the rest each get their own.\n" +" - Each Assembly: uses a single shared center for the whole object or assembly." +msgstr "" + +msgid "Each Surface" +msgstr "" + +msgid "Each Model" +msgstr "" + +msgid "Each Assembly" +msgstr "" + # TODO: Review, changed by lang refactor. PR 14254 msgid "This is the speed at which traveling is done." msgstr "Tốc độ di chuyển nhanh hơn và không có đùn." @@ -19474,6 +19579,19 @@ msgstr "" "Tránh cong vênh\n" "Bạn có biết rằng khi in vật liệu dễ cong vênh như ABS, tăng nhiệt độ bàn nóng một cách thích hợp có thể giảm xác suất cong vênh không?" +#~ msgctxt "Sync_Nozzle_AMS" +#~ msgid "Cancel" +#~ msgstr "Hủy" + +#~ msgid "Align infill direction to model" +#~ msgstr "Căn chỉnh hướng infill với model" + +#~ msgid "Print" +#~ msgstr "In" + +#~ msgid "in" +#~ msgstr "in" + #~ msgid "Object coordinates" #~ msgstr "Tọa độ vật thể" diff --git a/localization/i18n/zh_CN/OrcaSlicer_zh_CN.po b/localization/i18n/zh_CN/OrcaSlicer_zh_CN.po index 59b7c8c990..7c2496127e 100644 --- a/localization/i18n/zh_CN/OrcaSlicer_zh_CN.po +++ b/localization/i18n/zh_CN/OrcaSlicer_zh_CN.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: Slic3rPE\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-07-06 12:57-0300\n" +"POT-Creation-Date: 2026-07-12 12:27-0300\n" "PO-Revision-Date: 2026-06-11 12:37-0300\n" "Last-Translator: Handle \n" "Language-Team: \n" @@ -165,6 +165,12 @@ msgstr "填充" msgid "Gap Fill" msgstr "缝隙填充" +msgid "Vertical" +msgstr "垂直" + +msgid "Horizontal" +msgstr "水平" + #, boost-format msgid "Allows painting only on facets selected by: \"%1%\"" msgstr "绘制仅对由%1%选中的面片生效" @@ -260,12 +266,6 @@ msgstr "三角形" msgid "Height Range" msgstr "高度范围" -msgid "Vertical" -msgstr "垂直" - -msgid "Horizontal" -msgstr "水平" - msgid "Remove painted color" msgstr "移除已绘制的颜色" @@ -330,6 +330,7 @@ msgstr "Gizmo-旋转" msgid "Optimize orientation" msgstr "优化朝向" +msgctxt "Verb" msgid "Scale" msgstr "缩放" @@ -339,8 +340,9 @@ msgstr "缩放工具" msgid "Error: Please close all toolbar menus first" msgstr "错误:请先关闭所有工具栏菜单" +msgctxt "inches" msgid "in" -msgstr "在" +msgstr "" msgid "mm" msgstr "mm" @@ -373,6 +375,9 @@ msgstr "缩放比例" msgid "Object operations" msgstr "对象操作" +msgid "Scale" +msgstr "缩放" + # TODO: Review, changed by lang refactor. PR 14254 msgid "Volume operations" msgstr "零件操作" @@ -424,6 +429,10 @@ msgstr "重置当前旋转为打开旋转工具时的值" msgid "Reset current rotation to real zeros." msgstr "重置当前旋转为真实零位" +msgctxt "Noun" +msgid "Scale" +msgstr "缩放" + #. TRN - Input label. Be short as possible msgid "Size" msgstr "大小" @@ -3638,7 +3647,7 @@ msgstr "校准完成。如下图中的示例,请在您的热床上找到最均 msgid "Save" msgstr "保存" -# TODO: Review, changed by lang refactor. PR 14254 +msgctxt "Navigation" msgid "Back" msgstr "背面" @@ -5013,6 +5022,7 @@ msgstr "工具更换" msgid "Color change" msgstr "颜色更换" +msgctxt "Noun" msgid "Print" msgstr "打印" @@ -5177,11 +5187,15 @@ msgstr "避开挤出校准区域" msgid "Align to Y axis" msgstr "对齐到Y轴" -msgctxt "Camera" +msgctxt "Camera View" +msgid "Back" +msgstr "背面" + +msgctxt "Camera View" msgid "Left" msgstr "左" -msgctxt "Camera" +msgctxt "Camera View" msgid "Right" msgstr "右" @@ -5509,6 +5523,10 @@ msgstr "打印单盘" msgid "Export G-code file" msgstr "导出G-code文件" +msgctxt "Verb" +msgid "Print" +msgstr "打印" + msgid "Export plate sliced file" msgstr "导出单盘切片文件" @@ -5682,15 +5700,6 @@ msgstr "导出当前选择的预设" msgid "Export" msgstr "导出" -msgid "Sync Presets" -msgstr "同步预设" - -msgid "Pull and apply the latest presets from OrcaCloud" -msgstr "从 OrcaCloud 拉取并应用最新的预设" - -msgid "You must be logged in to sync presets from cloud." -msgstr "您必须登录后才能从云端同步预设。" - msgid "Quit" msgstr "退出程序" @@ -5807,6 +5816,15 @@ msgstr "视图" msgid "Preset Bundle" msgstr "预设包" +msgid "Sync Presets" +msgstr "同步预设" + +msgid "Pull and apply the latest presets from OrcaCloud" +msgstr "从 OrcaCloud 拉取并应用最新的预设" + +msgid "You must be logged in to sync presets from cloud." +msgstr "您必须登录后才能从云端同步预设。" + msgid "Syncing presets from cloud…" msgstr "正在从云端同步预设…" @@ -10310,12 +10328,8 @@ msgstr "成功同步喷嘴信息。" msgid "Successfully synchronized nozzle and AMS number information." msgstr "已成功同步喷嘴和 AMS 编号信息。" -msgid "Continue to sync filaments" -msgstr "继续同步耗材丝" - -msgctxt "Sync_Nozzle_AMS" -msgid "Cancel" -msgstr "取消" +msgid "Do you want to continue to sync filaments?" +msgstr "" msgid "Successfully synchronized filament color from printer." msgstr "已成功同步打印机的耗材丝颜色。" @@ -11643,19 +11657,11 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." msgstr "" -"外部桥接角度覆盖。\n" -"如果保持为零,每个具体桥接的桥接角度都会自动计算。\n" -"否则将按以下方式使用所提供的角度:\n" -" - 绝对坐标\n" -" - 绝对坐标 + 模型旋转:如果启用了“对齐填充方向到模型”\n" -" - 最佳自动角度 + 此值:如果启用了“相对桥接角度”\n" -"\n" -"使用 180° 表示绝对角度为零。" msgid "Internal bridge infill direction" msgstr "内部桥接填充方向" @@ -11665,19 +11671,11 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." msgstr "" -"内部桥接角度覆盖。\n" -"如果保持为零,每个具体桥接的桥接角度都会自动计算。\n" -"否则将按以下方式使用所提供的角度:\n" -" - 绝对坐标\n" -" - 绝对坐标 + 模型旋转:如果启用了“对齐填充方向到模型”\n" -" - 最佳自动角度 + 此值:如果启用了“相对桥接角度”\n" -"\n" -"使用 180° 表示绝对角度为零。" msgid "Relative bridge angle" msgstr "相对桥接角度" @@ -12436,6 +12434,42 @@ msgstr "" "100% 的值会创建一个完全实心、平滑的顶面。降低此值会根据所选的顶面图案生成有纹理的顶面。0% 的值将只生成顶层的墙。\n" "此选项仅为美观或功能性目的,而不是为了解决过量挤出等问题。" +msgid "Top surface expansion" +msgstr "" + +msgid "" +"Expands the top surfaces by this distance to connect distinct top surfaces and fill gaps.\n" +"Useful for cases where the top surface is interrupted by a raised feature, such as text on a plane.Expanding it removes the holes beneath these features and creates a continuous path with a better finish for printing on top.The expansion is applied to the original top surface, before any other processing such as bridging or overhang detection." +msgstr "" + +msgid "Top expansion wall margin" +msgstr "" + +msgid "" +"Using “Top surface expansion” may cause a surface that did not previously touch the model's outer walls to now do so.\n" +"This can cause contraction marks (such as the hull line) on the outer walls.\n" +"By adding a small margin, this contraction will not occur directly on the walls, thereby preventing a visible mark." +msgstr "" + +msgid "Top expansion direction" +msgstr "" + +msgid "" +"Direction in which the top surface expansion grows.\n" +" - Inward grows into the holes and gaps left by features rising from the middle of a top surface.\n" +" - Outward grows the outer edge of the surface, connecting surfaces separated by features that can divide a surface, such as a lattice pattern.\n" +" - Inward and Outward does both." +msgstr "" + +msgid "Inward and Outward" +msgstr "" + +msgid "Inward" +msgstr "" + +msgid "Outward" +msgstr "" + msgid "Bottom surface pattern" msgstr "底面图案" @@ -13109,15 +13143,13 @@ msgstr "稀疏填充密度" msgid "Density of internal sparse infill, 100% turns all sparse infill into solid infill and internal solid infill pattern will be used." msgstr "内部稀疏填充的密度,100%会将所有稀疏填充变为实心填充,并将使用内部实心填充图案。" -msgid "Align infill direction to model" -msgstr "对齐填充方向到模型" +msgid "Align directions to model" +msgstr "" msgid "" -"Aligns infill, bridge, ironing and surface fill directions to follow the model's orientation on the build plate.\n" -"When enabled, directions rotate with the model to maintain optimal strength characteristics." +"Aligns infill, bridge, ironing, and top/bottom surface directions to follow the model's orientation on the build plate.\n" +"When enabled, these directions rotate together with the model so the printed features keep their intended orientation relative to the part, preserving optimal strength and surface characteristics regardless of how the model is placed." msgstr "" -"使填充、桥接、熨烫和表面填充的方向跟随模型在打印板上的朝向。\n" -"启用后,这些方向会随模型一起旋转,以保持最佳的强度特性。" msgid "Insert solid layers" msgstr "插入实心层" @@ -14895,6 +14927,10 @@ msgstr "对齐" msgid "Aligned back" msgstr "背部对齐" +# TODO: Review, changed by lang refactor. PR 14254 +msgid "Back" +msgstr "背面" + msgid "Random" msgstr "随机" @@ -15261,6 +15297,18 @@ msgstr "所有挤出机画线" msgid "If enabled, all printing extruders will be primed at the front edge of the print bed at the start of the print." msgstr "如果启用,所有挤出机将在打印开始时在床前画线" +msgid "Toolchange ordering" +msgstr "" + +msgid "" +"Determines the order of tool changes on each layer.\n" +"- Default: Starts with the last used extruder to minimize tool changes.\n" +"- Cyclic: Uses a fixed tool sequence each layer. This sacrifices speed for better surface quality, as the extra toolchanges allow layers more time to cool." +msgstr "" + +msgid "Cyclic" +msgstr "" + msgid "Slice gap closing radius" msgstr "切片间隙闭合半径" @@ -15703,6 +15751,45 @@ msgstr "顶部壳体厚度" msgid "The number of top solid layers is increased when slicing if the thickness calculated by top shell layers is thinner than this value. This can avoid having too thin a shell when layer height is small. 0 means that this setting is disabled and thickness of top shell is determined simply by the number of top shell layers." msgstr "如果由顶部壳体层数算出的厚度小于这个数值,那么切片时将自动增加顶部壳体层数。这能够避免当层高很小时,顶部壳体过薄。0 表示关闭这个设置,同时顶部壳体的厚度完全由顶部壳体层数决定" +msgid "Anisotropic surfaces" +msgstr "" + +msgid "" +"Anisotropic patterns on the top and bottom surfaces.\n" +"Co-directional printing mode will be applied. For certain patterns, omni-directional filling provides color dispersion when using multi-colored or silk plastics.\n" +"This option disable the gap fill.\n" +"This option can increase a printing time." +msgstr "" + +msgid "Separated infills" +msgstr "" + +msgid "" +"Centers the internal infill of each part on itself, as if it were sliced on its own, instead of on the whole assembly. Parts that touch or overlap are treated as one body and share a center; separate parts (or distinct 3D objects) each get their own.\n" +"Useful when an assembly groups several objects that should each keep a consistent, self-centered infill.\n" +"Affects line and grid patterns and rotation-template infills.\n" +"Patterns locked to global coordinates (Gyroid, Honeycomb, TPMS, ...) are unaffected." +msgstr "" + +msgid "Center surface pattern on" +msgstr "" + +msgid "" +"Chooses where the centering point of centered top/bottom surface patterns (Archimedean Chords, Octagram Spiral) is placed.\n" +" - Each Surface: centers the pattern on every individual surface region, so each island is symmetric on its own.\n" +" - Each Model: centers the pattern on each connected body. Parts that touch or overlap share one center; parts detached from the rest each get their own.\n" +" - Each Assembly: uses a single shared center for the whole object or assembly." +msgstr "" + +msgid "Each Surface" +msgstr "" + +msgid "Each Model" +msgstr "" + +msgid "Each Assembly" +msgstr "" + # TODO: Review, changed by lang refactor. PR 14254 msgid "This is the speed at which traveling is done." msgstr "空驶的速度。空驶是无挤出量的快速移动。" @@ -19736,6 +19823,68 @@ msgstr "" "避免翘曲\n" "您知道吗?打印ABS这类易翘曲材料时,适当提高热床温度可以降低翘曲的概率。" +#~ msgid "Continue to sync filaments" +#~ msgstr "继续同步耗材丝" + +#~ msgctxt "Sync_Nozzle_AMS" +#~ msgid "Cancel" +#~ msgstr "取消" + +#, no-c-format, no-boost-format +#~ msgid "" +#~ "External Bridging angle override.\n" +#~ "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" +#~ "Otherwise the provided angle will be used according to:\n" +#~ " - The absolute coordinates\n" +#~ " - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +#~ " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" +#~ "\n" +#~ "Use 180° for zero absolute angle." +#~ msgstr "" +#~ "外部桥接角度覆盖。\n" +#~ "如果保持为零,每个具体桥接的桥接角度都会自动计算。\n" +#~ "否则将按以下方式使用所提供的角度:\n" +#~ " - 绝对坐标\n" +#~ " - 绝对坐标 + 模型旋转:如果启用了“对齐填充方向到模型”\n" +#~ " - 最佳自动角度 + 此值:如果启用了“相对桥接角度”\n" +#~ "\n" +#~ "使用 180° 表示绝对角度为零。" + +#~ msgid "" +#~ "Internal Bridging angle override.\n" +#~ "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" +#~ "Otherwise the provided angle will be used according to:\n" +#~ " - The absolute coordinates\n" +#~ " - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +#~ " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" +#~ "\n" +#~ "Use 180° for zero absolute angle." +#~ msgstr "" +#~ "内部桥接角度覆盖。\n" +#~ "如果保持为零,每个具体桥接的桥接角度都会自动计算。\n" +#~ "否则将按以下方式使用所提供的角度:\n" +#~ " - 绝对坐标\n" +#~ " - 绝对坐标 + 模型旋转:如果启用了“对齐填充方向到模型”\n" +#~ " - 最佳自动角度 + 此值:如果启用了“相对桥接角度”\n" +#~ "\n" +#~ "使用 180° 表示绝对角度为零。" + +#~ msgid "Align infill direction to model" +#~ msgstr "对齐填充方向到模型" + +#~ msgid "" +#~ "Aligns infill, bridge, ironing and surface fill directions to follow the model's orientation on the build plate.\n" +#~ "When enabled, directions rotate with the model to maintain optimal strength characteristics." +#~ msgstr "" +#~ "使填充、桥接、熨烫和表面填充的方向跟随模型在打印板上的朝向。\n" +#~ "启用后,这些方向会随模型一起旋转,以保持最佳的强度特性。" + +#~ msgid "Print" +#~ msgstr "打印" + +#~ msgid "in" +#~ msgstr "在" + #~ msgid "Object coordinates" #~ msgstr "物体坐标" diff --git a/localization/i18n/zh_TW/OrcaSlicer_zh_TW.po b/localization/i18n/zh_TW/OrcaSlicer_zh_TW.po index 2b8a0a7d23..f6a86e478e 100644 --- a/localization/i18n/zh_TW/OrcaSlicer_zh_TW.po +++ b/localization/i18n/zh_TW/OrcaSlicer_zh_TW.po @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: Orca Slicer\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-07-06 12:57-0300\n" +"POT-Creation-Date: 2026-07-12 12:27-0300\n" "PO-Revision-Date: 2025-11-28 13:48-0600\n" "Last-Translator: tntchn <15895303+tntchn@users.noreply.github.com>\n" "Language-Team: \n" @@ -168,6 +168,12 @@ msgstr "填充" msgid "Gap Fill" msgstr "縫隙填充" +msgid "Vertical" +msgstr "垂直" + +msgid "Horizontal" +msgstr "水平" + #, boost-format msgid "Allows painting only on facets selected by: \"%1%\"" msgstr "僅允許在由以下條件選擇的平面上進行繪製:「%1%」" @@ -263,12 +269,6 @@ msgstr "三角形" msgid "Height Range" msgstr "高度範圍" -msgid "Vertical" -msgstr "垂直" - -msgid "Horizontal" -msgstr "水平" - msgid "Remove painted color" msgstr "移除已繪製的顏色" @@ -333,6 +333,7 @@ msgstr "Gizmo-旋轉" msgid "Optimize orientation" msgstr "最佳化方向" +msgctxt "Verb" msgid "Scale" msgstr "縮放" @@ -342,8 +343,9 @@ msgstr "Gizmo 比例" msgid "Error: Please close all toolbar menus first" msgstr "錯誤:請先關閉所有工具欄選單" +msgctxt "inches" msgid "in" -msgstr "在" +msgstr "" msgid "mm" msgstr "mm" @@ -376,6 +378,9 @@ msgstr "縮放比例" msgid "Object operations" msgstr "物件操作" +msgid "Scale" +msgstr "縮放" + # TODO: Review, changed by lang refactor. PR 14254 msgid "Volume operations" msgstr "零件操作" @@ -427,6 +432,10 @@ msgstr "重設旋轉角度為開啟旋轉工具時的狀態。" msgid "Reset current rotation to real zeros." msgstr "將旋轉角度歸零" +msgctxt "Noun" +msgid "Scale" +msgstr "縮放" + #. TRN - Input label. Be short as possible msgid "Size" msgstr "尺寸" @@ -3649,7 +3658,7 @@ msgstr "校正完成。如下圖中的範例,請在您的熱床上找到最均 msgid "Save" msgstr "儲存" -# TODO: Review, changed by lang refactor. PR 14254 +msgctxt "Navigation" msgid "Back" msgstr "背面" @@ -5055,6 +5064,7 @@ msgstr "取代工具" msgid "Color change" msgstr "顏色更換" +msgctxt "Noun" msgid "Print" msgstr "列印" @@ -5219,11 +5229,15 @@ msgstr "避開擠出校正區域" msgid "Align to Y axis" msgstr "與 Y 軸對齊" -msgctxt "Camera" +msgctxt "Camera View" +msgid "Back" +msgstr "背面" + +msgctxt "Camera View" msgid "Left" msgstr "左" -msgctxt "Camera" +msgctxt "Camera View" msgid "Right" msgstr "右" @@ -5552,6 +5566,10 @@ msgstr "列印單一列印板" msgid "Export G-code file" msgstr "匯出 G-code 檔案" +msgctxt "Verb" +msgid "Print" +msgstr "列印" + msgid "Export plate sliced file" msgstr "匯出單一列印板切片檔案" @@ -5725,15 +5743,6 @@ msgstr "匯出目前選擇的設定檔" msgid "Export" msgstr "匯出" -msgid "Sync Presets" -msgstr "同步預設" - -msgid "Pull and apply the latest presets from OrcaCloud" -msgstr "從 OrcaCloud 拉取並套用最新的預設" - -msgid "You must be logged in to sync presets from cloud." -msgstr "您必須登入才能從雲端同步預設。" - msgid "Quit" msgstr "結束" @@ -5850,6 +5859,15 @@ msgstr "視角" msgid "Preset Bundle" msgstr "設定檔組" +msgid "Sync Presets" +msgstr "同步預設" + +msgid "Pull and apply the latest presets from OrcaCloud" +msgstr "從 OrcaCloud 拉取並套用最新的預設" + +msgid "You must be logged in to sync presets from cloud." +msgstr "您必須登入才能從雲端同步預設。" + msgid "Syncing presets from cloud…" msgstr "正在從雲端同步預設…" @@ -10374,12 +10392,8 @@ msgstr "成功同步噴嘴資訊。" msgid "Successfully synchronized nozzle and AMS number information." msgstr "成功同步噴嘴和 AMS 數量資訊。" -msgid "Continue to sync filaments" -msgstr "繼續同步線材" - -msgctxt "Sync_Nozzle_AMS" -msgid "Cancel" -msgstr "取消" +msgid "Do you want to continue to sync filaments?" +msgstr "" msgid "Successfully synchronized filament color from printer." msgstr "成功從列印設備同步線材顏色。" @@ -11710,19 +11724,11 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." msgstr "" -"外部橋接角度覆蓋。\n" -"若保持為零,將為每個特定橋接自動計算橋接角度。\n" -"否則將依下列方式使用所提供的角度:\n" -" - 絕對座標\n" -" - 絕對座標 + 模型旋轉:若已啟用「對齊填充方向至模型」\n" -" - 最佳自動角度 + 此數值:若已啟用「相對橋接角度」\n" -"\n" -"若要設定絕對角度為零,請使用 180°。" msgid "Internal bridge infill direction" msgstr "內部橋接結構的填充方向" @@ -11732,19 +11738,11 @@ msgid "" "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" -" - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +" - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" "\n" "Use 180° for zero absolute angle." msgstr "" -"內部橋接角度覆寫。\n" -"若保持為零,將為每個特定橋接自動計算橋接角度。\n" -"否則將依照下列方式使用所提供的角度:\n" -" - 絕對座標\n" -" - 絕對座標 + 模型旋轉:若啟用「將填充方向對齊模型」\n" -" - 最佳自動角度 + 此值:若啟用「相對橋接角度」\n" -"\n" -"使用 180° 表示零絕對角度。" msgid "Relative bridge angle" msgstr "相對橋接角度" @@ -12503,6 +12501,42 @@ msgstr "頂面密度" msgid "Density of top surface layer. A value of 100% creates a fully solid, smooth top layer. Reducing this value results in a textured top surface, according to the chosen top surface pattern. A value of 0% will result in only the walls on the top layer being created. Intended for aesthetic or functional purposes, not to fix issues such as over-extrusion." msgstr "頂面層的密度。100% 將建立完全實心且平滑的頂層。降低此數值會根據所選的頂面圖案產生紋理表面。0% 則只會建立頂層的牆體。此功能旨在實現美觀或功能需求,而非修正過擠等問題" +msgid "Top surface expansion" +msgstr "" + +msgid "" +"Expands the top surfaces by this distance to connect distinct top surfaces and fill gaps.\n" +"Useful for cases where the top surface is interrupted by a raised feature, such as text on a plane.Expanding it removes the holes beneath these features and creates a continuous path with a better finish for printing on top.The expansion is applied to the original top surface, before any other processing such as bridging or overhang detection." +msgstr "" + +msgid "Top expansion wall margin" +msgstr "" + +msgid "" +"Using “Top surface expansion” may cause a surface that did not previously touch the model's outer walls to now do so.\n" +"This can cause contraction marks (such as the hull line) on the outer walls.\n" +"By adding a small margin, this contraction will not occur directly on the walls, thereby preventing a visible mark." +msgstr "" + +msgid "Top expansion direction" +msgstr "" + +msgid "" +"Direction in which the top surface expansion grows.\n" +" - Inward grows into the holes and gaps left by features rising from the middle of a top surface.\n" +" - Outward grows the outer edge of the surface, connecting surfaces separated by features that can divide a surface, such as a lattice pattern.\n" +" - Inward and Outward does both." +msgstr "" + +msgid "Inward and Outward" +msgstr "" + +msgid "Inward" +msgstr "" + +msgid "Outward" +msgstr "" + msgid "Bottom surface pattern" msgstr "底面圖案" @@ -13163,15 +13197,13 @@ msgstr "稀疏填充密度" msgid "Density of internal sparse infill, 100% turns all sparse infill into solid infill and internal solid infill pattern will be used." msgstr "設定內部稀疏填充的密度,當密度為 100% 時,所有稀疏填充將變為實心填充,並套用內部實心填充的圖案" -msgid "Align infill direction to model" -msgstr "對齊填充方向至模型" +msgid "Align directions to model" +msgstr "" msgid "" -"Aligns infill, bridge, ironing and surface fill directions to follow the model's orientation on the build plate.\n" -"When enabled, directions rotate with the model to maintain optimal strength characteristics." +"Aligns infill, bridge, ironing, and top/bottom surface directions to follow the model's orientation on the build plate.\n" +"When enabled, these directions rotate together with the model so the printed features keep their intended orientation relative to the part, preserving optimal strength and surface characteristics regardless of how the model is placed." msgstr "" -"使填充、橋接、熨燙與表面填充的方向對齊,以跟隨模型在列印板上的方向。\n" -"啟用後,方向會隨模型一同旋轉,以維持最佳的強度特性。" msgid "Insert solid layers" msgstr "插入實心層" @@ -14956,6 +14988,10 @@ msgstr "對齊" msgid "Aligned back" msgstr "背部對齊" +# TODO: Review, changed by lang refactor. PR 14254 +msgid "Back" +msgstr "背面" + msgid "Random" msgstr "隨機" @@ -15311,6 +15347,18 @@ msgstr "所有擠出機畫線" msgid "If enabled, all printing extruders will be primed at the front edge of the print bed at the start of the print." msgstr "如果啟用,所有擠出機將在列印開始時在列印板前方畫線。" +msgid "Toolchange ordering" +msgstr "" + +msgid "" +"Determines the order of tool changes on each layer.\n" +"- Default: Starts with the last used extruder to minimize tool changes.\n" +"- Cyclic: Uses a fixed tool sequence each layer. This sacrifices speed for better surface quality, as the extra toolchanges allow layers more time to cool." +msgstr "" + +msgid "Cyclic" +msgstr "" + msgid "Slice gap closing radius" msgstr "切片間隙閉合半徑" @@ -15751,6 +15799,45 @@ msgstr "頂部外殼厚度" msgid "The number of top solid layers is increased when slicing if the thickness calculated by top shell layers is thinner than this value. This can avoid having too thin a shell when layer height is small. 0 means that this setting is disabled and thickness of top shell is determined simply by the number of top shell layers." msgstr "當切片時,如果通過頂部殼層計算的厚度小於設定值,將自動增加頂部實心層的數量,以避免層高較小時頂部殼層過薄。若設為 0,則停用此功能,頂部殼層厚度完全由設定的頂部殼層數決定" +msgid "Anisotropic surfaces" +msgstr "" + +msgid "" +"Anisotropic patterns on the top and bottom surfaces.\n" +"Co-directional printing mode will be applied. For certain patterns, omni-directional filling provides color dispersion when using multi-colored or silk plastics.\n" +"This option disable the gap fill.\n" +"This option can increase a printing time." +msgstr "" + +msgid "Separated infills" +msgstr "" + +msgid "" +"Centers the internal infill of each part on itself, as if it were sliced on its own, instead of on the whole assembly. Parts that touch or overlap are treated as one body and share a center; separate parts (or distinct 3D objects) each get their own.\n" +"Useful when an assembly groups several objects that should each keep a consistent, self-centered infill.\n" +"Affects line and grid patterns and rotation-template infills.\n" +"Patterns locked to global coordinates (Gyroid, Honeycomb, TPMS, ...) are unaffected." +msgstr "" + +msgid "Center surface pattern on" +msgstr "" + +msgid "" +"Chooses where the centering point of centered top/bottom surface patterns (Archimedean Chords, Octagram Spiral) is placed.\n" +" - Each Surface: centers the pattern on every individual surface region, so each island is symmetric on its own.\n" +" - Each Model: centers the pattern on each connected body. Parts that touch or overlap share one center; parts detached from the rest each get their own.\n" +" - Each Assembly: uses a single shared center for the whole object or assembly." +msgstr "" + +msgid "Each Surface" +msgstr "" + +msgid "Each Model" +msgstr "" + +msgid "Each Assembly" +msgstr "" + # TODO: Review, changed by lang refactor. PR 14254 msgid "This is the speed at which traveling is done." msgstr "空駛的速度。空駛是無擠出量的快速移動" @@ -19807,6 +19894,68 @@ msgstr "" "您知道嗎?當列印容易翹曲的材料(如 ABS)時,適當提高熱床溫度\n" "可以降低翹曲的機率。" +#~ msgid "Continue to sync filaments" +#~ msgstr "繼續同步線材" + +#~ msgctxt "Sync_Nozzle_AMS" +#~ msgid "Cancel" +#~ msgstr "取消" + +#, no-c-format, no-boost-format +#~ msgid "" +#~ "External Bridging angle override.\n" +#~ "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" +#~ "Otherwise the provided angle will be used according to:\n" +#~ " - The absolute coordinates\n" +#~ " - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +#~ " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" +#~ "\n" +#~ "Use 180° for zero absolute angle." +#~ msgstr "" +#~ "外部橋接角度覆蓋。\n" +#~ "若保持為零,將為每個特定橋接自動計算橋接角度。\n" +#~ "否則將依下列方式使用所提供的角度:\n" +#~ " - 絕對座標\n" +#~ " - 絕對座標 + 模型旋轉:若已啟用「對齊填充方向至模型」\n" +#~ " - 最佳自動角度 + 此數值:若已啟用「相對橋接角度」\n" +#~ "\n" +#~ "若要設定絕對角度為零,請使用 180°。" + +#~ msgid "" +#~ "Internal Bridging angle override.\n" +#~ "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" +#~ "Otherwise the provided angle will be used according to:\n" +#~ " - The absolute coordinates\n" +#~ " - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" +#~ " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n" +#~ "\n" +#~ "Use 180° for zero absolute angle." +#~ msgstr "" +#~ "內部橋接角度覆寫。\n" +#~ "若保持為零,將為每個特定橋接自動計算橋接角度。\n" +#~ "否則將依照下列方式使用所提供的角度:\n" +#~ " - 絕對座標\n" +#~ " - 絕對座標 + 模型旋轉:若啟用「將填充方向對齊模型」\n" +#~ " - 最佳自動角度 + 此值:若啟用「相對橋接角度」\n" +#~ "\n" +#~ "使用 180° 表示零絕對角度。" + +#~ msgid "Align infill direction to model" +#~ msgstr "對齊填充方向至模型" + +#~ msgid "" +#~ "Aligns infill, bridge, ironing and surface fill directions to follow the model's orientation on the build plate.\n" +#~ "When enabled, directions rotate with the model to maintain optimal strength characteristics." +#~ msgstr "" +#~ "使填充、橋接、熨燙與表面填充的方向對齊,以跟隨模型在列印板上的方向。\n" +#~ "啟用後,方向會隨模型一同旋轉,以維持最佳的強度特性。" + +#~ msgid "Print" +#~ msgstr "列印" + +#~ msgid "in" +#~ msgstr "在" + #~ msgid "Object coordinates" #~ msgstr "物件座標" diff --git a/resources/fonts/HarmonyOS_Sans_SC_Bold.ttf b/resources/fonts/HarmonyOS_Sans_SC_Bold.ttf index 4e2fa07f88..f5a6b6ff63 100644 Binary files a/resources/fonts/HarmonyOS_Sans_SC_Bold.ttf and b/resources/fonts/HarmonyOS_Sans_SC_Bold.ttf differ diff --git a/resources/fonts/HarmonyOS_Sans_SC_Regular.ttf b/resources/fonts/HarmonyOS_Sans_SC_Regular.ttf index af95249830..a3a2a1231c 100644 Binary files a/resources/fonts/HarmonyOS_Sans_SC_Regular.ttf and b/resources/fonts/HarmonyOS_Sans_SC_Regular.ttf differ diff --git a/resources/images/advanced_option3.svg b/resources/images/advanced_option3.svg index d60800be11..20ba7ba0c7 100644 --- a/resources/images/advanced_option3.svg +++ b/resources/images/advanced_option3.svg @@ -1,3 +1,3 @@ - + diff --git a/resources/images/advanced_option4.svg b/resources/images/advanced_option4.svg index c4bf14ed8f..9b3aedbf0a 100644 --- a/resources/images/advanced_option4.svg +++ b/resources/images/advanced_option4.svg @@ -1,3 +1,3 @@ - + diff --git a/resources/images/param_z_contouring.svg b/resources/images/param_z_contouring.svg new file mode 100644 index 0000000000..38fc8f1a00 --- /dev/null +++ b/resources/images/param_z_contouring.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/shaders/110/gouraud.fs b/resources/shaders/110/gouraud.fs index e602d6067d..960b797c38 100644 --- a/resources/shaders/110/gouraud.fs +++ b/resources/shaders/110/gouraud.fs @@ -50,6 +50,15 @@ uniform PrintVolumeDetection print_volume; uniform float z_far; uniform float z_near; +// Depth-based shadow map (object-on-object and self shadows). shadow_intensity == 0 disables it. +uniform sampler2D shadow_map; +uniform mat4 shadow_light_vp; +uniform float shadow_intensity; +uniform float shadow_map_texel; + +// LIGHT_TOP_DIR in eye space (matches the diffuse light used for shading in gouraud.vs). +const vec3 SHADOW_LIGHT_DIR = vec3(-0.4574957, 0.4574957, 0.7624929); + varying vec3 clipping_planes_dots; varying float color_clip_plane_dot; @@ -125,6 +134,35 @@ float DetectSilho(vec2 fragCoord) ); } +// Returns a lighting multiplier in [1 - shadow_intensity, 1]: < 1 where the fragment is +// occluded from the light in the shadow map. 3x3 PCF softens the edges. +float shadow_shade() +{ + if (shadow_intensity <= 0.0) + return 1.0; + + vec4 lp = shadow_light_vp * world_pos; + vec3 proj = lp.xyz / lp.w; + proj = proj * 0.5 + 0.5; + if (proj.z > 1.0) + return 1.0; + + // Slope-scaled depth bias: larger where the surface grazes / faces away from the light. This + // suppresses self-shadow acne without discarding real shadows cast by other objects onto + // back-facing surfaces (e.g. the shaded back/tip of a cone sitting inside a larger shadow). + float NdotL = dot(normalize(eye_normal), SHADOW_LIGHT_DIR); + float bias = mix(0.0004, 0.004, clamp(1.0 - NdotL, 0.0, 1.0)); + // 5x5 PCF: softens shadow edges into a smooth penumbra and blurs residual facet acne. + float sum = 0.0; + for (int x = -2; x <= 2; ++x) { + for (int y = -2; y <= 2; ++y) { + float closest = texture2D(shadow_map, proj.xy + vec2(float(x), float(y)) * shadow_map_texel).r; + sum += (proj.z - bias > closest) ? 1.0 : 0.0; + } + } + return 1.0 - shadow_intensity * (sum / 25.0); +} + void main() { if (any(lessThan(clipping_planes_dots, ZERO))) @@ -166,9 +204,11 @@ void main() } color.rgb = (any(lessThan(pv_check_min, ZERO)) || any(greaterThan(pv_check_max, ZERO))) ? mix(color.rgb, ZERO, 0.3333) : color.rgb; + float shade = shadow_shade(); + //BBS: add outline_color if (is_outline) { - color = vec4(vec3(intensity.y) + color.rgb * intensity.x, color.a); + color = vec4((vec3(intensity.y) + color.rgb * intensity.x) * shade, color.a); vec2 fragCoord = gl_FragCoord.xy; float s = DetectSilho(fragCoord); // Makes silhouettes thicker. @@ -176,13 +216,13 @@ void main() { s = max(s, DetectSilho(fragCoord.xy + vec2(i, 0))); s = max(s, DetectSilho(fragCoord.xy + vec2(0, i))); - } + } gl_FragColor = vec4(mix(color.rgb, getBackfaceColor(color.rgb), s), color.a); } #ifdef ENABLE_ENVIRONMENT_MAP else if (use_environment_tex) - gl_FragColor = vec4(0.45 * texture(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + 0.8 * color.rgb * intensity.x, color.a); + gl_FragColor = vec4((0.45 * texture(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + 0.8 * color.rgb * intensity.x) * shade, color.a); #endif else - gl_FragColor = vec4(vec3(intensity.y) + color.rgb * intensity.x, color.a); + gl_FragColor = vec4((vec3(intensity.y) + color.rgb * intensity.x) * shade, color.a); } \ No newline at end of file diff --git a/resources/shaders/110/phong.fs b/resources/shaders/110/phong.fs index a0c6372ca5..a5c1c5b8ab 100644 --- a/resources/shaders/110/phong.fs +++ b/resources/shaders/110/phong.fs @@ -65,6 +65,12 @@ uniform float z_far; uniform float z_near; uniform bool enable_ssao; +// Depth-based shadow map (object-on-object and self shadows). shadow_intensity == 0 disables it. +uniform sampler2D shadow_map; +uniform mat4 shadow_light_vp; +uniform float shadow_intensity; +uniform float shadow_map_texel; + varying vec3 clipping_planes_dots; varying float color_clip_plane_dot; @@ -167,10 +173,39 @@ vec3 compute_window_reflection(vec3 normal, vec3 view_dir) float intensity = window_light * bars * (0.15 + 0.15 * fresnel) * facing; intensity = clamp(intensity, 0.0, 0.25); - + return vec3(intensity); } +// Returns a lighting multiplier in [1 - shadow_intensity, 1]: < 1 where the fragment is +// occluded from the light in the shadow map. 3x3 PCF softens the edges. +float shadow_shade() +{ + if (shadow_intensity <= 0.0) + return 1.0; + + vec4 lp = shadow_light_vp * world_pos; + vec3 proj = lp.xyz / lp.w; + proj = proj * 0.5 + 0.5; + if (proj.z > 1.0) + return 1.0; + + // Slope-scaled depth bias: larger where the surface grazes / faces away from the light. This + // suppresses self-shadow acne without discarding real shadows cast by other objects onto + // back-facing surfaces (e.g. the shaded back/tip of a cone sitting inside a larger shadow). + float NdotL = dot(normalize(eye_normal), LIGHT_TOP_DIR); + float bias = mix(0.0004, 0.004, clamp(1.0 - NdotL, 0.0, 1.0)); + // 5x5 PCF: softens shadow edges into a smooth penumbra and blurs residual facet acne. + float sum = 0.0; + for (int x = -2; x <= 2; ++x) { + for (int y = -2; y <= 2; ++y) { + float closest = texture2D(shadow_map, proj.xy + vec2(float(x), float(y)) * shadow_map_texel).r; + sum += (proj.z - bias > closest) ? 1.0 : 0.0; + } + } + return 1.0 - shadow_intensity * (sum / 25.0); +} + void main() { if (any(lessThan(clipping_planes_dots, ZERO))) @@ -226,8 +261,10 @@ void main() // SSAO is applied in post-process pass. Keep base lighting unchanged here. + float shade = shadow_shade(); + if (is_outline) { - vec3 shaded_rgb = (vec3(specular) + window_reflection + color.rgb * diffuse) * PHONG_BRIGHTNESS; + vec3 shaded_rgb = (vec3(specular) + window_reflection + color.rgb * diffuse) * PHONG_BRIGHTNESS * shade; vec4 shaded_color = vec4(clamp(shaded_rgb, vec3(0.0), vec3(1.0)), color.a); vec2 fragCoord = gl_FragCoord.xy; float s = DetectSilho(fragCoord); @@ -240,8 +277,8 @@ void main() } #ifdef ENABLE_ENVIRONMENT_MAP else if (use_environment_tex) - gl_FragColor = vec4(clamp((0.45 * texture2D(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + window_reflection + 0.8 * color.rgb * diffuse) * PHONG_BRIGHTNESS, vec3(0.0), vec3(1.0)), color.a); + gl_FragColor = vec4(clamp((0.45 * texture2D(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + window_reflection + 0.8 * color.rgb * diffuse) * PHONG_BRIGHTNESS * shade, vec3(0.0), vec3(1.0)), color.a); #endif else - gl_FragColor = vec4(clamp((vec3(specular) + window_reflection + color.rgb * diffuse) * PHONG_BRIGHTNESS, vec3(0.0), vec3(1.0)), color.a); + gl_FragColor = vec4(clamp((vec3(specular) + window_reflection + color.rgb * diffuse) * PHONG_BRIGHTNESS * shade, vec3(0.0), vec3(1.0)), color.a); } \ No newline at end of file diff --git a/resources/shaders/110/printbed_shadow.fs b/resources/shaders/110/printbed_shadow.fs new file mode 100644 index 0000000000..a4fd6801dd --- /dev/null +++ b/resources/shaders/110/printbed_shadow.fs @@ -0,0 +1,40 @@ +#version 110 + +// Draws the build-plate as a receiver of the same depth shadow map used for object/self shadows, +// so the plate, objects, and self-shadows all come from one unified technique. +uniform sampler2D shadow_map; +uniform mat4 shadow_light_vp; +uniform float shadow_intensity; +uniform float shadow_map_texel; + +varying vec4 world_pos; + +// Fraction of the 5x5 PCF kernel occluded from the light. Matches the object shadow shader. +float shadow_occlusion() +{ + vec4 lp = shadow_light_vp * world_pos; + vec3 proj = lp.xyz / lp.w; + proj = proj * 0.5 + 0.5; + if (proj.z > 1.0) + return 0.0; + + // The plate is a pure receiver (never rendered into the shadow map), so a tiny constant + // bias for numerical safety is enough here. + float bias = 0.0004; + float sum = 0.0; + for (int x = -2; x <= 2; ++x) { + for (int y = -2; y <= 2; ++y) { + float closest = texture2D(shadow_map, proj.xy + vec2(float(x), float(y)) * shadow_map_texel).r; + sum += (proj.z - bias > closest) ? 1.0 : 0.0; + } + } + return sum / 25.0; +} + +void main() +{ + float occ = shadow_occlusion(); + if (occ <= 0.0) + discard; + gl_FragColor = vec4(0.0, 0.0, 0.0, shadow_intensity * occ); +} diff --git a/resources/shaders/110/printbed_shadow.vs b/resources/shaders/110/printbed_shadow.vs new file mode 100644 index 0000000000..d004fac7c9 --- /dev/null +++ b/resources/shaders/110/printbed_shadow.vs @@ -0,0 +1,16 @@ +#version 110 + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; + +attribute vec3 v_position; + +// The plate mask quad is authored directly in world coordinates (z = 0 plane), +// so v_position is already the world position of the fragment. +varying vec4 world_pos; + +void main() +{ + world_pos = vec4(v_position, 1.0); + gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0); +} diff --git a/resources/shaders/140/gouraud.fs b/resources/shaders/140/gouraud.fs index bbfb76f7a1..efd7eaff2a 100644 --- a/resources/shaders/140/gouraud.fs +++ b/resources/shaders/140/gouraud.fs @@ -49,6 +49,15 @@ uniform PrintVolumeDetection print_volume; uniform float z_far; uniform float z_near; +// Depth-based shadow map (object-on-object and self shadows). shadow_intensity == 0 disables it. +uniform sampler2D shadow_map; +uniform mat4 shadow_light_vp; +uniform float shadow_intensity; +uniform float shadow_map_texel; + +// LIGHT_TOP_DIR in eye space (matches the diffuse light used for shading in gouraud.vs). +const vec3 SHADOW_LIGHT_DIR = vec3(-0.4574957, 0.4574957, 0.7624929); + in vec3 clipping_planes_dots; in float color_clip_plane_dot; @@ -124,6 +133,35 @@ float DetectSilho(vec2 fragCoord) ); } +// Returns a lighting multiplier in [1 - shadow_intensity, 1]: < 1 where the fragment is +// occluded from the light in the shadow map. 3x3 PCF softens the edges. +float shadow_shade() +{ + if (shadow_intensity <= 0.0) + return 1.0; + + vec4 lp = shadow_light_vp * world_pos; + vec3 proj = lp.xyz / lp.w; + proj = proj * 0.5 + 0.5; + if (proj.z > 1.0) + return 1.0; + + // Slope-scaled depth bias: larger where the surface grazes / faces away from the light. This + // suppresses self-shadow acne without discarding real shadows cast by other objects onto + // back-facing surfaces (e.g. the shaded back/tip of a cone sitting inside a larger shadow). + float NdotL = dot(normalize(eye_normal), SHADOW_LIGHT_DIR); + float bias = mix(0.0004, 0.004, clamp(1.0 - NdotL, 0.0, 1.0)); + // 5x5 PCF: softens shadow edges into a smooth penumbra and blurs residual facet acne. + float sum = 0.0; + for (int x = -2; x <= 2; ++x) { + for (int y = -2; y <= 2; ++y) { + float closest = texture(shadow_map, proj.xy + vec2(float(x), float(y)) * shadow_map_texel).r; + sum += (proj.z - bias > closest) ? 1.0 : 0.0; + } + } + return 1.0 - shadow_intensity * (sum / 25.0); +} + out vec4 out_color; void main() @@ -167,9 +205,11 @@ void main() } color.rgb = (any(lessThan(pv_check_min, ZERO)) || any(greaterThan(pv_check_max, ZERO))) ? mix(color.rgb, ZERO, 0.3333) : color.rgb; + float shade = shadow_shade(); + //BBS: add outline_color if (is_outline) { - color = vec4(vec3(intensity.y) + color.rgb * intensity.x, color.a); + color = vec4((vec3(intensity.y) + color.rgb * intensity.x) * shade, color.a); vec2 fragCoord = gl_FragCoord.xy; float s = DetectSilho(fragCoord); // Makes silhouettes thicker. @@ -177,13 +217,13 @@ void main() { s = max(s, DetectSilho(fragCoord.xy + vec2(i, 0))); s = max(s, DetectSilho(fragCoord.xy + vec2(0, i))); - } + } out_color = vec4(mix(color.rgb, getBackfaceColor(color.rgb), s), color.a); } #ifdef ENABLE_ENVIRONMENT_MAP else if (use_environment_tex) - out_color = vec4(0.45 * texture(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + 0.8 * color.rgb * intensity.x, color.a); + out_color = vec4((0.45 * texture(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + 0.8 * color.rgb * intensity.x) * shade, color.a); #endif else - out_color = vec4(vec3(intensity.y) + color.rgb * intensity.x, color.a); + out_color = vec4((vec3(intensity.y) + color.rgb * intensity.x) * shade, color.a); } \ No newline at end of file diff --git a/resources/shaders/140/phong.fs b/resources/shaders/140/phong.fs index d7456663ec..894e3eb863 100644 --- a/resources/shaders/140/phong.fs +++ b/resources/shaders/140/phong.fs @@ -65,6 +65,12 @@ uniform float z_far; uniform float z_near; uniform bool enable_ssao; +// Depth-based shadow map (object-on-object and self shadows). shadow_intensity == 0 disables it. +uniform sampler2D shadow_map; +uniform mat4 shadow_light_vp; +uniform float shadow_intensity; +uniform float shadow_map_texel; + in vec3 clipping_planes_dots; in float color_clip_plane_dot; @@ -170,11 +176,40 @@ vec3 compute_window_reflection(vec3 normal, vec3 view_dir) float intensity = window_light * bars * (0.15 + 0.15 * fresnel) * facing; - intensity = clamp(intensity, 0.0, 0.25); - + intensity = clamp(intensity, 0.0, 0.25); + return vec3(intensity); } +// Returns a lighting multiplier in [1 - shadow_intensity, 1]: < 1 where the fragment is +// occluded from the light in the shadow map. 3x3 PCF softens the edges. +float shadow_shade() +{ + if (shadow_intensity <= 0.0) + return 1.0; + + vec4 lp = shadow_light_vp * world_pos; + vec3 proj = lp.xyz / lp.w; + proj = proj * 0.5 + 0.5; + if (proj.z > 1.0) + return 1.0; + + // Slope-scaled depth bias: larger where the surface grazes / faces away from the light. This + // suppresses self-shadow acne without discarding real shadows cast by other objects onto + // back-facing surfaces (e.g. the shaded back/tip of a cone sitting inside a larger shadow). + float NdotL = dot(normalize(eye_normal), LIGHT_TOP_DIR); + float bias = mix(0.0004, 0.004, clamp(1.0 - NdotL, 0.0, 1.0)); + // 5x5 PCF: softens shadow edges into a smooth penumbra and blurs residual facet acne. + float sum = 0.0; + for (int x = -2; x <= 2; ++x) { + for (int y = -2; y <= 2; ++y) { + float closest = texture(shadow_map, proj.xy + vec2(float(x), float(y)) * shadow_map_texel).r; + sum += (proj.z - bias > closest) ? 1.0 : 0.0; + } + } + return 1.0 - shadow_intensity * (sum / 25.0); +} + void main() { if (any(lessThan(clipping_planes_dots, ZERO))) @@ -230,8 +265,10 @@ void main() // SSAO is applied in post-process pass. Keep base lighting unchanged here. + float shade = shadow_shade(); + if (is_outline) { - vec3 shaded_rgb = (vec3(specular) + window_reflection + color.rgb * diffuse) * PHONG_BRIGHTNESS; + vec3 shaded_rgb = (vec3(specular) + window_reflection + color.rgb * diffuse) * PHONG_BRIGHTNESS * shade; vec4 shaded_color = vec4(clamp(shaded_rgb, vec3(0.0), vec3(1.0)), color.a); vec2 fragCoord = gl_FragCoord.xy; float s = DetectSilho(fragCoord); @@ -244,8 +281,8 @@ void main() } #ifdef ENABLE_ENVIRONMENT_MAP else if (use_environment_tex) - out_color = vec4(clamp((0.45 * texture(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + window_reflection + 0.8 * color.rgb * diffuse) * PHONG_BRIGHTNESS, vec3(0.0), vec3(1.0)), color.a); + out_color = vec4(clamp((0.45 * texture(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + window_reflection + 0.8 * color.rgb * diffuse) * PHONG_BRIGHTNESS * shade, vec3(0.0), vec3(1.0)), color.a); #endif else - out_color = vec4(clamp((vec3(specular) + window_reflection + color.rgb * diffuse) * PHONG_BRIGHTNESS, vec3(0.0), vec3(1.0)), color.a); + out_color = vec4(clamp((vec3(specular) + window_reflection + color.rgb * diffuse) * PHONG_BRIGHTNESS * shade, vec3(0.0), vec3(1.0)), color.a); } \ No newline at end of file diff --git a/resources/shaders/140/printbed_shadow.fs b/resources/shaders/140/printbed_shadow.fs new file mode 100644 index 0000000000..650d88950e --- /dev/null +++ b/resources/shaders/140/printbed_shadow.fs @@ -0,0 +1,42 @@ +#version 140 + +// Draws the build-plate as a receiver of the same depth shadow map used for object/self shadows, +// so the plate, objects, and self-shadows all come from one unified technique. +uniform sampler2D shadow_map; +uniform mat4 shadow_light_vp; +uniform float shadow_intensity; +uniform float shadow_map_texel; + +in vec4 world_pos; + +out vec4 out_color; + +// Fraction of the 5x5 PCF kernel occluded from the light. Matches the object shadow shader. +float shadow_occlusion() +{ + vec4 lp = shadow_light_vp * world_pos; + vec3 proj = lp.xyz / lp.w; + proj = proj * 0.5 + 0.5; + if (proj.z > 1.0) + return 0.0; + + // The plate is a pure receiver (never rendered into the shadow map), so a tiny constant + // bias for numerical safety is enough here. + float bias = 0.0004; + float sum = 0.0; + for (int x = -2; x <= 2; ++x) { + for (int y = -2; y <= 2; ++y) { + float closest = texture(shadow_map, proj.xy + vec2(float(x), float(y)) * shadow_map_texel).r; + sum += (proj.z - bias > closest) ? 1.0 : 0.0; + } + } + return sum / 25.0; +} + +void main() +{ + float occ = shadow_occlusion(); + if (occ <= 0.0) + discard; + out_color = vec4(0.0, 0.0, 0.0, shadow_intensity * occ); +} diff --git a/resources/shaders/140/printbed_shadow.vs b/resources/shaders/140/printbed_shadow.vs new file mode 100644 index 0000000000..297e9e9a12 --- /dev/null +++ b/resources/shaders/140/printbed_shadow.vs @@ -0,0 +1,16 @@ +#version 140 + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; + +in vec3 v_position; + +// The plate mask quad is authored directly in world coordinates (z = 0 plane), +// so v_position is already the world position of the fragment. +out vec4 world_pos; + +void main() +{ + world_pos = vec4(v_position, 1.0); + gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0); +} diff --git a/scripts/run_gettext.bat b/scripts/run_gettext.bat index fb4a72d36f..ced22a2c73 100644 --- a/scripts/run_gettext.bat +++ b/scripts/run_gettext.bat @@ -23,7 +23,7 @@ if %FULL_MODE%==1 ( call :prepareGettextList "%list_file%" "%filtered_list%" "%missing_list%" if "!has_sources!"=="1" ( if not exist "%generated_i18n%" mkdir "%generated_i18n%" - .\tools\xgettext.exe --keyword=L --keyword=_L --keyword=_u8L --keyword=L_CONTEXT:1,2c --keyword=_L_PLURAL:1,2 --add-comments=TRN --from-code=UTF-8 --no-location --debug --boost --no-wrap -f "%filtered_list%" -o "%generated_pot%" + .\tools\xgettext.exe --keyword=L --keyword=_L --keyword=_u8L --keyword=L_CONTEXT:1,2c --keyword=_CTX:1,2c --keyword=_CTX_utf8:1,2c --keyword=_L_PLURAL:1,2 --add-comments=TRN --from-code=UTF-8 --no-location --debug --boost --no-wrap -f "%filtered_list%" -o "%generated_pot%" if errorlevel 1 ( set "script_exit_code=1" ) else ( diff --git a/scripts/run_gettext.sh b/scripts/run_gettext.sh index 9fdf6503f0..e956e441af 100755 --- a/scripts/run_gettext.sh +++ b/scripts/run_gettext.sh @@ -85,7 +85,7 @@ if $FULL_MODE; then generated_pot_file="${generated_i18n_dir}/OrcaSlicer.pot" mkdir -p "$generated_i18n_dir" - xgettext --keyword=L --keyword=_L --keyword=_u8L --keyword=L_CONTEXT:1,2c --keyword=_L_PLURAL:1,2 --add-comments=TRN --from-code=UTF-8 --no-location --debug --boost --no-wrap -f "$filtered_list" -o "$generated_pot_file" + xgettext --keyword=L --keyword=_L --keyword=_u8L --keyword=L_CONTEXT:1,2c --keyword=_CTX:1,2c --keyword=_CTX_utf8:1,2c --keyword=_L_PLURAL:1,2 --add-comments=TRN --from-code=UTF-8 --no-location --debug --boost --no-wrap -f "$filtered_list" -o "$generated_pot_file" python3 scripts/HintsToPot.py ./resources "$generated_i18n_dir" if [ -f "$pot_file" ] && files_equal_ignoring_pot_date "$pot_file" "$generated_pot_file"; then diff --git a/scripts/run_unit_tests.sh b/scripts/run_unit_tests.sh index bd9e969227..f6a01dd3e0 100755 --- a/scripts/run_unit_tests.sh +++ b/scripts/run_unit_tests.sh @@ -4,11 +4,21 @@ # It should only require the directories build/tests, scripts/, and tests/ to function, # and cmake (with ctest) installed. # (otherwise, update the workflow too, but try to avoid to keep things self-contained) +# +# Usage: run_unit_tests.sh [TEST_DIR] [BUILD_CONFIG] +# TEST_DIR directory containing the built tests (default: build/tests) +# BUILD_CONFIG configuration to run; required for multi-config generators +# (Windows/macOS), harmless/omitted for single-config (Linux). ROOT_DIR="$(dirname "$0")/.." cd "${ROOT_DIR}" || exit 1 +TEST_DIR="${1:-build/tests}" +BUILD_CONFIG="${2:-}" + # Run the whole suite, excluding tests tagged [NotWorking]. # --no-tests=error fails the job if the filter matches nothing (instead of passing green). -ctest --test-dir build/tests -LE "NotWorking" --no-tests=error --output-junit "$(pwd)/ctest_results.xml" --output-on-failure -j +args=(--test-dir "${TEST_DIR}" -LE "NotWorking" --no-tests=error --output-junit "$(pwd)/ctest_results.xml" --output-on-failure -j) +[ -n "${BUILD_CONFIG}" ] && args+=(--build-config "${BUILD_CONFIG}") +ctest "${args[@]}" diff --git a/src/OrcaSlicer.cpp b/src/OrcaSlicer.cpp index 7e1341ac18..311451f774 100644 --- a/src/OrcaSlicer.cpp +++ b/src/OrcaSlicer.cpp @@ -7359,7 +7359,7 @@ bool CLI::export_project(Model *model, std::string& path, PlateDataPtrs &partpla bool success = false; StoreParams store_params; - store_params.path = path.c_str(); + store_params.path = path; store_params.model = model; store_params.plate_data_list = partplate_data; store_params.project_presets = project_presets; diff --git a/src/libslic3r/Arachne/SkeletalTrapezoidation.cpp b/src/libslic3r/Arachne/SkeletalTrapezoidation.cpp index 2d2cf9896d..da5c7357c1 100644 --- a/src/libslic3r/Arachne/SkeletalTrapezoidation.cpp +++ b/src/libslic3r/Arachne/SkeletalTrapezoidation.cpp @@ -1660,7 +1660,7 @@ void SkeletalTrapezoidation::propagateBeadingsDownward(edge_t* edge_to_peak, ptr } -SkeletalTrapezoidation::Beading SkeletalTrapezoidation::interpolate(const Beading& left, double ratio_left_to_whole, const Beading& right, coord_t switching_radius) const +SkeletalTrapezoidation::Beading SkeletalTrapezoidation::interpolate(const Beading& left, double ratio_left_to_whole, const Beading& right, coord_t switching_radius) { assert(ratio_left_to_whole >= 0.0 && ratio_left_to_whole <= 1.0); Beading ret = interpolate(left, ratio_left_to_whole, right); @@ -1684,6 +1684,12 @@ SkeletalTrapezoidation::Beading SkeletalTrapezoidation::interpolate(const Beadin { // We cant adjust to fit the next edge because there is no previous one?! return ret; } + // ret follows the thicker of left/right, which can hold fewer insets than left when bead + // count and thickness disagree; skip the adjustment rather than index ret past its end. + if (next_inset_idx >= coord_t(ret.toolpath_locations.size())) + { + return ret; + } assert(next_inset_idx < coord_t(left.toolpath_locations.size())); assert(left.toolpath_locations[next_inset_idx] <= switching_radius); assert(left.toolpath_locations[next_inset_idx + 1] >= switching_radius); @@ -1703,7 +1709,7 @@ SkeletalTrapezoidation::Beading SkeletalTrapezoidation::interpolate(const Beadin } -SkeletalTrapezoidation::Beading SkeletalTrapezoidation::interpolate(const Beading& left, double ratio_left_to_whole, const Beading& right) const +SkeletalTrapezoidation::Beading SkeletalTrapezoidation::interpolate(const Beading& left, double ratio_left_to_whole, const Beading& right) { assert(ratio_left_to_whole >= 0.0 && ratio_left_to_whole <= 1.0); float ratio_right_to_whole = 1.0 - ratio_left_to_whole; diff --git a/src/libslic3r/Arachne/SkeletalTrapezoidation.hpp b/src/libslic3r/Arachne/SkeletalTrapezoidation.hpp index 70c2a7d9a3..d87cd74728 100644 --- a/src/libslic3r/Arachne/SkeletalTrapezoidation.hpp +++ b/src/libslic3r/Arachne/SkeletalTrapezoidation.hpp @@ -488,7 +488,7 @@ protected: * beads. * \return The beading at the interpolated location. */ - Beading interpolate(const Beading& left, double ratio_left_to_whole, const Beading& right, coord_t switching_radius) const; + static Beading interpolate(const Beading& left, double ratio_left_to_whole, const Beading& right, coord_t switching_radius); /*! * Subroutine of \ref interpolate(const Beading&, Ratio, const Beading&, coord_t) @@ -501,7 +501,7 @@ protected: * \param right One of the beadings to interpolate between. * \return The beading at the interpolated location. */ - Beading interpolate(const Beading& left, double ratio_left_to_whole, const Beading& right) const; + static Beading interpolate(const Beading& left, double ratio_left_to_whole, const Beading& right); /*! * Get the beading at a certain node of the skeletal graph, or create one if diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt index 93946ca477..01c1a0636b 100644 --- a/src/libslic3r/CMakeLists.txt +++ b/src/libslic3r/CMakeLists.txt @@ -221,6 +221,7 @@ set(lisbslic3r_sources GCode/FanMover.hpp GCode/GCodeProcessor.cpp GCode/GCodeProcessor.hpp + GCode/ElegooGCodeProcessorHelper.cpp GCode.hpp GCode/PchipInterpolatorHelper.cpp GCode/PchipInterpolatorHelper.hpp diff --git a/src/libslic3r/Clipper2Utils.cpp b/src/libslic3r/Clipper2Utils.cpp index 12fd867500..d389d25209 100644 --- a/src/libslic3r/Clipper2Utils.cpp +++ b/src/libslic3r/Clipper2Utils.cpp @@ -188,6 +188,18 @@ ExPolygons offset_ex_2(const ExPolygons &expolygons, double delta) return results; } +ExPolygons offset_ex_2(const ExPolygons &expolygons, double delta, Clipper2Lib::JoinType joinType) +{ + Clipper2Lib::Paths64 subject = Slic3rExPolygons_to_Paths64(expolygons); + Clipper2Lib::ClipperOffset offsetter; + offsetter.AddPaths(subject, joinType, Clipper2Lib::EndType::Polygon); + Clipper2Lib::PolyPath64 polytree; + offsetter.Execute(delta, polytree); + ExPolygons results = PolyTreeToExPolygons(std::move(polytree)); + + return results; +} + ExPolygons offset2_ex_2(const ExPolygons& expolygons, double delta1, double delta2) { // 1st offset diff --git a/src/libslic3r/Clipper2Utils.hpp b/src/libslic3r/Clipper2Utils.hpp index 54b48d6bd7..2b4b0fb2ef 100644 --- a/src/libslic3r/Clipper2Utils.hpp +++ b/src/libslic3r/Clipper2Utils.hpp @@ -15,6 +15,7 @@ Slic3r::Polylines diff_pl_2(const Slic3r::Polylines& subject, const Slic3r::Pol ExPolygons union_ex_2(const Polygons &expolygons); ExPolygons union_ex_2(const ExPolygons &expolygons); ExPolygons offset_ex_2(const ExPolygons &expolygons, double delta); +ExPolygons offset_ex_2(const ExPolygons &expolygons, double delta, Clipper2Lib::JoinType joinType); ExPolygons offset2_ex_2(const ExPolygons &expolygons, double delta1, double delta2); } diff --git a/src/libslic3r/Config.hpp b/src/libslic3r/Config.hpp index 54a09ec96a..9d8a3dcc40 100644 --- a/src/libslic3r/Config.hpp +++ b/src/libslic3r/Config.hpp @@ -363,6 +363,7 @@ public: virtual void set_with_restore(const ConfigOptionVectorBase* rhs, std::vector& restore_index, int stride) = 0; virtual void set_with_restore_2(const ConfigOptionVectorBase* rhs, std::vector& restore_index, int start, int len, bool skip_error = false) = 0; virtual void set_only_diff(const ConfigOptionVectorBase* rhs, std::vector& diff_index, int stride) = 0; + virtual void set_to_index(const ConfigOptionVectorBase* rhs, std::vector& dest_index, int stride) = 0; virtual void set_with_nil(const ConfigOptionVectorBase* rhs, const ConfigOptionVectorBase* inherits, int stride) = 0; // Resize the vector of values, copy the newly added values from opt_default if provided. virtual void resize(size_t n, const ConfigOption *opt_default = nullptr) = 0; @@ -586,6 +587,32 @@ public: throw ConfigurationError("ConfigOptionVector::set_only_diff(): Assigning an incompatible type"); } + //set a item related with extruder variants when apply static config with dynamic config + //rhs: item from dynamic config + //dest_index: which index in this vector need to be used + virtual void set_to_index(const ConfigOptionVectorBase* rhs, std::vector& dest_index, int stride) override + { + if (rhs->type() == this->type()) { + // Assign the first value of the rhs vector. + auto other = static_cast*>(rhs); + T v = other->values.front(); + this->values.resize(dest_index.size() * stride, v); + + for (size_t i = 0; i < dest_index.size(); i++) { + if (dest_index[i] < 0) + continue; + for (size_t j = 0; j < size_t(stride); j++) + { + const size_t src_idx = size_t(dest_index[i]) * size_t(stride) + j; + if (src_idx < other->values.size() && !other->is_nil(size_t(dest_index[i]) * size_t(stride))) + this->values[i * size_t(stride) + j] = other->values[src_idx]; + } + } + } + else + throw ConfigurationError("ConfigOptionVector::set_to_index(): Assigning an incompatible type"); + } + //set a item related with extruder variants when saving user config, set the non-diff value of some extruder to nill //this item has different value with inherit config //rhs: item from userconfig diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp index bdb21124d4..fbaade10ab 100644 --- a/src/libslic3r/Fill/Fill.cpp +++ b/src/libslic3r/Fill/Fill.cpp @@ -272,6 +272,10 @@ struct SurfaceFillParams // For Gyroid: when true, use the parameterized "optimized" wave. bool gyroid_optimized = false; + bool anisotropic_surfaces{false}; + CenterOfSurfacePattern center_of_surface_pattern{CenterOfSurfacePattern::Each_Surface}; + bool separated_infills{false}; + bool operator<(const SurfaceFillParams &rhs) const { #define RETURN_COMPARE_NON_EQUAL(KEY) if (this->KEY < rhs.KEY) return true; if (this->KEY > rhs.KEY) return false; #define RETURN_COMPARE_NON_EQUAL_TYPED(TYPE, KEY) if (TYPE(this->KEY) < TYPE(rhs.KEY)) return true; if (TYPE(this->KEY) > TYPE(rhs.KEY)) return false; @@ -301,8 +305,12 @@ struct SurfaceFillParams RETURN_COMPARE_NON_EQUAL(lateral_lattice_angle_2); RETURN_COMPARE_NON_EQUAL(symmetric_infill_y_axis); RETURN_COMPARE_NON_EQUAL(infill_lock_depth); - RETURN_COMPARE_NON_EQUAL(skin_infill_depth); RETURN_COMPARE_NON_EQUAL(infill_overhang_angle); + RETURN_COMPARE_NON_EQUAL(skin_infill_depth); + RETURN_COMPARE_NON_EQUAL(infill_overhang_angle); RETURN_COMPARE_NON_EQUAL(gyroid_optimized); + RETURN_COMPARE_NON_EQUAL(anisotropic_surfaces); + RETURN_COMPARE_NON_EQUAL(center_of_surface_pattern); + RETURN_COMPARE_NON_EQUAL(separated_infills); return false; } @@ -329,6 +337,9 @@ struct SurfaceFillParams this->infill_lock_depth == rhs.infill_lock_depth && this->skin_infill_depth == rhs.skin_infill_depth && this->infill_overhang_angle == rhs.infill_overhang_angle && + this->anisotropic_surfaces == rhs.anisotropic_surfaces && + this->center_of_surface_pattern == rhs.center_of_surface_pattern && + this->separated_infills == rhs.separated_infills && this->gyroid_optimized == rhs.gyroid_optimized; } }; @@ -868,6 +879,9 @@ std::vector group_fills(const Layer &layer, LockRegionParam &lock_p params.lateral_lattice_angle_1 = region_config.lateral_lattice_angle_1; params.lateral_lattice_angle_2 = region_config.lateral_lattice_angle_2; params.infill_overhang_angle = region_config.infill_overhang_angle; + params.anisotropic_surfaces = region_config.anisotropic_surfaces; + params.center_of_surface_pattern = region_config.center_of_surface_pattern; + params.separated_infills = region_config.separated_infills; if (params.pattern == ipLockedZag) { params.infill_lock_depth = scale_(region_config.infill_lock_depth); params.skin_infill_depth = scale_(region_config.skin_infill_depth); @@ -1309,6 +1323,22 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive: params.config = ®ion_config; params.pattern = surface_fill.params.pattern; + // Orca: Checking the filling of a centered surface by drawing for each model parts + bool is_top_or_bottom = params.extrusion_role == erTopSolidInfill || params.extrusion_role == erBottomSurface; + bool is_centered_infill = surface_fill.params.pattern == ipArchimedeanChords || surface_fill.params.pattern == ipOctagramSpiral; + if (is_top_or_bottom) { + params.is_anisotropic = surface_fill.params.anisotropic_surfaces; // Orca: anisotropic surfaces + params.center_of_surface_pattern = surface_fill.params.center_of_surface_pattern; // Orca: center of surface pattern + } + // Orca: Each_Model centers the pattern on each model part's bbox; Each_Surface / Each_Assembly + // fall through to the default (whole-object) bounding box below. + bool is_per_model_center = is_top_or_bottom && params.center_of_surface_pattern == CenterOfSurfacePattern::Each_Model && is_centered_infill; + bool is_separate_infill = !is_top_or_bottom && surface_fill.params.separated_infills && + ( + is_separable_infill_pattern(surface_fill.params.pattern) || + params.config->solid_infill_rotate_template != "" || + params.config->sparse_infill_rotate_template != "" ); + if( surface_fill.params.pattern == ipLockedZag ) { params.locked_zag = true; params.infill_lock_depth = surface_fill.params.infill_lock_depth; @@ -1332,7 +1362,36 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive: params.can_reverse = false; for (ExPolygon& expoly : surface_fill.expolygons) { - f->no_overlap_expolygons = intersection_ex(surface_fill.no_overlap_expolygons, ExPolygons() = {expoly}, ApplySafetyOffset::Yes); + // Orca: separate infill / per-model pattern centering. + // + // Center the pattern on each connected body of the object independently, so every piece + // is filled exactly as if it were sliced on its own: touching/overlapping parts merge + // into one body sharing a center, while separate parts and disconnected islands (even + // interleaved-but-not-touching ones, e.g. chain links) each get their own. The body each + // island belongs to, and its full bounding box, were resolved in 3D by PrintObject:: + // infill() (lslices_separated_component_bboxes, aligned with this layer's lslices). We + // match this fill region to the island it overlaps most, then re-use the whole-object + // bounding box (origin-centered — identical extent to the default, so coverage and cost + // are unchanged) re-centered on that body. + if (is_per_model_center || is_separate_infill) { + double best_overlap = 0.; + BoundingBox best_component; + for (size_t r = 0; r < this->lslices.size() && r < this->lslices_separated_component_bboxes.size(); ++ r) { + const double overlap = area(intersection_ex(this->lslices[r], expoly)); + if (overlap > best_overlap) { + best_overlap = overlap; + best_component = this->lslices_separated_component_bboxes[r]; + } + } + if (best_component.defined) { + const Point c = best_component.center(); + BoundingBox part_bbox = bbox; // origin-centered, whole-object extent (from above) + part_bbox.translate(c.x(), c.y()); // re-center on this body + f->set_bounding_box(part_bbox); + } + } // - End: separate infill / per-model pattern centering + + f->no_overlap_expolygons = intersection_ex(surface_fill.no_overlap_expolygons, ExPolygons() = {expoly}, ApplySafetyOffset::Yes); if (params.symmetric_infill_y_axis) { params.symmetric_y_axis = f->extended_object_bounding_box().center().x(); expoly.symmetric_y(params.symmetric_y_axis); diff --git a/src/libslic3r/Fill/FillBase.cpp b/src/libslic3r/Fill/FillBase.cpp index 1d15614ccb..cf74606dd4 100644 --- a/src/libslic3r/Fill/FillBase.cpp +++ b/src/libslic3r/Fill/FillBase.cpp @@ -165,7 +165,7 @@ void Fill::fill_surface_extrusion(const Surface* surface, const FillParams& para // ORCA: special flag for flow rate calibration auto is_flow_calib = params.extrusion_role == erTopSolidInfill && this->print_object_config->has("calib_flowrate_topinfill_special_order") && this->print_object_config->option("calib_flowrate_topinfill_special_order")->getBool(); - if (is_flow_calib) { + if (is_flow_calib || params.is_anisotropic) { // Orca: disable sorting while anisotropic surfaces eec->no_sort = true; } size_t idx = eec->entities.size(); @@ -186,7 +186,8 @@ void Fill::fill_surface_extrusion(const Surface* surface, const FillParams& para } // Orca: run gap fill - this->_create_gap_fill(surface, params, eec); + if (!(params.is_anisotropic)) // Orca: Disable gap filling while anisotropic + this->_create_gap_fill(surface, params, eec); } } diff --git a/src/libslic3r/Fill/FillBase.hpp b/src/libslic3r/Fill/FillBase.hpp index ef6a6bc804..ffeed3045b 100644 --- a/src/libslic3r/Fill/FillBase.hpp +++ b/src/libslic3r/Fill/FillBase.hpp @@ -106,6 +106,8 @@ struct FillParams bool locked_zag{false}; float infill_lock_depth{0.0}; float skin_infill_depth{0.0}; + bool is_anisotropic{false}; + CenterOfSurfacePattern center_of_surface_pattern{CenterOfSurfacePattern::Each_Surface}; }; static_assert(IsTriviallyCopyable::value, "FillParams class is not POD (and it should be - see constructor)."); diff --git a/src/libslic3r/Fill/FillPlanePath.cpp b/src/libslic3r/Fill/FillPlanePath.cpp index b4681d05f9..01f4ca00da 100644 --- a/src/libslic3r/Fill/FillPlanePath.cpp +++ b/src/libslic3r/Fill/FillPlanePath.cpp @@ -77,20 +77,24 @@ void FillPlanePath::_fill_surface_single( //FIXME Vojtech: We are not sure whether the user expects the fill patterns on visible surfaces to be aligned across all the islands of a single layer. // One may align for this->centered() to align the patterns for Archimedean Chords and Octagram Spiral patterns. - const bool align = params.density < 0.995; - + // Orca: the old implementation became obsolete when it became possible to change the density of the top and bottom surfaces + bool align = params.extrusion_role == ExtrusionRole::erInternalInfill; + BoundingBox bounding_box; BoundingBox snug_bounding_box = get_extents(expolygon).inflated(SCALED_EPSILON); // Expand the bounding box to avoid artifacts at the edges - snug_bounding_box.offset(scale_(this->spacing)*params.multiline); + snug_bounding_box.offset(scale_(this->spacing)*params.multiline); - // Rotated bounding box of the area to fill in with the pattern. - BoundingBox bounding_box = align ? - // Sparse infill needs to be aligned across layers. Align infill across layers using the object's bounding box. - this->bounding_box.rotated(-direction.first) : - // Solid infill does not need to be aligned across layers, generate the infill pattern - // around the clipping expolygon only. - snug_bounding_box; + // Sparse infill (or Internal where align == true) needs to be aligned across layers. Align infill across layers using the object's bounding box. + // Solid infill does not need to be aligned across layers, generate the infill pattern around the clipping expolygon only. + if (align) + bounding_box = this->bounding_box.rotated(-direction.first); + else if (params.center_of_surface_pattern == CenterOfSurfacePattern::Each_Surface) + bounding_box = snug_bounding_box; + else if (params.center_of_surface_pattern == CenterOfSurfacePattern::Each_Model) + bounding_box = this->bounding_box.rotated(-direction.first); + else + bounding_box = extended_object_bounding_box(); Point shift = this->centered() ? bounding_box.center() : @@ -129,35 +133,49 @@ void FillPlanePath::_fill_surface_single( polylines = intersection_pl(std::move(polylines), expolygon); if (!polylines.empty()) { Polylines chained; - if (params.dont_connect() || params.density > 0.5) { - // ORCA: special flag for flow rate calibration - auto is_flow_calib = params.extrusion_role == erTopSolidInfill && - this->print_object_config->has("calib_flowrate_topinfill_special_order") && - this->print_object_config->option("calib_flowrate_topinfill_special_order")->getBool() && - dynamic_cast(this); - if (is_flow_calib) { - // We want the spiral part to be printed inside-out - // Find the center spiral line first, by looking for the longest one - auto it = std::max_element(polylines.begin(), polylines.end(), - [](const Polyline& a, const Polyline& b) { return a.length() < b.length(); }); - Polyline center_spiral = std::move(*it); + if (!params.is_anisotropic) { // Orca: not anisotropic surface + if ((params.dont_connect() || params.density > 0.5)) { + // ORCA: special flag for flow rate calibration + auto is_flow_calib = params.extrusion_role == erTopSolidInfill && + this->print_object_config->has("calib_flowrate_topinfill_special_order") && + this->print_object_config->option("calib_flowrate_topinfill_special_order")->getBool() && + dynamic_cast(this); + if (is_flow_calib) { + // We want the spiral part to be printed inside-out + // Find the center spiral line first, by looking for the longest one + auto it = std::max_element(polylines.begin(), polylines.end(), + [](const Polyline& a, const Polyline& b) { return a.length() < b.length(); }); + Polyline center_spiral = std::move(*it); - // Ensure the spiral is printed from inside to out - if (center_spiral.first_point().squaredNorm() > center_spiral.last_point().squaredNorm()) { - center_spiral.reverse(); + // Ensure the spiral is printed from inside to out + if ((center_spiral.first_point().squaredNorm() > center_spiral.last_point().squaredNorm())) { + center_spiral.reverse(); + } + + // Chain the other polylines + polylines.erase(it); + chained = chain_polylines(std::move(polylines), nullptr); + + // Then add the center spiral back + chained.push_back(std::move(center_spiral)); + } else { + chained = chain_polylines(std::move(polylines), nullptr); } - - // Chain the other polylines - polylines.erase(it); - chained = chain_polylines(std::move(polylines)); - - // Then add the center spiral back - chained.push_back(std::move(center_spiral)); - } else { - chained = chain_polylines(std::move(polylines)); + } else + connect_infill(std::move(polylines), expolygon, chained, this->spacing, params); + } else { // Orca: anisotropic surface + const Point _center(0., 0.); + for (Polyline& segment : polylines) { // sort paths by its direction + if (segment.size() > 1) { // need at least two points to evaluate direction + if (segment.first_point().ccw(segment.points[1], _center) < 0) + segment.reverse(); + } + chained.emplace_back(std::move(segment)); } - } else - connect_infill(std::move(polylines), expolygon, chained, this->spacing, params); + std::sort(chained.begin(), chained.end(), [&_center](const Polyline& a, const Polyline& b) { // just sort polylines from center to outside + return a.distance_to(_center) < b.distance_to(_center); + }); + } // paths must be repositioned and rotated back for (Polyline& pl : chained) { pl.translate(shift.x(), shift.y()); diff --git a/src/libslic3r/Fill/FillRectilinear.cpp b/src/libslic3r/Fill/FillRectilinear.cpp index 5638dea869..138b50bc88 100644 --- a/src/libslic3r/Fill/FillRectilinear.cpp +++ b/src/libslic3r/Fill/FillRectilinear.cpp @@ -2739,13 +2739,19 @@ static void polylines_from_paths(const std::vector &path, c // The extended bounding box of the whole object that covers any rotation of every layer. BoundingBox FillRectilinear::extended_object_bounding_box() const { + // Build the extension around the box center. The transpose merge and the sqrt(2.) scaling + // (which covers any possible rotation) are both defined about the origin, so a box that is not + // origin-centered — e.g. a separated-infill box re-centered on a single assembly part — would be + // distorted. Shift to the origin first and back afterwards; for the default origin-centered box + // the two translations cancel and this is identical to the original behavior. + const Point c = this->bounding_box.center(); BoundingBox out = this->bounding_box; + out.translate(-c.x(), -c.y()); out.merge(Point(out.min.y(), out.min.x())); out.merge(Point(out.max.y(), out.max.x())); - - // The bounding box is scaled by sqrt(2.) to ensure that the bounding box - // covers any possible rotations. - return out.scaled(sqrt(2.)); + out = out.scaled(sqrt(2.)); + out.translate(c.x(), c.y()); + return out; } bool FillRectilinear::fill_surface_by_lines(const Surface *surface, const FillParams ¶ms, float angleBase, float pattern_shift, Polylines &polylines_out) @@ -3098,8 +3104,11 @@ bool FillRectilinear::fill_surface_trapezoidal( const coord_t d2 = coord_t(0.5 * period - d1); - // Align bounding box to the grid - bb.merge(align_to_grid(bb.min, Point(period, period))); + // Align bounding box to the grid, phased through the box center so separated infills align + // each part on itself (grid_center is the origin for a standalone object / feature off). + // Captured before the merge, which grows bb and would otherwise shift its center. + const Point grid_center = bb.center(); + bb.merge(align_to_grid(bb.min, Point(period, period), grid_center)); const coord_t xmin = bb.min.x(); const coord_t xmax = bb.max.x(); const coord_t ymin = bb.min.y(); @@ -3146,11 +3155,17 @@ bool FillRectilinear::fill_surface_trapezoidal( flip_vertical = !flip_vertical; } - // transpose points for odd infill layers (taking infill combination into account) + // transpose points for odd infill layers (taking infill combination into account). + // Orca: mirror across the diagonal through grid_center (not the origin), so the swapped + // layers stay aligned with the center-phased grid. For a standalone object / feature off, + // grid_center is the origin and this is a plain x/y swap. if (infill_layer_id % 2 == 1) { for (Polyline& pl : polylines) { for (Point& p : pl.points) { - std::swap(p.x(), p.y()); + const coord_t dx = p.x() - grid_center.x(); + const coord_t dy = p.y() - grid_center.y(); + p.x() = grid_center.x() + dy; + p.y() = grid_center.y() + dx; } } } @@ -3341,6 +3356,14 @@ bool FillRectilinear::fill_surface_trapezoidal( break; } + // Orca: cases 1 & 2 build the pattern symmetrically around the origin, so on their own they + // phase to the global origin and every part shares one grid. Shift the pattern onto the box + // center this->bounding_box carries, so separated infills align each part on itself. The center + // is the origin for a standalone object (or when the feature is off), making this a no-op there. + if (Pattern_type != 0) + for (Polyline &pl : polylines) + pl.translate(rotate_vector.second); + // Apply multiline fill multiline_fill(polylines, params, spacing); diff --git a/src/libslic3r/Format/bbs_3mf.cpp b/src/libslic3r/Format/bbs_3mf.cpp index 31519e4fbe..fd395135ae 100644 --- a/src/libslic3r/Format/bbs_3mf.cpp +++ b/src/libslic3r/Format/bbs_3mf.cpp @@ -5949,7 +5949,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result) m_thumbnail_middle = iter->second; } boost::system::error_code ec; - std::string filename = std::string(store_params.path); + std::string filename = store_params.path; boost::filesystem::remove(filename + ".tmp", ec); bool result = _save_model_to_file(filename + ".tmp", *store_params.model, store_params.plate_data_list, store_params.project_presets, store_params.config, @@ -8988,7 +8988,7 @@ bool store_bbs_3mf(StoreParams& store_params) // All export should use "C" locales for number formatting. CNumericLocalesSetter locales_setter; - if (store_params.path == nullptr || store_params.model == nullptr) + if (store_params.path.empty() || store_params.model == nullptr) return false; _BBS_3MF_Exporter exporter; diff --git a/src/libslic3r/Format/bbs_3mf.hpp b/src/libslic3r/Format/bbs_3mf.hpp index df4f91f6e9..c16c423f66 100644 --- a/src/libslic3r/Format/bbs_3mf.hpp +++ b/src/libslic3r/Format/bbs_3mf.hpp @@ -226,7 +226,7 @@ typedef std::map PlateDataMaps; struct StoreParams { - const char* path; + std::string path; Model* model = nullptr; PlateDataPtrs plate_data_list; int export_plate_idx = -1; diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 0b62fd0d6f..8238f5be85 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -6215,7 +6215,8 @@ std::string GCode::extrude_support(const ExtrusionEntityCollection &support_fill static constexpr const char* support_transition_label = "support transition"; static constexpr const char* support_ironing_label = "support ironing"; - static const auto speed_for_path = [&](double length, ExtrusionRole role, double default_speed = -1.0) { + // Not static: it captures `this` by reference. + const auto speed_for_path = [&](double length, ExtrusionRole role, double default_speed = -1.0) { if (!is_support(role) || length > SMALL_PERIMETER_LENGTH(NOZZLE_CONFIG(small_support_perimeter_threshold))) return default_speed; diff --git a/src/libslic3r/GCode/ElegooGCodeProcessorHelper.cpp b/src/libslic3r/GCode/ElegooGCodeProcessorHelper.cpp new file mode 100644 index 0000000000..cac53637a5 --- /dev/null +++ b/src/libslic3r/GCode/ElegooGCodeProcessorHelper.cpp @@ -0,0 +1,190 @@ +#include "GCodeProcessor.hpp" + +#include "libslic3r/libslic3r.h" + +#include +#include +#include +#include + +namespace Slic3r { +namespace { + +bool equals_case_insensitive(std::string_view lhs, std::string_view rhs) +{ + return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin(), [](unsigned char l, unsigned char r) { + return std::tolower(l) == std::tolower(r); + }); +} + +float get_clamped_param(const GCodeReader::GCodeLine& line, char axis, float default_value, float min_value, float max_value) +{ + float value = default_value; + line.has_value(axis, value); + return std::clamp(value, min_value, max_value); +} + +float extrusion_time(float e_length, float feedrate) +{ + return feedrate > 0.0f && e_length > 0.0f ? e_length / feedrate * 60.0f : 0.0f; +} + +float retract_time(float e_length) +{ + static constexpr float retract_feedrate = 1800.0f; + return extrusion_time(std::max(e_length, 0.0f), retract_feedrate); +} + +float s819_time(float e_length, float feedrate) +{ + static constexpr float s819_tail_flush_length = 10.0f; + static constexpr float s819_tail_feedrate = 400.0f; + + const float tail_length = std::min(std::max(e_length, 0.0f), s819_tail_flush_length); + const float main_length = std::max(e_length - tail_length, 0.0f); + return extrusion_time(main_length, feedrate) + extrusion_time(tail_length, s819_tail_feedrate); +} + +float estimate_M6211_time_for_centauri_carbon(const GCodeReader::GCodeLine& line, float length, double current_x, + double current_y) +{ + static constexpr float max_segment_length = 73.0f; + static constexpr float wipe_after_flush_time = 2.8f; + static constexpr float main_feedrate = 500.0f; + static constexpr float tail_feedrate = 400.0f; + static constexpr float travel_feedrate = 5000.0f; + static constexpr double parking_x = 256.0; + static constexpr double parking_y = 0.0; + + const float flush_length = std::clamp(length, 10.0f, 1000.0f); + const float cool_time = get_clamped_param(line, 'P', 5000.0f, 0.0f, 20000.0f) * 0.001f; + const float travel_time = static_cast(std::abs(current_y - parking_y) + std::abs(current_x - parking_x)) / + travel_feedrate * 60.0f; + + // Initial time, including: material change, heating, etc. + float m6211_time = 18.2f + travel_time; + + float remaining_flush_length = std::max(flush_length, 0.0f); + while (remaining_flush_length > 0.0f) { + const float segment_length = std::min(remaining_flush_length, max_segment_length); + remaining_flush_length -= segment_length; + if (segment_length >= max_segment_length) { + // Full segment: 3-phase extrusion (30+35+10=75mm) + retract + m6211_time += extrusion_time(30.0f, main_feedrate) + extrusion_time(35.0f, main_feedrate) + + extrusion_time(10.0f, tail_feedrate) + extrusion_time(2.0f, tail_feedrate) + cool_time + + wipe_after_flush_time; + } else { + // Partial last segment: simple extrude at F500 + retract at F400 + m6211_time += extrusion_time(segment_length, main_feedrate) + extrusion_time(2.0f, tail_feedrate) + cool_time + + wipe_after_flush_time; + } + } + + return m6211_time; +} + +float estimate_M6211_time_for_centauri_carbon_2(const GCodeReader::GCodeLine& line, float length, float new_extruder_temp) +{ + const float flush_length = std::clamp(length, 10.0f, 1000.0f); + const float flush_length_single = get_clamped_param(line, 'K', 75.0f, 10.0f, 300.0f); + const float old_filament_e_feedrate = get_clamped_param(line, 'M', 300.0f, 10.0f, 600.0f); + const float new_filament_e_feedrate = get_clamped_param(line, 'N', 300.0f, 10.0f, 600.0f); + const float cool_time = get_clamped_param(line, 'P', 3000.0f, 0.0f, 20000.0f) * 0.001f; + + // The flush length of the old material, unit: mm + static constexpr float e_flush_dist = 15.0f; + // Wipe time after flush, in seconds + static constexpr float wipe_after_flush_time = 5.0f; + + const float flush_length_after_start = std::max(flush_length - e_flush_dist, 0.0f); + const int flush_times = std::max(1, static_cast(std::ceil(flush_length_after_start / flush_length_single))); + const float flush_length_actual = flush_length_single; + + // Initial time, including: material change, heating, moving, etc. + float m6211_time = 31.0f; + m6211_time += extrusion_time(std::min(e_flush_dist, flush_length), old_filament_e_feedrate); + + const int intermediate_flush_times = flush_times - 1; + const float intermediate_flush_time = s819_time(flush_length_actual, new_filament_e_feedrate) + retract_time(6.0f) + cool_time + + wipe_after_flush_time; + m6211_time += static_cast(intermediate_flush_times) * intermediate_flush_time; + m6211_time += s819_time(flush_length_actual, new_filament_e_feedrate * 0.8f) + retract_time(4.0f) + cool_time + wipe_after_flush_time; + + static constexpr float cooling_rate = 1.36f; + const float r_temp = get_clamped_param(line, 'R', new_extruder_temp + 20.0f, 185.0f, 350.0f); + const float s_temp = get_clamped_param(line, 'S', 250.0f, 185.0f, 350.0f); + + if (s_temp < r_temp) + m6211_time += (r_temp - s_temp) / cooling_rate; + + return m6211_time; +} + +float estimate_M6211_time(const GCodeReader::GCodeLine& line, std::string_view printer_model, float length, float new_extruder_temp, double current_x, double current_y) +{ + if (equals_case_insensitive(printer_model, "Elegoo Centauri Carbon") || equals_case_insensitive(printer_model, "Elegoo Centauri")) { + return estimate_M6211_time_for_centauri_carbon(line, length, current_x, current_y); + } else if (equals_case_insensitive(printer_model, "Elegoo Centauri Carbon 2") || + equals_case_insensitive(printer_model, "Elegoo Centauri 2")) { + return estimate_M6211_time_for_centauri_carbon_2(line, length, new_extruder_temp); + } + return 0.0f; +} + +} // namespace + +void GCodeProcessor::process_elegoo_M6211(const GCodeReader::GCodeLine& line) +{ + float length = 0.0f; + if (!line.has_value('L', length) || length <= 0.0f) + return; + + float t = -1.0f; + if (!line.has_value('T', t) || t < 0.0f) + return; + + const int filament_id = static_cast(std::round(t)); + if (filament_id < 0 || filament_id >= m_result.filaments_count) + return; + + const int extruder_id = m_filament_maps[filament_id]; + + float new_extruder_temp = 0.0f; + if (line.has_value('S', new_extruder_temp)) { + if (extruder_id >= 0 && static_cast(extruder_id) < m_extruder_temps.size()) + m_extruder_temps[static_cast(extruder_id)] = new_extruder_temp; + } + + const float m6211_time = estimate_M6211_time(line, m_printer_model, length, new_extruder_temp, + m_start_position[X], m_start_position[Y]); + const int curr_filament_id = get_filament_id(false); + const bool is_first_extrusion = (curr_filament_id == -1) || (filament_id == curr_filament_id); + + m_time_processor.filament_unload_times = 0; + m_time_processor.filament_load_times = m6211_time; + process_filament_change(filament_id); + + if (extruder_id >= 0 && static_cast(extruder_id) < m_remaining_volume.size()) { + const float remaining_volume = static_cast(extruder_id) < m_nozzle_volume.size() ? + m_nozzle_volume[extruder_id] : + 0.0f; + const float filament_diameter = static_cast(filament_id) < m_result.filament_diameters.size() ? + m_result.filament_diameters[filament_id] : + m_result.filament_diameters.back(); + const float area_filament_cross_section = static_cast(M_PI) * sqr(0.5f * filament_diameter); + const float volume_flushed_filament = area_filament_cross_section * length; + + if (volume_flushed_filament >= remaining_volume) { + if (!is_first_extrusion) + m_used_filaments.update_flush_per_filament(curr_filament_id, remaining_volume); + + m_used_filaments.update_flush_per_filament(filament_id, volume_flushed_filament - remaining_volume); + m_remaining_volume[extruder_id] = 0.0f; + } else { + m_used_filaments.update_flush_per_filament(filament_id, volume_flushed_filament); + m_remaining_volume[extruder_id] -= volume_flushed_filament; + } + } +} + +} // namespace Slic3r diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 44cb185aec..c0a92780c4 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -1839,7 +1839,8 @@ void GCodeProcessor::register_commands() {"VM104", [this](const GCodeReader::GCodeLine& line) { process_VM104(line); }}, {"VM109", [this](const GCodeReader::GCodeLine& line) { process_VM109(line); }}, {"M622", [this](const GCodeReader::GCodeLine& line) { process_M622(line);}}, - {"M623", [this](const GCodeReader::GCodeLine& line) { process_M623(line);}} + {"M623", [this](const GCodeReader::GCodeLine& line) { process_M623(line);}}, + {"M6211", [this](const GCodeReader::GCodeLine& line) { process_M6211(line); }} }; std::unordered_setearly_quit_commands = { @@ -1863,6 +1864,12 @@ void GCodeProcessor::register_commands() } } +void GCodeProcessor::process_M6211(const GCodeReader::GCodeLine& line) +{ + if (boost::algorithm::istarts_with(m_printer_model, "elegoo")) + process_elegoo_M6211(line); +} + bool GCodeProcessor::check_multi_extruder_gcode_valid(const int extruder_size, const Pointfs plate_printable_area, const double plate_printable_height, @@ -2027,6 +2034,7 @@ void GCodeProcessor::apply_config(const PrintConfig& config) m_parser.apply_config(config); m_flavor = config.gcode_flavor; + m_printer_model = config.printer_model.value; m_single_extruder_multi_material = config.single_extruder_multi_material; @@ -2213,6 +2221,10 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config) if (printer_settings_id != nullptr) m_result.settings_ids.printer = printer_settings_id->value; + const ConfigOptionString* printer_model = config.option("printer_model"); + if (printer_model != nullptr) + m_printer_model = printer_model->value; + // BBS m_result.filaments_count = config.option("filament_diameter")->values.size(); diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index 1d2e0890da..fcefd1a9a7 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -846,6 +846,7 @@ class Print; float m_preheat_time; int m_preheat_steps; bool m_disable_m73; + std::string m_printer_model; enum class EProducer { @@ -1084,6 +1085,10 @@ class Print; // Unload the current filament into the MK3 MMU2 unit at the end of print. void process_M702(const GCodeReader::GCodeLine& line); + //Used for Elegoo printer to change tool head + void process_M6211(const GCodeReader::GCodeLine& line); + void process_elegoo_M6211(const GCodeReader::GCodeLine& line); + void process_SYNC(const GCodeReader::GCodeLine& line); // Processes T line (Select Tool) diff --git a/src/libslic3r/GCode/ToolOrdering.cpp b/src/libslic3r/GCode/ToolOrdering.cpp index 5cb66ba5e5..65c887f343 100644 --- a/src/libslic3r/GCode/ToolOrdering.cpp +++ b/src/libslic3r/GCode/ToolOrdering.cpp @@ -138,7 +138,8 @@ static double calc_max_layer_height(const PrintConfig &config, double max_object { double max_layer_height = std::numeric_limits::max(); for (size_t i = 0; i < config.nozzle_diameter.values.size(); ++ i) { - double mlh = config.max_layer_height.values[i]; + // max_layer_height may be shorter than the extruder count; get_at() clamps. + double mlh = config.max_layer_height.get_at(i); if (mlh == 0.) mlh = 0.75 * config.nozzle_diameter.values[i]; max_layer_height = std::min(max_layer_height, mlh); @@ -187,6 +188,10 @@ static void apply_first_layer_order(const DynamicPrintConfig* config, std::vecto void ToolOrdering::handle_dontcare_extruder(const std::vector& tool_order_layer0) { + const PrintConfig* print_config = m_print_config_ptr; + if (!print_config && m_print_object_ptr) + print_config = &m_print_object_ptr->print()->config(); + if(m_layer_tools.empty() || tool_order_layer0.empty()) return; @@ -221,6 +226,8 @@ void ToolOrdering::handle_dontcare_extruder(const std::vector& too for (int i = 1; i < m_layer_tools.size(); i++) { LayerTools& lt = m_layer_tools[i]; + // Extruders in lt.extruders are already sorted. + if (lt.extruders.empty()) continue; if (lt.extruders.size() == 1 && lt.extruders.front() == 0) @@ -229,14 +236,23 @@ void ToolOrdering::handle_dontcare_extruder(const std::vector& too if (lt.extruders.front() == 0) // Pop the "don't care" extruder, the "don't care" region will be merged with the next one. lt.extruders.erase(lt.extruders.begin()); - // Reorder the extruders to start with the last one. - for (size_t i = 1; i < lt.extruders.size(); ++i) - if (lt.extruders[i] == last_extruder_id) { - // Move the last extruder to the front. - memmove(lt.extruders.data() + 1, lt.extruders.data(), i * sizeof(unsigned int)); - lt.extruders.front() = last_extruder_id; - break; + + if (print_config == nullptr + || print_config->toolchange_ordering == ToolChangeOrderingType::Default) + { + // Reorder the extruders to start with the last one. + for (size_t i = 1; i < lt.extruders.size(); ++i) { + if (lt.extruders[i] == last_extruder_id) { + // Move the last extruder to the front. + std::rotate( + lt.extruders.begin(), + lt.extruders.begin() + i, + lt.extruders.begin() + i + 1 + ); + break; + } } + } } last_extruder_id = lt.extruders.back(); } @@ -252,6 +268,10 @@ void ToolOrdering::handle_dontcare_extruder(const std::vector& too void ToolOrdering::handle_dontcare_extruder(unsigned int last_extruder_id) { + const PrintConfig* print_config = m_print_config_ptr; + if (!print_config && m_print_object_ptr) + print_config = &m_print_object_ptr->print()->config(); + if(m_layer_tools.empty()) return; if(last_extruder_id == (unsigned int)-1){ @@ -275,6 +295,8 @@ void ToolOrdering::handle_dontcare_extruder(unsigned int last_extruder_id) } for (LayerTools < : m_layer_tools) { + // Extruders in lt.extruders are already sorted. + if (lt.extruders.empty()) continue; if (lt.extruders.size() == 1 && lt.extruders.front() == 0) @@ -283,21 +305,30 @@ void ToolOrdering::handle_dontcare_extruder(unsigned int last_extruder_id) if (lt.extruders.front() == 0) // Pop the "don't care" extruder, the "don't care" region will be merged with the next one. lt.extruders.erase(lt.extruders.begin()); - // Reorder the extruders to start with the last one. - for (size_t i = 1; i < lt.extruders.size(); ++ i) - if (lt.extruders[i] == last_extruder_id) { - // Move the last extruder to the front. - memmove(lt.extruders.data() + 1, lt.extruders.data(), i * sizeof(unsigned int)); - lt.extruders.front() = last_extruder_id; - break; + + if (print_config == nullptr + || print_config->toolchange_ordering == ToolChangeOrderingType::Default) + { + // Reorder the extruders to start with the last one. + for (size_t i = 1; i < lt.extruders.size(); ++i) { + if (lt.extruders[i] == last_extruder_id) { + // Move the last extruder to the front. + std::rotate( + lt.extruders.begin(), + lt.extruders.begin() + i, + lt.extruders.begin() + i + 1 + ); + break; + } } + } if (lt == m_layer_tools[0]) { // On first layer with wipe tower, prefer a soluble extruder // at the beginning, so it is not wiped on the first layer. - if (m_print_config_ptr && m_print_config_ptr->enable_prime_tower) { + if (print_config && print_config->enable_prime_tower) { for (size_t i = 0; ifilament_soluble.get_at(lt.extruders[i]-1)) { // 1-based... + if (print_config->filament_soluble.get_at(lt.extruders[i]-1)) { // 1-based... std::swap(lt.extruders[i], lt.extruders.front()); break; } @@ -396,6 +427,7 @@ void ToolOrdering::sort_and_build_data(const PrintObject& object , unsigned int ToolOrdering::ToolOrdering(const PrintObject &object, unsigned int first_extruder, bool prime_multi_material) { m_print_full_config = &object.print()->full_print_config(); + m_print_config_ptr = &object.print()->config(); m_print_object_ptr = &object; m_print = const_cast(object.print()); if (object.layers().empty()) @@ -1329,8 +1361,11 @@ void ToolOrdering::reorder_extruders_for_minimum_flush_volume(bool reorder_first if (!m_layer_tools.empty()) first_layer_filaments = m_layer_tools[0].extruders; + const bool use_cyclic_ordering = + (print_config->toolchange_ordering == ToolChangeOrderingType::Cyclic); + // other_layers_seq: the layer_idx and extruder_idx are base on 1 - auto get_custom_seq = [&other_layers_seqs, &reorder_first_layer, &first_layer_filaments](int layer_idx, std::vector& out_seq) -> bool { + auto get_custom_seq = [&other_layers_seqs, &reorder_first_layer, &first_layer_filaments, &layer_filaments, use_cyclic_ordering](int layer_idx, std::vector& out_seq) -> bool { if (!reorder_first_layer && layer_idx == 0) { out_seq.resize(first_layer_filaments.size()); std::transform(first_layer_filaments.begin(), first_layer_filaments.end(), out_seq.begin(), [](auto item) {return item + 1; }); @@ -1343,6 +1378,15 @@ void ToolOrdering::reorder_extruders_for_minimum_flush_volume(bool reorder_first return true; } } + + if (use_cyclic_ordering && layer_idx >= 0 && size_t(layer_idx) < layer_filaments.size()) { + std::vector ordered = layer_filaments[size_t(layer_idx)]; + std::sort(ordered.begin(), ordered.end()); + out_seq.resize(ordered.size()); + std::transform(ordered.begin(), ordered.end(), out_seq.begin(), [](auto item) { return int(item) + 1; }); + return true; + } + return false; }; diff --git a/src/libslic3r/GCodeWriter.cpp b/src/libslic3r/GCodeWriter.cpp index a3d8e66ac3..a13d05e1c3 100644 --- a/src/libslic3r/GCodeWriter.cpp +++ b/src/libslic3r/GCodeWriter.cpp @@ -110,6 +110,7 @@ void GCodeWriter::set_extruders(std::vector extruder_ids) m_filament_extruders.clear(); //ORCA: Reset current extruder ID and clear pointers to prevent dangling pointers when extruders are recreated. m_curr_extruder_id = -1; + m_cached_extruder_idx = 0; std::fill(m_curr_filament_extruder.begin(), m_curr_filament_extruder.end(), nullptr); m_filament_extruders.reserve(extruder_ids.size()); for (unsigned int extruder_id : extruder_ids) @@ -617,6 +618,7 @@ std::string GCodeWriter::toolchange(unsigned int filament_id) assert(filament_extruder_iter != m_filament_extruders.end() && filament_extruder_iter->id() == filament_id); m_curr_extruder_id = filament_extruder_iter->extruder_id(); m_curr_filament_extruder[m_curr_extruder_id] = &*filament_extruder_iter; + m_cached_extruder_idx = get_extruder_index(this->config, filament_id); // return the toolchange command // if we are running a single-extruder setup, just set the extruder and return nothing @@ -658,7 +660,7 @@ std::string GCodeWriter::travel_to_xy(const Vec2d &point, const std::string &com GCodeG1Formatter w; w.emit_xy(point_on_plate); auto speed = m_is_first_layer - ? this->config.get_abs_value_at("initial_layer_travel_speed", get_extruder_index(this->config, filament()->id())) : this->config.travel_speed.get_at(get_extruder_index(this->config, filament()->id())); + ? this->config.get_abs_value_at("initial_layer_travel_speed", m_cached_extruder_idx) : this->config.travel_speed.get_at(m_cached_extruder_idx); w.emit_f(speed * 60.0); //BBS w.emit_comment(GCodeWriter::full_gcode_comment, comment); @@ -744,7 +746,7 @@ std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &co // BBS Vec3d dest_point = point; auto travel_speed = - m_is_first_layer ? this->config.get_abs_value_at("initial_layer_travel_speed", get_extruder_index(this->config, filament()->id())) : this->config.travel_speed.get_at(get_extruder_index(this->config, filament()->id())); + m_is_first_layer ? this->config.get_abs_value_at("initial_layer_travel_speed", m_cached_extruder_idx) : this->config.travel_speed.get_at(m_cached_extruder_idx); //BBS: a z_hop need to be handle when travel if (std::abs(m_to_lift) > EPSILON) { assert(std::abs(m_lifted) < EPSILON); @@ -841,13 +843,13 @@ std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &co { //force to move xy first then z after filament change w.emit_xy(Vec2d(point_on_plate.x(), point_on_plate.y())); - w.emit_f(this->config.travel_speed.get_at(get_extruder_index(this->config, filament()->id())) * 60.0); + w.emit_f(this->config.travel_speed.get_at(m_cached_extruder_idx) * 60.0); w.emit_comment(GCodeWriter::full_gcode_comment, comment); out_string = w.string() + _travel_to_z(point_on_plate.z(), comment); } else { GCodeG1Formatter w; w.emit_xyz(point_on_plate); - w.emit_f(this->config.travel_speed.get_at(get_extruder_index(this->config, filament()->id())) * 60.0); + w.emit_f(this->config.travel_speed.get_at(m_cached_extruder_idx) * 60.0); w.emit_comment(GCodeWriter::full_gcode_comment, comment); out_string = w.string(); } @@ -880,10 +882,10 @@ std::string GCodeWriter::_travel_to_z(double z, const std::string &comment) { m_pos(2) = z; - double speed = this->config.travel_speed_z.get_at(get_extruder_index(this->config, filament()->id())); + double speed = this->config.travel_speed_z.get_at(m_cached_extruder_idx); if (speed == 0.) { - speed = m_is_first_layer ? this->config.get_abs_value_at("initial_layer_travel_speed", get_extruder_index(this->config, filament()->id())) - : this->config.travel_speed.get_at(get_extruder_index(this->config, filament()->id())); + speed = m_is_first_layer ? this->config.get_abs_value_at("initial_layer_travel_speed", m_cached_extruder_idx) + : this->config.travel_speed.get_at(m_cached_extruder_idx); } GCodeG1Formatter w; @@ -897,11 +899,11 @@ std::string GCodeWriter::_travel_to_z(double z, const std::string &comment) std::string GCodeWriter::_spiral_travel_to_z(double z, const Vec2d &ij_offset, const std::string &comment) { std::string output; - double speed = this->config.travel_speed_z.get_at(get_extruder_index(this->config, filament()->id())); + double speed = this->config.travel_speed_z.get_at(m_cached_extruder_idx); if (speed == 0.) { - speed = m_is_first_layer ? this->config.get_abs_value_at("initial_layer_travel_speed", get_extruder_index(this->config, filament()->id())) - : this->config.travel_speed.get_at(get_extruder_index(this->config, filament()->id())); + speed = m_is_first_layer ? this->config.get_abs_value_at("initial_layer_travel_speed", m_cached_extruder_idx) + : this->config.travel_speed.get_at(m_cached_extruder_idx); } if (!this->config.enable_arc_fitting) { // Orca: if arc fitting is disabled, approximate the arc with small linear segments @@ -1261,6 +1263,7 @@ void GCodeWriter::init_extruder(unsigned int filament_id) assert(filament_extruder_iter != m_filament_extruders.end() && filament_extruder_iter->id() == filament_id); m_curr_extruder_id = filament_extruder_iter->extruder_id(); m_curr_filament_extruder[m_curr_extruder_id] = &*filament_extruder_iter; + m_cached_extruder_idx = get_extruder_index(this->config, filament_id); } } diff --git a/src/libslic3r/GCodeWriter.hpp b/src/libslic3r/GCodeWriter.hpp index d3f419df7c..358356e0e0 100644 --- a/src/libslic3r/GCodeWriter.hpp +++ b/src/libslic3r/GCodeWriter.hpp @@ -19,6 +19,7 @@ public: GCodeWriter() : multiple_extruders(false), m_curr_filament_extruder(MAXIMUM_EXTRUDER_NUMBER, nullptr), m_curr_extruder_id (-1), + m_cached_extruder_idx(0), m_single_extruder_multi_material(false), m_last_acceleration(0), m_max_acceleration(0),m_last_travel_acceleration(0), m_max_travel_acceleration(0), m_last_jerk(0), m_max_jerk_x(0), m_max_jerk_y(0), @@ -135,6 +136,8 @@ public: bool m_single_extruder_multi_material; std::vector m_curr_filament_extruder; int m_curr_extruder_id; + // Motion uses the global/base process variant until a filament becomes active. + size_t m_cached_extruder_idx; unsigned int m_last_acceleration; unsigned int m_last_travel_acceleration; std::vector m_max_travel_acceleration; diff --git a/src/libslic3r/Layer.hpp b/src/libslic3r/Layer.hpp index d871bcbea2..8a5aa78036 100644 --- a/src/libslic3r/Layer.hpp +++ b/src/libslic3r/Layer.hpp @@ -157,6 +157,10 @@ public: ExPolygons lslices; ExPolygons lslices_extrudable; // BBS: the extrudable part of lslices used for tree support std::vector lslices_bboxes; + // Orca: for separated infills / per-model centering. Aligned with lslices: for each island, the + // full bounding box of the 3D connected body (across all layers) it belongs to. Populated by + // PrintObject::infill() only when the feature is used; empty otherwise. + std::vector lslices_separated_component_bboxes; // BBS ExPolygons loverhangs; diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index b15124d9ed..2d46bc4cdf 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -920,6 +920,13 @@ public: // Extruder ID is only valid for FFF. Returns -1 for SLA or if the extruder ID is not applicable (support volumes). int extruder_id() const; + //Orca: cache clearing procedure to ensure that the shape is positioned accurately when manipulating it + void clear_cache() { + m_cached_trans_matrix = Transform3d::Identity().inverse(); // get unvelivable matrix + m_convex_hull_2d.clear(); + m_cached_2d_polygon.clear(); + }; + bool is_splittable() const; // BBS @@ -966,34 +973,34 @@ public: static std::string type_to_string(const ModelVolumeType t); const Geometry::Transformation& get_transformation() const { return m_transformation; } - void set_transformation(const Geometry::Transformation& transformation) { m_transformation = transformation; } - void set_transformation(const Transform3d& trafo) { m_transformation.set_matrix(trafo); } + void set_transformation(const Geometry::Transformation& transformation) { clear_cache(); m_transformation = transformation; } + void set_transformation(const Transform3d& trafo) { clear_cache(); m_transformation.set_matrix(trafo); } Vec3d get_offset() const { return m_transformation.get_offset(); } double get_offset(Axis axis) const { return m_transformation.get_offset(axis); } - void set_offset(const Vec3d& offset) { m_transformation.set_offset(offset); } - void set_offset(Axis axis, double offset) { m_transformation.set_offset(axis, offset); } + void set_offset(const Vec3d& offset) { clear_cache(); m_transformation.set_offset(offset); } + void set_offset(Axis axis, double offset) { clear_cache(); m_transformation.set_offset(axis, offset); } Vec3d get_rotation() const { return m_transformation.get_rotation(); } double get_rotation(Axis axis) const { return m_transformation.get_rotation(axis); } - void set_rotation(const Vec3d& rotation) { m_transformation.set_rotation(rotation); } - void set_rotation(Axis axis, double rotation) { m_transformation.set_rotation(axis, rotation); } + void set_rotation(const Vec3d& rotation) { clear_cache(); m_transformation.set_rotation(rotation); } + void set_rotation(Axis axis, double rotation) { clear_cache(); m_transformation.set_rotation(axis, rotation); } Vec3d get_scaling_factor() const { return m_transformation.get_scaling_factor(); } double get_scaling_factor(Axis axis) const { return m_transformation.get_scaling_factor(axis); } - void set_scaling_factor(const Vec3d& scaling_factor) { m_transformation.set_scaling_factor(scaling_factor); } - void set_scaling_factor(Axis axis, double scaling_factor) { m_transformation.set_scaling_factor(axis, scaling_factor); } + void set_scaling_factor(const Vec3d& scaling_factor) { clear_cache(); m_transformation.set_scaling_factor(scaling_factor); } + void set_scaling_factor(Axis axis, double scaling_factor) {clear_cache(); m_transformation.set_scaling_factor(axis, scaling_factor); } Vec3d get_mirror() const { return m_transformation.get_mirror(); } double get_mirror(Axis axis) const { return m_transformation.get_mirror(axis); } bool is_left_handed() const { return m_transformation.is_left_handed(); } - void set_mirror(const Vec3d& mirror) { m_transformation.set_mirror(mirror); } - void set_mirror(Axis axis, double mirror) { m_transformation.set_mirror(axis, mirror); } + void set_mirror(const Vec3d& mirror) { clear_cache(); m_transformation.set_mirror(mirror); } + void set_mirror(Axis axis, double mirror) { clear_cache(); m_transformation.set_mirror(axis, mirror); } void convert_from_imperial_units(); void convert_from_meters(); diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index 6c29367c01..1c785c3184 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -571,6 +571,19 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator& p return extrusion_coll; } +// ORCA: only_one_wall_top detects the top as "slice − upper", so a feature rising from the middle of a +// top surface becomes an enclosed hole that gets ringed with extra inner walls. Fill those holes back +// into the top. Only holes that are both covered by the upper layer (excludes bridges) and backed by +// solid material (excludes voids) are filled. +static ExPolygons fill_enclosed_top_feature_holes(const ExPolygons &top, const Polygons &covered_by_upper, const ExPolygons &solid) +{ + ExPolygons filled = top; + for (ExPolygon &ex : filled) + ex.holes.clear(); + const ExPolygons feature_holes = intersection_ex(intersection_ex(diff_ex(filled, top), covered_by_upper), solid); + return feature_holes.empty() ? top : union_ex(top, feature_holes); +} + void PerimeterGenerator::split_top_surfaces(const ExPolygons &orig_polygons, ExPolygons &top_fills, ExPolygons &non_top_polygons, ExPolygons &fill_clip) const { // other perimeters @@ -636,6 +649,8 @@ void PerimeterGenerator::split_top_surfaces(const ExPolygons &orig_polygons, ExP ExPolygons delete_bridge = diff_ex(orig_polygons, bridge_checker, ApplySafetyOffset::Yes); ExPolygons top_polygons = diff_ex(delete_bridge, upper_polygons_series_clipped, ApplySafetyOffset::Yes); + top_polygons = fill_enclosed_top_feature_holes(top_polygons, upper_polygons_series_clipped, orig_polygons); + // get the not-top surface, from the "real top" but enlarged by external_infill_margin (and the // min_width_top_surface we removed a bit before) ExPolygons temp_gap = diff_ex(top_polygons, fill_clip); @@ -2194,6 +2209,7 @@ void PerimeterGenerator::process_arachne() upper_slices_clipped = ClipperUtils::clip_clipper_polygons_with_subject_bbox(*upper_slices, infill_contour_bbox); top_expolygons = diff_ex(infill_contour, upper_slices_clipped); + top_expolygons = fill_enclosed_top_feature_holes(top_expolygons, upper_slices_clipped, infill_contour); if (!top_expolygons.empty()) { if (lower_slices != nullptr) { diff --git a/src/libslic3r/PlaceholderParser.cpp b/src/libslic3r/PlaceholderParser.cpp index 865b70434b..e3a4037590 100644 --- a/src/libslic3r/PlaceholderParser.cpp +++ b/src/libslic3r/PlaceholderParser.cpp @@ -712,6 +712,26 @@ namespace client static void regex_matches (expr &lhs, IteratorRange &rhs) { return regex_op(lhs, rhs, '=', lhs); } static void regex_doesnt_match(expr &lhs, IteratorRange &rhs) { return regex_op(lhs, rhs, '!', lhs); } + // Replace every match of the regular expression 'pattern' in the string 'subject' with 'replacement'. + // The replacement may reference capture groups ($1, $2, ...). Store the result into subject. + static void regex_replace(expr &subject, IteratorRange &pattern, expr &replacement) + { + if (subject.type() == TYPE_EMPTY) + // Inside an if / else block to be skipped + return; + if (subject.type() != TYPE_STRING) + subject.throw_exception("regex_replace() first parameter must be a string."); + try { + std::string re(++ pattern.begin(), -- pattern.end()); + std::string result = SLIC3R_REGEX_NAMESPACE::regex_replace(subject.s(), SLIC3R_REGEX_NAMESPACE::regex(re), replacement.to_string()); + subject.set_s(std::move(result)); + } catch (SLIC3R_REGEX_NAMESPACE::regex_error &ex) { + // Syntax error in the regular expression + boost::throw_exception(qi::expectation_failure( + pattern.begin(), pattern.end(), spirit::info(std::string("*Regular expression compilation failed: ") + ex.what()))); + } + } + static void one_of_test_init(expr &out) { out.set_b(false); } @@ -2323,6 +2343,8 @@ namespace client [ px::bind(&expr::digits, _val, _2, _3) ] | (kw["zdigits"] > '(' > conditional_expression(_r1) [_val = _1] > ',' > conditional_expression(_r1) > optional_parameter(_r1)) [ px::bind(&expr::digits, _val, _2, _3) ] + | (kw["regex_replace"] > '(' > conditional_expression(_r1) [_val = _1] > ',' > regular_expression > ',' > conditional_expression(_r1) > ')') + [ px::bind(&expr::regex_replace, _val, _2, _3) ] | (kw["int"] > '(' > conditional_expression(_r1) > ')') [ px::bind(&FactorActions::to_int, _1, _val) ] | (kw["round"] > '(' > conditional_expression(_r1) > ')') [ px::bind(&FactorActions::round, _1, _val) ] | (kw["ceil"] > '(' > conditional_expression(_r1) > ')') [ px::bind(&FactorActions::ceil, _1, _val) ] @@ -2404,6 +2426,7 @@ namespace client ("min") ("max") ("random") + ("regex_replace") ("filament_change") ("repeat") ("round") diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 077814130d..ee5a9266a8 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -892,12 +892,11 @@ std::string Preset::get_printer_type(PresetBundle *preset_bundle) { if (preset_bundle) { auto config = &preset_bundle->printers.get_edited_preset().config; - std::string vendor_name; - for (auto vendor_profile : preset_bundle->vendors) { - for (auto vendor_model : vendor_profile.second.models) - if (vendor_model.name == config->opt_string("printer_model")) + const auto& printer_model = config->opt_string("printer_model"); + for (const auto& vendor_profile : preset_bundle->vendors) { + for (const auto& vendor_model : vendor_profile.second.models) + if (vendor_model.name == printer_model) { - vendor_name = vendor_profile.first; return vendor_model.model_id; } } @@ -909,11 +908,10 @@ std::string Preset::get_current_printer_type(PresetBundle *preset_bundle) { if (preset_bundle) { auto config = &(this->config); - std::string vendor_name; - for (auto vendor_profile : preset_bundle->vendors) { - for (auto vendor_model : vendor_profile.second.models) - if (vendor_model.name == config->opt_string("printer_model")) { - vendor_name = vendor_profile.first; + const auto& printer_model = config->opt_string("printer_model"); + for (const auto& vendor_profile : preset_bundle->vendors) { + for (const auto& vendor_model : vendor_profile.second.models) + if (vendor_model.name == printer_model) { return vendor_model.model_id; } } @@ -1046,6 +1044,9 @@ static std::vector s_Preset_print_options{ "lightning_prune_angle", "lightning_straightening_angle", "top_surface_pattern", + "top_surface_expansion", + "top_surface_expansion_margin", + "top_surface_expansion_direction", "bottom_surface_pattern", "infill_direction", "solid_infill_direction", @@ -1062,6 +1063,9 @@ static std::vector s_Preset_print_options{ "skin_infill_density", "align_infill_direction_to_model", "extra_solid_infills", + "anisotropic_surfaces", + "center_of_surface_pattern", + "separated_infills", "minimum_sparse_infill_area", "reduce_infill_retraction", "internal_solid_infill_pattern", @@ -1274,6 +1278,7 @@ static std::vector s_Preset_print_options{ "wipe_tower_bridging", "wipe_tower_extra_flow", "single_extruder_multi_material_priming", + "toolchange_ordering", "wipe_tower_rotation_angle", "tree_support_branch_distance_organic", "tree_support_branch_diameter_organic", diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index a676d24cc0..1242d5a7ff 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -209,6 +209,9 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n "chamber_minimal_temperature", "thumbnails", "thumbnails_format", + "anisotropic_surfaces", + "center_of_surface_pattern", + "separated_infills", "seam_gap", "role_based_wipe_speed", "wipe_speed", @@ -330,6 +333,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n || opt_key == "first_layer_print_sequence" || opt_key == "other_layers_print_sequence" || opt_key == "other_layers_print_sequence_nums" + || opt_key == "toolchange_ordering" || opt_key == "extruder_ams_count" || opt_key == "filament_map_mode" || opt_key == "filament_map" diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index b9f70506fb..059b724090 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -418,7 +418,7 @@ public: // (layer height, first layer height, raft settings, print nozzle diameter etc). const SlicingParameters& slicing_parameters() const { return m_slicing_params; } // Orca: XYZ shrinkage compensation has introduced the const Vec3d &object_shrinkage_compensation parameter to the function below - static SlicingParameters slicing_parameters(const DynamicPrintConfig &full_config, const ModelObject &model_object, float object_max_z, const Vec3d &object_shrinkage_compensation); + static SlicingParameters slicing_parameters(const DynamicPrintConfig &full_config, const ModelObject &model_object, float object_max_z, const Vec3d &object_shrinkage_compensation, std::vector variant_index = std::vector()); size_t num_printing_regions() const throw() { return m_shared_regions->all_regions.size(); } const PrintRegion& printing_region(size_t idx) const throw() { return *m_shared_regions->all_regions[idx].get(); } @@ -489,7 +489,7 @@ public: // If ! m_slicing_params.valid, recalculate. void update_slicing_parameters(); - static PrintObjectConfig object_config_from_model_object(const PrintObjectConfig &default_object_config, const ModelObject &object, size_t num_extruders); + static PrintObjectConfig object_config_from_model_object(const PrintObjectConfig &default_object_config, const ModelObject &object, size_t num_extruders, std::vector& variant_index); private: void make_perimeters(); diff --git a/src/libslic3r/PrintApply.cpp b/src/libslic3r/PrintApply.cpp index 0678f75277..8035cf3f27 100644 --- a/src/libslic3r/PrintApply.cpp +++ b/src/libslic3r/PrintApply.cpp @@ -724,7 +724,7 @@ PrintObjectRegions::BoundingBox find_modifier_volume_extents(const PrintObjectRe return out; } -PrintRegionConfig region_config_from_model_volume(const PrintRegionConfig &default_or_parent_region_config, const DynamicPrintConfig *layer_range_config, const ModelVolume &volume, size_t num_extruders); +PrintRegionConfig region_config_from_model_volume(const PrintRegionConfig &default_or_parent_region_config, const DynamicPrintConfig *layer_range_config, const ModelVolume &volume, size_t num_extruders, std::vector& variant_index); void print_region_ref_inc(PrintRegion &r) { ++ r.m_ref_cnt; } void print_region_ref_reset(PrintRegion &r) { r.m_ref_cnt = 0; } @@ -738,7 +738,8 @@ bool verify_update_print_object_regions( const PrintRegionConfig &default_region_config, size_t num_extruders, PrintObjectRegions &print_object_regions, - const std::function &callback_invalidate) + const std::function &callback_invalidate, + std::vector& variant_index) { // Sort by ModelVolume ID. model_volumes_sort_by_id(model_volumes); @@ -783,7 +784,7 @@ bool verify_update_print_object_regions( } else if (PrintObjectRegions::BoundingBox parent_bbox = find_modifier_volume_extents(layer_range, parent_region_id); parent_bbox.intersects(*bbox)) // Such parent region does not exist. If it is needed, then we need to reslice. // Only create new region for a modifier, which actually modifies config of it's parent. - if (PrintRegionConfig config = region_config_from_model_volume(parent_region.region->config(), nullptr, **it_model_volume, num_extruders); + if (PrintRegionConfig config = region_config_from_model_volume(parent_region.region->config(), nullptr, **it_model_volume, num_extruders, variant_index); config != parent_region.region->config()) // This modifier newly overrides a region, which it did not before. We need to reslice. return false; @@ -791,8 +792,8 @@ bool verify_update_print_object_regions( } } PrintRegionConfig cfg = region.parent == -1 ? - region_config_from_model_volume(default_region_config, layer_range.config, **it_model_volume, num_extruders) : - region_config_from_model_volume(layer_range.volume_regions[region.parent].region->config(), nullptr, **it_model_volume, num_extruders); + region_config_from_model_volume(default_region_config, layer_range.config, **it_model_volume, num_extruders, variant_index) : + region_config_from_model_volume(layer_range.volume_regions[region.parent].region->config(), nullptr, **it_model_volume, num_extruders, variant_index); if (cfg != region.region->config()) { // Region configuration changed. if (print_region_ref_cnt(*region.region) == 0) { @@ -964,6 +965,7 @@ static PrintObjectRegions* generate_print_object_regions( size_t num_extruders, const float xy_contour_compensation, const std::vector &painting_extruders, + std::vector &variant_index, const bool has_painted_fuzzy_skin) { // Reuse the old object or generate a new one. @@ -1022,7 +1024,7 @@ static PrintObjectRegions* generate_print_object_regions( // Add a model volume, assign an existing region or generate a new one. layer_range.volume_regions.push_back({ &volume, -1, - get_create_region(region_config_from_model_volume(default_region_config, layer_range.config, volume, num_extruders)), + get_create_region(region_config_from_model_volume(default_region_config, layer_range.config, volume, num_extruders, variant_index)), bbox }); } else if (volume.is_negative_volume()) { @@ -1039,7 +1041,7 @@ static PrintObjectRegions* generate_print_object_regions( if (parent_volume.is_model_part() || parent_volume.is_modifier()) if (PrintObjectRegions::BoundingBox parent_bbox = find_modifier_volume_extents(layer_range, parent_region_id); parent_bbox.intersects(*bbox)) { // Only create new region for a modifier, which actually modifies config of it's parent. - if (PrintRegionConfig config = region_config_from_model_volume(parent_region.region->config(), nullptr, volume, num_extruders); + if (PrintRegionConfig config = region_config_from_model_volume(parent_region.region->config(), nullptr, volume, num_extruders, variant_index); config != parent_region.region->config()) { added = true; layer_range.volume_regions.push_back({ &volume, parent_region_id, get_create_region(std::move(config)), bbox }); @@ -1162,12 +1164,13 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_ } //apply extruder related values + std::vector print_variant_index; if (!extruder_applied) { // variant_2 must be processed first, because variant_1 will make `printer_extruder_id` and `printer_extruder_variant` half of the size that makes `get_index_for_extruder` no longer work properly new_full_config.update_values_to_printer_extruders(new_full_config, printer_options_with_variant_2, "printer_extruder_id", "printer_extruder_variant", 2); new_full_config.update_values_to_printer_extruders(new_full_config, printer_options_with_variant_1, "printer_extruder_id", "printer_extruder_variant"); //update print config related with variants - new_full_config.update_values_to_printer_extruders(new_full_config, print_options_with_variant, "print_extruder_id", "print_extruder_variant"); + print_variant_index = new_full_config.update_values_to_printer_extruders(new_full_config, print_options_with_variant, "print_extruder_id", "print_extruder_variant"); m_ori_full_print_config = new_full_config; new_full_config.update_values_to_printer_extruders_for_multiple_filaments(new_full_config, filament_options_with_variant, "filament_self_index", "filament_extruder_variant"); @@ -1475,7 +1478,7 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_ if (object_config_changed) model_object.config.assign_config(model_object_new.config); if (! object_diff.empty() || object_config_changed || num_extruders_changed ) { - PrintObjectConfig new_config = PrintObject::object_config_from_model_object(m_default_object_config, model_object, num_extruders ); + PrintObjectConfig new_config = PrintObject::object_config_from_model_object(m_default_object_config, model_object, num_extruders, print_variant_index); for (const PrintObjectStatus &print_object_status : print_object_status_db.get_range(model_object)) { t_config_option_keys diff = print_object_status.print_object->config().diff(new_config); if (! diff.empty()) { @@ -1541,10 +1544,10 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_ // Generate a list of trafos and XY offsets for instances of a ModelObject // Producing the config for PrintObject on demand, caching it at print_object_last. const PrintObject *print_object_last = nullptr; - auto print_object_apply_config = [this, &print_object_last, model_object, num_extruders ](PrintObject *print_object) { + auto print_object_apply_config = [this, &print_object_last, model_object, num_extruders, &print_variant_index](PrintObject *print_object) { print_object->config_apply(print_object_last ? print_object_last->config() : - PrintObject::object_config_from_model_object(m_default_object_config, *model_object, num_extruders )); + PrintObject::object_config_from_model_object(m_default_object_config, *model_object, num_extruders, print_variant_index)); print_object_last = print_object; }; if (old.empty()) { @@ -1715,7 +1718,8 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_ for (auto it = it_print_object; it != it_print_object_end; ++it) if ((*it)->m_shared_regions != nullptr) update_apply_status((*it)->invalidate_state_by_config_options(old_config, new_config, diff_keys)); - })) { + }, + print_variant_index)) { // Regions are valid, just keep them. } else { // Regions were reshuffled. @@ -1737,6 +1741,7 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_ num_extruders , print_object.is_mm_painted() ? 0.f : float(print_object.config().xy_contour_compensation.value), painting_extruders, + print_variant_index, print_object.is_fuzzy_skin_painted()); } for (auto it = it_print_object; it != it_print_object_end; ++it) diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 7c116dce3e..f703da5805 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -188,6 +188,12 @@ static t_config_enum_values s_keys_map_PowerLossRecoveryMode { }; CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(PowerLossRecoveryMode) +static t_config_enum_values s_keys_map_CenterOfSurfacePattern{ + {"each_surface", int(CenterOfSurfacePattern::Each_Surface)}, + {"each_model", int(CenterOfSurfacePattern::Each_Model)}, + {"each_assembly", int(CenterOfSurfacePattern::Each_Assembly)}}; +CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(CenterOfSurfacePattern) + static t_config_enum_values s_keys_map_FuzzySkinType { { "none", int(FuzzySkinType::None) }, { "external", int(FuzzySkinType::External) }, @@ -221,6 +227,13 @@ static t_config_enum_values s_keys_map_FuzzySkinMode { }; CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(FuzzySkinMode) +static t_config_enum_values s_keys_map_TopSurfaceExpansionDirection { + { "inward_and_outward", int(TopSurfaceExpansionDirection::InwardAndOutward) }, + { "inward", int(TopSurfaceExpansionDirection::Inward) }, + { "outward", int(TopSurfaceExpansionDirection::Outward) } +}; +CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(TopSurfaceExpansionDirection) + static t_config_enum_values s_keys_map_InfillPattern { { "monotonic", ipMonotonic }, { "monotonicline", ipMonotonicLine }, @@ -522,6 +535,12 @@ static t_config_enum_values s_keys_map_PerimeterGeneratorType{ }; CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(PerimeterGeneratorType) +static t_config_enum_values s_keys_map_ToolChangeOrderingType { + { "default", int(ToolChangeOrderingType::Default) }, + { "cyclic", int(ToolChangeOrderingType::Cyclic) } +}; +CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(ToolChangeOrderingType) + static const t_config_enum_values s_keys_map_ZHopType = { { "Auto Lift", zhtAuto }, { "Normal Lift", zhtNormal }, @@ -1236,7 +1255,7 @@ void PrintConfigDef::init_fff_params() "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" - " - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" + " - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n\n" "Use 180° for zero absolute angle."); def->sidetext = u8"°"; // degrees, don't need translation @@ -1253,7 +1272,7 @@ void PrintConfigDef::init_fff_params() "If left to zero, the bridging angle will be calculated automatically for each specific bridge.\n" "Otherwise the provided angle will be used according to:\n" " - The absolute coordinates\n" - " - The absolute coordinates + Model rotation: If Align infill direction to model is enabled\n" + " - The absolute coordinates + Model rotation: If Align directions to model is enabled\n" " - The optimal automatic angle + this value: If 'Relative Bridge Angle' is enabled\n\n" "Use 180° for zero absolute angle."); def->sidetext = u8"°"; // degrees, don't need translation @@ -2117,6 +2136,47 @@ void PrintConfigDef::init_fff_params() def->max = 100; def->set_default_value(new ConfigOptionPercent(100)); + def = this->add("top_surface_expansion", coFloat); + def->label = L("Top surface expansion"); + def->category = L("Strength"); + def->tooltip = L("Expands the top surfaces by this distance to connect distinct top surfaces and fill gaps.\n" + "Useful for cases where the top surface is interrupted by a raised feature, such as text on a plane." + "Expanding it removes the holes beneath these features and creates a continuous path with a better finish for printing on top." + "The expansion is applied to the original top surface, before any other processing such as bridging or overhang detection."); + def->sidetext = L("mm"); + def->min = 0; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloat(0)); + + def = this->add("top_surface_expansion_margin", coFloat); + def->label = L("Top expansion wall margin"); + def->category = L("Strength"); + def->tooltip = L("Using “Top surface expansion” may cause a surface that did not previously touch the model's outer walls to now do so.\n" + "This can cause contraction marks (such as the hull line) on the outer walls.\n" + "By adding a small margin, this contraction will not occur directly on the walls, thereby preventing a visible mark."); + def->sidetext = L("mm"); + def->min = 0; + def->max = 10; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloat(0)); + + def = this->add("top_surface_expansion_direction", coEnum); + def->label = L("Top expansion direction"); + def->category = L("Strength"); + def->tooltip = L("Direction in which the top surface expansion grows.\n" + " - Inward grows into the holes and gaps left by features rising from the middle of a top surface.\n" + " - Outward grows the outer edge of the surface, connecting surfaces separated by features that can divide a surface, such as a lattice pattern.\n" + " - Inward and Outward does both."); + def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); + def->enum_values.push_back("inward_and_outward"); + def->enum_values.push_back("inward"); + def->enum_values.push_back("outward"); + def->enum_labels.push_back(L("Inward and Outward")); + def->enum_labels.push_back(L("Inward")); + def->enum_labels.push_back(L("Outward")); + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionEnum(TopSurfaceExpansionDirection::InwardAndOutward)); + def = this->add("bottom_surface_pattern", coEnum); def->label = L("Bottom surface pattern"); def->category = L("Strength"); @@ -3035,12 +3095,13 @@ void PrintConfigDef::init_fff_params() def->min = 0; def->max = 100; def->set_default_value(new ConfigOptionPercent(20)); - + def = this->add("align_infill_direction_to_model", coBool); - def->label = L("Align infill direction to model"); + def->label = L("Align directions to model"); def->category = L("Strength"); - def->tooltip = L("Aligns infill, bridge, ironing and surface fill directions to follow the model's orientation on the build plate.\n" - "When enabled, directions rotate with the model to maintain optimal strength characteristics."); + def->tooltip = L("Aligns infill, bridge, ironing, and top/bottom surface directions to follow the model's orientation on the build plate.\n" + "When enabled, these directions rotate together with the model so the printed features keep their intended orientation " + "relative to the part, preserving optimal strength and surface characteristics regardless of how the model is placed."); def->mode = comAdvanced; def->set_default_value(new ConfigOptionBool(false)); @@ -6076,6 +6137,22 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionBool(false)); + def = this->add("toolchange_ordering", coEnum); + def->label = L("Toolchange ordering"); + def->category = L("Advanced"); + def->tooltip = L( + "Determines the order of tool changes on each layer.\n" + "- Default: Starts with the last used extruder to minimize tool changes.\n" + "- Cyclic: Uses a fixed tool sequence each layer. This sacrifices speed for better surface quality, as the extra toolchanges allow layers more time to cool." + ); + def->mode = comAdvanced; + def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); + def->enum_values.emplace_back("default"); + def->enum_values.emplace_back("cyclic"); + def->enum_labels.emplace_back(L("Default")); + def->enum_labels.emplace_back(L("Cyclic")); + def->set_default_value(new ConfigOptionEnum(ToolChangeOrderingType::Default)); + def = this->add("slice_closing_radius", coFloat); def->label = L("Slice gap closing radius"); def->category = L("Quality"); @@ -6799,6 +6876,47 @@ void PrintConfigDef::init_fff_params() def->min = 0; def->set_default_value(new ConfigOptionFloat(0.6)); + def = this->add("anisotropic_surfaces", coBool); + def->label = L("Anisotropic surfaces"); + def->category = L("Strength"); + def->tooltip = L("Anisotropic patterns on the top and bottom surfaces.\n" + "Co-directional printing mode will be applied. For certain patterns, omni-directional filling provides color " + "dispersion when using multi-colored or silk plastics.\n" + "This option disable the gap fill.\n" + "This option can increase a printing time."); + def->mode = comExpert; + def->set_default_value(new ConfigOptionBool(false)); + + def = this->add("separated_infills", coBool); + def->label = L("Separated infills"); + def->category = L("Strength"); + def->tooltip = L("Centers the internal infill of each part on itself, as if it were sliced on its own, instead of on the " + "whole assembly. Parts that touch or overlap are treated as one body and share a center; separate parts " + "(or distinct 3D objects) each get their own.\n" + "Useful when an assembly groups several objects that should each keep a consistent, self-centered infill.\n" + "Affects line and grid patterns and rotation-template infills.\n" + "Patterns locked to global coordinates (Gyroid, Honeycomb, TPMS, ...) are unaffected."); + def->mode = comExpert; + def->set_default_value(new ConfigOptionBool(false)); + + def = this->add("center_of_surface_pattern", coEnum); + def->label = L("Center surface pattern on"); + def->category = L("Strength"); + def->tooltip = L("Chooses where the centering point of centered top/bottom surface patterns (Archimedean Chords, " + "Octagram Spiral) is placed.\n" + " - Each Surface: centers the pattern on every individual surface region, so each island is symmetric on its own.\n" + " - Each Model: centers the pattern on each connected body. Parts that touch or overlap share one center; " + "parts detached from the rest each get their own.\n" + " - Each Assembly: uses a single shared center for the whole object or assembly."); + def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); + def->enum_values.push_back("each_surface"); + def->enum_values.push_back("each_model"); + def->enum_values.push_back("each_assembly"); + def->enum_labels.push_back(L("Each Surface")); + def->enum_labels.push_back(L("Each Model")); + def->enum_labels.push_back(L("Each Assembly")); + def->mode = comExpert; + def->set_default_value(new ConfigOptionEnum(CenterOfSurfacePattern::Each_Surface)); def = this->add("travel_speed", coFloats); def->label = L("Travel"); @@ -9519,7 +9637,7 @@ int DynamicPrintConfig::update_values_from_multi_to_multi_2(const std::vector::max(); for(auto idx : indices){ - if(opt && !opt->is_nil(idx)){ + if(opt && idx < opt->values.size() && !opt->is_nil(idx)){ has_value = true; target_value = std::min(target_value, src_values[idx]); } @@ -9706,10 +9824,12 @@ DynamicPrintConfig::get_filament_type() const return std::string(); } -void DynamicPrintConfig::update_values_to_printer_extruders(DynamicPrintConfig& printer_config, std::set& key_set, std::string id_name, std::string variant_name, unsigned int stride, unsigned int extruder_id) +std::vector DynamicPrintConfig::update_values_to_printer_extruders(DynamicPrintConfig& printer_config, std::set& key_set, std::string id_name, std::string variant_name, unsigned int stride, unsigned int extruder_id) { int extruder_count; bool different_extruder = printer_config.support_different_extruders(extruder_count); + std::vector variant_index; + if ((extruder_count > 1) || different_extruder) { BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", Line %1%: different extruders processing")%__LINE__; @@ -9720,9 +9840,9 @@ void DynamicPrintConfig::update_values_to_printer_extruders(DynamicPrintConfig& auto opt_nozzle_volume_type = dynamic_cast(printer_config.option("nozzle_volume_type")); if (!opt_extruder_type || !opt_nozzle_volume_type) { BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", Line %1%: extruder_type or nozzle_volume_type option not found, skipping")%__LINE__; - return; + return variant_index; } - std::vector variant_index; + if (extruder_id > 0 && extruder_id <= static_cast (extruder_count)) { variant_index.resize(1); @@ -9761,7 +9881,7 @@ void DynamicPrintConfig::update_values_to_printer_extruders(DynamicPrintConfig& const ConfigDef *config_def = this->def(); if (!config_def) { BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(", Line %1%: can not find config define")%__LINE__; - return; + return variant_index; } for (auto& key: key_set) { @@ -9875,6 +9995,8 @@ void DynamicPrintConfig::update_values_to_printer_extruders(DynamicPrintConfig& } } } + + return variant_index; } void DynamicPrintConfig::update_values_to_printer_extruders_for_multiple_filaments(DynamicPrintConfig& printer_config, std::set& key_set, std::string id_name, std::string variant_name) @@ -10407,6 +10529,28 @@ void compute_filament_override_value(const std::string& opt_key, const ConfigOpt } +void update_static_print_config_from_dynamic(ConfigBase& config, const DynamicPrintConfig& dest_config, std::vector variant_index, std::set& key_set1, int stride) +{ + if (variant_index.size() > 0) { + const t_config_option_keys &keys = dest_config.keys(); + for (auto& opt : keys) { + ConfigOption *opt_src = config.option(opt); + const ConfigOption *opt_dest = dest_config.option(opt); + if (opt_src && opt_dest && (*opt_src != *opt_dest)) { + if (opt_dest->is_scalar() || (key_set1.find(opt) == key_set1.end())) + opt_src->set(opt_dest); + else { + ConfigOptionVectorBase* opt_vec_src = static_cast(opt_src); + const ConfigOptionVectorBase* opt_vec_dest = static_cast(opt_dest); + opt_vec_src->set_to_index(opt_vec_dest, variant_index, stride); + } + } + } + } + else + config.apply(dest_config, true); +} + //BBS: pass map to recording all invalid valies //FIXME localize this function. std::map validate(const FullPrintConfig &cfg, bool under_cli) diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 6ea1f9db1c..6b65860edf 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -62,6 +62,19 @@ enum class FuzzySkinMode { Combined, }; +// ORCA: direction in which top_surface_expansion grows the top surfaces. +enum class TopSurfaceExpansionDirection { + InwardAndOutward, + Inward, + Outward, +}; + +enum class CenterOfSurfacePattern { + Each_Surface, + Each_Model, + Each_Assembly, +}; + enum class NoiseType { Classic, Perlin, @@ -97,6 +110,34 @@ enum InfillPattern : int { ipCount, }; +// Orca: Infill patterns whose alignment origin follows the fill bounding box, so the +// "separated_infills" option can re-center them per connected body. Patterns evaluated in +// absolute/global coordinates (Gyroid, TPMS, Honeycomb, CrossHatch, ...) or that are shape-relative +// (Concentric) ignore that bounding box and are therefore excluded. +inline bool is_separable_infill_pattern(InfillPattern pattern) +{ + switch (pattern) { + case ipRectilinear: + case ipAlignedRectilinear: + case ipZigZag: + case ipCrossZag: + case ipLockedZag: + case ipGrid: + case ipTriangles: + case ipStars: // tri-hexagon + case ipCubic: + case ipQuarterCubic: + case ipLateralHoneycomb: + case ipLateralLattice: + case ipHilbertCurve: + case ipArchimedeanChords: + case ipOctagramSpiral: + return true; + default: + return false; + } +} + enum class IroningType { NoIroning, TopSurfaces, @@ -300,6 +341,12 @@ enum class PerimeterGeneratorType Arachne }; +enum class ToolChangeOrderingType +{ + Default, + Cyclic, +}; + // BBS enum OverhangFanThreshold { Overhang_threshold_none = 0, @@ -534,6 +581,7 @@ CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(PrinterTechnology) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(GCodeFlavor) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(FuzzySkinType) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(FuzzySkinMode) +CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(TopSurfaceExpansionDirection) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(WipeTowerType) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(NoiseType) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(InfillPattern) @@ -561,6 +609,7 @@ CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(PrintHostType) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(AuthorizationType) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(WipeTowerWallType) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(PerimeterGeneratorType) +CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(ToolChangeOrderingType) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(PowerLossRecoveryMode) #undef CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS @@ -671,7 +720,7 @@ public: bool is_using_different_extruders(); bool support_different_extruders(int& extruder_count) const; int get_index_for_extruder(int extruder_or_filament_id, std::string id_name, ExtruderType extruder_type, NozzleVolumeType nozzle_volume_type, std::string variant_name, unsigned int stride = 1) const; - void update_values_to_printer_extruders(DynamicPrintConfig& printer_config, std::set& key_set, std::string id_name, std::string variant_name, unsigned int stride = 1, unsigned int extruder_id = 0); + std::vector update_values_to_printer_extruders(DynamicPrintConfig& printer_config, std::set& key_set, std::string id_name, std::string variant_name, unsigned int stride = 1, unsigned int extruder_id = 0); void update_values_to_printer_extruders_for_multiple_filaments(DynamicPrintConfig& printer_config, std::set& key_set, std::string id_name, std::string variant_name); void update_non_diff_values_to_base_config(DynamicPrintConfig& new_config, const t_config_option_keys& keys, const std::set& different_keys, std::string extruder_id_name, std::string extruder_variant_name, @@ -700,6 +749,7 @@ extern std::set empty_options; extern std::set filament_dev_options; +extern void update_static_print_config_from_dynamic(ConfigBase& config, const DynamicPrintConfig& dest_config, std::vector variant_index, std::set& key_set1, int stride = 1); extern void compute_filament_override_value(const std::string& opt_key, const ConfigOption *opt_old_machine, const ConfigOption *opt_new_machine, const ConfigOption *opt_new_filament, const DynamicPrintConfig& new_full_config, t_config_option_keys& diff_keys, DynamicPrintConfig& filament_overrides, std::vector& f_maps); @@ -1124,6 +1174,9 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionFloat, lightning_prune_angle)) ((ConfigOptionFloat, lightning_straightening_angle)) ((ConfigOptionBool, align_infill_direction_to_model)) + ((ConfigOptionBool, anisotropic_surfaces)) + ((ConfigOptionEnum, center_of_surface_pattern)) + ((ConfigOptionBool, separated_infills)) ((ConfigOptionString, extra_solid_infills)) ((ConfigOptionEnum, fuzzy_skin)) ((ConfigOptionFloat, fuzzy_skin_thickness)) @@ -1189,6 +1242,9 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionFloatOrPercent, top_surface_line_width)) ((ConfigOptionInt, top_shell_layers)) ((ConfigOptionFloat, top_shell_thickness)) + ((ConfigOptionFloat, top_surface_expansion)) + ((ConfigOptionFloat, top_surface_expansion_margin)) + ((ConfigOptionEnum, top_surface_expansion_direction)) ((ConfigOptionFloatsNullable, top_surface_speed)) //BBS ((ConfigOptionBoolsNullable, enable_overhang_speed)) @@ -1415,6 +1471,7 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionBool, single_extruder_multi_material)) ((ConfigOptionBool, manual_filament_change)) ((ConfigOptionBool, single_extruder_multi_material_priming)) + ((ConfigOptionEnum, toolchange_ordering)) ((ConfigOptionBool, wipe_tower_no_sparse_layers)) ((ConfigOptionString, change_filament_gcode)) ((ConfigOptionString, change_extrusion_role_gcode)) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 13d7297f93..d89a9b8ab4 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -4,6 +4,7 @@ #include "Print.hpp" #include "BoundingBox.hpp" #include "ClipperUtils.hpp" +#include "Clipper2Utils.hpp" #include "ElephantFootCompensation.hpp" #include "Geometry.hpp" #include "I18N.hpp" @@ -97,7 +98,7 @@ PrintObject::PrintObject(Print* print, ModelObject* model_object, const Transfor // snug height and an approximate bounding box in XY. BoundingBoxf3 bbox = model_object->raw_bounding_box(); Vec3d bbox_center = bbox.center(); - + // We may need to rotate the bbox / bbox_center from the original instance to the current instance. double z_diff = Geometry::rotation_diff_z(model_object->instances.front()->get_rotation(), instances.front().model_instance->get_rotation()); if (std::abs(z_diff) > EPSILON) { @@ -704,6 +705,72 @@ void PrintObject::infill() if (this->set_started(posInfill)) { m_print->set_status(35, L("Generating infill toolpath")); + + // Orca: precompute the object's 3D connected bodies for separated infills / per-model + // centering. Two islands belong to the same body when their slices overlap on adjacent + // layers; islands that only overlap in top-down projection but never touch (e.g. interleaved + // chain links) stay separate, matching "split to objects". Each layer island then records + // the full bounding box of its body, so its infill is centered on that body as if it were + // sliced alone. Done once here, before the parallel fill, and only when a region needs it. + bool needs_separated_components = false; + for (size_t i = 0; i < this->num_printing_regions(); ++ i) { + const PrintRegionConfig &rc = this->printing_region(i).config(); + if (rc.separated_infills || rc.center_of_surface_pattern == CenterOfSurfacePattern::Each_Model) { + needs_separated_components = true; + break; + } + } + // Fast path: the feature only changes anything when the object is made of more than one + // connected body. Detect that cheaply the same way as "Split to objects" — more than one + // model part, or a single part whose mesh is splittable (is_splittable() is cached). A single + // body already shares the object center, i.e. the default, so skip the connectivity pass. + if (needs_separated_components) { + int parts = 0; + const ModelVolume *first_part = nullptr; + for (const ModelVolume *v : this->model_object()->volumes) + if (v->is_model_part()) { ++ parts; first_part = v; } + if (parts <= 1 && ! (first_part != nullptr && first_part->is_splittable())) + needs_separated_components = false; + } + for (Layer *layer : m_layers) + layer->lslices_separated_component_bboxes.clear(); + if (needs_separated_components) { + const size_t nl = m_layers.size(); + std::vector offset(nl + 1, 0); // flat index of the first island of each layer + for (size_t i = 0; i < nl; ++ i) + offset[i + 1] = offset[i] + m_layers[i]->lslices.size(); + const size_t nreg = offset[nl]; + // Union-find over every (layer, island). + std::vector parent(nreg); + for (size_t i = 0; i < nreg; ++ i) parent[i] = i; + auto find = [&parent](size_t x) { + while (parent[x] != x) { parent[x] = parent[parent[x]]; x = parent[x]; } + return x; + }; + auto unite = [&](size_t a, size_t b) { a = find(a); b = find(b); if (a != b) parent[a] = b; }; + // Join islands that overlap between two consecutive layers. + for (size_t i = 0; i + 1 < nl; ++ i) { + const Layer *la = m_layers[i], *lb = m_layers[i + 1]; + for (size_t a = 0; a < la->lslices.size(); ++ a) + for (size_t b = 0; b < lb->lslices.size(); ++ b) + if (la->lslices_bboxes[a].overlap(lb->lslices_bboxes[b]) && + ! intersection_ex(la->lslices[a], lb->lslices[b]).empty()) + unite(offset[i] + a, offset[i + 1] + b); + } + // Full bounding box of each body, indexed by its union-find root. + std::vector body_bbox(nreg); + for (size_t i = 0; i < nl; ++ i) + for (size_t a = 0; a < m_layers[i]->lslices.size(); ++ a) + body_bbox[find(offset[i] + a)].merge(m_layers[i]->lslices_bboxes[a]); + // Store the body bbox for every island. + for (size_t i = 0; i < nl; ++ i) { + Layer *layer = m_layers[i]; + layer->lslices_separated_component_bboxes.resize(layer->lslices.size()); + for (size_t a = 0; a < layer->lslices.size(); ++ a) + layer->lslices_separated_component_bboxes[a] = body_bbox[find(offset[i] + a)]; + } + } + const auto& adaptive_fill_octree = this->m_adaptive_fill_octrees.first; const auto& support_fill_octree = this->m_adaptive_fill_octrees.second; @@ -1297,6 +1364,9 @@ bool PrintObject::invalidate_state_by_config_options( || opt_key == "infill_combination_max_layer_height" || opt_key == "bottom_shell_thickness" || opt_key == "top_shell_thickness" + || opt_key == "top_surface_expansion" + || opt_key == "top_surface_expansion_margin" + || opt_key == "top_surface_expansion_direction" || opt_key == "minimum_sparse_infill_area" || opt_key == "sparse_infill_filament_id" || opt_key == "internal_solid_filament_id" @@ -1330,6 +1400,9 @@ bool PrintObject::invalidate_state_by_config_options( || opt_key == "top_surface_line_width" || opt_key == "top_surface_density" || opt_key == "bottom_surface_density" + || opt_key == "anisotropic_surfaces" + || opt_key == "center_of_surface_pattern" + || opt_key == "separated_infills" || opt_key == "initial_layer_line_width" || opt_key == "small_area_infill_flow_compensation" || opt_key == "lateral_lattice_angle_1" @@ -1686,6 +1759,69 @@ void PrintObject::detect_surfaces_type() } } + // ORCA: Expand the top surfaces outward by top_surface_expansion in every direction. This + // enlarges the top solid infill and, in particular, grows it over the covered material left + // by features rising from the middle of a top surface (filling holes and joining tops so the + // features rest on it). The expansion stays inside the section it belongs to: each connected + // solid island has its own outer wall, so the top is grown within each island separately and + // clipped to it - growing one island's top across the gap into another island (which may have + // no top surface, leaving a partially filled layer) is never allowed. The top infill sits + // inside the perimeters, so the margin is measured from the walls: the island is inset by the + // band the walls consume (outer wall + inner walls) plus the configured margin, making that + // value the real clearance between the expanded top and the walls (avoiding a hull line). The + // original top is unioned back in, so where it already sits within that band it is kept as-is. + // Never claims a bottom surface. + const double top_expansion = layerm->region().config().top_surface_expansion.value; + if (top_expansion > 0. && ! top.empty()) { + const double d = scale_(top_expansion); + const auto jt = Clipper2Lib::JoinType::Miter; + const ExPolygons T = union_ex(to_expolygons(top)); + const int wall_loops = layerm->region().config().wall_loops.value; + const double wall_band = wall_loops <= 0 ? 0. : + double(layerm->flow(frExternalPerimeter).scaled_width()) + + double(layerm->flow(frPerimeter).scaled_width()) * double(wall_loops - 1); + const double margin = scale_(layerm->region().config().top_surface_expansion_margin.value); + // minimum real top to act on: ignore anything thinner than ~2 top-infill lines + const float min_top = float(layerm->flow(frTopSolidInfill).scaled_width()); + const auto direction = layerm->region().config().top_surface_expansion_direction.value; + + ExPolygons grown; + for (const ExPolygon &island : union_ex(layerm_slices_surfaces)) { + // The top infill only exists inside the perimeters, so seed and measure from the infill + // region (the island minus the wall band), not the raw slice. A section whose only + // exposed top lies in the wall band - i.e. a layer where the top is just the walls + // themselves - has no infill here and is skipped, instead of being flooded inward by + // the expansion. Thin slivers inside the infill region are dropped by the opening too. + const ExPolygons infill_region = wall_band > 0. ? offset_ex(island, -float(wall_band)) : ExPolygons{ island }; + const ExPolygons island_top = intersection_ex(T, infill_region); + if (opening_ex(island_top, min_top).empty()) + continue; // no real top infill in this section - never expand into it + + // grow by d, then keep only the part allowed by the configured direction: inward fills + // the holes/gaps left by features (clip the growth back to the top's own filled outline, + // which leaves the outer edge fixed), outward grows the outer edge toward the walls (drop + // the growth that fell into the original holes), and inward+outward keeps both. + ExPolygons expanded = offset_ex_2(island_top, d, jt); + if (direction != TopSurfaceExpansionDirection::InwardAndOutward) { + ExPolygons outline; // the top with its holes filled (same outer edge) + outline.reserve(island_top.size()); + for (const ExPolygon &ex : island_top) + outline.emplace_back(ex.contour); + outline = union_ex(outline); + expanded = direction == TopSurfaceExpansionDirection::Inward ? + intersection_ex(expanded, outline) : // only growth into the holes + diff_ex(expanded, diff_ex(outline, island_top)); // only growth past the outer edge + } + // hold the expansion clear of the walls by the configured margin + const ExPolygons allowed = margin > 0. ? offset_ex(infill_region, -float(margin)) : infill_region; + append(grown, intersection_ex(expanded, allowed)); + } + + ExPolygons new_top = diff_ex(union_ex(T, grown), to_expolygons(bottom)); + top.clear(); + surfaces_append(top, std::move(new_top), stTop); + } + #ifdef SLIC3R_DEBUG_SLICE_PROCESSING { static int iRun = 0; @@ -2182,7 +2318,7 @@ void PrintObject::discover_vertical_shells() #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */ Flow solid_infill_flow = layerm->flow(frSolidInfill); - coord_t infill_line_spacing = solid_infill_flow.scaled_spacing(); + coord_t infill_line_spacing = solid_infill_flow.scaled_spacing(); // Find a union of perimeters below / above this surface to guarantee a minimum shell thickness. Polygons shell; Polygons holes; @@ -2224,7 +2360,7 @@ void PrintObject::discover_vertical_shells() shell = std::move(shells2); else if (! shells2.empty()) { polygons_append(shell, shells2); - // Running the union_ using the Clipper library piece by piece is cheaper + // Running the union_ using the Clipper library piece by piece is cheaper // than running the union_ all at once. shell = union_(shell); } @@ -2291,12 +2427,12 @@ void PrintObject::discover_vertical_shells() Slic3r::SVG svg(debug_out_path("discover_vertical_shells-perimeters-before-union-%d.svg", debug_idx), get_extents(shell)); svg.draw(shell); svg.draw_outline(shell, "black", scale_(0.05)); - svg.Close(); + svg.Close(); } #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */ #if 0 // shell = union_(shell, true); - shell = union_(shell, false); + shell = union_(shell, false); #endif #ifdef SLIC3R_DEBUG_SLICE_PROCESSING shell_ex = union_safety_offset_ex(shell); @@ -2600,7 +2736,7 @@ void PrintObject::bridge_over_infill() } } - // LIGHTNING INFILL SECTION - If lightning infill is used somewhere, we check the areas that are going to be bridges, and those that rely on the + // LIGHTNING INFILL SECTION - If lightning infill is used somewhere, we check the areas that are going to be bridges, and those that rely on the // lightning infill under them get expanded. This somewhat helps to ensure that most of the extrusions are anchored to the lightning infill at the ends. // It requires modifying this instance of print object in a specific way, so that we do not invalidate the pointers in our surfaces_by_layer structure. if (has_lightning_infill) { @@ -3575,13 +3711,13 @@ static void clamp_feature_filament_to_valid(ConfigOptionInt &opt, size_t num_ext opt.value = 1; } -PrintObjectConfig PrintObject::object_config_from_model_object(const PrintObjectConfig &default_object_config, const ModelObject &object, size_t num_extruders) +PrintObjectConfig PrintObject::object_config_from_model_object(const PrintObjectConfig &default_object_config, const ModelObject &object, size_t num_extruders, std::vector& variant_index) { PrintObjectConfig config = default_object_config; { DynamicPrintConfig src_normalized(object.config.get()); src_normalized.normalize_fdm(); - config.apply(src_normalized, true); + update_static_print_config_from_dynamic(config, src_normalized, variant_index, print_options_with_variant, 1); } // Clamp invalid extruders to the default extruder (with index 1). clamp_exturder_to_default(config.support_filament, num_extruders); @@ -3609,7 +3745,7 @@ struct FeatureFilamentOverrideMask bool inner_wall_filament_id = false; }; -static void apply_to_print_region_config(PrintRegionConfig &out, const DynamicPrintConfig &in, FeatureFilamentOverrideMask &feature_overrides) +static void apply_to_print_region_config(PrintRegionConfig &out, const DynamicPrintConfig &in, FeatureFilamentOverrideMask &feature_overrides, std::vector& variant_index) { // 1) Explicit feature filament values take precedence over base extruder fallback. auto *opt_extruder = in.opt(key_extruder); @@ -3650,8 +3786,18 @@ static void apply_to_print_region_config(PrintRegionConfig &out, const DynamicPr else if (it->first == "inner_wall_filament_id") feature_overrides.inner_wall_filament_id = false; } - } else - my_opt->set(it->second.get()); + } else { + if (*my_opt != *(it->second)) { + if (my_opt->is_scalar() || variant_index.empty() || (print_options_with_variant.find(it->first) == print_options_with_variant.end())) + my_opt->set(it->second.get()); + //my_opt->set(it->second.get()); + else { + ConfigOptionVectorBase* opt_vec_src = static_cast(my_opt); + const ConfigOptionVectorBase* opt_vec_dest = static_cast(it->second.get()); + opt_vec_src->set_to_index(opt_vec_dest, variant_index, 1); + } + } + } } // 3) Apply base extruder only to features that were not explicitly overridden. @@ -3671,7 +3817,7 @@ static void apply_to_print_region_config(PrintRegionConfig &out, const DynamicPr } } -PrintRegionConfig region_config_from_model_volume(const PrintRegionConfig &default_or_parent_region_config, const DynamicPrintConfig *layer_range_config, const ModelVolume &volume, size_t num_extruders) +PrintRegionConfig region_config_from_model_volume(const PrintRegionConfig &default_or_parent_region_config, const DynamicPrintConfig *layer_range_config, const ModelVolume &volume, size_t num_extruders, std::vector& variant_index) { PrintRegionConfig config = default_or_parent_region_config; FeatureFilamentOverrideMask feature_overrides; @@ -3689,17 +3835,17 @@ PrintRegionConfig region_config_from_model_volume(const PrintRegionConfig &defau if (volume.is_model_part()) { // default_or_parent_region_config contains the Print's PrintRegionConfig. // Override with ModelObject's PrintRegionConfig values. - apply_to_print_region_config(config, volume.get_object()->config.get(), feature_overrides); + apply_to_print_region_config(config, volume.get_object()->config.get(), feature_overrides, variant_index); } else { // default_or_parent_region_config contains parent PrintRegion config, which already contains ModelVolume's config. } - apply_to_print_region_config(config, volume.config.get(), feature_overrides); + apply_to_print_region_config(config, volume.config.get(), feature_overrides, variant_index); if (! volume.material_id().empty()) - apply_to_print_region_config(config, volume.material()->config.get(), feature_overrides); + apply_to_print_region_config(config, volume.material()->config.get(), feature_overrides, variant_index); if (layer_range_config != nullptr) { // Not applicable to modifiers. assert(volume.is_model_part()); - apply_to_print_region_config(config, *layer_range_config, feature_overrides); + apply_to_print_region_config(config, *layer_range_config, feature_overrides, variant_index); } // Resolve feature defaults and clamp invalid extruders to index 1. clamp_feature_filament_to_valid(config.sparse_infill_filament_id, num_extruders); @@ -3749,7 +3895,7 @@ void PrintObject::update_slicing_parameters() } // Orca: XYZ shrinkage compensation has introduced the const Vec3d &object_shrinkage_compensation parameter to the function below -SlicingParameters PrintObject::slicing_parameters(const DynamicPrintConfig &full_config, const ModelObject &model_object, float object_max_z, const Vec3d &object_shrinkage_compensation) +SlicingParameters PrintObject::slicing_parameters(const DynamicPrintConfig &full_config, const ModelObject &model_object, float object_max_z, const Vec3d &object_shrinkage_compensation, std::vector variant_index) { PrintConfig print_config; PrintObjectConfig object_config; @@ -3759,14 +3905,14 @@ SlicingParameters PrintObject::slicing_parameters(const DynamicPrintConfig &full default_region_config.apply(full_config, true); // BBS size_t filament_extruders = print_config.filament_diameter.size(); - object_config = object_config_from_model_object(object_config, model_object, filament_extruders); + object_config = object_config_from_model_object(object_config, model_object, filament_extruders, variant_index); std::vector object_extruders; for (const ModelVolume* model_volume : model_object.volumes) if (model_volume->is_model_part()) { PrintRegion::collect_object_printing_extruders( print_config, - region_config_from_model_volume(default_region_config, nullptr, *model_volume, filament_extruders), + region_config_from_model_volume(default_region_config, nullptr, *model_volume, filament_extruders, variant_index), object_config.brim_type != btNoBrim && object_config.brim_width > 0., object_extruders); for (const std::pair &range_and_config : model_object.layer_config_ranges) @@ -3778,7 +3924,7 @@ SlicingParameters PrintObject::slicing_parameters(const DynamicPrintConfig &full range_and_config.second.has("bottom_surface_filament_id")) PrintRegion::collect_object_printing_extruders( print_config, - region_config_from_model_volume(default_region_config, &range_and_config.second.get(), *model_volume, filament_extruders), + region_config_from_model_volume(default_region_config, &range_and_config.second.get(), *model_volume, filament_extruders, variant_index), object_config.brim_type != btNoBrim && object_config.brim_width > 0., object_extruders); } diff --git a/src/libslic3r/miniz_extension.cpp b/src/libslic3r/miniz_extension.cpp index 424e76462c..53a4a8e9de 100644 --- a/src/libslic3r/miniz_extension.cpp +++ b/src/libslic3r/miniz_extension.cpp @@ -1,6 +1,8 @@ #include +#include #include "miniz_extension.hpp" +#include "Utils.hpp" #if defined(_MSC_VER) || defined(__MINGW64__) #include "boost/nowide/cstdio.hpp" @@ -15,6 +17,33 @@ namespace Slic3r { namespace { +std::string decode_zip_unicode_path_extra_field(const std::string& extra, const std::string& path) +{ + size_t offset = 0; + const mz_uint32 path_crc = mz_crc32(0, reinterpret_cast(path.data()), path.size()); + + while (offset + 4 <= extra.size()) { + const unsigned char* field = reinterpret_cast(extra.data() + offset); + const std::uint16_t len = field[2] | (static_cast(field[3]) << 8); + if (offset + 4 + len > extra.size()) + break; + + if (field[0] == 0x75 && field[1] == 0x70 && len >= 5 && field[4] == 0x01) { + const mz_uint32 stored_crc = + static_cast(field[5]) | + (static_cast(field[6]) << 8) | + (static_cast(field[7]) << 16) | + (static_cast(field[8]) << 24); + if (stored_crc == path_crc) + return std::string(extra.data() + offset + 9, extra.data() + offset + 4 + len); + } + + offset += 4 + len; + } + + return Slic3r::decode_path(path.c_str()); +} + bool open_zip(mz_zip_archive *zip, const char *fname, bool isread) { if (!zip) return false; @@ -76,6 +105,16 @@ bool open_zip_writer(mz_zip_archive *zip, const std::string &fname) bool close_zip_reader(mz_zip_archive *zip) { return close_zip(zip, true); } bool close_zip_writer(mz_zip_archive *zip) { return close_zip(zip, false); } +std::string decode_archive_entry_path(mz_zip_archive *zip, const mz_zip_archive_file_stat &stat) +{ + if (stat.m_is_utf8) + return stat.m_filename; + + std::string extra(1024, 0); + const size_t extra_size = mz_zip_reader_get_extra(zip, stat.m_file_index, extra.data(), extra.size()); + return decode_zip_unicode_path_extra_field(extra.substr(0, extra_size > 0 ? extra_size - 1 : 0), stat.m_filename); +} + MZ_Archive::MZ_Archive() { mz_zip_zero_struct(&arch); diff --git a/src/libslic3r/miniz_extension.hpp b/src/libslic3r/miniz_extension.hpp index 006226bf24..1a1c96689f 100644 --- a/src/libslic3r/miniz_extension.hpp +++ b/src/libslic3r/miniz_extension.hpp @@ -10,6 +10,7 @@ bool open_zip_reader(mz_zip_archive *zip, const std::string &fname_utf8); bool open_zip_writer(mz_zip_archive *zip, const std::string &fname_utf8); bool close_zip_reader(mz_zip_archive *zip); bool close_zip_writer(mz_zip_archive *zip); +std::string decode_archive_entry_path(mz_zip_archive *zip, const mz_zip_archive_file_stat &stat); class MZ_Archive { public: diff --git a/src/slic3r/GUI/AboutDialog.cpp b/src/slic3r/GUI/AboutDialog.cpp index 6bbc86f884..a4f0f06d65 100644 --- a/src/slic3r/GUI/AboutDialog.cpp +++ b/src/slic3r/GUI/AboutDialog.cpp @@ -324,10 +324,12 @@ AboutDialog::AboutDialog() m_html->SetFonts(font.GetFaceName(), font.GetFaceName(), size); m_html->SetMinSize(wxSize(FromDIP(-1), FromDIP(16))); m_html->SetBorders(2); + wxColour bgr_clr = GetBackgroundColour(); + const auto bgr_clr_str = encode_color(ColorRGB(bgr_clr.Red(), bgr_clr.Green(), bgr_clr.Blue())); const auto text = from_u8( (boost::format( "" - "" + "" "

https://www.orcaslicer.com

" "" "") diff --git a/src/slic3r/GUI/AmsMappingPopup.cpp b/src/slic3r/GUI/AmsMappingPopup.cpp index cf417498d5..19561dc783 100644 --- a/src/slic3r/GUI/AmsMappingPopup.cpp +++ b/src/slic3r/GUI/AmsMappingPopup.cpp @@ -569,7 +569,7 @@ void MaterialSyncItem::doRender(wxDC &dc) dc.DrawRoundedRectangle(1, 1, MATERIAL_ITEM_SIZE.x - 1, MATERIAL_ITEM_SIZE.y - 1, 5); if (m_selected) { - dc.SetPen(wxColour(0x00, 0xAE, 0x42)); + dc.SetPen(wxColour("#009688")); // ORCA selected item border color dc.SetBrush(*wxTRANSPARENT_BRUSH); dc.DrawRoundedRectangle(1, 1, MATERIAL_ITEM_SIZE.x - 1, MATERIAL_ITEM_SIZE.y - 1, 5); } @@ -580,7 +580,7 @@ void MaterialSyncItem::doRender(wxDC &dc) dc.DrawRoundedRectangle(0, 0, MATERIAL_ITEM_SIZE.x, MATERIAL_ITEM_SIZE.y, 5); if (m_selected) { - dc.SetPen(wxPen(wxColour(0x00, 0xAE, 0x42), FromDIP(2))); + dc.SetPen(wxPen(wxColour("#009688"), FromDIP(2))); // ORCA selected item border color dc.SetBrush(*wxTRANSPARENT_BRUSH); dc.DrawRoundedRectangle(FromDIP(1), FromDIP(1), MATERIAL_ITEM_SIZE.x - FromDIP(1), MATERIAL_ITEM_SIZE.y - FromDIP(1), 5); } @@ -813,7 +813,7 @@ void AmsMapingPopup::msw_rescale() m_split_left_line->SetMaxSize(wxSize(-1, 1)); sizer_split_ams->Add(0, 0, 0, wxEXPAND, 0); sizer_split_ams->Add(ams_title_text, 0, wxALIGN_CENTER, 0); - sizer_split_ams->Add(m_split_left_line, 1, wxEXPAND, 0); + sizer_split_ams->Add(m_split_left_line, 1, wxALIGN_CENTER, 0); // ORCA align line vertically return sizer_split_ams; } @@ -1420,7 +1420,7 @@ bool AmsMapingPopup::ProcessLeftDown(wxMouseEvent &event) void AmsMapingPopup::paintEvent(wxPaintEvent &evt) { wxPaintDC dc(this); - dc.SetPen(wxColour(0xAC, 0xAC, 0xAC)); + dc.SetPen(wxPen(StateColor::darkModeColorFor(wxColour("#009688")),FromDIP(2))); // ORCA use colorful border for separation dc.SetBrush(*wxTRANSPARENT_BRUSH); dc.DrawRoundedRectangle(0, 0, GetSize().x, GetSize().y, 0); } @@ -2281,7 +2281,7 @@ AmsRMGroup* AmsReplaceMaterialDialog::create_backup_group(wxString gname, std::m void AmsReplaceMaterialDialog::paintEvent(wxPaintEvent& evt) { wxPaintDC dc(this); - dc.SetPen(wxColour(0xAC, 0xAC, 0xAC)); + dc.SetPen(StateColor::darkModeColorFor(wxColour("#DBDBDB"))); // ORCA fix popup border color for dark mode dc.SetBrush(*wxTRANSPARENT_BRUSH); dc.DrawRoundedRectangle(0, 0, GetSize().x, GetSize().y, 0); } diff --git a/src/slic3r/GUI/BaseTransparentDPIFrame.cpp b/src/slic3r/GUI/BaseTransparentDPIFrame.cpp index fa2b8cab91..918116d89b 100644 --- a/src/slic3r/GUI/BaseTransparentDPIFrame.cpp +++ b/src/slic3r/GUI/BaseTransparentDPIFrame.cpp @@ -30,6 +30,19 @@ BaseTransparentDPIFrame::BaseTransparentDPIFrame( // SetBackgroundStyle(wxBackgroundStyle::wxBG_STYLE_TRANSPARENT); SetTransparent(m_init_transparent); SetBackgroundColour(wxColour(23, 25, 22, 128)); + + // ORCA add border + Bind(wxEVT_PAINT, [this](wxPaintEvent& evt) { + wxPaintDC dc(this); + dc.SetPen(wxPen(StateColor::darkModeColorFor(wxColour("#009688")), FromDIP(2))); + dc.SetBrush(*wxTRANSPARENT_BRUSH); + dc.DrawRoundedRectangle(0, 0, GetSize().x, GetSize().y, 0); + }); + + int window_padding = 15; + auto imgsize = 32; + auto imgright = 10; + //Adaptive Frame Width wxClientDC dc(parent); wxSize msg_sz = dc.GetMultiLineTextExtent(ok_text); @@ -44,21 +57,16 @@ BaseTransparentDPIFrame::BaseTransparentDPIFrame( m_sizer_main = new wxBoxSizer(wxVERTICAL); wxBoxSizer *text_sizer = new wxBoxSizer(wxHORIZONTAL); - text_sizer->AddSpacer(FromDIP(20)); - auto image_sizer = new wxBoxSizer(wxVERTICAL); - auto imgsize = FromDIP(25); - auto completedimg = new wxStaticBitmap(this, wxID_ANY, create_scaled_bitmap("completed", this, 25), wxDefaultPosition, wxSize(imgsize, imgsize), 0); - image_sizer->Add(completedimg, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxALL, FromDIP(0)); - image_sizer->AddStretchSpacer(); - text_sizer->Add(image_sizer); - text_sizer->AddSpacer(FromDIP(5)); + + auto completedimg = new wxStaticBitmap(this, wxID_ANY, create_scaled_bitmap("completed", this, imgsize), wxDefaultPosition, FromDIP(wxSize(imgsize, imgsize)), 0); + + text_sizer->Add(completedimg, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, FromDIP(imgright)); m_finish_text = new Label(this, win_text, LB_AUTO_WRAP); - m_finish_text->SetMinSize(wxSize(FromDIP(win_width - 64), -1)); - m_finish_text->SetMaxSize(wxSize(FromDIP(win_width - 64), -1)); + m_finish_text->SetMinSize(wxSize(FromDIP(win_width - (window_padding * 2 + imgright + imgsize)), -1)); + m_finish_text->SetMaxSize(wxSize(FromDIP(win_width - (window_padding * 2 + imgright + imgsize)), -1)); m_finish_text->SetForegroundColour(wxColour(255, 255, 255, 255)); - text_sizer->Add(m_finish_text, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxALL, 0); - text_sizer->AddSpacer(FromDIP(20)); - m_sizer_main->Add(text_sizer, FromDIP(0), wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxTOP, FromDIP(15)); + text_sizer->Add(m_finish_text, 0, wxALIGN_CENTER_VERTICAL); + m_sizer_main->Add(text_sizer, 0, wxALL, FromDIP(15)); wxBoxSizer *bSizer_button = new wxBoxSizer(wxHORIZONTAL); bSizer_button->SetMinSize(wxSize(FromDIP(100), -1)); @@ -66,22 +74,18 @@ BaseTransparentDPIFrame::BaseTransparentDPIFrame( bSizer_button->Add(m_checkbox, 0, wxALIGN_LEFT);*/ bSizer_button->AddStretchSpacer(1); m_button_ok = new Button(this, ok_text); - m_button_ok->SetStyle(ButtonStyle::Confirm, ButtonType::Window); - m_button_ok->SetSize(wxSize(FromDIP(60), FromDIP(30))); - m_button_ok->SetMinSize(wxSize(FromDIP(90), FromDIP(30))); - bSizer_button->Add(m_button_ok, 0, wxALIGN_RIGHT | wxLEFT | wxTOP, FromDIP(10)); + m_button_ok->SetStyle(ButtonStyle::Confirm, ButtonType::Choice); + bSizer_button->Add(m_button_ok, 0, wxALIGN_RIGHT | wxLEFT, FromDIP(10)); m_button_ok->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this](wxCommandEvent &e) { deal_ok(); }); m_button_cancel = new Button(this, cancel_text); - m_button_cancel->SetStyle(ButtonStyle::Regular, ButtonType::Window); - m_button_cancel->SetSize(wxSize(FromDIP(65), FromDIP(30))); - m_button_cancel->SetMinSize(wxSize(FromDIP(65), FromDIP(30))); - bSizer_button->Add(m_button_cancel, 0, wxALIGN_RIGHT | wxLEFT | wxTOP, FromDIP(10)); + m_button_cancel->SetStyle(ButtonStyle::Regular, ButtonType::Choice); + bSizer_button->Add(m_button_cancel, 0, wxALIGN_RIGHT | wxLEFT, FromDIP(10)); m_button_cancel->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this](wxCommandEvent &e) { deal_cancel(); }); - m_sizer_main->Add(bSizer_button, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, FromDIP(20)); + m_sizer_main->Add(bSizer_button, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, FromDIP(window_padding)); Bind(wxEVT_CLOSE_WINDOW, [this](auto &e) { on_hide(); diff --git a/src/slic3r/GUI/BonjourDialog.cpp b/src/slic3r/GUI/BonjourDialog.cpp index db7794a52a..8b3217e193 100644 --- a/src/slic3r/GUI/BonjourDialog.cpp +++ b/src/slic3r/GUI/BonjourDialog.cpp @@ -8,7 +8,6 @@ #include #include -#include #include #include #include @@ -20,6 +19,8 @@ #include "slic3r/GUI/format.hpp" #include "slic3r/Utils/Bonjour.hpp" +#include "slic3r/GUI/Widgets/DialogButtons.hpp" + namespace Slic3r { @@ -63,30 +64,30 @@ BonjourDialog::BonjourDialog(wxWindow *parent, Slic3r::PrinterTechnology tech) , timer_state(0) , tech(tech) { + SetBackgroundColour(*wxWHITE); + const int em = GUI::wxGetApp().em_unit(); list->SetMinSize(wxSize(80 * em, 30 * em)); wxBoxSizer *vsizer = new wxBoxSizer(wxVERTICAL); + label->SetFont(Label::Body_14); vsizer->Add(label, 0, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, em); list->SetSingleStyle(wxLC_SINGLE_SEL); list->SetSingleStyle(wxLC_SORT_DESCENDING); - list->AppendColumn(_(L("Address")), wxLIST_FORMAT_LEFT, 5 * em); + list->AppendColumn(_(L("Address")), wxLIST_FORMAT_LEFT, 20 * em); list->AppendColumn(_(L("Hostname")), wxLIST_FORMAT_LEFT, 10 * em); list->AppendColumn(_(L("Service name")), wxLIST_FORMAT_LEFT, 20 * em); if (tech == ptFFF) { - list->AppendColumn(_(L("OctoPrint version")), wxLIST_FORMAT_LEFT, 5 * em); + list->AppendColumn(_(L("OctoPrint version")), wxLIST_FORMAT_LEFT, 15 * em); } vsizer->Add(list, 1, wxEXPAND | wxALL, em); - wxBoxSizer *button_sizer = new wxBoxSizer(wxHORIZONTAL); - button_sizer->Add(new wxButton(this, wxID_OK, _L("OK")), 0, wxALL, em); - button_sizer->Add(new wxButton(this, wxID_CANCEL, _L("Cancel")), 0, wxALL, em); - // ^ Note: The Ok/Cancel labels are translated by wxWidgets + auto dlg_btns = new GUI::DialogButtons(this, {"OK", "Cancel"}); - vsizer->Add(button_sizer, 0, wxALIGN_CENTER); + vsizer->Add(dlg_btns, 0, wxEXPAND); SetSizerAndFit(vsizer); Bind(EVT_BONJOUR_REPLY, &BonjourDialog::on_reply, this); @@ -241,12 +242,15 @@ IPListDialog::IPListDialog(wxWindow* parent, const wxString& hostname, const std , m_list(new wxListView(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_REPORT | wxSIMPLE_BORDER)) , m_selected_index (selected_index) { + SetBackgroundColour(*wxWHITE); + const int em = GUI::wxGetApp().em_unit(); m_list->SetMinSize(wxSize(40 * em, 30 * em)); wxBoxSizer* vsizer = new wxBoxSizer(wxVERTICAL); auto* label = new wxStaticText(this, wxID_ANY, GUI::format_wxstr(_L("There are several IP addresses resolving to hostname %1%.\nPlease select one that should be used."), hostname)); + label->SetFont(Label::Body_14); vsizer->Add(label, 0, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, em); m_list->SetSingleStyle(wxLC_SINGLE_SEL); @@ -259,11 +263,9 @@ IPListDialog::IPListDialog(wxWindow* parent, const wxString& hostname, const std vsizer->Add(m_list, 1, wxEXPAND | wxALL, em); - wxBoxSizer* button_sizer = new wxBoxSizer(wxHORIZONTAL); - button_sizer->Add(new wxButton(this, wxID_OK, _L("OK")), 0, wxALL, em); - button_sizer->Add(new wxButton(this, wxID_CANCEL, _L("Cancel")), 0, wxALL, em); + auto dlg_btns = new GUI::DialogButtons(this, {"OK", "Cancel"}); - vsizer->Add(button_sizer, 0, wxALIGN_CENTER); + vsizer->Add(dlg_btns, 0, wxEXPAND); SetSizerAndFit(vsizer); GUI::wxGetApp().UpdateDlgDarkUI(this); diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index 46758e3e64..4bd9749073 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -713,6 +713,36 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, in toggle_field("top_layer_direction", has_top_shell); toggle_field("bottom_layer_direction", has_bottom_shell); + toggle_line("top_surface_expansion", has_top_shell); + toggle_line("top_surface_expansion_margin", has_top_shell); + bool has_top_surface_expansion = config->opt_float("top_surface_expansion") > 0; + toggle_field("top_surface_expansion_margin", has_top_surface_expansion); + toggle_line("top_surface_expansion_direction", has_top_shell); + toggle_field("top_surface_expansion_direction", has_top_surface_expansion); + + // Orca: Archimedean Chords and Octagram Spiral are the centered surface patterns that the + // pattern-centering, anisotropic-surface and separated-infill features act on. + auto is_centered_pattern = [](InfillPattern p) { + return p == InfillPattern::ipArchimedeanChords || p == InfillPattern::ipOctagramSpiral; + }; + bool is_top_centered = is_centered_pattern(config->option>("top_surface_pattern")->value); + bool is_bottom_centered = is_centered_pattern(config->option>("bottom_surface_pattern")->value); + bool has_centered_surface = (has_top_shell && is_top_centered) || (has_bottom_shell && is_bottom_centered); + + // Orca: center of surface pattern / anisotropic surfaces + toggle_line("center_of_surface_pattern", has_centered_surface); + toggle_line("anisotropic_surfaces", has_centered_surface); + + // Orca: separate infills + bool is_internal_infill_separable = is_separable_infill_pattern(config->option>("sparse_infill_pattern")->value) || + config->opt_string("sparse_infill_rotate_template") != "" || + config->opt_string("solid_infill_rotate_template") != ""; + toggle_line("separated_infills", is_internal_infill_separable); + + // Orca: no need gaps + for (auto el : {"gap_fill_target", "filter_out_gap_fill"}) + toggle_field(el, !config->opt_bool("anisotropic_surfaces")); + for (auto el : { "infill_direction", "sparse_infill_line_width", "gap_fill_target","filter_out_gap_fill","infill_wall_overlap", "bridge_angle", "internal_bridge_angle", "relative_bridge_angle", "solid_infill_direction", "solid_infill_rotate_template", "internal_solid_infill_pattern", "internal_solid_filament_id", "top_surface_filament_id", "bottom_surface_filament_id", @@ -916,7 +946,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, in toggle_line("wipe_tower_extra_rib_length", have_rib_wall); toggle_line("wipe_tower_rib_width", have_rib_wall); toggle_line("wipe_tower_fillet_wall", have_rib_wall); - toggle_field("prime_tower_width", have_prime_tower && (supports_wipe_tower_2 || have_rib_wall)); + toggle_field("prime_tower_width", have_prime_tower && !have_rib_wall); toggle_line("single_extruder_multi_material_priming", !bSEMM && have_prime_tower && supports_wipe_tower_2); diff --git a/src/slic3r/GUI/ExtrusionCalibration.cpp b/src/slic3r/GUI/ExtrusionCalibration.cpp index 28255f37e4..cd3f49e977 100644 --- a/src/slic3r/GUI/ExtrusionCalibration.cpp +++ b/src/slic3r/GUI/ExtrusionCalibration.cpp @@ -239,7 +239,7 @@ void ExtrusionCalibration::create() m_button_save_result->SetStyle(ButtonStyle::Confirm, ButtonType::Choice); m_button_save_result->Bind(wxEVT_BUTTON, &ExtrusionCalibration::on_click_save, this); - m_button_last_step = new Button(m_step_2_panel, _L("Back")); // Back for english + m_button_last_step = new Button(m_step_2_panel, _CTX("Back", "Navigation")); // Back for english m_button_last_step->SetStyle(ButtonStyle::Regular, ButtonType::Choice); m_button_last_step->Bind(wxEVT_BUTTON, &ExtrusionCalibration::on_click_last, this); diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index 42fe6b4ce1..1cb0cf6148 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -936,6 +936,7 @@ bool TextCtrl::value_was_changed() case coString: case coStrings: case coFloatOrPercent: + case coFloatsOrPercents: return boost::any_cast(m_value) != boost::any_cast(val); default: return true; diff --git a/src/slic3r/GUI/FileArchiveDialog.cpp b/src/slic3r/GUI/FileArchiveDialog.cpp index 18c804196f..982187211c 100644 --- a/src/slic3r/GUI/FileArchiveDialog.cpp +++ b/src/slic3r/GUI/FileArchiveDialog.cpp @@ -221,16 +221,7 @@ FileArchiveDialog::FileArchiveDialog(wxWindow* parent_window, mz_zip_archive* ar std::vector> filtered_entries; // second is unzipped size for (mz_uint i = 0; i < num_entries; ++i) { if (mz_zip_reader_file_stat(archive, i, &stat)) { - std::string extra(1024, 0); - boost::filesystem::path path; - size_t extra_size = mz_zip_reader_get_filename_from_extra(archive, i, extra.data(), extra.size()); - if (extra_size > 0) { - path = boost::filesystem::path(extra.substr(0, extra_size)); - } else { - wxString wname = boost::nowide::widen(stat.m_filename); - std::string name = into_u8(wname); - path = boost::filesystem::path(name); - } + boost::filesystem::path path = Slic3r::decode_archive_entry_path(archive, stat); assert(!path.empty()); if (!path.has_extension()) continue; diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 150a40dc0d..bb7ff21ad6 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -489,7 +489,7 @@ void GCodeViewer::SequentialView::Marker::render_position_window(const libvgcode const float main_row_h = 2.0f * text_h + item_spacing_y; // Two lines of text (position and detail) + spacing between them const float properties_h = static_cast(properties_rows.size()) * (text_h + 2.0f * cell_pad_y) + 2.0f * cell_pad_y + 1.0f + item_spacing_y // table rows + item_spacing_y + show_button_h // Spacing() + Show/Hide button row - + item_spacing_y + 1.0f + style.FramePadding.y; // Spacing() + Separator() + Dummy() + + item_spacing_y + 1.0f + style.WindowPadding.y; // Spacing() + Separator() + Dummy() const float folded_window_h = std::ceil(window_pad_h + main_row_h); // Height of the window when properties are hidden, with padding, rounded up for better look const float unfolded_window_h = std::ceil(folded_window_h + properties_h); // Height of the window when properties are shown, with padding, rounded up for better look const float window_h = properties_shown ? unfolded_window_h : folded_window_h; // Final window height depending on whether properties are shown or not @@ -615,9 +615,12 @@ void GCodeViewer::SequentialView::Marker::render_position_window(const libvgcode ImGui::Spacing(); ImGui::Separator(); - ImGui::Dummy({0, style.FramePadding.y}); + ImGui::Dummy({0, style.WindowPadding.y}); } + float draw_area_height = ImGui::GetTextLineHeight() * 2.f + style.ItemSpacing.y; + ImGui::Dummy({10.f, draw_area_height}); // reserve area + ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding , 3.f * m_scale); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding , ImVec2(2.f, 2.f) * m_scale); ImGui::PushStyleColor(ImGuiCol_Button , ImVec4(0, 0, 0, 0)); @@ -625,6 +628,10 @@ void GCodeViewer::SequentialView::Marker::render_position_window(const libvgcode ImGui::PushStyleColor(ImGuiCol_ButtonActive , ImVec4(84 / 255.f, 84 / 255.f, 90 / 255.f, 1.f)); const float main_wnd_height = ImGui::GetWindowHeight(); + const float draw_start_y = main_wnd_height - draw_area_height - style.WindowPadding.y; + + ImGui::SetCursorPos(ImVec2(style.WindowPadding.x, draw_start_y)); + // ORCA use glyph based button for fixing button sizes changing depends on used font size on platform const wchar_t foldIcon = properties_shown ? ImGui::UnfoldButtonIcon : ImGui::FoldButtonIcon; if (imgui.glyph_button(foldIcon, ImVec2(16.f, 16.f) * m_scale)) { @@ -640,10 +647,7 @@ void GCodeViewer::SequentialView::Marker::render_position_window(const libvgcode ImGui::PopStyleColor(3); ImGui::PopStyleVar(2); - ImGui::SameLine(); - - if(!properties_shown) - ImGui::SetCursorPosY(ImGui::GetCursorPosY() - style.FramePadding.y); // aligns button with next group + ImGui::SetCursorPos(ImVec2(style.WindowPadding.x + style.ItemSpacing.x + 24.f * m_scale, draw_start_y - 1.f * m_scale)); ImGui::BeginGroup(); // group contents to make information area more compact @@ -4258,7 +4262,7 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv }; auto append_print = [&imgui, imperial_units](const ColorRGBA& color, const std::array& offsets, const Times& times, std::pair used_filament) { - imgui.text(_u8L("Print")); + imgui.text(_CTX_utf8("Print", "Noun")); ImGui::SameLine(); float icon_size = ImGui::GetTextLineHeight(); @@ -4292,7 +4296,7 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv for (const PartialTime& item : partial_times) { switch (item.type) { - case PartialTime::EType::Print: { labels.push_back(_u8L("Print")); break; } + case PartialTime::EType::Print: { labels.push_back(_CTX_utf8("Print", "Noun")); break; } case PartialTime::EType::Pause: { labels.push_back(_u8L("Pause")); break; } case PartialTime::EType::ColorChange: { labels.push_back(_u8L("Color change")); break; } } diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 4237632393..5b8943d998 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1231,6 +1231,14 @@ GLCanvas3D::~GLCanvas3D() glsafe(::glDeleteTextures(1, &m_ssao_depth_texture_id)); m_ssao_depth_texture_id = 0; } + if (m_shadow_map_texture_id != 0) { + glsafe(::glDeleteTextures(1, &m_shadow_map_texture_id)); + m_shadow_map_texture_id = 0; + } + if (m_shadow_map_fbo != 0) { + glsafe(::glDeleteFramebuffers(1, &m_shadow_map_fbo)); + m_shadow_map_fbo = 0; + } m_plate_shadow_mask.reset(); } m_plate_shadow_mask_key.clear(); @@ -2033,6 +2041,9 @@ void GLCanvas3D::render(bool only_init) // draw scene glsafe(::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)); + // Invalidate the shadow map each frame; only the View3D path below rebuilds it. This keeps + // the Preview / Assemble canvases from sampling a stale map with an outdated light matrix. + m_shadow_map_valid = false; _render_background(); //BBS add partplater rendering logic @@ -2057,7 +2068,8 @@ void GLCanvas3D::render(bool only_init) _render_platelist(camera.get_view_matrix(), camera.get_projection_matrix(), !camera.is_looking_downward(), only_current, only_body, hover_id, true, show_grid); //BBS: add outline logic - _render_cast_shadows_on_plate(camera.get_view_matrix(), camera.get_projection_matrix()); + // Depth pass for object-on-object and self shadows; consumed by the gouraud shader below. + _render_shadows(camera.get_view_matrix(), camera.get_projection_matrix()); _render_objects(GLVolumeCollection::ERenderType::Opaque, !m_gizmos.is_running()); _render_sla_slices(); _render_selection(); @@ -6036,11 +6048,11 @@ void GLCanvas3D::_render_3d_navigator() strcpy(style.AxisLabels[ImGuizmo::Axis::Axis_Y], "Z"); // ORCA use uppercase to match text on tranform widgets strcpy(style.AxisLabels[ImGuizmo::Axis::Axis_Z], "X"); // ORCA use uppercase to match text on tranform widgets strcpy(style.FaceLabels[ImGuizmo::FACES::FACE_FRONT], _utf8("Front").c_str()); - strcpy(style.FaceLabels[ImGuizmo::FACES::FACE_BACK], _utf8("Back").c_str()); + strcpy(style.FaceLabels[ImGuizmo::FACES::FACE_BACK], _CTX_utf8("Back", "Camera View").c_str()); strcpy(style.FaceLabels[ImGuizmo::FACES::FACE_TOP], _utf8("Top").c_str()); strcpy(style.FaceLabels[ImGuizmo::FACES::FACE_BOTTOM], _utf8("Bottom").c_str()); - strcpy(style.FaceLabels[ImGuizmo::FACES::FACE_LEFT], _CTX_utf8(L_CONTEXT("Left", "Camera"), "Camera").c_str()); - strcpy(style.FaceLabels[ImGuizmo::FACES::FACE_RIGHT], _CTX_utf8(L_CONTEXT("Right", "Camera"), "Camera").c_str()); + strcpy(style.FaceLabels[ImGuizmo::FACES::FACE_LEFT], _CTX_utf8("Left", "Camera View").c_str()); + strcpy(style.FaceLabels[ImGuizmo::FACES::FACE_RIGHT], _CTX_utf8("Right", "Camera View").c_str()); float sc = get_scale(); #ifdef WIN32 @@ -7858,9 +7870,8 @@ void GLCanvas3D::_render_platelist(const Transform3d& view_matrix, const Transfo wxGetApp().plater()->get_partplate_list().render(view_matrix, projection_matrix, bottom, only_current, only_body, hover_id, render_cali, show_grid); } -void GLCanvas3D::_render_cast_shadows_on_plate(const Transform3d& view_matrix, const Transform3d& projection_matrix) +void GLCanvas3D::_render_shadows(const Transform3d& view_matrix, const Transform3d& projection_matrix) { - // Check if shadow rendering is enabled in configuration if (wxGetApp().app_config == nullptr) return; if (!wxGetApp().app_config->get_bool(SETTING_OPENGL_REALISTIC_MODE)) @@ -7874,54 +7885,181 @@ void GLCanvas3D::_render_cast_shadows_on_plate(const Transform3d& view_matrix, c if (shader == nullptr) return; - // Fixed light direction (pointing downward at an angle) - // Drive shadow direction from current view angle: define light in eye-space, - // then transform it to world-space with inverse view rotation. - const Vec3d light_dir_eye = Vec3d(-0.4574957, 0.4574957, 0.7624929).normalized(); - const Matrix3d view_rot = view_matrix.matrix().block<3, 3>(0, 0); - const Vec3d light_dir_to_light = (view_rot.transpose() * light_dir_eye).normalized(); - const Vec3d ray_dir = -light_dir_to_light; // Direction of shadow projection - - if (std::abs(ray_dir.z()) < 1e-6) + if (OpenGLManager::get_framebuffers_type() == OpenGLManager::EFramebufferType::Arb) { + + // Light direction (same as used in shading and plate shading) + const Vec3d light_dir_eye = Vec3d(-0.4574957, 0.4574957, 0.7624929).normalized(); + const Matrix3d view_rot = view_matrix.matrix().block<3, 3>(0, 0); + const Vec3d dir_to_light = (view_rot.transpose() * light_dir_eye).normalized(); + + // Bounding box of the printable objects (the shadow casters). + BoundingBoxf3 obj_bb; + for (const GLVolume* volume : m_volumes.volumes) { + if (volume == nullptr || !volume->is_active || !volume->printable || volume->is_modifier || volume->is_wipe_tower) + continue; + obj_bb.merge(volume->transformed_bounding_box()); + } + if (!obj_bb.defined) + return; // no objects to cast shadows + + // Orthographic light-space basis (z points toward the light). + const Vec3d up = (std::abs(dir_to_light.z()) > 0.99) ? Vec3d::UnitY() : Vec3d::UnitZ(); + const Vec3d z_axis = dir_to_light; + const Vec3d x_axis = up.cross(z_axis).normalized(); + const Vec3d y_axis = z_axis.cross(x_axis).normalized(); + + // Fit the frustum to the object AABB *and* the object's shadow projected onto the plate + // (clamped to the plate footprint). This keeps the map tight/high-res for short shadows + // while still covering long shadows at grazing light angles, which previously fell outside + // the map and were clipped. + const Vec3d ray_dir = -dir_to_light; // direction the shadow travels + const BoundingBoxf3 plate_bb = m_bed.build_volume().valid() ? m_bed.build_volume().bounding_volume() : obj_bb; + + Vec3d lmin(DBL_MAX, DBL_MAX, DBL_MAX); + Vec3d lmax(-DBL_MAX, -DBL_MAX, -DBL_MAX); + auto enclose = [&](const Vec3d& p) { + const Vec3d lp(x_axis.dot(p), y_axis.dot(p), z_axis.dot(p)); + lmin = lmin.cwiseMin(lp); + lmax = lmax.cwiseMax(lp); + }; + for (int i = 0; i < 8; ++i) { + const Vec3d corner((i & 1) ? obj_bb.max.x() : obj_bb.min.x(), + (i & 2) ? obj_bb.max.y() : obj_bb.min.y(), + (i & 4) ? obj_bb.max.z() : obj_bb.min.z()); + enclose(corner); + // Where this corner's shadow lands on z = 0, clamped to the plate so a grazing angle + // (t -> infinity) stays bounded. + if (ray_dir.z() < -1e-6) { + const double t = -corner.z() / ray_dir.z(); + Vec3d s = corner + t * ray_dir; + s.x() = std::min(std::max(s.x(), plate_bb.min.x()), plate_bb.max.x()); + s.y() = std::min(std::max(s.y(), plate_bb.min.y()), plate_bb.max.y()); + s.z() = 0.0; + enclose(s); + } + } + + // Light "camera" placed just past the nearest enclosed point, looking toward the scene. + const double range = lmax.z() - lmin.z(); + const double margin = std::max(1.0, 0.05 * range); + const double cx = 0.5 * (lmin.x() + lmax.x()); + const double cy = 0.5 * (lmin.y() + lmax.y()); + const Vec3d eye = x_axis * cx + y_axis * cy + z_axis * (lmax.z() + margin); + + Matrix4d light_view = Matrix4d::Identity(); + light_view.block<1, 3>(0, 0) = x_axis.transpose(); + light_view.block<1, 3>(1, 0) = y_axis.transpose(); + light_view.block<1, 3>(2, 0) = z_axis.transpose(); + light_view(0, 3) = -x_axis.dot(eye); + light_view(1, 3) = -y_axis.dot(eye); + light_view(2, 3) = -z_axis.dot(eye); + + // Ortho fit to the light-space extent (symmetric in X/Y around cx,cy; +2% edge padding). + const double halfx = std::max(0.5 * (lmax.x() - lmin.x()), 1.0) * 1.02; + const double halfy = std::max(0.5 * (lmax.y() - lmin.y()), 1.0) * 1.02; + const double near_z = margin * 0.5; + const double far_z = range + margin * 1.5; + Matrix4d light_proj = Matrix4d::Identity(); + light_proj(0, 0) = 1.0 / halfx; + light_proj(1, 1) = 1.0 / halfy; + light_proj(2, 2) = -2.0 / (far_z - near_z); + light_proj(2, 3) = -(far_z + near_z) / (far_z - near_z); + + m_shadow_light_vp = Transform3d(light_proj * light_view); + + // Create / resize the depth texture and FBO + const unsigned int size = 2048; + if (m_shadow_map_texture_id == 0) { + glsafe(::glGenTextures(1, &m_shadow_map_texture_id)); + glsafe(::glBindTexture(GL_TEXTURE_2D, m_shadow_map_texture_id)); + glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); + glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); + glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER)); + glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER)); + const float border[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + glsafe(::glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border)); + m_shadow_map_size = 0; + } + if (m_shadow_map_size != size) { + glsafe(::glBindTexture(GL_TEXTURE_2D, m_shadow_map_texture_id)); + glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, size, size, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr)); + m_shadow_map_size = size; + } + if (m_shadow_map_fbo == 0) + glsafe(::glGenFramebuffers(1, &m_shadow_map_fbo)); + + // Save OpenGL state that we will modify + GLint prev_viewport[4] = { 0, 0, 0, 0 }; + glsafe(::glGetIntegerv(GL_VIEWPORT, prev_viewport)); + GLint prev_fbo = 0; + glsafe(::glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prev_fbo)); + GLboolean prev_color_mask[4] = { GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE }; + glsafe(::glGetBooleanv(GL_COLOR_WRITEMASK, prev_color_mask)); + const GLboolean prev_cull = ::glIsEnabled(GL_CULL_FACE); + GLint prev_depth_func = GL_LESS; + glsafe(::glGetIntegerv(GL_DEPTH_FUNC, &prev_depth_func)); + GLboolean prev_depth_mask = GL_TRUE; + glsafe(::glGetBooleanv(GL_DEPTH_WRITEMASK, &prev_depth_mask)); + glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, m_shadow_map_fbo)); + glsafe(::glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_shadow_map_texture_id, 0)); + glsafe(::glDrawBuffer(GL_NONE)); + glsafe(::glReadBuffer(GL_NONE)); + + if (::glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, static_cast(prev_fbo))); + m_shadow_map_valid = false; + } else { + glsafe(::glViewport(0, 0, size, size)); + glsafe(::glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE)); + glsafe(::glEnable(GL_DEPTH_TEST)); + glsafe(::glDepthMask(GL_TRUE)); + glsafe(::glDepthFunc(GL_LESS)); + glsafe(::glClear(GL_DEPTH_BUFFER_BIT)); + glsafe(::glEnable(GL_POLYGON_OFFSET_FILL)); + glsafe(::glPolygonOffset(4.0f, 4.0f)); + glsafe(::glDisable(GL_CULL_FACE)); + + shader->start_using(); + shader->set_uniform("projection_matrix", Transform3d(light_proj)); + for (GLVolume* volume : m_volumes.volumes) { + if (volume == nullptr || !volume->is_active || !volume->printable || volume->is_modifier || volume->is_wipe_tower) + continue; + const Transform3d view_model = Transform3d(light_view) * volume->world_matrix(); + shader->set_uniform("view_model_matrix", view_model); + volume->model.render(shader); + } + shader->stop_using(); + + // Restore state + glsafe(::glDisable(GL_POLYGON_OFFSET_FILL)); + glsafe(::glColorMask(prev_color_mask[0], prev_color_mask[1], prev_color_mask[2], prev_color_mask[3])); + if (prev_cull) + glsafe(::glEnable(GL_CULL_FACE)); + else + glsafe(::glDisable(GL_CULL_FACE)); + glsafe(::glDepthFunc(prev_depth_func)); + glsafe(::glDepthMask(prev_depth_mask)); + glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, static_cast(prev_fbo))); + glsafe(::glViewport(prev_viewport[0], prev_viewport[1], prev_viewport[2], prev_viewport[3])); + + m_shadow_map_valid = true; + } + } else { + m_shadow_map_valid = false; + } + + // ---------------------------------------------------------------------------------- + // Unified plate shadow: draw the build-plate footprint and darken it wherever the same + // depth shadow map (built above) says the light is occluded. This replaces the old planar + // stencil projection so plate, object and self shadows all come from one technique. + // ---------------------------------------------------------------------------------- + if (!m_shadow_map_valid) return; - // Shadow projection matrix - flattens geometry onto Z=0 plane along light direction - Matrix4d shadow_proj = Matrix4d::Identity(); - shadow_proj(0, 2) = -ray_dir.x() / ray_dir.z(); - shadow_proj(1, 2) = -ray_dir.y() / ray_dir.z(); - shadow_proj(2, 0) = 0.0; - shadow_proj(2, 1) = 0.0; - shadow_proj(2, 2) = 0.0; - shadow_proj(2, 3) = 0.01; // Bias to prevent shadow acne + GLShaderProgram* plate_shader = wxGetApp().get_shader("printbed_shadow"); + if (plate_shader == nullptr) + return; - // Save OpenGL state - GLint prev_depth_func = GL_LESS; - glsafe(::glGetIntegerv(GL_DEPTH_FUNC, &prev_depth_func)); - GLboolean prev_depth_mask = GL_TRUE; - glsafe(::glGetBooleanv(GL_DEPTH_WRITEMASK, &prev_depth_mask)); - GLint prev_stencil_mask = 0xFF; - glsafe(::glGetIntegerv(GL_STENCIL_WRITEMASK, &prev_stencil_mask)); - GLboolean prev_stencil_test = GL_FALSE; - glsafe(::glGetBooleanv(GL_STENCIL_TEST, &prev_stencil_test)); - - // ============================================================ - // PASS 0: Create stencil mask for the build plate (value = 1) - // ============================================================ - glsafe(::glEnable(GL_STENCIL_TEST)); - glsafe(::glStencilMask(0xFF)); - glsafe(::glClearStencil(0)); - glsafe(::glClear(GL_STENCIL_BUFFER_BIT)); - - glsafe(::glStencilFunc(GL_ALWAYS, 1, 0xFF)); - glsafe(::glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE)); - - glsafe(::glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE)); - glsafe(::glDisable(GL_DEPTH_TEST)); - - shader->start_using(); - shader->set_uniform("projection_matrix", projection_matrix); - - // Draw the build plate (cached model to avoid per-frame uploads) if (const BuildVolume& build_volume = m_bed.build_volume(); build_volume.valid()) { const std::string mask_key = build_volume.type() == BuildVolume_Type::Rectangle ? (boost::format("rect|%1$.5f|%2$.5f|%3$.5f|%4$.5f") @@ -7977,87 +8115,49 @@ void GLCanvas3D::_render_cast_shadows_on_plate(const Transform3d& view_matrix, c } if (m_plate_shadow_mask.is_initialized()) { - shader->set_uniform("view_model_matrix", view_matrix); - m_plate_shadow_mask.render(shader); + // Blend the shadow over the already-drawn plate. Depth test keeps it behind anything + // already in front; depth writes are off, and a small negative polygon offset lifts it + // just above the bed to avoid z-fighting. + GLboolean prev_depth_mask = GL_TRUE; + glsafe(::glGetBooleanv(GL_DEPTH_WRITEMASK, &prev_depth_mask)); + GLint prev_depth_func = GL_LESS; + glsafe(::glGetIntegerv(GL_DEPTH_FUNC, &prev_depth_func)); + + glsafe(::glEnable(GL_DEPTH_TEST)); + glsafe(::glDepthMask(GL_FALSE)); + glsafe(::glDepthFunc(GL_LEQUAL)); + glsafe(::glEnable(GL_BLEND)); + glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); + glsafe(::glEnable(GL_POLYGON_OFFSET_FILL)); + glsafe(::glPolygonOffset(-1.0f, -1.0f)); + + glsafe(::glActiveTexture(GL_TEXTURE4)); + glsafe(::glBindTexture(GL_TEXTURE_2D, m_shadow_map_texture_id)); + glsafe(::glActiveTexture(GL_TEXTURE0)); + + plate_shader->start_using(); + plate_shader->set_uniform("view_model_matrix", view_matrix); + plate_shader->set_uniform("projection_matrix", projection_matrix); + plate_shader->set_uniform("shadow_map", 4); + plate_shader->set_uniform("shadow_light_vp", m_shadow_light_vp); + plate_shader->set_uniform("shadow_intensity", 0.35f); + plate_shader->set_uniform("shadow_map_texel", 1.0f / static_cast(m_shadow_map_size)); + m_plate_shadow_mask.render(plate_shader); + plate_shader->stop_using(); + + glsafe(::glActiveTexture(GL_TEXTURE4)); + glsafe(::glBindTexture(GL_TEXTURE_2D, 0)); + glsafe(::glActiveTexture(GL_TEXTURE0)); + + glsafe(::glDisable(GL_POLYGON_OFFSET_FILL)); + glsafe(::glDisable(GL_BLEND)); + glsafe(::glDepthFunc(prev_depth_func)); + glsafe(::glDepthMask(prev_depth_mask)); } } - - // ============================================================ - // PASS 1: Project object shadows onto plate (increment stencil to 2) - // ============================================================ - // Only render where plate exists (stencil == 1), then increment to 2 - glsafe(::glStencilFunc(GL_EQUAL, 1, 0xFF)); - glsafe(::glStencilOp(GL_KEEP, GL_KEEP, GL_INCR)); - - glsafe(::glDepthMask(GL_FALSE)); - glsafe(::glEnable(GL_DEPTH_TEST)); - glsafe(::glDepthFunc(GL_ALWAYS)); // Shadows don't need depth testing - glsafe(::glEnable(GL_POLYGON_OFFSET_FILL)); - glsafe(::glPolygonOffset(-2.0f, -2.0f)); - glsafe(::glDisable(GL_CULL_FACE)); - - // Render projected shadow geometry - for (GLVolume* volume : m_volumes.volumes) { - if (volume == nullptr || !volume->is_active || !volume->printable || volume->is_modifier || volume->is_wipe_tower) - continue; - - // CRITICAL FIX: Apply shadow projection in object's local space, then to world, then to view - // This ensures shadows are cast from the object's actual position - Matrix4d world_matrix = volume->world_matrix().matrix(); - - // Project the shadow - this flattens the geometry onto Z=0 in WORLD space - Matrix4d shadow_world_matrix = shadow_proj * world_matrix; - - // Transform to view space for rendering - Matrix4d view_shadow_matrix = view_matrix.matrix() * shadow_world_matrix; - - shader->set_uniform("view_model_matrix", view_shadow_matrix); - shader->set_uniform("projection_matrix", projection_matrix); - - volume->model.render(shader); - } - - // ============================================================ - // PASS 2: Draw shadow color where stencil == 2 - // ============================================================ - glsafe(::glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE)); - glsafe(::glStencilFunc(GL_EQUAL, 2, 0xFF)); - glsafe(::glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP)); - glsafe(::glStencilMask(0x00)); - - glsafe(::glDepthFunc(GL_ALWAYS)); - glsafe(::glEnable(GL_BLEND)); - glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); - - // Draw shadow fill - shader->set_uniform("view_model_matrix", Transform3d::Identity()); - shader->set_uniform("projection_matrix", Transform3d::Identity()); - - const ColorRGBA shadow_fill_color(0.0f, 0.0f, 0.0f, 0.4f); // Darker shadow for visibility - const ColorRGBA prev_bg_color = m_background.get_geometry().color; - m_background.set_color(shadow_fill_color); - shader->set_uniform("uniform_color", shadow_fill_color); - m_background.render(shader); - m_background.set_color(prev_bg_color); - shader->set_uniform("uniform_color", prev_bg_color); - - shader->stop_using(); - - // ============================================================ - // RESTORE STATE - // ============================================================ - glsafe(::glEnable(GL_DEPTH_TEST)); - glsafe(::glDepthMask(prev_depth_mask)); - glsafe(::glDepthFunc(prev_depth_func)); - glsafe(::glEnable(GL_CULL_FACE)); - glsafe(::glDisable(GL_POLYGON_OFFSET_FILL)); - glsafe(::glDisable(GL_BLEND)); - - if (!prev_stencil_test) - glsafe(::glDisable(GL_STENCIL_TEST)); - glsafe(::glStencilMask(prev_stencil_mask)); } + void GLCanvas3D::_render_plane() const { ;//TODO render assemble plane @@ -8142,6 +8242,20 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with const bool phong_ssao = wxGetApp().app_config != nullptr && wxGetApp().app_config->get_bool(SETTING_OPENGL_PHONG_SSAO); shader->set_uniform("enable_ssao", phong_ssao); + // Object-on-object and self shadows: sample the depth map built in _render_shadow_map_pass(). + // shadow_intensity == 0 disables the effect entirely (unchanged behavior when off / unsupported). + if (m_shadow_map_valid && m_shadow_map_texture_id != 0) { + glsafe(::glActiveTexture(GL_TEXTURE4)); + glsafe(::glBindTexture(GL_TEXTURE_2D, m_shadow_map_texture_id)); + glsafe(::glActiveTexture(GL_TEXTURE0)); + shader->set_uniform("shadow_map", 4); + shader->set_uniform("shadow_light_vp", m_shadow_light_vp); + shader->set_uniform("shadow_map_texel", 1.0f / static_cast(m_shadow_map_size)); + shader->set_uniform("shadow_intensity", 0.35f); + } + else + shader->set_uniform("shadow_intensity", 0.0f); + const Size& cvn_size = get_canvas_size(); { const Camera& camera = wxGetApp().plater()->get_camera(); @@ -8233,6 +8347,12 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with shader->set_uniform("show_wireframe", false); }*/ + if (m_shadow_map_valid && m_shadow_map_texture_id != 0) { + glsafe(::glActiveTexture(GL_TEXTURE4)); + glsafe(::glBindTexture(GL_TEXTURE_2D, 0)); + glsafe(::glActiveTexture(GL_TEXTURE0)); + } + shader->stop_using(); } @@ -9324,7 +9444,7 @@ void GLCanvas3D::_render_canvas_toolbar() ); create_menu_item( _utf8(L("Realistic View")), - true, + m_canvas_type != ECanvasType::CanvasPreview, // not work on preview cfg->get_bool(SETTING_OPENGL_REALISTIC_MODE), [this, &cfg]{ cfg->set_bool(SETTING_OPENGL_REALISTIC_MODE, !cfg->get_bool(SETTING_OPENGL_REALISTIC_MODE)); diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index a3209dcc1c..4c2402c546 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -732,6 +732,12 @@ public: std::array m_ssao_texture_size{ { 0, 0 } }; GLModel m_plate_shadow_mask; std::string m_plate_shadow_mask_key; + // Depth-based shadow map used to cast object shadows onto other objects and themselves. + unsigned int m_shadow_map_fbo{ 0 }; + unsigned int m_shadow_map_texture_id{ 0 }; + unsigned int m_shadow_map_size{ 0 }; + Transform3d m_shadow_light_vp{ Transform3d::Identity() }; + bool m_shadow_map_valid{ false }; public: explicit GLCanvas3D(wxGLCanvas* canvas, Bed3D &bed); ~GLCanvas3D(); @@ -1251,7 +1257,9 @@ private: void _render_ssao_pass(unsigned int width, unsigned int height); void _render_background(); void _render_bed(const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, bool show_axes); - void _render_cast_shadows_on_plate(const Transform3d& view_matrix, const Transform3d& projection_matrix); + // Build the light-space depth shadow map (consumed by gouraud/phong for object & self shadows) + // and cast it onto the build plate. Realistic view only. + void _render_shadows(const Transform3d& view_matrix, const Transform3d& projection_matrix); //BBS: add part plate related logic void _render_platelist(const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, bool only_current, bool only_body = false, int hover_id = -1, bool render_cali = false, bool show_grid = true); //BBS: add outline drawing logic diff --git a/src/slic3r/GUI/GLModel.cpp b/src/slic3r/GUI/GLModel.cpp index f7fab43817..3dd15c3fdd 100644 --- a/src/slic3r/GUI/GLModel.cpp +++ b/src/slic3r/GUI/GLModel.cpp @@ -457,10 +457,9 @@ void GLModel::init_from(const indexed_triangle_set& its) data.reserve_indices(3 * its.indices.size()); // Read user preference: smooth normals enabled - const bool realistic_mode = wxGetApp().app_config != nullptr && wxGetApp().app_config->get_bool(SETTING_OPENGL_REALISTIC_MODE); const bool smooth_normals_enabled = wxGetApp().app_config != nullptr && wxGetApp().app_config->get_bool(SETTING_OPENGL_PHONG_SMOOTH_NORMALS); - if (realistic_mode && smooth_normals_enabled) { + if (smooth_normals_enabled) { // Use per-corner smooth normals (via IGL) using MapMatrixXfUnaligned = Eigen::Map>; using MapMatrixXiUnaligned = Eigen::Map>; diff --git a/src/slic3r/GUI/GLShadersManager.cpp b/src/slic3r/GUI/GLShadersManager.cpp index d368aaecd2..2b8a0edf0a 100644 --- a/src/slic3r/GUI/GLShadersManager.cpp +++ b/src/slic3r/GUI/GLShadersManager.cpp @@ -68,6 +68,10 @@ std::pair GLShadersManager::init() valid &= append_shader("thumbnail", { prefix + "thumbnail.vs", prefix + "thumbnail.fs"}); // used to render printbed valid &= append_shader("printbed", { prefix + "printbed.vs", prefix + "printbed.fs" }); +#if !SLIC3R_OPENGL_ES + // used to cast the object shadow map onto the build plate (realistic view) + valid &= append_shader("printbed_shadow", { prefix + "printbed_shadow.vs", prefix + "printbed_shadow.fs" }); +#endif // !SLIC3R_OPENGL_ES valid &= append_shader("hotbed", {prefix + "hotbed.vs", prefix + "hotbed.fs"}); // used to render options in gcode preview if (GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) { diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 121acdb947..feaddf07ab 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -6965,6 +6965,10 @@ void GUI_App::start_sync_user_preset(bool with_progress_dlg) // finishFn tears down the progress dialog (and clears the re-entrancy guard), so it // must run on every exit path — otherwise an early bail-out would leak the modal // dialog and leave the guard stuck, blocking all later manual syncs. + // Guard the whole thread body: an uncaught exception here (e.g. a transient + // boost::filesystem error while scanning the preset folder) would otherwise + // propagate out of the thread and terminate the entire application. + try { if (!m_agent) { finishFn(false); return; } // One-time scan for orphaned .info files left over from offline deletions; queues HTTP DELETEs. @@ -7206,6 +7210,11 @@ void GUI_App::start_sync_user_preset(bool with_progress_dlg) boost::this_thread::sleep_for(boost::chrono::milliseconds(500)); } } + } catch (const std::exception& e) { + BOOST_LOG_TRIVIAL(error) << "user preset sync thread terminated by exception: " << e.what(); + } catch (...) { + BOOST_LOG_TRIVIAL(error) << "user preset sync thread terminated by unknown exception"; + } }); } @@ -8526,8 +8535,13 @@ void GUI_App::scan_orphaned_info_files() if (!fs::exists(type_dir)) continue; - // Iterate through all .info files - for (auto& entry : boost::filesystem::directory_iterator(type_dir)) { + // Iterate through all .info files. Use the error_code-based iterator so a transient + // directory-read failure (e.g. macOS readdir returning ENOTSUP) is logged and skipped + // instead of throwing an uncaught exception that would terminate the app from the + // background sync thread this runs on. + boost::system::error_code ec; + for (boost::filesystem::directory_iterator it(type_dir, ec), end; !ec && it != end; it.increment(ec)) { + const auto& entry = *it; if (entry.path().extension() != ".info") continue; @@ -8546,6 +8560,8 @@ void GUI_App::scan_orphaned_info_files() } } } + if (ec) + BOOST_LOG_TRIVIAL(warning) << "scan_orphaned_info_files: failed to scan " << type_dir.string() << ": " << ec.message(); } } diff --git a/src/slic3r/GUI/GUI_Factories.cpp b/src/slic3r/GUI/GUI_Factories.cpp index ccb6dedd29..75dc44add6 100644 --- a/src/slic3r/GUI/GUI_Factories.cpp +++ b/src/slic3r/GUI/GUI_Factories.cpp @@ -132,6 +132,9 @@ std::map> SettingsFactory::PART_CATE {"infill_anchor", "", 1}, {"infill_anchor_max", "", 1}, {"top_surface_pattern", "", 1}, + {"top_surface_expansion", "", 1}, + {"top_surface_expansion_margin", "", 1}, + {"top_surface_expansion_direction", "", 1}, {"bottom_surface_pattern", "", 1}, {"internal_solid_infill_pattern", "", 1}, {"align_infill_direction_to_model", "", 1}, @@ -187,7 +190,7 @@ std::vector SettingsFactory::get_visible_options(const std::s //Quality "wall_infill_order", "ironing_type", "inner_wall_line_width", "outer_wall_line_width", "top_surface_line_width", //Shell - "wall_loops", "top_shell_layers", "bottom_shell_layers", "top_shell_thickness", "bottom_shell_thickness", + "wall_loops", "top_shell_layers", "bottom_shell_layers", "top_shell_thickness", "bottom_shell_thickness", "top_surface_expansion", "top_surface_expansion_margin", "top_surface_expansion_direction", //Infill "sparse_infill_density", "sparse_infill_pattern", "top_surface_pattern", "bottom_surface_pattern", "infill_combination", "infill_direction", "infill_wall_overlap", //speed diff --git a/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp index 992c28c119..2d448df164 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp @@ -1905,7 +1905,7 @@ bool GLGizmoAdvancedCut::render_slider_double_input(const std::string &label, fl mean_size *= float(units_mm_to_in); min_size *= float(units_mm_to_in); } - std::string format = value_in < 0.f ? " " : m_imperial_units ? "%.4f " + _u8L("in") : "%.2f " + _u8L("mm"); + std::string format = value_in < 0.f ? " " : m_imperial_units ? "%.4f " + _CTX_utf8("in", "inches") : "%.2f " + _u8L("mm"); m_imgui->bbl_slider_float_style(("##" + label).c_str(), &value, min_size, mean_size, format.c_str()); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp index 414c520ded..353301995f 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp @@ -241,7 +241,7 @@ std::string GLGizmoCut3D::get_tooltip() const std::string tooltip; if (m_hover_id == Z || (m_dragging && m_hover_id == CutPlane)) { double koef = m_imperial_units ? GizmoObjectManipulation::mm_to_in : 1.0; - std::string unit_str = " " + (m_imperial_units ? _u8L("in") : _u8L("mm")); + std::string unit_str = " " + (m_imperial_units ? _CTX_utf8("in", "inches") : _u8L("mm")); const BoundingBoxf3& tbb = m_transformed_bounding_box; const std::string name = m_keep_as_parts ? _u8L("Part") : _u8L("Object"); @@ -541,7 +541,7 @@ bool GLGizmoCut3D::render_double_input(const std::string& label, double& value_i ImGui::InputDouble(("##" + label).c_str(), &value, 0.0f, 0.0f, "%.2f", ImGuiInputTextFlags_CharsDecimal); ImGui::SameLine(); - m_imgui->text(m_imperial_units ? _L("in") : _L("mm")); + m_imgui->text(m_imperial_units ? _CTX("in", "inches") : _L("mm")); value_in = value * (m_imperial_units ? GizmoObjectManipulation::in_to_mm : 1.0); return !is_approx(old_val, value); @@ -582,7 +582,7 @@ bool GLGizmoCut3D::render_slider_two_input(const std::string& label, float& valu if (m_imperial_units) { min_size *= f_mm_to_in; } - std::string format = value_in < 0.f ? " " : m_imperial_units ? "%.4f " + _u8L("in") : "%.2f " + _u8L("mm"); + std::string format = value_in < 0.f ? " " : m_imperial_units ? "%.4f " + _CTX_utf8("in", "inches") : "%.2f " + _u8L("mm"); m_imgui->bbl_slider_float_style(("##" + label).c_str(), &value, min_size, mean_size, format.c_str()); @@ -653,7 +653,7 @@ bool GLGizmoCut3D::render_slider_input(const std::string& label, float& value_in if (m_imperial_units) { min_size *= f_mm_to_in; } - std::string format = value_in < 0.f ? " " : m_imperial_units ? "%.4f " + _u8L("in") : "%.2f " + _u8L("mm"); + std::string format = value_in < 0.f ? " " : m_imperial_units ? "%.4f " + _CTX_utf8("in", "inches") : "%.2f " + _u8L("mm"); m_imgui->bbl_slider_float_style(("##" + label).c_str(), &value, min_size, max_value, format.c_str()); @@ -2472,7 +2472,7 @@ void GLGizmoCut3D::render_connectors_input_window(CutConnectors &connectors, flo void GLGizmoCut3D::render_build_size() { double koef = m_imperial_units ? GizmoObjectManipulation::mm_to_in : 1.0; - wxString unit_str = m_imperial_units ? _L("in") : _L("mm"); + wxString unit_str = m_imperial_units ? _CTX("in", "inches") : _L("mm"); Vec3d tbb_sz = m_transformed_bounding_box.size() * koef; // ORCA ImGui::AlignTextToFramePadding(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp index b7c963cc63..3d51c77c00 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp @@ -1951,7 +1951,7 @@ void GLGizmoEmboss::draw_model_type() float minimum_spacing_x = 8.0f; float minimum_offset_x = ImGui::GetCursorPosX() + minimum_spacing_x; float offset_x = std::max(m_gui_cfg->input_offset, minimum_offset_x); - ImGui::SameLine(offset_x); + ImGui::SameLine(); ImGuiWrapper::push_radio_style(m_parent.get_scale()); // ORCA if (ImGui::RadioButton(_u8L("Join").c_str(), type == part)) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp index dc2ec0d46e..f190e1ad97 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp @@ -315,6 +315,17 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l ImGui::SameLine(drag_left_width + sliders_left_width); ImGui::PushItemWidth(1.5 * slider_icon_width); ImGui::BBLDragFloat("##cursor_radius_input", &m_cursor_radius, 0.05f, 0.0f, 0.0f, "%.2f"); + + if (m_imgui->bbl_checkbox(_L("Vertical"), m_vertical_only)) { + if (m_vertical_only) { + m_horizontal_only = false; + } + } + if (m_imgui->bbl_checkbox(_L("Horizontal"), m_horizontal_only)) { + if (m_horizontal_only) { + m_vertical_only = false; + } + } } else if (m_current_tool == ImGui::SphereButtonIcon) { m_cursor_type = TriangleSelector::CursorType::SPHERE; m_tool_type = ToolType::BRUSH; @@ -327,6 +338,17 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l ImGui::SameLine(drag_left_width + sliders_left_width); ImGui::PushItemWidth(1.5 * slider_icon_width); ImGui::BBLDragFloat("##cursor_radius_input", &m_cursor_radius, 0.05f, 0.0f, 0.0f, "%.2f"); + + if (m_imgui->bbl_checkbox(_L("Vertical"), m_vertical_only)) { + if (m_vertical_only) { + m_horizontal_only = false; + } + } + if (m_imgui->bbl_checkbox(_L("Horizontal"), m_horizontal_only)) { + if (m_horizontal_only) { + m_vertical_only = false; + } + } } else if (m_current_tool == ImGui::FillButtonIcon) { m_cursor_type = TriangleSelector::CursorType::POINTER; m_tool_type = ToolType::SMART_FILL; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp index 0bdc3d1302..a99b68340d 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp @@ -1252,7 +1252,7 @@ void GLGizmoMeasure::render_dimensioning() const bool use_inches = wxGetApp().app_config->get_bool("use_inches"); const double curr_value = use_inches ? GizmoObjectManipulation::mm_to_in * distance : distance; const std::string curr_value_str = format_double(curr_value); - const std::string units = use_inches ? _u8L("in") : _u8L("mm"); + const std::string units = use_inches ? _CTX_utf8("in", "inches") : _u8L("mm"); const float value_str_width = 20.0f + ImGui::CalcTextSize(curr_value_str.c_str()).x; static double edit_value = 0.0; @@ -1303,7 +1303,7 @@ void GLGizmoMeasure::render_dimensioning() return; const double ratio = new_value / old_value; - wxGetApp().plater()->take_snapshot(_u8L("Scale"), UndoRedo::SnapshotType::GizmoAction); + wxGetApp().plater()->take_snapshot(_CTX_utf8("Scale", "Verb"), UndoRedo::SnapshotType::GizmoAction); // apply scale TransformationType type; type.set_world(); @@ -2130,7 +2130,7 @@ void GLGizmoMeasure::show_face_face_assembly_senior() void GLGizmoMeasure::init_render_input_window() { m_use_inches = wxGetApp().app_config->get_bool("use_inches"); - m_units = m_use_inches ? " " + _u8L("in") : " " + _u8L("mm"); + m_units = " " + (m_use_inches ? _CTX_utf8("in", "inches") : _u8L("mm")); m_space_size = ImGui::CalcTextSize(" ").x * 2; m_input_size_max = ImGui::CalcTextSize("-100.00").x * 1.2; m_same_model_object = is_two_volume_in_same_model_object(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSVG.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSVG.cpp index 68f353e606..1da865105f 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSVG.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSVG.cpp @@ -1704,7 +1704,7 @@ void GLGizmoSVG::draw_size() if (m_keep_ratio) { std::stringstream ss; - ss << std::setprecision(2) << std::fixed << width << " x " << height << " " << (use_inch ? "in" : "mm"); + ss << std::setprecision(2) << std::fixed << width << " x " << height << " " << (use_inch ? _CTX("in", "inches") : _L("mm")); ImGui::SameLine(m_gui_cfg->input_offset); ImGui::SetNextItemWidth(m_gui_cfg->input_width); @@ -1989,7 +1989,7 @@ void GLGizmoSVG::draw_mirroring() void GLGizmoSVG::draw_model_type() { - ImGui::AlignTextToFramePadding(); + //ImGui::AlignTextToFramePadding(); bool is_last_solid_part = m_volume->is_the_only_one_part(); std::string title = _u8L("Operation"); if (is_last_solid_part) { @@ -2005,6 +2005,8 @@ void GLGizmoSVG::draw_model_type() ModelVolumeType part = ModelVolumeType::MODEL_PART; ModelVolumeType type = m_volume->type(); + ImGui::SameLine(); + //TRN EmbossOperation ImGuiWrapper::push_radio_style(m_parent.get_scale()); //ORCA if (ImGui::RadioButton(_u8L("Join").c_str(), type == part)) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp index 77fc7ef46c..ebbb76f348 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp @@ -143,9 +143,9 @@ bool GLGizmoScale3D::on_init() std::string GLGizmoScale3D::on_get_name() const { if (!on_is_activable() && m_state == EState::Off) { - return _u8L("Scale") + ":\n" + _u8L("Please select at least one object."); + return _CTX_utf8("Scale", "Verb") + ":\n" + _u8L("Please select at least one object."); } else { - return _u8L("Scale"); + return _CTX_utf8("Scale", "Verb"); } } diff --git a/src/slic3r/GUI/Gizmos/GizmoObjectManipulation.cpp b/src/slic3r/GUI/Gizmos/GizmoObjectManipulation.cpp index 8680ee13a3..3f82777a2a 100644 --- a/src/slic3r/GUI/Gizmos/GizmoObjectManipulation.cpp +++ b/src/slic3r/GUI/Gizmos/GizmoObjectManipulation.cpp @@ -54,7 +54,7 @@ GizmoObjectManipulation::GizmoObjectManipulation(GLCanvas3D& glcanvas) : m_glcanvas(glcanvas) { m_imperial_units = wxGetApp().app_config->get("use_inches") == "1"; - m_new_unit_string = m_imperial_units ? L("in") : L("mm"); + m_new_unit_string = m_imperial_units ? L_CONTEXT("in", "inches") : L("mm"); const wxString shift = GUI::shortkey_shift_prefix(); const wxString alt = GUI::shortkey_alt_prefix(); @@ -92,7 +92,7 @@ void GizmoObjectManipulation::update_ui_from_settings() if (m_imperial_units != (wxGetApp().app_config->get("use_inches") == "1")) { m_imperial_units = wxGetApp().app_config->get("use_inches") == "1"; - m_new_unit_string = m_imperial_units ? L("in") : L("mm"); + m_new_unit_string = m_imperial_units ? L_CONTEXT("in", "inches") : L("mm"); update_buffered_value(); } @@ -1161,7 +1161,7 @@ void GizmoObjectManipulation::do_render_scale_input_window(ImGuiWrapper* imgui_w imgui_wrapper->calc_text_size(_L("Part")).x }) + imgui_wrapper->calc_text_size("xxx"sv).x + imgui_wrapper->scaled(3.5f); float label_max = std::max({ - imgui_wrapper->calc_text_size(_L("Scale")).x, + imgui_wrapper->calc_text_size(_CTX("Scale", "Noun")).x, imgui_wrapper->calc_text_size(_L("Size")).x }); float caption_max = std::max(label_max, coord_combo_width - 3 * space_size); @@ -1218,7 +1218,7 @@ void GizmoObjectManipulation::do_render_scale_input_window(ImGuiWrapper* imgui_w //ImGui::PushItemWidth(unit_size * 2); ImGui::AlignTextToFramePadding(); - imgui_wrapper->text(_L("Scale")); + imgui_wrapper->text(_CTX("Scale", "Noun")); ImGui::SameLine(caption_max + space_size); ImGui::PushItemWidth(unit_size); ImGui::BBLInputDouble(label_scale_values[0][0], &scale[0], 0.0f, 0.0f, "%.2f"); diff --git a/src/slic3r/GUI/ImGuiWrapper.cpp b/src/slic3r/GUI/ImGuiWrapper.cpp index d4d08aa84f..c7609be5ef 100644 --- a/src/slic3r/GUI/ImGuiWrapper.cpp +++ b/src/slic3r/GUI/ImGuiWrapper.cpp @@ -2781,6 +2781,11 @@ void ImGuiWrapper::init_font(bool compress) builder.BuildRanges(&ranges); // Build the final result (ordered ranges with all the unique characters submitted) io.Fonts->Flags |= ImFontAtlasFlags_NoPowerOfTwoHeight; + // TexDesiredWidth will be increased adaptively below if the built height + // exceeds GL_MAX_TEXTURE_SIZE. Leave it at 0 so ImGui picks the minimum + // width for small glyph sets and we only widen when actually necessary. + io.Fonts->TexDesiredWidth = 0; + ImFontConfig cfg = ImFontConfig(); cfg.OversampleH = cfg.OversampleV = 1; //FIXME replace with io.Fonts->AddFontFromMemoryTTF(buf_decompressed_data, (int)buf_decompressed_size, m_font_size, nullptr, ranges.Data); @@ -2852,7 +2857,23 @@ void ImGuiWrapper::init_font(bool compress) io.Fonts->AddCustomRectFontGlyph(default_font, icon.first, icon_sz * 4, icon_sz * 4, 3.0 * font_scale + icon_sz * 4); } - // Build texture atlas + // Build texture atlas, widening it if the height would exceed GL_MAX_TEXTURE_SIZE. + // Increasing the width allows the packing algorithm to grow more horizontally which reduces the height. + io.Fonts->Build(); + GLint gl_max_tex_size = 0; + glsafe(::glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max_tex_size)); + constexpr int max_retries = 6; + for (int attempt = 0; attempt < max_retries && io.Fonts->TexHeight > gl_max_tex_size; ++attempt) { + io.Fonts->TexDesiredWidth = (io.Fonts->TexDesiredWidth > 0 ? io.Fonts->TexDesiredWidth : io.Fonts->TexWidth) * 2; + io.Fonts->Build(); + } + if (io.Fonts->TexHeight > gl_max_tex_size) { + // Shouldn't really happen + BOOST_LOG_TRIVIAL(error) << "Font atlas height " << io.Fonts->TexHeight + << " still exceeds GL_MAX_TEXTURE_SIZE (" << gl_max_tex_size << ")" + << " after " << max_retries << " attempts; rendering may be incomplete"; + } + unsigned char* pixels; int width, height; io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory. diff --git a/src/slic3r/GUI/ImageGrid.cpp b/src/slic3r/GUI/ImageGrid.cpp index 77fd7b132e..3c333c93fb 100644 --- a/src/slic3r/GUI/ImageGrid.cpp +++ b/src/slic3r/GUI/ImageGrid.cpp @@ -644,7 +644,7 @@ void Slic3r::GUI::ImageGrid::renderContent1(wxDC &dc, wxPoint const &pt, int ind if (m_file_sys->GetFileType() == PrinterFileSystem::F_MODEL) { if (secondAction != _L("Play")) thirdAction = secondAction; - secondAction = _L("Print"); + secondAction = _CTX("Print", "Verb"); } // Draw buttons on hovered item wxRect rect{pt.x, pt.y + m_content_rect.GetBottom() - m_buttons_background.GetHeight(), m_content_rect.GetWidth(), m_buttons_background.GetHeight()}; diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 66d7d87835..d850f2a925 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -2013,10 +2013,10 @@ wxBoxSizer* MainFrame::create_side_tools() }); // upload and print - SideButton* send_gcode_btn = new SideButton(p, _L("Print"), ""); + SideButton* send_gcode_btn = new SideButton(p, _CTX("Print", "Verb"), ""); send_gcode_btn->SetCornerRadius(0); send_gcode_btn->Bind(wxEVT_BUTTON, [this, p](wxCommandEvent&) { - m_print_btn->SetLabel(_L("Print")); + m_print_btn->SetLabel(_CTX("Print", "Verb")); m_print_select = eSendGcode; m_print_enable = get_enable_print_status(); m_print_btn->Enable(m_print_enable); @@ -2662,9 +2662,9 @@ static void add_common_view_menu_items(wxMenu* view_menu, MainFrame* mainFrame, "", nullptr, [can_change_view]() { return can_change_view(); }, mainFrame); append_menu_item(view_menu, wxID_ANY, _L("Rear") + "\t" + ctrl + "4", _L("Rear View"), [mainFrame](wxCommandEvent&) { mainFrame->select_view("rear"); }, "", nullptr, [can_change_view]() { return can_change_view(); }, mainFrame); - append_menu_item(view_menu, wxID_ANY, _CTX(L_CONTEXT("Left", "Camera"), "Camera") + "\t" + ctrl + "5", _L("Left View"),[mainFrame](wxCommandEvent &) {mainFrame->select_view("left"); }, + append_menu_item(view_menu, wxID_ANY, _CTX("Left", "Camera View") + "\t" + ctrl + "5", _L("Left View"),[mainFrame](wxCommandEvent &) {mainFrame->select_view("left"); }, "", nullptr, [can_change_view]() { return can_change_view(); }, mainFrame); - append_menu_item(view_menu, wxID_ANY, _CTX(L_CONTEXT("Right", "Camera"), "Camera") + "\t" + ctrl + "6", _L("Right View"),[mainFrame](wxCommandEvent &) { mainFrame->select_view("right"); }, + append_menu_item(view_menu, wxID_ANY, _CTX("Right", "Camera View") + "\t" + ctrl + "6", _L("Right View"),[mainFrame](wxCommandEvent &) { mainFrame->select_view("right"); }, "", nullptr, [can_change_view]() { return can_change_view(); }, mainFrame); } @@ -2809,21 +2809,6 @@ void MainFrame::init_menubar_as_editor() append_submenu(fileMenu, export_menu, wxID_ANY, _L("Export"), ""); fileMenu->AppendSeparator(); - append_menu_item(fileMenu, wxID_ANY, _L("Sync Presets"), _L("Pull and apply the latest presets from OrcaCloud"), - [this](wxCommandEvent&) { - if (!wxGetApp().is_user_login()) { - MessageDialog info_dlg(this, _L("You must be logged in to sync presets from cloud."), - _L("Sync Presets"), wxOK | wxICON_INFORMATION); - info_dlg.ShowModal(); - return; - } - wxGetApp().restart_sync_user_preset(); - }, "", nullptr, - [this]() { - return wxGetApp().is_user_login() && !wxGetApp().app_config->get_stealth_mode(); - }, this); - - fileMenu->AppendSeparator(); #ifndef __APPLE__ append_menu_item(fileMenu, wxID_EXIT, _L("Quit"), wxString::Format(_L("Quit")), @@ -3289,6 +3274,8 @@ void MainFrame::init_menubar_as_editor() }, "", nullptr, []() { return true; }, this); + m_topbar->GetTopMenu()->AppendSeparator(); + append_menu_item( m_topbar->GetTopMenu(), wxID_ANY, _L("Preset Bundle") + "\t", "", [this](wxCommandEvent &) { @@ -3316,6 +3303,8 @@ void MainFrame::init_menubar_as_editor() return wxGetApp().is_user_login() && !wxGetApp().app_config->get_stealth_mode(); }, this); + m_topbar->GetTopMenu()->AppendSeparator(); + //m_topbar->AddDropDownMenuItem(preference_item); //m_topbar->AddDropDownMenuItem(printer_item); //m_topbar->AddDropDownMenuItem(language_item); @@ -3425,6 +3414,25 @@ void MainFrame::init_menubar_as_editor() plater()->get_current_canvas3D()->force_set_focus(); }, "", nullptr, []() { return true; }, this); + + append_menu_item( + fileMenu, wxID_ANY, _L("Sync Presets"), _L("Pull and apply the latest presets from OrcaCloud"), + [this](wxCommandEvent&) { + if (!wxGetApp().is_user_login()) { + MessageDialog info_dlg(this, _L("You must be logged in to sync presets from cloud."), + _L("Sync Presets"), wxOK | wxICON_INFORMATION); + info_dlg.ShowModal(); + return; + } + if (m_plater) + m_plater->get_notification_manager()->push_notification( + into_u8(_L("Syncing presets from cloud\u2026"))); + wxGetApp().restart_sync_user_preset(); + }, "", nullptr, + [this]() { + return wxGetApp().is_user_login() && !wxGetApp().app_config->get_stealth_mode(); + }, this); + m_menubar->Append(fileMenu, wxString::Format("&%s", _L("File"))); if (editMenu) m_menubar->Append(editMenu, wxString::Format("&%s", _L("Edit"))); @@ -4040,7 +4048,7 @@ void MainFrame::set_print_button_to_default(PrintSelectType select_type) m_print_btn->Enable(m_print_enable); this->Layout(); } else if (select_type == PrintSelectType::eSendGcode) { - m_print_btn->SetLabel(_L("Print")); + m_print_btn->SetLabel(_CTX("Print", "Verb")); m_print_select = eSendGcode; if (m_print_enable) m_print_enable = get_enable_print_status() && can_send_gcode(); diff --git a/src/slic3r/GUI/MediaFilePanel.cpp b/src/slic3r/GUI/MediaFilePanel.cpp index 1fca47e7c4..6c1a261966 100644 --- a/src/slic3r/GUI/MediaFilePanel.cpp +++ b/src/slic3r/GUI/MediaFilePanel.cpp @@ -520,7 +520,7 @@ void MediaFilePanel::fetchUrl(boost::weak_ptr wfs) fs->SetUrl(res); } }); - }); + }, wxGetApp().get_printer_cloud_provider()); } } @@ -556,7 +556,7 @@ void MediaFilePanel::doAction(size_t index, int action) } else if (action == 1) { if (fs->GetFileType() == PrinterFileSystem::F_MODEL) { if (index != -1) { - auto dlg = new MediaProgressDialog(_L("Print"), this, [fs] { fs->FetchModelCancel(); }); + auto dlg = new MediaProgressDialog(_CTX("Print", "Verb"), this, [fs] { fs->FetchModelCancel(); }); dlg->Update(0, _L("Fetching model information...")); fs->FetchModel(index, [this, fs, dlg, index](int result, std::string const &data) { dlg->Destroy(); @@ -566,7 +566,7 @@ void MediaFilePanel::doAction(size_t index, int action) wxString msg = data.empty() ? _L("Failed to fetch model information from printer.") : from_u8(data); CallAfter([this, msg] { - MessageDialog(this, msg, _L("Print"), wxOK).ShowModal(); + MessageDialog(this, msg, _CTX("Print", "Verb"), wxOK).ShowModal(); }); return; } @@ -579,7 +579,7 @@ void MediaFilePanel::doAction(size_t index, int action) || plate_data_list.empty()) { MessageDialog(this, _L("Failed to parse model information."), - _L("Print"), wxOK).ShowModal(); + _CTX("Print", "Verb"), wxOK).ShowModal(); return; } diff --git a/src/slic3r/GUI/NotificationManager.cpp b/src/slic3r/GUI/NotificationManager.cpp index 2e8d22ebee..0b184710c2 100644 --- a/src/slic3r/GUI/NotificationManager.cpp +++ b/src/slic3r/GUI/NotificationManager.cpp @@ -2299,9 +2299,17 @@ void NotificationManager::push_import_finished_notification(const std::string& p void NotificationManager::SharedProfilesNotification::init() { PopNotification::init(); - // Add two extra lines for the hyperlink row ("Browse shared profiles" + "Don't show again") - // and 1 more additional line for adding spacing between them to make it easier to click - m_lines_count = m_lines_count + 2; // ORCA + + // PopNotification::count_lines() may append a duplicate "hypertext doesn't fit inline" placeholder endline (same value as the previous entry) + // for the generic renderer's benefit. This class always renders its hyperlink on its own dedicated line regardless, + // so that placeholder is meaningless here and would otherwise be drawn as a spurious blank text row. + if (!m_hypertext.empty() && m_endlines.size() >= 2 && m_endlines.back() == m_endlines[m_endlines.size() - 2]) { + m_endlines.pop_back(); + m_lines_count--; + } + + // Reserve rows for: "Browse shared profiles" hyperlink, spacing, "Don't show again" + m_lines_count += 3; } void NotificationManager::SharedProfilesNotification::render_text(ImGuiWrapper& imgui, @@ -2327,22 +2335,26 @@ void NotificationManager::SharedProfilesNotification::render_text(ImGuiWrapper& } } - // Render "Browse shared profiles" hyperlink on the next line - float hyper_y = starting_y + m_endlines.size() * shift_y - m_line_height / 2.f; - render_hypertext(imgui, x_offset, hyper_y, m_hypertext); - - // Render "Don't show again" hyperlink after the browse link { - float dont_show_y = hyper_y + ImGui::CalcTextSize((m_hypertext + " ").c_str()).y + m_line_height / 2.f; - std::string dont_show_text = _u8L("Don't show again"); + float hyper_y = starting_y + m_endlines.size() * shift_y + m_line_height * .5f; + float dont_show_y = hyper_y + ImGui::CalcTextSize((m_hypertext + " ").c_str()).y + m_line_height * .5f; + std::string dont_show_text = _u8L("Don't show again") + std::to_string(m_endlines.size()); ImVec2 part_size = ImGui::CalcTextSize(dont_show_text.c_str()); + if (!m_multiline && m_lines_count > 2) { + render_hypertext(imgui, x_offset + (m_endlines.size() == 1 ? 0 : ImGui::CalcTextSize((line + " ").c_str()).x) , starting_y + shift_y, _u8L("More"), true); + } + else { + // Render "Browse shared profiles" hyperlink on the next line + render_hypertext(imgui, x_offset, hyper_y, m_hypertext); + // Invisible button ImGui::SetCursorPosX(x_offset); // ORCA render on new line to prevent long translations from being cut off ImGui::SetCursorPosY(dont_show_y); ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f)); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f)); ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(.0f, .0f, .0f, .0f)); + // Render "Don't show again" hyperlink after the browse link if (imgui.button("##dont_show_btn", part_size.x + 6, part_size.y + 10)) { wxGetApp().app_config->set_bool("show_shared_profiles_notification", false); wxGetApp().app_config->save(); @@ -2370,6 +2382,7 @@ void NotificationManager::SharedProfilesNotification::render_text(ImGuiWrapper& ImGui::GetWindowDrawList()->AddLine(lineStart, lineEnd, IM_COL32((int)(color.x * 255), (int)(color.y * 255), (int)(color.z * 255), (int)(color.w * 255.f * (m_state == EState::FadingOut ? m_current_fade_opacity : 1.f)))); + } } } @@ -2382,8 +2395,10 @@ bool NotificationManager::SharedProfilesNotification::on_text_click() void NotificationManager::SharedProfilesNotification::render_hypertext(ImGuiWrapper& imgui, const float text_x, const float text_y, const std::string text, bool more) { - render_hyperlink_action(imgui, text_x, text_y, text, "##browse_btn", - [this] { if (on_text_click()) close(); }); + if (more) + PopNotification::render_hypertext(imgui, text_x, text_y, text, true); + else + render_hyperlink_action(imgui, text_x, text_y, text, "##browse_btn", [this] { if (on_text_click()) close(); }); } void NotificationManager::OrcaSyncConflictNotification::init() diff --git a/src/slic3r/GUI/PartPlate.cpp b/src/slic3r/GUI/PartPlate.cpp index 18d6e17b33..6a4e747d3a 100644 --- a/src/slic3r/GUI/PartPlate.cpp +++ b/src/slic3r/GUI/PartPlate.cpp @@ -385,7 +385,7 @@ void PartPlate::set_spiral_vase_mode(bool spiral_mode, bool as_global) } } -bool PartPlate::valid_instance(int obj_id, int instance_id) +bool PartPlate::valid_instance(int obj_id, int instance_id) const { if ((obj_id >= 0) && (obj_id < m_model->objects.size())) { @@ -1688,7 +1688,7 @@ std::vector PartPlate::get_extruders_under_cli(bool conside_custom_gcode, D int obj_id = it->first; int instance_id = it->second; - if ((obj_id >= 0) && (obj_id < m_model->objects.size())) + if (valid_instance(obj_id, instance_id)) { ModelObject* object = m_model->objects[obj_id]; ModelInstance* instance = object->instances[instance_id]; @@ -2359,6 +2359,9 @@ void PartPlate::set_pos_and_size(Vec3d& origin, int width, int depth, int height for (std::set>::iterator it = obj_to_instance_set.begin(); it != obj_to_instance_set.end(); ++it) { int obj_id = it->first; int instance_id = it->second; + if (!valid_instance(obj_id, instance_id)) + continue; + ModelObject* object = m_model->objects[obj_id]; ModelInstance* instance = object->instances[instance_id]; @@ -2833,7 +2836,7 @@ void PartPlate::duplicate_all_instance(unsigned int dup_count, bool need_skip, s int obj_id = it->first; int instance_id = it->second; - if ((obj_id >= 0) && (obj_id < m_model->objects.size())) + if (valid_instance(obj_id, instance_id)) { ModelObject* object = m_model->objects[obj_id]; ModelInstance* instance = object->instances[instance_id]; @@ -2866,7 +2869,7 @@ void PartPlate::duplicate_all_instance(unsigned int dup_count, bool need_skip, s int obj_id = it->first; int instance_id = it->second; - if ((obj_id >= 0) && (obj_id < m_model->objects.size())) + if (valid_instance(obj_id, instance_id)) { ModelObject* object = m_model->objects[obj_id]; ModelInstance* instance = object->instances[instance_id]; @@ -2983,8 +2986,8 @@ int PartPlate::printable_instance_size() int obj_id = it->first; int instance_id = it->second; - if (obj_id >= m_model->objects.size()) - continue; + if (!valid_instance(obj_id, instance_id)) + continue; ModelObject * object = m_model->objects[obj_id]; ModelInstance *instance = object->instances[instance_id]; @@ -3006,7 +3009,7 @@ bool PartPlate::has_printable_instances() int obj_id = it->first; int instance_id = it->second; - if (obj_id >= m_model->objects.size()) + if (!valid_instance(obj_id, instance_id)) continue; ModelObject* object = m_model->objects[obj_id]; @@ -3030,7 +3033,8 @@ bool PartPlate::is_all_instances_unprintable() int obj_id = it->first; int instance_id = it->second; - if (obj_id >= m_model->objects.size()) continue; + if (!valid_instance(obj_id, instance_id)) + continue; ModelObject * object = m_model->objects[obj_id]; ModelInstance *instance = object->instances[instance_id]; diff --git a/src/slic3r/GUI/PartPlate.hpp b/src/slic3r/GUI/PartPlate.hpp index d4c5399142..f841c001a5 100644 --- a/src/slic3r/GUI/PartPlate.hpp +++ b/src/slic3r/GUI/PartPlate.hpp @@ -167,7 +167,7 @@ private: wxCoord m_name_texture_height; void init(); - bool valid_instance(int obj_id, int instance_id); + bool valid_instance(int obj_id, int instance_id) const; void generate_print_polygon(ExPolygon &print_polygon); void generate_exclude_polygon(ExPolygon &exclude_polygon); void generate_logo_polygon(ExPolygon &logo_polygon); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 26b9217b3f..b7b8111f1e 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -537,6 +537,7 @@ struct Sidebar::priv //wxComboBox * m_comboBox_print_preset; wxStaticLine * m_staticline1; StaticBox* m_panel_filament_title; + wxPanel* m_panel_filament_separator; wxStaticText* m_staticText_filament_settings; wxStaticText* m_staticText_filament_count; ScalableButton * m_bpButton_add_filament; @@ -556,6 +557,7 @@ struct Sidebar::priv // BBS printer config StaticBox* m_panel_printer_title = nullptr; + wxPanel* m_panel_printer_separator = nullptr; ScalableButton* m_printer_icon = nullptr; ScalableButton* m_printer_connect = nullptr; ScalableButton* m_printer_bbl_sync = nullptr; @@ -1735,10 +1737,6 @@ Sidebar::Sidebar(Plater *parent) p->m_panel_printer_title->Layout(); // 1.2 Add spliters around title bar - // add spliter 1 - //auto spliter_1 = new ::StaticLine(p->scrolled); - //spliter_1->SetBackgroundColour("#A6A9AA"); - //scrolled_sizer->Add(spliter_1, 0, wxEXPAND); // add printer title scrolled_sizer->Add(p->m_panel_printer_title, 0, wxEXPAND | wxALL, 0); @@ -1750,14 +1748,13 @@ Sidebar::Sidebar(Plater *parent) wxString title = _L("Printer") + wxString(!isShown ? "" : (" | " + p->combo_printer->GetValue())); p->m_text_printer_settings->SetLabel(title); p->m_panel_printer_content->Show(!isShown); + p->m_panel_printer_separator->Show(isShown); m_scrolled_sizer->Layout(); }); - - // add spliter 2 - auto spliter_2 = new ::StaticLine(p->scrolled); - spliter_2->SetLineColour("#CECECE"); - scrolled_sizer->Add(spliter_2, 0, wxEXPAND); - + // ORCA add bottom border for seperation wile sections folded + p->m_panel_printer_separator = new wxPanel(p->scrolled, wxID_ANY, wxDefaultPosition, wxSize(-1, FromDIP(2))); // ORCA staticline class not works without string + p->m_panel_printer_separator->SetBackgroundColour("#FFFFFF"); + scrolled_sizer->Add(p->m_panel_printer_separator, 0, wxEXPAND); /*************************** 2. add printer content ************************/ @@ -1937,9 +1934,9 @@ Sidebar::Sidebar(Plater *parent) } wxGridSizer *nozzle_dia_sizer = new wxGridSizer(3, 1, FromDIP(2), 0); - nozzle_dia_sizer->Add(p->label_nozzle_title, 0, wxALIGN_CENTER | wxTOP, FromDIP(4)); - nozzle_dia_sizer->Add(p->combo_nozzle_dia , 0, wxALIGN_CENTER | wxTOP | wxBOTTOM, FromDIP(2)); - nozzle_dia_sizer->Add(p->label_nozzle_type , 0, wxALIGN_CENTER); + nozzle_dia_sizer->Add(p->label_nozzle_title, 1, wxALIGN_CENTER | wxTOP , FromDIP(2)); + nozzle_dia_sizer->Add(p->combo_nozzle_dia , 0, wxALIGN_CENTER); + nozzle_dia_sizer->Add(p->label_nozzle_type , 1, wxALIGN_CENTER | wxBOTTOM, FromDIP(1)); p->panel_nozzle_dia->SetSizer(nozzle_dia_sizer); @@ -2108,7 +2105,9 @@ Sidebar::Sidebar(Plater *parent) else if (ams_btn->IsShown()) exclude_pt = ams_btn->GetPosition().x; if (e.GetPosition().x > exclude_pt) return; - p->m_panel_filament_content->Show(!p->m_panel_filament_content->IsShown()); + bool isShown = p->m_panel_filament_content->IsShown(); + p->m_panel_filament_content->Show(!isShown); + p->m_panel_filament_separator->Show(isShown); m_scrolled_sizer->Layout(); CallAfter([this]{update_filaments_counter(true);}); // call after all UI processing done @@ -2128,13 +2127,11 @@ Sidebar::Sidebar(Plater *parent) p->m_panel_filament_title->SetSizer( bSizer39 ); p->m_panel_filament_title->Layout(); - auto spliter_1 = new ::StaticLine(p->scrolled); - spliter_1->SetLineColour("#A6A9AA"); - scrolled_sizer->Add(spliter_1, 0, wxEXPAND); scrolled_sizer->Add(p->m_panel_filament_title, 0, wxEXPAND | wxALL, 0); - auto spliter_2 = new ::StaticLine(p->scrolled); - spliter_2->SetLineColour("#CECECE"); - scrolled_sizer->Add(spliter_2, 0, wxEXPAND); + // ORCA add bottom border for seperation wile sections folded + p->m_panel_filament_separator = new wxPanel(p->scrolled, wxID_ANY, wxDefaultPosition, wxSize(-1, FromDIP(2))); // ORCA staticline class not works without string + p->m_panel_filament_separator->SetBackgroundColour("#FFFFFF"); + scrolled_sizer->Add(p->m_panel_filament_separator, 0, wxEXPAND); bSizer39->AddStretchSpacer(1); @@ -9687,11 +9684,14 @@ void Plater::priv::on_select_preset(wxCommandEvent &evt) } } } + } else { + // BBS + // wxWindowUpdateLocker noUpdates1(sidebar->print_panel()); + wxWindowUpdateLocker noUpdates2(sidebar->filament_panel()); + wxGetApp().get_tab(preset_type)->select_preset(preset_name); + // update plater with new config + q->on_config_change(wxGetApp().preset_bundle->full_config()); } - //BBS - //wxWindowUpdateLocker noUpdates1(sidebar->print_panel()); - wxWindowUpdateLocker noUpdates2(sidebar->filament_panel()); - wxGetApp().get_tab(preset_type)->select_preset(preset_name); } // ORCA: Always refresh the selected filament combo so its color swatch (clr_picker) @@ -12212,8 +12212,9 @@ void Plater::load_project(wxString const& filename2, BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": current loading other project, return directly"); return; } - else - m_loading_project = true; + + m_loading_project = true; + ScopeGuard loading_project_sc([this]() { m_loading_project = false; }); // Make sure state restored on any early return m_only_gcode = false; m_exported_file = false; @@ -12307,7 +12308,6 @@ void Plater::load_project(wxString const& filename2, sidebar().set_flushing_volume_warning(has_modify); BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << __LINE__ << " load project done"; - m_loading_project = false; } // BBS: save logic @@ -13113,6 +13113,9 @@ void adjust_settings_for_flowrate_calib(ModelObjectPtrs& objects, bool linear, i _obj->config.set_key_value("top_solid_infill_flow_ratio", new ConfigOptionFloat(1.0f)); _obj->config.set_key_value("infill_direction", new ConfigOptionFloat(45)); _obj->config.set_key_value("solid_infill_direction", new ConfigOptionFloat(135)); + _obj->config.set_key_value("anisotropic_surfaces", new ConfigOptionBool(false)); + _obj->config.set_key_value("center_of_surface_pattern", new ConfigOptionEnum(CenterOfSurfacePattern::Each_Surface)); + _obj->config.set_key_value("separated_infills", new ConfigOptionBool(false)); _obj->config.set_key_value("align_infill_direction_to_model", new ConfigOptionBool(true)); _obj->config.set_key_value("ironing_type", new ConfigOptionEnum(IroningType::NoIroning)); _obj->config.set_key_value("internal_solid_infill_speed", new ConfigOptionFloatsNullable(internal_solid_speeds)); @@ -13923,17 +13926,9 @@ bool Plater::preview_zip_archive(const boost::filesystem::path& archive_path) if (mz_zip_reader_file_stat(&archive, i, &stat)) { if (size != stat.m_uncomp_size) // size must fit continue; - wxString wname = boost::nowide::widen(stat.m_filename); - std::string name = into_u8(wname); + std::string name = Slic3r::decode_archive_entry_path(&archive, stat); fs::path archive_path(name); - std::string extra(1024, 0); - size_t extra_size = mz_zip_reader_get_filename_from_extra(&archive, i, extra.data(), extra.size()); - if (extra_size > 0) { - archive_path = fs::path(extra.substr(0, extra_size)); - name = archive_path.string(); - } - if (archive_path.empty()) continue; if (path != archive_path) @@ -15750,7 +15745,7 @@ int Plater::export_3mf(const boost::filesystem::path& output_path, SaveStrategy std::vector project_presets = preset_bundle.get_current_project_embedded_presets(); StoreParams store_params; - store_params.path = path_u8.c_str(); + store_params.path = path_u8; store_params.model = &p->model; store_params.plate_data_list = plate_data_list; store_params.export_plate_idx = export_plate_idx; diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index af7522c33d..e1501e9c4d 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -797,7 +797,7 @@ wxBoxSizer *PreferencesDialog::create_item_decimal_input(wxString title, wxStrin input->SetToolTip(tooltip); input->GetTextCtrl()->SetValidator(validator); - m_sizer->Add(input, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(5)); + m_sizer->Add(input, 0, wxALIGN_CENTER_VERTICAL); auto apply_value = [this, param, input, min, max, decimals]() { auto value = input->GetTextCtrl()->GetValue(); @@ -1797,6 +1797,17 @@ void PreferencesDialog::create_items() g_sizer = f_sizers.back(); g_sizer->AddGrowableCol(0, 1); + //// GRAPHICS > General + g_sizer->Add(create_item_title(_L("General")), 1, wxEXPAND); + + auto smooth_normals = create_item_checkbox( + _L("Smooth normals"), + _L("Applies smooth normals to the model.\n\nRequires manual scene reload to take effect " + "(right-click on 3D view → \"Reload All\")."), + SETTING_OPENGL_PHONG_SMOOTH_NORMALS + ); + g_sizer->Add(smooth_normals); + //// GRAPHICS > Realistic view g_sizer->Add(create_item_title(_L("Realistic View")), 1, wxEXPAND); @@ -1816,20 +1827,11 @@ void PreferencesDialog::create_items() auto item_realistic_shadows = create_item_checkbox( _L("Shadows"), - _L("Renders cast shadows on the plate in realistic view."), + _L("Renders cast shadows on the plate, other objects, and each object onto itself in realistic view."), SETTING_OPENGL_PHONG_BASIC_PLATE_SHADOWS ); g_sizer->Add(item_realistic_shadows); - - auto item_realistic_smooth_normals = create_item_checkbox( - _L("Smooth normals"), - _L("Applies smooth normals to the realistic view.\n\nRequires manual scene reload to take effect " - "(right-click on 3D view → \"Reload All\")."), - SETTING_OPENGL_PHONG_SMOOTH_NORMALS - ); - g_sizer->Add(item_realistic_smooth_normals); - //// GRAPHICS > Anti-aliasing g_sizer->Add(create_item_title(_L("Anti-aliasing")), 1, wxEXPAND); diff --git a/src/slic3r/GUI/PresetComboBoxes.cpp b/src/slic3r/GUI/PresetComboBoxes.cpp index 6475ae1c88..a6798c077e 100644 --- a/src/slic3r/GUI/PresetComboBoxes.cpp +++ b/src/slic3r/GUI/PresetComboBoxes.cpp @@ -1310,7 +1310,7 @@ void PlaterPresetComboBox::update() selected_in_ams = add_ams_filaments(into_u8(selected_user_preset.empty() ? selected_system_preset : selected_user_preset), true); } - std::vector filament_orders = {"Bambu PLA Basic", "Bambu PLA Matte", "Bambu PETG HF", "Bambu ABS", "Bambu PLA Silk", "Bambu PLA-CF", + std::vector filament_orders = {"Bambu PLA Basic", "Bambu PLA Matte", "Bambu PETG HF", "Bambu ABS", "Bambu PLA Silk", "Bambu PLA-CF", "Bambu PLA Galaxy", "Bambu PLA Metal", "Bambu PLA Marble", "Bambu PETG-CF", "Bambu PETG Translucent", "Bambu ABS-GF"}; std::vector first_vendors = {"", "Bambu", "Generic"}; // Empty vendor for non-system presets std::vector first_types = {"PLA", "PETG", "ABS", "TPU"}; @@ -1600,6 +1600,7 @@ TabPresetComboBox::TabPresetComboBox(wxWindow* parent, Preset::Type preset_type) // BBS: new layout PresetComboBox(parent, preset_type, wxSize(20 * wxGetApp().em_unit(), 30 * wxGetApp().em_unit() / 10)) { + GetDropDown().SetUseContentWidth(true,true); } void TabPresetComboBox::OnSelect(wxCommandEvent &evt) diff --git a/src/slic3r/GUI/SelectMachine.cpp b/src/slic3r/GUI/SelectMachine.cpp index d5ea29046b..ecdb817a24 100644 --- a/src/slic3r/GUI/SelectMachine.cpp +++ b/src/slic3r/GUI/SelectMachine.cpp @@ -138,7 +138,7 @@ SelectMachineDialog::SelectMachineDialog(Plater *plater) /*mode switch*/ /*auto m_sizer_mode_switch = new wxBoxSizer(wxHORIZONTAL); - m_mode_print = new SendModeSwitchButton(scroll_area, _L("Print"), true); + m_mode_print = new SendModeSwitchButton(scroll_area, _CTX("Print", "Verb"), true); m_mode_send = new SendModeSwitchButton(scroll_area,_L("Save to printer"), false); m_sizer_mode_switch->Add(m_mode_print, 0, wxALIGN_CENTER, 0); m_sizer_mode_switch->Add(0, 0, 0, wxLEFT, FromDIP(8)); diff --git a/src/slic3r/GUI/StepMeshDialog.cpp b/src/slic3r/GUI/StepMeshDialog.cpp index 33e1c4914a..cd0f4bd423 100644 --- a/src/slic3r/GUI/StepMeshDialog.cpp +++ b/src/slic3r/GUI/StepMeshDialog.cpp @@ -30,7 +30,7 @@ static int _ITEM_WIDTH() { return _scale(30); } #define SLIDER_SCALE_10(val) ((val) / 0.01) #define SLIDER_UNSCALE_10(val) ((val) * 0.01) #define LEFT_RIGHT_PADING FromDIP(20) -#define FONT_COLOR wxColour("#262E30") +#define FONT_COLOR wxColour("#363636") // label color wxDEFINE_EVENT(wxEVT_THREAD_DONE, wxCommandEvent); diff --git a/src/slic3r/GUI/SyncAmsInfoDialog.cpp b/src/slic3r/GUI/SyncAmsInfoDialog.cpp index 535c561b55..63b13bc7a6 100644 --- a/src/slic3r/GUI/SyncAmsInfoDialog.cpp +++ b/src/slic3r/GUI/SyncAmsInfoDialog.cpp @@ -19,6 +19,7 @@ #include "Widgets/Label.hpp" #include "Widgets/Button.hpp" #include "Widgets/CheckBox.hpp" +#include "Widgets/DialogButtons.hpp" #include "CapsuleButton.hpp" #include "PrePrintChecker.hpp" @@ -37,7 +38,7 @@ using namespace Slic3r::GUI; #define SyncAmsInfoDialogWidth FromDIP(675) #define SyncAmsInfoDialogHeightMIN FromDIP(620) #define SyncAmsInfoDialogHeightMIDDLE FromDIP(630) -#define SyncAmsInfoDialogHeightMAX FromDIP(660) +#define SyncAmsInfoDialogHeightMAX FromDIP(700) #define SyncLabelWidth FromDIP(640) #define SyncAttentionTipWidth FromDIP(550) namespace Slic3r { namespace GUI { @@ -282,14 +283,14 @@ wxBoxSizer *SyncAmsInfoDialog::create_sizer_thumbnail(wxButton *image_button, bo if (left) { wxBoxSizer *text_sizer = new wxBoxSizer(wxHORIZONTAL); auto sync_text = new Label(image_button->GetParent(), _CTX(L_CONTEXT("Original", "Sync_AMS"), "Sync_AMS")); - sync_text->SetForegroundColour(wxColour(107, 107, 107, 100)); + sync_text->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#363636"))); // ORCA match label colors text_sizer->Add(sync_text, 0, wxALIGN_CENTER | wxALL, 0); sizer_thumbnail->Add(sync_text, FromDIP(0), wxALIGN_CENTER | wxALL, FromDIP(4)); } else { wxBoxSizer *text_sizer = new wxBoxSizer(wxHORIZONTAL); m_after_map_text = new Label(image_button->GetParent(), _L("After mapping")); - m_after_map_text->SetForegroundColour(wxColour(107, 107, 107, 100)); + m_after_map_text->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#363636"))); // ORCA match label colors text_sizer->Add(m_after_map_text, 0, wxALIGN_CENTER | wxALL, 0); sizer_thumbnail->Add(m_after_map_text, FromDIP(0), wxALIGN_CENTER | wxALL, FromDIP(4)); } @@ -655,10 +656,6 @@ SyncAmsInfoDialog::SyncAmsInfoDialog(wxWindow *parent, SyncInfo &info) : // font SetFont(wxGetApp().normal_font()); - // icon - std::string icon_path = (boost::format("%1%/images/OrcaSlicerTitle.ico") % resources_dir()).str(); - SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO)); - Freeze(); SetBackgroundColour(m_colour_def_color); @@ -733,7 +730,7 @@ SyncAmsInfoDialog::SyncAmsInfoDialog(wxWindow *parent, SyncInfo &info) : m_colormap_btn->Bind(wxEVT_BUTTON, &SyncAmsInfoDialog::update_when_change_map_mode,this); // update_when_change_map_mode(e.GetSelection()); m_override_btn->Bind(wxEVT_BUTTON, &SyncAmsInfoDialog::update_when_change_map_mode,this); - bSizer->Add(m_mode_combox_sizer, FromDIP(0), wxEXPAND | wxTOP, FromDIP(10)); + bSizer->Add(m_mode_combox_sizer, FromDIP(0), wxEXPAND | wxTOP | wxBOTTOM, FromDIP(10)); } m_basic_panel = new wxPanel(m_scrolledWindow, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL); @@ -847,8 +844,8 @@ SyncAmsInfoDialog::SyncAmsInfoDialog(wxWindow *parent, SyncInfo &info) : sizer_advanced_options_title = new wxBoxSizer(wxHORIZONTAL); auto advanced_options_title = new Label(m_scrolledWindow, _L("Advanced Options")); - advanced_options_title->SetFont(::Label::Body_13); - advanced_options_title->SetForegroundColour(wxColour(38, 46, 48)); + advanced_options_title->SetFont(::Label::Head_14); // ORCA + advanced_options_title->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#363636"))); // ORCA match label colors sizer_advanced_options_title->Add(0, 0, 1, wxEXPAND, 0); sizer_advanced_options_title->Add(advanced_options_title, 0, wxALIGN_CENTER, 0); @@ -914,13 +911,15 @@ SyncAmsInfoDialog::SyncAmsInfoDialog(wxWindow *parent, SyncInfo &info) : {//new content//tip confirm ok button wxBoxSizer *tip_sizer = new wxBoxSizer(wxHORIZONTAL); m_attention_text = new wxStaticText(m_scrolledWindow, wxID_ANY, _L("Tip") + ": "); + m_attention_text->SetFont(::Label::Head_14); + m_attention_text->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#009688"))); // ORCA match label colors tip_sizer->Add(m_attention_text, 0, wxALIGN_LEFT | wxTOP, FromDIP(2)); m_tip_attention_color_map = _L("Only synchronize filament type and color, not including AMS slot information."); m_tip_attention_override = _L("Replace the project filaments list sequentially based on printer filaments. And unused printer filaments will be automatically added to the end of the list."); m_tip_text = new Label(m_scrolledWindow, m_tip_attention_color_map, LB_AUTO_WRAP); m_tip_text->SetMinSize(wxSize(SyncAttentionTipWidth, -1)); m_tip_text->SetMaxSize(wxSize(SyncAttentionTipWidth, -1)); - m_tip_text->SetForegroundColour(wxColour(107, 107, 107, 100)); + m_tip_text->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#363636"))); // ORCA match label colors tip_sizer->Add(m_tip_text, 0, wxALIGN_LEFT | wxTOP, FromDIP(2)); tip_sizer->AddSpacer(FromDIP(20)); bSizer->Add(tip_sizer, 0, wxEXPAND | wxLEFT, FromDIP(25)); @@ -931,7 +930,8 @@ SyncAmsInfoDialog::SyncAmsInfoDialog(wxWindow *parent, SyncInfo &info) : m_advace_setting_sizer = new wxBoxSizer(wxHORIZONTAL); m_more_setting_tips = new wxStaticText(m_scrolledWindow, wxID_ANY, _L("Advanced settings")); - m_more_setting_tips->SetForegroundColour(wxColour(0, 137, 123)); + m_more_setting_tips->SetFont(::Label::Head_14); // ORCA + m_more_setting_tips->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#363636"))); // ORCA match label colors m_more_setting_tips->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent &e) { m_expand_more_settings = !m_expand_more_settings; update_more_setting(true,true); @@ -959,6 +959,7 @@ SyncAmsInfoDialog::SyncAmsInfoDialog(wxWindow *parent, SyncInfo &info) : m_append_color_sizer->Add(m_append_color_checkbox, 0, wxALIGN_LEFT | wxTOP, FromDIP(4)); const int gap_between_checebox_and_text = 2; m_append_color_text = new Label(m_scrolledWindow, _L("Add unused AMS filaments to filaments list.")); + m_append_color_text->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#363636"))); // ORCA match label colors m_append_color_text->Hide(); m_append_color_sizer->AddSpacer(FromDIP(gap_between_checebox_and_text)); m_append_color_sizer->Add(m_append_color_text, 0, wxALIGN_LEFT | wxTOP, FromDIP(4)); @@ -981,6 +982,7 @@ SyncAmsInfoDialog::SyncAmsInfoDialog(wxWindow *parent, SyncInfo &info) : m_merge_color_text = new Label(m_scrolledWindow, _L("Automatically merge the same colors in the model after mapping.")); + m_merge_color_text->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#363636"))); // ORCA match label colors m_merge_color_text->Hide(); m_merge_color_sizer->AddSpacer(FromDIP(gap_between_checebox_and_text)); m_merge_color_sizer->Add(m_merge_color_text, 0, wxALIGN_LEFT | wxTOP, FromDIP(2)); @@ -994,17 +996,19 @@ SyncAmsInfoDialog::SyncAmsInfoDialog(wxWindow *parent, SyncInfo &info) : m_override_undone_str = _L("After being synced, this action cannot be undone."); m_undone_str = _L("After being synced, the project's filament presets and colors will be replaced with the mapped filament types and colors. This action cannot be undone."); m_confirm_title = new Label(m_scrolledWindow, m_undone_str, LB_AUTO_WRAP); + m_confirm_title->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#363636"))); // ORCA match label colors m_confirm_title->SetMinSize(wxSize(SyncLabelWidth, -1)); m_confirm_title->SetMaxSize(wxSize(SyncLabelWidth, -1)); - confirm_boxsizer->Add(m_confirm_title, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxTOP | wxRIGHT, FromDIP(10)); + confirm_boxsizer->Add(m_confirm_title, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxTOP | wxRIGHT | wxBOTTOM, FromDIP(10)); m_are_you_sure_title = new wxStaticText(m_scrolledWindow, wxID_ANY, _L("Are you sure to synchronize the filaments?")); + m_are_you_sure_title->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#363636"))); // ORCA match label colors //m_are_you_sure_title->SetFont(Label::Head_14); confirm_boxsizer->Add(m_are_you_sure_title, 0, wxALIGN_LEFT | wxTOP, FromDIP(0)); bSizer->Add(confirm_boxsizer, 0, wxALIGN_LEFT | wxLEFT , FromDIP(25)); wxBoxSizer *warning_sizer = new wxBoxSizer(wxHORIZONTAL); m_warning_text = new wxStaticText(m_scrolledWindow, wxID_ANY, _L("Error") + ":"); - m_warning_text->SetForegroundColour(wxColour(107, 107, 107, 100)); + m_warning_text->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#363636"))); // ORCA match label colors m_warning_text->Hide(); warning_sizer->Add(m_warning_text, 0, wxALIGN_CENTER | wxTOP, FromDIP(2)); bSizer->Add(warning_sizer, 0, wxEXPAND | wxLEFT, FromDIP(25)); @@ -1012,46 +1016,22 @@ SyncAmsInfoDialog::SyncAmsInfoDialog(wxWindow *parent, SyncInfo &info) : m_scrolledWindow->SetSizerAndFit(m_sizer_main); m_sizer_show_page->Add(m_scrolledWindow, 1, wxEXPAND, 0); - wxBoxSizer *bSizer_button = new wxBoxSizer(wxHORIZONTAL); - bSizer_button->SetMinSize(wxSize(FromDIP(100), -1)); - /* m_checkbox = new wxCheckBox(this, wxID_ANY, _L("Don't show again"), wxDefaultPosition, wxDefaultSize, 0); - bSizer_button->Add(m_checkbox, 0, wxALIGN_LEFT);*/ - bSizer_button->AddStretchSpacer(1); - StateColor btn_bg_green(std::pair(wxColour(0, 137, 123), StateColor::Pressed), std::pair(wxColour(38, 166, 154), StateColor::Hovered), - std::pair(AMS_CONTROL_BRAND_COLOUR, StateColor::Normal)); - m_button_ok = new Button(m_show_page, _L("Synchronize now")); - m_button_ok->SetBackgroundColor(btn_bg_green); - m_button_ok->SetBorderColor(*wxWHITE); - m_button_ok->SetTextColor(wxColour("#FFFFFE")); - m_button_ok->SetFont(Label::Body_12); - m_button_ok->SetSize(OK_BUTTON_SIZE); - m_button_ok->SetMinSize(OK_BUTTON_SIZE); - m_button_ok->SetCornerRadius(FromDIP(12)); - bSizer_button->Add(m_button_ok, 0, wxALIGN_RIGHT | wxLEFT | wxTOP, FromDIP(10)); - + auto* dlg_btns = new DialogButtons(m_show_page, {"OK", "Cancel"}); + m_button_ok = dlg_btns->GetOK(); + m_button_ok->SetLabel(_L("Synchronize now")); m_button_ok->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this](wxCommandEvent &e) { deal_ok(); EndModal(wxID_YES); SetFocusIgnoringChildren(); }); - StateColor btn_bg_white(std::pair(wxColour(206, 206, 206), StateColor::Pressed), std::pair(wxColour(238, 238, 238), StateColor::Hovered), - std::pair(*wxWHITE, StateColor::Normal)); - - m_button_cancel = new Button(m_show_page, m_input_info.cancel_text_to_later ? _L("Later") : _L("Cancel")); - m_button_cancel->SetBackgroundColor(btn_bg_white); - m_button_cancel->SetBorderColor(wxColour(38, 46, 48)); - m_button_cancel->SetFont(Label::Body_12); - m_button_cancel->SetSize(CANCEL_BUTTON_SIZE); - m_button_cancel->SetMinSize(CANCEL_BUTTON_SIZE); - m_button_cancel->SetCornerRadius(FromDIP(12)); - bSizer_button->Add(m_button_cancel, 0, wxALIGN_RIGHT | wxLEFT | wxTOP, FromDIP(10)); - + m_button_cancel = dlg_btns->GetCANCEL(); + m_button_cancel->SetLabel(m_input_info.cancel_text_to_later ? _L("Later") : _L("Cancel")); m_button_cancel->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this](wxCommandEvent &e) { EndModal(wxID_CANCEL); }); - m_sizer_show_page->Add(bSizer_button, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, FromDIP(20)); + m_sizer_show_page->Add(dlg_btns, 0, wxEXPAND); m_show_page->SetSizer(m_sizer_show_page); } show_print_failed_info(false); @@ -2480,10 +2460,10 @@ void SyncAmsInfoDialog::on_dpi_changed(const wxRect &suggested_rect) } m_swipe_left_button->msw_rescale(); m_swipe_right_button->msw_rescale(); - m_button_ok->SetMinSize(OK_BUTTON_SIZE); - m_button_ok->SetCornerRadius(FromDIP(12)); - m_button_cancel->SetMinSize(CANCEL_BUTTON_SIZE); - m_button_cancel->SetCornerRadius(FromDIP(12)); + //m_button_ok->SetMinSize(OK_BUTTON_SIZE); // ORCA DialogButtons automatically manages style and size + //m_button_ok->SetCornerRadius(FromDIP(12)); + //m_button_cancel->SetMinSize(CANCEL_BUTTON_SIZE); + //m_button_cancel->SetCornerRadius(FromDIP(12)); m_merge_color_checkbox->Rescale(); m_append_color_checkbox->Rescale(); m_combobox_plate->Rescale(); @@ -2628,14 +2608,14 @@ void SyncAmsInfoDialog::reset_and_sync_ams_list() is_first_row = false; if (!m_original_in_colormap) { m_original_in_colormap = new wxStaticText(m_filament_panel, wxID_ANY, _CTX(L_CONTEXT("Original", "Sync_AMS"), "Sync_AMS") + ":"); - m_original_in_colormap->SetForegroundColour(wxColour(107, 107, 107, 100)); + m_original_in_colormap->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#363636"))); // ORCA match label colors m_original_in_colormap->SetFont(::Label::Head_12); } ams_tip_sizer->Add(m_original_in_colormap, 0, wxALIGN_LEFT | wxTOP, FromDIP(6)); if (!m_ams_or_ext_text_in_colormap) { m_ams_or_ext_text_in_colormap = new wxStaticText(m_filament_panel, wxID_ANY, _L("AMS") + ":"); - m_ams_or_ext_text_in_colormap->SetForegroundColour(wxColour(107, 107, 107, 100)); + m_ams_or_ext_text_in_colormap->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#363636"))); // ORCA match label colors m_ams_or_ext_text_in_colormap->SetFont(::Label::Head_12); } ams_tip_sizer->Add(m_ams_or_ext_text_in_colormap, 0, wxALIGN_LEFT | wxTOP, FromDIP(9)); @@ -2840,7 +2820,7 @@ void SyncAmsInfoDialog::generate_override_fix_ams_list() is_first_row = false; if (!m_original_in_override) { m_original_in_override = new wxStaticText(m_fix_filament_panel, wxID_ANY, _CTX(L_CONTEXT("Original", "Sync_AMS"), "Sync_AMS") + ":"); - m_original_in_override->SetForegroundColour(wxColour(107, 107, 107, 100)); + m_original_in_override->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#363636"))); // ORCA match label colors m_original_in_override->SetFont(::Label::Head_12); } ams_tip_sizer->Add(m_original_in_override, 0, wxALIGN_LEFT | wxTOP, FromDIP(6)); @@ -2848,7 +2828,7 @@ void SyncAmsInfoDialog::generate_override_fix_ams_list() if (!m_ams_or_ext_text_in_override) { auto text = (m_only_exist_ext_spool_flag ? _L("Ext spool") : _L("AMS")) + ":"; m_ams_or_ext_text_in_override = new wxStaticText(m_fix_filament_panel, wxID_ANY, text); - m_ams_or_ext_text_in_override->SetForegroundColour(wxColour(107, 107, 107, 100)); + m_ams_or_ext_text_in_override->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#363636"))); // ORCA match label colors m_ams_or_ext_text_in_override->SetFont(::Label::Head_12); } ams_tip_sizer->Add(m_ams_or_ext_text_in_override, 0, wxALIGN_LEFT | wxTOP, FromDIP(9)); @@ -3236,10 +3216,12 @@ SyncNozzleAndAmsDialog::SyncNozzleAndAmsDialog(InputInfo &input_info) wxGetApp().preset_bundle->get_printer_extruder_count() == 1 ? 370 :320, input_info.dialog_pos, 90, + ( wxGetApp().preset_bundle->get_printer_extruder_count() == 1 ? _L("Successfully synchronized nozzle information.") : - _L("Successfully synchronized nozzle and AMS number information."), - _L("Continue to sync filaments"), - _CTX(L_CONTEXT("Cancel", "Sync_Nozzle_AMS"), "Sync_Nozzle_AMS"), + _L("Successfully synchronized nozzle and AMS number information.") + ) + "\n\n" + _L("Do you want to continue to sync filaments?"), + _L("Yes"), // ORCA use shorter text for buttons + _CTX(L_CONTEXT(_L("No"), "Sync_Nozzle_AMS"), "Sync_Nozzle_AMS"), DisappearanceMode::TimedDisappearance) , m_input_info(input_info) { diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 52537d9331..a0697b8784 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1184,7 +1184,7 @@ void Tab::update_extruder_switch_colors() void Tab::check_extruder_options_status(int index, bool &sys_extruder, bool &modified_extruder, const std::vector& pages_to_check) { int config_index = index; - if (m_type == Preset::TYPE_PRINT || m_type == Preset::TYPE_PRINTER) { + if (m_type == Preset::TYPE_PRINT || m_type == Preset::TYPE_PRINTER || m_type == Preset::TYPE_MODEL) { int extruder_id; NozzleVolumeType nozzle_type; parse_extruder_selection(index, extruder_id, nozzle_type); @@ -2658,7 +2658,7 @@ void TabPrint::build() optgroup->append_single_option_line("ironing_angle", "quality_settings_ironing#angle-offset"); optgroup->append_single_option_line("ironing_angle_fixed", "quality_settings_ironing#fixed-angle"); - optgroup = page->new_optgroup(L("Z contouring"), L"param_advanced"); + optgroup = page->new_optgroup(L("Z contouring"), L"param_z_contouring"); optgroup->append_single_option_line("zaa_enabled", "quality_settings_z_contouring"); optgroup->append_single_option_line("zaa_minimize_perimeter_height", "quality_settings_z_contouring#minimize-wall-height-angle"); optgroup->append_single_option_line("zaa_min_z", "quality_settings_z_contouring#minimum-z-height"); @@ -2742,12 +2742,17 @@ void TabPrint::build() optgroup->append_single_option_line("top_shell_thickness", "strength_settings_top_bottom_shells#shell-thickness"); optgroup->append_single_option_line("top_surface_density", "strength_settings_top_bottom_shells#surface-density"); optgroup->append_single_option_line("top_surface_pattern", "strength_settings_top_bottom_shells#surface-pattern"); - optgroup->append_single_option_line("top_layer_direction", "strength_settings_infill#top-direction"); + optgroup->append_single_option_line("top_layer_direction", "strength_settings_infill#top-bottom-direction"); + optgroup->append_single_option_line("top_surface_expansion", "strength_settings_top_bottom_shells#surface-expansion"); + optgroup->append_single_option_line("top_surface_expansion_margin", "strength_settings_top_bottom_shells#surface-expansion-margin"); + optgroup->append_single_option_line("top_surface_expansion_direction", "strength_settings_top_bottom_shells#surface-expansion-direction"); optgroup->append_single_option_line("bottom_shell_layers", "strength_settings_top_bottom_shells#shell-layers"); optgroup->append_single_option_line("bottom_shell_thickness", "strength_settings_top_bottom_shells#shell-thickness"); optgroup->append_single_option_line("bottom_surface_density", "strength_settings_top_bottom_shells#surface-density"); optgroup->append_single_option_line("bottom_surface_pattern", "strength_settings_top_bottom_shells#surface-pattern"); - optgroup->append_single_option_line("bottom_layer_direction", "strength_settings_infill#direction"); + optgroup->append_single_option_line("bottom_layer_direction", "strength_settings_infill#top-bottom-direction"); + optgroup->append_single_option_line("center_of_surface_pattern", "strength_settings_top_bottom_shells#center-surface-pattern-on"); + optgroup->append_single_option_line("anisotropic_surfaces", "strength_settings_top_bottom_shells#anisotropic-surfaces"); optgroup->append_single_option_line("top_bottom_infill_wall_overlap", "strength_settings_top_bottom_shells#infillwall-overlap"); optgroup = page->new_optgroup(L("Infill"), L"param_infill"); @@ -2778,10 +2783,11 @@ void TabPrint::build() optgroup->append_single_option_line("solid_infill_rotate_template", "strength_settings_infill_rotation_template_metalanguage"); optgroup->append_single_option_line("gap_fill_target", "strength_settings_infill#apply-gap-fill"); optgroup->append_single_option_line("filter_out_gap_fill", "strength_settings_infill#filter-out-tiny-gaps"); + optgroup->append_single_option_line("separated_infills", "strength_settings_infill#separated-infills"); optgroup->append_single_option_line("infill_wall_overlap", "strength_settings_infill#infill-wall-overlap"); optgroup = page->new_optgroup(L("Advanced"), L"param_advanced"); - optgroup->append_single_option_line("align_infill_direction_to_model", "strength_settings_advanced#align-infill-direction-to-model"); + optgroup->append_single_option_line("align_infill_direction_to_model", "strength_settings_advanced#align-directions-to-model"); optgroup->append_single_option_line("extra_solid_infills", "strength_settings_infill#extra-solid-infill"); optgroup->append_single_option_line("bridge_angle", "strength_settings_advanced#bridge-infill-direction"); optgroup->append_single_option_line("internal_bridge_angle", "strength_settings_advanced#bridge-infill-direction"); // ORCA: Internal bridge angle override @@ -2976,6 +2982,7 @@ void TabPrint::build() optgroup->append_single_option_line("flush_into_support", "multimaterial_settings_flush_options#flush-into-objects-support"); optgroup = page->new_optgroup(L("Advanced"), L"advanced"); optgroup->append_single_option_line("interlocking_beam", "multimaterial_settings_advanced#interlocking-beam"); + optgroup->append_single_option_line("toolchange_ordering", "multimaterial_settings_advanced#toolchange-ordering"); optgroup->append_single_option_line("interface_shells", "multimaterial_settings_advanced#interface-shells"); optgroup->append_single_option_line("mmu_segmented_region_max_width", "multimaterial_settings_advanced#maximum-width-of-segmented-region"); optgroup->append_single_option_line("mmu_segmented_region_interlocking_depth", "multimaterial_settings_advanced#interlocking-depth-of-segmented-region"); @@ -7677,7 +7684,7 @@ bool Tab::validate_filament_temperature_pairs() RichMessageDialog dialog(parent(), msg_text, _L("Temperature Safety Check"), wxYES | wxNO | wxICON_WARNING); dialog.SetButtonLabel(wxID_YES, _L("Continue"), true); - dialog.SetButtonLabel(wxID_NO, _L("Back")); + dialog.SetButtonLabel(wxID_NO, _CTX("Back", "Navigation")); dialog.ShowCheckBox(_L("Don't warn again for this preset")); const int answer = dialog.ShowModal(); // Session-only suppression (does not modify/save filament preset data). @@ -7713,6 +7720,11 @@ void Tab::update_extruder_variants(int extruder_id, bool reload) auto nozzle_volumes = m_preset_bundle->project_config.option("nozzle_volume_type"); int extruder_nums = m_preset_bundle->get_printer_extruder_count(); nozzle_volumes->values.resize(extruder_nums); + + // Orca: update `m_actual_nozzle_volumes` to current selected ones + m_actual_nozzle_volumes.resize(extruder_nums, NozzleVolumeType::nvtStandard); + for (int i = 0; i < extruder_nums; i++) m_actual_nozzle_volumes[i] = (NozzleVolumeType)nozzle_volumes->values[i]; + if (extruder_nums == 2) { auto options = generate_extruder_options(); m_extruder_switch->SetOptions(options); diff --git a/src/slic3r/GUI/WebViewDialog.cpp b/src/slic3r/GUI/WebViewDialog.cpp index 20ed70e799..d10eaedef5 100644 --- a/src/slic3r/GUI/WebViewDialog.cpp +++ b/src/slic3r/GUI/WebViewDialog.cpp @@ -47,7 +47,7 @@ WebViewPanel::WebViewPanel(wxWindow *parent) // Create the button bSizer_toolbar = new wxBoxSizer(wxHORIZONTAL); - m_button_back = new wxButton(this, wxID_ANY, _L("Back"), wxDefaultPosition, wxDefaultSize, 0); + m_button_back = new wxButton(this, wxID_ANY, _CTX("Back", "Navigation"), wxDefaultPosition, wxDefaultSize, 0); m_button_back->Enable(false); bSizer_toolbar->Add(m_button_back, 0, wxALL, 5); diff --git a/src/slic3r/GUI/calib_dlg.cpp b/src/slic3r/GUI/calib_dlg.cpp index 8cf33c3851..0a18e2d448 100644 --- a/src/slic3r/GUI/calib_dlg.cpp +++ b/src/slic3r/GUI/calib_dlg.cpp @@ -1471,12 +1471,24 @@ FlowRateCalibrationDialog::FlowRateCalibrationDialog(wxWindow* parent, wxWindowI type_box->Add(m_rbType, 0, wxALL | wxEXPAND, FromDIP(4)); v_sizer->Add(type_box, 0, wxTOP | wxRIGHT | wxLEFT | wxEXPAND, FromDIP(10)); - // Pattern selection - auto labeled_box_pattern = new LabeledStaticBox(this, _L("Top Surface Pattern")); - auto pattern_box = new wxStaticBoxSizer(labeled_box_pattern, wxVERTICAL); + // Settings + auto stb = new LabeledStaticBox(this, _L("Settings")); + auto settings_sizer = new wxStaticBoxSizer(stb, wxVERTICAL); + + wxString pattern_str = _L("Top Surface Pattern"); + int text_max = GetTextMax(this, std::vector{pattern_str}); + + settings_sizer->AddSpacer(FromDIP(5)); + + auto st_size = wxSize(text_max, -1); + auto ti_size = FromDIP(wxSize(120, -1)); + + // Top surface pattern + auto pattern_sizer = new wxBoxSizer(wxHORIZONTAL); + auto pattern_text = new wxStaticText(this, wxID_ANY, pattern_str, wxDefaultPosition, st_size, wxALIGN_LEFT); // ORCA: Use ComboBox with icons instead of RadioGroup - m_rbPattern = new ComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, nullptr, wxCB_READONLY); + m_rbPattern = new ComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, ti_size, 0, nullptr, wxCB_READONLY); boost::filesystem::path image_path(Slic3r::resources_dir()); image_path /= "images"; @@ -1497,9 +1509,13 @@ FlowRateCalibrationDialog::FlowRateCalibrationDialog(wxWindow* parent, wxWindowI m_rbPattern->SetSelection(0); // Default to Archimedean Chords // ORCA: explicit set value to ensure display on Windows m_rbPattern->SetValue(m_rbPattern->GetString(0)); + m_rbPattern->GetDropDown().SetUseContentWidth(true); - pattern_box->Add(m_rbPattern, 0, wxALL | wxEXPAND, FromDIP(4)); - v_sizer->Add(pattern_box, 0, wxTOP | wxRIGHT | wxLEFT | wxEXPAND, FromDIP(10)); + pattern_sizer->Add(pattern_text, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2)); + pattern_sizer->Add(m_rbPattern , 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2)); + settings_sizer->Add(pattern_sizer, 0, wxLEFT, FromDIP(3)); + + v_sizer->Add(settings_sizer, 0, wxTOP | wxRIGHT | wxLEFT | wxEXPAND, FromDIP(10)); v_sizer->AddSpacer(FromDIP(5)); diff --git a/src/slic3r/Utils/CalibUtils.cpp b/src/slic3r/Utils/CalibUtils.cpp index 29d302c776..8e7de91318 100644 --- a/src/slic3r/Utils/CalibUtils.cpp +++ b/src/slic3r/Utils/CalibUtils.cpp @@ -7,6 +7,7 @@ #include "../GUI/PartPlate.hpp" #include "libslic3r/CutUtils.hpp" #include "libslic3r/ClipperUtils.hpp" +#include "libslic3r/Utils.hpp" #include "libslic3r/Model.hpp" #include "slic3r/GUI/Jobs/BoostThreadWorker.hpp" @@ -27,11 +28,19 @@ const double MIN_PA_K_VALUE = 0.0; const double MAX_PA_K_VALUE = 2.0; std::unique_ptr CalibUtils::print_worker; -wxString wxstr_temp_dir = fs::path(fs::temp_directory_path() / "calib").wstring(); -static const std::string temp_dir = wxstr_temp_dir.utf8_string(); -static const std::string temp_gcode_path = temp_dir + "/temp.gcode"; -static const std::string path = temp_dir + "/test.3mf"; -static const std::string config_3mf_path = temp_dir + "/test_config.3mf"; + +// Built lazily so temporary_dir() is read on first use, after set_temporary_dir() +// has run at startup (it isolates the temp root per user to avoid cross-user collisions). +static const std::string& calib_temp_dir() +{ + static const std::string dir = temporary_dir() + "/calib"; + return dir; +} +static std::string calib_temp_file(const std::string& name) { return calib_temp_dir() + "/" + name; } + +static const std::string gcode_filename = "temp.gcode"; +static const std::string model_filename = "test.3mf"; +static const std::string config_filename = "test_config.3mf"; static std::string MachineBedTypeString[7] = { "auto", @@ -1599,7 +1608,7 @@ bool CalibUtils::process_and_store_3mf(Model *model, const DynamicPrintConfig &f part_plate->update_slice_result_valid_state(true); gcode_result->reset(); - fff_print->export_gcode(temp_gcode_path, gcode_result, nullptr); + fff_print->export_gcode(calib_temp_file(gcode_filename), gcode_result, nullptr); std::vector thumbnails; PlateDataPtrs plate_data_list; @@ -1618,7 +1627,7 @@ bool CalibUtils::process_and_store_3mf(Model *model, const DynamicPrintConfig &f } for (auto plate_data : plate_data_list) { - plate_data->gcode_file = temp_gcode_path; + plate_data->gcode_file = calib_temp_file(gcode_filename); plate_data->is_sliced_valid = true; plate_data->printer_model_id = obj_->printer_type; FilamentInfo& filament_info = plate_data->slice_filaments_info.front(); @@ -1681,7 +1690,7 @@ bool CalibUtils::process_and_store_3mf(Model *model, const DynamicPrintConfig &f } StoreParams store_params; - store_params.path = path.c_str(); + store_params.path = calib_temp_file(model_filename); store_params.model = model; store_params.plate_data_list = plate_data_list; store_params.config = &new_print_config; @@ -1695,7 +1704,7 @@ bool CalibUtils::process_and_store_3mf(Model *model, const DynamicPrintConfig &f bool success = Slic3r::store_bbs_3mf(store_params); store_params.strategy = SaveStrategy::Silence | SaveStrategy::SplitModel | SaveStrategy::WithSliceInfo | SaveStrategy::SkipAuxiliary; - store_params.path = config_3mf_path.c_str(); + store_params.path = calib_temp_file(config_filename); success = Slic3r::store_bbs_3mf(store_params); release_PlateData_list(plate_data_list); @@ -1784,9 +1793,9 @@ void CalibUtils::send_to_print(const CalibInfo &calib_info, wxString &error_mess PrintPrepareData job_data; job_data.is_from_plater = false; job_data.plate_idx = 0; - job_data._3mf_config_path = config_3mf_path; - job_data._3mf_path = path; - job_data._temp_path = temp_dir; + job_data._3mf_config_path = calib_temp_file(config_filename); + job_data._3mf_path = calib_temp_file(model_filename); + job_data._temp_path = calib_temp_dir(); PlateListData plate_data; plate_data.is_valid = true; @@ -1889,9 +1898,9 @@ void CalibUtils::send_to_print(const std::vector &calib_infos, wxStri PrintPrepareData job_data; job_data.is_from_plater = false; job_data.plate_idx = 0; - job_data._3mf_config_path = config_3mf_path; - job_data._3mf_path = path; - job_data._temp_path = temp_dir; + job_data._3mf_config_path = calib_temp_file(config_filename); + job_data._3mf_path = calib_temp_file(model_filename); + job_data._temp_path = calib_temp_dir(); PlateListData plate_data; plate_data.is_valid = true; diff --git a/tests/fff_print/test_multifilament.cpp b/tests/fff_print/test_multifilament.cpp index 12c1cae766..f33a8e1e61 100644 --- a/tests/fff_print/test_multifilament.cpp +++ b/tests/fff_print/test_multifilament.cpp @@ -85,3 +85,22 @@ TEST_CASE("Per-object wall filament override is honored", "[MultiFilament]") CHECK(tools_for_role(gcode, "perimeter") == std::set{ 0, 1 }); CHECK(tools_for_role(gcode, "infill") == std::set{ 0 }); // infill not overridden: stays on F1 } + +// max_layer_height can be shorter than the extruder count (normalization sizes it to the +// filament count under single_extruder_multi_material). calc_max_layer_height() in ToolOrdering +// indexed it per-nozzle and read past the end. Shortened directly here to isolate that read; +// the other per-extruder keys stay extruder-length so slicing reaches the code under test. +TEST_CASE("Multi-extruder slice stays in bounds with a short max_layer_height", "[MultiFilament]") +{ + DynamicPrintConfig config = multifilament_config(2); + config.set_deserialize_strict({ + { "nozzle_diameter", "0.4,0.4" }, + { "printer_extruder_id", "1,2" }, + { "printer_extruder_variant", "Direct Drive Standard,Direct Drive Standard" }, + { "extruder_printable_height", "0,0" }, + { "max_layer_height", "0.3" }, // deliberately one entry short + }); + Print print; + init_and_process_print({ cube(20) }, print, config); + REQUIRE_FALSE(print.objects().front()->layers().empty()); +} diff --git a/tests/fff_print/test_support_material.cpp b/tests/fff_print/test_support_material.cpp index 24c0e9cdc5..f854939c8c 100644 --- a/tests/fff_print/test_support_material.cpp +++ b/tests/fff_print/test_support_material.cpp @@ -93,3 +93,14 @@ SCENARIO("Support layer Z honors contact distance", "[SupportMaterial]") } } } + +// extrude_support once held a `static` lambda capturing `this`, so a second export in the +// same process dereferenced a returned stack frame (ASan: stack-use-after-return). +TEST_CASE("Support G-code emission survives a second slice in the same process", "[SupportMaterial][Regression]") +{ + const std::string first = slice({ TestMesh::overhang }, { { "enable_support", 1 } }); + REQUIRE(! layers_with_role(first, "support").empty()); + + const std::string second = slice({ TestMesh::overhang }, { { "enable_support", 1 } }); + REQUIRE(! layers_with_role(second, "support").empty()); +} diff --git a/tests/libslic3r/test_arachne_walls.cpp b/tests/libslic3r/test_arachne_walls.cpp index 2d8ee3bc03..4ca18400af 100644 --- a/tests/libslic3r/test_arachne_walls.cpp +++ b/tests/libslic3r/test_arachne_walls.cpp @@ -18,6 +18,7 @@ #include #include "libslic3r/Arachne/WallToolPaths.hpp" +#include "libslic3r/Arachne/SkeletalTrapezoidation.hpp" #include "libslic3r/Arachne/utils/ExtrusionLine.hpp" #include "libslic3r/Arachne/BeadingStrategy/BeadingStrategyFactory.hpp" #include "libslic3r/Arachne/BeadingStrategy/BeadingStrategy.hpp" @@ -265,3 +266,46 @@ TEST_CASE("Arachne widening keeps two beads in transition band (#14376)", "[Arac for (const coord_t w : beading.bead_widths) CHECK(w <= inner_width); } + +namespace { +// Exposes the protected static interpolate() for a focused unit test. +struct InterpolateProbe : SkeletalTrapezoidation { + using SkeletalTrapezoidation::interpolate; +}; +} // anonymous namespace + +// interpolate() indexes the merged beading with an index derived from `left`. The merged beading +// follows the thicker of left/right, so when the thicker side has fewer insets the index runs past +// its end. +TEST_CASE("Beading interpolation tolerates a thicker side with fewer insets", "[Arachne][Regression]") { + using Beading = BeadingStrategy::Beading; + + // Thicker side (right) has fewer insets, so the merged beading holds only 2 toolpath locations. + const coord_t w = scaled(0.42); + Beading left; + left.total_thickness = scaled(1.0); + left.bead_widths = { w, w, w, w }; + left.toolpath_locations = { scaled(0.1), scaled(0.3), scaled(0.5), scaled(0.7) }; + left.left_over = 0; + + Beading right; + right.total_thickness = scaled(2.0); + right.bead_widths = { w, w }; + right.toolpath_locations = { scaled(0.1), scaled(0.3) }; + right.left_over = 0; + + // Just past left's location [2] (0.5), so the derived index is 2, past the end of the 2-inset merged beading. + const coord_t switching_radius = scaled(0.6); + + Beading result; + REQUIRE_NOTHROW(result = InterpolateProbe::interpolate(left, 0.5, right, switching_radius)); + + // With the guard the adjustment is skipped, so the result is the plain interpolation. + const Beading expected = InterpolateProbe::interpolate(left, 0.5, right); + REQUIRE(result.toolpath_locations.size() == expected.toolpath_locations.size()); + REQUIRE(result.bead_widths.size() == expected.bead_widths.size()); + for (size_t i = 0; i < expected.toolpath_locations.size(); ++i) { + CHECK(result.toolpath_locations[i] == expected.toolpath_locations[i]); + CHECK(result.bead_widths[i] == expected.bead_widths[i]); + } +} diff --git a/tests/libslic3r/test_config.cpp b/tests/libslic3r/test_config.cpp index 8e6915e98f..2f16abc4f7 100644 --- a/tests/libslic3r/test_config.cpp +++ b/tests/libslic3r/test_config.cpp @@ -401,3 +401,212 @@ SCENARIO("update_diff_values_to_child_config tolerates legacy machine-limit vect // } // } // } + +SCENARIO("ConfigOptionVector::set_to_index with stride=1 copies values correctly", "[Config][set_to_index]") { + GIVEN("A destination vector and a source vector with 3 values") { + Slic3r::ConfigOptionFloats dest({0.0}); + Slic3r::ConfigOptionFloats src({10.0, 20.0, 30.0}); + std::vector variant_index = {0, 1, 2}; + int stride = 1; + + WHEN("set_to_index is called with stride=1") { + dest.set_to_index(&src, variant_index, stride); + + THEN("The destination contains the source values") { + REQUIRE(dest.values.size() == 3); + REQUIRE(dest.values[0] == 10.0); + REQUIRE(dest.values[1] == 20.0); + REQUIRE(dest.values[2] == 30.0); + } + } + } + + GIVEN("A destination vector and a source vector with subset mapping") { + Slic3r::ConfigOptionFloats dest({0.0}); + Slic3r::ConfigOptionFloats src({100.0, 200.0, 300.0}); + std::vector variant_index = {1, 2}; + int stride = 1; + + WHEN("set_to_index maps only indices 1 and 2") { + dest.set_to_index(&src, variant_index, stride); + + THEN("Only the mapped values are copied, default fills the others") { + REQUIRE(dest.values.size() == 2); + REQUIRE(dest.values[0] == 200.0); + REQUIRE(dest.values[1] == 300.0); + } + } + } +} + +SCENARIO("ConfigOptionVector::set_to_index with stride=2 copies grouped values correctly", "[Config][set_to_index]") { + GIVEN("A destination vector and a source vector with stride=2 (e.g., nozzle groups)") { + // Source has 4 groups of 2 values each: (10,11), (20,21), (30,31), (40,41) + Slic3r::ConfigOptionFloats dest({0.0}); + Slic3r::ConfigOptionFloats src({10.0, 11.0, 20.0, 21.0, 30.0, 31.0, 40.0, 41.0}); + int stride = 2; + + WHEN("set_to_index maps groups 0, 1, 3") { + std::vector variant_index = {0, 1, 3}; + dest.set_to_index(&src, variant_index, stride); + + THEN("The destination has 3 groups (6 values) mapped correctly") { + REQUIRE(dest.values.size() == 6); + // Group 0: (10, 11) + REQUIRE(dest.values[0] == 10.0); + REQUIRE(dest.values[1] == 11.0); + // Group 1: (20, 21) + REQUIRE(dest.values[2] == 20.0); + REQUIRE(dest.values[3] == 21.0); + // Group 3: (40, 41) + REQUIRE(dest.values[4] == 40.0); + REQUIRE(dest.values[5] == 41.0); + } + } + } + + GIVEN("A destination and a single-group source") { + Slic3r::ConfigOptionFloats dest({0.0}); + // Source has 1 group of 2 values + Slic3r::ConfigOptionFloats src({50.0, 60.0}); + int stride = 2; + + WHEN("set_to_index maps group 0 from a single-group source") { + std::vector variant_index = {0}; + dest.set_to_index(&src, variant_index, stride); + + THEN("The destination contains the single group correctly") { + REQUIRE(dest.values.size() == 2); + REQUIRE(dest.values[0] == 50.0); + REQUIRE(dest.values[1] == 60.0); + } + } + } +} + +SCENARIO("ConfigOptionVector::set_to_index handles empty dest_index", "[Config][set_to_index]") { + GIVEN("A destination and source with stride=2") { + Slic3r::ConfigOptionFloats dest({0.0}); + Slic3r::ConfigOptionFloats src({10.0, 11.0, 20.0, 21.0}); + std::vector variant_index = {}; + int stride = 2; + + WHEN("set_to_index is called with an empty index vector") { + dest.set_to_index(&src, variant_index, stride); + + THEN("The destination is resized to 0") { + REQUIRE(dest.values.size() == 0); + } + } + } +} + +SCENARIO("ConfigOptionVector::set_to_index handles nil values in source", "[Config][set_to_index]") { + GIVEN("A source with a nil group (stride=2)") { + Slic3r::ConfigOptionFloatsNullable dest({0.0}); + Slic3r::ConfigOptionFloatsNullable src({10.0, 11.0, + Slic3r::ConfigOptionFloatsNullable::nil_value(), Slic3r::ConfigOptionFloatsNullable::nil_value(), + 30.0, 31.0}); + int stride = 2; + + WHEN("set_to_index maps all groups including the nil one") { + std::vector variant_index = {0, 1, 2}; + dest.set_to_index(&src, variant_index, stride); + + THEN("Non-nil groups are copied and the nil group keeps the default") { + REQUIRE(dest.values.size() == 6); + // Group 0: (10, 11) — copied + REQUIRE(dest.values[0] == 10.0); + REQUIRE(dest.values[1] == 11.0); + // Group 1: nil — keeps default (the front value = 10.0) + REQUIRE(dest.values[2] == 10.0); + REQUIRE(dest.values[3] == 10.0); + // Group 2: (30, 31) — copied + REQUIRE(dest.values[4] == 30.0); + REQUIRE(dest.values[5] == 31.0); + } + } + } +} + +SCENARIO("ConfigOptionVector::set_to_index handles out-of-bounds dest_index", "[Config][set_to_index]") { + GIVEN("A source with only 2 groups (4 values) but dest_index references group 3") { + Slic3r::ConfigOptionFloats dest({0.0}); + Slic3r::ConfigOptionFloats src({10.0, 11.0, 20.0, 21.0}); // 2 groups of stride 2 + int stride = 2; + + WHEN("set_to_index maps group 3 which is out of bounds") { + std::vector variant_index = {0, 3}; // group 3 is out of range + dest.set_to_index(&src, variant_index, stride); + + THEN("Group 0 is copied, group 3 falls back to default without crashing") { + REQUIRE(dest.values.size() == 4); + // Group 0: (10, 11) — copied + REQUIRE(dest.values[0] == 10.0); + REQUIRE(dest.values[1] == 11.0); + // Group 3: out of bounds — keeps default (10.0 = src.values.front()) + REQUIRE(dest.values[2] == 10.0); + REQUIRE(dest.values[3] == 10.0); + } + } + } +} + +SCENARIO("ConfigOptionVector::set_to_index handles negative dest_index values", "[Config][set_to_index]") { + GIVEN("A destination and source with a negative entry in dest_index") { + // The dest is initially empty, so resize fills all slots with src.values.front(). + Slic3r::ConfigOptionFloats dest; + Slic3r::ConfigOptionFloats src({100.0, 101.0, 200.0, 201.0}); + int stride = 2; + + WHEN("set_to_index maps group 0 and a negative index") { + std::vector variant_index = {-1, 0}; + dest.set_to_index(&src, variant_index, stride); + + THEN("The negative index is skipped, the valid group is copied") { + REQUIRE(dest.values.size() == 4); + // Position 0 (variant_index[0] = -1): skipped, keeps default fill + // from resize (src.values.front() = 100.0, applied to all new elements) + REQUIRE(dest.values[0] == 100.0); + REQUIRE(dest.values[1] == 100.0); + // Position 1 (variant_index[1] = 0): copied from group 0 of src + REQUIRE(dest.values[2] == 100.0); + REQUIRE(dest.values[3] == 101.0); + } + } + } +} + +SCENARIO("ConfigOptionVector::set_to_index handles single-element groups with stride=1", "[Config][set_to_index]") { + GIVEN("A destination re-mapping one variant index with a stride=1 source") { + // Simulates the PrintObject.cpp code path: stride=1, variant_index={1} + Slic3r::ConfigOptionFloats dest({99.0, 99.0, 99.0, 99.0}); // pre-sized for 4 extruders + Slic3r::ConfigOptionFloats src({0.5, 0.6, 0.7, 0.8}); // 4 extruder values + std::vector variant_index = {1}; // only extruder 1 is active + int stride = 1; + + WHEN("set_to_index is called") { + dest.set_to_index(&src, variant_index, stride); + + THEN("Only the mapped value is copied, rest are defaulted") { + REQUIRE(dest.values.size() == 1); + REQUIRE(dest.values[0] == 0.6); + } + } + } +} + +SCENARIO("ConfigOptionVector::set_to_index throws on incompatible type", "[Config][set_to_index]") { + GIVEN("A Floats destination and an Ints source") { + Slic3r::ConfigOptionFloats dest({0.0}); + Slic3r::ConfigOptionInts src({1, 2, 3}); + std::vector variant_index = {0}; + int stride = 1; + + WHEN("set_to_index is called with mismatched types") { + THEN("A ConfigurationError is thrown") { + REQUIRE_THROWS_AS(dest.set_to_index(&src, variant_index, stride), Slic3r::ConfigurationError); + } + } + } +} diff --git a/tests/libslic3r/test_placeholder_parser.cpp b/tests/libslic3r/test_placeholder_parser.cpp index 8b96305b95..14716b0b5e 100644 --- a/tests/libslic3r/test_placeholder_parser.cpp +++ b/tests/libslic3r/test_placeholder_parser.cpp @@ -52,6 +52,11 @@ SCENARIO("Placeholder parser scripting", "[PlaceholderParser]") { SECTION("math: round(-13.4)") { REQUIRE(parser.process("{round(-13.4)}") == "-13"); } SECTION("math: round(13.6)") { REQUIRE(parser.process("{round(13.6)}") == "14"); } SECTION("math: round(-13.6)") { REQUIRE(parser.process("{round(-13.6)}") == "-14"); } + SECTION("math: round(13.5)") { REQUIRE(parser.process("{round(13.5)}") == "14"); } + SECTION("math: floor(13.9)") { REQUIRE(parser.process("{floor(13.9)}") == "13"); } + SECTION("math: floor(-13.1)") { REQUIRE(parser.process("{floor(-13.1)}") == "-14"); } + SECTION("math: ceil(13.1)") { REQUIRE(parser.process("{ceil(13.1)}") == "14"); } + SECTION("math: ceil(-13.9)") { REQUIRE(parser.process("{ceil(-13.9)}") == "-13"); } SECTION("math: digits(5, 15)") { REQUIRE(parser.process("{digits(5, 15)}") == " 5"); } SECTION("math: digits(5., 15)") { REQUIRE(parser.process("{digits(5., 15)}") == " 5"); } SECTION("math: zdigits(5, 15)") { REQUIRE(parser.process("{zdigits(5, 15)}") == "000000000000005"); } @@ -65,6 +70,21 @@ SCENARIO("Placeholder parser scripting", "[PlaceholderParser]") { SECTION("math: interpolate_table(13.84375892476, (0, 0), (20, 20))") { REQUIRE(std::stod(parser.process("{interpolate_table(13.84375892476, (0, 0), (20, 20))}")) == Catch::Approx(13.84375892476)); } SECTION("math: interpolate_table(13, (0, 0), (20, 20), (30, 20))") { REQUIRE(std::stod(parser.process("{interpolate_table(13, (0, 0), (20, 20), (30, 20))}")) == Catch::Approx(13.)); } SECTION("math: interpolate_table(25, (0, 0), (20, 20), (30, 20))") { REQUIRE(std::stod(parser.process("{interpolate_table(25, (0, 0), (20, 20), (30, 20))}")) == Catch::Approx(20.)); } + // Only the grammar's built-in functions are callable; any other name is an undefined variable and throws. + SECTION("math: a non-built-in function name throws") { REQUIRE_THROWS(parser.process("{sqrt(16)}")); } + + // regex_replace(subject, /pattern/, replacement): the string-transform primitive. + SECTION("regex_replace: strips a file extension") { REQUIRE(parser.process("{regex_replace(\"part.stl\", /\\.[^.]*$/, \"\")}") == "part"); } + SECTION("regex_replace: leaves a non-matching dot untouched") { REQUIRE(parser.process("{regex_replace(\"Bracket v2.1\", /\\.stl$/, \"\")}") == "Bracket v2.1"); } + SECTION("regex_replace: replaces every match") { REQUIRE(parser.process("{regex_replace(\"a-b-c\", /-/, \"_\")}") == "a_b_c"); } + SECTION("regex_replace: replacement may reference a capture group") { REQUIRE(parser.process("{regex_replace(\"v12\", /v(\\d+)/, \"$1\")}") == "12"); } + // The result is an ordinary string, usable in further expressions (the real filename-template shape). + SECTION("regex_replace: result composes with concatenation") { REQUIRE(parser.process("{regex_replace(\"part.stl\", /\\.[^.]*$/, \"\") + \".gcode\"}") == "part.gcode"); } + // A malformed pattern and a non-string subject are both hard errors. + SECTION("regex_replace: an invalid pattern throws") { REQUIRE_THROWS(parser.process("{regex_replace(\"x\", /[/, \"\")}")); } + SECTION("regex_replace: a non-string subject throws") { REQUIRE_THROWS(parser.process("{regex_replace(123, /2/, \"\")}")); } + // Inside a skipped branch the subject is TYPE_EMPTY and the call must no-op (exercises the guard). + SECTION("regex_replace: is skipped inside a false if-branch") { REQUIRE(parser.process("{if false}{regex_replace(\"x\", /x/, \"y\")}{endif}done") == "done"); } // Test the "coFloatOrPercent" and "xxx_line_width" substitutions. // min_width_top_surface ratio_over inner_wall_line_width. @@ -130,6 +150,7 @@ SCENARIO("Placeholder parser variables", "[PlaceholderParser]") { SECTION("create an int local variable") { REQUIRE(parser.process("{local myint = 33+2}{myint}", 0, nullptr, nullptr, nullptr) == "35"); } SECTION("create a string local variable") { REQUIRE(parser.process("{local mystr = \"mine\" + \"only\" + \"mine\"}{mystr}", 0, nullptr, nullptr, nullptr) == "mineonlymine"); } + SECTION("regex_replace transforms a string variable") { REQUIRE(parser.process("{local n = \"part.stl\"}{regex_replace(n, /\\.[^.]*$/, \"\")}", 0, nullptr, nullptr, nullptr) == "part"); } SECTION("create a bool local variable") { REQUIRE(parser.process("{local mybool = 1 + 1 == 2}{mybool}", 0, nullptr, nullptr, nullptr) == "true"); } SECTION("create an int global variable") { REQUIRE(parser.process("{global myint = 33+2}{myint}", 0, nullptr, nullptr, &context_with_global_dict) == "35"); } SECTION("create a string global variable") { REQUIRE(parser.process("{global mystr = \"mine\" + \"only\" + \"mine\"}{mystr}", 0, nullptr, nullptr, &context_with_global_dict) == "mineonlymine"); }