mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-06 07:11:10 +00:00
Merge branch 'main' into ui-fixes-100
This commit is contained in:
@@ -283,21 +283,41 @@ jobs:
|
||||
id: fp_cache_key
|
||||
run: echo "key=flatpak-builder-${{ matrix.variant.arch }}-${{ hashFiles('deps/**', 'scripts/flatpak/com.orcaslicer.OrcaSlicer.yml', 'scripts/flatpak/make_deps_tar.sh') }}" >> "$GITHUB_OUTPUT"
|
||||
shell: bash
|
||||
# Manage flatpak-builder cache externally so PRs restore but never upload
|
||||
# Manage flatpak-builder cache externally so PRs restore but never upload.
|
||||
# The compiler cache under it is keyed per run below, so it is left out.
|
||||
- name: Restore flatpak-builder cache
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: actions/cache/restore@v6
|
||||
with:
|
||||
path: .flatpak-builder
|
||||
path: |
|
||||
.flatpak-builder/*
|
||||
!.flatpak-builder/ccache
|
||||
key: ${{ steps.fp_cache_key.outputs.key }}
|
||||
restore-keys: flatpak-builder-${{ matrix.variant.arch }}-
|
||||
- name: Save/restore flatpak-builder cache
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: actions/cache@v6
|
||||
with:
|
||||
path: .flatpak-builder
|
||||
path: |
|
||||
.flatpak-builder/*
|
||||
!.flatpak-builder/ccache
|
||||
key: ${{ steps.fp_cache_key.outputs.key }}
|
||||
restore-keys: flatpak-builder-${{ matrix.variant.arch }}-
|
||||
# Compiler cache for the OrcaSlicer module, as in build_orca.yml. Pull
|
||||
# requests only restore it; every other run (main, release branches, the
|
||||
# nightly, a dispatch) saves it. orca_deps stays on the state cache above.
|
||||
- name: Name the compiler cache leg
|
||||
run: |
|
||||
leg="Flatpak-${{ matrix.variant.arch }}"
|
||||
echo "CCACHE_LEG=$leg" >> "$GITHUB_ENV"
|
||||
echo "CCACHE_ENTRY=ccache-$leg-${{ github.run_id }}-${{ github.run_attempt }}" >> "$GITHUB_ENV"
|
||||
shell: bash
|
||||
- name: Restore compiler cache
|
||||
uses: actions/cache/restore@v6
|
||||
with:
|
||||
path: .flatpak-builder/ccache
|
||||
key: ${{ env.CCACHE_ENTRY }}
|
||||
restore-keys: ccache-${{ env.CCACHE_LEG }}-
|
||||
- name: Disable debug info for faster CI builds
|
||||
run: |
|
||||
sed -i '/^build-options:/a\ no-debuginfo: true\n strip: true' \
|
||||
@@ -308,6 +328,33 @@ jobs:
|
||||
sed -i "/name: OrcaSlicer/{n;s|buildsystem: simple|buildsystem: simple\n build-options:\n env:\n git_commit_hash: \"$git_commit_hash\"|}" \
|
||||
scripts/flatpak/com.orcaslicer.OrcaSlicer.yml
|
||||
shell: bash
|
||||
# flatpak-builder's --ccache only wraps cc and gcc, and the manifest builds
|
||||
# with clang, so CMake's launcher runs ccache instead; --ccache is still what
|
||||
# mounts the cache directory into the sandbox. The settings go into that
|
||||
# directory's own config file, which the sandbox reads too.
|
||||
- name: Enable compiler cache
|
||||
run: |
|
||||
printf ' %s\n' \
|
||||
'CMAKE_C_COMPILER_LAUNCHER: ccache' \
|
||||
'CMAKE_CXX_COMPILER_LAUNCHER: ccache' > "$RUNNER_TEMP/ccache-env.yml"
|
||||
sed -i "/^ git_commit_hash: /r $RUNNER_TEMP/ccache-env.yml" \
|
||||
scripts/flatpak/com.orcaslicer.OrcaSlicer.yml
|
||||
grep -q '^ CMAKE_CXX_COMPILER_LAUNCHER: ccache$' scripts/flatpak/com.orcaslicer.OrcaSlicer.yml
|
||||
mkdir -p .flatpak-builder/ccache
|
||||
export CCACHE_DIR=$PWD/.flatpak-builder/ccache
|
||||
ccache --set-config=max_size=3G
|
||||
# The compiler is reinstalled every run, so its mtime means nothing.
|
||||
ccache --set-config=compiler_check=content
|
||||
# Headers a fresh checkout has just written, the few files that use
|
||||
# __DATE__ or __TIME__, and the precompiled header, whose macros ccache
|
||||
# cannot see.
|
||||
ccache --set-config=sloppiness=pch_defines,time_macros,include_file_mtime,include_file_ctime
|
||||
# Hash the includes the compiler reports instead of preprocessing every
|
||||
# miss before compiling it.
|
||||
ccache --set-config=depend_mode=true
|
||||
# The restored directory carries the previous run's counters.
|
||||
ccache -z
|
||||
shell: bash
|
||||
- name: Check the manifest keeps orca_deps cacheable
|
||||
run: ./scripts/flatpak/check_manifest_cacheable.sh
|
||||
shell: bash
|
||||
@@ -318,9 +365,42 @@ jobs:
|
||||
with:
|
||||
bundle: OrcaSlicer-Linux-flatpak_${{ env.ver }}_${{ matrix.variant.arch }}.flatpak
|
||||
manifest-path: scripts/flatpak/com.orcaslicer.OrcaSlicer.yml
|
||||
cache: false
|
||||
# cache only turns on flatpak-builder --ccache; the caching itself is above.
|
||||
cache: true
|
||||
restore-cache: false
|
||||
save-cache: false
|
||||
arch: ${{ matrix.variant.arch }}
|
||||
upload-artifact: false
|
||||
- name: Compiler cache statistics
|
||||
if: always()
|
||||
run: |
|
||||
export CCACHE_DIR=$PWD/.flatpak-builder/ccache
|
||||
ccache -s -v || ccache -s
|
||||
shell: bash
|
||||
# Save the new entry first, then drop the older ones for this leg on this
|
||||
# ref, so a failed save leaves the previous entry in place.
|
||||
- name: Save compiler cache
|
||||
id: ccache_save
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: actions/cache/save@v6
|
||||
with:
|
||||
path: .flatpak-builder/ccache
|
||||
key: ${{ env.CCACHE_ENTRY }}
|
||||
- name: Drop older compiler cache entries
|
||||
if: ${{ steps.ccache_save.outcome == 'success' }}
|
||||
# The container has no gh, so this is the list and delete over the REST API.
|
||||
continue-on-error: true
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
api="$GITHUB_API_URL/repos/$GITHUB_REPOSITORY/actions/caches"
|
||||
curl -sSf -H "Authorization: Bearer $GH_TOKEN" \
|
||||
"$api?ref=$GITHUB_REF&key=ccache-$CCACHE_LEG-&per_page=100" \
|
||||
| jq -r --arg keep "$CCACHE_ENTRY" '.actions_caches[] | select(.key != $keep) | .id' \
|
||||
| while read -r id; do
|
||||
curl -sSf -X DELETE -H "Authorization: Bearer $GH_TOKEN" "$api/$id"
|
||||
done
|
||||
shell: bash
|
||||
- name: Upload artifacts Flatpak
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
|
||||
@@ -76,6 +76,57 @@ jobs:
|
||||
if (-not (Test-Path "$cmakeBin\cmake.exe")) { throw "cmake.exe not found at $cmakeBin" }
|
||||
Add-Content -Path $env:GITHUB_PATH -Value $cmakeBin
|
||||
|
||||
# Compiler cache. Pushes save it, so main keeps it warm; pull requests
|
||||
# restore it and discard what they compiled. Objects are keyed on the
|
||||
# preprocessed source, the compiler and the flags, so a leg only ever
|
||||
# hits its own entries. A failed install costs the caching, not the build.
|
||||
- name: Name the compiler cache leg
|
||||
if: ${{ !inputs.macos-combine-only }}
|
||||
shell: bash
|
||||
run: |
|
||||
leg="${{ runner.os }}-${{ inputs.arch || 'amd64' }}${{ runner.os == 'Windows' && format('-{0}', inputs.compiler) || '' }}"
|
||||
echo "CCACHE_LEG=$leg" >> "$GITHUB_ENV"
|
||||
echo "CCACHE_ENTRY=ccache-$leg-${{ github.run_id }}-${{ github.run_attempt }}" >> "$GITHUB_ENV"
|
||||
|
||||
# The action only installs and configures ccache. Restore and save go
|
||||
# through actions/cache with one path string, since the cache service
|
||||
# only matches entries saved under the identical path and the action
|
||||
# spells it differently on Windows.
|
||||
- name: Compiler cache
|
||||
id: ccache
|
||||
if: ${{ !inputs.macos-combine-only }}
|
||||
continue-on-error: true
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
key: ${{ env.CCACHE_LEG }}
|
||||
max-size: 3G
|
||||
restore: false
|
||||
save: false
|
||||
|
||||
- name: Restore compiler cache
|
||||
if: ${{ steps.ccache.outcome == 'success' }}
|
||||
uses: actions/cache/restore@v6
|
||||
with:
|
||||
path: ${{ github.workspace }}/.ccache
|
||||
key: ${{ env.CCACHE_ENTRY }}
|
||||
restore-keys: ccache-${{ env.CCACHE_LEG }}-
|
||||
|
||||
- name: Enable compiler cache
|
||||
if: ${{ steps.ccache.outcome == 'success' }}
|
||||
shell: bash
|
||||
run: |
|
||||
echo "CMAKE_C_COMPILER_LAUNCHER=ccache" >> "$GITHUB_ENV"
|
||||
echo "CMAKE_CXX_COMPILER_LAUNCHER=ccache" >> "$GITHUB_ENV"
|
||||
# Headers a fresh checkout has just written, the few files that
|
||||
# use __DATE__ or __TIME__, and the precompiled header, whose
|
||||
# macros ccache cannot see.
|
||||
echo "CCACHE_SLOPPINESS=pch_defines,time_macros,include_file_mtime,include_file_ctime" >> "$GITHUB_ENV"
|
||||
# Hash the includes the compiler reports instead of preprocessing
|
||||
# every miss before compiling it.
|
||||
echo "CCACHE_DEPEND=1" >> "$GITHUB_ENV"
|
||||
# The restored directory carries the previous run's counters.
|
||||
ccache -z
|
||||
|
||||
- name: Get the version and date on Ubuntu and macOS
|
||||
if: runner.os != 'Windows'
|
||||
run: |
|
||||
@@ -670,3 +721,32 @@ jobs:
|
||||
asset_name: orca_custom_preset_tests.zip
|
||||
asset_content_type: application/octet-stream
|
||||
max_releases: 1
|
||||
|
||||
- name: Compiler cache statistics
|
||||
if: ${{ always() && steps.ccache.outcome == 'success' }}
|
||||
shell: bash
|
||||
run: ccache -s -v || ccache -s
|
||||
|
||||
# Entries are immutable, so the new one is saved first and the older
|
||||
# ones for this leg on this ref are dropped afterwards: a failed save
|
||||
# leaves the previous entry in place.
|
||||
- name: Save compiler cache
|
||||
id: ccache_save
|
||||
if: ${{ steps.ccache.outcome == 'success' && github.event_name != 'pull_request' }}
|
||||
uses: actions/cache/save@v6
|
||||
with:
|
||||
path: ${{ github.workspace }}/.ccache
|
||||
key: ${{ env.CCACHE_ENTRY }}
|
||||
|
||||
- name: Drop older compiler cache entries
|
||||
if: ${{ steps.ccache_save.outcome == 'success' }}
|
||||
# A read-only token (fork PRs) cannot delete; that only costs storage.
|
||||
continue-on-error: true
|
||||
shell: bash
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
gh cache list --ref "$GITHUB_REF" --key "ccache-$CCACHE_LEG-" --limit 100 --json id,key \
|
||||
| jq -r --arg keep "$CCACHE_ENTRY" '.[] | select(.key != $keep) | .id' \
|
||||
| tr -d '\r' \
|
||||
| while read -r id; do gh cache delete "$id"; done
|
||||
|
||||
@@ -256,6 +256,13 @@ function(add_precompiled_header _target _input)
|
||||
message(STATUS "Adding precompiled header ${_input} to target ${_target}.")
|
||||
target_precompile_headers(${_target} PRIVATE ${_input})
|
||||
|
||||
# Clang records the modification time of every input in the precompiled
|
||||
# header, which makes it differ between two checkouts of the same source
|
||||
# and defeats a compiler cache. The build system already rebuilds the
|
||||
# header when an input changes.
|
||||
target_compile_options(${_target} PRIVATE
|
||||
"$<$<CXX_COMPILER_ID:Clang,AppleClang>:SHELL:-Xclang -fno-pch-timestamp>")
|
||||
|
||||
get_target_property(_sources ${_target} SOURCES)
|
||||
list(FILTER _sources INCLUDE REGEX ".*\\.mm?")
|
||||
|
||||
|
||||
@@ -2128,7 +2128,7 @@ msgid ""
|
||||
"OrcaSlicer has attempted to recreate the configuration file.\n"
|
||||
"Please note, application settings will be lost, but printer profiles will not be affected."
|
||||
msgstr ""
|
||||
"O arquivo de configuração do OrcaSlicer pode estar corrompido e não pode ser analisado.\n"
|
||||
"O arquivo de configuração do OrcaSlicer pode estar corrompido e não pode ser processado.\n"
|
||||
"O OrcaSlicer tentou recriar o arquivo de configuração.\n"
|
||||
"Por favor, note que as configurações do aplicativo serão perdidas, mas os perfis de impressora não serão afetados."
|
||||
|
||||
@@ -6675,7 +6675,7 @@ msgid "Failed to fetch model information from printer."
|
||||
msgstr "Falha ao obter informação do modelo da impressora."
|
||||
|
||||
msgid "Failed to parse model information."
|
||||
msgstr "Falha ao analisar a informação do modelo."
|
||||
msgstr "Falha ao processar a informação do modelo."
|
||||
|
||||
msgid "The .gcode.3mf file contains no G-code data. Please slice it with Orca Slicer and export a new .gcode.3mf file."
|
||||
msgstr "O arquivo .gcode.3mf não contém dados de G-code. Por favor, fatie com Orca Slicer e exporte um novo arquivo .gcode.3mf."
|
||||
@@ -8637,7 +8637,7 @@ msgstr ""
|
||||
"\n"
|
||||
"Deseja baixar e instalar esta versão agora?\n"
|
||||
"\n"
|
||||
"Observação: o aplicativo pode precisar ser reiniciado após a instalação."
|
||||
"Nota: o aplicativo pode precisar ser reiniciado após a instalação."
|
||||
|
||||
msgid "Download Network Plug-in"
|
||||
msgstr "Baixar Plug-in de Rede"
|
||||
@@ -9135,7 +9135,7 @@ msgid ""
|
||||
"Note: When Stealth Mode is enabled, your user profiles will not be backed up to Orca Cloud."
|
||||
msgstr ""
|
||||
"Isso desativa todos os recursos da nuvem, incluindo a sincronização de perfis do Orca Cloud. Usuários que preferem trabalhar totalmente offline podem ativar esta opção.\n"
|
||||
"Observação: quando o Modo Furtivo está ativado, seus perfis de usuário não serão copiados para o Orca Cloud."
|
||||
"Nota: quando o Modo Furtivo está ativado, seus perfis de usuário não serão copiados para o Orca Cloud."
|
||||
|
||||
msgid "Hide login side panel"
|
||||
msgstr "Ocultar painel lateral de autenticação"
|
||||
@@ -9775,7 +9775,6 @@ msgstr "A impressora falhou ao gerar a tabela de mapeamento automático do bico
|
||||
msgid "The current nozzle mapping may produce an extra %0.2f g of waste."
|
||||
msgstr "O mapeamento de bicos atual pode gerar um desperdício adicional de %0.2f g."
|
||||
|
||||
# AI Translated
|
||||
#, c-format, boost-format
|
||||
msgid "Recommended filament arrangement saves %s->"
|
||||
msgstr "A disposição de filamento recomendada economiza %s->"
|
||||
@@ -9834,7 +9833,6 @@ msgstr "Este processo determina os valores de fluxo dinâmico para melhorar a qu
|
||||
msgid "Internal"
|
||||
msgstr "Interno"
|
||||
|
||||
# AI Translated
|
||||
#, c-format, boost-format
|
||||
msgid "%s space less than 20MB. Timelapse may not save properly. You can turn it off or"
|
||||
msgstr "%s com espaço inferior a 20MB. O timelapse pode não ser salvo corretamente. Você pode desativá-lo ou"
|
||||
@@ -9842,15 +9840,12 @@ msgstr "%s com espaço inferior a 20MB. O timelapse pode não ser salvo corretam
|
||||
msgid "Clean up files"
|
||||
msgstr "Limpar arquivos"
|
||||
|
||||
# AI Translated
|
||||
msgid "Low internal storage. This timelapse will overwrite the oldest video files."
|
||||
msgstr "Armazenamento interno baixo. Este timelapse substituirá os arquivos de vídeo mais antigos."
|
||||
|
||||
# AI Translated
|
||||
msgid "Low external storage. This timelapse will overwrite the oldest video files."
|
||||
msgstr "Armazenamento externo baixo. Este timelapse substituirá os arquivos de vídeo mais antigos."
|
||||
|
||||
# AI Translated
|
||||
msgid "Insufficient external storage for time-lapse photography. Connect to computer to delete files, or use a larger memory card."
|
||||
msgstr "Armazenamento externo insuficiente para fotografia time-lapse. Conecte ao computador para excluir arquivos ou use um cartão de memória maior."
|
||||
|
||||
@@ -9886,7 +9881,6 @@ msgstr "Atualizando informações dos hotends (%d/%d)."
|
||||
msgid "There are not enough available hotends currently."
|
||||
msgstr "Não há hotends disponíveis em quantidade suficiente no momento."
|
||||
|
||||
# AI Translated
|
||||
msgid "Please complete the hotend rack setup and try again."
|
||||
msgstr "Por favor, conclua a configuração do rack de hotend e tente novamente."
|
||||
|
||||
@@ -9903,11 +9897,9 @@ msgstr "As informações reportadas sobre o hotend podem não ser confiáveis."
|
||||
msgid "The printer has no nozzle matching the slicing file (%s)."
|
||||
msgstr "A impressora não possui um bico compatível com o arquivo de fatiamento (%s)."
|
||||
|
||||
# AI Translated
|
||||
msgid "Please install a matching nozzle in the hotend rack, or set the corresponding printer preset while slicing."
|
||||
msgstr "Por favor, instale um bico compatível no rack de hotend, ou defina a predefinição de impressora correspondente ao fatiar."
|
||||
|
||||
# AI Translated
|
||||
msgid "The toolhead and hotend rack are full. Please remove at least one hotend before printing."
|
||||
msgstr "A cabeça da ferramenta e o rack de hotend estão cheios. Por favor, remova pelo menos um hotend antes de imprimir."
|
||||
|
||||
@@ -9933,24 +9925,19 @@ msgstr "ambas extrusoras"
|
||||
msgid "The hardness of current material (%s) exceeds the hardness of %s(%s). Please verify the nozzle or material settings and try again."
|
||||
msgstr "A dureza do material atual (%s) excede a dureza de %s(%s). Verifique as configurações do bico ou do material e tente novamente."
|
||||
|
||||
# AI Translated
|
||||
msgid "Your current firmware version cannot start this print job. Please update to the latest version and try again."
|
||||
msgstr "Sua versão atual do firmware não pode iniciar este trabalho de impressão. Atualize para a versão mais recente e tente novamente."
|
||||
|
||||
# AI Translated
|
||||
#, c-format, boost-format
|
||||
msgid "The hardness of current material (%s) exceeds the hardness of %s(%s). It may cause nozzle wear, leading to material leakage and unstable flow. Please exercise caution when using it."
|
||||
msgstr "A dureza do material atual (%s) excede a dureza de %s(%s). Isso pode causar desgaste do bico, levando a vazamento de material e fluxo instável. Tenha cuidado ao usá-lo."
|
||||
|
||||
# AI Translated
|
||||
msgid "Some filaments may switch between extruders during printing. Manual K-value calibration cannot be applied throughout the entire print, which may affect print quality. Enabling Flow Dynamics Calibration is recommended."
|
||||
msgstr "Alguns filamentos podem alternar entre extrusoras durante a impressão. A calibração manual do valor K não pode ser aplicada durante toda a impressão, o que pode afetar a qualidade da impressão. Recomenda-se ativar a Calibração de Dinâmica de Fluxo."
|
||||
|
||||
# AI Translated
|
||||
msgid "There is stringing-prone filament in this file. For best print quality, we recommend switching nozzle clumping detection to Auto mode."
|
||||
msgstr "Há filamento propenso a fiapos neste arquivo. Para a melhor qualidade de impressão, recomendamos alternar a detecção de aglomeração no bico para o modo Automático."
|
||||
msgstr "Há filamento propenso a criar fios neste arquivo. Para a melhor qualidade de impressão, recomendamos alternar a detecção de aglomeração no bico para o modo Automático."
|
||||
|
||||
# AI Translated
|
||||
msgid "If 'Dynamic Flow Calibration' is set to Auto/On, the system will use the manual calibration value or the default value and skip the flow calibration process. You can perform a manual flow calibration for TPU filament on the 'Calibration' page."
|
||||
msgstr "Se a 'Calibração de Fluxo Dinâmico' estiver definida como Automático/Ativado, o sistema usará o valor de calibração manual ou o valor padrão e ignorará o processo de calibração de fluxo. Você pode realizar uma calibração de fluxo manual para filamento TPU na página 'Calibração'."
|
||||
|
||||
@@ -10057,7 +10044,6 @@ msgstr "Desative a calibração de fluxo dinâmico para habilitar o valor de flu
|
||||
msgid "This printer does not support printing all plates."
|
||||
msgstr "Esta impressora não suporta a imprimir todas as placas."
|
||||
|
||||
# AI Translated
|
||||
#, c-format, boost-format
|
||||
msgid "The current firmware supports a maximum of %s materials. You can either reduce the number of materials to %s or fewer on the Preparation Page, or try updating the firmware. If you are still restricted after the update, please wait for subsequent firmware support."
|
||||
msgstr "O firmware atual suporta no máximo %s materiais. Você pode reduzir o número de materiais para %s ou menos na Página de Preparação, ou tentar atualizar o firmware. Se ainda estiver restrito após a atualização, aguarde o suporte de firmware subsequente."
|
||||
@@ -10065,11 +10051,9 @@ msgstr "O firmware atual suporta no máximo %s materiais. Você pode reduzir o n
|
||||
msgid "The type of external filament is unknown or does not match with the filament type in the slicing file. Please make sure you have installed the correct filament in the external spool."
|
||||
msgstr "O tipo de filamento externo é desconhecido ou não corresponde ao tipo de filamento no arquivo de fatiamento. Certifique-se de ter instalado o filamento correto no carretel externo."
|
||||
|
||||
# AI Translated
|
||||
msgid "TPU 90A/TPU 85A are too soft. It is recommended to perform manual flow calibration on the 'Calibration' page. If 'Dynamic Flow Calibration' is set to auto/on, the system will use the previous calibration value and skip the flow calibration process."
|
||||
msgstr "TPU 90A/TPU 85A são muito macios. Recomenda-se realizar a calibração de fluxo manual na página 'Calibração'. Se a 'Calibração de Fluxo Dinâmico' estiver definida como automático/ativado, o sistema usará o valor de calibração anterior e ignorará o processo de calibração de fluxo."
|
||||
|
||||
# AI Translated
|
||||
msgid "The filament in the AMS may be insufficient for this print. Please refill or replace it."
|
||||
msgstr "O filamento no AMS pode ser insuficiente para esta impressão. Por favor, reabasteça ou substitua-o."
|
||||
|
||||
@@ -10146,7 +10130,7 @@ msgid "Failed to post ticket to server"
|
||||
msgstr "Falha ao enviar o ticket para o servidor"
|
||||
|
||||
msgid "Failed to parse login report reason"
|
||||
msgstr "Falha ao analisar o motivo do relatório de login"
|
||||
msgstr "Falha ao processar o motivo do relatório de login"
|
||||
|
||||
msgid "Receive login report timeout"
|
||||
msgstr "Limite de tempo excedido ao receber o relatório de login"
|
||||
@@ -10242,11 +10226,9 @@ msgstr "Excluir esta predefinição"
|
||||
msgid "Search in preset"
|
||||
msgstr "Pesquisar nas predefinições"
|
||||
|
||||
# AI Translated
|
||||
msgid "Synchronization of different extruder drives or nozzle volume types is not supported."
|
||||
msgstr "A sincronização de diferentes acionamentos de extrusora ou tipos de volume do bico não é suportada."
|
||||
|
||||
# AI Translated
|
||||
msgid "Synchronize the modification of parameters to the corresponding parameters of another extruder."
|
||||
msgstr "Sincroniza a modificação de parâmetros com os parâmetros correspondentes de outra extrusora."
|
||||
|
||||
@@ -10316,7 +10298,7 @@ msgid "Are you sure you want to enable this option?"
|
||||
msgstr "Tem certeza de que deseja habilitar esta opção?"
|
||||
|
||||
msgid "Infill patterns are typically designed to handle rotation automatically to ensure proper printing and achieve their intended effects (e.g., Gyroid, Cubic). Rotating the current sparse infill pattern may lead to insufficient support. Please proceed with caution and thoroughly check for any potential printing issues. Are you sure you want to enable this option?"
|
||||
msgstr "Padrões de preenchimento são projetados para lidar com a rotação automaticamente para garantir a impressão adequada e atingir os efeitos pretendidos (Ex. Giroide, Cúbico). Girar o padrão de preenchimento esparso atual pode causar suporte insuficiente. Prossiga com cautela e verifique cuidadosamente se há possíveis problemas de impressão. Tem certeza de que deseja habilitar esta opção?"
|
||||
msgstr "Padrões de preenchimento são projetados para lidar com a rotação automaticamente para garantir a impressão adequada e atingir os efeitos pretendidos (ex.: Giroide, Cúbico). Girar o padrão de preenchimento esparso atual pode causar suporte insuficiente. Prossiga com cautela e verifique cuidadosamente se há possíveis problemas de impressão. Tem certeza de que deseja habilitar esta opção?"
|
||||
|
||||
msgid "Experimental feature: Retracting and cutting off the filament at a greater distance during filament changes to minimize flush. Although it can notably reduce flush, it may also elevate the risk of nozzle clogs or other printing complications."
|
||||
msgstr "Funcionalidade experimental: Retrair e cortar o filamento a uma distância maior durante mudanças de filamento para minimizar a purga. Embora possa reduzir notavelmente a purga, ele também pode elevar o risco de bolhas no bico ou outras complicações de impressão."
|
||||
@@ -10479,7 +10461,6 @@ msgstr "G-code de mudança de tipo de extrusão"
|
||||
msgid "Post-processing Scripts"
|
||||
msgstr "Scripts de pós-processamento"
|
||||
|
||||
# AI Translated
|
||||
msgid "Slicing Pipeline Plugin"
|
||||
msgstr "Plugin de Pipeline de Fatiamento"
|
||||
|
||||
@@ -10533,9 +10514,8 @@ msgstr "Temperatura da câmara de impressão"
|
||||
msgid "Chamber temperature"
|
||||
msgstr "Temperatura da câmara"
|
||||
|
||||
# AI Translated
|
||||
msgid "Target chamber temperature, and the minimal chamber temperature at which printing should start"
|
||||
msgstr "Temperatura da câmara alvo, e a temperatura mínima da câmara na qual a impressão deve começar"
|
||||
msgstr "Temperatura alvo da câmara, e a temperatura mínima da câmara na qual a impressão deve começar"
|
||||
|
||||
msgid "Target"
|
||||
msgstr "Alvo"
|
||||
@@ -10773,7 +10753,6 @@ msgstr "Limites de altura da camada"
|
||||
msgid "Z-Hop"
|
||||
msgstr "Z-Hop"
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"The Retract before wipe option could be only 100% when using the Firmware Retraction mode.\n"
|
||||
"\n"
|
||||
@@ -11081,7 +11060,6 @@ msgstr "Se ativo, este diálogo pode ser usado para transferir valores seleciona
|
||||
msgid "One of the presets does not exist"
|
||||
msgstr "Uma das predefinições não existe"
|
||||
|
||||
# AI Translated
|
||||
msgid "Compared presets has different printer technology"
|
||||
msgstr "As predefinições comparadas têm tecnologia de impressora diferente"
|
||||
|
||||
@@ -11416,9 +11394,8 @@ msgstr "Entrar"
|
||||
msgid "Login failed. Please try again."
|
||||
msgstr "Falha no login. Tente novamente."
|
||||
|
||||
# AI Translated
|
||||
msgid "parse json failed"
|
||||
msgstr "falha ao analisar o json"
|
||||
msgstr "falha ao processar o json"
|
||||
|
||||
msgid "[Action Required] "
|
||||
msgstr "[Ação Necessária] "
|
||||
@@ -11609,7 +11586,6 @@ msgctxt "Keyboard Shortcut"
|
||||
msgid "Space"
|
||||
msgstr "Espaço"
|
||||
|
||||
# AI Translated
|
||||
msgid "Open actions speed dial"
|
||||
msgstr "Abrir menu rápido de ações"
|
||||
|
||||
@@ -11691,11 +11667,9 @@ msgstr "informações de atualização da versão %s:"
|
||||
msgid "Network plug-in update"
|
||||
msgstr "Atualização do plug-in de rede"
|
||||
|
||||
# AI Translated
|
||||
msgid "Click OK to update the Network plug-in now. If a file is in use, the update will be applied the next time Orca Slicer launches."
|
||||
msgstr "Clique em OK para atualizar o plug-in de Rede agora. Se um arquivo estiver em uso, a atualização será aplicada na próxima vez que o Orca Slicer for iniciado."
|
||||
|
||||
# AI Translated
|
||||
msgid "A new Network plug-in is available. Do you want to install it?"
|
||||
msgstr "Um novo plug-in de Rede está disponível. Deseja instalá-lo?"
|
||||
|
||||
@@ -11755,7 +11729,6 @@ msgstr "Nome da impressora"
|
||||
msgid "Where to find your printer's IP and Access Code?"
|
||||
msgstr "Onde encontrar o IP e o Código de Acesso da sua impressora?"
|
||||
|
||||
# AI Translated
|
||||
msgid "How to trouble shooting"
|
||||
msgstr "Como solucionar problemas"
|
||||
|
||||
@@ -11903,11 +11876,9 @@ msgstr "Objeto: %1%"
|
||||
msgid "Parts of the object at these heights may be too thin or the object may have a faulty mesh."
|
||||
msgstr "Partes do objeto nessas alturas podem ser muito finas, ou o objeto pode ter uma malha com falhas."
|
||||
|
||||
# AI Translated
|
||||
msgid "Process change extrusion role G-code"
|
||||
msgstr "G-code de mudança de tipo de extrusão do processo"
|
||||
|
||||
# AI Translated
|
||||
msgid "Filament change extrusion role G-code"
|
||||
msgstr "G-code de mudança de tipo de extrusão do filamento"
|
||||
|
||||
@@ -12082,7 +12053,6 @@ msgstr " está muito perto de uma área de exclusão, e colisões vão ocorrer.\
|
||||
msgid " is too close to clumping detection area, and collisions will be caused.\n"
|
||||
msgstr " está muito perto da área de detecção de aglomeração, e ocorrerão colisões.\n"
|
||||
|
||||
# AI Translated
|
||||
msgid " is partially outside the printable area, and it cannot be printed.\n"
|
||||
msgstr " está parcialmente fora da área imprimível, e não pode ser impresso.\n"
|
||||
|
||||
@@ -12098,7 +12068,6 @@ msgstr "Se ainda assim desejar imprimir, você pode ativar a opção em Preferê
|
||||
msgid "No extrusions under current settings."
|
||||
msgstr "Nenhuma extrusão com as configurações atuais."
|
||||
|
||||
# AI Translated
|
||||
msgid "A gradient mixed filament is used, but 'Mixed color sublayer' is disabled. The gradient will not be printed."
|
||||
msgstr "Um filamento misto com gradiente está em uso, mas 'Subcamada de cor mista' está desativado. O gradiente não será impresso."
|
||||
|
||||
@@ -12138,7 +12107,6 @@ msgstr "Você pode querer reduzir o tamanho do seu modelo ou alterar as configur
|
||||
msgid "Variable layer height is not supported with Organic supports."
|
||||
msgstr "A altura de camada variável não é suportada com suportes Orgânicos."
|
||||
|
||||
# AI Translated
|
||||
msgid "The wipe tower filament cannot be a mixed filament."
|
||||
msgstr "O filamento da torre de purga não pode ser um filamento misto."
|
||||
|
||||
@@ -12775,7 +12743,6 @@ msgstr ""
|
||||
msgid "Internal bridge flow ratio"
|
||||
msgstr "Taxa de fluxo em ponte interna"
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"This value governs the thickness of the internal bridge layer. This is the first layer over sparse infill so increasing it may increase strength and upper layer quality.\n"
|
||||
"Values above 1.0: Increase the amount of material while maintaining line spacing. This can improve line contact and strength.\n"
|
||||
@@ -13165,11 +13132,9 @@ msgstr ""
|
||||
"A geometria será decimada antes de detectar ângulos agudos. Este parâmetro indica o comprimento mínimo da divergência para a decimação.\n"
|
||||
"0 para desativar."
|
||||
|
||||
# AI Translated
|
||||
msgid "Brim ears outer only"
|
||||
msgstr "Orelhas da borda apenas externas"
|
||||
msgstr "Apenas orelhas da borda externas"
|
||||
|
||||
# AI Translated
|
||||
msgid "Generate mouse ears only on the outer contour of the model, excluding holes and enclosed sections."
|
||||
msgstr "Gera orelhas de rato apenas no contorno externo do modelo, excluindo furos e seções fechadas."
|
||||
|
||||
@@ -13197,7 +13162,6 @@ msgstr "Por objeto"
|
||||
msgid "Intra-layer order"
|
||||
msgstr "Ordem intra-camada"
|
||||
|
||||
# AI Translated
|
||||
msgid ""
|
||||
"Order in which object instances are visited within a single layer, which controls how much travel is spent moving between them.\n"
|
||||
"\n"
|
||||
@@ -13255,7 +13219,7 @@ msgid "mm/s² or %"
|
||||
msgstr "mm/s² ou %"
|
||||
|
||||
msgid "Acceleration of bridges. If the value is expressed as a percentage (e.g. 50%), it will be calculated based on the outer wall acceleration."
|
||||
msgstr "Aceleração das pontes. Se o valor for expresso como uma porcentagem (por exemplo, 50%), será calculado com base na aceleração da parede externa."
|
||||
msgstr "Aceleração das pontes. Se o valor for expresso como uma porcentagem (ex.: 50%), será calculado com base na aceleração da parede externa."
|
||||
|
||||
msgid "Default filament profile"
|
||||
msgstr "Perfil de filamento padrão"
|
||||
@@ -13835,7 +13799,6 @@ msgstr "Tempo da camada"
|
||||
msgid "The part cooling fan will be enabled for layers where the estimated time is shorter than this value. Fan speed is interpolated between the minimum and maximum fan speeds according to layer printing time."
|
||||
msgstr "A ventoinha de resfriamento de peças será ativado para camadas cujo tempo estimado seja mais curto que esse valor. A velocidade da ventoinha é interpolada entre as velocidades mínima e máxima da ventoinha de acordo com o tempo de impressão da camada."
|
||||
|
||||
# AI Translated
|
||||
msgctxt "second"
|
||||
msgid "s"
|
||||
msgstr "s"
|
||||
@@ -14142,61 +14105,47 @@ msgstr "Material de suporte"
|
||||
msgid "Support material is commonly used to print supports and support interfaces."
|
||||
msgstr "O material de suporte é comumente usado para imprimir suportes e interfaces de suporte."
|
||||
|
||||
# AI Translated
|
||||
msgid "Is mixed filament"
|
||||
msgstr "É filamento misto"
|
||||
|
||||
# AI Translated
|
||||
msgid "Whether this filament slot is a mixed filament composed of multiple physical filaments"
|
||||
msgstr "Define se este slot de filamento é um filamento misto composto por vários filamentos físicos"
|
||||
|
||||
# AI Translated
|
||||
msgid "Mixed filament components"
|
||||
msgstr "Componentes do filamento misto"
|
||||
|
||||
# AI Translated
|
||||
msgid "Comma-separated 1-based indices of component filaments, e.g. \"1,3\""
|
||||
msgstr "Índices (começando em 1) dos filamentos componentes, separados por vírgulas; ex.: \"1,3\""
|
||||
|
||||
# AI Translated
|
||||
msgid "Mixed filament sublayer ratios"
|
||||
msgstr "Proporções de subcamada do filamento misto"
|
||||
|
||||
# AI Translated
|
||||
msgid "Comma-separated ratio values summing to 1.0, e.g. \"0.7,0.3\""
|
||||
msgstr "Valores de proporção separados por vírgulas cuja soma seja 1.0; ex.: \"0.7,0.3\""
|
||||
|
||||
# AI Translated
|
||||
msgid "Mixed filament gradient"
|
||||
msgstr "Gradiente do filamento misto"
|
||||
|
||||
# AI Translated
|
||||
msgid "Enable Z-direction gradient mode for mixed filament sub-layers. When enabled, the sub-layer ratios vary linearly across layers."
|
||||
msgstr "Ativa o modo de gradiente na direção Z para as subcamadas do filamento misto. Quando ativado, as proporções das subcamadas variam linearmente ao longo das camadas."
|
||||
msgstr "Ativa o modo de gradiente na direção Z para as subcamadas do filamento misto. Quando ativo, as proporções das subcamadas variam linearmente ao longo das camadas."
|
||||
|
||||
# AI Translated
|
||||
msgid "Mixed filament gradient range"
|
||||
msgstr "Faixa do gradiente do filamento misto"
|
||||
|
||||
# AI Translated
|
||||
msgid "Start and end ratios for the first component in gradient mode. Comma-separated pair, e.g. \"0.10,0.90\" means 10% to 90%."
|
||||
msgstr "Proporções inicial e final do primeiro componente no modo de gradiente. Par separado por vírgula; ex.: \"0.10,0.90\" significa de 10% a 90%."
|
||||
|
||||
# AI Translated
|
||||
msgid "Mixed filament gradient curve"
|
||||
msgstr "Curva do gradiente do filamento misto"
|
||||
|
||||
# AI Translated
|
||||
msgid "Optional Photoshop-style custom curve mapping Z progress to the first component ratio. Encoded as pipe-separated control points, either \"x,y\" (legacy) or \"x,y,m_in,m_out\" when a tangent override is needed (empty token or \"nan\" means use PCHIP default). x in [0,1]; y is clamped to the configured ratio range, e.g. \"0,0.15|0.5,0.50|1,0.85\". When empty, the linear gradient_range is used instead."
|
||||
msgstr "Curva personalizada opcional, no estilo do Photoshop, que mapeia o progresso em Z para a proporção do primeiro componente. Codificada como pontos de controle separados por barras verticais, no formato \"x,y\" (legado) ou \"x,y,m_in,m_out\" quando é necessário substituir a tangente (um valor vazio ou \"nan\" usa o padrão PCHIP). x está em [0,1]; y é limitado à faixa de proporção configurada; ex.: \"0,0.15|0.5,0.50|1,0.85\". Quando vazio, o gradient_range linear é usado."
|
||||
msgstr "Curva personalizada opcional no estilo do Photoshop, mapeando o progresso em Z para a proporção do primeiro componente. Codificada como pontos de controle separados por barras verticais, no formato \"x,y\" (legado) ou \"x,y,m_in,m_out\" quando é necessário substituir a tangente (um valor vazio ou \"nan\" usa o padrão PCHIP). X em [0,1]; Y é limitado à faixa de proporção configurada; ex.: \"0,0.15|0.5,0.50|1,0.85\". Quando vazio, o gradient_range linear é usado no lugar."
|
||||
|
||||
# AI Translated
|
||||
msgid "Mixed filament per-part gradient"
|
||||
msgstr "Gradiente por peça do filamento misto"
|
||||
|
||||
# AI Translated
|
||||
msgid "When gradient mode is enabled, apply the gradient to each part of an assembly independently rather than treating the whole assembly as one Z range."
|
||||
msgstr "Quando o modo de gradiente está ativado, aplica o gradiente a cada peça de uma montagem de forma independente, em vez de tratar toda a montagem como uma única faixa Z."
|
||||
msgstr "Quando o modo de gradiente está ativado, aplica o gradiente a cada peça de uma montagem de forma independente em vez de tratar toda a montagem como uma única faixa Z."
|
||||
|
||||
msgid "Filament printable"
|
||||
msgstr "Filamento imprimível"
|
||||
@@ -14287,7 +14236,7 @@ msgid "Insert solid layers"
|
||||
msgstr "Inserir camadas sólidas"
|
||||
|
||||
msgid "Insert solid infill at specific layers. Use N to insert every Nth layer, N#K to insert K consecutive solid layers every N layers (K is optional, e.g. '5#' equals '5#1'), or a comma-separated list (e.g. 1,7,9) to insert at explicit layers. Layers are 1-based."
|
||||
msgstr "Insere preenchimento sólido em camadas específicas. Use N para inserir a cada enésima camada, N#K para inserir K camadas sólidas consecutivas a cada enésima camada (K é opcional, ou seja, '5#' é igual a '5#1'), ou uma lista separada por vírgulas (Ex. 1,7,9) para inserir em camadas esplícitas. Camadas são baseadas em 1."
|
||||
msgstr "Insere preenchimento sólido em camadas específicas. Use N para inserir a cada enésima camada, N#K para inserir K camadas sólidas consecutivas a cada enésima camada (K é opcional, ex.: '5#' é igual a '5#1'), ou uma lista separada por vírgulas (Ex. 1,7,9) para inserir em camadas esplícitas. Camadas são baseadas em 1."
|
||||
|
||||
msgid "Fill Multiline"
|
||||
msgstr "Multilinhas de Preenchimento"
|
||||
@@ -14365,11 +14314,9 @@ msgstr "TPMS-FK"
|
||||
msgid "Gyroid"
|
||||
msgstr "Giroide"
|
||||
|
||||
# AI Translated
|
||||
msgid "Sparse infill smooth factor"
|
||||
msgstr "Fator de suavização do preenchimento esparso"
|
||||
|
||||
# AI Translated
|
||||
msgid "Controls how strongly sparse infill corners are rounded. 0% keeps the original sharp path, while 100% produces the largest possible curves between adjacent infill lines."
|
||||
msgstr "Controla o quanto os cantos do preenchimento esparso são arredondados. 0% mantém o trajeto original com cantos vivos, enquanto 100% produz as maiores curvas possíveis entre linhas de preenchimento adjacentes."
|
||||
|
||||
@@ -14383,10 +14330,10 @@ msgid "Acceleration of inner walls."
|
||||
msgstr "Aceleração das paredes internas."
|
||||
|
||||
msgid "Acceleration of sparse infill. If the value is expressed as a percentage (e.g. 100%), it will be calculated based on the default acceleration."
|
||||
msgstr "Aceleração do preenchimento esparso. Se o valor for expresso como uma porcentagem (por exemplo, 100%), será calculado com base na aceleração padrão."
|
||||
msgstr "Aceleração do preenchimento esparso. Se o valor for expresso como uma porcentagem (ex.: 100%), será calculado com base na aceleração padrão."
|
||||
|
||||
msgid "Acceleration of internal solid infill. If the value is expressed as a percentage (e.g. 100%), it will be calculated based on the default acceleration."
|
||||
msgstr "Aceleração do preenchimento sólido interno. Se o valor for expresso como uma porcentagem (por exemplo, 100%), será calculado com base na aceleração padrão."
|
||||
msgstr "Aceleração do preenchimento sólido interno. Se o valor for expresso como uma porcentagem (ex.: 100%), será calculado com base na aceleração padrão."
|
||||
|
||||
msgid "This is the printing acceleration for the first layer. Using limited acceleration can improve build plate adhesion."
|
||||
msgstr "Esta é a aceleração para a primeira camada. Usar aceleração limitada melhorar a adesão à placa de impressão."
|
||||
@@ -14490,7 +14437,7 @@ msgid ""
|
||||
"Only available when \"No cooling for the first\" is 0.\n"
|
||||
"Set to -1 to disable it."
|
||||
msgstr ""
|
||||
"Define uma velocidade exata da ventoinha para a primeira camada, substituindo todas as outras configurações de resfriamento. Útil para proteger peças impressas em 3D da cabeça da ferramenta (por exemplo, dutos ABS/ASA no estilo Voron) de uma mesa aquecida. Uma pequena quantidade de fluxo de ar resfria os dutos, sem usar o resfriamento total que pode, em certas condições, prejudicar a aderência da primeira camada.\n"
|
||||
"Define uma velocidade exata da ventoinha para a primeira camada, substituindo todas as outras configurações de resfriamento. Útil para proteger peças impressas em 3D da cabeça da ferramenta (ex.: dutos ABS/ASA no estilo Voron) de uma mesa aquecida. Uma pequena quantidade de fluxo de ar resfria os dutos, sem usar o resfriamento total que pode, em certas condições, prejudicar a aderência da primeira camada.\n"
|
||||
"A partir da segunda camada, o resfriamento normal é retomado.\n"
|
||||
"Se \"Velocidade total da ventoinha na camada\" também estiver definida, a ventoinha aumenta suavemente deste valor na primeira camada até o seu alvo na camada escolhida.\n"
|
||||
"Disponível apenas quando \"Sem resfriamento nas primeiras\" é 0.\n"
|
||||
@@ -14861,7 +14808,7 @@ msgid ""
|
||||
"Set to 0 to deactivate."
|
||||
msgstr ""
|
||||
"Algumas ventoinhas de resfriamento de componentes não conseguem iniciar a rotação quando comandadas abaixo de um determinado ciclo de trabalho PWM. Quando definido acima de 0, qualquer comando de ventoinha de resfriamento de componentes diferente de zero será elevado para pelo menos essa porcentagem, para que a ventoinha inicie de forma confiável. Um comando de ventoinha de 0 (ventoinha desligada) é sempre atendido exatamente. Essa limitação é aplicada após cada outro cálculo da ventoinha (rampa da primeira camada, interpolação do tempo da camada, substituições de saliência/ponte/interface de suporte/alisamento), para que o dimensionamento ainda opere dentro do intervalo [este valor, 100%].\n"
|
||||
"Se o seu firmware já desativa a ventoinha abaixo de um limite (por exemplo, [fan] off_below: 0.10 do Klipper desliga a ventoinha sempre que o ciclo de trabalho comandado for inferior a 10%), esta opção e o limite do firmware devem idealmente ser definidos com o mesmo valor. A correspondência entre eles (por exemplo, off_below: 0.10 no Klipper e 10% aqui) garante que o fatiador nunca emita um valor diferente de zero que o firmware emitiria a velocidade cai silenciosamente e a ventoinha nunca recebe um valor abaixo daquele que você sabe que ela pode realmente atingir.\n"
|
||||
"Se o seu firmware já desativa a ventoinha abaixo de um limite (por exemplo, [fan] off_below: 0.10 do Klipper desliga a ventoinha sempre que o ciclo de trabalho comandado for inferior a 10%), esta opção e o limite do firmware devem idealmente ser definidos com o mesmo valor. A correspondência entre eles (ex.: off_below: 0.10 no Klipper e 10% aqui) garante que o fatiador nunca emita um valor diferente de zero que o firmware emitiria a velocidade cai silenciosamente e a ventoinha nunca recebe um valor abaixo daquele que você sabe que ela pode realmente atingir.\n"
|
||||
"Defina como 0 para desativar."
|
||||
|
||||
msgid "Time cost"
|
||||
@@ -14908,13 +14855,11 @@ msgstr "Com que tipo de G-code a impressora é compatível."
|
||||
msgid "Klipper"
|
||||
msgstr "Klipper"
|
||||
|
||||
# AI Translated
|
||||
msgid "Skip G-code config block"
|
||||
msgstr "Omitir o bloco de configuração do G-code"
|
||||
|
||||
# AI Translated
|
||||
msgid "Do not write the CONFIG_BLOCK (slicer configuration key/value pairs) into the G-code file. This can help with printers whose firmware crashes when parsing these comment lines (e.g. Anycubic go-klipper). Note: the G-code file will no longer contain slicer settings, so importing it back into OrcaSlicer will not restore the configuration."
|
||||
msgstr "Não grava o CONFIG_BLOCK (os pares chave/valor da configuração do fatiador) no arquivo G-code. Isso pode ajudar com impressoras cujo firmware trava ao interpretar essas linhas de comentário (por exemplo, Anycubic go-klipper). Observação: o arquivo G-code não conterá mais as configurações do fatiador, então importá-lo de volta no OrcaSlicer não restaurará a configuração."
|
||||
msgstr "Não grava o CONFIG_BLOCK (os pares chave/valor da configuração do fatiador) no arquivo G-code. Isso pode ajudar com impressoras cujo firmware trava ao interpretar essas linhas de comentário (ex.: Anycubic go-klipper). Nota: o arquivo G-code não conterá mais as configurações do fatiador, então importá-lo de volta no OrcaSlicer não restaurará a configuração."
|
||||
|
||||
msgid "Pellet Modded Printer"
|
||||
msgstr "Impressora Modificada para Pellets"
|
||||
@@ -14962,13 +14907,13 @@ msgid "Sparse infill rotation template"
|
||||
msgstr "Gabarito de rotação de preenchimento esparso"
|
||||
|
||||
msgid "Rotate the sparse infill direction per layer using a template of angles. Enter comma-separated degrees (e.g., '0,30,60,90'). Angles are applied in order by layer and repeat when the list ends. Advanced syntax is supported: '+5' rotates +5° every layer; '+5#5' rotates +5° every 5 layers. See the Wiki for details. When a template is set, the standard infill direction setting is ignored. Note: some infill patterns (e.g., Gyroid) control rotation themselves; use with care."
|
||||
msgstr "Gira a direção do preenchimento esparso por camada usando um gabarito de ângulos. Insira graus separados por vírgula (por exemplo, '0, 30, 60, 90'). Os ângulos são aplicados em ordem por camada e repetidos quando a lista termina. Sintaxe avançada suportada: '+5' gira +5° a cada camada; '+5#5' gira +5° a cada 5 camadas. Consulte a Wiki para obter detalhes. Quando um modelo é definido, a configuração padrão de direção do preenchimento é ignorada. Observação: alguns padrões de preenchimento (por exemplo, Giróide) tem seu próprio controle de rotação, use com cuidado."
|
||||
msgstr "Gira a direção do preenchimento esparso por camada usando um gabarito de ângulos. Insira graus separados por vírgula (ex.: '0,30,60,90'). Os ângulos são aplicados em ordem por camada e repetidos quando a lista termina. Sintaxe avançada suportada: '+5' gira +5° a cada camada; '+5#5' gira +5° a cada 5 camadas. Consulte a Wiki para obter detalhes. Quando um modelo é definido, a configuração padrão de direção do preenchimento é ignorada. Nota: alguns padrões de preenchimento (ex.: Giróide) tem seu próprio controle de rotação, use com cuidado."
|
||||
|
||||
msgid "Solid infill rotation template"
|
||||
msgstr "Gabarito de rotação de preenchimento sólido"
|
||||
|
||||
msgid "This parameter adds a rotation of solid infill direction to each layer according to the specified template. The template is a comma-separated list of angles in degrees, e.g. '0,90'. The first angle is applied to the first layer, the second angle to the second layer, and so on. If there are more layers than angles, the angles will be repeated. Note that not all solid infill patterns support rotation."
|
||||
msgstr "Este parâmetro adiciona uma rotação da direção do preenchimento sólido a cada camada, de acordo com o gabarito especificado. O gabarito é uma lista de ângulos em graus separados por vírgulas, por exemplo, '0,90'. O primeiro ângulo é aplicado à primeira camada, o segundo ângulo à segunda camada e assim por diante. Se houver mais camadas do que ângulos, os ângulos serão repetidos. Observe que nem todos os padrões de preenchimento sólido suportam rotação."
|
||||
msgstr "Este parâmetro adiciona uma rotação da direção do preenchimento sólido a cada camada, de acordo com o gabarito especificado. O gabarito é uma lista de ângulos em graus separados por vírgulas, como '0,90'. O primeiro ângulo é aplicado à primeira camada, o segundo ângulo à segunda camada e assim por diante. Se houver mais camadas do que ângulos, os ângulos serão repetidos. Observe que nem todos os padrões de preenchimento sólido suportam rotação."
|
||||
|
||||
msgid "Skeleton infill density"
|
||||
msgstr "Densidade de preenchimento de esqueleto"
|
||||
@@ -15434,7 +15379,6 @@ msgstr "Força máxima do eixo Y"
|
||||
msgid "The allowed maximum output force of Y axis"
|
||||
msgstr "A força máxima de saída permitida do eixo Y"
|
||||
|
||||
# AI Translated
|
||||
msgctxt "Newton"
|
||||
msgid "N"
|
||||
msgstr "N"
|
||||
@@ -15445,7 +15389,6 @@ msgstr "Massa da mesa do eixo Y"
|
||||
msgid "The machine bed mass load of Y axis"
|
||||
msgstr "A carga de massa da mesa do equipamento no eixo Y"
|
||||
|
||||
# AI Translated
|
||||
msgctxt "gram"
|
||||
msgid "g"
|
||||
msgstr "g"
|
||||
@@ -15970,7 +15913,7 @@ msgid "Z-hop height"
|
||||
msgstr "Altura de Z-hop"
|
||||
|
||||
msgid "Whenever there is a retraction, the nozzle is lifted a little to create clearance between the nozzle and the print. This prevents the nozzle from hitting the print when traveling more. Using spiral lines to lift Z can prevent stringing."
|
||||
msgstr "Sempre que há uma retração, o bico é levantado um pouco para criar folga entre o bico e a impressão. Isso evita que o bico atinja a impressão ao se mover. Usar linhas em espiral para levantar Z pode evitar stringing."
|
||||
msgstr "Sempre que há uma retração, o bico é levantado um pouco para criar folga entre o bico e a impressão. Isso evita que o bico atinja a impressão ao se mover. Usar linhas em espiral para levantar Z pode evitar criação de fios."
|
||||
|
||||
msgid "Z-hop lower boundary"
|
||||
msgstr "Limite inferior do Z-hop"
|
||||
@@ -16051,7 +15994,7 @@ msgid "Has filament switcher"
|
||||
msgstr "Tem trocador de filamentos"
|
||||
|
||||
msgid "Printer has a filament switcher hardware (e.g., AMS)."
|
||||
msgstr "A impressora tem um sistema de troca de filamentos (Ex.: AMS)."
|
||||
msgstr "A impressora tem um sistema de troca de filamentos (ex.: AMS)."
|
||||
|
||||
msgid "Extra length on restart"
|
||||
msgstr "Comprimento extra na retração"
|
||||
@@ -16168,7 +16111,7 @@ msgid "Scarf joint speed"
|
||||
msgstr "Velocidade da costura em bisel"
|
||||
|
||||
msgid "This option sets the printing speed for scarf joints. It is recommended to print scarf joints at a slow speed (less than 100 mm/s). It's also advisable to enable 'Extrusion rate smoothing' if the set speed varies significantly from the speed of the outer or inner walls. If the speed specified here is higher than the speed of the outer or inner walls, the printer will default to the slower of the two speeds. When specified as a percentage (e.g., 80%), the speed is calculated based on the respective outer or inner wall speed. The default value is set to 100%."
|
||||
msgstr "Esta opção define a velocidade de impressão para as costuras em bisel. É recomendável imprimir as costuras em bisel em uma velocidade baixa (menor que 100 mm/s). Também é aconselhável habilitar 'Suavização da taxa de extrusão' se a velocidade definida variar significativamente da velocidade das paredes externas ou internas. Se a velocidade especificada aqui for maior que a velocidade das paredes externas ou internas, a impressora utilizará a mais lenta das duas velocidades. Quando especificado como uma porcentagem (por exemplo, 80%), a velocidade é calculada com base na velocidade do perímetro externo ou interna respectiva. O valor padrão é definido como 100%."
|
||||
msgstr "Esta opção define a velocidade de impressão para as costuras em bisel. É recomendável imprimir as costuras em bisel em uma velocidade baixa (menor que 100 mm/s). Também é aconselhável habilitar 'Suavização da taxa de extrusão' se a velocidade definida variar significativamente da velocidade das paredes externas ou internas. Se a velocidade especificada aqui for maior que a velocidade das paredes externas ou internas, a impressora utilizará a mais lenta das duas velocidades. Quando especificado como uma porcentagem (ex.: 80%), a velocidade é calculada com base na velocidade do perímetro externo ou interna respectiva. O valor padrão é definido como 100%."
|
||||
|
||||
msgid "Scarf joint flow ratio"
|
||||
msgstr "Taxa de fluxo da costura em bisel"
|
||||
@@ -16238,7 +16181,7 @@ msgid "Wipe speed"
|
||||
msgstr "Velocidade de limpeza"
|
||||
|
||||
msgid "The wipe speed is determined by the speed setting specified in this configuration. If the value is expressed as a percentage (e.g. 80%), it will be calculated based on the travel speed setting above. The default value for this parameter is 80%."
|
||||
msgstr "A velocidade de limpeza é determinada pela velocidade especificada nesta configuração. Se o valor for expresso como uma porcentagem (por exemplo, 80%), será calculado com base na configuração de velocidade de deslocamento acima. O valor padrão para este parâmetro é 80%."
|
||||
msgstr "A velocidade de limpeza é determinada pela velocidade especificada nesta configuração. Se o valor for expresso como uma porcentagem (ex.: 80%), será calculado com base na configuração de velocidade de deslocamento acima. O valor padrão para este parâmetro é 80%."
|
||||
|
||||
msgid "Skirt distance"
|
||||
msgstr "Distância da saia"
|
||||
@@ -16276,7 +16219,7 @@ msgstr ""
|
||||
"Um escudo de ar é útil para proteger uma impressão ABS ou ASA de deformações e desprendimento da mesa de impressão devido à corrente de ar. Geralmente, ele é necessário apenas com impressoras de estrutura aberta, ou seja, sem um gabinete.\n"
|
||||
"\n"
|
||||
"Habilitado = a saia é tão alta quanto o objeto impresso mais alto. Caso contrário, 'Altura da saia' é usada.\n"
|
||||
"Observação: com o escudo de ar ativo, a saia será impressa na distância da saia do objeto. Portanto, se as bordas estiverem ativas, ela pode se cruzar com elas. Para evitar isso, aumente o valor da distância da saia.\n"
|
||||
"Nota: com o escudo de ar ativo, a saia será impressa na distância da saia do objeto. Portanto, se as bordas estiverem ativas, ela pode se cruzar com elas. Para evitar isso, aumente o valor da distância da saia.\n"
|
||||
|
||||
msgid "Enabled"
|
||||
msgstr "Ativado"
|
||||
@@ -16417,10 +16360,10 @@ msgid "Preheat steps"
|
||||
msgstr "Passos de pré-aquecimento"
|
||||
|
||||
msgid "Insert multiple preheat commands (e.g. M104.1). Only useful for Prusa XL. For other printers, please set it to 1."
|
||||
msgstr "Insire múltiplos comandos de pré-aquecimento (por exemplo, M104.1). Útil apenas para Prusa XL. Para outras impressoras, defina como 1."
|
||||
msgstr "Insire múltiplos comandos de pré-aquecimento (ex.: M104.1). Útil apenas para Prusa XL. Para outras impressoras, defina como 1."
|
||||
|
||||
msgid "G-code written at the very top of the output file, before any other content. Useful for adding metadata that printer firmware reads from the first lines of the file (e.g. estimated print time, filament usage). Supports placeholders like {print_time_sec} and {used_filament_length}."
|
||||
msgstr "Código G escrito no início do arquivo de saída, antes de qualquer outro conteúdo. Útil para adicionar metadados que o firmware da impressora lê das primeiras linhas do arquivo (por exemplo, tempo estimado de impressão, consumo de filamento). Suporta marcadores como {print_time_sec} e {used_filament_length}."
|
||||
msgstr "Código G escrito no início do arquivo de saída, antes de qualquer outro conteúdo. Útil para adicionar metadados que o firmware da impressora lê das primeiras linhas do arquivo (ex.: tempo estimado de impressão, consumo de filamento). Suporta marcadores como {print_time_sec} e {used_filament_length}."
|
||||
|
||||
msgid "Start G-code"
|
||||
msgstr "G-code Inicial"
|
||||
@@ -16441,7 +16384,7 @@ msgid "Manual Filament Change"
|
||||
msgstr "Troca Manual de Filamento"
|
||||
|
||||
msgid "Enable this option to omit the custom Change filament G-code only at the beginning of the print. The tool change command (e.g., T0) will be skipped throughout the entire print. This is useful for manual multi-material printing, where we use M600/PAUSE to trigger the manual filament change action."
|
||||
msgstr "Ative esta opção para omitir o G-code de troca de filamento personalizado apenas no início da impressão. O comando de troca de ferramenta (por exemplo, T0) será ignorado durante toda a impressão. Isso é útil para impressão manual de vários materiais, onde usamos M600/PAUSE para acionar a ação de troca manual de filamento."
|
||||
msgstr "Ative esta opção para omitir o G-code de troca de filamento personalizado apenas no início da impressão. O comando de troca de ferramenta (ex.: T0) será ignorado durante toda a impressão. Isso é útil para impressão manual de vários materiais, onde usamos M600/PAUSE para acionar a ação de troca manual de filamento."
|
||||
|
||||
msgid "Wipe tower type"
|
||||
msgstr "Tipo de torre de purga"
|
||||
@@ -16997,11 +16940,9 @@ msgstr ""
|
||||
"\n"
|
||||
"Definir um valor na configuração de quantidade de retração antes da limpeza abaixo executará qualquer retração em excesso antes da limpeza, caso contrário, será realizada após."
|
||||
|
||||
# AI Translated
|
||||
msgid "Mixed color sublayer"
|
||||
msgstr "Subcamada de cor mista"
|
||||
|
||||
# AI Translated
|
||||
msgid "Enable mixed color sublayer splitting. When enabled, layers containing mixed color filaments will be split into sub-layers to achieve color mixing effects."
|
||||
msgstr "Ativa a divisão em subcamadas de cor mista. Quando ativado, as camadas que contêm filamentos de cor mista são divididas em subcamadas para obter efeitos de mistura de cores."
|
||||
|
||||
@@ -18061,9 +18002,8 @@ msgstr "A geração da malha do arquivo do modelo falhou ou não há forma váli
|
||||
msgid "The supplied file couldn't be read because it's empty."
|
||||
msgstr "O arquivo fornecido não pôde ser lido porque está vazio."
|
||||
|
||||
# AI Translated
|
||||
msgid "The file format is incompatible and cannot be parsed."
|
||||
msgstr "O formato do arquivo é incompatível e não pode ser lido."
|
||||
msgstr "O formato do arquivo é incompatível e não pode ser processado."
|
||||
|
||||
msgid "Unknown file format: input file must have .stl, .obj, or .amf(.xml) extension."
|
||||
msgstr "Formato de arquivo desconhecido: o arquivo de entrada deve ter extensão .stl, .obj, .amf(.xml)."
|
||||
@@ -18072,10 +18012,10 @@ msgid "Unknown file format: input file must have .3mf or .zip.amf extension."
|
||||
msgstr "Formato de arquivo desconhecido: o arquivo de entrada deve ter extensão .3mf ou .zip.amf."
|
||||
|
||||
msgid "load_obj: failed to parse"
|
||||
msgstr "load_obj: falha ao analisar"
|
||||
msgstr "load_obj: falha ao processar"
|
||||
|
||||
msgid "load mtl in obj: failed to parse"
|
||||
msgstr "carregar mtl em obj: falha ao analisar"
|
||||
msgstr "carregar mtl em obj: falha ao processsar"
|
||||
|
||||
msgid "The file contains polygons with more than 4 vertices."
|
||||
msgstr "O arquivo contém polígonos com mais de 4 vértices."
|
||||
@@ -19189,7 +19129,7 @@ msgid "Serial"
|
||||
msgstr "Série"
|
||||
|
||||
msgid "e.g. Basic, Matte, Silk, Marble"
|
||||
msgstr "por exemplo, Básico, Fosco, Seda, Mármore"
|
||||
msgstr "Ex.: Básico, Fosco, Seda, Mármore"
|
||||
|
||||
msgid "Filament Preset"
|
||||
msgstr "Predefinição de Filamento"
|
||||
@@ -19870,7 +19810,7 @@ msgid "Error. Can't get API token for authorization"
|
||||
msgstr "Erro. Não foi possível obter o token de API para autorização"
|
||||
|
||||
msgid "Could not parse server response."
|
||||
msgstr "Não foi possível decifrar a resposta do servidor."
|
||||
msgstr "Não foi possível processar a resposta do servidor."
|
||||
|
||||
msgid "Error saving session to file"
|
||||
msgstr "Erro salvando sessão para arquivo"
|
||||
@@ -19938,7 +19878,7 @@ msgstr "O host respondeu, mas não parece ser o Moonraker (falta o result.klippy
|
||||
|
||||
#, c-format, boost-format
|
||||
msgid "Could not parse Moonraker server response: %s"
|
||||
msgstr "Não foi possível analisar a resposta do servidor Moonraker: %s"
|
||||
msgstr "Não foi possível processar a resposta do servidor Moonraker: %s"
|
||||
|
||||
msgid "Connection to OctoPrint is working correctly."
|
||||
msgstr "A conexão com o OctoPrint funciona corretamente."
|
||||
@@ -20312,7 +20252,6 @@ msgstr "Removido"
|
||||
msgid "Enable smart filament assign: Assign one filament to multiple nozzles to maximize savings"
|
||||
msgstr "Ativar atribuição inteligente de filamento: Atribui um filamento a vários bicos para maximizar a economia"
|
||||
|
||||
# AI Translated
|
||||
msgid "File Saving"
|
||||
msgstr "Salvamento de Arquivo"
|
||||
|
||||
@@ -20499,7 +20438,7 @@ msgid "Connection timed out. Please check if the printer and computer network ar
|
||||
msgstr "Limite de tempo de conexão esgotado. Verifique se a impressora e a rede do computador estão funcionando corretamente e confirme se estão na mesma rede."
|
||||
|
||||
msgid "The Hostname/IP/URL could not be parsed, please check it and try again."
|
||||
msgstr "Não foi possível decifrar o Hostname/IP/URL; verifique-o e tente novamente."
|
||||
msgstr "Não foi possível processar o Hostname/IP/URL; verifique-o e tente novamente."
|
||||
|
||||
msgid "File/data transfer interrupted. Please check the printer and network, then try it again."
|
||||
msgstr "Transferência de arquivo/dados interrompida. Verifique a impressora e a rede e tente novamente."
|
||||
@@ -21282,15 +21221,6 @@ msgstr ""
|
||||
#~ msgid "Your system is missing H.264 codecs for GStreamer, which are required to play video. (Try installing the gstreamer1.0-plugins-bad or gstreamer1.0-libav packages, then restart Orca Slicer?)"
|
||||
#~ msgstr "Seu sistema não possui codecs H.264 para o GStreamer, que são necessários para reproduzir vídeos. (Tente instalar os pacotes gstreamer1.0-plugins-bad ou gstreamer1.0-libav e depois reinicie o OrcaSlicer?)"
|
||||
|
||||
#~ msgid "N"
|
||||
#~ msgstr "N"
|
||||
|
||||
#~ msgid "g"
|
||||
#~ msgstr "g"
|
||||
|
||||
#~ msgid "Fila Saving"
|
||||
#~ msgstr "Econo Filamento"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "Layer height is too small.\n"
|
||||
#~ "It will set to min_layer_height\n"
|
||||
@@ -21618,7 +21548,7 @@ msgstr ""
|
||||
#~ "Pontes externas de menor densidade podem ajudar a melhorar a confiabilidade, pois há mais espaço para o ar circular ao redor da ponte extrudada, melhorando sua velocidade de resfriamento. O mínimo é 10%.\n"
|
||||
#~ "\n"
|
||||
#~ "Densidades mais altas podem produzir superfícies de ponte mais lisas, pois as linhas sobrepostas fornecem suporte adicional durante a impressão. O máximo é 120%.\n"
|
||||
#~ "Observação: Densidade de ponte muito alta pode causar deformação ou sobrextrusão."
|
||||
#~ "Nota: Densidade de ponte muito alta pode causar deformação ou sobrextrusão."
|
||||
|
||||
#~ msgid ""
|
||||
#~ "Controls the density (spacing) of internal bridge lines. 100% means solid bridge. Default is 100%.\n"
|
||||
@@ -21663,7 +21593,7 @@ msgstr ""
|
||||
#~ "\n"
|
||||
#~ "Geralmente, é recomendável ter esta opção ativada, a menos que o resfriamento da impressora seja potente o suficiente ou a velocidade de impressão lenta o suficiente para que a curvatura do perímetro não aconteça. Se estiver imprimindo com uma alta velocidade de perímetro externo, este parâmetro pode introduzir pequenos artefatos ao desacelerar devido à grande variação nas velocidades de impressão. Se você notar artefatos, certifique-se de que seu pressure advance esteja ajustado corretamente.\n"
|
||||
#~ "\n"
|
||||
#~ "Observação: quando esta opção estiver habilitada, os perímetros de saliência são tratados como saliências, o que significa que a velocidade de saliência é aplicada mesmo se o perímetro de saliência for parte de uma ponte. Por exemplo, quando os perímetros estiverem 100% salientes, sem nenhuma parede apoiando-os por baixo, a velocidade de saliência de 100% será aplicada."
|
||||
#~ "Nota: quando esta opção estiver habilitada, os perímetros de saliência são tratados como saliências, o que significa que a velocidade de saliência é aplicada mesmo se o perímetro de saliência for parte de uma ponte. Por exemplo, quando os perímetros estiverem 100% salientes, sem nenhuma parede apoiando-os por baixo, a velocidade de saliência de 100% será aplicada."
|
||||
|
||||
#~ msgid "If enabled, bridges are more reliable, can bridge longer distances, but may look worse. If disabled, bridges look better but are reliable just for shorter bridged distances."
|
||||
#~ msgstr "Se ativado, as pontes são mais confiáveis, podem cobrir distâncias maiores, mas podem parecer piores. Se desativado, as pontes ficam melhores, mas são confiáveis apenas para distâncias de ponte mais curtas."
|
||||
@@ -22583,7 +22513,7 @@ msgstr ""
|
||||
#~ msgstr "Contagem máxima de projetos recentes"
|
||||
|
||||
#~ msgid "This parameter adds a rotation of sparse infill direction to each layer according to the specified template. The template is a comma-separated list of angles in degrees, e.g. '0,90'. The first angle is applied to the first layer, the second angle to the second layer, and so on. If there are more layers than angles, the angles will be repeated. Note that not all sparse infill patterns support rotation."
|
||||
#~ msgstr "Este parâmetro adiciona uma rotação na direção do preenchimento esparso a cada camada, de acordo com o gabarito especificado. O gabarito é uma lista de ângulos em graus separados por vírgulas, por exemplo, '0,90'. O primeiro ângulo é aplicado à primeira camada, o segundo ângulo à segunda camada e assim por diante. Se houver mais camadas do que ângulos, os ângulos serão repetidos. Observe que nem todos os padrões de preenchimento esparso suportam rotação."
|
||||
#~ msgstr "Este parâmetro adiciona uma rotação na direção do preenchimento esparso a cada camada, de acordo com o gabarito especificado. O gabarito é uma lista de ângulos em graus separados por vírgulas, como '0,90'. O primeiro ângulo é aplicado à primeira camada, o segundo ângulo à segunda camada e assim por diante. Se houver mais camadas do que ângulos, os ângulos serão repetidos. Observe que nem todos os padrões de preenchimento esparso suportam rotação."
|
||||
|
||||
#~ msgid "Set Position"
|
||||
#~ msgstr "Definir Posição"
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
<svg width="25" height="25" xmlns="http://www.w3.org/2000/svg" fill="none">
|
||||
|
||||
<g>
|
||||
<title>Layer 1</title>
|
||||
<path id="svg_1" stroke-linecap="round" stroke-width="2" stroke="#262E30" d="m1,12.5l23,0"/>
|
||||
<path id="svg_2" stroke-linecap="round" stroke-width="2" stroke="#262E30" d="m12.5,24l0,-23"/>
|
||||
</g>
|
||||
</svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<line x1="0.5" y1="7.5" x2="14.5" y2="7.5" style="fill:none;stroke:#949494;stroke-linecap:round;stroke-linejoin:round"/>
|
||||
<line x1="7.5" y1="0.5" x2="7.5" y2="14.5" style="fill:none;stroke:#949494;stroke-linecap:round;stroke-linejoin:round"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 312 B After Width: | Height: | Size: 332 B |
-6
@@ -324,12 +324,6 @@
|
||||
"slow_down_min_speed": [
|
||||
"20"
|
||||
],
|
||||
"supertack_plate_temp": [
|
||||
"35"
|
||||
],
|
||||
"supertack_plate_temp_initial_layer": [
|
||||
"35"
|
||||
],
|
||||
"support_material_interface_fan_speed": [
|
||||
"-1"
|
||||
],
|
||||
|
||||
-6
@@ -318,12 +318,6 @@
|
||||
"slow_down_min_speed": [
|
||||
"20"
|
||||
],
|
||||
"supertack_plate_temp": [
|
||||
"35"
|
||||
],
|
||||
"supertack_plate_temp_initial_layer": [
|
||||
"35"
|
||||
],
|
||||
"support_material_interface_fan_speed": [
|
||||
"-1"
|
||||
],
|
||||
|
||||
-6
@@ -324,12 +324,6 @@
|
||||
"slow_down_min_speed": [
|
||||
"20"
|
||||
],
|
||||
"supertack_plate_temp": [
|
||||
"35"
|
||||
],
|
||||
"supertack_plate_temp_initial_layer": [
|
||||
"35"
|
||||
],
|
||||
"support_material_interface_fan_speed": [
|
||||
"-1"
|
||||
],
|
||||
|
||||
-6
@@ -324,12 +324,6 @@
|
||||
"slow_down_min_speed": [
|
||||
"20"
|
||||
],
|
||||
"supertack_plate_temp": [
|
||||
"35"
|
||||
],
|
||||
"supertack_plate_temp_initial_layer": [
|
||||
"35"
|
||||
],
|
||||
"support_material_interface_fan_speed": [
|
||||
"-1"
|
||||
],
|
||||
|
||||
@@ -309,12 +309,6 @@
|
||||
"slow_down_min_speed": [
|
||||
"20"
|
||||
],
|
||||
"supertack_plate_temp": [
|
||||
"35"
|
||||
],
|
||||
"supertack_plate_temp_initial_layer": [
|
||||
"35"
|
||||
],
|
||||
"support_material_interface_fan_speed": [
|
||||
"-1"
|
||||
],
|
||||
|
||||
-6
@@ -318,12 +318,6 @@
|
||||
"slow_down_min_speed": [
|
||||
"20"
|
||||
],
|
||||
"supertack_plate_temp": [
|
||||
"35"
|
||||
],
|
||||
"supertack_plate_temp_initial_layer": [
|
||||
"35"
|
||||
],
|
||||
"support_material_interface_fan_speed": [
|
||||
"-1"
|
||||
],
|
||||
|
||||
-6
@@ -324,12 +324,6 @@
|
||||
"slow_down_min_speed": [
|
||||
"20"
|
||||
],
|
||||
"supertack_plate_temp": [
|
||||
"35"
|
||||
],
|
||||
"supertack_plate_temp_initial_layer": [
|
||||
"35"
|
||||
],
|
||||
"support_material_interface_fan_speed": [
|
||||
"-1"
|
||||
],
|
||||
|
||||
-6
@@ -324,12 +324,6 @@
|
||||
"slow_down_min_speed": [
|
||||
"10"
|
||||
],
|
||||
"supertack_plate_temp": [
|
||||
"35"
|
||||
],
|
||||
"supertack_plate_temp_initial_layer": [
|
||||
"35"
|
||||
],
|
||||
"support_material_interface_fan_speed": [
|
||||
"-1"
|
||||
],
|
||||
|
||||
-6
@@ -318,12 +318,6 @@
|
||||
"slow_down_min_speed": [
|
||||
"20"
|
||||
],
|
||||
"supertack_plate_temp": [
|
||||
"35"
|
||||
],
|
||||
"supertack_plate_temp_initial_layer": [
|
||||
"35"
|
||||
],
|
||||
"support_material_interface_fan_speed": [
|
||||
"-1"
|
||||
],
|
||||
|
||||
@@ -309,12 +309,6 @@
|
||||
"slow_down_min_speed": [
|
||||
"20"
|
||||
],
|
||||
"supertack_plate_temp": [
|
||||
"35"
|
||||
],
|
||||
"supertack_plate_temp_initial_layer": [
|
||||
"35"
|
||||
],
|
||||
"support_material_interface_fan_speed": [
|
||||
"-1"
|
||||
],
|
||||
|
||||
@@ -25,6 +25,12 @@
|
||||
"hot_plate_temp_initial_layer": [
|
||||
"80"
|
||||
],
|
||||
"supertack_plate_temp": [
|
||||
"60"
|
||||
],
|
||||
"supertack_plate_temp_initial_layer": [
|
||||
"60"
|
||||
],
|
||||
"slow_down_for_layer_cooling": [
|
||||
"1"
|
||||
],
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "Flashforge",
|
||||
"url": "",
|
||||
"version": "02.04.00.05",
|
||||
"version": "02.04.00.06",
|
||||
"force_update": "0",
|
||||
"description": "Flashforge configurations",
|
||||
"machine_model_list": [
|
||||
@@ -439,6 +439,22 @@
|
||||
"name": "0.14mm Standard @FF AD5X 0.25 nozzle",
|
||||
"sub_path": "process/0.14mm Standard @FF AD5X 0.25 nozzle.json"
|
||||
},
|
||||
{
|
||||
"name": "0.08mm Standard @FF C5 0.25 nozzle",
|
||||
"sub_path": "process/0.08mm Standard @FF C5 0.25 nozzle.json"
|
||||
},
|
||||
{
|
||||
"name": "0.10mm Standard @FF C5 0.25 nozzle",
|
||||
"sub_path": "process/0.10mm Standard @FF C5 0.25 nozzle.json"
|
||||
},
|
||||
{
|
||||
"name": "0.12mm Standard @FF C5 0.25 nozzle",
|
||||
"sub_path": "process/0.12mm Standard @FF C5 0.25 nozzle.json"
|
||||
},
|
||||
{
|
||||
"name": "0.14mm Standard @FF C5 0.25 nozzle",
|
||||
"sub_path": "process/0.14mm Standard @FF C5 0.25 nozzle.json"
|
||||
},
|
||||
{
|
||||
"name": "0.14mm Standard @Flashforge AD5M 0.25 Nozzle",
|
||||
"sub_path": "process/0.14mm Standard @Flashforge AD5M 0.25 Nozzle.json"
|
||||
@@ -2903,6 +2919,10 @@
|
||||
"name": "Flashforge AD5X 0.4 nozzle",
|
||||
"sub_path": "machine/Flashforge AD5X 0.4 nozzle.json"
|
||||
},
|
||||
{
|
||||
"name": "Flashforge Creator 5 0.25 nozzle",
|
||||
"sub_path": "machine/Flashforge Creator 5 0.25 nozzle.json"
|
||||
},
|
||||
{
|
||||
"name": "Flashforge Creator 5 0.4 nozzle",
|
||||
"sub_path": "machine/Flashforge Creator 5 0.4 nozzle.json"
|
||||
@@ -2915,6 +2935,10 @@
|
||||
"name": "Flashforge Creator 5 0.8 nozzle",
|
||||
"sub_path": "machine/Flashforge Creator 5 0.8 nozzle.json"
|
||||
},
|
||||
{
|
||||
"name": "Flashforge Creator 5 Pro 0.25 nozzle",
|
||||
"sub_path": "machine/Flashforge Creator 5 Pro 0.25 nozzle.json"
|
||||
},
|
||||
{
|
||||
"name": "Flashforge Creator 5 Pro 0.4 nozzle",
|
||||
"sub_path": "machine/Flashforge Creator 5 Pro 0.4 nozzle.json"
|
||||
|
||||
@@ -87,6 +87,12 @@
|
||||
"support_material_interface_fan_speed": [
|
||||
"90"
|
||||
],
|
||||
"supertack_plate_temp": [
|
||||
"60"
|
||||
],
|
||||
"supertack_plate_temp_initial_layer": [
|
||||
"60"
|
||||
],
|
||||
"temperature_vitrification": [
|
||||
"70"
|
||||
]
|
||||
|
||||
@@ -93,6 +93,12 @@
|
||||
"support_material_interface_fan_speed": [
|
||||
"90"
|
||||
],
|
||||
"supertack_plate_temp": [
|
||||
"60"
|
||||
],
|
||||
"supertack_plate_temp_initial_layer": [
|
||||
"60"
|
||||
],
|
||||
"temperature_vitrification": [
|
||||
"70"
|
||||
],
|
||||
|
||||
@@ -90,6 +90,12 @@
|
||||
"support_material_interface_fan_speed": [
|
||||
"90"
|
||||
],
|
||||
"supertack_plate_temp": [
|
||||
"60"
|
||||
],
|
||||
"supertack_plate_temp_initial_layer": [
|
||||
"60"
|
||||
],
|
||||
"temperature_vitrification": [
|
||||
"70"
|
||||
]
|
||||
|
||||
@@ -96,6 +96,12 @@
|
||||
"support_material_interface_fan_speed": [
|
||||
"90"
|
||||
],
|
||||
"supertack_plate_temp": [
|
||||
"60"
|
||||
],
|
||||
"supertack_plate_temp_initial_layer": [
|
||||
"60"
|
||||
],
|
||||
"temperature_vitrification": [
|
||||
"70"
|
||||
],
|
||||
|
||||
@@ -90,6 +90,12 @@
|
||||
"support_material_interface_fan_speed": [
|
||||
"90"
|
||||
],
|
||||
"supertack_plate_temp": [
|
||||
"60"
|
||||
],
|
||||
"supertack_plate_temp_initial_layer": [
|
||||
"60"
|
||||
],
|
||||
"temperature_vitrification": [
|
||||
"70"
|
||||
]
|
||||
|
||||
@@ -96,6 +96,12 @@
|
||||
"support_material_interface_fan_speed": [
|
||||
"90"
|
||||
],
|
||||
"supertack_plate_temp": [
|
||||
"60"
|
||||
],
|
||||
"supertack_plate_temp_initial_layer": [
|
||||
"60"
|
||||
],
|
||||
"temperature_vitrification": [
|
||||
"70"
|
||||
],
|
||||
|
||||
@@ -28,6 +28,12 @@
|
||||
"textured_plate_temp_initial_layer": [
|
||||
"85"
|
||||
],
|
||||
"supertack_plate_temp": [
|
||||
"60"
|
||||
],
|
||||
"supertack_plate_temp_initial_layer": [
|
||||
"60"
|
||||
],
|
||||
"slow_down_for_layer_cooling": [
|
||||
"1"
|
||||
],
|
||||
|
||||
@@ -0,0 +1,311 @@
|
||||
{
|
||||
"type": "machine",
|
||||
"name": "Flashforge Creator 5 0.25 nozzle",
|
||||
"inherits": "Flashforge Adventurer 5M Pro 0.4 Nozzle",
|
||||
"from": "system",
|
||||
"setting_id": "xp3cpTEGYdWjcrMM",
|
||||
"instantiation": "true",
|
||||
"adaptive_bed_mesh_margin": "0",
|
||||
"auxiliary_fan": "1",
|
||||
"bbl_use_printhost": "0",
|
||||
"bed_custom_model": "",
|
||||
"bed_custom_texture": "",
|
||||
"bed_exclude_area": [
|
||||
"0x0"
|
||||
],
|
||||
"bed_mesh_max": "99999,99999",
|
||||
"bed_mesh_min": "-99999,-99999",
|
||||
"bed_mesh_probe_distance": "50,50",
|
||||
"before_layer_change_gcode": ";BEFORE_LAYER_CHANGE\n;[layer_z]",
|
||||
"best_object_pos": "0.5,0.5",
|
||||
"change_extrusion_role_gcode": "",
|
||||
"change_filament_gcode": "",
|
||||
"cooling_tube_length": "0",
|
||||
"cooling_tube_retraction": "0",
|
||||
"default_bed_type": "",
|
||||
"default_filament_profile": [
|
||||
"Flashforge Generic PLA"
|
||||
],
|
||||
"default_print_profile": "0.12mm Standard @FF C5 0.25 nozzle",
|
||||
"deretraction_speed": [
|
||||
"30",
|
||||
"30",
|
||||
"30",
|
||||
"30"
|
||||
],
|
||||
"disable_m73": "1",
|
||||
"emit_machine_limits_to_gcode": "1",
|
||||
"enable_filament_ramming": "0",
|
||||
"enable_long_retraction_when_cut": "0",
|
||||
"extra_loading_move": "0",
|
||||
"extruder_clearance_height_to_lid": "360",
|
||||
"extruder_clearance_height_to_rod": "60",
|
||||
"extruder_clearance_radius": "92",
|
||||
"extruder_colour": [
|
||||
"#FCE94F",
|
||||
"#FCE94F",
|
||||
"#FCE94F",
|
||||
"#FCE94F"
|
||||
],
|
||||
"extruder_offset": [
|
||||
"0x0",
|
||||
"0x0",
|
||||
"0x0",
|
||||
"0x0"
|
||||
],
|
||||
"fan_kickstart": "0",
|
||||
"fan_speedup_overhangs": "1",
|
||||
"fan_speedup_time": "0",
|
||||
"gcode_flavor": "klipper",
|
||||
"head_wrap_detect_zone": [],
|
||||
"high_current_on_filament_swap": "0",
|
||||
"host_type": "octoprint",
|
||||
"layer_change_gcode": ";AFTER_LAYER_CHANGE\n;[layer_z]",
|
||||
"long_retractions_when_cut": [
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0"
|
||||
],
|
||||
"machine_end_gcode": ";end_gcode\nG1 X150 Y150 E-1.2 F12000",
|
||||
"machine_load_filament_time": "0",
|
||||
"machine_max_acceleration_e": [
|
||||
"5000",
|
||||
"5000"
|
||||
],
|
||||
"machine_max_acceleration_extruding": [
|
||||
"30000",
|
||||
"20000"
|
||||
],
|
||||
"machine_max_acceleration_retracting": [
|
||||
"5000",
|
||||
"5000"
|
||||
],
|
||||
"machine_max_acceleration_travel": [
|
||||
"20000",
|
||||
"20000"
|
||||
],
|
||||
"machine_max_acceleration_x": [
|
||||
"30000",
|
||||
"20000"
|
||||
],
|
||||
"machine_max_acceleration_y": [
|
||||
"30000",
|
||||
"20000"
|
||||
],
|
||||
"machine_max_acceleration_z": [
|
||||
"300",
|
||||
"500"
|
||||
],
|
||||
"machine_max_jerk_e": [
|
||||
"2.5",
|
||||
"2.5"
|
||||
],
|
||||
"machine_max_jerk_x": [
|
||||
"9",
|
||||
"9"
|
||||
],
|
||||
"machine_max_jerk_y": [
|
||||
"9",
|
||||
"9"
|
||||
],
|
||||
"machine_max_jerk_z": [
|
||||
"3",
|
||||
"3"
|
||||
],
|
||||
"machine_max_junction_deviation": [
|
||||
"0",
|
||||
"0"
|
||||
],
|
||||
"machine_max_speed_e": [
|
||||
"30",
|
||||
"30"
|
||||
],
|
||||
"machine_max_speed_x": [
|
||||
"600",
|
||||
"600"
|
||||
],
|
||||
"machine_max_speed_y": [
|
||||
"600",
|
||||
"600"
|
||||
],
|
||||
"machine_max_speed_z": [
|
||||
"20",
|
||||
"20"
|
||||
],
|
||||
"machine_min_extruding_rate": [
|
||||
"0",
|
||||
"0"
|
||||
],
|
||||
"machine_min_travel_rate": [
|
||||
"0",
|
||||
"0"
|
||||
],
|
||||
"machine_pause_gcode": "M25",
|
||||
"machine_start_gcode": ";start_gcode\nM140 S[bed_temperature_initial_layer_single]\nM106 P101 S0 ; L+R_PLA_Turbo_Fan_0-255\nM106 P2 S0 ; Center_Fresch_Air_Input_Fan_for_PLA30%_(80_0-255) \nM191 S0 ; Chamber temp. max65C\nM106 S0 ; Model_Fan_(Heat_Break_Cooler_80-255)100%=255\nM106 P3 S0 ; Filter_Unit_Fan_0-255(ABS=255)\nM104 S[nozzle_temperature_initial_layer]\nG90\nM83\nG1 Z5 F2400\nT[initial_extruder]\nM109 S[nozzle_temperature_initial_layer] T[initial_extruder]\nG1 X256 Y0 Z0.2 F6000\nG1 E5 F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60}\nG1 X216 E10 F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60}\n;start_gcode end",
|
||||
"machine_tool_change_time": "7",
|
||||
"machine_unload_filament_time": "0",
|
||||
"manual_filament_change": "0",
|
||||
"max_layer_height": [
|
||||
"0.14",
|
||||
"0.14",
|
||||
"0.14",
|
||||
"0.14"
|
||||
],
|
||||
"max_resonance_avoidance_speed": "120",
|
||||
"min_layer_height": [
|
||||
"0.08",
|
||||
"0.08",
|
||||
"0.08",
|
||||
"0.08"
|
||||
],
|
||||
"min_resonance_avoidance_speed": "70",
|
||||
"nozzle_diameter": [
|
||||
"0.25",
|
||||
"0.25",
|
||||
"0.25",
|
||||
"0.25"
|
||||
],
|
||||
"nozzle_height": "4",
|
||||
"nozzle_hrc": "0",
|
||||
"nozzle_type": "hardened_steel",
|
||||
"nozzle_volume": "0",
|
||||
"parking_pos_retraction": "0",
|
||||
"pellet_modded_printer": "0",
|
||||
"preferred_orientation": "0",
|
||||
"printable_area": [
|
||||
"0x0",
|
||||
"256x0",
|
||||
"256x256",
|
||||
"0x256"
|
||||
],
|
||||
"printable_height": "256",
|
||||
"printer_model": "Flashforge Creator 5",
|
||||
"printer_notes": "",
|
||||
"printer_settings_id": "Flashforge Creator 5 0.25 nozzle",
|
||||
"printer_structure": "corexy",
|
||||
"printer_technology": "FFF",
|
||||
"printer_variant": "0.25",
|
||||
"printhost_authorization_type": "key",
|
||||
"printhost_ssl_ignore_revoke": "0",
|
||||
"printing_by_object_gcode": "",
|
||||
"purge_in_prime_tower": "0",
|
||||
"resonance_avoidance": "0",
|
||||
"retract_before_wipe": [
|
||||
"100%",
|
||||
"100%",
|
||||
"100%",
|
||||
"100%"
|
||||
],
|
||||
"retract_length_toolchange": [
|
||||
"3",
|
||||
"3",
|
||||
"3",
|
||||
"3"
|
||||
],
|
||||
"retract_lift_above": [
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0"
|
||||
],
|
||||
"retract_lift_below": [
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0"
|
||||
],
|
||||
"retract_lift_enforce": [
|
||||
"All Surfaces",
|
||||
"All Surfaces",
|
||||
"All Surfaces",
|
||||
"All Surfaces"
|
||||
],
|
||||
"retract_restart_extra": [
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0"
|
||||
],
|
||||
"retract_restart_extra_toolchange": [
|
||||
"-0.8",
|
||||
"-0.8",
|
||||
"-0.8",
|
||||
"-0.8"
|
||||
],
|
||||
"retract_when_changing_layer": [
|
||||
"1",
|
||||
"1",
|
||||
"1",
|
||||
"1"
|
||||
],
|
||||
"retraction_distances_when_cut": [
|
||||
"18",
|
||||
"18",
|
||||
"18",
|
||||
"18"
|
||||
],
|
||||
"retraction_length": [
|
||||
"0.8",
|
||||
"0.8",
|
||||
"0.8",
|
||||
"0.8"
|
||||
],
|
||||
"retraction_minimum_travel": [
|
||||
"2",
|
||||
"2",
|
||||
"2",
|
||||
"2"
|
||||
],
|
||||
"retraction_speed": [
|
||||
"30",
|
||||
"30",
|
||||
"30",
|
||||
"30"
|
||||
],
|
||||
"scan_first_layer": "0",
|
||||
"silent_mode": "0",
|
||||
"single_extruder_multi_material": "0",
|
||||
"support_air_filtration": "0",
|
||||
"support_chamber_temp_control": "0",
|
||||
"support_multi_bed_types": "1",
|
||||
"template_custom_gcode": "",
|
||||
"thumbnails": "140x110/PNG",
|
||||
"thumbnails_format": "PNG",
|
||||
"time_cost": "0",
|
||||
"time_lapse_gcode": "",
|
||||
"travel_slope": [
|
||||
"3",
|
||||
"3",
|
||||
"3",
|
||||
"3"
|
||||
],
|
||||
"upward_compatible_machine": [],
|
||||
"use_firmware_retraction": "0",
|
||||
"use_relative_e_distances": "1",
|
||||
"wipe": [
|
||||
"1",
|
||||
"1",
|
||||
"1",
|
||||
"1"
|
||||
],
|
||||
"wipe_distance": [
|
||||
"2",
|
||||
"2",
|
||||
"2",
|
||||
"2"
|
||||
],
|
||||
"z_hop": [
|
||||
"0.4",
|
||||
"0.4",
|
||||
"0.4",
|
||||
"0.4"
|
||||
],
|
||||
"z_hop_types": [
|
||||
"Auto Lift",
|
||||
"Auto Lift",
|
||||
"Auto Lift",
|
||||
"Auto Lift"
|
||||
],
|
||||
"z_offset": "0"
|
||||
}
|
||||
@@ -0,0 +1,311 @@
|
||||
{
|
||||
"type": "machine",
|
||||
"name": "Flashforge Creator 5 Pro 0.25 nozzle",
|
||||
"inherits": "Flashforge Adventurer 5M Pro 0.4 Nozzle",
|
||||
"from": "system",
|
||||
"setting_id": "rpmib7bIKa85LNMR",
|
||||
"instantiation": "true",
|
||||
"adaptive_bed_mesh_margin": "0",
|
||||
"auxiliary_fan": "1",
|
||||
"bbl_use_printhost": "0",
|
||||
"bed_custom_model": "",
|
||||
"bed_custom_texture": "",
|
||||
"bed_exclude_area": [
|
||||
"0x0"
|
||||
],
|
||||
"bed_mesh_max": "99999,99999",
|
||||
"bed_mesh_min": "-99999,-99999",
|
||||
"bed_mesh_probe_distance": "50,50",
|
||||
"before_layer_change_gcode": ";BEFORE_LAYER_CHANGE\n;[layer_z]",
|
||||
"best_object_pos": "0.5,0.5",
|
||||
"change_extrusion_role_gcode": "",
|
||||
"change_filament_gcode": "",
|
||||
"cooling_tube_length": "0",
|
||||
"cooling_tube_retraction": "0",
|
||||
"default_bed_type": "",
|
||||
"default_filament_profile": [
|
||||
"Flashforge Generic PLA"
|
||||
],
|
||||
"default_print_profile": "0.12mm Standard @FF C5 0.25 nozzle",
|
||||
"deretraction_speed": [
|
||||
"30",
|
||||
"30",
|
||||
"30",
|
||||
"30"
|
||||
],
|
||||
"disable_m73": "1",
|
||||
"emit_machine_limits_to_gcode": "1",
|
||||
"enable_filament_ramming": "0",
|
||||
"enable_long_retraction_when_cut": "0",
|
||||
"extra_loading_move": "0",
|
||||
"extruder_clearance_height_to_lid": "360",
|
||||
"extruder_clearance_height_to_rod": "60",
|
||||
"extruder_clearance_radius": "92",
|
||||
"extruder_colour": [
|
||||
"#FCE94F",
|
||||
"#FCE94F",
|
||||
"#FCE94F",
|
||||
"#FCE94F"
|
||||
],
|
||||
"extruder_offset": [
|
||||
"0x0",
|
||||
"0x0",
|
||||
"0x0",
|
||||
"0x0"
|
||||
],
|
||||
"fan_kickstart": "0",
|
||||
"fan_speedup_overhangs": "1",
|
||||
"fan_speedup_time": "0",
|
||||
"gcode_flavor": "klipper",
|
||||
"head_wrap_detect_zone": [],
|
||||
"high_current_on_filament_swap": "0",
|
||||
"host_type": "octoprint",
|
||||
"layer_change_gcode": ";AFTER_LAYER_CHANGE\n;[layer_z]",
|
||||
"long_retractions_when_cut": [
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0"
|
||||
],
|
||||
"machine_end_gcode": ";end_gcode\nG1 X150 Y150 E-1.2 F12000",
|
||||
"machine_load_filament_time": "0",
|
||||
"machine_max_acceleration_e": [
|
||||
"5000",
|
||||
"5000"
|
||||
],
|
||||
"machine_max_acceleration_extruding": [
|
||||
"30000",
|
||||
"20000"
|
||||
],
|
||||
"machine_max_acceleration_retracting": [
|
||||
"5000",
|
||||
"5000"
|
||||
],
|
||||
"machine_max_acceleration_travel": [
|
||||
"20000",
|
||||
"20000"
|
||||
],
|
||||
"machine_max_acceleration_x": [
|
||||
"30000",
|
||||
"20000"
|
||||
],
|
||||
"machine_max_acceleration_y": [
|
||||
"30000",
|
||||
"20000"
|
||||
],
|
||||
"machine_max_acceleration_z": [
|
||||
"300",
|
||||
"500"
|
||||
],
|
||||
"machine_max_jerk_e": [
|
||||
"2.5",
|
||||
"2.5"
|
||||
],
|
||||
"machine_max_jerk_x": [
|
||||
"9",
|
||||
"9"
|
||||
],
|
||||
"machine_max_jerk_y": [
|
||||
"9",
|
||||
"9"
|
||||
],
|
||||
"machine_max_jerk_z": [
|
||||
"3",
|
||||
"3"
|
||||
],
|
||||
"machine_max_junction_deviation": [
|
||||
"0",
|
||||
"0"
|
||||
],
|
||||
"machine_max_speed_e": [
|
||||
"30",
|
||||
"30"
|
||||
],
|
||||
"machine_max_speed_x": [
|
||||
"600",
|
||||
"600"
|
||||
],
|
||||
"machine_max_speed_y": [
|
||||
"600",
|
||||
"600"
|
||||
],
|
||||
"machine_max_speed_z": [
|
||||
"20",
|
||||
"20"
|
||||
],
|
||||
"machine_min_extruding_rate": [
|
||||
"0",
|
||||
"0"
|
||||
],
|
||||
"machine_min_travel_rate": [
|
||||
"0",
|
||||
"0"
|
||||
],
|
||||
"machine_pause_gcode": "M25",
|
||||
"machine_start_gcode": ";start_gcode\nM140 S[bed_temperature_initial_layer_single]\nM106 P101 S0 ; L+R_PLA_Turbo_Fan_0-255\nM106 P2 S0 ; Center_Fresch_Air_Input_Fan_for_PLA30%_(80_0-255) \nM191 S0 ; Chamber temp. max65C\nM106 S0 ; Model_Fan_(Heat_Break_Cooler_80-255)100%=255\nM106 P3 S0 ; Filter_Unit_Fan_0-255(ABS=255)\nM104 S[nozzle_temperature_initial_layer]\nG90\nM83\nG1 Z5 F2400\nT[initial_extruder]\nM109 S[nozzle_temperature_initial_layer] T[initial_extruder]\nG1 X256 Y0 Z0.2 F6000\nG1 E5 F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60}\nG1 X216 E10 F{filament_max_volumetric_speed[initial_no_support_extruder]/2.4053*60}\n;start_gcode end",
|
||||
"machine_tool_change_time": "7",
|
||||
"machine_unload_filament_time": "0",
|
||||
"manual_filament_change": "0",
|
||||
"max_layer_height": [
|
||||
"0.14",
|
||||
"0.14",
|
||||
"0.14",
|
||||
"0.14"
|
||||
],
|
||||
"max_resonance_avoidance_speed": "120",
|
||||
"min_layer_height": [
|
||||
"0.08",
|
||||
"0.08",
|
||||
"0.08",
|
||||
"0.08"
|
||||
],
|
||||
"min_resonance_avoidance_speed": "70",
|
||||
"nozzle_diameter": [
|
||||
"0.25",
|
||||
"0.25",
|
||||
"0.25",
|
||||
"0.25"
|
||||
],
|
||||
"nozzle_height": "4",
|
||||
"nozzle_hrc": "0",
|
||||
"nozzle_type": "hardened_steel",
|
||||
"nozzle_volume": "0",
|
||||
"parking_pos_retraction": "0",
|
||||
"pellet_modded_printer": "0",
|
||||
"preferred_orientation": "0",
|
||||
"printable_area": [
|
||||
"0x0",
|
||||
"256x0",
|
||||
"256x256",
|
||||
"0x256"
|
||||
],
|
||||
"printable_height": "256",
|
||||
"printer_model": "Flashforge Creator 5 Pro",
|
||||
"printer_notes": "",
|
||||
"printer_settings_id": "Flashforge Creator 5 Pro 0.25 nozzle",
|
||||
"printer_structure": "corexy",
|
||||
"printer_technology": "FFF",
|
||||
"printer_variant": "0.25",
|
||||
"printhost_authorization_type": "key",
|
||||
"printhost_ssl_ignore_revoke": "0",
|
||||
"printing_by_object_gcode": "",
|
||||
"purge_in_prime_tower": "0",
|
||||
"resonance_avoidance": "0",
|
||||
"retract_before_wipe": [
|
||||
"100%",
|
||||
"100%",
|
||||
"100%",
|
||||
"100%"
|
||||
],
|
||||
"retract_length_toolchange": [
|
||||
"3",
|
||||
"3",
|
||||
"3",
|
||||
"3"
|
||||
],
|
||||
"retract_lift_above": [
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0"
|
||||
],
|
||||
"retract_lift_below": [
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0"
|
||||
],
|
||||
"retract_lift_enforce": [
|
||||
"All Surfaces",
|
||||
"All Surfaces",
|
||||
"All Surfaces",
|
||||
"All Surfaces"
|
||||
],
|
||||
"retract_restart_extra": [
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"0"
|
||||
],
|
||||
"retract_restart_extra_toolchange": [
|
||||
"-0.8",
|
||||
"-0.8",
|
||||
"-0.8",
|
||||
"-0.8"
|
||||
],
|
||||
"retract_when_changing_layer": [
|
||||
"1",
|
||||
"1",
|
||||
"1",
|
||||
"1"
|
||||
],
|
||||
"retraction_distances_when_cut": [
|
||||
"18",
|
||||
"18",
|
||||
"18",
|
||||
"18"
|
||||
],
|
||||
"retraction_length": [
|
||||
"0.8",
|
||||
"0.8",
|
||||
"0.8",
|
||||
"0.8"
|
||||
],
|
||||
"retraction_minimum_travel": [
|
||||
"2",
|
||||
"2",
|
||||
"2",
|
||||
"2"
|
||||
],
|
||||
"retraction_speed": [
|
||||
"30",
|
||||
"30",
|
||||
"30",
|
||||
"30"
|
||||
],
|
||||
"scan_first_layer": "0",
|
||||
"silent_mode": "0",
|
||||
"single_extruder_multi_material": "0",
|
||||
"support_air_filtration": "1",
|
||||
"support_chamber_temp_control": "1",
|
||||
"support_multi_bed_types": "1",
|
||||
"template_custom_gcode": "",
|
||||
"thumbnails": "140x110/PNG",
|
||||
"thumbnails_format": "PNG",
|
||||
"time_cost": "0",
|
||||
"time_lapse_gcode": "",
|
||||
"travel_slope": [
|
||||
"3",
|
||||
"3",
|
||||
"3",
|
||||
"3"
|
||||
],
|
||||
"upward_compatible_machine": [],
|
||||
"use_firmware_retraction": "0",
|
||||
"use_relative_e_distances": "1",
|
||||
"wipe": [
|
||||
"1",
|
||||
"1",
|
||||
"1",
|
||||
"1"
|
||||
],
|
||||
"wipe_distance": [
|
||||
"2",
|
||||
"2",
|
||||
"2",
|
||||
"2"
|
||||
],
|
||||
"z_hop": [
|
||||
"0.4",
|
||||
"0.4",
|
||||
"0.4",
|
||||
"0.4"
|
||||
],
|
||||
"z_hop_types": [
|
||||
"Auto Lift",
|
||||
"Auto Lift",
|
||||
"Auto Lift",
|
||||
"Auto Lift"
|
||||
],
|
||||
"z_offset": "0"
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
"type": "machine_model",
|
||||
"name": "Flashforge Creator 5 Pro",
|
||||
"model_id": "Flashforge-Creator-5-Pro",
|
||||
"nozzle_diameter": "0.4;0.6;0.8",
|
||||
"nozzle_diameter": "0.25;0.4;0.6;0.8",
|
||||
"machine_tech": "FFF",
|
||||
"family": "Flashforge",
|
||||
"bed_model": "flashforge_c5_buildplate_model.stl",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"type": "machine_model",
|
||||
"name": "Flashforge Creator 5",
|
||||
"model_id": "Flashforge-Creator-5",
|
||||
"nozzle_diameter": "0.4;0.6;0.8",
|
||||
"nozzle_diameter": "0.25;0.4;0.6;0.8",
|
||||
"machine_tech": "FFF",
|
||||
"family": "Flashforge",
|
||||
"bed_model": "flashforge_c5_buildplate_model.stl",
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"type": "process",
|
||||
"name": "0.08mm Standard @FF C5 0.25 nozzle",
|
||||
"inherits": "0.10mm Standard @FF AD5X 0.25 nozzle",
|
||||
"from": "system",
|
||||
"setting_id": "KrOSCGKyvNy9v08u",
|
||||
"instantiation": "true",
|
||||
"bottom_solid_infill_flow_ratio": "1",
|
||||
"compatible_printers": [
|
||||
"Flashforge Creator 5 0.25 nozzle",
|
||||
"Flashforge Creator 5 Pro 0.25 nozzle"
|
||||
],
|
||||
"initial_layer_print_height": "0.1",
|
||||
"internal_bridge_flow": "1",
|
||||
"layer_height": "0.08",
|
||||
"ooze_prevention": "1",
|
||||
"preheat_time": "20",
|
||||
"print_extruder_id": [
|
||||
"1"
|
||||
],
|
||||
"print_extruder_variant": [
|
||||
"Direct Drive Standard"
|
||||
],
|
||||
"print_settings_id": "0.08mm Standard @FF C5 0.25 nozzle",
|
||||
"small_perimeter_speed": "30",
|
||||
"standby_temperature_delta": "-100",
|
||||
"top_solid_infill_flow_ratio": "1"
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"type": "process",
|
||||
"name": "0.10mm Standard @FF C5 0.25 nozzle",
|
||||
"inherits": "0.10mm Standard @FF AD5X 0.25 nozzle",
|
||||
"from": "system",
|
||||
"setting_id": "0Mep1gVTvD4RwK53",
|
||||
"instantiation": "true",
|
||||
"bottom_solid_infill_flow_ratio": "1",
|
||||
"compatible_printers": [
|
||||
"Flashforge Creator 5 0.25 nozzle",
|
||||
"Flashforge Creator 5 Pro 0.25 nozzle"
|
||||
],
|
||||
"initial_layer_print_height": "0.1",
|
||||
"internal_bridge_flow": "1",
|
||||
"ooze_prevention": "1",
|
||||
"preheat_time": "20",
|
||||
"print_extruder_id": [
|
||||
"1"
|
||||
],
|
||||
"print_extruder_variant": [
|
||||
"Direct Drive Standard"
|
||||
],
|
||||
"print_settings_id": "0.10mm Standard @FF C5 0.25 nozzle",
|
||||
"small_perimeter_speed": "30",
|
||||
"standby_temperature_delta": "-100",
|
||||
"top_solid_infill_flow_ratio": "1"
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"type": "process",
|
||||
"name": "0.12mm Standard @FF C5 0.25 nozzle",
|
||||
"inherits": "0.10mm Standard @FF AD5X 0.25 nozzle",
|
||||
"from": "system",
|
||||
"setting_id": "rcKQBKZJvCfrfzqV",
|
||||
"instantiation": "true",
|
||||
"bottom_solid_infill_flow_ratio": "1",
|
||||
"compatible_printers": [
|
||||
"Flashforge Creator 5 0.25 nozzle",
|
||||
"Flashforge Creator 5 Pro 0.25 nozzle"
|
||||
],
|
||||
"initial_layer_print_height": "0.1",
|
||||
"internal_bridge_flow": "1",
|
||||
"layer_height": "0.12",
|
||||
"ooze_prevention": "1",
|
||||
"preheat_time": "20",
|
||||
"print_extruder_id": [
|
||||
"1"
|
||||
],
|
||||
"print_extruder_variant": [
|
||||
"Direct Drive Standard"
|
||||
],
|
||||
"print_settings_id": "0.12mm Standard @FF C5 0.25 nozzle",
|
||||
"small_perimeter_speed": "30",
|
||||
"standby_temperature_delta": "-100",
|
||||
"top_solid_infill_flow_ratio": "1"
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"type": "process",
|
||||
"name": "0.14mm Standard @FF C5 0.25 nozzle",
|
||||
"inherits": "0.10mm Standard @FF AD5X 0.25 nozzle",
|
||||
"from": "system",
|
||||
"setting_id": "749mQY3CU2jk0MOd",
|
||||
"instantiation": "true",
|
||||
"bottom_solid_infill_flow_ratio": "1",
|
||||
"compatible_printers": [
|
||||
"Flashforge Creator 5 0.25 nozzle",
|
||||
"Flashforge Creator 5 Pro 0.25 nozzle"
|
||||
],
|
||||
"initial_layer_print_height": "0.1",
|
||||
"internal_bridge_flow": "1",
|
||||
"layer_height": "0.14",
|
||||
"ooze_prevention": "1",
|
||||
"preheat_time": "20",
|
||||
"print_extruder_id": [
|
||||
"1"
|
||||
],
|
||||
"print_extruder_variant": [
|
||||
"Direct Drive Standard"
|
||||
],
|
||||
"print_settings_id": "0.14mm Standard @FF C5 0.25 nozzle",
|
||||
"small_perimeter_speed": "30",
|
||||
"standby_temperature_delta": "-100",
|
||||
"top_solid_infill_flow_ratio": "1"
|
||||
}
|
||||
@@ -8,6 +8,9 @@
|
||||
"box_temperature_range_high": [
|
||||
"45"
|
||||
],
|
||||
"chamber_temperature": [
|
||||
"55"
|
||||
],
|
||||
"close_fan_the_first_x_layers": [
|
||||
"3"
|
||||
],
|
||||
|
||||
@@ -14,9 +14,15 @@
|
||||
"box_temperature": [
|
||||
"55"
|
||||
],
|
||||
"chamber_temperature": [
|
||||
"55"
|
||||
],
|
||||
"close_fan_the_first_x_layers": [
|
||||
"3"
|
||||
],
|
||||
"during_print_exhaust_fan_speed": [
|
||||
"0"
|
||||
],
|
||||
"cool_plate_temp_initial_layer": [
|
||||
"60"
|
||||
],
|
||||
|
||||
@@ -14,9 +14,15 @@
|
||||
"box_temperature": [
|
||||
"60"
|
||||
],
|
||||
"chamber_temperature": [
|
||||
"55"
|
||||
],
|
||||
"close_fan_the_first_x_layers": [
|
||||
"3"
|
||||
],
|
||||
"during_print_exhaust_fan_speed": [
|
||||
"0"
|
||||
],
|
||||
"cool_plate_temp_initial_layer": [
|
||||
"80"
|
||||
],
|
||||
|
||||
@@ -14,9 +14,15 @@
|
||||
"box_temperature": [
|
||||
"60"
|
||||
],
|
||||
"chamber_temperature": [
|
||||
"55"
|
||||
],
|
||||
"close_fan_the_first_x_layers": [
|
||||
"3"
|
||||
],
|
||||
"during_print_exhaust_fan_speed": [
|
||||
"0"
|
||||
],
|
||||
"cool_plate_temp_initial_layer": [
|
||||
"80"
|
||||
],
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
"box_temperature": [
|
||||
"65"
|
||||
],
|
||||
"chamber_temperatures": [
|
||||
"0"
|
||||
"chamber_temperature": [
|
||||
"55"
|
||||
],
|
||||
"close_fan_the_first_x_layers": [
|
||||
"3"
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
"box_temperature": [
|
||||
"60"
|
||||
],
|
||||
"chamber_temperature": [
|
||||
"55"
|
||||
],
|
||||
"close_fan_the_first_x_layers": [
|
||||
"3"
|
||||
],
|
||||
|
||||
+143
-29
@@ -53,6 +53,7 @@ using namespace nlohmann;
|
||||
|
||||
#include "libslic3r/libslic3r.h"
|
||||
#include "libslic3r/Config.hpp"
|
||||
#include "libslic3r/Preset.hpp"
|
||||
#include "libslic3r/Geometry.hpp"
|
||||
#include "libslic3r/GCode.hpp"
|
||||
#include "libslic3r/Model.hpp"
|
||||
@@ -1466,6 +1467,10 @@ int CLI::run(int argc, char **argv)
|
||||
std::vector<std::string> upward_compatible_printers, new_print_compatible_printers, current_print_compatible_printers, current_different_settings;
|
||||
std::vector<std::string> current_filaments_name, current_filaments_system_name, current_inherits_group, current_extruder_variants, new_extruder_variants, current_print_extruder_variants, new_printer_extruder_variants;
|
||||
DynamicPrintConfig load_process_config, load_machine_config;
|
||||
//ORCA: full configs of the "current" (3MF-embedded) process/printer presets, kept so that
|
||||
// compatible_printers_condition can be evaluated for them below. Previously only the
|
||||
// literal compatible_printers list was extracted.
|
||||
DynamicPrintConfig current_process_full_config, current_printer_full_config;
|
||||
bool new_process_config_is_system = true, new_printer_config_is_system = true;
|
||||
std::string pipe_name, makerlab_name, makerlab_version, different_process_setting;
|
||||
const std::vector<std::string> &metadata_name = m_config.option<ConfigOptionStrings>("metadata_name", true)->values;
|
||||
@@ -2046,6 +2051,51 @@ int CLI::run(int argc, char **argv)
|
||||
error, allow_source_manifest);
|
||||
};
|
||||
|
||||
//ORCA: list the keys a user preset overrides relative to its system parent, for the
|
||||
// `different_settings_to_system` column of an exported 3MF. Without it the CLI
|
||||
// writes an empty column, so re-opening a CLI-exported project in the GUI shows
|
||||
// spurious "unsaved changes" and can revert inherited process/filament/machine
|
||||
// values to system defaults.
|
||||
//
|
||||
// The parent comes from the preset bundle that inherits resolution already builds,
|
||||
// so this adds no extra loading. Returns "" whenever the parent cannot be resolved,
|
||||
// which is exactly the previous behaviour.
|
||||
auto cli_different_settings = [&ensure_cli_preset_bundle](const DynamicPrintConfig &resolved,
|
||||
const std::string &parent_name,
|
||||
Preset::Type type) -> std::string {
|
||||
if (parent_name.empty())
|
||||
return std::string();
|
||||
std::string error;
|
||||
PresetBundle *bundle = ensure_cli_preset_bundle(error);
|
||||
if (bundle == nullptr) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "CLI: no preset bundle for different_settings_to_system: " << error;
|
||||
return std::string();
|
||||
}
|
||||
const PresetCollection *collection = nullptr;
|
||||
switch (type) {
|
||||
case Preset::TYPE_PRINT: collection = &bundle->prints; break;
|
||||
case Preset::TYPE_FILAMENT: collection = &bundle->filaments; break;
|
||||
case Preset::TYPE_PRINTER: collection = &bundle->printers; break;
|
||||
default: return std::string();
|
||||
}
|
||||
const Preset *parent = collection->find_preset2(parent_name, true);
|
||||
if (parent == nullptr) {
|
||||
BOOST_LOG_TRIVIAL(warning) << boost::format("CLI: parent preset '%1%' not found; leaving different_settings_to_system empty")%parent_name;
|
||||
return std::string();
|
||||
}
|
||||
std::vector<std::string> keys = resolved.diff(parent->config);
|
||||
//ORCA: preset metadata, not user-tunable settings. compatible_printers /
|
||||
// compatible_prints have their own tracking columns and would double-count.
|
||||
keys.erase(std::remove_if(keys.begin(), keys.end(), [](const std::string &k) {
|
||||
return k == "inherits" || k == "compatible_printers" || k == "compatible_prints"
|
||||
|| k == "compatible_printers_condition" || k == "compatible_prints_condition"
|
||||
|| k == "print_settings_id" || k == "filament_settings_id" || k == "printer_settings_id";
|
||||
}),
|
||||
keys.end());
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("CLI: %1% overrides vs parent '%2%'")%keys.size()%parent_name;
|
||||
return Slic3r::escape_strings_cstyle(keys);
|
||||
};
|
||||
|
||||
auto load_config_file = [&resolve_preset](const std::string& file, DynamicPrintConfig& config, std::string& config_type,
|
||||
std::string& config_name, std::string& filament_id, std::string& config_from) {
|
||||
if (! boost::filesystem::exists(file)) {
|
||||
@@ -2635,6 +2685,8 @@ int CLI::run(int argc, char **argv)
|
||||
flush_and_exit(ret);
|
||||
}
|
||||
upward_compatible_printers = config.option<ConfigOptionStrings>("upward_compatible_machine", true)->values;
|
||||
//ORCA: keep the full config so compatible_printers_condition can be evaluated against it below
|
||||
current_printer_full_config = std::move(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2657,6 +2709,8 @@ int CLI::run(int argc, char **argv)
|
||||
flush_and_exit(ret);
|
||||
}
|
||||
current_print_compatible_printers = config.option<ConfigOptionStrings>("compatible_printers", true)->values;
|
||||
//ORCA: keep the full config so compatible_printers_condition can be evaluated against it below
|
||||
current_process_full_config = std::move(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2675,46 +2729,88 @@ int CLI::run(int argc, char **argv)
|
||||
for (int index = 0; index < upward_compatible_printers.size(); index++) {
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("index %1%, upward_compatible_printers %2%")%index %upward_compatible_printers[index];
|
||||
}
|
||||
//ORCA: Replace the four manual equality-loop checks below with is_compatible_with_printer(), the
|
||||
// same helper the GUI uses, which also evaluates compatible_printers_condition. Process
|
||||
// profiles that declare compatibility via condition only -- leaving compatible_printers
|
||||
// empty -- were always reported incompatible by the literal-name match, so a CLI slice with
|
||||
// such a preset exited with CLI_PROCESS_NOT_COMPATIBLE (-17) even though the GUI accepts the
|
||||
// same pair. Behaviour is unchanged where an explicit list exists: is_compatible_with_printer
|
||||
// does the same name match, and returns true when both list and condition are empty (which
|
||||
// matches the "old 3mf, no compatible printers" path below).
|
||||
auto check_compat = [](const DynamicPrintConfig &process_cfg,
|
||||
const DynamicPrintConfig &printer_cfg,
|
||||
const std::string &printer_name) -> bool {
|
||||
return is_compatible_with_printer(process_cfg, Preset::TYPE_PRINT, printer_cfg, printer_name);
|
||||
};
|
||||
|
||||
//ORCA: a 3MF's project config does not carry compatible_printers / compatible_printers_condition.
|
||||
// PresetBundle::construct_full_config() erases both and re-emits them as
|
||||
// print_compatible_printers and compatible_machine_expression_group; they are renamed back
|
||||
// only on the PresetBundle load path, which the CLI does not take. Feeding the project config
|
||||
// to the check as-is therefore presents no list and no condition, and
|
||||
// is_compatible_with_printer() reads that as "no constraint" and accepts every printer.
|
||||
// Translate the two keys back. Index 0 of the expression group is the print preset -- the
|
||||
// group is filled print, filaments, printer (PresetBundle.cpp).
|
||||
// The raw keys win whenever they carry something. A project the CLI exported itself has the
|
||||
// real compatible_printers_condition AND an all-empty compatible_machine_expression_group,
|
||||
// so copying the group's first entry unconditionally would overwrite a valid condition with
|
||||
// "" and accept every printer. The renamed keys are only a fallback, and an empty value is
|
||||
// never written over a real one.
|
||||
auto cli_process_compat_config = [](const DynamicPrintConfig &project_cfg) -> DynamicPrintConfig {
|
||||
DynamicPrintConfig cfg = project_cfg;
|
||||
const auto *raw_list = project_cfg.option<ConfigOptionStrings>("compatible_printers");
|
||||
const auto *list = project_cfg.option<ConfigOptionStrings>("print_compatible_printers");
|
||||
if ((raw_list == nullptr || raw_list->values.empty()) && list != nullptr && !list->values.empty())
|
||||
cfg.set_key_value("compatible_printers", new ConfigOptionStrings(list->values));
|
||||
const auto *raw_cond = project_cfg.option<ConfigOptionString>("compatible_printers_condition");
|
||||
const auto *group = project_cfg.option<ConfigOptionStrings>("compatible_machine_expression_group");
|
||||
if ((raw_cond == nullptr || raw_cond->value.empty()) && group != nullptr && !group->values.empty() &&
|
||||
!group->values.front().empty())
|
||||
cfg.set_key_value("compatible_printers_condition", new ConfigOptionString(group->values.front()));
|
||||
return cfg;
|
||||
};
|
||||
if (!new_printer_name.empty()) {
|
||||
if (!new_process_name.empty()) {
|
||||
for (int index = 0; index < new_print_compatible_printers.size(); index++) {
|
||||
if (new_print_compatible_printers[index] == new_printer_system_name) {
|
||||
process_compatible = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//new process + new printer: both configs came from --load-settings
|
||||
process_compatible = check_compat(load_process_config, load_machine_config, new_printer_system_name);
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("new printer %1%, inherited from %2%, new process %3%, inherited from %4% ,compatible %5%")
|
||||
%new_printer_name %new_printer_system_name %new_process_name %new_process_system_name %process_compatible;
|
||||
}
|
||||
else {
|
||||
for (int index = 0; index < current_print_compatible_printers.size(); index++) {
|
||||
if (current_print_compatible_printers[index] == new_printer_system_name) {
|
||||
process_compatible = true;
|
||||
break;
|
||||
}
|
||||
//3MF-embedded process vs new printer. current_process_full_config is only populated from
|
||||
//profiles/BBL/process_full/, so for every other vendor fall back to the 3MF's own project
|
||||
//config in m_print_config, with its renamed compatibility keys translated back (see
|
||||
//cli_process_compat_config above). Without this a 3MF built from a condition-only process
|
||||
//is rejected when re-sliced with the very printer it was made for.
|
||||
{
|
||||
//ORCA: profiles/BBL/{process,machine}_full/ are gitignored and not generated in-tree,
|
||||
// so current_*_full_config is always empty and this fallback is the only live path.
|
||||
const DynamicPrintConfig process_cfg = current_process_full_config.empty()
|
||||
? cli_process_compat_config(m_print_config)
|
||||
: current_process_full_config;
|
||||
process_compatible = check_compat(process_cfg, load_machine_config, new_printer_system_name);
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("new printer %1%, inherited from %2%, old process %3%, inherited from %4% ,compatible %5%")
|
||||
%new_printer_name %new_printer_system_name %current_process_name %current_process_system_name %process_compatible;
|
||||
}
|
||||
}
|
||||
else if (!new_process_name.empty()) {
|
||||
for (int index = 0; index < new_print_compatible_printers.size(); index++) {
|
||||
if (new_print_compatible_printers[index] == current_printer_system_name) {
|
||||
process_compatible = true;
|
||||
break;
|
||||
}
|
||||
//new process vs 3MF-embedded printer. As above, current_printer_full_config only resolves for
|
||||
//BBL profiles; otherwise evaluate against the 3MF's own project config in m_print_config, which
|
||||
//holds the embedded printer's printer_notes / nozzle_diameter.
|
||||
{
|
||||
const DynamicPrintConfig &printer_cfg = current_printer_full_config.empty() ? m_print_config : current_printer_full_config;
|
||||
process_compatible = check_compat(load_process_config, printer_cfg, current_printer_system_name);
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("old printer %1%, inherited from %2%, new process %3%, inherited from %4% ,compatible %5%")
|
||||
%current_printer_name %current_printer_system_name %new_process_name %new_process_system_name %process_compatible;
|
||||
}
|
||||
else {
|
||||
//check the compatible of old printer&&process
|
||||
for (int index = 0; index < current_print_compatible_printers.size(); index++) {
|
||||
if (current_print_compatible_printers[index] == current_printer_system_name) {
|
||||
process_compatible = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//both sides 3MF-embedded (pure reprocess)
|
||||
if (!current_process_full_config.empty() && !current_printer_full_config.empty())
|
||||
process_compatible = check_compat(current_process_full_config, current_printer_full_config, current_printer_system_name);
|
||||
else
|
||||
process_compatible = std::find(current_print_compatible_printers.begin(), current_print_compatible_printers.end(), current_printer_system_name) != current_print_compatible_printers.end();
|
||||
if (!process_compatible && current_print_compatible_printers.empty())
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("old 3mf, no compatible printers, set to compatible");
|
||||
@@ -2937,8 +3033,10 @@ int CLI::run(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
else {
|
||||
//todo: support user machine preset's different settings
|
||||
different_settings[filament_count+1] = "";
|
||||
//ORCA: was a //todo — compute the user's overrides instead of writing an empty column.
|
||||
different_settings[filament_count+1] = new_printer_config_is_system
|
||||
? std::string()
|
||||
: cli_different_settings(load_machine_config, new_printer_system_name, Preset::TYPE_PRINTER);
|
||||
if (new_printer_config_is_system)
|
||||
inherits_group[filament_count+1] = "";
|
||||
else
|
||||
@@ -3080,8 +3178,14 @@ int CLI::run(int argc, char **argv)
|
||||
print_compatible_printers = std::move(current_print_compatible_printers);
|
||||
}
|
||||
else {
|
||||
//todo: support system process preset
|
||||
different_settings[0] = "";
|
||||
//ORCA: was a //todo. Prefer a value the loaded JSON already carried, otherwise
|
||||
// compute the overrides against the system parent.
|
||||
if (!different_process_setting.empty())
|
||||
different_settings[0] = different_process_setting;
|
||||
else
|
||||
different_settings[0] = new_process_config_is_system
|
||||
? std::string()
|
||||
: cli_different_settings(load_process_config, new_process_system_name, Preset::TYPE_PRINT);
|
||||
if (new_process_config_is_system)
|
||||
inherits_group[0] = "";
|
||||
else
|
||||
@@ -3268,6 +3372,16 @@ int CLI::run(int argc, char **argv)
|
||||
int filament_index = load_filaments_index[index];
|
||||
std::vector<std::string> different_keys;
|
||||
|
||||
//ORCA: diff before load_default_gcodes_to_config, the way the process and machine
|
||||
// slots above already do. That call materialises absent gcode keys via
|
||||
// option(..., true), and DynamicConfig::diff only compares keys present in
|
||||
// both configs -- so a gcode key the leaf did not carry would go from "not
|
||||
// compared" to "compared as empty against the parent" and land in the column
|
||||
// as an override the user never made.
|
||||
std::string filament_different_settings;
|
||||
if (load_filament_count > 0)
|
||||
filament_different_settings = cli_different_settings(config, load_filaments_inherit[index], Preset::TYPE_FILAMENT);
|
||||
|
||||
load_default_gcodes_to_config(config, Preset::TYPE_FILAMENT);
|
||||
|
||||
if (load_filament_count > 0) {
|
||||
@@ -3279,8 +3393,8 @@ int CLI::run(int argc, char **argv)
|
||||
opt_filament_settings->set_at(filament_name_setting, filament_index-1, 0);
|
||||
config.erase("filament_settings_id");
|
||||
|
||||
//todo: update different settings of filaments
|
||||
different_settings[filament_index] = "";
|
||||
//ORCA: was a //todo — same treatment as process/machine above.
|
||||
different_settings[filament_index] = filament_different_settings;
|
||||
inherits_group[filament_index] = load_filaments_inherit[index];
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -1006,6 +1006,7 @@ public:
|
||||
int getInt() const override { return this->value; }
|
||||
void setInt(int val) override { this->value = val; }
|
||||
ConfigOption* clone() const override { return new ConfigOptionInt(*this); }
|
||||
using ConfigOptionSingle<int>::operator==;
|
||||
bool operator==(const ConfigOptionInt &rhs) const throw() { return this->value == rhs.value; }
|
||||
|
||||
std::string serialize() const override
|
||||
@@ -1048,6 +1049,7 @@ public:
|
||||
ConfigOptionType type() const override { return static_type(); }
|
||||
ConfigOption* clone() const override { return new ConfigOptionIntsTempl(*this); }
|
||||
ConfigOptionIntsTempl& operator= (const ConfigOption *opt) { this->set(opt); return *this; }
|
||||
using ConfigOptionVector<int>::operator==;
|
||||
bool operator==(const ConfigOptionIntsTempl &rhs) const throw() { return this->values == rhs.values; }
|
||||
bool operator< (const ConfigOptionIntsTempl &rhs) const throw() { return this->values < rhs.values; }
|
||||
// Could a special "nil" value be stored inside the vector, indicating undefined value?
|
||||
@@ -1137,6 +1139,7 @@ public:
|
||||
ConfigOptionType type() const override { return static_type(); }
|
||||
ConfigOption* clone() const override { return new ConfigOptionString(*this); }
|
||||
ConfigOptionString& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
|
||||
using ConfigOptionSingle<std::string>::operator==;
|
||||
bool operator==(const ConfigOptionString &rhs) const throw() { return this->value == rhs.value; }
|
||||
bool operator< (const ConfigOptionString &rhs) const throw() { return this->value < rhs.value; }
|
||||
bool empty() const { return this->value.empty(); }
|
||||
@@ -1171,6 +1174,7 @@ public:
|
||||
ConfigOptionType type() const override { return static_type(); }
|
||||
ConfigOption* clone() const override { return new ConfigOptionStrings(*this); }
|
||||
ConfigOptionStrings& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
|
||||
using ConfigOptionVector<std::string>::operator==;
|
||||
bool operator==(const ConfigOptionStrings &rhs) const throw() { return this->values == rhs.values; }
|
||||
bool operator< (const ConfigOptionStrings &rhs) const throw() { return this->values < rhs.values; }
|
||||
bool is_nil(size_t) const override { return false; }
|
||||
@@ -1215,6 +1219,7 @@ public:
|
||||
ConfigOptionType type() const override { return static_type(); }
|
||||
ConfigOption* clone() const override { return new ConfigOptionPercent(*this); }
|
||||
ConfigOptionPercent& operator= (const ConfigOption *opt) { this->set(opt); return *this; }
|
||||
using ConfigOptionFloat::operator==;
|
||||
bool operator==(const ConfigOptionPercent &rhs) const throw() { return this->value == rhs.value; }
|
||||
bool operator< (const ConfigOptionPercent &rhs) const throw() { return this->value < rhs.value; }
|
||||
|
||||
@@ -1257,6 +1262,7 @@ public:
|
||||
ConfigOptionType type() const override { return static_type(); }
|
||||
ConfigOption* clone() const override { return new ConfigOptionPercentsTempl(*this); }
|
||||
ConfigOptionPercentsTempl& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
|
||||
using ConfigOptionFloatsTempl<NULLABLE>::operator==;
|
||||
bool operator==(const ConfigOptionPercentsTempl &rhs) const throw() { return ConfigOptionFloatsTempl<NULLABLE>::vectors_equal(this->values, rhs.values); }
|
||||
bool operator< (const ConfigOptionPercentsTempl &rhs) const throw() { return ConfigOptionFloatsTempl<NULLABLE>::vectors_lower(this->values, rhs.values); }
|
||||
|
||||
@@ -1502,6 +1508,7 @@ public:
|
||||
ConfigOptionType type() const override { return static_type(); }
|
||||
ConfigOption* clone() const override { return new ConfigOptionPoint(*this); }
|
||||
ConfigOptionPoint& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
|
||||
using ConfigOptionSingle<Vec2d>::operator==;
|
||||
bool operator==(const ConfigOptionPoint &rhs) const throw() { return this->value == rhs.value; }
|
||||
bool operator< (const ConfigOptionPoint &rhs) const throw() { return this->value < rhs.value; }
|
||||
|
||||
@@ -1539,6 +1546,7 @@ public:
|
||||
ConfigOptionType type() const override { return static_type(); }
|
||||
ConfigOption* clone() const override { return new ConfigOptionPoints(*this); }
|
||||
ConfigOptionPoints& operator= (const ConfigOption *opt) { this->set(opt); return *this; }
|
||||
using ConfigOptionVector<Vec2d>::operator==;
|
||||
bool operator==(const ConfigOptionPoints &rhs) const throw() { return this->values == rhs.values; }
|
||||
bool operator< (const ConfigOptionPoints &rhs) const throw()
|
||||
{ return std::lexicographical_compare(this->values.begin(), this->values.end(), rhs.values.begin(), rhs.values.end(), [](const auto &l, const auto &r){ return l < r; }); }
|
||||
@@ -1617,6 +1625,7 @@ public:
|
||||
ConfigOptionType type() const override { return static_type(); }
|
||||
ConfigOption* clone() const override { return new ConfigOptionPoint3(*this); }
|
||||
ConfigOptionPoint3& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
|
||||
using ConfigOptionSingle<Vec3d>::operator==;
|
||||
bool operator==(const ConfigOptionPoint3 &rhs) const throw() { return this->value == rhs.value; }
|
||||
bool operator< (const ConfigOptionPoint3 &rhs) const throw()
|
||||
{ return this->value.x() < rhs.value.x() || (this->value.x() == rhs.value.x() && (this->value.y() < rhs.value.y() || (this->value.y() == rhs.value.y() && this->value.z() < rhs.value.z()))); }
|
||||
@@ -1860,6 +1869,7 @@ public:
|
||||
bool getBool() const override { return this->value; }
|
||||
ConfigOption* clone() const override { return new ConfigOptionBool(*this); }
|
||||
ConfigOptionBool& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
|
||||
using ConfigOptionSingle<bool>::operator==;
|
||||
bool operator==(const ConfigOptionBool &rhs) const throw() { return this->value == rhs.value; }
|
||||
bool operator< (const ConfigOptionBool &rhs) const throw() { return int(this->value) < int(rhs.value); }
|
||||
|
||||
@@ -1911,6 +1921,7 @@ public:
|
||||
ConfigOptionType type() const override { return static_type(); }
|
||||
ConfigOption* clone() const override { return new ConfigOptionBoolsTempl(*this); }
|
||||
ConfigOptionBoolsTempl& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
|
||||
using ConfigOptionVector<unsigned char>::operator==;
|
||||
bool operator==(const ConfigOptionBoolsTempl &rhs) const throw() { return this->values == rhs.values; }
|
||||
bool operator< (const ConfigOptionBoolsTempl &rhs) const throw() { return this->values < rhs.values; }
|
||||
// Could a special "nil" value be stored inside the vector, indicating undefined value?
|
||||
@@ -2163,6 +2174,7 @@ public:
|
||||
ConfigOptionEnumsGenericTempl& operator= (const ConfigOption* opt) { this->set(opt); return *this; }
|
||||
bool operator< (const ConfigOptionInts& rhs) const throw() { return this->values < rhs.values; }
|
||||
|
||||
using ConfigOptionInts::operator==;
|
||||
bool operator==(const ConfigOptionInts& rhs) const
|
||||
{
|
||||
if (rhs.type() != this->type())
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
#ifdef _WIN32
|
||||
#include <charconv>
|
||||
#endif
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <fast_float/fast_float.h>
|
||||
|
||||
@@ -867,6 +867,20 @@ bool is_compatible_with_printer(const PresetWithVendorProfile &preset, const Pre
|
||||
return is_compatible_with_printer(preset, active_printer, &config);
|
||||
}
|
||||
|
||||
// ORCA: see the header. The CLI resolves --load-settings into bare DynamicPrintConfigs and has no
|
||||
// Preset objects to hand; without this it would have to reimplement the policy or build the shells
|
||||
// at every call site.
|
||||
bool is_compatible_with_printer(const DynamicPrintConfig &preset_config, Preset::Type preset_type,
|
||||
const DynamicPrintConfig &printer_config, const std::string &printer_name)
|
||||
{
|
||||
Preset preset(preset_type, std::string("__compat_check"));
|
||||
preset.config = preset_config;
|
||||
Preset printer(Preset::TYPE_PRINTER, printer_name);
|
||||
printer.config = printer_config;
|
||||
return is_compatible_with_printer(PresetWithVendorProfile(preset, nullptr),
|
||||
PresetWithVendorProfile(printer, nullptr));
|
||||
}
|
||||
|
||||
void Preset::set_visible_from_appconfig(const AppConfig &app_config)
|
||||
{
|
||||
//BBS: add config related log
|
||||
|
||||
@@ -459,6 +459,11 @@ protected:
|
||||
bool is_compatible_with_print (const PresetWithVendorProfile &preset, const PresetWithVendorProfile &active_print, const PresetWithVendorProfile &active_printer);
|
||||
bool is_compatible_with_printer(const PresetWithVendorProfile &preset, const PresetWithVendorProfile &active_printer, const DynamicPrintConfig *extra_config);
|
||||
bool is_compatible_with_printer(const PresetWithVendorProfile &preset, const PresetWithVendorProfile &active_printer);
|
||||
// ORCA: same check for callers that hold raw configs rather than Presets (the CLI). Wraps them in
|
||||
// throwaway Preset shells and delegates, so the compatibility policy -- including the fail-open on a
|
||||
// malformed compatible_printers_condition -- lives in one place for the GUI and the CLI alike.
|
||||
bool is_compatible_with_printer(const DynamicPrintConfig &preset_config, Preset::Type preset_type,
|
||||
const DynamicPrintConfig &printer_config, const std::string &printer_name);
|
||||
|
||||
// Where a preset is being loaded from. `Auto` lets load_presets() infer from the directory path.
|
||||
struct PresetOrigin {
|
||||
|
||||
@@ -4981,7 +4981,7 @@ static void apply_mixed_config_relocations(DynamicPrintConfig&
|
||||
case coBools: {
|
||||
auto* live = static_cast<ConfigOptionBools*>(opt);
|
||||
const auto* frozen = static_cast<const ConfigOptionBools*>(snapshot.get());
|
||||
for (const auto [from, to] : moves) {
|
||||
for (const auto& [from, to] : moves) {
|
||||
const unsigned char cell = from < frozen->values.size() ? frozen->values[from] : 0;
|
||||
if (live->values.size() <= to)
|
||||
live->values.resize(to + 1, 0);
|
||||
@@ -4992,7 +4992,7 @@ static void apply_mixed_config_relocations(DynamicPrintConfig&
|
||||
case coStrings: {
|
||||
auto* live = static_cast<ConfigOptionStrings*>(opt);
|
||||
const auto* frozen = static_cast<const ConfigOptionStrings*>(snapshot.get());
|
||||
for (const auto [from, to] : moves) {
|
||||
for (const auto& [from, to] : moves) {
|
||||
const std::string cell = from < frozen->values.size() ? frozen->values[from] : std::string();
|
||||
if (live->values.size() <= to)
|
||||
live->values.resize(to + 1, std::string{});
|
||||
@@ -5028,7 +5028,7 @@ static void apply_receiver_mix_relocations(DynamicPrintConfig&
|
||||
auto* live = static_cast<ConfigOptionBools*>(opt);
|
||||
std::unique_ptr<ConfigOption> snapshot(opt->clone());
|
||||
const auto* frozen = static_cast<const ConfigOptionBools*>(snapshot.get());
|
||||
for (const auto [from, to] : moves) {
|
||||
for (const auto& [from, to] : moves) {
|
||||
const bool cell = from < frozen->values.size() ? frozen->values[from] : false;
|
||||
if (live->values.size() <= to)
|
||||
live->values.resize(to + 1, false);
|
||||
@@ -5044,7 +5044,7 @@ static void apply_receiver_mix_relocations(DynamicPrintConfig&
|
||||
auto* live = static_cast<ConfigOptionStrings*>(opt);
|
||||
std::unique_ptr<ConfigOption> snapshot(opt->clone());
|
||||
const auto* frozen = static_cast<const ConfigOptionStrings*>(snapshot.get());
|
||||
for (const auto [from, to] : moves) {
|
||||
for (const auto& [from, to] : moves) {
|
||||
const std::string cell = from < frozen->values.size() ? frozen->values[from] : std::string();
|
||||
if (live->values.size() <= to)
|
||||
live->values.resize(to + 1, std::string{});
|
||||
@@ -5060,7 +5060,7 @@ static void apply_receiver_mix_relocations(DynamicPrintConfig&
|
||||
auto* live = static_cast<ConfigOptionInts*>(opt);
|
||||
std::unique_ptr<ConfigOption> snapshot(opt->clone());
|
||||
const auto* frozen = static_cast<const ConfigOptionInts*>(snapshot.get());
|
||||
for (const auto [from, to] : moves) {
|
||||
for (const auto& [from, to] : moves) {
|
||||
const int cell = from < frozen->values.size() ? frozen->values[from] : 0;
|
||||
if (live->values.size() <= to)
|
||||
live->values.resize(to + 1, 0);
|
||||
@@ -5087,7 +5087,7 @@ static void apply_receiver_mix_relocations(DynamicPrintConfig&
|
||||
move_ints("filament_volume_map");
|
||||
{
|
||||
const std::vector<std::vector<std::string>> frozen = ams_multi_color_filment;
|
||||
for (const auto [from, to] : moves) {
|
||||
for (const auto& [from, to] : moves) {
|
||||
const std::vector<std::string> cell = from < frozen.size() ? frozen[from] : std::vector<std::string>();
|
||||
if (ams_multi_color_filment.size() <= to)
|
||||
ams_multi_color_filment.resize(to + 1, std::vector<std::string>{});
|
||||
|
||||
@@ -30,6 +30,11 @@ static HMODULE s_hKernel32 = nullptr;
|
||||
static SetThreadDescriptionType s_fnSetThreadDescription = nullptr;
|
||||
static GetThreadDescriptionType s_fnGetThreadDescription = nullptr;
|
||||
|
||||
// Convert the FARPROC from GetProcAddress to Fn through a generic function pointer.
|
||||
template<typename Fn> static Fn load_proc(HMODULE module, const char* name) {
|
||||
return reinterpret_cast<Fn>(reinterpret_cast<void(*)()>(::GetProcAddress(module, name)));
|
||||
}
|
||||
|
||||
static bool WindowsGetSetThreadNameAPIInitialize()
|
||||
{
|
||||
if (! s_SetGetThreadDescriptionInitialized) {
|
||||
@@ -37,8 +42,8 @@ static bool WindowsGetSetThreadNameAPIInitialize()
|
||||
// to initialize
|
||||
s_hKernel32 = LoadLibraryW(L"Kernel32.dll");
|
||||
if (s_hKernel32) {
|
||||
s_fnSetThreadDescription = (SetThreadDescriptionType)::GetProcAddress(s_hKernel32, "SetThreadDescription");
|
||||
s_fnGetThreadDescription = (GetThreadDescriptionType)::GetProcAddress(s_hKernel32, "GetThreadDescription");
|
||||
s_fnSetThreadDescription = load_proc<SetThreadDescriptionType>(s_hKernel32, "SetThreadDescription");
|
||||
s_fnGetThreadDescription = load_proc<GetThreadDescriptionType>(s_hKernel32, "GetThreadDescription");
|
||||
}
|
||||
s_SetGetThreadDescriptionInitialized = true;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "MainFrame.hpp"
|
||||
#include "format.hpp"
|
||||
#include "Widgets/ProgressDialog.hpp"
|
||||
#include <wx/tooltip.h>
|
||||
#include "Widgets/RoundedRectangle.hpp"
|
||||
#include "Widgets/StaticBox.hpp"
|
||||
|
||||
|
||||
+30
-88
@@ -2157,6 +2157,7 @@ void PrinterAgentChoice::msw_rescale()
|
||||
void PluginField::BUILD()
|
||||
{
|
||||
auto* panel = new wxPanel(m_parent, wxID_ANY);
|
||||
panel->SetBackgroundColour(*wxWHITE);
|
||||
wxGetApp().UpdateDarkUI(panel);
|
||||
window = panel;
|
||||
|
||||
@@ -2199,9 +2200,8 @@ void PluginField::rebuild_ui()
|
||||
m_rows.clear();
|
||||
m_standalone_add_btn = nullptr;
|
||||
|
||||
if (m_values.empty()) {
|
||||
add_empty_state_row();
|
||||
} else {
|
||||
add_empty_state_row();
|
||||
if (!m_values.empty()) {
|
||||
for (size_t i = 0; i < m_values.size(); ++i)
|
||||
add_plugin_row(display_name_for_value(m_values[i]), i == m_values.size() - 1);
|
||||
}
|
||||
@@ -2218,94 +2218,43 @@ void PluginField::rebuild_ui()
|
||||
|
||||
void PluginField::add_empty_state_row()
|
||||
{
|
||||
const auto button_size = wxSize(def_width_thinner() * m_em_unit, -1);
|
||||
auto row_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
wxTextCtrl* display = new wxTextCtrl(window, wxID_ANY, _L("No plugin selected"),
|
||||
wxDefaultPosition, wxSize(def_width_wider() * m_em_unit, wxDefaultCoord),
|
||||
wxTE_READONLY);
|
||||
display->SetEditable(false);
|
||||
wxGetApp().UpdateDarkUI(display);
|
||||
display->SetToolTip(_L("No plugin selected"));
|
||||
|
||||
auto add_btn = new ScalableButton(window, wxID_ANY, "param_add", wxEmptyString,
|
||||
button_size, wxDefaultPosition, wxBU_EXACTFIT | wxNO_BORDER, true, 16);
|
||||
wxGetApp().UpdateDarkUI(add_btn);
|
||||
add_btn->SetToolTip(_L("Add plugin"));
|
||||
auto add_btn = new Button(window, _L("Add plugin"), "param_add", 0, 16);
|
||||
add_btn->SetStyle(ButtonStyle::Regular, ButtonType::Parameter);
|
||||
|
||||
add_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { on_add_clicked(); });
|
||||
|
||||
row_sizer->Add(display, 1, wxALIGN_CENTER_VERTICAL | wxRIGHT, 4);
|
||||
row_sizer->Add(add_btn, 0, wxALIGN_CENTER_VERTICAL);
|
||||
m_main_sizer->Add(row_sizer, 0, wxEXPAND);
|
||||
|
||||
PluginRow row;
|
||||
row.display = display;
|
||||
row.add_btn = add_btn;
|
||||
row.sizer = row_sizer;
|
||||
m_rows.push_back(row);
|
||||
m_main_sizer->Add(add_btn, 0, wxEXPAND | wxBOTTOM, window->FromDIP(SidebarProps::ContentMarginV()));
|
||||
|
||||
m_standalone_add_btn = add_btn;
|
||||
}
|
||||
|
||||
void PluginField::add_plugin_row(const wxString& value, bool is_last)
|
||||
{
|
||||
const auto button_size = wxSize(def_width_thinner() * m_em_unit, -1);
|
||||
auto row_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
ScalableButton* select_btn = new ScalableButton(window, wxID_ANY, "search", wxEmptyString,
|
||||
button_size, wxDefaultPosition, wxBU_EXACTFIT | wxNO_BORDER, true, 16);
|
||||
wxGetApp().UpdateDarkUI(select_btn);
|
||||
select_btn->SetToolTip(_L("Select plugin"));
|
||||
|
||||
wxTextCtrl* display = new wxTextCtrl(window, wxID_ANY, value,
|
||||
wxDefaultPosition, wxSize(def_width_wider() * m_em_unit, wxDefaultCoord),
|
||||
wxTE_READONLY);
|
||||
display->SetEditable(false);
|
||||
wxGetApp().UpdateDarkUI(display);
|
||||
ComboBox* display = new ComboBox(window, wxID_ANY, value, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY | CB_NO_DROP_ICON);
|
||||
display->SetIcon("edit");
|
||||
display->SetToolTip(get_tooltip_text(value));
|
||||
|
||||
ScalableButton* remove_btn = nullptr;
|
||||
if (!m_opt.readonly) {
|
||||
remove_btn = new ScalableButton(window, wxID_ANY, "cross", wxEmptyString,
|
||||
button_size, wxDefaultPosition, wxBU_EXACTFIT | wxNO_BORDER, true, 16);
|
||||
wxGetApp().UpdateDarkUI(remove_btn);
|
||||
remove_btn->SetToolTip(_L("Remove plugin"));
|
||||
}
|
||||
ScalableButton* remove_btn = new ScalableButton(window, wxID_ANY, "cross", wxEmptyString,
|
||||
wxDefaultSize, wxDefaultPosition, wxBU_EXACTFIT | wxNO_BORDER, true, 16);
|
||||
remove_btn->SetToolTip(_L("Remove plugin"));
|
||||
|
||||
ScalableButton* add_btn = nullptr;
|
||||
if (is_last && !m_opt.readonly) {
|
||||
add_btn = new ScalableButton(window, wxID_ANY, "param_add", wxEmptyString,
|
||||
button_size, wxDefaultPosition, wxBU_EXACTFIT | wxNO_BORDER, true, 16);
|
||||
wxGetApp().UpdateDarkUI(add_btn);
|
||||
add_btn->SetToolTip(_L("Add plugin"));
|
||||
add_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { on_add_clicked(); });
|
||||
}
|
||||
if (m_opt.readonly)
|
||||
remove_btn->Disable();
|
||||
|
||||
const size_t row_index = m_rows.size();
|
||||
select_btn->Bind(wxEVT_BUTTON, [this, row_index](wxCommandEvent&) { on_select_clicked(row_index); });
|
||||
if (remove_btn)
|
||||
remove_btn->Bind(wxEVT_BUTTON, [this, row_index](wxCommandEvent&) { on_remove_clicked(row_index); });
|
||||
display->Bind(wxEVT_LEFT_DOWN, [this, row_index](wxMouseEvent& ) { on_select_clicked(row_index); });
|
||||
remove_btn->Bind(wxEVT_BUTTON, [this, row_index](wxCommandEvent&) { on_remove_clicked(row_index); });
|
||||
|
||||
row_sizer->Add(select_btn, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 4);
|
||||
row_sizer->Add(display, 1, wxALIGN_CENTER_VERTICAL | wxRIGHT, 4);
|
||||
if (remove_btn)
|
||||
row_sizer->Add(remove_btn, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 4);
|
||||
if (add_btn)
|
||||
row_sizer->Add(add_btn, 0, wxALIGN_CENTER_VERTICAL);
|
||||
else if (!m_opt.readonly) {
|
||||
// Reserve space equal to the add button so all rows align.
|
||||
row_sizer->Add(button_size.GetWidth(), button_size.GetHeight(), 0, wxALIGN_CENTER_VERTICAL);
|
||||
}
|
||||
row_sizer->Add(display , 1, wxALIGN_CENTER_VERTICAL);
|
||||
row_sizer->Add(remove_btn, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, window->FromDIP(SidebarProps::ElementSpacing()));
|
||||
|
||||
const int bottom_gap = is_last ? 0 : 4;
|
||||
m_main_sizer->Add(row_sizer, 0, wxEXPAND | (bottom_gap > 0 ? wxBOTTOM : 0), bottom_gap);
|
||||
m_main_sizer->Add(row_sizer, 0, wxEXPAND | wxBOTTOM, window->FromDIP(is_last ? SidebarProps::ContentMarginV() : 4));
|
||||
|
||||
PluginRow row;
|
||||
row.select_btn = select_btn;
|
||||
row.display = display;
|
||||
row.remove_btn = remove_btn;
|
||||
row.add_btn = add_btn;
|
||||
row.sizer = row_sizer;
|
||||
m_rows.push_back(row);
|
||||
}
|
||||
@@ -2357,9 +2306,9 @@ void PluginField::on_add_clicked()
|
||||
m_values.push_back(selected);
|
||||
m_value = m_values;
|
||||
|
||||
rebuild_ui();
|
||||
|
||||
on_change_field();
|
||||
// Defer: don't destroy the clicked button from inside its own handler.
|
||||
if(window)
|
||||
window->CallAfter([this]() {rebuild_ui(); on_change_field();});
|
||||
}
|
||||
|
||||
void PluginField::on_remove_clicked(size_t index)
|
||||
@@ -2370,8 +2319,9 @@ void PluginField::on_remove_clicked(size_t index)
|
||||
m_values.erase(m_values.begin() + index);
|
||||
m_value = m_values;
|
||||
|
||||
rebuild_ui();
|
||||
on_change_field();
|
||||
// Defer: don't destroy the clicked button from inside its own handler.
|
||||
if(window)
|
||||
window->CallAfter([this]() {rebuild_ui(); on_change_field();});
|
||||
}
|
||||
|
||||
wxString PluginField::get_row_value(size_t index) const
|
||||
@@ -2385,7 +2335,7 @@ void PluginField::set_row_value(size_t index, const wxString& value)
|
||||
{
|
||||
if (index >= m_rows.size() || !m_rows[index].display)
|
||||
return;
|
||||
m_rows[index].display->ChangeValue(value);
|
||||
m_rows[index].display->SetValue(value);
|
||||
m_rows[index].display->SetToolTip(get_tooltip_text(value));
|
||||
}
|
||||
|
||||
@@ -2428,14 +2378,10 @@ boost::any& PluginField::get_value()
|
||||
void PluginField::enable()
|
||||
{
|
||||
for (auto& row : m_rows) {
|
||||
if (row.select_btn)
|
||||
row.select_btn->Enable();
|
||||
if (row.display)
|
||||
row.display->Enable();
|
||||
if (row.remove_btn)
|
||||
row.remove_btn->Enable();
|
||||
if (row.add_btn)
|
||||
row.add_btn->Enable();
|
||||
}
|
||||
if (m_standalone_add_btn)
|
||||
m_standalone_add_btn->Enable();
|
||||
@@ -2444,14 +2390,10 @@ void PluginField::enable()
|
||||
void PluginField::disable()
|
||||
{
|
||||
for (auto& row : m_rows) {
|
||||
if (row.select_btn)
|
||||
row.select_btn->Disable();
|
||||
if (row.display)
|
||||
row.display->Disable();
|
||||
if (row.remove_btn)
|
||||
row.remove_btn->Disable();
|
||||
if (row.add_btn)
|
||||
row.add_btn->Disable();
|
||||
}
|
||||
if (m_standalone_add_btn)
|
||||
m_standalone_add_btn->Disable();
|
||||
@@ -2866,11 +2808,11 @@ void PointCtrl::BUILD()
|
||||
//temp->Add(static_text_y, 0, wxALIGN_CENTER_VERTICAL, 0);
|
||||
temp->Add(y_input);
|
||||
|
||||
x_textctrl->Bind(wxEVT_TEXT_ENTER, ([this](wxCommandEvent e) { propagate_value(x_textctrl); }), x_textctrl->GetId());
|
||||
y_textctrl->Bind(wxEVT_TEXT_ENTER, ([this](wxCommandEvent e) { propagate_value(y_textctrl); }), y_textctrl->GetId());
|
||||
x_textctrl->Bind(wxEVT_TEXT_ENTER, ([this](wxCommandEvent e) { propagate_input_value(x_textctrl); }), x_textctrl->GetId());
|
||||
y_textctrl->Bind(wxEVT_TEXT_ENTER, ([this](wxCommandEvent e) { propagate_input_value(y_textctrl); }), y_textctrl->GetId());
|
||||
|
||||
x_textctrl->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e) { e.Skip(); propagate_value(x_textctrl); }), x_textctrl->GetId());
|
||||
y_textctrl->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e) { e.Skip(); propagate_value(y_textctrl); }), y_textctrl->GetId());
|
||||
x_textctrl->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e) { e.Skip(); propagate_input_value(x_textctrl); }), x_textctrl->GetId());
|
||||
y_textctrl->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e) { e.Skip(); propagate_input_value(y_textctrl); }), y_textctrl->GetId());
|
||||
|
||||
// // recast as a wxWindow to fit the calling convention
|
||||
window = dynamic_cast<wxWindow*>(x_input);
|
||||
@@ -2919,7 +2861,7 @@ bool PointCtrl::value_was_changed(wxTextCtrl* win)
|
||||
return boost::any_cast<Vec2d>(m_value) != boost::any_cast<Vec2d>(val);
|
||||
}
|
||||
|
||||
void PointCtrl::propagate_value(wxTextCtrl* win)
|
||||
void PointCtrl::propagate_input_value(wxTextCtrl* win)
|
||||
{
|
||||
if (win->GetValue().empty())
|
||||
on_kill_focus();
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "wxExtensions.hpp"
|
||||
#include "Widgets/SpinInput.hpp"
|
||||
#include "Widgets/TextInput.hpp"
|
||||
#include "Widgets/ComboBox.hpp"
|
||||
|
||||
#ifdef __WXMSW__
|
||||
#define wxMSW true
|
||||
@@ -532,10 +533,8 @@ public:
|
||||
|
||||
private:
|
||||
struct PluginRow {
|
||||
ScalableButton* select_btn { nullptr };
|
||||
wxTextCtrl* display { nullptr };
|
||||
ComboBox* display { nullptr };
|
||||
ScalableButton* remove_btn { nullptr };
|
||||
ScalableButton* add_btn { nullptr };
|
||||
wxBoxSizer* sizer { nullptr };
|
||||
};
|
||||
|
||||
@@ -553,7 +552,7 @@ private:
|
||||
wxBoxSizer* m_main_sizer { nullptr };
|
||||
std::vector<PluginRow> m_rows;
|
||||
std::vector<std::string> m_values;
|
||||
ScalableButton* m_standalone_add_btn { nullptr };
|
||||
Button* m_standalone_add_btn { nullptr };
|
||||
std::function<std::string()> m_selector;
|
||||
};
|
||||
|
||||
@@ -651,7 +650,7 @@ public:
|
||||
void BUILD() override;
|
||||
bool value_was_changed(wxTextCtrl* win);
|
||||
// Propagate value from field to the OptionGroupe and Config after kill_focus/ENTER
|
||||
void propagate_value(wxTextCtrl* win);
|
||||
void propagate_input_value(wxTextCtrl* win);
|
||||
void set_value(const Vec2d& value, bool change_event = false);
|
||||
void set_value(const boost::any& value, bool change_event = false) override;
|
||||
boost::any& get_value() override;
|
||||
|
||||
@@ -1078,56 +1078,36 @@ const double GLCanvas3D::DefaultCameraZoomToPlateMarginFactor = 1.25;
|
||||
|
||||
void GLCanvas3D::load_arrange_settings()
|
||||
{
|
||||
std::string dist_fff_str =
|
||||
wxGetApp().app_config->get("arrange", "min_object_distance_fff");
|
||||
// Each key must match what _render_arrange_menu writes, which appends a per-mode
|
||||
// postfix to the base name.
|
||||
auto load_float = [](const char *key, float &out) {
|
||||
// The menu writes these with float_to_string_decimal_point, so parse them back
|
||||
// the same way rather than with anything locale-dependent.
|
||||
std::string value = wxGetApp().app_config->get("arrange", key);
|
||||
size_t parsed = 0;
|
||||
double number = string_to_double_decimal_point(value, &parsed);
|
||||
if (parsed > 0)
|
||||
out = float(number);
|
||||
};
|
||||
auto load_bool = [](const char *key, bool &out) {
|
||||
std::string value = wxGetApp().app_config->get("arrange", key);
|
||||
if (!value.empty())
|
||||
out = (value == "1" || value == "true");
|
||||
};
|
||||
|
||||
std::string dist_fff_seq_print_str =
|
||||
wxGetApp().app_config->get("arrange", "min_object_distance_seq_print_fff");
|
||||
load_float("min_object_distance_fff", m_arrange_settings_fff.distance);
|
||||
load_float("min_object_distance_fff_seq_print", m_arrange_settings_fff_seq_print.distance);
|
||||
load_float("min_object_distance_sla", m_arrange_settings_sla.distance);
|
||||
|
||||
std::string dist_sla_str =
|
||||
wxGetApp().app_config->get("arrange", "min_object_distance_sla");
|
||||
load_bool("enable_rotation_fff", m_arrange_settings_fff.enable_rotation);
|
||||
load_bool("enable_rotation_fff_seq_print", m_arrange_settings_fff_seq_print.enable_rotation);
|
||||
load_bool("enable_rotation_sla", m_arrange_settings_sla.enable_rotation);
|
||||
|
||||
std::string en_rot_fff_str =
|
||||
wxGetApp().app_config->get("arrange", "enable_rotation_fff");
|
||||
|
||||
std::string en_rot_fff_seqp_str =
|
||||
wxGetApp().app_config->get("arrange", "enable_rotation_seq_print");
|
||||
|
||||
std::string en_rot_sla_str =
|
||||
wxGetApp().app_config->get("arrange", "enable_rotation_sla");
|
||||
|
||||
std::string en_allow_multiple_materials_str =
|
||||
wxGetApp().app_config->get("arrange", "allow_multi_materials_on_same_plate");
|
||||
|
||||
std::string en_avoid_region_str =
|
||||
wxGetApp().app_config->get("arrange", "avoid_extrusion_cali_region");
|
||||
|
||||
|
||||
|
||||
if (!dist_fff_str.empty())
|
||||
m_arrange_settings_fff.distance = std::stof(dist_fff_str);
|
||||
|
||||
if (!dist_fff_seq_print_str.empty())
|
||||
m_arrange_settings_fff_seq_print.distance = std::stof(dist_fff_seq_print_str);
|
||||
|
||||
if (!dist_sla_str.empty())
|
||||
m_arrange_settings_sla.distance = std::stof(dist_sla_str);
|
||||
|
||||
if (!en_rot_fff_str.empty())
|
||||
m_arrange_settings_fff.enable_rotation = (en_rot_fff_str == "1" || en_rot_fff_str == "true");
|
||||
|
||||
if (!en_allow_multiple_materials_str.empty())
|
||||
m_arrange_settings_fff.allow_multi_materials_on_same_plate = (en_allow_multiple_materials_str == "1" || en_allow_multiple_materials_str == "true");
|
||||
|
||||
|
||||
if (!en_rot_fff_seqp_str.empty())
|
||||
m_arrange_settings_fff_seq_print.enable_rotation = (en_rot_fff_seqp_str == "1" || en_rot_fff_seqp_str == "true");
|
||||
|
||||
if(!en_avoid_region_str.empty())
|
||||
m_arrange_settings_fff.avoid_extrusion_cali_region = (en_avoid_region_str == "1" || en_avoid_region_str == "true");
|
||||
|
||||
if (!en_rot_sla_str.empty())
|
||||
m_arrange_settings_sla.enable_rotation = (en_rot_sla_str == "1" || en_rot_sla_str == "true");
|
||||
// These two keys carry no postfix, so the one stored value covers both FFF modes.
|
||||
load_bool("allow_multi_materials_on_same_plate", m_arrange_settings_fff.allow_multi_materials_on_same_plate);
|
||||
load_bool("allow_multi_materials_on_same_plate", m_arrange_settings_fff_seq_print.allow_multi_materials_on_same_plate);
|
||||
load_bool("avoid_extrusion_cali_region", m_arrange_settings_fff.avoid_extrusion_cali_region);
|
||||
load_bool("avoid_extrusion_cali_region", m_arrange_settings_fff_seq_print.avoid_extrusion_cali_region);
|
||||
|
||||
//BBS: add specific arrange settings
|
||||
m_arrange_settings_fff_seq_print.is_seq_print = true;
|
||||
@@ -5059,7 +5039,21 @@ void GLCanvas3D::do_move(const std::string& snapshot_type)
|
||||
}
|
||||
|
||||
//BBS: notify instance updates to part plater list
|
||||
m_selection.notify_instance_update(-1, 0);
|
||||
// Only what moved: the selected instances, or every instance of an object one of whose
|
||||
// parts moved. Notifying a plate about an instance that stayed put invalidates its slice
|
||||
// result, and notifying instance 0 alone left a moved copy unregistered on its new plate.
|
||||
{
|
||||
std::set<std::pair<int, int>> notified;
|
||||
for (unsigned int i : m_selection.get_volume_idxs()) {
|
||||
const GLVolume* v = m_volumes.volumes[i];
|
||||
const int object_idx = v->object_idx();
|
||||
if (object_idx < 0 || object_idx >= static_cast<int>(m_model->objects.size()))
|
||||
continue;
|
||||
const std::pair<int, int> key(object_idx, selection_mode == Selection::Volume ? -1 : v->instance_idx());
|
||||
if (notified.insert(key).second)
|
||||
m_selection.notify_instance_update(key.first, key.second);
|
||||
}
|
||||
}
|
||||
|
||||
// Fixes sinking/flying instances (snaps object to buildplate)
|
||||
for (const std::pair<int, int>& i : done) {
|
||||
@@ -5945,7 +5939,7 @@ bool GLCanvas3D::_render_orient_menu(float left, float right, float bottom, floa
|
||||
}
|
||||
|
||||
//BBS: GUI refactor: adjust main toolbar position
|
||||
bool GLCanvas3D::_render_arrange_menu(float left, float right, float bottom, float top)
|
||||
void GLCanvas3D::_render_arrange_menu(float left, float right, float bottom, float top)
|
||||
{
|
||||
ImGuiWrapper *imgui = wxGetApp().imgui();
|
||||
|
||||
@@ -5970,7 +5964,6 @@ bool GLCanvas3D::_render_arrange_menu(float left, float right, float bottom, flo
|
||||
|
||||
imgui->begin(_L("Arrange options"), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar);
|
||||
|
||||
ArrangeSettings settings = get_arrange_settings();
|
||||
ArrangeSettings &settings_out = get_arrange_settings();
|
||||
const float slider_icon_width = imgui->get_slider_icon_size().x;
|
||||
const float cursor_slider_left = imgui->calc_text_size(_L("Spacing")).x + imgui->scaled(1.5f);
|
||||
@@ -5979,13 +5972,9 @@ bool GLCanvas3D::_render_arrange_menu(float left, float right, float bottom, flo
|
||||
auto &appcfg = wxGetApp().app_config;
|
||||
PrinterTechnology ptech = current_printer_technology();
|
||||
|
||||
bool settings_changed = false;
|
||||
float dist_min = 0.f; // 0 means auto
|
||||
std::string dist_key = "min_object_distance", rot_key = "enable_rotation";
|
||||
std::string bed_shrink_x_key = "bed_shrink_x", bed_shrink_y_key = "bed_shrink_y";
|
||||
std::string multi_material_key = "allow_multi_materials_on_same_plate";
|
||||
std::string avoid_extrusion_key = "avoid_extrusion_cali_region";
|
||||
std::string align_to_y_axis_key = "align_to_y_axis";
|
||||
std::string postfix;
|
||||
//BBS:
|
||||
bool seq_print = false;
|
||||
@@ -5993,59 +5982,41 @@ bool GLCanvas3D::_render_arrange_menu(float left, float right, float bottom, flo
|
||||
if (ptech == ptSLA) {
|
||||
postfix = "_sla";
|
||||
} else if (ptech == ptFFF) {
|
||||
seq_print = &settings == &m_arrange_settings_fff_seq_print;
|
||||
if (seq_print) {
|
||||
postfix = "_fff_seq_print";
|
||||
} else {
|
||||
postfix = "_fff";
|
||||
}
|
||||
seq_print = wxGetApp().global_print_sequence() == PrintSequence::ByObject;
|
||||
postfix = seq_print ? "_fff_seq_print" : "_fff";
|
||||
}
|
||||
|
||||
dist_key += postfix;
|
||||
rot_key += postfix;
|
||||
bed_shrink_x_key += postfix;
|
||||
bed_shrink_y_key += postfix;
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
imgui->text(_L("Spacing"));
|
||||
ImGui::SameLine(1.2 * cursor_slider_left);
|
||||
ImGui::PushItemWidth(window_width - slider_icon_width);
|
||||
bool b_Spacing = imgui->bbl_slider_float_style("##Spacing", &settings.distance, dist_min, 100.0f, "%5.2f") || dist_min > settings.distance;
|
||||
bool b_Spacing = imgui->bbl_slider_float_style("##Spacing", &settings_out.distance, 0.f, 100.0f, "%5.2f", 1.0f, /*clamp=*/false);
|
||||
ImGui::SameLine(window_width - slider_icon_width + 1.3 * cursor_slider_left);
|
||||
ImGui::PushItemWidth(1.5 * slider_icon_width);
|
||||
bool b_spacing_input = ImGui::BBLDragFloat("##spacing_input", &settings.distance, 0.05f, 0.0f, 0.0f, "%.2f");
|
||||
if (b_Spacing || b_spacing_input)
|
||||
{
|
||||
settings.distance = std::max(dist_min, settings.distance);
|
||||
settings_out.distance = settings.distance;
|
||||
bool b_spacing_input = ImGui::BBLDragFloat("##spacing_input", &settings_out.distance, 0.05f, 0.0f, 0.0f, "%.2f");
|
||||
if (b_Spacing || b_spacing_input) {
|
||||
settings_out.distance = std::max(0.f, settings_out.distance);
|
||||
appcfg->set("arrange", dist_key.c_str(), float_to_string_decimal_point(settings_out.distance));
|
||||
settings_changed = true;
|
||||
}
|
||||
imgui->text(_L("0 means auto spacing."));
|
||||
|
||||
ImGui::Separator();
|
||||
if (imgui->bbl_checkbox(_L("Auto rotate for arrangement"), settings.enable_rotation)) {
|
||||
settings_out.enable_rotation = settings.enable_rotation;
|
||||
if (imgui->bbl_checkbox(_L("Auto rotate for arrangement"), settings_out.enable_rotation))
|
||||
appcfg->set("arrange", rot_key.c_str(), settings_out.enable_rotation);
|
||||
settings_changed = true;
|
||||
}
|
||||
|
||||
if (imgui->bbl_checkbox(_L("Allow multiple materials on same plate"), settings.allow_multi_materials_on_same_plate)) {
|
||||
settings_out.allow_multi_materials_on_same_plate = settings.allow_multi_materials_on_same_plate;
|
||||
appcfg->set("arrange", multi_material_key.c_str(), settings_out.allow_multi_materials_on_same_plate );
|
||||
settings_changed = true;
|
||||
}
|
||||
if (imgui->bbl_checkbox(_L("Allow multiple materials on same plate"), settings_out.allow_multi_materials_on_same_plate))
|
||||
appcfg->set("arrange", multi_material_key.c_str(), settings_out.allow_multi_materials_on_same_plate);
|
||||
|
||||
// only show this option if the printer has micro Lidar and can do first layer scan
|
||||
DynamicPrintConfig ¤t_config = wxGetApp().preset_bundle->printers.get_edited_preset().config;
|
||||
const bool has_lidar = wxGetApp().preset_bundle->is_bbl_vendor();
|
||||
auto op = current_config.option("scan_first_layer");
|
||||
if (has_lidar && op && op->getBool()) {
|
||||
if (imgui->bbl_checkbox(_L("Avoid extrusion calibration region"), settings.avoid_extrusion_cali_region)) {
|
||||
settings_out.avoid_extrusion_cali_region = settings.avoid_extrusion_cali_region;
|
||||
appcfg->set("arrange", avoid_extrusion_key.c_str(), settings_out.avoid_extrusion_cali_region ? "1" : "0");
|
||||
settings_changed = true;
|
||||
}
|
||||
if (imgui->bbl_checkbox(_L("Avoid extrusion calibration region"), settings_out.avoid_extrusion_cali_region))
|
||||
appcfg->set("arrange", avoid_extrusion_key.c_str(), settings_out.avoid_extrusion_cali_region);
|
||||
} else {
|
||||
settings_out.avoid_extrusion_cali_region = false;
|
||||
}
|
||||
@@ -6057,11 +6028,7 @@ bool GLCanvas3D::_render_arrange_menu(float left, float right, float bottom, flo
|
||||
settings_out.align_to_y_axis = false;
|
||||
}
|
||||
|
||||
if (imgui->bbl_checkbox(_L("Align to Y axis"), settings.align_to_y_axis)) {
|
||||
settings_out.align_to_y_axis = settings.align_to_y_axis;
|
||||
appcfg->set("arrange", align_to_y_axis_key, settings_out.align_to_y_axis ? "1" : "0");
|
||||
settings_changed = true;
|
||||
}
|
||||
imgui->bbl_checkbox(_L("Align to Y axis"), settings_out.align_to_y_axis);
|
||||
|
||||
if (settings_out.enable_rotation == true) { imgui->disabled_end(); }
|
||||
}
|
||||
@@ -6077,7 +6044,6 @@ bool GLCanvas3D::_render_arrange_menu(float left, float right, float bottom, flo
|
||||
|
||||
if (imgui->button(_L("Reset"))) {
|
||||
settings_out = ArrangeSettings{};
|
||||
settings_out.distance = std::max(dist_min, settings_out.distance);
|
||||
//BBS: add specific arrange settings
|
||||
if (seq_print) settings_out.is_seq_print = true;
|
||||
|
||||
@@ -6087,18 +6053,16 @@ bool GLCanvas3D::_render_arrange_menu(float left, float right, float bottom, flo
|
||||
else
|
||||
settings_out.align_to_y_axis = false;
|
||||
|
||||
appcfg->set("arrange", dist_key, float_to_string_decimal_point(settings_out.distance));
|
||||
appcfg->set("arrange", rot_key, settings_out.enable_rotation ? "1" : "0");
|
||||
appcfg->set("arrange", align_to_y_axis_key, settings_out.align_to_y_axis ? "1" : "0");
|
||||
settings_changed = true;
|
||||
appcfg->erase("arrange", dist_key);
|
||||
appcfg->erase("arrange", rot_key);
|
||||
appcfg->erase("arrange", multi_material_key);
|
||||
appcfg->erase("arrange", avoid_extrusion_key);
|
||||
}
|
||||
ImGui::PopStyleVar(1);
|
||||
imgui->end();
|
||||
|
||||
//BBS
|
||||
ImGuiWrapper::pop_toolbar_style();
|
||||
|
||||
return settings_changed;
|
||||
}
|
||||
|
||||
static const float cameraProjection[16] = {1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f};
|
||||
|
||||
@@ -656,11 +656,7 @@ public:
|
||||
}
|
||||
|
||||
void load_arrange_settings();
|
||||
ArrangeSettings& get_arrange_settings();// { return get_arrange_settings(this); }
|
||||
ArrangeSettings& get_arrange_settings(PrintSequence print_seq) {
|
||||
return (print_seq == PrintSequence::ByObject) ? m_arrange_settings_fff_seq_print
|
||||
: m_arrange_settings_fff;
|
||||
}
|
||||
ArrangeSettings& get_arrange_settings();
|
||||
|
||||
class SequentialPrintClearance
|
||||
{
|
||||
@@ -1163,17 +1159,6 @@ public:
|
||||
void highlight_toolbar_item(const std::string& item_name);
|
||||
void highlight_gizmo(const std::string& gizmo_name);
|
||||
|
||||
ArrangeSettings get_arrange_settings() const {
|
||||
const ArrangeSettings &settings = get_arrange_settings();
|
||||
ArrangeSettings ret = settings;
|
||||
if (&settings == &m_arrange_settings_fff_seq_print) {
|
||||
ret.distance = std::max(ret.distance,
|
||||
float(min_object_distance(*m_config)));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Timestamp for FPS calculation and notification fade-outs.
|
||||
static int64_t timestamp_now() {
|
||||
#ifdef _WIN32
|
||||
@@ -1308,7 +1293,7 @@ private:
|
||||
void _render_selection_sidebar_hints() { m_selection.render_sidebar_hints(m_sidebar_field, m_gizmos.get_uniform_scaling()); }
|
||||
//BBS: GUI refactor: adjust main toolbar position
|
||||
bool _render_orient_menu(float left, float right, float bottom, float top);
|
||||
bool _render_arrange_menu(float left, float right, float bottom, float top);
|
||||
void _render_arrange_menu(float left, float right, float bottom, float top);
|
||||
void _render_3d_navigator();
|
||||
|
||||
void _update_volumes_hover_state();
|
||||
|
||||
@@ -9197,7 +9197,7 @@ int GUI_App::filaments_cnt() const
|
||||
PrintSequence GUI_App::global_print_sequence() const
|
||||
{
|
||||
PrintSequence global_print_seq = PrintSequence::ByDefault;
|
||||
auto curr_preset_config = preset_bundle->prints.get_edited_preset().config;
|
||||
const auto &curr_preset_config = preset_bundle->prints.get_edited_preset().config;
|
||||
if (curr_preset_config.has("print_sequence"))
|
||||
global_print_seq = curr_preset_config.option<ConfigOptionEnum<PrintSequence>>("print_sequence")->value;
|
||||
return global_print_seq;
|
||||
|
||||
@@ -2578,7 +2578,7 @@ void ObjectGridTable::OnSelectCell(int row, int col)
|
||||
return;
|
||||
m_panel->m_side_window->Freeze();
|
||||
if (row == 0 || col == col_filaments) {
|
||||
m_panel->m_object_settings->UpdateAndShow(row, false, false, false, nullptr, nullptr, std::string());
|
||||
m_panel->m_object_settings->UpdateAndShowRow(row, false, false, false, nullptr, nullptr, std::string());
|
||||
}
|
||||
else {
|
||||
ObjectGridRow* grid_row = m_grid_data[row - 1];
|
||||
@@ -2588,7 +2588,7 @@ void ObjectGridTable::OnSelectCell(int row, int col)
|
||||
|
||||
//m_panel->m_object_settings->get_og()->set_name(GUI::from_u8(grid_row->name.value));
|
||||
//m_panel->m_page_text->SetLabel(GUI::from_u8(grid_row->name.value));
|
||||
m_panel->m_object_settings->UpdateAndShow(row, true, is_object, false, object, grid_row->config, grid_col->category);
|
||||
m_panel->m_object_settings->UpdateAndShowRow(row, true, is_object, false, object, grid_row->config, grid_col->category);
|
||||
|
||||
std::vector<ObjectVolumeID> object_volume_ids;
|
||||
ObjectVolumeID object_volume_id;
|
||||
|
||||
@@ -463,7 +463,7 @@ void ObjectTableSettings::update_config_values(bool is_object, ModelObject* obje
|
||||
m_table->reload_cell_data(m_current_row, category);
|
||||
}
|
||||
|
||||
void ObjectTableSettings::UpdateAndShow(int row, const bool show, bool is_object, bool is_multiple_selection, ModelObject* object, ModelConfig* config, const std::string& category)
|
||||
void ObjectTableSettings::UpdateAndShowRow(int row, const bool show, bool is_object, bool is_multiple_selection, ModelObject* object, ModelConfig* config, const std::string& category)
|
||||
{
|
||||
m_current_row = row;
|
||||
m_current_category = category;
|
||||
|
||||
@@ -71,7 +71,7 @@ public:
|
||||
//return visible count
|
||||
int update_extra_column_visible_status(ConfigOptionsGroup* option_group, const std::vector<SimpleSettingData>& option_keys, ModelConfig* config);
|
||||
void update_config_values(bool is_object, ModelObject* object, ModelConfig* config, const std::string& category, const std::string& changed_opt_key = "");
|
||||
void UpdateAndShow(int row, const bool show, bool is_object, bool is_multiple_selection, ModelObject* object, ModelConfig* config, const std::string& category);
|
||||
void UpdateAndShowRow(int row, const bool show, bool is_object, bool is_multiple_selection, ModelObject* object, ModelConfig* config, const std::string& category);
|
||||
void ValueChanged(int row, bool is_object, ModelObject* object, ModelConfig* config, const std::string& category, const std::string& key);
|
||||
void resetAllValues(int row, bool is_object, ModelObject* object, ModelConfig* config, const std::string& category);
|
||||
void msw_rescale();
|
||||
|
||||
@@ -87,7 +87,6 @@ private:
|
||||
std::condition_variable m_thread_stop_condition;
|
||||
mutable std::mutex m_thread_stop_mutex;
|
||||
bool m_stop{ false };
|
||||
bool m_start{ true };
|
||||
|
||||
// background thread method
|
||||
void listen();
|
||||
|
||||
@@ -698,10 +698,15 @@ std::string OptionsGroup::pick_plugin(const ConfigOptionDef& opt)
|
||||
Slic3r::PluginManager& manager = Slic3r::PluginManager::instance();
|
||||
const Slic3r::PluginCapabilityType plugin_type = Slic3r::plugin_capability_type_from_string(opt.plugin_type);
|
||||
if (plugin_type == Slic3r::PluginCapabilityType::Unknown) {
|
||||
const std::string message = opt.plugin_type.empty()
|
||||
? "This setting does not specify a plugin capability type."
|
||||
: "This setting specifies an unrecognized plugin capability type: '" + opt.plugin_type + "'.";
|
||||
wxMessageBox(from_u8(message), _L("Plugin Selection"), wxOK | wxICON_WARNING, m_parent);
|
||||
MessageDialog dlg(m_parent,
|
||||
opt.plugin_type.empty() ? _L("This setting does not specify a plugin capability type.")
|
||||
: _L("This setting specifies an unrecognized plugin capability type: ") + "'" + opt.plugin_type + "'.",
|
||||
_L("Plugin Selection"),
|
||||
wxOK | wxICON_WARNING
|
||||
);
|
||||
dlg.CenterOnParent();
|
||||
dlg.ShowModal();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -714,7 +719,13 @@ std::string OptionsGroup::pick_plugin(const ConfigOptionDef& opt)
|
||||
});
|
||||
|
||||
if (caps.empty()) {
|
||||
wxMessageBox(_L("No plugins capabilities available for this type.\nEnable or install some to use."), _L("Plugin Selection"), wxOK | wxICON_INFORMATION, m_parent);
|
||||
MessageDialog dlg(m_parent,
|
||||
_L("No plugins capabilities available for this type.\nEnable or install some to use."),
|
||||
_L("Plugin Selection"),
|
||||
wxOK | wxICON_INFORMATION
|
||||
);
|
||||
dlg.CenterOnParent();
|
||||
dlg.ShowModal();
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
@@ -1917,7 +1917,7 @@ std::vector<int> PartPlate::get_extruders_without_support(bool conside_custom_gc
|
||||
const DynamicPrintConfig& glb_config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
|
||||
|
||||
for (int obj_idx = 0; obj_idx < m_model->objects.size(); obj_idx++) {
|
||||
if (!contain_instance_totally(obj_idx, 0))
|
||||
if (!contain_any_instance_totally(obj_idx))
|
||||
continue;
|
||||
|
||||
ModelObject* mo = m_model->objects[obj_idx];
|
||||
@@ -2088,7 +2088,7 @@ bool PartPlate::check_single_extruder_mixed_filament_risk(const DynamicPrintConf
|
||||
"which may significantly increase waste and the risk of nozzle / waste-chute clogging.");
|
||||
|
||||
for (int obj_idx = 0; obj_idx < (int)m_model->objects.size(); ++obj_idx) {
|
||||
if (!contain_instance_totally(obj_idx, 0))
|
||||
if (!contain_any_instance_totally(obj_idx))
|
||||
continue;
|
||||
ModelObject *mo = m_model->objects[obj_idx];
|
||||
int obj_ext = mo->config.has("extruder") ? mo->config.extruder() : 1;
|
||||
@@ -2307,7 +2307,7 @@ bool PartPlate::check_compatible_of_nozzle_and_filament(const DynamicPrintConfig
|
||||
return wipe_tower_size;
|
||||
|
||||
for (int obj_idx = 0; obj_idx < m_model->objects.size(); obj_idx++) {
|
||||
if (!use_global_objects && !contain_instance_totally(obj_idx, 0))
|
||||
if (!use_global_objects && !contain_any_instance_totally(obj_idx))
|
||||
continue;
|
||||
|
||||
BoundingBoxf3 bbox = m_model->objects[obj_idx]->bounding_box();
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/tooltip.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/button.h>
|
||||
|
||||
@@ -17842,6 +17842,10 @@ void Plater::increase_instances(size_t num)
|
||||
model_object->add_instance(offset_vec, model_instance->get_scaling_factor(), model_instance->get_rotation(), model_instance->get_mirror());
|
||||
// p->print.get_object(obj_idx)->add_copy(Slic3r::to_2d(offset_vec));
|
||||
}
|
||||
// Register the copies with the plate they land on before the scene reloads: the plate's
|
||||
// filament list and wipe tower preview are read from that registry.
|
||||
for (size_t i = model_object->instances.size() - num; i < model_object->instances.size(); ++i)
|
||||
p->partplate_list.notify_instance_update(obj_idx, static_cast<int>(i));
|
||||
|
||||
#ifdef SUPPORT_AUTO_CENTER
|
||||
if (p->get_config("autocenter") == "true")
|
||||
@@ -17872,8 +17876,10 @@ void Plater::decrease_instances(size_t num)
|
||||
|
||||
ModelObject* model_object = p->model.objects[obj_idx];
|
||||
if (model_object->instances.size() > num) {
|
||||
for (size_t i = 0; i < num; ++ i)
|
||||
for (size_t i = 0; i < num; ++ i) {
|
||||
p->partplate_list.notify_instance_removed(obj_idx, static_cast<int>(model_object->instances.size()) - 1);
|
||||
model_object->delete_last_instance();
|
||||
}
|
||||
p->update();
|
||||
// Delete object from Sidebar list. Do it after update, so that the GLScene selection is updated with the modified model.
|
||||
sidebar().obj_list()->decrease_object_instances(obj_idx, num);
|
||||
|
||||
@@ -9,12 +9,16 @@
|
||||
#include "GUI.hpp"
|
||||
#include "I18N.hpp"
|
||||
|
||||
#include "GUI_App.hpp"
|
||||
|
||||
#include "Widgets/DialogButtons.hpp"
|
||||
|
||||
namespace Slic3r { namespace GUI {
|
||||
|
||||
PluginPickerDialog::PluginPickerDialog(wxWindow* parent,
|
||||
const wxString& plugin_type_label,
|
||||
const std::vector<Slic3r::PluginDescriptor>& plugins)
|
||||
: wxDialog(parent, wxID_ANY, wxString::Format(_L("Select %s Plugin"), plugin_type_label))
|
||||
: DPIDialog(parent, wxID_ANY, wxString::Format(_L("Select %s Plugin"), plugin_type_label))
|
||||
, m_plugins(plugins)
|
||||
{
|
||||
build_ui(plugin_type_label);
|
||||
@@ -24,7 +28,7 @@ PluginPickerDialog::PluginPickerDialog(wxWindow* parent,
|
||||
PluginPickerDialog::PluginPickerDialog(wxWindow* parent,
|
||||
const wxString& plugin_type_label,
|
||||
std::vector<CapabilityEntry> capabilities)
|
||||
: wxDialog(parent, wxID_ANY, wxString::Format(_L("Select %s Plugin"), plugin_type_label))
|
||||
: DPIDialog(parent, wxID_ANY, wxString::Format(_L("Select %s Plugin"), plugin_type_label))
|
||||
, m_capabilities(std::move(capabilities))
|
||||
{
|
||||
build_capability_ui(plugin_type_label);
|
||||
@@ -33,12 +37,18 @@ PluginPickerDialog::PluginPickerDialog(wxWindow* parent,
|
||||
|
||||
void PluginPickerDialog::build_ui(const wxString& plugin_type_label)
|
||||
{
|
||||
SetBackgroundColour(*wxWHITE);
|
||||
|
||||
const bool has_plugins = !m_plugins.empty();
|
||||
|
||||
auto* top_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
auto* info_text = new wxStaticText(this, wxID_ANY,
|
||||
wxString::Format(_L("Choose a %s plugin from the list below."), plugin_type_label));
|
||||
top_sizer->Add(info_text, 0, wxALL | wxEXPAND, 10);
|
||||
info_text->SetFont(Label::Body_14);
|
||||
info_text->SetForegroundColour(wxColour("#363636"));
|
||||
top_sizer->Add(info_text, 0, wxALL | wxEXPAND, FromDIP(10));
|
||||
|
||||
top_sizer->AddSpacer(FromDIP(5));
|
||||
|
||||
wxArrayString choices;
|
||||
choices.reserve(m_plugins.size());
|
||||
@@ -49,84 +59,103 @@ void PluginPickerDialog::build_ui(const wxString& plugin_type_label)
|
||||
choices.Add(label);
|
||||
}
|
||||
|
||||
m_choice = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, choices);
|
||||
m_choice = new ComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY);
|
||||
for (const wxString &opt : choices) { m_choice->Append(opt); }
|
||||
|
||||
if (has_plugins) {
|
||||
m_choice->SetSelection(0);
|
||||
m_choice->Bind(wxEVT_CHOICE, [this](wxCommandEvent& evt) {
|
||||
m_choice->Bind(wxEVT_COMBOBOX, [this](wxCommandEvent& evt) {
|
||||
update_description(evt.GetSelection());
|
||||
});
|
||||
} else {
|
||||
m_choice->Enable(false);
|
||||
}
|
||||
|
||||
top_sizer->Add(m_choice, 0, wxLEFT | wxRIGHT | wxEXPAND, 10);
|
||||
top_sizer->Add(m_choice, 0, wxLEFT | wxRIGHT | wxEXPAND, FromDIP(10));
|
||||
|
||||
m_description = new wxStaticText(this, wxID_ANY, wxEmptyString);
|
||||
m_description->SetFont(Label::Body_14);
|
||||
m_description->SetForegroundColour(wxColour("#363636"));
|
||||
m_description->Wrap(400);
|
||||
top_sizer->Add(m_description, 0, wxALL | wxEXPAND, 10);
|
||||
top_sizer->Add(m_description, 0, wxALL | wxEXPAND, FromDIP(10));
|
||||
|
||||
if (has_plugins)
|
||||
update_description(0);
|
||||
else
|
||||
m_description->SetLabel(_L("No plugins found for this type."));
|
||||
|
||||
auto* button_sizer = new wxStdDialogButtonSizer();
|
||||
auto* ok_button = new wxButton(this, wxID_OK);
|
||||
ok_button->Enable(has_plugins);
|
||||
button_sizer->AddButton(ok_button);
|
||||
button_sizer->AddButton(new wxButton(this, wxID_CANCEL));
|
||||
button_sizer->Realize();
|
||||
auto dlg_btns = new DialogButtons(this, {"OK", "Cancel"});
|
||||
|
||||
top_sizer->Add(button_sizer, 0, wxALL | wxALIGN_RIGHT, 10);
|
||||
dlg_btns->GetOK()->Bind(wxEVT_BUTTON, [this](wxCommandEvent &e) { EndModal(wxID_OK); });
|
||||
dlg_btns->GetOK()->Enable(has_plugins);
|
||||
|
||||
dlg_btns->GetCANCEL()->Bind(wxEVT_BUTTON, [this](wxCommandEvent &e) { EndModal(wxID_CANCEL); });
|
||||
|
||||
top_sizer->Add(dlg_btns, 0, wxEXPAND);
|
||||
|
||||
SetSizerAndFit(top_sizer);
|
||||
|
||||
wxGetApp().UpdateDlgDarkUI(this);
|
||||
}
|
||||
|
||||
void PluginPickerDialog::build_capability_ui(const wxString& plugin_type_label)
|
||||
{
|
||||
SetBackgroundColour(*wxWHITE);
|
||||
|
||||
const bool has_capabilities = !m_capabilities.empty();
|
||||
|
||||
auto* top_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
auto* info_text = new wxStaticText(this, wxID_ANY,
|
||||
wxString::Format(_L("Choose a %s plugin from the list below."), plugin_type_label));
|
||||
top_sizer->Add(info_text, 0, wxALL | wxEXPAND, 10);
|
||||
info_text->SetFont(Label::Body_14);
|
||||
info_text->SetForegroundColour(wxColour("#363636"));
|
||||
|
||||
top_sizer->Add(info_text, 0, wxALL | wxEXPAND, FromDIP(10));
|
||||
|
||||
top_sizer->AddSpacer(FromDIP(5));
|
||||
|
||||
wxArrayString choices;
|
||||
choices.reserve(m_capabilities.size());
|
||||
for (const auto& cap : m_capabilities)
|
||||
choices.Add(cap.label);
|
||||
|
||||
m_choice = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, choices);
|
||||
m_choice = new ComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY);
|
||||
for (const wxString &opt : choices) { m_choice->Append(opt); }
|
||||
|
||||
if (has_capabilities) {
|
||||
m_choice->SetSelection(0);
|
||||
m_choice->Bind(wxEVT_CHOICE, [this](wxCommandEvent& evt) {
|
||||
m_choice->Bind(wxEVT_COMBOBOX, [this](wxCommandEvent& evt) {
|
||||
update_capability_description(evt.GetSelection());
|
||||
});
|
||||
} else {
|
||||
m_choice->Enable(false);
|
||||
}
|
||||
|
||||
top_sizer->Add(m_choice, 0, wxLEFT | wxRIGHT | wxEXPAND, 10);
|
||||
top_sizer->Add(m_choice, 0, wxLEFT | wxRIGHT | wxEXPAND, FromDIP(10));
|
||||
|
||||
m_description = new wxStaticText(this, wxID_ANY, wxEmptyString);
|
||||
m_description->SetFont(Label::Body_14);
|
||||
m_description->SetForegroundColour(wxColour("#363636"));
|
||||
m_description->Wrap(400);
|
||||
top_sizer->Add(m_description, 0, wxALL | wxEXPAND, 10);
|
||||
top_sizer->Add(m_description, 0, wxALL | wxEXPAND, FromDIP(10));
|
||||
|
||||
if (has_capabilities)
|
||||
update_capability_description(0);
|
||||
else
|
||||
m_description->SetLabel(_L("No plugins found for this type."));
|
||||
|
||||
auto* button_sizer = new wxStdDialogButtonSizer();
|
||||
auto* ok_button = new wxButton(this, wxID_OK);
|
||||
ok_button->Enable(has_capabilities);
|
||||
button_sizer->AddButton(ok_button);
|
||||
button_sizer->AddButton(new wxButton(this, wxID_CANCEL));
|
||||
button_sizer->Realize();
|
||||
auto dlg_btns = new DialogButtons(this, {"OK", "Cancel"});
|
||||
|
||||
top_sizer->Add(button_sizer, 0, wxALL | wxALIGN_RIGHT, 10);
|
||||
dlg_btns->GetOK()->Bind(wxEVT_BUTTON, [this](wxCommandEvent &e) { EndModal(wxID_OK); });
|
||||
dlg_btns->GetOK()->Enable(has_capabilities);
|
||||
|
||||
dlg_btns->GetCANCEL()->Bind(wxEVT_BUTTON, [this](wxCommandEvent &e) { EndModal(wxID_CANCEL); });
|
||||
|
||||
top_sizer->Add(dlg_btns, 0, wxEXPAND);
|
||||
|
||||
SetSizerAndFit(top_sizer);
|
||||
|
||||
wxGetApp().UpdateDlgDarkUI(this);
|
||||
}
|
||||
|
||||
PluginPickerDialog::CapabilityEntry PluginPickerDialog::selected_capability() const
|
||||
@@ -185,4 +214,6 @@ void PluginPickerDialog::update_description(int selection)
|
||||
Layout();
|
||||
}
|
||||
|
||||
void PluginPickerDialog::on_dpi_changed(const wxRect &suggested_rect) {}
|
||||
|
||||
}} // namespace Slic3r::GUI
|
||||
|
||||
@@ -11,9 +11,12 @@
|
||||
|
||||
#include "slic3r/plugin/PluginManager.hpp"
|
||||
|
||||
#include "GUI_Utils.hpp"
|
||||
#include "Widgets/ComboBox.hpp"
|
||||
|
||||
namespace Slic3r { namespace GUI {
|
||||
|
||||
class PluginPickerDialog : public wxDialog
|
||||
class PluginPickerDialog : public DPIDialog
|
||||
{
|
||||
public:
|
||||
// Entry for capability-level selection (plugin_type non-empty path).
|
||||
@@ -40,13 +43,15 @@ public:
|
||||
// Returns the {plugin_key, name} of the selected capability (capability path).
|
||||
CapabilityEntry selected_capability() const;
|
||||
|
||||
void on_dpi_changed(const wxRect &suggested_rect) override;
|
||||
|
||||
private:
|
||||
void build_ui(const wxString& plugin_type_label);
|
||||
void build_capability_ui(const wxString& plugin_type_label);
|
||||
void update_description(int selection);
|
||||
void update_capability_description(int selection);
|
||||
|
||||
wxChoice* m_choice { nullptr };
|
||||
ComboBox* m_choice { nullptr };
|
||||
wxStaticText* m_description { nullptr };
|
||||
std::vector<Slic3r::PluginDescriptor> m_plugins;
|
||||
std::vector<CapabilityEntry> m_capabilities;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define slic3r_PluginsDialog_hpp_
|
||||
|
||||
#include "Widgets/WebViewHostDialog.hpp"
|
||||
#include "Widgets/ProgressDialog.hpp"
|
||||
#include "PluginSource.hpp"
|
||||
#include "PluginStatus.hpp"
|
||||
#include "PluginSort.hpp"
|
||||
@@ -107,12 +108,12 @@ private:
|
||||
const wxString& title,
|
||||
const wxString& message,
|
||||
int maximum = 100,
|
||||
int style = wxPD_APP_MODAL | wxPD_AUTO_HIDE,
|
||||
int style = wxPD_APP_MODAL | wxPD_AUTO_HIDE, // | wxPD_CAN_ABORT for cancel button
|
||||
bool finish_after_dialog_destroyed = false)
|
||||
{
|
||||
const auto alive = m_alive;
|
||||
wxProgressDialog* progress = new wxProgressDialog(title, message, maximum, this, style);
|
||||
wxTimer* timer = new wxTimer();
|
||||
ProgressDialog* progress = new ProgressDialog(title, message, maximum, this, style);
|
||||
wxTimer* timer = new wxTimer();
|
||||
|
||||
timer->Bind(wxEVT_TIMER, [alive, progress, message](wxTimerEvent&) {
|
||||
if (alive->load(std::memory_order_acquire) && progress)
|
||||
|
||||
@@ -183,7 +183,9 @@ private:
|
||||
HyperLink* m_hyperlink{nullptr}; // ORCA
|
||||
wxBoxSizer * m_sizer_my_devices{nullptr};
|
||||
wxBoxSizer * m_sizer_other_devices{nullptr};
|
||||
#if defined(__WINDOWS__)
|
||||
wxBoxSizer * m_sizer_search_bar{nullptr};
|
||||
#endif
|
||||
wxSearchCtrl* m_search_bar{nullptr};
|
||||
wxScrolledWindow * m_scrolledWindow{nullptr};
|
||||
wxTimer * m_refresh_timer{nullptr};
|
||||
|
||||
@@ -134,7 +134,9 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
#if defined(__WXMSW__) || defined(__APPLE__)
|
||||
int m_suspended_count = 0;
|
||||
#endif
|
||||
};
|
||||
|
||||
static bool needs_filament_swatch_border(const wxColour& colour)
|
||||
|
||||
@@ -178,7 +178,7 @@ bool ProgressDialog::Create(const wxString &title, const wxString &message, int
|
||||
wxBoxSizer *sizer_1line = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_msg = new wxStaticText(m_panel_1line, wxID_ANY, wxEmptyString, wxDefaultPosition, PROGRESSDIALOG_SIMPLEBOOK_SIZE, 0);
|
||||
m_msg->Wrap(-1);
|
||||
m_msg->SetFont(::Label::Body_13);
|
||||
m_msg->SetFont(::Label::Body_14);
|
||||
m_msg->SetForegroundColour(PROGRESSDIALOG_GREY_700);
|
||||
sizer_1line->Add(m_msg, 0, wxALIGN_CENTER, 0);
|
||||
m_panel_1line->SetSizer(sizer_1line);
|
||||
@@ -188,7 +188,7 @@ bool ProgressDialog::Create(const wxString &title, const wxString &message, int
|
||||
wxBoxSizer *sizer_2line = new wxBoxSizer(wxVERTICAL);
|
||||
m_msg_2line = new wxStaticText(m_panel_2line, wxID_ANY, wxEmptyString, wxDefaultPosition, PROGRESSDIALOG_SIMPLEBOOK_SIZE, 0);
|
||||
m_msg_2line->Wrap(PROGRESSDIALOG_SIMPLEBOOK_SIZE.x);
|
||||
m_msg_2line->SetFont(::Label::Body_13);
|
||||
m_msg_2line->SetFont(::Label::Body_14);
|
||||
m_msg_2line->SetForegroundColour(PROGRESSDIALOG_GREY_700);
|
||||
m_msg_2line->SetMaxSize(wxSize(PROGRESSDIALOG_SIMPLEBOOK_SIZE.x, -1));
|
||||
sizer_2line->Add(m_msg_2line, 1, wxALL, 0);
|
||||
@@ -204,7 +204,7 @@ bool ProgressDialog::Create(const wxString &title, const wxString &message, int
|
||||
|
||||
m_msg = new wxStaticText(m_msg_scrolledWindow, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(PROGRESSDIALOG_SIMPLEBOOK_SIZE.x, -1), 0);
|
||||
m_msg->Wrap(PROGRESSDIALOG_SIMPLEBOOK_SIZE.x);
|
||||
m_msg->SetFont(::Label::Body_13);
|
||||
m_msg->SetFont(::Label::Body_14);
|
||||
m_msg->SetForegroundColour(PROGRESSDIALOG_GREY_700);
|
||||
|
||||
m_msg_sizer->Add(m_msg, 0, wxEXPAND | wxALL, 0);
|
||||
@@ -228,6 +228,9 @@ bool ProgressDialog::Create(const wxString &title, const wxString &message, int
|
||||
if (!HasPDFlag(wxPD_NO_PROGRESS)) {
|
||||
m_gauge = new wxGauge(this, wxID_ANY, maximum, wxDefaultPosition, PROGRESSDIALOG_GAUGE_SIZE, gauge_style);
|
||||
m_gauge->SetValue(0);
|
||||
m_gauge->SetForegroundColour(wxColour("#009688"));
|
||||
m_gauge->SetBackgroundColour(wxColour("#D9D9D9"));
|
||||
wxGetApp().UpdateDarkUI(m_gauge);
|
||||
m_sizer_main->Add(m_gauge, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(28));
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ class WXDLLIMPEXP_FWD_CORE wxWindowDisabler;
|
||||
#define PROGRESSDIALOG_GAUGE_SIZE wxSize(FromDIP(320), FromDIP(6))
|
||||
#define PROGRESSDIALOG_CANCEL_BUTTON_SIZE wxSize(FromDIP(60), FromDIP(24))
|
||||
#define PROGRESSDIALOG_DEF_BK wxColour(255,255,255)
|
||||
#define PROGRESSDIALOG_GREY_700 wxColour(107,107,107)
|
||||
#define PROGRESSDIALOG_GREY_700 wxColour(54,54,54) // #363636 label color
|
||||
|
||||
#define wxPD_NO_PROGRESS 0x0100
|
||||
|
||||
|
||||
@@ -331,7 +331,9 @@ void Serial::set_baud_rate(unsigned baud_rate)
|
||||
speed_t c_ispeed;
|
||||
speed_t c_ospeed;
|
||||
};
|
||||
#ifndef BOTHER
|
||||
#define BOTHER CBAUDEX
|
||||
#endif
|
||||
|
||||
termios2 ios;
|
||||
handle_errno(::ioctl(handle, TCGETS2, &ios));
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include "libslic3r/BoundingBox.hpp"
|
||||
#include "libslic3r/ClipperUtils.hpp"
|
||||
#include "libslic3r/ExPolygon.hpp"
|
||||
#include "libslic3r/Print.hpp"
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
|
||||
using namespace Slic3r;
|
||||
using namespace Slic3r::arrangement;
|
||||
@@ -24,11 +26,13 @@ ArrangePolygon make_square(coord_t side)
|
||||
return ap;
|
||||
}
|
||||
|
||||
ArrangePolygons squares(int n, double side_mm)
|
||||
ArrangePolygons squares(int n, double side_mm, double height_mm = 0.)
|
||||
{
|
||||
ArrangePolygons items;
|
||||
for (int i = 0; i < n; ++i)
|
||||
for (int i = 0; i < n; ++i) {
|
||||
items.emplace_back(make_square(scaled(side_mm)));
|
||||
items.back().height = height_mm;
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
@@ -82,6 +86,38 @@ void require_no_overlap(const ArrangePolygons &items)
|
||||
REQUIRE(disjoint(placed_shapes(items)));
|
||||
}
|
||||
|
||||
// The sequential-print floor is chosen by comparing object height against the nozzle,
|
||||
// so the two are defined together and every expectation is derived from them.
|
||||
constexpr double NOZZLE_HEIGHT_MM = 2.5;
|
||||
constexpr double CLEARANCE_MM = 30.;
|
||||
constexpr double NOZZLE_FLOOR_MM = MAX_OUTER_NOZZLE_DIAMETER / 2.;
|
||||
|
||||
ArrangeParams seq_print_params(coord_t min_dist)
|
||||
{
|
||||
ArrangeParams p = quiet_params(min_dist);
|
||||
p.is_seq_print = true;
|
||||
p.clearance_radius = float(CLEARANCE_MM);
|
||||
p.nozzle_height = float(NOZZLE_HEIGHT_MM);
|
||||
p.object_skirt_offset = 0.f;
|
||||
return p;
|
||||
}
|
||||
|
||||
// update_selected_items_inflation reads the bed out of the config to cap inflation.
|
||||
DynamicPrintConfig bed_config()
|
||||
{
|
||||
DynamicPrintConfig c;
|
||||
c.set_key_value("printable_area", new ConfigOptionPoints{{0, 0}, {200, 0}, {200, 200}, {0, 200}});
|
||||
return c;
|
||||
}
|
||||
|
||||
ArrangePolygons squares_of_heights(const std::vector<double> &heights_mm)
|
||||
{
|
||||
ArrangePolygons items;
|
||||
for (double height_mm : heights_mm)
|
||||
items.push_back(squares(1, 20., height_mm).front());
|
||||
return items;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// Prove the overlap check the other tests rely on actually detects overlap.
|
||||
@@ -222,3 +258,61 @@ TEST_CASE("Arrange aligns the pile to a custom center", "[Arrange]")
|
||||
REQUIRE(ap.bed_idx == 0);
|
||||
require_no_overlap(items);
|
||||
}
|
||||
|
||||
TEST_CASE("Sequential print floors the object distance by object height", "[Arrange]")
|
||||
{
|
||||
// The only place sequential-print clearance is enforced. The arrange menu offers
|
||||
// no floor of its own, so a stored 0 has to be raised here or not at all.
|
||||
struct Case
|
||||
{
|
||||
std::string description;
|
||||
std::vector<double> heights;
|
||||
double skirt_offset_mm;
|
||||
double expected_floor_mm;
|
||||
};
|
||||
|
||||
auto c = GENERATE(values<Case>({
|
||||
{"objects taller than the nozzle need the full clearance", {NOZZLE_HEIGHT_MM * 2, NOZZLE_HEIGHT_MM * 2}, 0., CLEARANCE_MM},
|
||||
{"an object exactly at the nozzle height counts as tall", {NOZZLE_HEIGHT_MM, NOZZLE_HEIGHT_MM}, 0., CLEARANCE_MM},
|
||||
{"one tall object among short ones is enough", {NOZZLE_HEIGHT_MM / 2, NOZZLE_HEIGHT_MM * 2}, 0., CLEARANCE_MM},
|
||||
{"objects the nozzle clears keep only the nozzle-width floor", {NOZZLE_HEIGHT_MM / 2, NOZZLE_HEIGHT_MM / 2}, 0., NOZZLE_FLOOR_MM},
|
||||
{"a wide skirt raises the floor for short objects", {NOZZLE_HEIGHT_MM / 2, NOZZLE_HEIGHT_MM / 2}, 3., 6.},
|
||||
}));
|
||||
|
||||
DYNAMIC_SECTION(c.description)
|
||||
{
|
||||
ArrangePolygons items = squares_of_heights(c.heights);
|
||||
DynamicPrintConfig cfg = bed_config();
|
||||
ArrangeParams p = seq_print_params(0);
|
||||
p.object_skirt_offset = float(c.skirt_offset_mm);
|
||||
|
||||
update_selected_items_inflation(items, &cfg, p);
|
||||
|
||||
CHECK(p.min_obj_distance >= scaled(c.expected_floor_mm));
|
||||
CHECK(p.min_obj_distance <= scaled(c.expected_floor_mm + 0.01));
|
||||
// Half each, so a pair ends up a full min_obj_distance apart.
|
||||
CHECK(items.front().inflation == p.min_obj_distance / 2);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Sequential print keeps an object distance already above the floor", "[Arrange]")
|
||||
{
|
||||
const coord_t stored = scaled(CLEARANCE_MM * 2);
|
||||
ArrangePolygons items = squares_of_heights({NOZZLE_HEIGHT_MM * 2, NOZZLE_HEIGHT_MM * 2});
|
||||
DynamicPrintConfig cfg = bed_config();
|
||||
ArrangeParams p = seq_print_params(stored);
|
||||
|
||||
update_selected_items_inflation(items, &cfg, p);
|
||||
CHECK(p.min_obj_distance == stored);
|
||||
}
|
||||
|
||||
TEST_CASE("Layered printing does not floor the object distance", "[Arrange]")
|
||||
{
|
||||
ArrangePolygons items = squares_of_heights({NOZZLE_HEIGHT_MM * 2, NOZZLE_HEIGHT_MM * 2});
|
||||
DynamicPrintConfig cfg = bed_config();
|
||||
ArrangeParams p = seq_print_params(0);
|
||||
p.is_seq_print = false;
|
||||
|
||||
update_selected_items_inflation(items, &cfg, p);
|
||||
CHECK(p.min_obj_distance == 0);
|
||||
}
|
||||
|
||||
@@ -1091,3 +1091,73 @@ TEST_CASE("get_filament_type treats empty vector options as absent", "[Config][F
|
||||
REQUIRE(displayed == "Sup.PLA");
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// min_object_distance reads exactly these three options.
|
||||
DynamicPrintConfig spacing_config(PrinterTechnology tech, PrintSequence seq, double clearance_radius)
|
||||
{
|
||||
DynamicPrintConfig c;
|
||||
c.set_key_value("printer_technology", new ConfigOptionEnum<PrinterTechnology>(tech));
|
||||
c.set_key_value("print_sequence", new ConfigOptionEnum<PrintSequence>(seq));
|
||||
c.set_key_value("extruder_clearance_radius", new ConfigOptionFloat(clearance_radius));
|
||||
return c;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST_CASE("min_object_distance floors object spacing per print sequence", "[Config]")
|
||||
{
|
||||
struct Case
|
||||
{
|
||||
std::string description;
|
||||
PrinterTechnology tech;
|
||||
PrintSequence sequence;
|
||||
double clearance_radius;
|
||||
double expected;
|
||||
};
|
||||
|
||||
auto c = GENERATE(values<Case>({
|
||||
{"sequential FFF takes a clearance radius above the floor", ptFFF, PrintSequence::ByObject, 12., 12.},
|
||||
{"sequential FFF holds the floor at the radius", ptFFF, PrintSequence::ByObject, 6., 6.},
|
||||
{"sequential FFF holds the floor below the radius", ptFFF, PrintSequence::ByObject, 4., 6.},
|
||||
{"layered FFF ignores the clearance radius", ptFFF, PrintSequence::ByLayer, 12., 6.},
|
||||
{"SLA is a flat 6mm", ptSLA, PrintSequence::ByObject, 12., 6.},
|
||||
{"SLA ignores the print sequence too", ptSLA, PrintSequence::ByLayer, 12., 6.},
|
||||
}));
|
||||
|
||||
DYNAMIC_SECTION(c.description)
|
||||
{
|
||||
CHECK_THAT(min_object_distance(spacing_config(c.tech, c.sequence, c.clearance_radius)),
|
||||
Catch::Matchers::WithinAbs(c.expected, 1e-9));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("min_object_distance yields no floor when an FFF config lacks the options", "[Config]")
|
||||
{
|
||||
// Missing options yield 0 rather than an error, so a caller gets no floor at all.
|
||||
SECTION("no clearance radius") {
|
||||
DynamicPrintConfig c;
|
||||
c.set_key_value("printer_technology", new ConfigOptionEnum<PrinterTechnology>(ptFFF));
|
||||
c.set_key_value("print_sequence", new ConfigOptionEnum<PrintSequence>(PrintSequence::ByObject));
|
||||
CHECK_THAT(min_object_distance(c), Catch::Matchers::WithinAbs(0., 1e-9));
|
||||
}
|
||||
|
||||
SECTION("no print sequence") {
|
||||
DynamicPrintConfig c;
|
||||
c.set_key_value("printer_technology", new ConfigOptionEnum<PrinterTechnology>(ptFFF));
|
||||
c.set_key_value("extruder_clearance_radius", new ConfigOptionFloat(12.));
|
||||
CHECK_THAT(min_object_distance(c), Catch::Matchers::WithinAbs(0., 1e-9));
|
||||
}
|
||||
|
||||
SECTION("nothing at all") {
|
||||
CHECK_THAT(min_object_distance(DynamicPrintConfig{}), Catch::Matchers::WithinAbs(0., 1e-9));
|
||||
}
|
||||
|
||||
SECTION("an unset printer technology is treated as FFF") {
|
||||
DynamicPrintConfig c;
|
||||
c.set_key_value("print_sequence", new ConfigOptionEnum<PrintSequence>(PrintSequence::ByObject));
|
||||
c.set_key_value("extruder_clearance_radius", new ConfigOptionFloat(12.));
|
||||
CHECK_THAT(min_object_distance(c), Catch::Matchers::WithinAbs(12., 1e-9));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user