Merge branch 'main' into weilun/speed_dial

# Conflicts:
#	src/slic3r/GUI/Tab.cpp
This commit is contained in:
Lam Wei Lun
2026-09-14 10:37:16 +08:00
136 changed files with 1439 additions and 557 deletions
+17 -22
View File
@@ -1,5 +1,5 @@
name: 🐞 Bug Report
description: File a bug report
description: Something behaves incorrectly while Orca Slicer keeps running
labels: ["bug"]
body:
- type: markdown
@@ -10,6 +10,8 @@ body:
Please note that this is not the place to make feature requests or ask for help.
For this, please use the [Feature request](https://github.com/OrcaSlicer/OrcaSlicer/issues/new?assignees=&labels=&projects=&template=feature_request.yml) issue type or you can discuss your idea on our [Discord server](https://discord.gg/P4VE9UY9gJ) with others.
If Orca Slicer closes on its own, freezes or stops responding, please use the [Crash report](https://github.com/OrcaSlicer/OrcaSlicer/issues/new?assignees=&labels=&projects=&template=crash_report.yml) form instead. It asks for the logs a crash needs.
Before filing, please check if the issue already exists (either open or closed) by using the search bar on the issues page. If it does, comment there. Even if it's closed, we can reopen it based on your comment.
- type: checkboxes
attributes:
@@ -47,7 +49,7 @@ body:
id: os_type
attributes:
label: "Operating System (OS)"
description: "What OSes are you are experiencing issues on?"
description: "What OSes are you experiencing issues on?"
multiple: true
options:
- Linux
@@ -86,7 +88,7 @@ body:
id: reproduce_steps
attributes:
label: How to reproduce
description: Please described the detailed steps to reproduce this issue
description: Please describe the detailed steps to reproduce this issue
placeholder: |
1. Go to '...'
2. Click on '...'
@@ -108,28 +110,23 @@ body:
description: What should happen after the above steps?
validations:
required: true
- type: markdown
id: file_required
attributes:
value: |
Please be sure to add the following files:
* Please upload a ZIP archive containing the **project file** used when the problem arise. Please export it just before or after the problem occurs. Even if you did nothing and/or there is no object, export it! (We need the configurations in project file).
You can export the project file from the application menu in `File`->`Save project as...`, then zip it
* A **log file** for crashes and similar issues.
You can find your log file here:
Windows: `%APPDATA%\OrcaSlicer\log` or usually `C:\Users\<your username>\AppData\Roaming\OrcaSlicer\log`
MacOS: `$HOME/Library/Application Support/OrcaSlicer/log`
Linux: `$HOME/.config/OrcaSlicer/log`
If Orca Slicer still starts, you can also reach this directory from the application menu in `Help` -> `Show Configuration Folder`
You can zip the log directory, or just select the newest logs when this issue happens, and zip them
- type: textarea
id: file_uploads
attributes:
label: Project file & Debug log uploads
description: Drop the project file and debug log here
description: |
Attach the files with the **Paste, drop, or click to add files** control directly underneath this box. Zip anything that is not a `.log`, `.txt` or image, since GitHub rejects other file types, and keep each file under 25 MB.
* The **project file** used when the problem happened, zipped. Export it just before or after the problem occurs. Even if you did nothing and there is no object on the plate, export it, since we need the configuration it carries. `File` -> `Save project as...`
* The **log folder**, zipped. `Help` -> `Show Configuration Folder` opens it, or find it at:
* Windows: `%APPDATA%\OrcaSlicer\log`, usually `C:\Users\<you>\AppData\Roaming\OrcaSlicer\log`
* macOS: `$HOME/Library/Application Support/OrcaSlicer/log`
* Linux: `$HOME/.config/OrcaSlicer/log`
* Flatpak: `$HOME/.var/app/com.orcaslicer.OrcaSlicer/config/OrcaSlicer/log`
* If the zip comes out over 25 MB, attach the newest logs from that folder on their own instead.
placeholder: |
Project File: `File` -> `Save project as...` then zip it & drop it here
Log File: `Help` -> `Show Configuration Folder`, then zip the log directory, or just select the newest logs in `log` when this issue happens and zip them, then drop the zip file here
Zipped project file
Zipped log folder
validations:
required: true
- type: checkboxes
@@ -144,7 +141,5 @@ body:
label: Anything else?
description: |
Screenshots? References? Anything that will give us more context about the issue you are encountering!
Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
validations:
required: false
+183
View File
@@ -0,0 +1,183 @@
name: 💥 Crash Report
description: Orca Slicer closes on its own, freezes or stops responding
labels: ["crash"]
body:
- type: markdown
attributes:
value: |
**Thank you for taking the time to report a crash.**
Use this form when Orca Slicer closes on its own, freezes, or stops responding.
If the application stays open and only produces a wrong result, please use the [Bug report](https://github.com/OrcaSlicer/OrcaSlicer/issues/new?assignees=&labels=&projects=&template=bug_report.yml) form instead.
A printer whose toolhead collides with the print is also a bug report rather than a crash, since the application itself did not stop.
Before filing, please check if the issue already exists (either open or closed) by using the search bar on the issues page. If it does, comment there. Even if it's closed, we can reopen it based on your comment.
- type: checkboxes
attributes:
label: Is this crash reproducible in the latest nightly build?
description: >
Please verify this crash still happens in the latest nightly build first. It may already be fixed there:
[Nightly builds](https://github.com/OrcaSlicer/OrcaSlicer/releases/tag/nightly-builds).
options:
- label: I have checked the latest nightly build and the crash is still reproducible
required: true
- type: checkboxes
attributes:
label: Is there an existing issue for this crash?
description: Please search to see if an issue already exists for the crash you encountered.
options:
- label: I have searched the existing issues
required: true
- type: input
id: version
attributes:
label: OrcaSlicer Version
description: Which version of Orca Slicer are you running? You can see the full version in `Help` -> `About Orca Slicer`.
placeholder: e.g. 2.5.0
validations:
required: true
- type: input
id: working_version
attributes:
label: Regression compared to a previous version
description: Did it work in a previous version?
placeholder: e.g. 2.3.2
validations:
required: false
- type: dropdown
id: os_type
attributes:
label: "Operating System (OS)"
description: "What OSes are you seeing the crash on?"
multiple: true
options:
- Linux
- macOS
- Windows
validations:
required: true
- type: input
id: os_version
attributes:
label: "OS Version"
description: "What OS version does this relate to?"
placeholder: "i.e. OS: Windows 7/8/10/11 ..., Ubuntu 22.04/Fedora 36 ..., macOS 10.15/11.1/12.3 ..."
validations:
required: true
- type: input
id: printer
attributes:
label: Printer
description: Which printer was selected
placeholder: Voron 2.4/VzBot/Prusa MK4/Bambu Lab X1 series/Bambu Lab P1P/...
validations:
required: true
- type: dropdown
id: crash_moment
attributes:
label: When does the crash happen?
description: Pick the point where Orca Slicer stops working.
options:
- Not sure
- On startup, before the main window appears
- When opening or importing a project or model
- While changing printer, filament or process settings
- While slicing
- In the 3D view, Preview or Assembly view
- When exporting G-code or sending a print to the printer
- On the Device tab, or connecting to a printer (camera, sync, login)
- While using a specific tool, dialog or calibration
- After resuming from sleep or changing monitors
- When closing the application
- No clear pattern
validations:
required: true
- type: dropdown
id: crash_frequency
attributes:
label: How often does it happen?
options:
- Not sure
- Every time
- Often, but not every time
- Rarely
- It only happened once
validations:
required: true
- type: dropdown
id: fresh_config
attributes:
label: Does it still crash with a fresh configuration?
description: >
Close Orca Slicer and rename your configuration folder (`%APPDATA%\OrcaSlicer` on Windows,
`$HOME/Library/Application Support/OrcaSlicer` on macOS, `$HOME/.config/OrcaSlicer` on Linux),
then start it again. Renaming keeps your settings, so you can put the folder back afterwards.
options:
- I have not tried this
- Yes, it still crashes
- No, the crash goes away
validations:
required: true
- type: textarea
id: reproduce_steps
attributes:
label: How to reproduce
description: Please describe the detailed steps that lead to the crash.
placeholder: |
1. Go to '...'
2. Click on '...'
3. Scroll down to '...'
4. Orca Slicer closes
validations:
required: true
- type: textarea
id: system_info
attributes:
label: Additional system information
description: >
Display card and driver version are worth adding for crashes on startup or in the 3D view.
CPU and memory are worth adding for crashes while slicing.
placeholder: |
CPU: 11th gen Intel r core tm i7-1185g7/AMD Ryzen 7 6800h/...
Memory: 32/16 GB...
Display Card: NVIDIA Quadro P400/...
validations:
required: false
- type: textarea
id: file_uploads
attributes:
label: Project file, logs and crash report uploads
description: |
A crash report without logs usually cannot be acted on. Attach the files with the **Paste, drop, or click to add files** control directly underneath this box. Zip anything that is not a `.log`, `.txt` or image, since GitHub rejects other file types, and keep each file under 25 MB.
* The **project file** used when the crash happened, zipped. Export it just before or after the crash, even if the plate is empty, since we need the configuration it carries. `File` -> `Save project as...`
* The whole **log folder**, zipped rather than single files picked out of it. `Help` -> `Show Configuration Folder` opens it, or find it at:
* Windows: `%APPDATA%\OrcaSlicer\log`, usually `C:\Users\<you>\AppData\Roaming\OrcaSlicer\log`
* macOS: `$HOME/Library/Application Support/OrcaSlicer/log`
* Linux: `$HOME/.config/OrcaSlicer/log`
* Flatpak: `$HOME/.var/app/com.orcaslicer.OrcaSlicer/config/OrcaSlicer/log`
* On Windows the crash itself is written to a separate `crash_*.log` in there, and that is the file we need most. If the zip comes out over 25 MB GitHub will refuse it, so attach the newest log and any `crash_*.log` on their own instead.
* The **operating system crash report**, on macOS and Linux, where Orca Slicer cannot write its own crash log. It is often the only record of where it died:
* macOS: Console.app -> Crash Reports, or `$HOME/Library/Logs/DiagnosticReports/`. The file starts with `OrcaSlicer` and ends in `.ips`. Zip it before attaching, GitHub does not accept `.ips` files.
* Linux: run `orca-slicer` from a terminal (Flatpak: `flatpak run com.orcaslicer.OrcaSlicer`) and paste everything it prints when it dies. On systemd systems `coredumpctl info orca-slicer` gives a backtrace.
placeholder: |
Zipped project file
Zipped log folder
Zipped macOS .ips crash report, or the terminal output on Linux
validations:
required: true
- type: checkboxes
id: file_checklist
attributes:
label: Checklist of files to include
options:
- label: Log folder
- label: Project file
- label: Operating system crash report (macOS and Linux)
- type: textarea
attributes:
label: Anything else?
description: |
Screenshots? References? Anything that will give us more context about the crash you are encountering!
validations:
required: false
+95 -6
View File
@@ -100,7 +100,7 @@ jobs:
matrix:
include: ${{ fromJSON(vars.SELF_HOSTED
&& '[{"arch":"x64","os":"orca-win-server","compiler":"clang"}]'
|| '[{"arch":"x64","os":"windows-latest","compiler":"clang"},{"arch":"arm64","os":"windows-11-arm","compiler":"clang"}]') }}
|| '[{"arch":"x64","os":"windows-latest","compiler":"clang"},{"arch":"arm64","os":"windows-11-vs2026-arm","compiler":"clang"}]') }}
needs: check_build_script
# Don't run scheduled builds on forks:
if: ${{ !cancelled() && needs.check_build_script.result == 'success' && (github.event_name != 'schedule' || github.repository == 'OrcaSlicer/OrcaSlicer') }}
@@ -169,7 +169,7 @@ jobs:
if: ${{ !cancelled() && success() && !vars.SELF_HOSTED }}
uses: ./.github/workflows/unit_tests.yml
with:
os: windows-11-arm
os: windows-11-vs2026-arm
artifact: ${{ github.sha }}-tests-windows-arm64
test-dir: build-arm64/tests
unit_tests_macos_arm64:
@@ -283,21 +283,42 @@ 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
id: ccache_restore
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 +329,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 +366,50 @@ 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
# The build has just touched everything it can use, so an object untouched
# for a week is dead, usually orphaned by a flag change.
- name: Compiler cache statistics
if: always()
run: |
export CCACHE_DIR=$PWD/.flatpak-builder/ccache
ccache --evict-older-than 7d
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. A cancelled or
# failed build saves too, since what it compiled is still valid; a restore
# that did not finish does not, since the directory may be a truncated copy.
- name: Save compiler cache
id: ccache_save
if: ${{ always() && steps.ccache_restore.outcome == 'success' && 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: ${{ always() && steps.ccache_save.outcome == 'success' }}
# The container has no gh, so this is the list and delete over the REST API.
# Older means a lower run id, so two runs finishing close together keep
# the newer entry whichever of them cleans up last.
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 prefix "ccache-$CCACHE_LEG-" --argjson run "$GITHUB_RUN_ID" \
'.actions_caches[] | select((.key | ltrimstr($prefix) | split("-")[0] | tonumber?) < $run) | .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:
+92
View File
@@ -76,6 +76,60 @@ 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.24
with:
key: ${{ env.CCACHE_LEG }}
max-size: 3G
restore: false
save: false
# ccache -s runs as its own step; no summary table per job.
job-summary: ''
- name: Restore compiler cache
id: ccache_restore
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 +724,41 @@ jobs:
asset_name: orca_custom_preset_tests.zip
asset_content_type: application/octet-stream
max_releases: 1
# The build has just touched everything it can use, so an object
# untouched for a week is dead, usually orphaned by a flag change.
- name: Compiler cache statistics
if: ${{ always() && steps.ccache.outcome == 'success' }}
shell: bash
run: |
ccache --evict-older-than 7d
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. A cancelled or failed build saves
# too, since what it compiled is still valid; a restore that did not
# finish does not, since the directory may be a truncated copy.
- name: Save compiler cache
id: ccache_save
if: ${{ always() && steps.ccache_restore.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: ${{ always() && steps.ccache_save.outcome == 'success' }}
# A read-only token (fork PRs) cannot delete; that only costs storage.
# Older means a lower run id, so two runs finishing close together keep
# the newer entry whichever of them cleans up last.
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 prefix "ccache-$CCACHE_LEG-" --argjson run "$GITHUB_RUN_ID" \
'.[] | select((.key | ltrimstr($prefix) | split("-")[0] | tonumber?) < $run) | .id' \
| tr -d '\r' \
| while read -r id; do gh cache delete "$id"; done
+12 -5
View File
@@ -19,11 +19,18 @@ jobs:
permissions:
contents: read
steps:
- uses: thejerrybao/setup-swap-space@v1
with:
swap-space-path: /swapfile
swap-size-gb: 8
remove-existing-swap-files: true
# Doxygen with call graphs over all of src/ outgrows the runner's RAM;
# replace the runner's swapfile with an 8 GB one.
- name: Grow swap space
run: |
set -euo pipefail
sudo swapoff -a
sudo rm -f /swapfile
sudo fallocate -l 8G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
free -h
- name: Checkout repository
uses: actions/checkout@v7
+95 -52
View File
@@ -4,6 +4,10 @@ endif()
cmake_minimum_required(VERSION 3.13)
if(POLICY CMP0177)
cmake_policy(SET CMP0177 NEW)
endif()
# The following line used to be in tests/CMakeLists.txt
# Having it there causes rebuilds of all targets on any CMakeLists.txt change under tests/
@@ -553,59 +557,101 @@ if ((NOT MSVC OR IS_CLANG_CL) AND ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR
elseif (NOT MINGW)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall" )
endif ()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-reorder" )
# On GCC and Clang, no return from a non-void function is a warning only. Here, we make it an error.
add_compile_options(-Werror=return-type)
# Every warning is an error unless it appears in one of the two lists below.
# disabled - never wanted. Off everywhere, so it never warns or errors.
# demoted - wanted, not cleared yet. Still warns, does not error.
# Since some portions of code are just commented out or put under conditional compilation, there are
# a bunch of warning related to unused functions and variables. Suppress those warnings to not pollute
# compilers diagnostics output with warnings we not going to look at
add_compile_options(-Wno-unused-function -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-label -Wno-unused-local-typedefs)
# Disabled.
set(warnings_disabled
reorder # members initialised in an order we chose
sign-compare # signed/unsigned comparisons throughout
misleading-indentation # false positives on mixed tabs and spaces
switch # unhandled enum value in a switch
unused-function # commented-out or conditionally compiled code
unused-variable # commented-out or conditionally compiled code
unused-but-set-variable # commented-out or conditionally compiled code
unused-label # commented-out or conditionally compiled code
unused-local-typedefs # commented-out or conditionally compiled code
)
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
list(APPEND warnings_disabled deprecated-declarations) # legacy OpenGL calls
endif ()
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 6.0)
list(APPEND warnings_disabled ignored-attributes) # from Eigen headers marked SYSTEM
endif ()
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
list(APPEND warnings_disabled unknown-pragmas) # igl pragmas, GCC bug 66943
endif ()
foreach (w IN LISTS warnings_disabled)
add_compile_options(-Wno-${w})
endforeach ()
# Ignore signed/unsigned comparison warnings
add_compile_options(-Wno-sign-compare)
# Turn everything else into an error. Dependency headers are exempt because the SYSTEM
# include flag (-imsvc on clang-cl, -isystem elsewhere) keeps their diagnostics out,
# apart from GCC's maybe-uninitialized, demoted below.
add_compile_options(-Werror)
# The mismatch of tabs and spaces throughout the project can sometimes
# cause this warning to appear even though the indentation is fine.
# Some includes also cause the warning
add_compile_options(-Wno-misleading-indentation)
# Demoted. Remove a name once its category is cleared on every compiler.
set(warnings_demoted)
if (APPLE)
list(APPEND warnings_demoted
# MacDarkMode.mm makes two calls to AppKit's private titlebarViewController
# and one to a wxWidgets category on NSTableColumn whose header is not
# imported. Clearing it means declaring the private selectors ourselves, which
# needs a macOS build to verify.
objc-method-access
)
endif ()
if (WIN32 AND CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64")
list(APPEND warnings_demoted
# About two dozen GetProcAddress casts, most in the vendored dark_mode.hpp,
# retype FARPROC to a real signature. The __stdcall typedefs are identical to
# FARPROC on x64, so only arm64 reports them. Clearing them is a separate
# sweep.
cast-function-type-mismatch
)
endif ()
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
list(APPEND warnings_demoted
# maybe-uninitialized runs after inlining and reports inside boost/variant,
# boost/tuple and the bundled clipper header even with -isystem.
maybe-uninitialized
# Disable warning if enum value does not have a corresponding case in switch statement
add_compile_options(-Wno-switch)
# array-bounds is reported once, where ConfigOptionVector::set_at inlines
# into OrcaSlicer.cpp on a branch the preceding type test rules out.
array-bounds
# removes LOTS of extraneous Eigen warnings (GCC only supports it since 6.1)
# https://eigen.tuxfamily.org/bz/show_bug.cgi?id=1221
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 6.0)
add_compile_options(-Wno-ignored-attributes) # Tamas: Eigen include dirs are marked as SYSTEM
endif()
# template-id-cdtor is a GCC 14+ warning in the bundled Clipper2 headers.
template-id-cdtor
)
endif ()
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
list(APPEND warnings_demoted
# enum-constexpr-conversion is a Clang warning that defaults to an error,
# present through clang 20 and gone in clang 21.
enum-constexpr-conversion
)
endif ()
# Clang reports legacy OpenGL calls as deprecated. Turn off the warning for now
# to reduce the clutter, we know about this one. It should be reenabled after
# we finally get rid of the deprecated code.
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
add_compile_options(-Wno-deprecated-declarations)
endif()
if((${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang" OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "AppleClang") AND ${CMAKE_CXX_COMPILER_VERSION} VERSION_GREATER 15)
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag(-Wno-error=enum-constexpr-conversion HAS_WNO_ERROR_ENUM_CONSTEXPR_CONV)
if(HAS_WNO_ERROR_ENUM_CONSTEXPR_CONV)
add_compile_options(-Wno-error=enum-constexpr-conversion)
endif()
endif()
#GCC generates loads of -Wunknown-pragmas when compiling igl. The fix is not easy due to a bug in gcc, see
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66943 or
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53431
# We will turn the warning of for GCC for now:
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
# GCC generates loads of -Wunknown-pragmas when compiling igl. The fix is not easy due to a bug in gcc, see
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66943 or
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53431
# We will turn the warning of for GCC for now:
add_compile_options(-Wno-unknown-pragmas)
endif()
# The list mixes names not every compiler has, so add each exception only where the
# compiler knows the warning. Probe with the positive -W<name>, which an unknown
# warning fails on both compilers (GCC errors, Clang reports unknown-warning-option).
# An option that takes a =N argument rejects the bare -W<name>, so fall back to
# -W<name>=1 and demote with the trailing =.
include(CheckCXXCompilerFlag)
foreach (category IN LISTS warnings_demoted)
string(MAKE_C_IDENTIFIER "ORCA_HAS_W_${category}" _orca_has_w)
check_cxx_compiler_flag("-W${category}" ${_orca_has_w})
if (${_orca_has_w})
add_compile_options(-Wno-error=${category})
else ()
check_cxx_compiler_flag("-W${category}=1" ${_orca_has_w}_arg)
if (${${_orca_has_w}_arg})
add_compile_options(-Wno-error=${category}=)
endif ()
endif ()
endforeach ()
# Compress the debug info with zstd to save space in Flatpak CI builds
if(FLATPAK)
@@ -615,10 +661,6 @@ if ((NOT MSVC OR IS_CLANG_CL) AND ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR
endif()
endif()
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 14)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=template-id-cdtor" )
endif()
endif()
if (SLIC3R_ASAN)
@@ -1208,8 +1250,9 @@ endif ()
if (NOT SLIC3R_WARNINGS)
add_compile_options(-w)
elseif (MSVC AND NOT IS_CLANG_CL)
# /we4715 is C4715, no return from a non-void function, matching the
# -Werror=return-type the GNU/Clang builds apply.
# /we4715 is C4715, no return from a non-void function, an error on the GNU/Clang
# builds under -Werror. MSVC is not in that model, so this stays a single promoted
# warning.
add_compile_options(/W3 /we4715)
endif ()
+7
View File
@@ -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?")
@@ -0,0 +1,29 @@
diff --git a/src/osx/cocoa/colour.mm b/src/osx/cocoa/colour.mm
index 31515d146f..86b33e94a2 100644
--- a/src/osx/cocoa/colour.mm
+++ b/src/osx/cocoa/colour.mm
@@ -125,3 +125,3 @@
wxOSXEffectiveAppearanceSetter helper;
- if ( NSColor* colRGBA = [m_nsColour colorUsingColorSpaceName:NSCalibratedRGBColorSpace] )
+ if ( NSColor* colRGBA = [m_nsColour colorUsingColorSpace:[NSColorSpace sRGBColorSpace]] )
return [colRGBA redComponent];
@@ -134,3 +134,3 @@
wxOSXEffectiveAppearanceSetter helper;
- if ( NSColor* colRGBA = [m_nsColour colorUsingColorSpaceName:NSCalibratedRGBColorSpace] )
+ if ( NSColor* colRGBA = [m_nsColour colorUsingColorSpace:[NSColorSpace sRGBColorSpace]] )
return [colRGBA greenComponent];
@@ -143,3 +143,3 @@
wxOSXEffectiveAppearanceSetter helper;
- if ( NSColor* colRGBA = [m_nsColour colorUsingColorSpaceName:NSCalibratedRGBColorSpace] )
+ if ( NSColor* colRGBA = [m_nsColour colorUsingColorSpace:[NSColorSpace sRGBColorSpace]] )
return [colRGBA blueComponent];
@@ -152,3 +152,3 @@
wxOSXEffectiveAppearanceSetter helper;
- if ( NSColor* colRGBA = [m_nsColour colorUsingColorSpaceName:NSCalibratedRGBColorSpace] )
+ if ( NSColor* colRGBA = [m_nsColour colorUsingColorSpace:[NSColorSpace sRGBColorSpace]] )
return [colRGBA alphaComponent];
@@ -160,3 +160,3 @@
{
- return [m_nsColour colorUsingColorSpaceName:NSCalibratedRGBColorSpace] != nil;
+ return [m_nsColour colorUsingColorSpace:[NSColorSpace sRGBColorSpace]] != nil;
}
+10
View File
@@ -21,12 +21,22 @@ else ()
set(_wx_edge "-DwxUSE_WEBVIEW_EDGE=OFF")
endif ()
set(_wx_patch_command "")
if (APPLE)
set(_wx_patch_command
${GIT_EXECUTABLE} checkout -f -- src/osx/cocoa/colour.mm
COMMAND ${GIT_EXECUTABLE} apply --verbose
${CMAKE_CURRENT_LIST_DIR}/0001-macos-use-srgb-colour-components.patch
)
endif ()
orcaslicer_add_cmake_project(
wxWidgets
GIT_REPOSITORY "https://github.com/SoftFever/Orca-deps-wxWidgets"
GIT_TAG v3.3.2
GIT_SHALLOW ON
GIT_SUBMODULES 3rdparty/catch 3rdparty/pcre 3rdparty/libwebp
PATCH_COMMAND ${_wx_patch_command}
DEPENDS ${PNG_PKG} ${ZLIB_PKG} ${EXPAT_PKG} ${JPEG_PKG}
CMAKE_ARGS
-DwxBUILD_PRECOMP=ON
+1 -3
View File
@@ -5007,9 +5007,7 @@ msgstr ""
#, possible-c-format, possible-boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
#, possible-boost-format
+2 -6
View File
@@ -5441,13 +5441,9 @@ msgstr "El valor %s està fora de rang. El rang vàlid és de %d a %d."
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"És %s%% or %s %s?\n"
"SÍ per %s%%.\n"
"NO per %s %s."
"És %s%% or %s %s?"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+2 -6
View File
@@ -5398,13 +5398,9 @@ msgstr "Hodnota %s je mimo rozsah. Platný rozsah je od %d do %d."
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"Je to %s%% nebo %s %s?\n"
"ANO pro %s%%,\n"
"NE pro %s %s."
"Je to %s%% nebo %s %s?"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+2 -6
View File
@@ -5303,13 +5303,9 @@ msgstr "Wert %s ist außerhalb des Bereichs. Der gültige Bereich liegt zwischen
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"Heißt es %s%% oder %s %s?\n"
"Ja für %s%%, \n"
"Nein für %s %s."
"Heißt es %s%% oder %s %s?"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+1 -3
View File
@@ -5003,9 +5003,7 @@ msgstr ""
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
#, boost-format
+2 -6
View File
@@ -5167,13 +5167,9 @@ msgstr "El valor %s está fuera de rango. El rango válido es de %d a %d."
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"¿Es %s%% o %s %s?\n"
"SÍ para %s%%, \n"
"NO para %s %s."
"¿Es %s%% o %s %s?"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+2 -6
View File
@@ -5215,13 +5215,9 @@ msgstr "%s balioa tartetik kanpo dago. Baliozko tartea %d eta %d artekoa da."
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"%s%% edo %s %s da?\n"
"BAI %s%%-(r)entzat,\n"
"EZ %s %s-(r)entzat."
"%s%% edo %s %s da?"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+2 -6
View File
@@ -5253,13 +5253,9 @@ msgstr "La valeur %s est hors plage. La plage valide est comprise entre %d et %d
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"Est-ce %s%% ou %s %s ?\n"
"OUI pour %s%%, \n"
"NON pour %s %s."
"Est-ce %s%% ou %s %s ?"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+2 -6
View File
@@ -5350,13 +5350,9 @@ msgstr "%s érték tartományon kívül van. Az érvényes tartomány: %d - %d."
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"%s%% vagy %s %s?\n"
"IGEN %s%%, \n"
"NEM %s %s."
"%s%% vagy %s %s?"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+2 -6
View File
@@ -5351,13 +5351,9 @@ msgstr "Il valore %s è fuori intervallo. L'intervallo valido è da %d a %d."
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"È %s%% o %s %s?\n"
"Sì per %s%%, \n"
"NO per %s %s."
"È %s%% o %s %s?"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+2 -5
View File
@@ -5365,12 +5365,9 @@ msgstr "値%sは範囲外です。有効な範囲は%dから%dです。"
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"%s%% か、それとも %s %sですか?\n"
"%s%% の場合ははい、 %s %s はいいえ。"
"%s%% か、それとも %s %sですか?"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+2 -6
View File
@@ -5376,13 +5376,9 @@ msgstr "값 %s이 범위를 벗어났습니다. 유효한 범위는 %d에서 %d
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"%s%% 또는 %s %s입니까?\n"
"%s%%에 대해 예,\n"
"%s %s에 대해 아니요."
"%s%% 또는 %s %s입니까?"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+2 -6
View File
@@ -5337,13 +5337,9 @@ msgstr "Reikšmė %s yra už ribų. Galimas diapazonas yra nuo %d iki %d."
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"Ar tai %s%% ar %s %s?\n"
"TAIP %s%%, \n"
"NE %s %s."
"Ar tai %s%% ar %s %s?"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+2 -6
View File
@@ -5843,13 +5843,9 @@ msgstr "Waarde %s valt buiten het bereik. Het geldige bereik loopt van %d tot %d
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"Is het %s%% or %s %s?\n"
"JA voor %s%%, \n"
"NEE voor %s %s."
"Is het %s%% or %s %s?"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+2 -15
View File
@@ -5464,13 +5464,9 @@ msgstr "Wartość %s jest spoza zakresu. Poprawny zakres wynosi od %d do %d."
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"Czy to %s%% czy %s %s?\n"
"TAK dla %s%%,\n"
"NIE dla %s %s."
"Czy to %s%% czy %s %s?"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
@@ -25507,15 +25503,6 @@ msgstr ""
#~ msgid "Low-temperature filament (PLA/PETG/TPU) is loaded in the extruder. In order to avoid extruder clogging, it is not allowed to set the chamber temperature above 45℃."
#~ msgstr "W ekstruzorze jest załadowany filament o niskiej temperaturze (PLA/PETG/TPU). Aby uniknąć zatkania ekstruzora, nie wolno ustawiać temperatury komory powyżej 45℃."
#~ msgid ""
#~ "Is it %s%% or %s %s?\n"
#~ "YES for %s%%,\n"
#~ "NO for %s %s."
#~ msgstr ""
#~ "Czy to %s%% czy %s %s?\n"
#~ "TAK dla %s%%,\n"
#~ "NIE dla %s %s."
#~ msgid "Allow multiple materials on the same plate"
#~ msgstr "Pozwól na kilka filamentów na tej samej płycie"
+2 -6
View File
@@ -5181,13 +5181,9 @@ msgstr "Valor %s está fora do intervalo. O intervalo válido é de %d para %d."
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"É %s%% ou %s %s?\n"
"SIM para %s%%, \n"
"NÃO para %s %s."
"É %s%% ou %s %s?"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+2 -6
View File
@@ -5347,13 +5347,9 @@ msgstr "Значение %s выходит за пределы допустим
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"Имелось ввиду %s%%? (введено %s %s)\n"
"Да – изменить на %s%%\n"
"Нет оставить %s %s."
"Имелось ввиду %s%% или %s %s?"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+2 -6
View File
@@ -5917,13 +5917,9 @@ msgstr "Värdet %s ligger utanför intervallet. Giltigt intervall är från %d t
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"Det är %s%% eller %s %s?\n"
"JA för %s%%, \n"
"NEJ för %s %s."
"Det är %s%% eller %s %s?"
# AI Translated
#, boost-format
+2 -6
View File
@@ -5331,13 +5331,9 @@ msgstr "ค่า %s อยู่นอกช่วง ช่วงที่ถ
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"มันคือ %s%% หรือ %s %s?\n"
"ใช่สำหรับ %s%% \n"
"ไม่ สำหรับ %s %s"
"มันคือ %s%% หรือ %s %s?"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+2 -6
View File
@@ -5394,13 +5394,9 @@ msgstr "Değer %s aralık dışında. Geçerli aralık %d ile %d arasındadır."
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"%s%% mi yoksa %s %s mi?\n"
"%s%% için EVET,\n"
"%s %s için HAYIR."
"%s%% mi yoksa %s %s mi?"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+2 -6
View File
@@ -5342,13 +5342,9 @@ msgstr "Значення %s знаходиться за межами діапа
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"Це %s%% або %s %s?\n"
"ТАК для %s%%, \n"
"НІ для %s %s."
"Це %s%% або %s %s?"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+2 -6
View File
@@ -5647,13 +5647,9 @@ msgstr "Giá trị %s nằm ngoài phạm vi. Phạm vi hợp lệ từ %d đế
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"Là %s%% hay %s %s?\n"
"YES cho %s%%, \n"
"NO cho %s %s."
"Là %s%% hay %s %s?"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+2 -6
View File
@@ -5187,13 +5187,9 @@ msgstr "值 %s 超出了范围,有效的范围是从 %d 到 %d 。"
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"%s%%还是%s %s\n"
"是:%s%%\n"
"否:%s %s"
"%s%%还是%s %s"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+2 -6
View File
@@ -5316,13 +5316,9 @@ msgstr "數值 %s 超出範圍。有效範圍是從 %d 到 %d。"
#, c-format, boost-format
msgid ""
"Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."
"Is it %s%% or %s %s?"
msgstr ""
"是 %s%% 還是 %s %s\n"
"選『是』代表 %s%%\n"
"選『否』代表 %s %s。"
"是 %s%% 還是 %s %s"
#, boost-format
msgid "Invalid input format. Expected vector of dimensions in the following format: \"%1%\""
+145 -30
View File
@@ -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"
@@ -77,8 +78,9 @@ using namespace nlohmann;
#include "libslic3r/ObjColorUtils.hpp"
#include "OrcaSlicer.hpp"
//BBS: add exception handler for win32
#include <wx/filename.h>
#include <wx/stdpaths.h>
//BBS: add exception handler for win32
#ifdef WIN32
#include "dev-utils/BaseException.h"
#endif
@@ -1466,6 +1468,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 +2052,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 +2686,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 +2710,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 +2730,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 +3034,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 +3179,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 +3373,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 +3394,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 {
+12
View File
@@ -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())
+7 -2
View File
@@ -6308,8 +6308,13 @@ LayerResult GCode::process_layer(
all_label_ids.insert(inst.label_object_id);
break;
}
std::vector<size_t> filament_instances_id(all_label_ids.begin(), all_label_ids.end());
m_filament_instances_code = _encode_label_ids_to_base64(filament_instances_id);
// Orca: A scheduled extruder may have no object instances on this layer.
// Clear any pending mask so it cannot be emitted for the wrong toolchange.
m_filament_instances_code.clear();
if (!all_label_ids.empty()) {
std::vector<size_t> filament_instances_id(all_label_ids.begin(), all_label_ids.end());
m_filament_instances_code = _encode_label_ids_to_base64(filament_instances_id);
}
}
// The inline _extrude hook may already have taken the snapshot mid-extrusion on a
+15 -7
View File
@@ -187,6 +187,12 @@ void Layer::make_perimeters()
{
BOOST_LOG_TRIVIAL(trace) << "Generating perimeters for layer " << this->id();
const auto clear_generated_extrusions = [](LayerRegion *layer_region) {
layer_region->perimeters.clear();
layer_region->fills.clear();
layer_region->thin_fills.clear();
};
// keep track of regions whose perimeters we have already generated
std::vector<unsigned char> done(m_regions.size(), false);
@@ -217,13 +223,11 @@ void Layer::make_perimeters()
if (this_region.gradient_volume_id() != other_region.gradient_volume_id())
continue;
if (is_perimeter_compatible(*m_object->print(), this_region, other_region))
{
other_layerm->perimeters.clear();
other_layerm->fills.clear();
other_layerm->thin_fills.clear();
layerms.push_back(other_layerm);
done[it - m_regions.begin()] = true;
}
{
clear_generated_extrusions(other_layerm);
layerms.push_back(other_layerm);
done[it - m_regions.begin()] = true;
}
}
if (layerms.size() == 1) { // optimization
@@ -231,6 +235,10 @@ void Layer::make_perimeters()
(*layerm)->make_perimeters((*layerm)->slices, {*layerm}, &(*layerm)->fill_surfaces, &(*layerm)->fill_no_overlap_expolygons);
(*layerm)->fill_expolygons = to_expolygons((*layerm)->fill_surfaces.surfaces);
} else {
// Orca: Unlike the compatible regions above, the initiating region has not
// been cleared yet and may contain paths from a previous incompatible run.
clear_generated_extrusions(*layerm);
SurfaceCollection new_slices;
// Use the region with highest infill rate, as the make_perimeters() function below decides on the gap fill based on the infill existence.
LayerRegion *layerm_config = layerms.front();
+2
View File
@@ -3,6 +3,8 @@
#ifdef _WIN32
#include <charconv>
#endif
#include <iomanip>
#include <sstream>
#include <stdexcept>
#include <fast_float/fast_float.h>
+14
View File
@@ -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
+5
View File
@@ -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 {
+6 -6
View File
@@ -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>{});
+43 -41
View File
@@ -1011,41 +1011,46 @@ public: \
{ PrintConfigDef::handle_legacy(opt_key, value); }
#define PRINT_CONFIG_CLASS_ELEMENT_DEFINITION(r, data, elem) BOOST_PP_TUPLE_ELEM(0, elem) BOOST_PP_TUPLE_ELEM(1, elem);
#define PRINT_CONFIG_CLASS_ELEMENT_INITIALIZATION2(KEY) cache.opt_add(BOOST_PP_STRINGIZE(KEY), base_ptr, this->KEY);
#define PRINT_CONFIG_CLASS_ELEMENT_INITIALIZATION(r, data, elem) PRINT_CONFIG_CLASS_ELEMENT_INITIALIZATION2(BOOST_PP_TUPLE_ELEM(1, elem))
#define PRINT_CONFIG_CLASS_ELEMENT_HASH(r, data, elem) boost::hash_combine(seed, BOOST_PP_TUPLE_ELEM(1, elem).hash());
#define PRINT_CONFIG_CLASS_ELEMENT_EQUAL(r, data, elem) if (! (BOOST_PP_TUPLE_ELEM(1, elem) == rhs.BOOST_PP_TUPLE_ELEM(1, elem))) return false;
#define PRINT_CONFIG_CLASS_ELEMENT_LOWER(r, data, elem) \
if (BOOST_PP_TUPLE_ELEM(1, elem) < rhs.BOOST_PP_TUPLE_ELEM(1, elem)) return true; \
if (! (BOOST_PP_TUPLE_ELEM(1, elem) == rhs.BOOST_PP_TUPLE_ELEM(1, elem))) return false;
#define PRINT_CONFIG_CLASS_ELEMENT_VISIT(r, data, elem) if (! f(BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(1, elem)), this->BOOST_PP_TUPLE_ELEM(1, elem), rhs.BOOST_PP_TUPLE_ELEM(1, elem))) return;
// Each option list is expanded into the members and again into for_each_option_pair(), which calls
// f(key, this->option, rhs.option) in declaration order and stops when f returns false. hash(),
// operator==, operator< and initialize() iterate the options through that visitor.
#define PRINT_CONFIG_CLASS_COMMON_BODY(CLASS_NAME) \
size_t hash() const throw() \
{ \
size_t seed = 0; \
this->for_each_option_pair(*this, [&seed](const char*, const auto &a, const auto&) { boost::hash_combine(seed, a.hash()); return true; }); \
return seed; \
} \
bool operator==(const CLASS_NAME &rhs) const throw() \
{ \
bool eq = true; \
this->for_each_option_pair(rhs, [&eq](const char*, const auto &a, const auto &b) { eq = (a == b); return eq; }); \
return eq; \
} \
bool operator!=(const CLASS_NAME &rhs) const throw() { return ! (*this == rhs); } \
bool operator<(const CLASS_NAME &rhs) const throw() \
{ \
int c = 0; \
this->for_each_option_pair(rhs, [&c](const char*, const auto &a, const auto &b) { if (a < b) c = -1; else if (! (a == b)) c = 1; return c == 0; }); \
return c < 0; \
} \
protected: \
void initialize(StaticCacheBase &cache, const char *base_ptr) \
{ \
this->for_each_option_pair(*this, [&cache, base_ptr](const char *key, const auto &a, const auto&) { cache.opt_add(key, base_ptr, a); return true; }); \
}
#define PRINT_CONFIG_CLASS_DEFINE(CLASS_NAME, PARAMETER_DEFINITION_SEQ) \
class CLASS_NAME : public StaticPrintConfig { \
STATIC_PRINT_CONFIG_CACHE(CLASS_NAME) \
public: \
BOOST_PP_SEQ_FOR_EACH(PRINT_CONFIG_CLASS_ELEMENT_DEFINITION, _, PARAMETER_DEFINITION_SEQ) \
size_t hash() const throw() \
template<typename F> void for_each_option_pair(const CLASS_NAME &rhs, F &&f) const \
{ \
size_t seed = 0; \
BOOST_PP_SEQ_FOR_EACH(PRINT_CONFIG_CLASS_ELEMENT_HASH, _, PARAMETER_DEFINITION_SEQ) \
return seed; \
} \
bool operator==(const CLASS_NAME &rhs) const throw() \
{ \
BOOST_PP_SEQ_FOR_EACH(PRINT_CONFIG_CLASS_ELEMENT_EQUAL, _, PARAMETER_DEFINITION_SEQ) \
return true; \
} \
bool operator!=(const CLASS_NAME &rhs) const throw() { return ! (*this == rhs); } \
bool operator<(const CLASS_NAME &rhs) const throw() \
{ \
BOOST_PP_SEQ_FOR_EACH(PRINT_CONFIG_CLASS_ELEMENT_LOWER, _, PARAMETER_DEFINITION_SEQ) \
return false; \
} \
protected: \
void initialize(StaticCacheBase &cache, const char *base_ptr) \
{ \
BOOST_PP_SEQ_FOR_EACH(PRINT_CONFIG_CLASS_ELEMENT_INITIALIZATION, _, PARAMETER_DEFINITION_SEQ) \
BOOST_PP_SEQ_FOR_EACH(PRINT_CONFIG_CLASS_ELEMENT_VISIT, _, PARAMETER_DEFINITION_SEQ) \
} \
PRINT_CONFIG_CLASS_COMMON_BODY(CLASS_NAME) \
};
#define PRINT_CONFIG_CLASS_DERIVED_CLASS_LIST_ITEM(r, data, i, elem) BOOST_PP_COMMA_IF(i) public elem
@@ -1059,43 +1064,43 @@ protected: \
if (! (*static_cast<const elem*>(this) == static_cast<const elem&>(rhs))) return false;
// Generic version, with or without new parameters. Don't use this directly.
#define PRINT_CONFIG_CLASS_DERIVED_DEFINE1(CLASS_NAME, CLASSES_PARENTS_TUPLE, PARAMETER_DEFINITION, PARAMETER_REGISTRATION, PARAMETER_HASHES, PARAMETER_EQUALS) \
#define PRINT_CONFIG_CLASS_DERIVED_DEFINE1(CLASS_NAME, CLASSES_PARENTS_TUPLE, PARAMETER_DEFINITION, PARAMETER_VISIT) \
class CLASS_NAME : PRINT_CONFIG_CLASS_DERIVED_CLASS_LIST(CLASSES_PARENTS_TUPLE) { \
STATIC_PRINT_CONFIG_CACHE_DERIVED(CLASS_NAME) \
CLASS_NAME() : PRINT_CONFIG_CLASS_DERIVED_INITIALIZER(CLASSES_PARENTS_TUPLE, 0) { assert(s_cache_##CLASS_NAME.initialized()); *this = s_cache_##CLASS_NAME.defaults(); } \
public: \
PARAMETER_DEFINITION \
template<typename F> void for_each_option_pair(const CLASS_NAME &rhs, F &&f) const { PARAMETER_VISIT } \
size_t hash() const throw() \
{ \
size_t seed = 0; \
BOOST_PP_SEQ_FOR_EACH(PRINT_CONFIG_CLASS_DERIVED_HASH, _, BOOST_PP_TUPLE_TO_SEQ(CLASSES_PARENTS_TUPLE)) \
PARAMETER_HASHES \
this->for_each_option_pair(*this, [&seed](const char*, const auto &a, const auto&) { boost::hash_combine(seed, a.hash()); return true; }); \
return seed; \
} \
bool operator==(const CLASS_NAME &rhs) const throw() \
{ \
BOOST_PP_SEQ_FOR_EACH(PRINT_CONFIG_CLASS_DERIVED_EQUAL, _, BOOST_PP_TUPLE_TO_SEQ(CLASSES_PARENTS_TUPLE)) \
PARAMETER_EQUALS \
return true; \
bool eq = true; \
this->for_each_option_pair(rhs, [&eq](const char*, const auto &a, const auto &b) { eq = (a == b); return eq; }); \
return eq; \
} \
bool operator!=(const CLASS_NAME &rhs) const throw() { return ! (*this == rhs); } \
protected: \
CLASS_NAME(int) : PRINT_CONFIG_CLASS_DERIVED_INITIALIZER(CLASSES_PARENTS_TUPLE, 1) {} \
void initialize(StaticCacheBase &cache, const char* base_ptr) { \
PRINT_CONFIG_CLASS_DERIVED_INITCACHE(CLASSES_PARENTS_TUPLE) \
PARAMETER_REGISTRATION \
this->for_each_option_pair(*this, [&cache, base_ptr](const char *key, const auto &a, const auto&) { cache.opt_add(key, base_ptr, a); return true; }); \
} \
};
// Variant without adding new parameters.
#define PRINT_CONFIG_CLASS_DERIVED_DEFINE0(CLASS_NAME, CLASSES_PARENTS_TUPLE) \
PRINT_CONFIG_CLASS_DERIVED_DEFINE1(CLASS_NAME, CLASSES_PARENTS_TUPLE, BOOST_PP_EMPTY(), BOOST_PP_EMPTY(), BOOST_PP_EMPTY(), BOOST_PP_EMPTY())
PRINT_CONFIG_CLASS_DERIVED_DEFINE1(CLASS_NAME, CLASSES_PARENTS_TUPLE, BOOST_PP_EMPTY(), BOOST_PP_EMPTY())
// Variant with adding new parameters.
#define PRINT_CONFIG_CLASS_DERIVED_DEFINE(CLASS_NAME, CLASSES_PARENTS_TUPLE, PARAMETER_DEFINITION_SEQ) \
PRINT_CONFIG_CLASS_DERIVED_DEFINE1(CLASS_NAME, CLASSES_PARENTS_TUPLE, \
BOOST_PP_SEQ_FOR_EACH(PRINT_CONFIG_CLASS_ELEMENT_DEFINITION, _, PARAMETER_DEFINITION_SEQ), \
BOOST_PP_SEQ_FOR_EACH(PRINT_CONFIG_CLASS_ELEMENT_INITIALIZATION, _, PARAMETER_DEFINITION_SEQ), \
BOOST_PP_SEQ_FOR_EACH(PRINT_CONFIG_CLASS_ELEMENT_HASH, _, PARAMETER_DEFINITION_SEQ), \
BOOST_PP_SEQ_FOR_EACH(PRINT_CONFIG_CLASS_ELEMENT_EQUAL, _, PARAMETER_DEFINITION_SEQ))
BOOST_PP_SEQ_FOR_EACH(PRINT_CONFIG_CLASS_ELEMENT_VISIT, _, PARAMETER_DEFINITION_SEQ))
// This object is mapped to Perl as Slic3r::Config::PrintObject.
PRINT_CONFIG_CLASS_DEFINE(
@@ -2148,11 +2153,8 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE0(
#undef STATIC_PRINT_CONFIG_CACHE_BASE
#undef STATIC_PRINT_CONFIG_CACHE_DERIVED
#undef PRINT_CONFIG_CLASS_ELEMENT_DEFINITION
#undef PRINT_CONFIG_CLASS_ELEMENT_EQUAL
#undef PRINT_CONFIG_CLASS_ELEMENT_LOWER
#undef PRINT_CONFIG_CLASS_ELEMENT_HASH
#undef PRINT_CONFIG_CLASS_ELEMENT_INITIALIZATION
#undef PRINT_CONFIG_CLASS_ELEMENT_INITIALIZATION2
#undef PRINT_CONFIG_CLASS_ELEMENT_VISIT
#undef PRINT_CONFIG_CLASS_COMMON_BODY
#undef PRINT_CONFIG_CLASS_DEFINE
#undef PRINT_CONFIG_CLASS_DERIVED_CLASS_LIST
#undef PRINT_CONFIG_CLASS_DERIVED_CLASS_LIST_ITEM
+7 -2
View File
@@ -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;
}
+1
View File
@@ -1,6 +1,7 @@
#include "AMSDryControl.hpp"
#include "slic3r/GUI/DeviceCore/DevFilaSystem.h"
#include "GUI_App.hpp"
#include "slic3r/Utils/NetworkAgent.hpp"
#include "I18N.hpp"
#include "slic3r/GUI/DeviceCore/DevExtruderSystem.h"
+1
View File
@@ -14,6 +14,7 @@
//Previous defintions
class wxGrid;
class ProgressBar;
namespace Slic3r {
+2
View File
@@ -2,6 +2,8 @@
#include "ExtrusionCalibration.hpp"
#include "MsgDialog.hpp"
#include "GUI_App.hpp"
#include "GUI.hpp"
#include "slic3r/Utils/NetworkAgent.hpp"
#include "libslic3r/Preset.hpp"
#include "I18N.hpp"
#include <algorithm>
+1
View File
@@ -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"
@@ -5,8 +5,10 @@
#include <thread>
#include "GUI_App.hpp"
#include "GUI_Utils.hpp"
#include <wx/timer.h>
class Button;
class Label;
class CheckBox;
namespace Slic3r { namespace GUI {
class CapsuleButton;
+1
View File
@@ -1,6 +1,7 @@
#include "CalibrationWizard.hpp"
#include "I18N.hpp"
#include "GUI_App.hpp"
#include "slic3r/Utils/NetworkAgent.hpp"
#include "MsgDialog.hpp"
#include "CalibrationWizardPage.hpp"
#include "../../libslic3r/calib.hpp"
@@ -1,5 +1,7 @@
#include <regex>
#include "CalibrationWizardPresetPage.hpp"
#include "GUI.hpp"
#include "slic3r/Utils/NetworkAgent.hpp"
#include "I18N.hpp"
#include "Widgets/Label.hpp"
#include "MsgDialog.hpp"
@@ -1,4 +1,5 @@
#include "CalibrationWizardSavePage.hpp"
#include "GUI.hpp"
#include "I18N.hpp"
#include "Widgets/Label.hpp"
#include "MsgDialog.hpp"
+1
View File
@@ -1,5 +1,6 @@
#include "GUI_App.hpp"
#include "CapsuleButton.hpp"
#include "Widgets/StateColor.hpp"
#include <wx/dcbuffer.h>
#include "wx/graphics.h"
#include "Widgets/Label.hpp"
+1
View File
@@ -1,4 +1,5 @@
#include "ColorDecomposeSupport.hpp"
#include "slic3r/Utils/NetworkAgent.hpp"
#include "MixedFilamentDialog.hpp"
#include "GUI_App.hpp"
#include "MsgDialog.hpp"
+1
View File
@@ -2,6 +2,7 @@
#include "ConfigManipulation.hpp"
#include "I18N.hpp"
#include "GUI_App.hpp"
#include "DeviceCore/DevConfigUtil.h"
#include "format.hpp"
#include "libslic3r/Config.hpp"
#include "libslic3r/Model.hpp"
+1
View File
@@ -1,4 +1,5 @@
#include "DailyTips.hpp"
#include "slic3r/GUI/Widgets/Label.hpp"
#ifndef IMGUI_DEFINE_MATH_OPERATORS
#define IMGUI_DEFINE_MATH_OPERATORS
+2
View File
@@ -1,5 +1,7 @@
#include <boost/log/trivial.hpp>
#include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/I18N.hpp"
#include "slic3r/GUI/DeviceManager.hpp"
#include "slic3r/GUI/UserNotification.hpp"
#include "libslic3r/PrintConfig.hpp"
@@ -4,6 +4,8 @@
#include <set>
#include "DevFilaBlackList.h"
#include "slic3r/Utils/NetworkAgent.hpp"
#include "slic3r/GUI/DeviceManager.hpp"
#include "DevFilaSystem.h"
#include "DevManager.h"
#include "DevConfigUtil.h"
@@ -1,5 +1,6 @@
#include <nlohmann/json.hpp>
#include "DevFilaSystem.h"
#include "slic3r/Utils/NetworkAgent.hpp"
#include "DevNozzleSystem.h" // DevNozzle / DevNozzleSystem for GetNozzleFlowStringByAmsId
// TODO: remove this include
+2
View File
@@ -1,5 +1,7 @@
#include "libslic3r/libslic3r.h"
#include "DeviceManager.hpp"
#include "HMS.hpp"
#include "I18N.hpp"
#include "libslic3r/Time.hpp"
#include "libslic3r/Thread.hpp"
#include "slic3r/Utils/NetworkAgent.hpp"
+1
View File
@@ -1,6 +1,7 @@
#include "wgtMsgPanel.h"
#include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/I18N.hpp"
#include "slic3r/GUI/Widgets/Label.hpp"
#include "slic3r/GUI/Widgets/StateColor.hpp"
#include "slic3r/GUI/wxExtensions.hpp"
+1
View File
@@ -1,6 +1,7 @@
#include "DragCanvas.hpp"
#include "wxExtensions.hpp"
#include "GUI_App.hpp"
#include "Widgets/StateColor.hpp"
namespace Slic3r { namespace GUI {
+3
View File
@@ -1,7 +1,10 @@
#include "EncodedFilament.hpp"
#include <nlohmann/json.hpp>
#include "GUI_App.hpp"
using json = nlohmann::json;
namespace Slic3r
{
@@ -1,4 +1,5 @@
#include "ExportPresetBundleDialog.hpp"
#include "slic3r/Utils/NetworkAgent.hpp"
#include "GUI_App.hpp"
#include "ConfigWizard.hpp"
#include "I18N.hpp"
@@ -12,7 +13,11 @@
#include <libslic3r/PresetBundle.hpp>
#include <wx/string.h>
#include <miniz.h>
#include <nlohmann/json.hpp>
#include <slic3r/GUI/MsgDialog.hpp>
using json = nlohmann::json;
namespace Slic3r { namespace GUI {
ExportPresetBundleDialog::ExportPresetBundleDialog(
+1
View File
@@ -1,6 +1,7 @@
#include "ExtraRenderers.hpp"
#include "wxExtensions.hpp"
#include "GUI.hpp"
#include "I18N.hpp"
#include "BitmapComboBox.hpp"
#include "Plater.hpp"
#include "Widgets/ComboBox.hpp"
+1
View File
@@ -1,5 +1,6 @@
#include "ExtrusionCalibration.hpp"
#include "GUI_App.hpp"
#include "GUI.hpp"
#include "MsgDialog.hpp"
#include "libslic3r/Preset.hpp"
#include <algorithm>
+84 -39
View File
@@ -11,6 +11,7 @@
#include "libslic3r/PrintConfig.hpp"
#include <algorithm>
#include <cmath>
#include <regex>
#include <utility>
#include <cstdint>
@@ -540,51 +541,95 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true
case coStrings:
case coFloatOrPercent:
case coFloatsOrPercents: {
if ((m_opt.type == coFloatOrPercent || m_opt.type == coFloatsOrPercents) && !str.IsEmpty() && str.Last() != '%')
{
if ((m_opt.type == coFloatOrPercent || m_opt.type == coFloatsOrPercents) && !str.IsEmpty() &&
!(m_opt.nullable && str == m_na_value)) {
bool update_control = false;
wxString numeric_str = str;
double val = 0.;
const char dec_sep = is_decimal_separator_point() ? '.' : ',';
const char dec_sep_alt = dec_sep == '.' ? ',' : '.';
// Replace the first incorrect separator in decimal number.
if (str.Replace(dec_sep_alt, dec_sep, false) != 0)
set_value(str, false);
// Orca: normalize the decimal separator and optional unit before
// detecting the percentage suffix and parsing the numeric part.
update_control |= numeric_str.Replace(dec_sep_alt, dec_sep, false) != 0;
update_control |= numeric_str.Replace(" ", "", true) != 0;
const bool has_literal_unit = numeric_str.EndsWith("mm");
if (has_literal_unit) {
numeric_str.RemoveLast(2);
update_control = true;
}
bool is_percent = !numeric_str.IsEmpty() && numeric_str.Last() == '%';
if (is_percent)
numeric_str.RemoveLast();
// remove space and "mm" substring, if any exists
str.Replace(" ", "", true);
str.Replace("m", "", true);
if (!str.ToDouble(&val))
{
if ((has_literal_unit && is_percent) || !numeric_str.ToDouble(&val) || !std::isfinite(val)) {
if (!check_value) {
m_value.clear();
break;
}
show_error(m_parent, _L("Invalid numeric."));
set_value(double_to_string(val), true);
}
else if (((m_opt.sidetext.rfind("mm/s") != std::string::npos && val > m_opt.max) ||
(m_opt.sidetext.rfind("mm ") != std::string::npos && val > /*1*/m_opt.max_literal)) &&
(m_value.empty() || into_u8(str) != boost::any_cast<std::string>(m_value)))
{
if (!check_value) {
m_value.clear();
break;
numeric_str = double_to_string(std::clamp(0., double(m_opt.min), double(m_opt.max)));
is_percent = false;
update_control = true;
} else {
const bool looks_like_missing_percent = !is_percent && !has_literal_unit &&
((m_opt.sidetext.rfind("mm/s") != std::string::npos && val > m_opt.max) ||
(m_opt.sidetext.rfind("mm ") != std::string::npos && val > m_opt.max_literal));
// Orca: validate explicit percentages and literal values before
// asking whether an otherwise valid literal was meant as a percentage.
const bool out_of_range = !m_opt.is_value_valid(val);
if (out_of_range) {
if (!check_value) {
m_value.clear();
break;
}
show_error(m_parent, _L("Value is out of range."));
val = std::clamp(val, double(m_opt.min), double(m_opt.max));
// Orca: retain the inferred percent unit when clamping a
// suspicious unitless value, so 2000 becomes 100%, not 100 mm.
is_percent |= looks_like_missing_percent;
numeric_str = double_to_string(val);
update_control = true;
} else {
const bool value_changed = m_value.empty() || into_u8(str) != boost::any_cast<std::string>(m_value);
if (looks_like_missing_percent && value_changed) {
if (!check_value) {
m_value.clear();
break;
}
const std::string sidetext = m_opt.sidetext.rfind("mm/s") != std::string::npos ? "mm/s" : "mm";
const wxString stVal = numeric_str;
const wxString msg_text = from_u8((boost::format(_utf8(L("Is it %s%% or %s %s?"))) %
stVal % stVal % sidetext).str());
WarningDialog dialog(m_parent, msg_text, _L("Parameter validation") + ": " + m_opt_id, wxYES | wxNO);
dialog.SetButtonLabel(wxID_YES, stVal + _L("%"));
dialog.SetButtonLabel(wxID_NO, stVal + " " + _L(sidetext));
dialog.GetSizer()->SetSizeHints(&dialog);
dialog.Fit();
dialog.CenterOnParent();
is_percent = dialog.ShowModal() == wxID_YES;
update_control = true;
}
}
const std::string sidetext = m_opt.sidetext.rfind("mm/s") != std::string::npos ? "mm/s" : "mm";
const wxString stVal = double_to_string(val, 2);
const wxString msg_text = from_u8((boost::format(_utf8(L("Is it %s%% or %s %s?\n"
"YES for %s%%, \n"
"NO for %s %s."))) %
stVal % stVal % sidetext % stVal % stVal % sidetext)
.str());
WarningDialog dialog(m_parent, msg_text, _L("Parameter validation") + ": " + m_opt_id, wxYES | wxNO);
if ((val > 100) && dialog.ShowModal() == wxID_YES) {
set_value(from_u8((boost::format("%s%%") % stVal).str()), false /*true*/);
str += "%%";
} else
set_value(stVal, false); // it's no needed but can be helpful, when inputted value contained "," instead of "."
// Orca: also enforce the literal limit after clamping an explicit mm input.
if (!is_percent && m_opt.sidetext.rfind("mm ") != std::string::npos && val > m_opt.max_literal) {
if (!check_value) {
m_value.clear();
break;
}
if (!out_of_range)
show_error(m_parent, _L("Value is out of range."));
val = m_opt.max_literal;
numeric_str = double_to_string(val);
update_control = true;
}
}
if (update_control) {
str = numeric_str + (is_percent ? "%" : "");
set_value(str, true);
}
}
if (m_opt.opt_key == "thumbnails") {
@@ -2805,11 +2850,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);
@@ -2858,7 +2903,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();
+1 -1
View File
@@ -650,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;
+1
View File
@@ -1,5 +1,6 @@
#include "FilamentMapPanel.hpp"
#include "GUI_App.hpp"
#include "I18N.hpp"
#include "Plater.hpp"
#include "Widgets/MultiNozzleSync.hpp" // manuallySetNozzleCount producer for extruder_nozzle_stats
#include <algorithm>
+44 -94
View File
@@ -1077,56 +1077,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;
@@ -5953,7 +5933,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();
@@ -5978,7 +5958,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);
@@ -5987,13 +5966,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;
@@ -6001,59 +5976,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 &current_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;
}
@@ -6065,11 +6022,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(); }
}
@@ -6085,7 +6038,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;
@@ -6095,18 +6047,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};
+2 -17
View File
@@ -655,11 +655,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
{
@@ -1162,17 +1158,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
@@ -1307,7 +1292,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();
+2
View File
@@ -9,6 +9,7 @@
#include "3DScene.hpp"
#include "OpenGLManager.hpp"
#include "GUI_App.hpp"
#include "GUI.hpp"
#include "GLModel.hpp"
#include <glad/gl.h>
@@ -31,6 +32,7 @@
#include "GUI_App.hpp"
#include <boost/log/trivial.hpp>
#include <wx/dcgraph.h>
#include <wx/dcmemory.h>
namespace Slic3r {
namespace GUI {
+9 -1
View File
@@ -3,6 +3,14 @@
#include "libslic3r/Technologies.hpp"
#include "libslic3r/Platform.hpp"
#include "GUI_App.hpp"
#include "BindDialog.hpp"
#include "DeviceManager.hpp"
#include "HMS.hpp"
#include "PresetBundleDialog.hpp"
#include "WebUserLoginDialog.hpp"
#include "WebViewDialog.hpp"
#include "slic3r/Utils/BBLCloudServiceAgent.hpp"
#include "slic3r/Utils/NetworkAgent.hpp"
#include "GUI_Init.hpp"
#include "GUI_ObjectList.hpp"
#include "slic3r/GUI/UserManager.hpp"
@@ -9276,7 +9284,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;
+10 -9
View File
@@ -1,23 +1,17 @@
#ifndef slic3r_GUI_App_hpp_
#define slic3r_GUI_App_hpp_
#include <functional>
#include <memory>
#include <string>
#include "ActionRegistry.hpp"
#include "ImGuiWrapper.hpp"
#include "ConfigWizard.hpp"
#include "OpenGLManager.hpp"
#include "PresetBundleDialog.hpp"
#include "libslic3r/Preset.hpp"
#include "libslic3r/PresetBundle.hpp"
#include "slic3r/GUI/DeviceManager.hpp"
#include "slic3r/GUI/UserNotification.hpp"
#include "slic3r/Utils/NetworkAgent.hpp"
#include "slic3r/Utils/BBLCloudServiceAgent.hpp"
#include "slic3r/GUI/WebViewDialog.hpp"
#include "slic3r/GUI/WebUserLoginDialog.hpp"
#include "slic3r/GUI/BindDialog.hpp"
#include "slic3r/GUI/HMS.hpp"
#include "slic3r/Utils/CloudProvider.hpp"
#include "slic3r/GUI/Jobs/UpgradeNetworkJob.hpp"
#include "slic3r/GUI/HttpServer.hpp"
#include "../Utils/PrintHost.hpp"
@@ -64,9 +58,14 @@ class ModelObject;
class Model;
class UserManager;
class DeviceManager;
class MachineObject;
class NetworkAgent;
class IPrinterAgent;
class TaskManager;
// Same typedef as in bambu_networking.hpp, so this header need not include it.
typedef std::function<bool()> WasCancelledFn;
namespace GUI{
class RemovableDriveManager;
@@ -85,6 +84,8 @@ class ParamsDialog;
class HMSQuery;
class ModelMallDialog;
class PingCodeBindDialog;
class PresetBundleDialog;
class ZUserLogin;
class NetworkErrorDialog;
class PluginsDialog;
class SpeedDialWebDialog;
@@ -837,7 +838,7 @@ wxDECLARE_EVENT(EVT_UPDATE_BUNDLE_COMPLETE, wxCommandEvent);
bool is_support_filament(int extruder_id, bool strict_check = true);
bool is_soluble_filament(int extruder_id);
// check if the filament for model is in the list
bool has_filaments(const std::vector<string>& model_filaments);
bool has_filaments(const std::vector<std::string>& model_filaments);
} // namespace GUI
} // Slic3r
+2 -20
View File
@@ -1410,7 +1410,7 @@ void MenuFactory::create_default_menu()
{
wxMenu* sub_menu_primitives = append_submenu_add_generic(&m_default_menu, ModelVolumeType::INVALID);
wxMenu* sub_menu_handy = append_submenu_add_handy_model(&m_default_menu, ModelVolumeType::INVALID);
#ifdef __WINDOWS__
append_submenu(&m_default_menu, sub_menu_primitives, wxID_ANY, _L("Add Primitive"), "", "menu_add_part",
[]() {return true; }, m_parent);
append_submenu(&m_default_menu, sub_menu_handy, wxID_ANY, _L("Add Handy models"), "", "menu_add_part",
@@ -1418,15 +1418,6 @@ void MenuFactory::create_default_menu()
append_menu_item(&m_default_menu, wxID_ANY, _L("Add Models"), "", // ORCA: Add Models
[](wxCommandEvent&) { plater()->add_file(); }, "menu_add_part", &m_default_menu,
[]() {return wxGetApp().plater()->can_add_model(); }, m_parent);
#else
append_submenu(&m_default_menu, sub_menu_primitives, wxID_ANY, _L("Add Primitive"), "", "",
[]() {return true; }, m_parent);
append_submenu(&m_default_menu, sub_menu_handy, wxID_ANY, _L("Add Handy models"), "", "",
[]() {return true; }, m_parent);
append_menu_item(&m_default_menu, wxID_ANY, _L("Add Models"), "", // ORCA: Add Models
[](wxCommandEvent&) { plater()->add_file(); }, "", &m_default_menu,
[]() {return wxGetApp().plater()->can_add_model(); }, m_parent);
#endif
m_default_menu.AppendSeparator();
@@ -1807,7 +1798,6 @@ void MenuFactory::create_plate_menu()
wxMenu* sub_menu_primitives = append_submenu_add_generic(menu, ModelVolumeType::INVALID);
wxMenu* sub_menu_handy = append_submenu_add_handy_model(menu, ModelVolumeType::INVALID);
#ifdef __WINDOWS__
append_submenu(menu, sub_menu_primitives, wxID_ANY, _L("Add Primitive"), "", "menu_add_part",
[]() {return true; }, m_parent);
append_submenu(menu, sub_menu_handy, wxID_ANY, _L("Add Handy models"), "", "menu_add_part",
@@ -1815,15 +1805,7 @@ void MenuFactory::create_plate_menu()
append_menu_item(menu, wxID_ANY, _L("Add Models"), "", // ORCA: Add Models
[](wxCommandEvent&) { plater()->add_file(); }, "menu_add_part", menu,
[]() {return wxGetApp().plater()->can_add_model(); }, m_parent);
#else
append_submenu(menu, sub_menu_primitives, wxID_ANY, _L("Add Primitive"), "", "",
[]() {return true; }, m_parent);
append_submenu(menu, sub_menu_handy, wxID_ANY, _L("Add Handy models"), "", "",
[]() {return true; }, m_parent);
append_menu_item(menu, wxID_ANY, _L("Add Models"), "", // ORCA: Add Models
[](wxCommandEvent&) { plater()->add_file(); }, "", menu,
[]() {return wxGetApp().plater()->can_add_model(); }, m_parent);
#endif
append_menu_item_replace_all_with_stl(menu);
+2 -2
View File
@@ -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;
+1 -1
View File
@@ -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;
+1 -1
View File
@@ -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();
@@ -1,5 +1,7 @@
// Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, which overrides our localization "L" macro.
#include "GLGizmoAdvancedCut.hpp"
#include "slic3r/GUI/Widgets/ProgressDialog.hpp"
#include "slic3r/GUI/GUI.hpp"
#include "slic3r/GUI/GLCanvas3D.hpp"
#include <glad/gl.h>
@@ -1,6 +1,7 @@
#include "GLGizmoBrimEars.hpp"
#include <glad/gl.h>
#include "slic3r/GUI/GLCanvas3D.hpp"
#include "slic3r/GUI/GUI.hpp"
#include "slic3r/GUI/Camera.hpp"
#include "slic3r/GUI/Gizmos/GLGizmosCommon.hpp"
#include "slic3r/GUI/GUI_App.hpp"
@@ -4,6 +4,7 @@
#include "libslic3r/Print.hpp"
#include "slic3r/GUI/GLCanvas3D.hpp"
#include "slic3r/GUI/GUI.hpp"
#include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/GUI_ObjectList.hpp"
#include "slic3r/GUI/ImGuiWrapper.hpp"
+1
View File
@@ -1,4 +1,5 @@
#include "GLGizmoMeasure.hpp"
#include "slic3r/GUI/GUI.hpp"
#include "slic3r/GUI/GLCanvas3D.hpp"
#include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/Plater.hpp"
+2
View File
@@ -32,6 +32,8 @@
*/
using namespace std::string_view_literals;
namespace Slic3r::GUI::GLGizmoUtils {
void render_tooltip_button(
+4
View File
@@ -4,6 +4,10 @@
#include "slic3r/Utils/Http.hpp"
#include "slic3r/Utils/NetworkAgent.hpp"
#include "slic3r/Utils/BBLNetworkPlugin.hpp"
#include "libslic3r/Thread.hpp"
#include <nlohmann/json.hpp>
using json = nlohmann::json;
namespace Slic3r {
namespace GUI {
+1
View File
@@ -1,6 +1,7 @@
#include "IMSlider.hpp"
#include "libslic3r/GCode.hpp"
#include "GUI_App.hpp"
#include "GUI.hpp"
#include "NotificationManager.hpp"
#include "Widgets/StateColor.hpp"
#ifndef IMGUI_DEFINE_MATH_OPERATORS
+2
View File
@@ -3,6 +3,8 @@
#include "GUI_App.hpp"
#include "GUI_Utils.hpp"
#include <wx/stattext.h>
#include <wx/timer.h>
class wxStaticBitmap;
namespace Slic3r { namespace GUI {
+1 -1
View File
@@ -521,7 +521,7 @@ void ImageGrid::render(wxDC& dc)
if (!m_status_msg.IsEmpty()) {
auto si = m_status_icon.GetBmpSize();
auto st = dc.GetMultiLineTextExtent(m_status_msg);
auto rect = wxRect{0, 0, max(st.x, si.x), si.y + 26 + st.y}.CenterIn(wxRect({0, 0}, size));
auto rect = wxRect{0, 0, std::max(st.x, si.x), si.y + 26 + st.y}.CenterIn(wxRect({0, 0}, size));
dc.DrawBitmap(m_status_icon.bmp(), rect.x + (rect.width - si.x) / 2, rect.y);
dc.SetTextForeground(wxColor(0x909090));
dc.DrawText(m_status_msg, rect.x + (rect.width - st.x) / 2, rect.GetBottom() - st.y);
+4 -1
View File
@@ -114,7 +114,10 @@ namespace instance_check_internal
if (my_instance_hash == other_instance_hash) {
BOOST_LOG_TRIVIAL(debug) << "win enum - found correct instance";
orca_slicer_hwnd = hwnd;
ShowWindow(hwnd, SW_SHOWMAXIMIZED);
// Do not alter the window state when opening a file in the existing instance.
// A minimized window still needs restoring before it can receive focus.
if (IsIconic(hwnd))
ShowWindow(hwnd, SW_RESTORE);
SetForegroundWindow(hwnd);
return false;
}
-1
View File
@@ -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();
+4
View File
@@ -3,6 +3,10 @@
#include "slic3r/GUI/Plater.hpp"
#include "slic3r/GUI/GUI.hpp"
#include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/DeviceManager.hpp"
#include "slic3r/GUI/HMS.hpp"
#include "slic3r/GUI/I18N.hpp"
#include "slic3r/Utils/NetworkAgent.hpp"
#include "slic3r/GUI/DeviceCore/DevManager.h"
+2
View File
@@ -1,4 +1,6 @@
#include "SendJob.hpp"
#include "slic3r/GUI/I18N.hpp"
#include "slic3r/Utils/NetworkAgent.hpp"
#include "libslic3r/MTUtils.hpp"
#include "libslic3r/Model.hpp"
#include "libslic3r/PresetBundle.hpp"
@@ -2,6 +2,7 @@
#include "slic3r/GUI/GUI.hpp"
#include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/I18N.hpp"
#include "slic3r/Utils/Http.hpp"
namespace Slic3r {
+1
View File
@@ -66,6 +66,7 @@ class Tab;
class PrintHostQueueDialog;
class Plater;
class MainFrame;
class WebViewPanel;
class ParamsDialog;
#ifdef __WXGTK__
class ResizeEdgePanel;
+3
View File
@@ -2,6 +2,9 @@
#include "ImageGrid.h"
#include "I18N.hpp"
#include "GUI_App.hpp"
#include "GUI.hpp"
#include "DeviceManager.hpp"
#include "slic3r/Utils/NetworkAgent.hpp"
#include "Plater.hpp"
#include "Widgets/Button.hpp"
#include "Widgets/SwitchButton.hpp"
+6
View File
@@ -3,6 +3,11 @@
#include "Widgets/CheckBox.hpp"
#include "Widgets/Label.hpp"
#include "GUI_App.hpp"
#include "GUI.hpp"
#include "DeviceManager.hpp"
#include "DeviceCore/DevConfigUtil.h"
#include "slic3r/Utils/NetworkAgent.hpp"
#include "libslic3r/Thread.hpp"
#include "libslic3r/AppConfig.hpp"
#include "I18N.hpp"
#include "MsgDialog.hpp"
@@ -13,6 +18,7 @@
#include <boost/lexical_cast.hpp>
#include <boost/log/trivial.hpp>
#include <boost/nowide/cstdio.hpp>
#include <boost/nowide/fstream.hpp>
#include <boost/nowide/utf8_codecvt.hpp>
#undef pid_t
#include <boost/process.hpp>
+1
View File
@@ -1,6 +1,7 @@
#include "libslic3r/libslic3r.h"
#include "libslic3r/PresetBundle.hpp"
#include "Mouse3DController.hpp"
#include "GUI.hpp"
#include "Camera.hpp"
#include "GUI_App.hpp"
+3 -5
View File
@@ -804,11 +804,9 @@ void ConfigOptionsGroup::back_to_config_value(const DynamicPrintConfig& config,
#endif
else if (opt_key == "printer_agent")
{
// why: printer_agent is a coString kept out of m_opt_map. The generic non-opt_map revert
// below restores the edited config from get_value(), but a deregistered/"(missing)" saved
// id has no selectable row, so the field yields no value and the edited config keeps the
// user's interim pick -> stuck dirty. Restore the SAVED id straight into the edited config
// (displayable or not; config is the saved or system baseline), then repaint and notify.
// A deregistered/"(missing)" saved id has no selectable row, so the field yields no
// value. Restore the saved id directly instead of letting the generic revert path read
// the field value back into the edited config.
const std::string saved_id = config.opt_string("printer_agent");
set_value(opt_key, saved_id);
this->change_opt_value(opt_key, saved_id);
+1
View File
@@ -17,6 +17,7 @@
#include <boost/log/trivial.hpp>
#include <boost/nowide/convert.hpp>
#include <boost/nowide/cstdio.hpp>
#include <boost/nowide/fstream.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include "libslic3r/libslic3r.h"
+1
View File
@@ -1,5 +1,6 @@
#include "GUI_Utils.hpp"
#include "GUI_App.hpp"
#include "slic3r/Utils/NetworkAgent.hpp"
#include <wx/panel.h>
#include <wx/bitmap.h>
#include <wx/image.h>
+1
View File
@@ -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>
+1
View File
@@ -42,6 +42,7 @@ class Button;
namespace Slic3r {
class BuildVolume;
class MachineObject;
enum class BuildVolume_Type : char;
class Model;
class ModelObject;

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