diff --git a/.claude/commands/commit-push-pr.md b/.claude/commands/commit-push-pr.md
new file mode 100644
index 0000000000..0a624d60ab
--- /dev/null
+++ b/.claude/commands/commit-push-pr.md
@@ -0,0 +1,19 @@
+---
+allowed-tools: Bash(git checkout --branch:*), Bash(git add:*), Bash(git status:*), Bash(git push:*), Bash(git commit:*), Bash(gh pr create:*)
+description: Commit, push, and open a PR
+---
+
+## Context
+
+- Current git status: !`git status`
+- Current git diff (staged and unstaged changes): !`git diff HEAD`
+- Current branch: !`git branch --show-current`
+
+## Your task
+
+Based on the above changes:
+1. Create a new branch if on main
+2. Create a single commit with an appropriate message
+3. Push the branch to origin
+4. Create a pull request using `gh pr create`
+5. You have the capability to call multiple tools in a single response. You MUST do all of the above in a single message. Do not use any other tools or do anything else. Do not send any other text or messages besides these tool calls.
diff --git a/.claude/commands/dedupe.md b/.claude/commands/dedupe.md
new file mode 100644
index 0000000000..646a4d7fbe
--- /dev/null
+++ b/.claude/commands/dedupe.md
@@ -0,0 +1,38 @@
+---
+allowed-tools: Bash(gh issue view:*), Bash(gh search:*), Bash(gh issue list:*), Bash(gh api:*), Bash(gh issue comment:*)
+description: Find duplicate GitHub issues
+---
+
+Find up to 3 likely duplicate issues for a given GitHub issue.
+
+To do this, follow these steps precisely:
+
+1. Use an agent to check if the Github issue (a) is closed, (b) does not need to be deduped (eg. because it is broad product feedback without a specific solution, or positive feedback), or (c) already has a duplicates comment that you made earlier. If so, do not proceed.
+2. Use an agent to view a Github issue, and ask the agent to return a summary of the issue
+3. Then, launch 5 parallel agents to search Github for duplicates of this issue, using diverse keywords and search approaches, using the summary from #1
+4. Next, feed the results from #1 and #2 into another agent, so that it can filter out false positives, that are likely not actually duplicates of the original issue. If there are no duplicates remaining, do not proceed.
+5. Finally, comment back on the issue with a list of up to three duplicate issues (or zero, if there are no likely duplicates)
+
+Notes (be sure to tell this to your agents, too):
+
+- Use `gh` to interact with Github, rather than web fetch
+- Do not use other tools, beyond `gh` (eg. don't use other MCP servers, file edit, etc.)
+- Make a todo list first
+- For your comment, follow the following format precisely (assuming for this example that you found 3 suspected duplicates):
+
+---
+
+Found 3 possible duplicate issues:
+
+1.
+2.
+3.
+
+This issue will be automatically closed as a duplicate in 3 days.
+
+- If your issue is a duplicate, please close it and 👍 the existing issue instead
+- To prevent auto-closure, add a comment or 👎 this comment
+
+🤖 OrcaSlicer bot
+
+---
diff --git a/.claude/commands/oncall-triage.md b/.claude/commands/oncall-triage.md
new file mode 100644
index 0000000000..656be4af3b
--- /dev/null
+++ b/.claude/commands/oncall-triage.md
@@ -0,0 +1,40 @@
+---
+allowed-tools: Bash(gh issue list:*), Bash(gh issue view:*), Bash(gh issue edit:*), TodoWrite
+description: Triage GitHub issues and label critical ones for oncall
+---
+
+You're an oncall triage assistant for GitHub issues. Your task is to identify critical issues that require immediate oncall attention and apply the "oncall" label.
+
+Repository: OrcaSlicer/OrcaSlicer
+
+Task overview:
+
+1. First, get all open bugs updated in the last 3 days with at least 50 engagements:
+ ```bash
+ gh issue list --repo OrcaSlicer/OrcaSlicer --state open --label bug --limit 1000 --json number,title,updatedAt,comments,reactions | jq -r '.[] | select((.updatedAt >= (now - 259200 | strftime("%Y-%m-%dT%H:%M:%SZ"))) and ((.comments | length) + ([.reactions[].content] | length) >= 50)) | "\(.number)"'
+ ```
+
+2. Save the list of issue numbers and create a TODO list with ALL of them. This ensures you process every single one.
+
+3. For each issue in your TODO list:
+ - Use `gh issue view --repo OrcaSlicer/OrcaSlicer --json title,body,labels,comments` to get full details
+ - Read and understand the full issue content and comments to determine actual user impact
+ - Evaluate: Is this truly blocking users from using Claude Code?
+ - Consider: "crash", "stuck", "frozen", "hang", "unresponsive", "cannot use", "blocked", "broken"
+ - Does it prevent core functionality? Can users work around it?
+ - Be conservative - only flag issues that truly prevent users from getting work done
+
+4. For issues that are truly blocking and don't already have the "oncall" label:
+ - Use `gh issue edit --repo OrcaSlicer/OrcaSlicer --add-label "oncall"`
+ - Mark the issue as complete in your TODO list
+
+5. After processing all issues, provide a summary:
+ - List each issue number that received the "oncall" label
+ - Include the issue title and brief reason why it qualified
+ - If no issues qualified, state that clearly
+
+Important:
+- Process ALL issues in your TODO list systematically
+- Don't post any comments to issues
+- Only add the "oncall" label, never remove it
+- Use individual `gh issue view` commands instead of bash for loops to avoid approval prompts
diff --git a/.doxygen b/.doxygen
index fb8ae5f045..d557f6ba85 100644
--- a/.doxygen
+++ b/.doxygen
@@ -48,7 +48,7 @@ PROJECT_NAME = OrcaSlicer
# could be handy for archiving the generated documentation or if some version
# control system is used.
-PROJECT_NUMBER = 1.6.3
+PROJECT_NUMBER = latest
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
@@ -68,7 +68,7 @@ PROJECT_LOGO = ./resources/images/OrcaSlicer_32px.png
# entered, it will be relative to the location where doxygen was started. If
# left blank the current directory will be used.
-OUTPUT_DIRECTORY = ../
+OUTPUT_DIRECTORY = .
# If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096
# sub-directories (in 2 levels) under the output directory of each output format
@@ -1059,7 +1059,11 @@ EXCLUDE_SYMLINKS = NO
# Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories for example use the pattern */test/*
-EXCLUDE_PATTERNS =
+EXCLUDE_PATTERNS = */deps/*
+EXCLUDE_PATTERNS = */build/*
+EXCLUDE_PATTERNS = */deps_src/*
+
+
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
# (namespaces, classes, functions, etc.) that should be excluded from the
@@ -1286,7 +1290,7 @@ GENERATE_HTML = YES
# The default directory is: html.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_OUTPUT = OrcaSlicer_Dev_Document
+HTML_OUTPUT = internal_docs
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
# generated HTML page (for example: .htm, .php, .asp).
@@ -1565,7 +1569,7 @@ TOC_EXPAND = NO
# protocol see https://www.sitemaps.org
# This tag requires that the tag GENERATE_HTML is set to YES.
-SITEMAP_URL =
+SITEMAP_URL = internals.orcaslicer.com
# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index b8477e12c6..c21e7778ca 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -8,7 +8,7 @@ body:
**Thank you for using Orca Slicer and wanting to report a bug.**
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/SoftFever/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.
+ 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.
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
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
index 3639de151a..066570738f 100644
--- a/.github/ISSUE_TEMPLATE/config.yml
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -4,5 +4,5 @@ contact_links:
url: https://discord.gg/P4VE9UY9gJ
about: Please ask and answer support "how do I?"questions here.
- name: Discussion Forum
- url: https://github.com/SoftFever/OrcaSlicer/discussions
+ url: https://github.com/OrcaSlicer/OrcaSlicer/discussions
about: Please raise ideas and feature suggestions here.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml
index 4ae8a24faa..8494386c5c 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.yml
+++ b/.github/ISSUE_TEMPLATE/feature_request.yml
@@ -8,7 +8,7 @@ body:
Thanks for taking the time to fill out this feature request!
If your idea is still at the formulation stage, or you're not sure it would
- be useful to many users, you can raise it as a discussion topic under [Ideas](https://github.com/SoftFever/OrcaSlicer/discussions/categories/ideas)
+ be useful to many users, you can raise it as a discussion topic under [Ideas](https://github.com/OrcaSlicer/OrcaSlicer/discussions/categories/ideas)
or you can raise it on the [Discord server](https://discord.gg/P4VE9UY9gJ).
- type: checkboxes
attributes:
diff --git a/.github/workflows/assign.yml b/.github/workflows/assign.yml
index 103f2b2359..12ded0d598 100644
--- a/.github/workflows/assign.yml
+++ b/.github/workflows/assign.yml
@@ -14,7 +14,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Assign the user or unassign stale assignments
- uses: takanome-dev/assign-issue-action@v2.3
+ # Note: v3.0.0 is broken (dist/index.mjs vs action.yml expects index.js)
+ # See: https://github.com/takanome-dev/assign-issue-action/issues/426
+ uses: takanome-dev/assign-issue-action@v2.2
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
maintainers: 'noisyfox,softfever'
diff --git a/.github/workflows/auto-close-duplicates.yml b/.github/workflows/auto-close-duplicates.yml
new file mode 100644
index 0000000000..6612c98a03
--- /dev/null
+++ b/.github/workflows/auto-close-duplicates.yml
@@ -0,0 +1,31 @@
+name: Auto-close duplicate issues
+description: Auto-closes issues that are duplicates of existing issues
+on:
+ schedule:
+ - cron: "0 9 * * *"
+ workflow_dispatch:
+
+jobs:
+ auto-close-duplicates:
+ runs-on: ubuntu-latest
+ timeout-minutes: 10
+ permissions:
+ contents: read
+ issues: write
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v6
+
+ - name: Setup Bun
+ uses: oven-sh/setup-bun@v2
+ with:
+ bun-version: latest
+
+ - name: Auto-close duplicate issues
+ run: bun run scripts/auto-close-duplicates.ts
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ GITHUB_REPOSITORY_OWNER: ${{ github.repository_owner }}
+ GITHUB_REPOSITORY_NAME: ${{ github.event.repository.name }}
+ STATSIG_API_KEY: ${{ secrets.STATSIG_API_KEY }}
diff --git a/.github/workflows/backfill-duplicate-comments.yml b/.github/workflows/backfill-duplicate-comments.yml
new file mode 100644
index 0000000000..a4253e8ae0
--- /dev/null
+++ b/.github/workflows/backfill-duplicate-comments.yml
@@ -0,0 +1,44 @@
+name: Backfill Duplicate Comments
+description: Triggers duplicate detection for old issues that don't have duplicate comments
+
+on:
+ workflow_dispatch:
+ inputs:
+ days_back:
+ description: 'How many days back to look for old issues'
+ required: false
+ default: '90'
+ type: string
+ dry_run:
+ description: 'Dry run mode (true to only log what would be done)'
+ required: false
+ default: 'true'
+ type: choice
+ options:
+ - 'true'
+ - 'false'
+
+jobs:
+ backfill-duplicate-comments:
+ runs-on: ubuntu-latest
+ timeout-minutes: 30
+ permissions:
+ contents: read
+ issues: read
+ actions: write
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v6
+
+ - name: Setup Bun
+ uses: oven-sh/setup-bun@v2
+ with:
+ bun-version: latest
+
+ - name: Backfill duplicate comments
+ run: bun run scripts/backfill-duplicate-comments.ts
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ DAYS_BACK: ${{ inputs.days_back }}
+ DRY_RUN: ${{ inputs.dry_run }}
\ No newline at end of file
diff --git a/.github/workflows/build_all.yml b/.github/workflows/build_all.yml
index 1a46740b8f..010775d119 100644
--- a/.github/workflows/build_all.yml
+++ b/.github/workflows/build_all.yml
@@ -21,6 +21,7 @@ on:
- release/*
paths:
- 'deps/**'
+ - 'deps_src/**'
- 'src/**'
- '**/CMakeLists.txt'
- 'version.inc'
@@ -30,6 +31,7 @@ on:
- 'build_release_macos.sh'
- 'scripts/flatpak/**'
+
schedule:
- cron: '0 17 * * *' # run once a day at 1 AM Singapore time (UTC+8)
@@ -51,7 +53,7 @@ jobs:
strategy:
fail-fast: false
# Don't run scheduled builds on forks:
- if: ${{ !cancelled() && (github.event_name != 'schedule' || github.repository == 'SoftFever/OrcaSlicer') }}
+ if: ${{ !cancelled() && (github.event_name != 'schedule' || github.repository == 'OrcaSlicer/OrcaSlicer') }}
uses: ./.github/workflows/build_check_cache.yml
with:
os: ubuntu-24.04
@@ -64,10 +66,10 @@ jobs:
matrix:
include:
- os: windows-latest
- - os: macos-14
+ - os: orca-macos-arm64
arch: arm64
# Don't run scheduled builds on forks:
- if: ${{ !cancelled() && (github.event_name != 'schedule' || github.repository == 'SoftFever/OrcaSlicer') }}
+ if: ${{ !cancelled() && (github.event_name != 'schedule' || github.repository == 'OrcaSlicer/OrcaSlicer') }}
uses: ./.github/workflows/build_check_cache.yml
with:
os: ${{ matrix.os }}
@@ -82,15 +84,16 @@ jobs:
if: ${{ !cancelled() && success() }}
steps:
- name: Checkout
- uses: actions/checkout@v5
+ uses: actions/checkout@v6
with:
sparse-checkout: |
.github
scripts
+ tests
- name: Apt-Install Dependencies
uses: ./.github/actions/apt-install-deps
- name: Restore Test Artifact
- uses: actions/download-artifact@v6
+ uses: actions/download-artifact@v7
with:
name: ${{ github.sha }}-tests
- uses: lukka/get-cmake@latest
@@ -102,7 +105,7 @@ jobs:
tar -xvf build_tests.tar
scripts/run_unit_tests.sh
- name: Upload Test Logs
- uses: actions/upload-artifact@v5
+ uses: actions/upload-artifact@v6
if: ${{ failure() }}
with:
name: unit-test-logs
@@ -115,13 +118,14 @@ jobs:
flatpak:
name: "Flatpak"
container:
- image: ghcr.io/flathub-infra/flatpak-github-actions:gnome-47
+ image: ghcr.io/flathub-infra/flatpak-github-actions:gnome-48
options: --privileged
volumes:
- /usr/local/lib/android:/usr/local/lib/android
- /usr/share/dotnet:/usr/share/dotnet
- /opt/ghc:/opt/ghc1
- /usr/local/share/boost:/usr/local/share/boost1
+ - /opt/hostedtoolcache:/opt/hostedtoolcache1
strategy:
fail-fast: false
matrix:
@@ -131,7 +135,7 @@ jobs:
- arch: aarch64
runner: ubuntu-24.04-arm
# Don't run scheduled builds on forks:
- if: ${{ !cancelled() && (github.event_name != 'schedule' || github.repository == 'SoftFever/OrcaSlicer') }}
+ if: ${{ !cancelled() && (github.event_name != 'schedule' || github.repository == 'OrcaSlicer/OrcaSlicer') }}
runs-on: ${{ matrix.variant.runner }}
env:
date:
@@ -140,8 +144,8 @@ jobs:
steps:
- name: "Remove unneeded stuff to free disk space"
run:
- rm -rf /usr/local/lib/android/* /usr/share/dotnet/* /opt/ghc1/* "/usr/local/share/boost1/*"
- - uses: actions/checkout@v5
+ rm -rf /usr/local/lib/android/* /usr/share/dotnet/* /opt/ghc1/* "/usr/local/share/boost1/*" /opt/hostedtoolcache1/*
+ - uses: actions/checkout@v6
- name: Get the version and date
run: |
ver_pure=$(grep 'set(SoftFever_VERSION' version.inc | cut -d '"' -f2)
@@ -157,7 +161,7 @@ jobs:
echo "date=$(date +'%Y%m%d')" >> $GITHUB_ENV
echo "git_commit_hash=$git_commit_hash" >> $GITHUB_ENV
shell: bash
- - uses: flathub-infra/flatpak-github-actions/flatpak-builder@master
+ - uses: flatpak/flatpak-github-actions/flatpak-builder@master
with:
bundle: OrcaSlicer-Linux-flatpak_${{ env.ver }}_${{ matrix.variant.arch }}.flatpak
manifest-path: scripts/flatpak/io.github.softfever.OrcaSlicer.yml
@@ -165,15 +169,15 @@ jobs:
arch: ${{ matrix.variant.arch }}
upload-artifact: false
- name: Upload artifacts Flatpak
- uses: actions/upload-artifact@v5
+ uses: actions/upload-artifact@v6
with:
name: OrcaSlicer-Linux-flatpak_${{ env.ver }}_${{ matrix.variant.arch }}.flatpak
path: '/__w/OrcaSlicer/OrcaSlicer/OrcaSlicer-Linux-flatpak_${{ env.ver }}_${{ matrix.variant.arch }}.flatpak'
- name: Deploy Flatpak to nightly release
- if: github.repository == 'SoftFever/OrcaSlicer' && github.ref == 'refs/heads/main'
+ if: github.repository == 'OrcaSlicer/OrcaSlicer' && github.ref == 'refs/heads/main'
uses: WebFreak001/deploy-nightly@v3.2.0
with:
- upload_url: https://uploads.github.com/repos/SoftFever/OrcaSlicer/releases/137995723/assets{?name,label}
+ upload_url: https://uploads.github.com/repos/OrcaSlicer/OrcaSlicer/releases/137995723/assets{?name,label}
release_id: 137995723
asset_path: /__w/OrcaSlicer/OrcaSlicer/OrcaSlicer-Linux-flatpak_${{ env.ver }}_${{ matrix.variant.arch }}.flatpak
asset_name: OrcaSlicer-Linux-flatpak_nightly_${{ matrix.variant.arch }}.flatpak
diff --git a/.github/workflows/build_check_cache.yml b/.github/workflows/build_check_cache.yml
index a97962aa7e..61de1f3ff0 100644
--- a/.github/workflows/build_check_cache.yml
+++ b/.github/workflows/build_check_cache.yml
@@ -26,14 +26,14 @@ jobs:
valid-cache: ${{ steps.cache_deps.outputs.cache-hit }}
steps:
- name: Checkout
- uses: actions/checkout@v5
+ uses: actions/checkout@v6
with:
lfs: 'true'
- name: set outputs
id: set_outputs
env:
- dep-folder-name: ${{ inputs.os != 'macos-14' && '/OrcaSlicer_dep' || '' }}
+ dep-folder-name: ${{ inputs.os != 'orca-macos-arm64' && '/OrcaSlicer_dep' || '' }}
output-cmd: ${{ inputs.os == 'windows-latest' && '$env:GITHUB_OUTPUT' || '"$GITHUB_OUTPUT"'}}
run: |
echo cache-key=${{ inputs.os }}-cache-orcaslicer_deps-build-${{ hashFiles('deps/**') }} >> ${{ env.output-cmd }}
@@ -41,7 +41,7 @@ jobs:
- name: load cache
id: cache_deps
- uses: actions/cache@v4
+ uses: actions/cache@v5
with:
path: ${{ steps.set_outputs.outputs.cache-path }}
key: ${{ steps.set_outputs.outputs.cache-key }}
diff --git a/.github/workflows/build_deps.yml b/.github/workflows/build_deps.yml
index e4a985b77a..2ebb53dd1f 100644
--- a/.github/workflows/build_deps.yml
+++ b/.github/workflows/build_deps.yml
@@ -34,12 +34,12 @@ jobs:
# Setup the environment
- name: Checkout
- uses: actions/checkout@v5
+ uses: actions/checkout@v6
with:
lfs: 'true'
- name: load cached deps
- uses: actions/cache@v4
+ uses: actions/cache@v5
with:
path: ${{ inputs.cache-path }}
key: ${{ inputs.cache-key }}
@@ -69,23 +69,23 @@ jobs:
working-directory: ${{ github.workspace }}
run: |
choco install strawberryperl
- .\build_release_vs2022.bat deps
- .\build_release_vs2022.bat pack
+ .\build_release_vs.bat deps
+ .\build_release_vs.bat pack
cd ${{ github.workspace }}/deps/build
- name: Build on Mac ${{ inputs.arch }}
- if: inputs.os == 'macos-14'
+ if: inputs.os == 'orca-macos-arm64'
working-directory: ${{ github.workspace }}
run: |
- brew install automake texinfo libtool
- brew list
- brew uninstall --ignore-dependencies zstd
- ./build_release_macos.sh -dx -a universal -t 10.15 -1
+ # brew install automake texinfo libtool
+ # brew list
+ # brew uninstall --ignore-dependencies zstd
+ ./build_release_macos.sh -dx -a universal -t 10.15
for arch in arm64 x86_64; do
(cd "${{ github.workspace }}/deps/build/${arch}" && \
find . -mindepth 1 -maxdepth 1 ! -name 'OrcaSlicer_dep' -exec rm -rf {} +)
done
- brew install zstd
+ # brew install zstd
- name: Apt-Install Dependencies
@@ -104,15 +104,15 @@ jobs:
# Upload Artifacts
# - name: Upload Mac ${{ inputs.arch }} artifacts
- # if: inputs.os == 'macos-14'
- # uses: actions/upload-artifact@v5
+ # if: inputs.os == 'orca-macos-arm64'
+ # uses: actions/upload-artifact@v6
# with:
# name: OrcaSlicer_dep_mac_${{ env.date }}
# path: ${{ github.workspace }}/deps/build/OrcaSlicer_dep*.tar.gz
- name: Upload Windows artifacts
if: inputs.os == 'windows-latest'
- uses: actions/upload-artifact@v5
+ uses: actions/upload-artifact@v6
with:
name: OrcaSlicer_dep_win64_${{ env.date }}
path: ${{ github.workspace }}/deps/build/OrcaSlicer_dep*.zip
@@ -121,7 +121,7 @@ jobs:
if: ${{ ! env.ACT && inputs.os == 'ubuntu-20.04' || inputs.os == 'ubuntu-24.04' }}
env:
ubuntu-ver: ${{ (inputs.os == 'ubuntu-20.04' && '2004') || (inputs.os == 'ubuntu-24.04' && '2404') || '' }}
- uses: actions/upload-artifact@v5
+ uses: actions/upload-artifact@v6
with:
name: OrcaSlicer_dep_ubuntu_${{ env.ubuntu-ver }}_${{ env.date }}
path: ${{ github.workspace }}/deps/build/OrcaSlicer_dep_ubuntu_*.tar.gz
diff --git a/.github/workflows/build_orca.yml b/.github/workflows/build_orca.yml
index 9da7295565..dbf9d929c7 100644
--- a/.github/workflows/build_orca.yml
+++ b/.github/workflows/build_orca.yml
@@ -26,12 +26,12 @@ jobs:
steps:
- name: Checkout
- uses: actions/checkout@v5
+ uses: actions/checkout@v6
with:
lfs: 'true'
- name: load cached deps
- uses: actions/cache@v4
+ uses: actions/cache@v5
with:
path: ${{ inputs.cache-path }}
key: ${{ inputs.cache-key }}
@@ -86,29 +86,29 @@ jobs:
# Mac
- name: Install tools mac
- if: inputs.os == 'macos-14'
+ if: inputs.os == 'orca-macos-arm64'
run: |
- brew install libtool
- brew list
+ # brew install libtool
+ # brew list
mkdir -p ${{ github.workspace }}/deps/build
- - name: Free disk space
- if: inputs.os == 'macos-14'
- run: |
- df -hI /dev/disk3s1s1
- sudo find /Applications -maxdepth 1 -type d -name "Xcode_*.app" ! -name "Xcode_15.4.app" -exec rm -rf {} +
- sudo rm -rf ~/Library/Developer/CoreSimulator/Caches/*
- df -hI /dev/disk3s1s1
+ # - name: Free disk space
+ # if: inputs.os == 'orca-macos-arm64'
+ # run: |
+ # df -hI /dev/disk3s1s1
+ # sudo find /Applications -maxdepth 1 -type d -name "Xcode_*.app" ! -name "Xcode_15.4.app" -exec rm -rf {} +
+ # sudo rm -rf ~/Library/Developer/CoreSimulator/Caches/*
+ # df -hI /dev/disk3s1s1
- name: Build slicer mac
- if: inputs.os == 'macos-14'
+ if: inputs.os == 'orca-macos-arm64'
working-directory: ${{ github.workspace }}
run: |
- ./build_release_macos.sh -s -n -x -a universal -t 10.15 -1
+ ./build_release_macos.sh -s -n -x -a universal -t 10.15
# Thanks to RaySajuuk, it's working now
- name: Sign app and notary
- if: github.repository == 'SoftFever/OrcaSlicer' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/')) && inputs.os == 'macos-14'
+ if: github.repository == 'OrcaSlicer/OrcaSlicer' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/')) && inputs.os == 'orca-macos-arm64'
working-directory: ${{ github.workspace }}
env:
BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
@@ -122,6 +122,8 @@ jobs:
security create-keychain -p $KEYCHAIN_PASSWORD $KEYCHAIN_PATH
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
security unlock-keychain -p $KEYCHAIN_PASSWORD $KEYCHAIN_PATH
+ # Set the temporary keychain as the default to prevent codesign from accessing the locked login keychain
+ security default-keychain -s "$KEYCHAIN_PATH"
security import $CERTIFICATE_PATH -P $P12_PASSWORD -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
security list-keychain -d user -s $KEYCHAIN_PATH
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $P12_PASSWORD $KEYCHAIN_PATH
@@ -150,18 +152,17 @@ jobs:
fi
# Notarize main DMG
- xcrun notarytool store-credentials "notarytool-profile" --apple-id "${{ secrets.APPLE_DEV_ACCOUNT }}" --team-id "${{ secrets.TEAM_ID }}" --password "${{ secrets.APP_PWD }}"
- xcrun notarytool submit "OrcaSlicer_Mac_universal_${{ env.ver }}.dmg" --keychain-profile "notarytool-profile" --wait
+ xcrun notarytool submit "OrcaSlicer_Mac_universal_${{ env.ver }}.dmg" --apple-id "${{ secrets.APPLE_DEV_ACCOUNT }}" --team-id "${{ secrets.TEAM_ID }}" --password "${{ secrets.APP_PWD }}" --wait
xcrun stapler staple OrcaSlicer_Mac_universal_${{ env.ver }}.dmg
-
+
# Notarize profile validator DMG if it exists
if [ -f "OrcaSlicer_profile_validator_Mac_universal_${{ env.ver }}.dmg" ]; then
- xcrun notarytool submit "OrcaSlicer_profile_validator_Mac_universal_${{ env.ver }}.dmg" --keychain-profile "notarytool-profile" --wait
+ xcrun notarytool submit "OrcaSlicer_profile_validator_Mac_universal_${{ env.ver }}.dmg" --apple-id "${{ secrets.APPLE_DEV_ACCOUNT }}" --team-id "${{ secrets.TEAM_ID }}" --password "${{ secrets.APP_PWD }}" --wait
xcrun stapler staple OrcaSlicer_profile_validator_Mac_universal_${{ env.ver }}.dmg
fi
- name: Create DMG without notary
- if: github.ref != 'refs/heads/main' && inputs.os == 'macos-14'
+ if: github.ref != 'refs/heads/main' && inputs.os == 'orca-macos-arm64'
working-directory: ${{ github.workspace }}
run: |
mkdir -p ${{ github.workspace }}/build/universal/OrcaSlicer_dmg
@@ -180,25 +181,25 @@ jobs:
fi
- name: Upload artifacts mac
- if: inputs.os == 'macos-14'
- uses: actions/upload-artifact@v5
+ if: inputs.os == 'orca-macos-arm64'
+ uses: actions/upload-artifact@v6
with:
name: OrcaSlicer_Mac_universal_${{ env.ver }}
path: ${{ github.workspace }}/OrcaSlicer_Mac_universal_${{ env.ver }}.dmg
- name: Upload OrcaSlicer_profile_validator DMG mac
- if: inputs.os == 'macos-14'
- uses: actions/upload-artifact@v5
+ if: inputs.os == 'orca-macos-arm64'
+ uses: actions/upload-artifact@v6
with:
name: OrcaSlicer_profile_validator_Mac_universal_DMG_${{ env.ver }}
path: ${{ github.workspace }}/OrcaSlicer_profile_validator_Mac_universal_${{ env.ver }}.dmg
if-no-files-found: ignore
- name: Deploy Mac release
- if: github.repository == 'SoftFever/OrcaSlicer' && github.ref == 'refs/heads/main' && inputs.os == 'macos-14'
+ if: github.repository == 'OrcaSlicer/OrcaSlicer' && github.ref == 'refs/heads/main' && inputs.os == 'orca-macos-arm64'
uses: WebFreak001/deploy-nightly@v3.2.0
with:
- upload_url: https://uploads.github.com/repos/SoftFever/OrcaSlicer/releases/137995723/assets{?name,label}
+ upload_url: https://uploads.github.com/repos/OrcaSlicer/OrcaSlicer/releases/137995723/assets{?name,label}
release_id: 137995723
asset_path: ${{ github.workspace }}/OrcaSlicer_Mac_universal_${{ env.ver }}.dmg
asset_name: OrcaSlicer_Mac_universal_nightly.dmg
@@ -206,10 +207,10 @@ jobs:
max_releases: 1 # optional, if there are more releases than this matching the asset_name, the oldest ones are going to be deleted
- name: Deploy Mac OrcaSlicer_profile_validator DMG release
- if: github.repository == 'SoftFever/OrcaSlicer' && github.ref == 'refs/heads/main' && inputs.os == 'macos-14'
+ if: github.repository == 'OrcaSlicer/OrcaSlicer' && github.ref == 'refs/heads/main' && inputs.os == 'orca-macos-arm64'
uses: WebFreak001/deploy-nightly@v3.2.0
with:
- upload_url: https://uploads.github.com/repos/SoftFever/OrcaSlicer/releases/137995723/assets{?name,label}
+ upload_url: https://uploads.github.com/repos/OrcaSlicer/OrcaSlicer/releases/137995723/assets{?name,label}
release_id: 137995723
asset_path: ${{ github.workspace }}/OrcaSlicer_profile_validator_Mac_universal_${{ env.ver }}.dmg
asset_name: OrcaSlicer_profile_validator_Mac_universal_nightly.dmg
@@ -233,7 +234,7 @@ jobs:
env:
WindowsSdkDir: 'C:\Program Files (x86)\Windows Kits\10\'
WindowsSDKVersion: '10.0.26100.0\'
- run: .\build_release_vs2022.bat slicer
+ run: .\build_release_vs.bat slicer
- name: Create installer Win
if: inputs.os == 'windows-latest'
@@ -255,37 +256,37 @@ jobs:
- name: Upload artifacts Win zip
if: inputs.os == 'windows-latest'
- uses: actions/upload-artifact@v5
+ uses: actions/upload-artifact@v6
with:
name: OrcaSlicer_Windows_${{ env.ver }}_portable
path: ${{ github.workspace }}/build/OrcaSlicer
- name: Upload artifacts Win installer
if: inputs.os == 'windows-latest'
- uses: actions/upload-artifact@v5
+ uses: actions/upload-artifact@v6
with:
name: OrcaSlicer_Windows_${{ env.ver }}
path: ${{ github.workspace }}/build/OrcaSlicer*.exe
- name: Upload artifacts Win PDB
if: inputs.os == 'windows-latest'
- uses: actions/upload-artifact@v5
+ uses: actions/upload-artifact@v6
with:
name: PDB
path: ${{ github.workspace }}/build/src/Release/Debug_PDB_${{ env.ver }}_for_developers_only.7z
- name: Upload OrcaSlicer_profile_validator Win
if: inputs.os == 'windows-latest'
- uses: actions/upload-artifact@v5
+ uses: actions/upload-artifact@v6
with:
name: OrcaSlicer_profile_validator_Windows_${{ env.ver }}
path: ${{ github.workspace }}/build/src/Release/OrcaSlicer_profile_validator.exe
- name: Deploy Windows release portable
- if: github.repository == 'SoftFever/OrcaSlicer' && github.ref == 'refs/heads/main' && inputs.os == 'windows-latest'
+ if: github.repository == 'OrcaSlicer/OrcaSlicer' && github.ref == 'refs/heads/main' && inputs.os == 'windows-latest'
uses: WebFreak001/deploy-nightly@v3.2.0
with:
- upload_url: https://uploads.github.com/repos/SoftFever/OrcaSlicer/releases/137995723/assets{?name,label}
+ upload_url: https://uploads.github.com/repos/OrcaSlicer/OrcaSlicer/releases/137995723/assets{?name,label}
release_id: 137995723
asset_path: ${{ github.workspace }}/build/OrcaSlicer_Windows_${{ env.ver }}_portable.zip
asset_name: OrcaSlicer_Windows_nightly_portable.zip
@@ -293,10 +294,10 @@ jobs:
max_releases: 1
- name: Deploy Windows release installer
- if: github.repository == 'SoftFever/OrcaSlicer' && github.ref == 'refs/heads/main' && inputs.os == 'windows-latest'
+ if: github.repository == 'OrcaSlicer/OrcaSlicer' && github.ref == 'refs/heads/main' && inputs.os == 'windows-latest'
uses: WebFreak001/deploy-nightly@v3.2.0
with:
- upload_url: https://uploads.github.com/repos/SoftFever/OrcaSlicer/releases/137995723/assets{?name,label}
+ upload_url: https://uploads.github.com/repos/OrcaSlicer/OrcaSlicer/releases/137995723/assets{?name,label}
release_id: 137995723
asset_path: ${{ github.workspace }}/build/OrcaSlicer_Windows_Installer_${{ env.ver }}.exe
asset_name: OrcaSlicer_Windows_Installer_nightly.exe
@@ -304,10 +305,10 @@ jobs:
max_releases: 1
- name: Deploy Windows OrcaSlicer_profile_validator release
- if: github.repository == 'SoftFever/OrcaSlicer' && github.ref == 'refs/heads/main' && inputs.os == 'windows-latest'
+ if: github.repository == 'OrcaSlicer/OrcaSlicer' && github.ref == 'refs/heads/main' && inputs.os == 'windows-latest'
uses: WebFreak001/deploy-nightly@v3.2.0
with:
- upload_url: https://uploads.github.com/repos/SoftFever/OrcaSlicer/releases/137995723/assets{?name,label}
+ upload_url: https://uploads.github.com/repos/OrcaSlicer/OrcaSlicer/releases/137995723/assets{?name,label}
release_id: 137995723
asset_path: ${{ github.workspace }}/build/src/Release/OrcaSlicer_profile_validator.exe
asset_name: OrcaSlicer_profile_validator_Windows_nightly.exe
@@ -336,7 +337,7 @@ jobs:
# and doesn't preserve file permissions
- name: Upload Test Artifact
if: inputs.os == 'ubuntu-24.04'
- uses: actions/upload-artifact@v5
+ uses: actions/upload-artifact@v6
with:
name: ${{ github.sha }}-tests
overwrite: true
@@ -358,7 +359,7 @@ jobs:
env:
ubuntu-ver: ${{ (inputs.os == 'ubuntu-20.04' && '2004') || (inputs.os == 'ubuntu-24.04' && '2404') || '' }}
ubuntu-ver-str: ${{ (inputs.os == 'ubuntu-24.04' && '_Ubuntu2404') || '' }}
- uses: actions/upload-artifact@v5
+ uses: actions/upload-artifact@v6
with:
name: OrcaSlicer_Linux_ubuntu_${{ env.ubuntu-ver }}_${{ env.ver }}
path: './build/OrcaSlicer_Linux_AppImage${{ env.ubuntu-ver-str }}_${{ env.ver }}.AppImage'
@@ -367,25 +368,25 @@ jobs:
if: ${{ ! env.ACT && inputs.os == 'ubuntu-20.04' || inputs.os == 'ubuntu-24.04' }}
env:
ubuntu-ver: ${{ (inputs.os == 'ubuntu-20.04' && '2004') || (inputs.os == 'ubuntu-24.04' && '2404') || '' }}
- uses: actions/upload-artifact@v5
+ uses: actions/upload-artifact@v6
with:
name: OrcaSlicer_profile_validator_Linux_ubuntu_${{ env.ubuntu-ver }}_${{ env.ver }}
path: './build/src/Release/OrcaSlicer_profile_validator'
- name: Deploy Ubuntu release
- if: ${{ github.repository == 'SoftFever/OrcaSlicer' && ! env.ACT && github.ref == 'refs/heads/main' && (inputs.os == 'ubuntu-20.04' || inputs.os == 'ubuntu-24.04') }}
+ if: ${{ github.repository == 'OrcaSlicer/OrcaSlicer' && ! env.ACT && github.ref == 'refs/heads/main' && (inputs.os == 'ubuntu-20.04' || inputs.os == 'ubuntu-24.04') }}
env:
ubuntu-ver-str: ${{ (inputs.os == 'ubuntu-24.04' && '_Ubuntu2404') || '' }}
uses: WebFreak001/deploy-nightly@v3.2.0
with:
- upload_url: https://uploads.github.com/repos/SoftFever/OrcaSlicer/releases/137995723/assets{?name,label}
+ upload_url: https://uploads.github.com/repos/OrcaSlicer/OrcaSlicer/releases/137995723/assets{?name,label}
release_id: 137995723
asset_path: ./build/OrcaSlicer_Linux_AppImage${{ env.ubuntu-ver-str }}_${{ env.ver }}.AppImage
asset_name: OrcaSlicer_Linux_AppImage${{ env.ubuntu-ver-str }}_nightly.AppImage
asset_content_type: application/octet-stream
max_releases: 1 # optional, if there are more releases than this matching the asset_name, the oldest ones are going to be deleted
- name: Deploy Ubuntu release
- if: ${{ github.repository == 'SoftFever/OrcaSlicer' && ! env.ACT && github.ref == 'refs/heads/main' && inputs.os == 'ubuntu-24.04' }}
+ if: ${{ github.repository == 'OrcaSlicer/OrcaSlicer' && ! env.ACT && github.ref == 'refs/heads/main' && inputs.os == 'ubuntu-24.04' }}
uses: rickstaa/action-create-tag@v1
with:
tag: "nightly-builds"
@@ -394,12 +395,12 @@ jobs:
message: "nightly-builds"
- name: Deploy Ubuntu OrcaSlicer_profile_validator release
- if: ${{ github.repository == 'SoftFever/OrcaSlicer' && ! env.ACT && github.ref == 'refs/heads/main' && (inputs.os == 'ubuntu-20.04' || inputs.os == 'ubuntu-24.04') }}
+ if: ${{ github.repository == 'OrcaSlicer/OrcaSlicer' && ! env.ACT && github.ref == 'refs/heads/main' && (inputs.os == 'ubuntu-20.04' || inputs.os == 'ubuntu-24.04') }}
env:
ubuntu-ver-str: ${{ (inputs.os == 'ubuntu-24.04' && '_Ubuntu2404') || '' }}
uses: WebFreak001/deploy-nightly@v3.2.0
with:
- upload_url: https://uploads.github.com/repos/SoftFever/OrcaSlicer/releases/137995723/assets{?name,label}
+ upload_url: https://uploads.github.com/repos/OrcaSlicer/OrcaSlicer/releases/137995723/assets{?name,label}
release_id: 137995723
asset_path: ./build/src/Release/OrcaSlicer_profile_validator
asset_name: OrcaSlicer_profile_validator_Linux${{ env.ubuntu-ver-str }}_nightly
@@ -407,10 +408,10 @@ jobs:
max_releases: 1
- name: Deploy orca_custom_preset_tests
- if: ${{ github.repository == 'SoftFever/OrcaSlicer' && ! env.ACT && github.ref == 'refs/heads/main' && inputs.os == 'ubuntu-24.04' }}
+ if: ${{ github.repository == 'OrcaSlicer/OrcaSlicer' && ! env.ACT && github.ref == 'refs/heads/main' && inputs.os == 'ubuntu-24.04' }}
uses: WebFreak001/deploy-nightly@v3.2.0
with:
- upload_url: https://uploads.github.com/repos/SoftFever/OrcaSlicer/releases/137995723/assets{?name,label}
+ upload_url: https://uploads.github.com/repos/OrcaSlicer/OrcaSlicer/releases/137995723/assets{?name,label}
release_id: 137995723
asset_path: ${{ github.workspace }}/resources/profiles/orca_custom_preset_tests.zip
asset_name: orca_custom_preset_tests.zip
diff --git a/.github/workflows/check_locale.yml b/.github/workflows/check_locale.yml
index 5eed883792..f248ced29c 100644
--- a/.github/workflows/check_locale.yml
+++ b/.github/workflows/check_locale.yml
@@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
- uses: actions/checkout@v5
+ uses: actions/checkout@v6
- name: Install gettext
run: |
diff --git a/.github/workflows/check_profiles.yml b/.github/workflows/check_profiles.yml
index f1d75d818f..9da59f43a7 100644
--- a/.github/workflows/check_profiles.yml
+++ b/.github/workflows/check_profiles.yml
@@ -1,8 +1,8 @@
name: Check profiles
-on:
+on:
pull_request:
- branches:
- - main
+ branches:
+ - main
paths:
- 'resources/profiles/**'
- ".github/workflows/check_profiles.yml"
@@ -10,25 +10,33 @@ on:
workflow_dispatch:
inputs:
logLevel:
- description: 'Log level'
+ description: 'Log level'
required: true
default: 'warning'
+permissions:
+ pull-requests: write
+ contents: read
+
jobs:
check_translation:
name: Check profiles
runs-on: ubuntu-24.04
- steps:
+ steps:
- name: Checkout repository
- uses: actions/checkout@v5
+ uses: actions/checkout@v6
- name: Run extra JSON check
+ id: extra_json_check
+ continue-on-error: true
run: |
- python3 ./scripts/orca_extra_profile_check.py
+ set +e
+ python3 ./scripts/orca_extra_profile_check.py 2>&1 | tee ${{ runner.temp }}/extra_json_check.log
+ exit ${PIPESTATUS[0]}
# download
- - name: Download
+ - name: Download
working-directory: ${{ github.workspace }}
run: |
curl -LJO https://github.com/SoftFever/Orca_tools/releases/download/1/OrcaSlicer_profile_validator
@@ -36,15 +44,71 @@ jobs:
# validate profiles
- name: validate system profiles
+ id: validate_system
+ continue-on-error: true
run: |
- ./OrcaSlicer_profile_validator -p ${{ github.workspace }}/resources/profiles -l 2
+ set +e
+ ./OrcaSlicer_profile_validator -p ${{ github.workspace }}/resources/profiles -l 2 2>&1 | tee ${{ runner.temp }}/validate_system.log
+ exit ${PIPESTATUS[0]}
- name: validate custom presets
+ id: validate_custom
+ continue-on-error: true
working-directory: ${{ github.workspace }}
run: |
- curl -LJO https://github.com/SoftFever/OrcaSlicer/releases/download/nightly-builds/orca_custom_preset_tests.zip
- unzip ./orca_custom_preset_tests.zip -d ${{ github.workspace }}/resources/profiles
- ./OrcaSlicer_profile_validator -p ${{ github.workspace }}/resources/profiles -l 2
+ set +e
+ curl -LJO https://github.com/OrcaSlicer/OrcaSlicer/releases/download/nightly-builds/orca_custom_preset_tests.zip
+ unzip -q ./orca_custom_preset_tests.zip -d ${{ github.workspace }}/resources/profiles
+ ./OrcaSlicer_profile_validator -p ${{ github.workspace }}/resources/profiles -l 2 2>&1 | tee ${{ runner.temp }}/validate_custom.log
+ exit ${PIPESTATUS[0]}
+
+ - name: Post error comment on PR
+ if: ${{ always() && github.event_name == 'pull_request' && (steps.extra_json_check.outcome == 'failure' || steps.validate_system.outcome == 'failure' || steps.validate_custom.outcome == 'failure') }}
+ env:
+ GH_TOKEN: ${{ github.token }}
+ run: |
+ {
+ echo "## :x: Profile Validation Errors"
+ echo ""
+
+ if [ "${{ steps.extra_json_check.outcome }}" = "failure" ]; then
+ echo "### Extra JSON Check Failed"
+ echo ""
+ echo '```'
+ head -c 30000 ${{ runner.temp }}/extra_json_check.log || echo "No output captured"
+ echo '```'
+ echo ""
+ fi
+
+ if [ "${{ steps.validate_system.outcome }}" = "failure" ]; then
+ echo "### System Profile Validation Failed"
+ echo ""
+ echo '```'
+ head -c 30000 ${{ runner.temp }}/validate_system.log || echo "No output captured"
+ echo '```'
+ echo ""
+ fi
+
+ if [ "${{ steps.validate_custom.outcome }}" = "failure" ]; then
+ echo "### Custom Preset Validation Failed"
+ echo ""
+ echo '```'
+ head -c 30000 ${{ runner.temp }}/validate_custom.log || echo "No output captured"
+ echo '```'
+ echo ""
+ fi
+
+ echo "---"
+ echo "*Please fix the above errors and push a new commit.*"
+ } > ${{ runner.temp }}/pr_comment.md
+
+ gh pr comment ${{ github.event.pull_request.number }} --body-file ${{ runner.temp }}/pr_comment.md
+
+ - name: Fail if any check failed
+ if: ${{ always() && (steps.extra_json_check.outcome == 'failure' || steps.validate_system.outcome == 'failure' || steps.validate_custom.outcome == 'failure') }}
+ run: |
+ echo "One or more profile checks failed. See above for details."
+ exit 1
diff --git a/.github/workflows/dedupe-issues.yml b/.github/workflows/dedupe-issues.yml
new file mode 100644
index 0000000000..abaf978d27
--- /dev/null
+++ b/.github/workflows/dedupe-issues.yml
@@ -0,0 +1,81 @@
+name: Orca Issue Dedupe
+description: Automatically dedupe GitHub issues using AI
+on:
+ issues:
+ types: [opened]
+ workflow_dispatch:
+ inputs:
+ issue_number:
+ description: 'Issue number to process for duplicate detection'
+ required: true
+ type: string
+
+jobs:
+ dedupe-issues:
+ runs-on: ubuntu-latest
+ timeout-minutes: 30
+ permissions:
+ contents: read
+ issues: write
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v6
+
+ - name: Run Claude Code slash command
+ uses: anthropics/claude-code-base-action@beta
+ with:
+ prompt: "/dedupe ${{ github.repository }}/issues/${{ github.event.issue.number || inputs.issue_number }}"
+ claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
+ claude_args: "--model claude-sonnet-4-5-20250929"
+ claude_env: |
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Log duplicate comment event to Statsig
+ if: always()
+ env:
+ STATSIG_API_KEY: ${{ secrets.STATSIG_API_KEY }}
+ run: |
+ ISSUE_NUMBER=${{ github.event.issue.number || inputs.issue_number }}
+ REPO=${{ github.repository }}
+
+ if [ -z "$STATSIG_API_KEY" ]; then
+ echo "STATSIG_API_KEY not found, skipping Statsig logging"
+ exit 0
+ fi
+
+ # Prepare the event payload
+ EVENT_PAYLOAD=$(jq -n \
+ --arg issue_number "$ISSUE_NUMBER" \
+ --arg repo "$REPO" \
+ --arg triggered_by "${{ github.event_name }}" \
+ '{
+ events: [{
+ eventName: "github_duplicate_comment_added",
+ value: 1,
+ metadata: {
+ repository: $repo,
+ issue_number: ($issue_number | tonumber),
+ triggered_by: $triggered_by,
+ workflow_run_id: "${{ github.run_id }}"
+ },
+ time: (now | floor | tostring)
+ }]
+ }')
+
+ # Send to Statsig API
+ echo "Logging duplicate comment event to Statsig for issue #${ISSUE_NUMBER}"
+
+ RESPONSE=$(curl -s -w "\n%{http_code}" -X POST https://events.statsigapi.net/v1/log_event \
+ -H "Content-Type: application/json" \
+ -H "STATSIG-API-KEY: ${STATSIG_API_KEY}" \
+ -d "$EVENT_PAYLOAD")
+
+ HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
+ BODY=$(echo "$RESPONSE" | head -n-1)
+
+ if [ "$HTTP_CODE" -eq 200 ] || [ "$HTTP_CODE" -eq 202 ]; then
+ echo "Successfully logged duplicate comment event for issue #${ISSUE_NUMBER}"
+ else
+ echo "Failed to log duplicate comment event for issue #${ISSUE_NUMBER}. HTTP ${HTTP_CODE}: ${BODY}"
+ fi
diff --git a/.github/workflows/doxygen-docs.yml b/.github/workflows/doxygen-docs.yml
new file mode 100644
index 0000000000..f30c3e0d0e
--- /dev/null
+++ b/.github/workflows/doxygen-docs.yml
@@ -0,0 +1,78 @@
+name: Generate Doxygen Documentation
+
+on:
+ schedule:
+ - cron: '0 0 * * 1' # Every Monday at midnight UTC
+ workflow_dispatch: # Manual trigger
+
+concurrency:
+ group: ${{ github.workflow }}
+ cancel-in-progress: true
+
+jobs:
+ build-and-deploy:
+ name: Build and Deploy Docs
+ runs-on: ubuntu-latest
+ timeout-minutes: 60
+ # Only run on main branch of the main repository
+ if: github.repository == 'OrcaSlicer/OrcaSlicer' && github.ref == 'refs/heads/main'
+ permissions:
+ contents: read
+ steps:
+ - uses: thejerrybao/setup-swap-space@v1
+ with:
+ swap-space-path: /swapfile
+ swap-size-gb: 8
+ remove-existing-swap-files: true
+
+ - name: Checkout repository
+ uses: actions/checkout@v6
+
+ - name: Install Doxygen and Graphviz
+ run: |
+ set -euo pipefail
+ sudo apt-get update
+ sudo apt-get install -y doxygen graphviz
+
+ - name: Generate documentation
+ run: |
+ set -euo pipefail
+ # Override DOT_NUM_THREADS to avoid parallel dot race condition bug
+ sed -i 's/^DOT_NUM_THREADS.*/DOT_NUM_THREADS = 1/' .doxygen
+ doxygen .doxygen
+ # Verify documentation was generated
+ if [ ! -f "internal_docs/index.html" ]; then
+ echo "Error: Documentation generation failed - index.html not found"
+ exit 1
+ fi
+ - name: Install Rclone
+ run: |
+ set -euo pipefail
+ sudo -v
+ curl -fsSL https://rclone.org/install.sh | sudo bash
+
+ - name: optimize
+ run: |
+ set -euo pipefail
+ rm -f internal_docs/Nodes.xml internal_docs/Tokens.xml
+ find internal_docs -name "*.map" -type f -delete || true
+ find internal_docs -name "*.md5" -type f -delete || true
+
+ - name: upload
+ # We configure rclone dynamically using environment variables
+ run: |
+ set -euo pipefail
+ # Remove existing config if it exists to avoid conflicts
+ rclone config delete cloudflare 2>/dev/null || true
+ rclone config create cloudflare s3 \
+ provider Cloudflare \
+ access_key_id ${{ secrets.R2_ACCESS_KEY_ID }} \
+ secret_access_key ${{ secrets.R2_SECRET_ACCESS_KEY }} \
+ endpoint ${{ secrets.R2_ENDPOINT }}
+
+ rclone sync internal_docs/ cloudflare:orcaslicer-internals \
+ --progress \
+ --transfers 512 \
+ --checkers 512
+
+ echo "Documentation upload completed successfully"
\ No newline at end of file
diff --git a/.github/workflows/orca_bot.yml b/.github/workflows/orca_bot.yml
deleted file mode 100644
index 81664be04e..0000000000
--- a/.github/workflows/orca_bot.yml
+++ /dev/null
@@ -1,73 +0,0 @@
-name: Orca bot
-on:
- schedule:
- - cron: "0 0 * * *"
- workflow_dispatch:
- inputs:
- logLevel:
- description: 'Log level'
- required: true
- default: 'warning'
-
-jobs:
- stale:
- runs-on: ubuntu-latest
- permissions:
- issues: write
- pull-requests: write
- contents: write # only for delete-branch option
- steps:
- - uses: actions/stale@v10
- with:
- # PAT for GitHub API authentication
- repo-token: ${{ secrets.GITHUB_TOKEN }}
- # Max number of operations per run
- operations-per-run: 1000
- # Order to get issues/PRs
- ascending: true
-
- # ISSUES
- # Do not auto-close an issue if it is assigned to a milestone
- exempt-all-issue-milestones: true
- # Exempt all issues with assignees from stale
- exempt-all-issue-assignees: true
- # Exempt feature requests
- exempt-issue-labels: "enhancement"
- # Idle number of days before marking issues stale
- days-before-issue-stale: 90
- # Idle number of days before marking issues close
- days-before-issue-close: 7
- # Label to apply on staled issues
- stale-issue-label: "stale"
- # Issue close reason
- close-issue-reason: not_planned
- # Remove stale label from issues on updates
- remove-issue-stale-when-updated: true
- # Issue stale message
- stale-issue-message: "Orca bot: this issue is stale because it has been open for 90 days with no activity."
- # Issue closure message
- close-issue-message: "Orca bot: This issue was closed because it has been inactive for 7 days since being marked as stale."
-
- # PRs
- # Do not auto-close a PR if it is assigned to a milestone
- exempt-all-pr-milestones: true
- # Exempt all PRs with assignees from stale
- exempt-all-pr-assignees: true
- # Skip the stale action for draft PRs
- exempt-draft-pr: true
- # Idle number of days before marking PRs stale
- days-before-pr-stale: -1
- # Idle number of days before marking PRs close
- days-before-pr-close: -1
- # Label to apply on staled PRs
- stale-pr-label: "stale"
- # Label to apply on closed PRs
- close-pr-label: not_planned
- # Remove stale label from PRs on updates
- remove-pr-stale-when-updated: true
- # PR stale message
- stale-pr-message: "Orca bot: this PR is stale because it has been open for XX days with no activity."
- # PR closure message
- close-pr-message: "Orca bot: This PR was closed because it has been inactive for X days since being marked as stale."
- # Delete branch after closing a stale PR
- delete-branch: true
diff --git a/.github/workflows/publish_docs_to_wiki.yml b/.github/workflows/publish_docs_to_wiki.yml
deleted file mode 100644
index 06a0d8f772..0000000000
--- a/.github/workflows/publish_docs_to_wiki.yml
+++ /dev/null
@@ -1,46 +0,0 @@
-name: Publish docs to Wiki
-
-# Trigger this action only if there are changes pushed to the doc/** directory under the main branch
-on:
- push:
- paths:
- - doc/** # This includes all sub folders
- branches:
- - main # This can be changed to any branch of your preference
-
- workflow_dispatch:
- inputs:
- logLevel:
- description: 'Log level'
- required: true
- default: 'warning'
-
-env:
- USER_TOKEN: ${{ secrets.GH_WIKI_PAT }} # This is the repository secret personal access token
- USER_NAME: ${{ vars.BOT_USER_NAME }} # Enter the username of your (bot) account
- OWNER: ${{ github.event.repository.owner.name }} # This is the repository owner
- REPOSITORY_NAME: ${{ github.event.repository.name }} # This is the repository name
-
-jobs:
- publish_docs_to_wiki:
- name: Publish docs to Wiki
- runs-on: ubuntu-latest
- steps:
- - name: Checkout repository
- uses: actions/checkout@v5
-
- # 1. Clone the current wiki master branch to a folder named `tmp_wiki`
- - name: Pull content from wiki
- run: |
- git config --global user.name "$USER_NAME"
- git config --global user.email "$USER_NAME"@users.noreply.github.com
- git clone https://"$USER_TOKEN"@github.com/SoftFever/"$REPOSITORY_NAME".wiki.git tmp_wiki
- # 4. Synchronize differences between `doc` & `tmp_wiki`
- # 5. Push new Wiki content
- - name: Push main repo content to wiki
- run: |
- rsync -av --delete doc/ tmp_wiki/ --exclude .git
- cd tmp_wiki
- git add .
- git commit -m "Updated Wiki content"
- git push origin master
diff --git a/.github/workflows/shellcheck.yml b/.github/workflows/shellcheck.yml
index db702f467f..d5fe5a35d2 100644
--- a/.github/workflows/shellcheck.yml
+++ b/.github/workflows/shellcheck.yml
@@ -21,7 +21,7 @@ jobs:
steps:
- name: Cache shellcheck download
id: cache-shellcheck-v0_11
- uses: actions/cache@v4
+ uses: actions/cache@v5
with:
path: ~/shellcheck
key: ${{ runner.os }}-shellcheck-v0_11
@@ -36,7 +36,7 @@ jobs:
tar -xvf ~/sc.tar.xz -C ~
mv ~/shellcheck-"${INPUT_VERSION}"/shellcheck ~/shellcheck
- - uses: actions/checkout@v5
+ - uses: actions/checkout@v6
with:
fetch-depth: 1
diff --git a/.github/workflows/update-translation.yml b/.github/workflows/update-translation.yml
index aeae4a37b2..983e418b5b 100644
--- a/.github/workflows/update-translation.yml
+++ b/.github/workflows/update-translation.yml
@@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
- uses: actions/checkout@v5
+ uses: actions/checkout@v6
- name: Setup Python
uses: actions/setup-python@v6
diff --git a/.github/workflows/validate-documentation.yml b/.github/workflows/validate-documentation.yml
deleted file mode 100644
index b2ce951135..0000000000
--- a/.github/workflows/validate-documentation.yml
+++ /dev/null
@@ -1,368 +0,0 @@
-name: Validate Documentation
-
-on:
- pull_request:
- paths:
- - 'src/slic3r/GUI/Tab.cpp'
- - 'doc/**/*.md'
- workflow_dispatch:
-
-permissions:
- contents: read
- pull-requests: write
- issues: write
-
-jobs:
- validate:
- runs-on: windows-latest
- name: Check Documentation
-
- steps:
- - name: Checkout
- uses: actions/checkout@v5
-
- - name: Get changed files
- id: changed-files
- uses: tj-actions/changed-files@v47
- with:
- files: |
- src/slic3r/GUI/Tab.cpp
- doc/**/*.md
-
- - name: Run validation
- if: steps.changed-files.outputs.any_changed == 'true'
- shell: pwsh
- run: |
- # Helper Functions
- function Normalize-Fragment($fragment) {
- return $fragment.ToLower().Trim() -replace '[^a-z0-9\s-]', '' -replace ' ', '-' -replace '^-+|-+$', ''
- }
-
- function Add-BrokenReference($sourceFile, $line, $target, $issue, $type) {
- return @{
- SourceFile = $sourceFile
- Line = $line
- Target = $target
- Issue = $issue
- Type = $type
- }
- }
-
- function Validate-Fragment($fragment, $availableAnchors, $sourceFile, $line, $target, $type) {
- $cleanFragment = $fragment.StartsWith('#') ? $fragment.Substring(1) : $fragment
- $normalizedFragment = Normalize-Fragment $cleanFragment
-
- if ($availableAnchors -notcontains $normalizedFragment) {
- return Add-BrokenReference $sourceFile $line $target "Fragment does not exist" $type
- }
- return $null
- }
-
- function Get-ImagesFromLine($line) {
- $images = @()
- $lineForParsing = [regex]::Replace($line, '`[^`]*`', '')
-
- # Process markdown and HTML images
- $imagePatterns = @(
- @{ Pattern = "!\[([^\]]*)\]\(([^)]+)\)"; Type = "Markdown"; AltGroup = 1; UrlGroup = 2 }
- @{ Pattern = '
]*>'; Type = "HTML"; AltGroup = -1; UrlGroup = -1 }
- )
-
- foreach ($pattern in $imagePatterns) {
- foreach ($match in [regex]::Matches($lineForParsing, $pattern.Pattern)) {
- $altText = ""
- $url = ""
-
- if ($pattern.Type -eq "Markdown") {
- $altText = $match.Groups[$pattern.AltGroup].Value
- $url = $match.Groups[$pattern.UrlGroup].Value
- } else {
- # Extract from HTML
- $imgTag = $match.Value
- if ($imgTag -match 'alt\s*=\s*[`"'']([^`"'']*)[`"'']') { $altText = $matches[1] }
- if ($imgTag -match 'src\s*=\s*[`"'']([^`"'']*)[`"'']') { $url = $matches[1] }
- }
-
- $images += @{
- Match = $match.Value
- Type = $pattern.Type
- AltText = $altText
- Url = $url
- StartIndex = $match.Index
- Length = $match.Length
- }
- }
- }
-
- return $images
- }
-
- # Initialize
- $tabFile = Join-Path $PWD "src/slic3r/GUI/Tab.cpp"
- $docDir = Join-Path $PWD 'doc'
- $brokenReferences = @()
- $docIndex = @{}
-
- Write-Host "Validating documentation..." -ForegroundColor Blue
-
- # Validate paths
- $hasTabFile = Test-Path $tabFile
- if (-not $hasTabFile) { Write-Host "::warning::Tab.cpp file not found at: $tabFile" }
- if (-not (Test-Path $docDir)) { Write-Host "::error::doc folder does not exist"; exit 1 }
-
- # Build documentation index
- $mdFiles = Get-ChildItem -Path $docDir -Filter *.md -Recurse -File -ErrorAction SilentlyContinue
-
- foreach ($mdFile in $mdFiles) {
- $baseName = [System.IO.Path]::GetFileNameWithoutExtension($mdFile.Name)
- $relPath = (Resolve-Path $mdFile.FullName).Path.Substring($docDir.Length).TrimStart('\', '/')
- $content = Get-Content -Path $mdFile.FullName -Encoding UTF8 -Raw
- $lines = Get-Content -Path $mdFile.FullName -Encoding UTF8
-
- # Extract anchors
- $anchors = @()
- $anchors += [regex]::Matches($content, '(?i)]*(?:name|id)\s*=\s*[`"'']([^`"'']+)[`"'']') |
- ForEach-Object { $_.Groups[1].Value.ToLower() }
- $anchors += [regex]::Matches($content, '(?m)^#+\s+(.+)$') |
- ForEach-Object { Normalize-Fragment $_.Groups[1].Value.Trim() }
-
- # Parse links
- $links = @()
- $inCodeFence = $false
- for ($i = 0; $i -lt $lines.Count; $i++) {
- $line = $lines[$i]
- if ($line.TrimStart() -match '^(```|~~~)') {
- $inCodeFence = -not $inCodeFence
- continue
- }
- if ($inCodeFence) { continue }
-
- $lineForParsing = [regex]::Replace($line, '`[^`]*`', '')
-
- # Get all images from this line to skip them in link processing
- $imagesInLine = Get-ImagesFromLine $line
- $imageRanges = @()
- foreach ($img in $imagesInLine) {
- # Exclude the entire image syntax from link processing
- $imageRanges += @{ Start = $img.StartIndex; End = $img.StartIndex + $img.Length }
- }
-
- # Find all markdown links, but exclude those that are part of images
- foreach ($linkMatch in [regex]::Matches($lineForParsing, '(?append_single_option_line\s*\(\s*(?:"([^"]+)"|([^,]+?))\s*,\s*"([^"]+)"\s*\)'
- $lines = Get-Content -Path $tabFile -Encoding UTF8
-
- for ($i = 0; $i -lt $lines.Count; $i++) {
- foreach ($match in [regex]::Matches($lines[$i], $regex)) {
- $arg2Full = $match.Groups[3].Value.Trim()
-
- if ($arg2Full.Contains('##')) {
- $brokenReferences += Add-BrokenReference "Tab.cpp" ($i + 1) $arg2Full "Use single # for fragments." "Link"
- continue
- }
-
- $arg2Parts = $arg2Full -split '#', 2
- $docBase = $arg2Parts[0].Trim()
- $fragment = ($arg2Parts.Length -gt 1) ? $arg2Parts[1].Trim() : $null
-
- if (-not $docIndex.ContainsKey($docBase)) {
- $brokenReferences += Add-BrokenReference "Tab.cpp" ($i + 1) $docBase "File does not exist" "Link"
- } elseif ($fragment) {
- $validationResult = Validate-Fragment $fragment $docIndex[$docBase].Anchors "Tab.cpp" ($i + 1) "$docBase#$fragment" "Link"
- if ($validationResult) { $brokenReferences += $validationResult }
- }
- }
- }
- }
-
- # Validate markdown links
- foreach ($baseName in $docIndex.Keys) {
- foreach ($link in $docIndex[$baseName].Links) {
- if (-not $docIndex.ContainsKey($link.TargetBase)) {
- $brokenReferences += Add-BrokenReference $link.SourceFile $link.Line "$($link.TargetBase).md" "File does not exist" "Link"
- } elseif ($link.Fragment) {
- $validationResult = Validate-Fragment $link.Fragment $docIndex[$link.TargetBase].Anchors $link.SourceFile $link.Line "$($link.TargetBase)#$($link.Fragment)" "Link"
- if ($validationResult) { $brokenReferences += $validationResult }
- }
- }
- }
-
- # Validate images
- Write-Host "Validating images..." -ForegroundColor Blue
- $expectedUrlPattern = '^https://github\.com/SoftFever/OrcaSlicer/blob/main/([^?]+)\?raw=true$'
-
- foreach ($file in $mdFiles) {
- $lines = Get-Content $file.FullName -Encoding UTF8
- $relPath = (Resolve-Path $file.FullName).Path.Substring($docDir.Length).TrimStart('\', '/')
-
- $inCodeFence = $false
- for ($lineNumber = 0; $lineNumber -lt $lines.Count; $lineNumber++) {
- $line = $lines[$lineNumber]
- if ($line.TrimStart() -match '^(```|~~~)') {
- $inCodeFence = -not $inCodeFence
- continue
- }
- if ($inCodeFence) { continue }
-
- # Use the unified image detection function
- $imagesInLine = Get-ImagesFromLine $line
-
- foreach ($image in $imagesInLine) {
- $altText = $image.AltText
- $url = $image.Url
- $imageMatch = $image.Match
- $imageType = $image.Type
-
- if (-not $altText.Trim() -and $url) {
- $brokenReferences += Add-BrokenReference $relPath ($lineNumber + 1) $imageMatch "[$imageType] Missing alt text for image" "Image"
- } elseif ($url -and $altText) {
- # Validate URL format and file existence
- if ($url -match $expectedUrlPattern) {
- $relativePathInUrl = $matches[1]
- $fileNameFromUrl = [System.IO.Path]::GetFileNameWithoutExtension($relativePathInUrl)
-
- if ($altText -ne $fileNameFromUrl) {
- $brokenReferences += Add-BrokenReference $relPath ($lineNumber + 1) $imageMatch "[$imageType] Alt text `"$altText`" ≠ filename `"$fileNameFromUrl`"" "Image"
- }
-
- $expectedImagePath = Join-Path $PWD ($relativePathInUrl -replace "/", "\")
- if (-not (Test-Path $expectedImagePath)) {
- $brokenReferences += Add-BrokenReference $relPath ($lineNumber + 1) $imageMatch "[$imageType] Image not found at path: $relativePathInUrl" "Image"
- }
- } else {
- $urlIssues = @()
- if (-not $url.StartsWith('https://github.com/SoftFever/OrcaSlicer/blob/main/')) { $urlIssues += "URL must start with expected prefix" }
- if (-not $url.EndsWith('?raw=true')) { $urlIssues += "URL must end with '?raw=true'" }
- if ($url -match '^https?://(?!github\.com/SoftFever/OrcaSlicer)') { $urlIssues += "External URLs not allowed" }
-
- $issueText = "[$imageType] URL format issues: " + ($urlIssues -join '; ')
- $brokenReferences += Add-BrokenReference $relPath ($lineNumber + 1) $imageMatch $issueText "Image"
- }
- }
- }
- }
- }
-
- # Report results
- $linkErrors = $brokenReferences | Where-Object { $_.Type -eq "Link" }
- $imageErrors = $brokenReferences | Where-Object { $_.Type -eq "Image" }
-
- if ($brokenReferences.Count -gt 0) {
- Write-Host "::error::Documentation validation failed"
-
- # Build error summary for PR comment
- $errorSummary = ""
-
- # Report link errors
- if ($linkErrors) {
- Write-Host "::group::🔗 Link Validation Errors"
- $errorSummary += "## 🔗 Link Validation Errors`n`n"
- $linkErrors | Group-Object SourceFile | ForEach-Object {
- Write-Host "📄 $($_.Name):" -ForegroundColor Yellow
- $errorSummary += "**📄 doc/$($_.Name):**`n"
- $_.Group | Sort-Object Line | ForEach-Object {
- Write-Host " Line $($_.Line): $($_.Target) - $($_.Issue)" -ForegroundColor Red
- Write-Host "::error file=doc/$($_.SourceFile),line=$($_.Line)::$($_.Target) - $($_.Issue)"
- $errorSummary += "- Line $($_.Line): ``$($_.Target)`` - $($_.Issue)`n"
- }
- $errorSummary += "`n"
- }
- Write-Host "::endgroup::"
- }
-
- # Report image errors
- if ($imageErrors) {
- Write-Host "::group::🖼️ Image Validation Errors"
- $errorSummary += "## 🖼️ Image Validation Errors`n`n"
- $imageErrors | Group-Object SourceFile | ForEach-Object {
- Write-Host "📄 $($_.Name):" -ForegroundColor Yellow
- $errorSummary += "**📄 doc/$($_.Name):**`n"
- $_.Group | Sort-Object Line | ForEach-Object {
- Write-Host " Line $($_.Line): $($_.Issue)" -ForegroundColor Red
- Write-Host "::error file=doc/$($_.SourceFile),line=$($_.Line)::$($_.Issue)"
- $errorSummary += "- Line $($_.Line): $($_.Issue)`n"
- }
- $errorSummary += "`n"
- }
- Write-Host "::endgroup::"
- }
-
- # Export error summary for PR comment
- Add-Content -Path $env:GITHUB_ENV -Value "VALIDATION_ERRORS< SLIC3R_DESKTOP_INTEGRATION is always 0, othrewise variable.
-CMAKE_DEPENDENT_OPTION(SLIC3R_DESKTOP_INTEGRATION "Allow perfoming desktop integration during runtime" 1 "NOT SLIC3R_FHS" 0)
+CMAKE_DEPENDENT_OPTION(SLIC3R_DESKTOP_INTEGRATION "Allow performing desktop integration during runtime" 1 "NOT SLIC3R_FHS" 0)
set(OPENVDB_FIND_MODULE_PATH "" CACHE PATH "Path to OpenVDB installation's find modules.")
@@ -340,7 +350,7 @@ if(WIN32)
if (DEFINED ENV{WindowsSdkDir} AND DEFINED ENV{WindowsSDKVersion})
set(WIN10SDK_INCLUDE_PATH "$ENV{WindowsSdkDir}/Include/$ENV{WindowsSDKVersion}")
else ()
- set(WIN10SDK_INCLUDE_PATH "C:/Program Files (x86)/Windows Kits/10/Include/10.0.22000.0")
+ set(WIN10SDK_INCLUDE_PATH "C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0")
endif ()
if (NOT EXISTS "${WIN10SDK_INCLUDE_PATH}/winrt/windows.graphics.printing3d.h")
message("${WIN10SDK_INCLUDE_PATH}/winrt/windows.graphics.printing3d.h was not found")
@@ -565,6 +575,7 @@ endif()
if(POLICY CMP0167)
cmake_policy(SET CMP0167 NEW)
endif()
+set(Boost_NO_SYSTEM_PATHS TRUE)
find_package(Boost 1.83.0 REQUIRED COMPONENTS system filesystem thread log log_setup locale regex chrono atomic date_time iostreams program_options nowide)
add_library(boost_libs INTERFACE)
@@ -682,6 +693,10 @@ find_package(PNG REQUIRED)
set(OpenGL_GL_PREFERENCE "LEGACY")
find_package(OpenGL REQUIRED)
+if(APPLE AND CMAKE_VERSION VERSION_GREATER_EQUAL "4.0")
+ set(OPENGL_LIBRARIES "-framework OpenGL" CACHE STRING "OpenGL framework" FORCE)
+endif()
+
set(GLEW_ROOT "${CMAKE_PREFIX_PATH}")
message("GLEW_ROOT: ${GLEW_ROOT}")
# Find glew or use bundled version
@@ -716,7 +731,7 @@ add_custom_target(gettext_make_pot
)
add_custom_target(gettext_merge_po_with_pot
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
- COMMENT "Merge localization po with new generted pot file"
+ COMMENT "Merge localization po with new generated pot file"
)
file(GLOB BBL_L10N_PO_FILES "${BBL_L18N_DIR}/*/OrcaSlicer*.po")
foreach(po_file ${BBL_L10N_PO_FILES})
@@ -930,7 +945,7 @@ set (CPACK_PACKAGE_VERSION_MINOR "${ORCA_VERSION_MINOR}")
set (CPACK_PACKAGE_VERSION_PATCH "${ORCA_VERSION_PATCH}")
set (CPACK_PACKAGE_FILE_NAME "OrcaSlicer_Windows_Installer_V${SoftFever_VERSION}")
set (CPACK_PACKAGE_DESCRIPTION_SUMMARY "Orca Slicer is an open source slicer for FDM printers")
-set (CPACK_PACKAGE_HOMEPAGE_URL "https://github.com/SoftFever/OrcaSlicer")
+set (CPACK_PACKAGE_HOMEPAGE_URL "https://github.com/OrcaSlicer/OrcaSlicer")
set (CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME})
set (CPACK_PACKAGE_ICON "${CMAKE_SOURCE_DIR}/resources/images\\\\OrcaSlicer.ico")
set (CPACK_NSIS_MUI_ICON "${CPACK_PACKAGE_ICON}")
diff --git a/README.md b/README.md
index 2b9f804853..afd418ea0a 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@
-[](https://github.com/SoftFever/OrcaSlicer/stargazers) [](https://github.com/SoftFever/OrcaSlicer/actions/workflows/build_all.yml)
+[](https://github.com/OrcaSlicer/OrcaSlicer/stargazers) [](https://github.com/OrcaSlicer/OrcaSlicer/actions/workflows/build_all.yml)
OrcaSlicer: an open source Next-Gen Slicing Software for Precision 3D Prints.
Optimize your prints with ultra-fast slicing, intelligent support generation, and seamless printer compatibility—engineered for perfection.
@@ -18,7 +18,7 @@ Optimize your prints with ultra-fast slicing, intelligent support generation, an
OrcaSlicer.com
#### Github Repository:
-
+
#### Follow us:
@@ -44,64 +44,62 @@ If you come across any of these in search results, please report them as
# Main features
-- **[Advanced Calibration Tools](https://github.com/SoftFever/OrcaSlicer/wiki/Calibration)**
+- **[Advanced Calibration Tools](https://www.orcaslicer.com/wiki/Calibration)**
Comprehensive suite: temperature towers, flow rate, retraction & more for optimal performance.
-- **[Precise Wall](https://github.com/SoftFever/OrcaSlicer/wiki/quality_settings_precision#precise-wall) and [Seam Control](https://github.com/SoftFever/OrcaSlicer/wiki/quality_settings_seam)**
+- **[Precise Wall](https://www.orcaslicer.com/wiki/quality_settings_precision#precise-wall) and [Seam Control](https://www.orcaslicer.com/wiki/quality_settings_seam)**
Adjust outer wall spacing and apply scarf seams to enhance print accuracy.
-- **[Sandwich Mode](https://github.com/SoftFever/OrcaSlicer/wiki/quality_settings_wall_and_surfaces#innerouterinner) and [Polyholes](https://github.com/SoftFever/OrcaSlicer/wiki/quality_settings_precision#polyholes) Support**
- Use varied infill [patterns](https://github.com/SoftFever/OrcaSlicer/wiki/strength_settings_patterns) and accurate hole shapes for improved clarity.
-- **[Overhang](https://github.com/SoftFever/OrcaSlicer/wiki/quality_settings_overhangs) and [Support Optimization](https://github.com/SoftFever/OrcaSlicer/wiki#support-settings)**
+- **[Sandwich Mode](https://www.orcaslicer.com/wiki/quality_settings_wall_and_surfaces#innerouterinner) and [Polyholes](https://www.orcaslicer.com/wiki/quality_settings_precision#polyholes) Support**
+ Use varied infill [patterns](https://www.orcaslicer.com/wiki/strength_settings_patterns) and accurate hole shapes for improved clarity.
+- **[Overhang](https://www.orcaslicer.com/wiki/quality_settings_overhangs) and [Support Optimization](https://www.orcaslicer.com/wiki#support-settings)**
Modify geometry for printable overhangs with precise support placement.
-- **[Granular Controls](https://github.com/SoftFever/OrcaSlicer/wiki#process-settings) and Customization**
+- **[Granular Controls and Customization](https://www.orcaslicer.com/wiki#process-settings)**
Fine-tune print speed, layer height, pressure, and temperature with precision.
- **Network Printer Support**
Seamless integration with Klipper, PrusaLink, and OctoPrint for remote control.
-- **[Mouse Ear Brims](https://github.com/SoftFever/OrcaSlicer/wiki/others_settings_brim) & Adaptive Bed Mesh**
+- **[Mouse Ear Brims](https://www.orcaslicer.com/wiki/others_settings_brim) & [Adaptive Bed Mesh](https://www.orcaslicer.com/wiki/printer_basic_information_adaptive_bed_mesh)**
Automatic brims and adaptive mesh calibration ensure consistent adhesion.
- **User-Friendly Interface**
Intuitive drag-and-drop design with pre-made profiles for popular printers.
-- **[Open-Source](https://github.com/SoftFever/OrcaSlicer) & [Community Driven](https://discord.gg/P4VE9UY9gJ)**
+- **[Open-Source](https://github.com/OrcaSlicer/OrcaSlicer) & [Community Driven](https://discord.gg/P4VE9UY9gJ)**
Regular updates fueled by continuous community contributions.
- **Wide Printer Compatibility**
Supports a broad range of printers: Bambu Lab, Prusa, Creality, Voron, and more.
-- Additional features can be found in the [change notes](https://github.com/SoftFever/OrcaSlicer/releases/).
+- Additional features can be found in the [change notes](https://github.com/OrcaSlicer/OrcaSlicer/releases/).
# Wiki
-The wiki below aims to provide a detailed explanation of the slicer settings, including how to maximize their use and how to calibrate and set up your printer.
+The [wiki](https://www.orcaslicer.com/wiki) aims to provide a detailed explanation of the slicer settings, including how to maximize their use and how to calibrate and set up your printer.
-Please note that the wiki is a work in progress. We appreciate your patience as we continue to develop and improve it!
-
-- **[Access the wiki here](https://github.com/SoftFever/OrcaSlicer/wiki)**
-- **[Contribute to the wiki](https://github.com/SoftFever/OrcaSlicer/wiki/How-to-wiki)**
+- **[Access the wiki here](https://www.orcaslicer.com/wiki)**
+- **[Contribute to the wiki](https://www.orcaslicer.com/wiki/How-to-wiki)**
# Download
## Stable Release
-📥 **[Download the Latest Stable Release](https://github.com/SoftFever/OrcaSlicer/releases/latest)**
+📥 **[Download the Latest Stable Release](https://github.com/OrcaSlicer/OrcaSlicer/releases/latest)**
Visit our GitHub Releases page for the latest stable version of OrcaSlicer, recommended for most users.
## Nightly Builds
-🌙 **[Download the Latest Nightly Build](https://github.com/SoftFever/OrcaSlicer/releases/tag/nightly-builds)**
+🌙 **[Download the Latest Nightly Build](https://github.com/OrcaSlicer/OrcaSlicer/releases/tag/nightly-builds)**
Explore the latest developments in OrcaSlicer with our nightly builds. Feedback on these versions is highly appreciated.
# How to install
## Windows
-Download the **Windows Installer exe** for your preferred version from the [releases page](https://github.com/SoftFever/OrcaSlicer/releases).
+Download the **Windows Installer exe** for your preferred version from the [releases page](https://github.com/OrcaSlicer/OrcaSlicer/releases).
- *For convenience there is also a portable build available.*
Troubleshooting
- *If you have troubles to run the build, you might need to install following runtimes:*
- - [MicrosoftEdgeWebView2RuntimeInstallerX64](https://github.com/SoftFever/OrcaSlicer/releases/download/v1.0.10-sf2/MicrosoftEdgeWebView2RuntimeInstallerX64.exe)
+ - [MicrosoftEdgeWebView2RuntimeInstallerX64](https://github.com/OrcaSlicer/OrcaSlicer/releases/download/v1.0.10-sf2/MicrosoftEdgeWebView2RuntimeInstallerX64.exe)
- [Details of this runtime](https://aka.ms/webview2)
- [Alternative Download Link Hosted by Microsoft](https://go.microsoft.com/fwlink/p/?LinkId=2124703)
- - [vcredist2019_x64](https://github.com/SoftFever/OrcaSlicer/releases/download/v1.0.10-sf2/vcredist2019_x64.exe)
+ - [vcredist2019_x64](https://github.com/OrcaSlicer/OrcaSlicer/releases/download/v1.0.10-sf2/vcredist2019_x64.exe)
- [Alternative Download Link Hosted by Microsoft](https://aka.ms/vs/17/release/vc_redist.x64.exe)
- This file may already be available on your computer if you've installed visual studio. Check the following location: `%VCINSTALLDIR%Redist\MSVC\v142`
@@ -146,7 +144,7 @@ winget install --id=SoftFever.OrcaSlicer -e
# How to Compile
-All updated build instructions for Windows, macOS, and Linux are now available on the official [OrcaSlicer Wiki - How to build](https://github.com/SoftFever/OrcaSlicer/wiki/How-to-build) page.
+All updated build instructions for Windows, macOS, and Linux are now available on the official [OrcaSlicer Wiki - How to build](https://www.orcaslicer.com/wiki/How-to-build) page.
Please refer to the wiki to ensure you're following the latest and most accurate steps for your platform.
diff --git a/build_flatpak.sh b/build_flatpak.sh
index 3cdf49b5a4..bdfac22555 100755
--- a/build_flatpak.sh
+++ b/build_flatpak.sh
@@ -186,22 +186,22 @@ echo -e "${GREEN}All required dependencies found${NC}"
# Install runtime and SDK if requested
if [[ "$INSTALL_RUNTIME" == true ]]; then
echo -e "${YELLOW}Installing GNOME runtime and SDK...${NC}"
- flatpak install --user -y flathub org.gnome.Platform//47
- flatpak install --user -y flathub org.gnome.Sdk//47
+ flatpak install --user -y flathub org.gnome.Platform//48
+ flatpak install --user -y flathub org.gnome.Sdk//48
fi
# Check if required runtime is available
-if ! flatpak info --user org.gnome.Platform//47 &> /dev/null; then
- echo -e "${RED}Error: GNOME Platform 47 runtime is not installed.${NC}"
+if ! flatpak info --user org.gnome.Platform//48 &> /dev/null; then
+ echo -e "${RED}Error: GNOME Platform 48 runtime is not installed.${NC}"
echo "Run with -i flag to install it automatically, or install manually:"
- echo "flatpak install --user flathub org.gnome.Platform//47"
+ echo "flatpak install --user flathub org.gnome.Platform//48"
exit 1
fi
-if ! flatpak info --user org.gnome.Sdk//47 &> /dev/null; then
- echo -e "${RED}Error: GNOME SDK 47 is not installed.${NC}"
+if ! flatpak info --user org.gnome.Sdk//48 &> /dev/null; then
+ echo -e "${RED}Error: GNOME SDK 48 is not installed.${NC}"
echo "Run with -i flag to install it automatically, or install manually:"
- echo "flatpak install --user flathub org.gnome.Sdk//47"
+ echo "flatpak install --user flathub org.gnome.Sdk//48"
exit 1
fi
diff --git a/build_linux.sh b/build_linux.sh
index 1f35b464f6..9a9a9160ba 100755
--- a/build_linux.sh
+++ b/build_linux.sh
@@ -27,7 +27,6 @@ function usage() {
echo " -L: use ld.lld as linker (if available)"
echo "For a first use, you want to './${SCRIPT_NAME} -u'"
echo " and then './${SCRIPT_NAME} -dsi'"
- echo "To build with tests: './${SCRIPT_NAME} -st' or './${SCRIPT_NAME} -dst'"
}
SLIC3R_PRECOMPILED_HEADERS="ON"
@@ -102,11 +101,6 @@ if [ ${OPTIND} -eq 1 ] ; then
exit 1
fi
-if [[ -n "${BUILD_TESTS}" ]] && [[ -z "${BUILD_ORCA}" ]] ; then
- echo "-t flag requires -s flag in the same invocation"
- exit 1
-fi
-
function check_available_memory_and_disk() {
FREE_MEM_GB=$(free --gibi --total | grep 'Mem' | rev | cut --delimiter=" " --fields=1 | rev)
MIN_MEM_GB=10
@@ -221,7 +215,7 @@ if [[ -n "${BUILD_DEPS}" ]] ; then
print_and_run cmake --build deps/$BUILD_DIR
fi
-if [[ -n "${BUILD_ORCA}" ]] ; then
+if [[ -n "${BUILD_ORCA}" ]] || [[ -n "${BUILD_TESTS}" ]] ; then
echo "Configuring OrcaSlicer..."
if [[ -n "${CLEAN_BUILD}" ]] ; then
print_and_run rm -fr $BUILD_DIR
@@ -243,11 +237,13 @@ if [[ -n "${BUILD_ORCA}" ]] ; then
"${COLORED_OUTPUT}" \
"${BUILD_ARGS[@]}"
echo "done"
- echo "Building OrcaSlicer ..."
- print_and_run cmake --build $BUILD_DIR --config "${BUILD_CONFIG}" --target OrcaSlicer
- echo "Building OrcaSlicer_profile_validator .."
- print_and_run cmake --build $BUILD_DIR --config "${BUILD_CONFIG}" --target OrcaSlicer_profile_validator
- ./scripts/run_gettext.sh
+ if [[ -n "${BUILD_ORCA}" ]]; then
+ echo "Building OrcaSlicer ..."
+ print_and_run cmake --build $BUILD_DIR --config "${BUILD_CONFIG}" --target OrcaSlicer
+ echo "Building OrcaSlicer_profile_validator .."
+ print_and_run cmake --build $BUILD_DIR --config "${BUILD_CONFIG}" --target OrcaSlicer_profile_validator
+ ./scripts/run_gettext.sh
+ fi
if [[ -n "${BUILD_TESTS}" ]] ; then
echo "Building tests ..."
print_and_run cmake --build ${BUILD_DIR} --config "${BUILD_CONFIG}" --target tests/all
diff --git a/build_release_macos.sh b/build_release_macos.sh
index e42490f1bd..1999c62b92 100755
--- a/build_release_macos.sh
+++ b/build_release_macos.sh
@@ -3,7 +3,7 @@
set -e
set -o pipefail
-while getopts ":dpa:snt:xbc:1h" opt; do
+while getopts ":dpa:snt:xbc:1Th" opt; do
case "${opt}" in
d )
export BUILD_TARGET="deps"
@@ -37,6 +37,9 @@ while getopts ":dpa:snt:xbc:1h" opt; do
1 )
export CMAKE_BUILD_PARALLEL_LEVEL=1
;;
+ T )
+ export BUILD_TESTS="1"
+ ;;
h ) echo "Usage: ./build_release_macos.sh [-d]"
echo " -d: Build deps only"
echo " -a: Set ARCHITECTURE (arm64 or x86_64 or universal)"
@@ -47,6 +50,7 @@ while getopts ":dpa:snt:xbc:1h" opt; do
echo " -b: Build without reconfiguring CMake"
echo " -c: Set CMake build configuration, default is Release"
echo " -1: Use single job for building"
+ echo " -T: Build and run tests"
exit 0
;;
* )
@@ -85,6 +89,15 @@ if [ -z "$OSX_DEPLOYMENT_TARGET" ]; then
export OSX_DEPLOYMENT_TARGET="11.3"
fi
+CMAKE_VERSION=$(cmake --version | head -1 | sed 's/[^0-9]*\([0-9]*\).*/\1/')
+if [ "$CMAKE_VERSION" -ge 4 ] 2>/dev/null; then
+ export CMAKE_POLICY_VERSION_MINIMUM=3.5
+ export CMAKE_POLICY_COMPAT="-DCMAKE_POLICY_VERSION_MINIMUM=3.5"
+ echo "Detected CMake 4.x, adding compatibility flag (env + cmake arg)"
+else
+ export CMAKE_POLICY_COMPAT=""
+fi
+
echo "Build params:"
echo " - ARCH: $ARCH"
echo " - BUILD_CONFIG: $BUILD_CONFIG"
@@ -133,7 +146,8 @@ function build_deps() {
-G "${DEPS_CMAKE_GENERATOR}" \
-DCMAKE_BUILD_TYPE="$BUILD_CONFIG" \
-DCMAKE_OSX_ARCHITECTURES:STRING="${_ARCH}" \
- -DCMAKE_OSX_DEPLOYMENT_TARGET="${OSX_DEPLOYMENT_TARGET}"
+ -DCMAKE_OSX_DEPLOYMENT_TARGET="${OSX_DEPLOYMENT_TARGET}" \
+ ${CMAKE_POLICY_COMPAT}
fi
cmake --build . --config "$BUILD_CONFIG" --target deps
)
@@ -170,13 +184,24 @@ function build_slicer() {
-G "${SLICER_CMAKE_GENERATOR}" \
-DORCA_TOOLS=ON \
${ORCA_UPDATER_SIG_KEY:+-DORCA_UPDATER_SIG_KEY="$ORCA_UPDATER_SIG_KEY"} \
+ ${BUILD_TESTS:+-DBUILD_TESTS=ON} \
-DCMAKE_BUILD_TYPE="$BUILD_CONFIG" \
-DCMAKE_OSX_ARCHITECTURES="${_ARCH}" \
- -DCMAKE_OSX_DEPLOYMENT_TARGET="${OSX_DEPLOYMENT_TARGET}"
+ -DCMAKE_OSX_DEPLOYMENT_TARGET="${OSX_DEPLOYMENT_TARGET}" \
+ ${CMAKE_POLICY_COMPAT}
fi
cmake --build . --config "$BUILD_CONFIG" --target "$SLICER_BUILD_TARGET"
)
+ if [ "1." == "$BUILD_TESTS". ]; then
+ echo "Running tests for $_ARCH..."
+ (
+ set -x
+ cd "$PROJECT_BUILD_DIR"
+ ctest --build-config "$BUILD_CONFIG" --output-on-failure
+ )
+ fi
+
echo "Verify localization with gettext..."
(
cd "$PROJECT_DIR"
diff --git a/build_release_vs.bat b/build_release_vs.bat
new file mode 100644
index 0000000000..d2832450b3
--- /dev/null
+++ b/build_release_vs.bat
@@ -0,0 +1,119 @@
+@REM OrcaSlicer build script for Windows with VS auto-detect
+@echo off
+set WP=%CD%
+
+@REM Detect Visual Studio version using msbuild
+echo Detecting Visual Studio version using msbuild...
+
+@REM Try to get MSBuild version - the output format varies by VS version
+set VS_MAJOR=
+for /f "tokens=*" %%i in ('msbuild -version 2^>^&1 ^| findstr /r "^[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*"') do (
+ for /f "tokens=1 delims=." %%a in ("%%i") do set VS_MAJOR=%%a
+ set MSBUILD_OUTPUT=%%i
+ goto :version_found
+)
+
+@REM Alternative method for newer MSBuild versions
+if "%VS_MAJOR%"=="" (
+ for /f "tokens=*" %%i in ('msbuild -version 2^>^&1 ^| findstr /r "[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*"') do (
+ for /f "tokens=1 delims=." %%a in ("%%i") do set VS_MAJOR=%%a
+ set MSBUILD_OUTPUT=%%i
+ goto :version_found
+ )
+)
+
+:version_found
+echo MSBuild version detected: %MSBUILD_OUTPUT%
+echo Major version: %VS_MAJOR%
+
+if "%VS_MAJOR%"=="" (
+ echo Error: Could not determine Visual Studio version from msbuild
+ echo Please ensure Visual Studio and MSBuild are properly installed
+ exit /b 1
+)
+
+if "%VS_MAJOR%"=="16" (
+ set VS_VERSION=2019
+ set CMAKE_GENERATOR="Visual Studio 16 2019"
+) else if "%VS_MAJOR%"=="17" (
+ set VS_VERSION=2022
+ set CMAKE_GENERATOR="Visual Studio 17 2022"
+) else if "%VS_MAJOR%"=="18" (
+ set VS_VERSION=2026
+ set CMAKE_GENERATOR="Visual Studio 18 2026"
+) else (
+ echo Error: Unsupported Visual Studio version: %VS_MAJOR%
+ echo Supported versions: VS2019 (16.x^), VS2022 (17.x^), VS2026 (18.x^)
+ exit /b 1
+)
+
+echo Detected Visual Studio %VS_VERSION% (version %VS_MAJOR%)
+echo Using CMake generator: %CMAKE_GENERATOR%
+
+@REM Pack deps
+if "%1"=="pack" (
+ setlocal ENABLEDELAYEDEXPANSION
+ cd %WP%/deps/build
+ for /f "tokens=2-4 delims=/ " %%a in ('date /t') do set build_date=%%c%%b%%a
+ echo packing deps: OrcaSlicer_dep_win64_!build_date!_vs!VS_VERSION!.zip
+
+ %WP%/tools/7z.exe a OrcaSlicer_dep_win64_!build_date!_vs!VS_VERSION!.zip OrcaSlicer_dep
+ exit /b 0
+)
+
+set debug=OFF
+set debuginfo=OFF
+if "%1"=="debug" set debug=ON
+if "%2"=="debug" set debug=ON
+if "%1"=="debuginfo" set debuginfo=ON
+if "%2"=="debuginfo" set debuginfo=ON
+if "%debug%"=="ON" (
+ set build_type=Debug
+ set build_dir=build-dbg
+) else (
+ if "%debuginfo%"=="ON" (
+ set build_type=RelWithDebInfo
+ set build_dir=build-dbginfo
+ ) else (
+ set build_type=Release
+ set build_dir=build
+ )
+)
+echo build type set to %build_type%
+
+setlocal DISABLEDELAYEDEXPANSION
+cd deps
+mkdir %build_dir%
+cd %build_dir%
+set "SIG_FLAG="
+if defined ORCA_UPDATER_SIG_KEY set "SIG_FLAG=-DORCA_UPDATER_SIG_KEY=%ORCA_UPDATER_SIG_KEY%"
+
+if "%1"=="slicer" (
+ GOTO :slicer
+)
+echo "building deps.."
+
+echo on
+REM Set minimum CMake policy to avoid <3.5 errors
+set CMAKE_POLICY_VERSION_MINIMUM=3.5
+cmake ../ -G %CMAKE_GENERATOR% -A x64 -DCMAKE_BUILD_TYPE=%build_type%
+cmake --build . --config %build_type% --target deps -- -m
+@echo off
+
+if "%1"=="deps" exit /b 0
+
+:slicer
+echo "building Orca Slicer..."
+cd %WP%
+mkdir %build_dir%
+cd %build_dir%
+
+echo on
+set CMAKE_POLICY_VERSION_MINIMUM=3.5
+cmake .. -G %CMAKE_GENERATOR% -A x64 -DORCA_TOOLS=ON %SIG_FLAG% -DCMAKE_BUILD_TYPE=%build_type%
+cmake --build . --config %build_type% --target ALL_BUILD -- -m
+@echo off
+cd ..
+call scripts/run_gettext.bat
+cd %build_dir%
+cmake --build . --target install --config %build_type%
diff --git a/build_release_vs2022.bat b/build_release_vs2022.bat
index ce4390f621..4a5ae11277 100644
--- a/build_release_vs2022.bat
+++ b/build_release_vs2022.bat
@@ -46,6 +46,8 @@ if "%1"=="slicer" (
echo "building deps.."
echo on
+REM Set minimum CMake policy to avoid <3.5 errors
+set CMAKE_POLICY_VERSION_MINIMUM=3.5
cmake ../ -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=%build_type%
cmake --build . --config %build_type% --target deps -- -m
@echo off
@@ -59,6 +61,7 @@ mkdir %build_dir%
cd %build_dir%
echo on
+set CMAKE_POLICY_VERSION_MINIMUM=3.5
cmake .. -G "Visual Studio 17 2022" -A x64 -DORCA_TOOLS=ON %SIG_FLAG% -DCMAKE_BUILD_TYPE=%build_type%
cmake --build . --config %build_type% --target ALL_BUILD -- -m
@echo off
diff --git a/cmake/modules/Catch2/Catch.cmake b/cmake/modules/Catch2/Catch.cmake
deleted file mode 100644
index 0ffe978dc5..0000000000
--- a/cmake/modules/Catch2/Catch.cmake
+++ /dev/null
@@ -1,175 +0,0 @@
-# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
-# file Copyright.txt or https://cmake.org/licensing for details.
-
-#[=======================================================================[.rst:
-Catch
------
-
-This module defines a function to help use the Catch test framework.
-
-The :command:`catch_discover_tests` discovers tests by asking the compiled test
-executable to enumerate its tests. This does not require CMake to be re-run
-when tests change. However, it may not work in a cross-compiling environment,
-and setting test properties is less convenient.
-
-This command is intended to replace use of :command:`add_test` to register
-tests, and will create a separate CTest test for each Catch test case. Note
-that this is in some cases less efficient, as common set-up and tear-down logic
-cannot be shared by multiple test cases executing in the same instance.
-However, it provides more fine-grained pass/fail information to CTest, which is
-usually considered as more beneficial. By default, the CTest test name is the
-same as the Catch name; see also ``TEST_PREFIX`` and ``TEST_SUFFIX``.
-
-.. command:: catch_discover_tests
-
- Automatically add tests with CTest by querying the compiled test executable
- for available tests::
-
- catch_discover_tests(target
- [TEST_SPEC arg1...]
- [EXTRA_ARGS arg1...]
- [WORKING_DIRECTORY dir]
- [TEST_PREFIX prefix]
- [TEST_SUFFIX suffix]
- [PROPERTIES name1 value1...]
- [TEST_LIST var]
- )
-
- ``catch_discover_tests`` sets up a post-build command on the test executable
- that generates the list of tests by parsing the output from running the test
- with the ``--list-test-names-only`` argument. This ensures that the full
- list of tests is obtained. Since test discovery occurs at build time, it is
- not necessary to re-run CMake when the list of tests changes.
- However, it requires that :prop_tgt:`CROSSCOMPILING_EMULATOR` is properly set
- in order to function in a cross-compiling environment.
-
- Additionally, setting properties on tests is somewhat less convenient, since
- the tests are not available at CMake time. Additional test properties may be
- assigned to the set of tests as a whole using the ``PROPERTIES`` option. If
- more fine-grained test control is needed, custom content may be provided
- through an external CTest script using the :prop_dir:`TEST_INCLUDE_FILES`
- directory property. The set of discovered tests is made accessible to such a
- script via the ``_TESTS`` variable.
-
- The options are:
-
- ``target``
- Specifies the Catch executable, which must be a known CMake executable
- target. CMake will substitute the location of the built executable when
- running the test.
-
- ``TEST_SPEC arg1...``
- Specifies test cases, wildcarded test cases, tags and tag expressions to
- pass to the Catch executable with the ``--list-test-names-only`` argument.
-
- ``EXTRA_ARGS arg1...``
- Any extra arguments to pass on the command line to each test case.
-
- ``WORKING_DIRECTORY dir``
- Specifies the directory in which to run the discovered test cases. If this
- option is not provided, the current binary directory is used.
-
- ``TEST_PREFIX prefix``
- Specifies a ``prefix`` to be prepended to the name of each discovered test
- case. This can be useful when the same test executable is being used in
- multiple calls to ``catch_discover_tests()`` but with different
- ``TEST_SPEC`` or ``EXTRA_ARGS``.
-
- ``TEST_SUFFIX suffix``
- Similar to ``TEST_PREFIX`` except the ``suffix`` is appended to the name of
- every discovered test case. Both ``TEST_PREFIX`` and ``TEST_SUFFIX`` may
- be specified.
-
- ``PROPERTIES name1 value1...``
- Specifies additional properties to be set on all tests discovered by this
- invocation of ``catch_discover_tests``.
-
- ``TEST_LIST var``
- Make the list of tests available in the variable ``var``, rather than the
- default ``_TESTS``. This can be useful when the same test
- executable is being used in multiple calls to ``catch_discover_tests()``.
- Note that this variable is only available in CTest.
-
-#]=======================================================================]
-
-#------------------------------------------------------------------------------
-function(catch_discover_tests TARGET)
- cmake_parse_arguments(
- ""
- ""
- "TEST_PREFIX;TEST_SUFFIX;WORKING_DIRECTORY;TEST_LIST"
- "TEST_SPEC;EXTRA_ARGS;PROPERTIES"
- ${ARGN}
- )
-
- if(NOT _WORKING_DIRECTORY)
- set(_WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
- endif()
- if(NOT _TEST_LIST)
- set(_TEST_LIST ${TARGET}_TESTS)
- endif()
-
- ## Generate a unique name based on the extra arguments
- string(SHA1 args_hash "${_TEST_SPEC} ${_EXTRA_ARGS}")
- string(SUBSTRING ${args_hash} 0 7 args_hash)
-
- # Define rule to generate test list for aforementioned test executable
- set(ctest_include_file "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_include-${args_hash}.cmake")
- set(ctest_tests_file "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_tests-${args_hash}.cmake")
- get_property(crosscompiling_emulator
- TARGET ${TARGET}
- PROPERTY CROSSCOMPILING_EMULATOR
- )
- add_custom_command(
- TARGET ${TARGET} POST_BUILD
- BYPRODUCTS "${ctest_tests_file}"
- COMMAND "${CMAKE_COMMAND}"
- -D "TEST_TARGET=${TARGET}"
- -D "TEST_EXECUTABLE=$"
- -D "TEST_EXECUTOR=${crosscompiling_emulator}"
- -D "TEST_WORKING_DIR=${_WORKING_DIRECTORY}"
- -D "TEST_SPEC=${_TEST_SPEC}"
- -D "TEST_EXTRA_ARGS=${_EXTRA_ARGS}"
- -D "TEST_PROPERTIES=${_PROPERTIES}"
- -D "TEST_PREFIX='${_TEST_PREFIX}'"
- -D "TEST_SUFFIX='${_TEST_SUFFIX}'"
- -D "TEST_LIST=${_TEST_LIST}"
- -D "CTEST_FILE=${ctest_tests_file}"
- -P "${_CATCH_DISCOVER_TESTS_SCRIPT}"
- VERBATIM
- )
-
- file(WRITE "${ctest_include_file}"
- "if(EXISTS \"${ctest_tests_file}\")\n"
- " include(\"${ctest_tests_file}\")\n"
- "else()\n"
- " add_test(${TARGET}_NOT_BUILT-${args_hash} ${TARGET}_NOT_BUILT-${args_hash})\n"
- "endif()\n"
- )
-
- if(NOT ${CMAKE_VERSION} VERSION_LESS "3.10.0")
- # Add discovered tests to directory TEST_INCLUDE_FILES
- set_property(DIRECTORY
- APPEND PROPERTY TEST_INCLUDE_FILES "${ctest_include_file}"
- )
- else()
- # Add discovered tests as directory TEST_INCLUDE_FILE if possible
- get_property(test_include_file_set DIRECTORY PROPERTY TEST_INCLUDE_FILE SET)
- if (NOT ${test_include_file_set})
- set_property(DIRECTORY
- PROPERTY TEST_INCLUDE_FILE "${ctest_include_file}"
- )
- else()
- message(FATAL_ERROR
- "Cannot set more than one TEST_INCLUDE_FILE"
- )
- endif()
- endif()
-
-endfunction()
-
-###############################################################################
-
-set(_CATCH_DISCOVER_TESTS_SCRIPT
- ${CMAKE_CURRENT_LIST_DIR}/CatchAddTests.cmake
-)
diff --git a/cmake/modules/Catch2/CatchAddTests.cmake b/cmake/modules/Catch2/CatchAddTests.cmake
deleted file mode 100644
index ca5ebc17e5..0000000000
--- a/cmake/modules/Catch2/CatchAddTests.cmake
+++ /dev/null
@@ -1,106 +0,0 @@
-# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
-# file Copyright.txt or https://cmake.org/licensing for details.
-
-set(prefix "${TEST_PREFIX}")
-set(suffix "${TEST_SUFFIX}")
-set(spec ${TEST_SPEC})
-set(extra_args ${TEST_EXTRA_ARGS})
-set(properties ${TEST_PROPERTIES})
-set(script)
-set(suite)
-set(tests)
-
-function(add_command NAME)
- set(_args "")
- foreach(_arg ${ARGN})
- if(_arg MATCHES "[^-./:a-zA-Z0-9_]")
- set(_args "${_args} [==[${_arg}]==]") # form a bracket_argument
- else()
- set(_args "${_args} ${_arg}")
- endif()
- endforeach()
- set(script "${script}${NAME}(${_args})\n" PARENT_SCOPE)
-endfunction()
-
-macro(_add_catch_test_labels LINE)
- # convert to list of tags
- string(REPLACE "][" "]\\;[" tags ${line})
-
- add_command(
- set_tests_properties "${prefix}${test}${suffix}"
- PROPERTIES
- LABELS "${tags}"
- )
-endmacro()
-
-macro(_add_catch_test LINE)
- set(test ${line})
- # use escape commas to handle properly test cases with commans inside the name
- string(REPLACE "," "\\," test_name ${test})
- # ...and add to script
- add_command(
- add_test "${prefix}${test}${suffix}"
- ${TEST_EXECUTOR}
- "${TEST_EXECUTABLE}"
- "${test_name}"
- ${extra_args}
- )
-
- add_command(
- set_tests_properties "${prefix}${test}${suffix}"
- PROPERTIES
- WORKING_DIRECTORY "${TEST_WORKING_DIR}"
- ${properties}
- )
- list(APPEND tests "${prefix}${test}${suffix}")
-endmacro()
-
-# Run test executable to get list of available tests
-if(NOT EXISTS "${TEST_EXECUTABLE}")
- message(FATAL_ERROR
- "Specified test executable '${TEST_EXECUTABLE}' does not exist"
- )
-endif()
-execute_process(
- COMMAND ${TEST_EXECUTOR} "${TEST_EXECUTABLE}" ${spec} --list-tests
- OUTPUT_VARIABLE output
- RESULT_VARIABLE result
-)
-# Catch --list-test-names-only reports the number of tests, so 0 is... surprising
-if(${result} EQUAL 0)
- message(WARNING
- "Test executable '${TEST_EXECUTABLE}' contains no tests!\n"
- )
-elseif(${result} LESS 0)
- message(FATAL_ERROR
- "Error running test executable '${TEST_EXECUTABLE}':\n"
- " Result: ${result}\n"
- " Output: ${output}\n"
- )
-endif()
-
-string(REPLACE "\n" ";" output "${output}")
-set(test)
-set(tags_regex "(\\[([^\\[]*)\\])+$")
-
-# Parse output
-foreach(line ${output})
- # lines without leading whitespaces are catch output not tests
- if(${line} MATCHES "^[ \t]+")
- # strip leading spaces and tabs
- string(REGEX REPLACE "^[ \t]+" "" line ${line})
-
- if(${line} MATCHES "${tags_regex}")
- _add_catch_test_labels(${line})
- else()
- _add_catch_test(${line})
- endif()
- endif()
-endforeach()
-
-# Create a list of all discovered tests, which users may use to e.g. set
-# properties on the tests
-add_command(set ${TEST_LIST} ${tests})
-
-# Write CTest script
-file(WRITE "${CTEST_FILE}" "${script}")
diff --git a/cmake/modules/FindGLEW.cmake b/cmake/modules/FindGLEW.cmake
index 56661ffd33..93e8ed89bf 100644
--- a/cmake/modules/FindGLEW.cmake
+++ b/cmake/modules/FindGLEW.cmake
@@ -3,7 +3,7 @@
# PrusaSlicer specifics:
# This file is backported from CMake 3.15 distribution to behave uniformly
-# across all versions of CMake. It explicitly adds GLEW_STATIC complile
+# across all versions of CMake. It explicitly adds GLEW_STATIC compile
# definition to static targets which is needed to prevent link errors.
#[=======================================================================[.rst:
@@ -223,8 +223,13 @@ if(NOT TARGET GLEW::glew AND NOT GLEW_USE_STATIC_LIBS)
PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${GLEW_INCLUDE_DIRS}")
if(APPLE)
- set_target_properties(GLEW::glew
- PROPERTIES INTERFACE_LINK_LIBRARIES OpenGL::GL)
+ if(CMAKE_VERSION VERSION_GREATER_EQUAL "4.0")
+ set_target_properties(GLEW::glew
+ PROPERTIES INTERFACE_LINK_LIBRARIES "-framework OpenGL")
+ else()
+ set_target_properties(GLEW::glew
+ PROPERTIES INTERFACE_LINK_LIBRARIES OpenGL::GL)
+ endif()
endif()
if(GLEW_SHARED_LIBRARY_RELEASE)
@@ -258,8 +263,13 @@ elseif(NOT TARGET GLEW::glew_s AND GLEW_USE_STATIC_LIBS)
set_target_properties(GLEW::glew_s PROPERTIES INTERFACE_COMPILE_DEFINITIONS GLEW_STATIC)
if(APPLE)
- set_target_properties(GLEW::glew_s
- PROPERTIES INTERFACE_LINK_LIBRARIES OpenGL::GL)
+ if(CMAKE_VERSION VERSION_GREATER_EQUAL "4.0")
+ set_target_properties(GLEW::glew_s
+ PROPERTIES INTERFACE_LINK_LIBRARIES "-framework OpenGL")
+ else()
+ set_target_properties(GLEW::glew_s
+ PROPERTIES INTERFACE_LINK_LIBRARIES OpenGL::GL)
+ endif()
endif()
if(GLEW_STATIC_LIBRARY_RELEASE)
@@ -292,8 +302,13 @@ if(NOT TARGET GLEW::GLEW)
PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${GLEW_INCLUDE_DIRS}")
if(APPLE)
- set_target_properties(GLEW::GLEW
- PROPERTIES INTERFACE_LINK_LIBRARIES OpenGL::GL)
+ if(CMAKE_VERSION VERSION_GREATER_EQUAL "4.0")
+ set_target_properties(GLEW::GLEW
+ PROPERTIES INTERFACE_LINK_LIBRARIES "-framework OpenGL")
+ else()
+ set_target_properties(GLEW::GLEW
+ PROPERTIES INTERFACE_LINK_LIBRARIES OpenGL::GL)
+ endif()
endif()
if(TARGET GLEW::glew)
diff --git a/cmake/modules/FindTBB.cmake.in b/cmake/modules/FindTBB.cmake.in
index 49e405c184..fde8ca51fb 100644
--- a/cmake/modules/FindTBB.cmake.in
+++ b/cmake/modules/FindTBB.cmake.in
@@ -61,7 +61,7 @@
#
# * TBB_FOUND - Set to false, or undefined, if we haven’t found, or
# don’t want to use TBB.
-# * TBB__FOUND - If False, optional part of TBB sytem is
+# * TBB__FOUND - If False, optional part of TBB system is
# not available.
# * TBB_VERSION - The full version string
# * TBB_VERSION_MAJOR - The major version
@@ -77,7 +77,7 @@
# tbbmalloc, tbbmalloc_debug, tbb_preview, or
# tbb_preview_debug.
#
-# The following varibles should be used to build and link with TBB:
+# The following variables should be used to build and link with TBB:
#
# * TBB_INCLUDE_DIRS - The include directory for TBB.
# * TBB_LIBRARIES - The libraries to link against to use TBB.
diff --git a/cmake/modules/MacOSXBundleInfo.plist.in b/cmake/modules/MacOSXBundleInfo.plist.in
index 2f010c8a82..15979c4822 100644
--- a/cmake/modules/MacOSXBundleInfo.plist.in
+++ b/cmake/modules/MacOSXBundleInfo.plist.in
@@ -133,7 +133,7 @@
${MACOSX_BUNDLE_COPYRIGHT}
NSAppTransportSecurity
-
+
NSAllowsArbitraryLoads
NSAllowsArbitraryLoadsInWebContent
diff --git a/deps/CGAL/0001-clang19.patch b/deps/CGAL/0001-clang19.patch
deleted file mode 100644
index 92a0293735..0000000000
--- a/deps/CGAL/0001-clang19.patch
+++ /dev/null
@@ -1,59 +0,0 @@
---- a/BGL/include/CGAL/boost/graph/iterator.h 2022-10-07 19:04:41 UTC
-+++ b/BGL/include/CGAL/boost/graph/iterator.h
-@@ -213,18 +213,7 @@ class Halfedge_around_source_iterator { (public)
- {}
-
- #ifndef DOXYGEN_RUNNING
-- // design patter: "safe bool"
-- // will be replaced by explicit operator bool with C++11
-- typedef void (Halfedge_around_source_iterator::*bool_type)() const;
-
-- void this_type_does_not_support_comparisons() const {}
--
-- operator bool_type() const
-- {
-- return (! (this->base() == nullptr)) ?
-- &Halfedge_around_source_iterator::this_type_does_not_support_comparisons : 0;
-- }
--
- bool operator==( const Self& i) const {
- CGAL_assertion( anchor == anchor);
- return ( g == i.g) && ( pos == i.pos) && ( winding == i.winding);
-@@ -313,18 +302,7 @@ class Halfedge_around_target_iterator { (public)
- {}
-
- #ifndef DOXYGEN_RUNNING
-- // design patter: "safe bool"
-- // will be replaced by explicit operator bool with C++11
-- typedef void (Halfedge_around_target_iterator::*bool_type)() const;
-
-- void this_type_does_not_support_comparisons() const {}
--
-- operator bool_type() const
-- {
-- return (! (this->base() == nullptr)) ?
-- &Halfedge_around_target_iterator::this_type_does_not_support_comparisons : 0;
-- }
--
- bool operator==( const Self& i) const {
- CGAL_assertion( anchor == anchor);
- return ( g == i.g) && ( pos == i.pos) && ( winding == i.winding);
-@@ -411,18 +389,6 @@ class Halfedge_around_face_iterator { (public)
- const value_type& operator * ( ) const { return pos; }
- pointer operator -> ( ) { return &pos; }
- const value_type* operator -> ( ) const { return &pos; }
--
-- // design patter: "safe bool"
-- // will be replaced by explicit operator bool with C++11
-- typedef void (Halfedge_around_face_iterator::*bool_type)() const;
--
-- void this_type_does_not_support_comparisons() const {}
--
-- operator bool_type() const
-- {
-- return (! (this->base() == nullptr)) ?
-- &Halfedge_around_face_iterator::this_type_does_not_support_comparisons : 0;
-- }
-
- bool operator==( const Self& i) const {
- CGAL_assertion( anchor == anchor);
diff --git a/deps/CGAL/CGAL.cmake b/deps/CGAL/CGAL.cmake
index 73eee6701b..ec77e0ebae 100644
--- a/deps/CGAL/CGAL.cmake
+++ b/deps/CGAL/CGAL.cmake
@@ -5,11 +5,10 @@ endif ()
orcaslicer_add_cmake_project(
CGAL
# GIT_REPOSITORY https://github.com/CGAL/cgal.git
- # GIT_TAG bec70a6d52d8aacb0b3d82a7b4edc3caa899184b # releases/CGAL-5.0
+ # GIT_TAG 3654f780ae0c64675cabaef0e5ddaf904c48b4b7 # releases/CGAL-5.6.3
# For whatever reason, this keeps downloading forever (repeats downloads if finished)
- URL https://github.com/CGAL/cgal/archive/refs/tags/v5.4.zip
- URL_HASH SHA256=d7605e0a5a5ca17da7547592f6f6e4a59430a0bc861948974254d0de43eab4c0
- PATCH_COMMAND git apply ${CGAL_DIRECTORY_FLAG} --verbose --ignore-space-change --whitespace=fix ${CMAKE_CURRENT_LIST_DIR}/0001-clang19.patch
+ URL https://github.com/CGAL/cgal/releases/download/v5.6.3/CGAL-5.6.3.zip
+ URL_HASH SHA256=5d577acb4a9918ccb960491482da7a3838f8d363aff47e14d703f19fd84733d4
DEPENDS dep_Boost dep_GMP dep_MPFR
)
diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt
index 633ebe2a37..492696a58a 100644
--- a/deps/CMakeLists.txt
+++ b/deps/CMakeLists.txt
@@ -1,3 +1,7 @@
+if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "4.0")
+ set(CMAKE_POLICY_VERSION_MINIMUM 3.5 CACHE STRING "" FORCE)
+endif()
+
#
# This CMake project downloads, configures and builds OrcaSlicer dependencies on Unix and Windows.
#
@@ -16,8 +20,8 @@
# On Windows, architecture (64 vs 32 bits) is judged based on the compiler variant.
# To build dependencies for either 64 or 32 bit OS, use the respective compiler command line.
#
-# WARNING: On UNIX platforms wxWidgets hardcode the destdir path into its `wx-conffig` utility,
-# therefore, unfortunatelly, the installation cannot be copied/moved elsewhere without re-installing wxWidgets.
+# WARNING: On UNIX platforms wxWidgets hardcode the destdir path into its `wx-config` utility,
+# therefore, unfortunately, the installation cannot be copied/moved elsewhere without re-installing wxWidgets.
#
cmake_minimum_required(VERSION 3.2)
@@ -177,6 +181,7 @@ if (NOT IS_CROSS_COMPILE OR NOT APPLE)
DOWNLOAD_DIR ${DEP_DOWNLOAD_DIR}/${projectname}
${_gen}
CMAKE_ARGS
+ -DCMAKE_POLICY_VERSION_MINIMUM=3.5
-DCMAKE_INSTALL_PREFIX:STRING=${DESTDIR}
-DCMAKE_MODULE_PATH:STRING=${PROJECT_SOURCE_DIR}/../cmake/modules
-DCMAKE_PREFIX_PATH:STRING=${DESTDIR}
@@ -221,6 +226,7 @@ else()
DOWNLOAD_DIR ${DEP_DOWNLOAD_DIR}/${projectname}
${_gen}
CMAKE_ARGS
+ -DCMAKE_POLICY_VERSION_MINIMUM=3.5
-DCMAKE_INSTALL_PREFIX:STRING=${DESTDIR}
-DCMAKE_PREFIX_PATH:STRING=${DESTDIR}
-DBUILD_SHARED_LIBS:BOOL=OFF
diff --git a/deps/MPFR/MPFR.cmake b/deps/MPFR/MPFR.cmake
index dc45aad7b8..67758a8596 100644
--- a/deps/MPFR/MPFR.cmake
+++ b/deps/MPFR/MPFR.cmake
@@ -25,7 +25,8 @@ else ()
endif ()
ExternalProject_Add(dep_MPFR
- URL https://www.mpfr.org/mpfr-4.2.2/mpfr-4.2.2.tar.bz2
+ URL https://ftp.gnu.org/gnu/mpfr/mpfr-4.2.2.tar.bz2
+ https://www.mpfr.org/mpfr-4.2.2/mpfr-4.2.2.tar.bz2
URL_HASH SHA256=9ad62c7dc910303cd384ff8f1f4767a655124980bb6d8650fe62c815a231bb7b
DOWNLOAD_DIR ${DEP_DOWNLOAD_DIR}/MPFR
BUILD_IN_SOURCE ON
diff --git a/deps/OpenCV/0001-vs2022.patch b/deps/OpenCV/0001-vs.patch
similarity index 51%
rename from deps/OpenCV/0001-vs2022.patch
rename to deps/OpenCV/0001-vs.patch
index 6e5aba84e8..5e6ac7785b 100644
--- a/deps/OpenCV/0001-vs2022.patch
+++ b/deps/OpenCV/0001-vs.patch
@@ -1,15 +1,21 @@
-From 6fb3f6333150a777e835fc7c48e49750591bf7fe Mon Sep 17 00:00:00 2001
-From: Benjamin Buch
-Date: Thu, 23 May 2024 16:05:19 +0200
-Subject: [PATCH] Support VS 2022 17.1x.y
-
-With 17.10.0 the MSVC toolset was set to 19.40.x which breaks the compatibility test in the OpenCV's CMake Config files.
----
- cmake/templates/OpenCVConfig.root-WIN32.cmake.in | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
+diff --git a/cmake/OpenCVDetectCXXCompiler.cmake b/cmake/OpenCVDetectCXXCompiler.cmake
+index 7f229cde96..d8e20f8fe9 100644
+--- a/cmake/OpenCVDetectCXXCompiler.cmake
++++ b/cmake/OpenCVDetectCXXCompiler.cmake
+@@ -171,8 +171,10 @@ elseif(MSVC)
+ set(OpenCV_RUNTIME vc15)
+ elseif(MSVC_VERSION MATCHES "^192[0-9]$")
+ set(OpenCV_RUNTIME vc16)
+- elseif(MSVC_VERSION MATCHES "^193[0-9]$")
++ elseif(MSVC_VERSION MATCHES "^19[34][0-9]$")
+ set(OpenCV_RUNTIME vc17)
++ elseif(MSVC_VERSION MATCHES "^195[0-9]$")
++ set(OpenCV_RUNTIME vc18)
+ else()
+ message(WARNING "OpenCV does not recognize MSVC_VERSION \"${MSVC_VERSION}\". Cannot set OpenCV_RUNTIME")
+ endif()
diff --git a/cmake/templates/OpenCVConfig.root-WIN32.cmake.in b/cmake/templates/OpenCVConfig.root-WIN32.cmake.in
-index b0f254ebe8..62e36272f3 100644
+index b0f254ebe8..8f0178b0ae 100644
--- a/cmake/templates/OpenCVConfig.root-WIN32.cmake.in
+++ b/cmake/templates/OpenCVConfig.root-WIN32.cmake.in
@@ -137,7 +137,7 @@ elseif(MSVC)
@@ -21,32 +27,28 @@ index b0f254ebe8..62e36272f3 100644
set(OpenCV_RUNTIME vc17)
check_one_config(has_VS2022)
if(NOT has_VS2022)
---
-2.45.2.windows.1
-
-From f85818ba6f9031c450475a7453dee0acce31a881 Mon Sep 17 00:00:00 2001
-From: Benjamin Buch
-Date: Fri, 24 May 2024 11:10:09 +0200
-Subject: [PATCH] Support VS 2022 17.1x.y in OpenCVDetectCXXCompiler.cmake
-
-With 17.10.0 the MSVC toolset was set to 19.40.x which breaks the compatibility test in the OpenCV's CMake Config files.
----
- cmake/OpenCVDetectCXXCompiler.cmake | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/cmake/OpenCVDetectCXXCompiler.cmake b/cmake/OpenCVDetectCXXCompiler.cmake
-index 1743aca11f..448afd46ea 100644
---- a/cmake/OpenCVDetectCXXCompiler.cmake
-+++ b/cmake/OpenCVDetectCXXCompiler.cmake
-@@ -176,7 +176,7 @@ elseif(MSVC)
- set(OpenCV_RUNTIME vc15)
- elseif(MSVC_VERSION MATCHES "^192[0-9]$")
- set(OpenCV_RUNTIME vc16)
-- elseif(MSVC_VERSION MATCHES "^193[0-9]$")
-+ elseif(MSVC_VERSION MATCHES "^19[34][0-9]$")
- set(OpenCV_RUNTIME vc17)
- else()
- message(WARNING "OpenCV does not recognize MSVC_VERSION \"${MSVC_VERSION}\". Cannot set OpenCV_RUNTIME")
---
-2.45.2.windows.1
-
+@@ -151,6 +151,24 @@ elseif(MSVC)
+ endif()
+ endif()
+ endif()
++ elseif(MSVC_VERSION MATCHES "^195[0-9]$")
++ set(OpenCV_RUNTIME vc18)
++ check_one_config(has_VS2026)
++ if(NOT has_VS2026)
++ set(OpenCV_RUNTIME vc17)
++ check_one_config(has_VS2022)
++ if(NOT has_VS2022)
++ set(OpenCV_RUNTIME vc16)
++ check_one_config(has_VS2019)
++ if(NOT has_VS2019)
++ set(OpenCV_RUNTIME vc15) # selecting previous compatible runtime version
++ check_one_config(has_VS2017)
++ if(NOT has_VS2017)
++ set(OpenCV_RUNTIME vc14) # selecting previous compatible runtime version
++ endif()
++ endif()
++ endif()
++ endif()
+ endif()
+ elseif(MINGW)
+ set(OpenCV_RUNTIME mingw)
diff --git a/deps/OpenCV/OpenCV.cmake b/deps/OpenCV/OpenCV.cmake
index d9be1b7f50..ad8c0a3585 100644
--- a/deps/OpenCV/OpenCV.cmake
+++ b/deps/OpenCV/OpenCV.cmake
@@ -11,7 +11,7 @@ endif ()
orcaslicer_add_cmake_project(OpenCV
URL https://github.com/opencv/opencv/archive/refs/tags/4.6.0.tar.gz
URL_HASH SHA256=1ec1cba65f9f20fe5a41fda1586e01c70ea0c9a6d7b67c9e13edf0cfe2239277
- PATCH_COMMAND git apply ${OpenCV_DIRECTORY_FLAG} --verbose --ignore-space-change --whitespace=fix ${CMAKE_CURRENT_LIST_DIR}/0001-vs2022.patch ${CMAKE_CURRENT_LIST_DIR}/0002-clang19-macos.patch
+ PATCH_COMMAND git apply ${OpenCV_DIRECTORY_FLAG} --verbose --ignore-space-change --whitespace=fix ${CMAKE_CURRENT_LIST_DIR}/0001-vs.patch ${CMAKE_CURRENT_LIST_DIR}/0002-clang19-macos.patch
CMAKE_ARGS
-DBUILD_SHARED_LIBS=0
-DBUILD_PERE_TESTS=OFF
diff --git a/deps/Qhull/Qhull.cmake b/deps/Qhull/Qhull.cmake
index 9376700428..97667021c0 100644
--- a/deps/Qhull/Qhull.cmake
+++ b/deps/Qhull/Qhull.cmake
@@ -1,11 +1,11 @@
include(GNUInstallDirs)
orcaslicer_add_cmake_project(Qhull
- URL "https://github.com/qhull/qhull/archive/v8.0.1.zip"
- URL_HASH SHA256=5287f5edd6a0372588f5d6640799086a4033d89d19711023ef8229dd9301d69b
+ URL "https://github.com/qhull/qhull/archive/v8.0.2.zip"
+ URL_HASH SHA256=a378e9a39e718e289102c20d45632f873bfdc58a7a5f924246ea4b176e185f1e
CMAKE_ARGS
-DINCLUDE_INSTALL_DIR=${CMAKE_INSTALL_INCLUDEDIR}
)
if (MSVC)
add_debug_dep(dep_Qhull)
-endif ()
\ No newline at end of file
+endif ()
diff --git a/deps/deps-windows.cmake b/deps/deps-windows.cmake
index 5b47c68ce1..cd4dbd150f 100644
--- a/deps/deps-windows.cmake
+++ b/deps/deps-windows.cmake
@@ -19,6 +19,10 @@ elseif (MSVC_VERSION LESS 1950)
# 1930-1949 = VS 17.0 (v143 toolset)
set(DEP_VS_VER "17")
set(DEP_BOOST_TOOLSET "msvc-14.3")
+elseif (MSVC_VERSION LESS 1960)
+# 1950-1959 = VS 18.0 (v145 toolset)
+ set(DEP_VS_VER "18")
+ set(DEP_BOOST_TOOLSET "msvc-14.5")
else ()
message(FATAL_ERROR "Unsupported MSVC version")
endif ()
diff --git a/deps/wxWidgets/wxWidgets.cmake b/deps/wxWidgets/wxWidgets.cmake
index e45979fb42..3a52d14198 100644
--- a/deps/wxWidgets/wxWidgets.cmake
+++ b/deps/wxWidgets/wxWidgets.cmake
@@ -24,6 +24,14 @@ else ()
set(_wx_edge "-DwxUSE_WEBVIEW_EDGE=OFF")
endif ()
+set(_wx_opengl_override "")
+if(APPLE AND CMAKE_VERSION VERSION_GREATER_EQUAL "4.0")
+ set(_wx_opengl_override
+ -DOPENGL_gl_LIBRARY="-framework OpenGL"
+ -DOPENGL_glu_LIBRARY="-framework OpenGL"
+ )
+endif()
+
orcaslicer_add_cmake_project(
wxWidgets
GIT_REPOSITORY "https://github.com/SoftFever/Orca-deps-wxWidgets"
@@ -31,6 +39,7 @@ orcaslicer_add_cmake_project(
DEPENDS ${PNG_PKG} ${ZLIB_PKG} ${EXPAT_PKG} ${JPEG_PKG}
${_wx_flatpak_patch}
CMAKE_ARGS
+ ${_wx_opengl_override}
-DwxBUILD_PRECOMP=ON
${_wx_toolkit}
"-DCMAKE_DEBUG_POSTFIX:STRING=${_wx_debug_postfix}"
diff --git a/deps_src/CMakeLists.txt b/deps_src/CMakeLists.txt
index 5c4e62b99f..390cffad30 100644
--- a/deps_src/CMakeLists.txt
+++ b/deps_src/CMakeLists.txt
@@ -10,13 +10,13 @@ add_subdirectory(earcut)
add_subdirectory(fast_float)
add_subdirectory(nanosvg)
add_subdirectory(nlohmann)
-add_subdirectory(spline) # Header-only spline library
add_subdirectory(stb_dxt) # Header-only STB DXT compression library
# Static libraries
add_subdirectory(Shiny)
add_subdirectory(admesh)
add_subdirectory(clipper)
+add_subdirectory(clipper2)
add_subdirectory(expat)
add_subdirectory(glu-libtess)
add_subdirectory(hidapi)
diff --git a/deps_src/README_CMAKE_INTERFACES.md b/deps_src/README_CMAKE_INTERFACES.md
index 78a806fc0b..6ab88c63af 100644
--- a/deps_src/README_CMAKE_INTERFACES.md
+++ b/deps_src/README_CMAKE_INTERFACES.md
@@ -24,18 +24,7 @@ target_link_libraries(your_target PRIVATE semver::semver)
target_link_libraries(your_target PRIVATE hints)
```
-### 3. **spline** (Interface Library)
-- **Type**: Interface library (header-only)
-- **Target**: `spline` or `spline::spline`
-- **Headers**: `spline.h`
-- **Usage**:
-```cmake
-target_link_libraries(your_target PRIVATE spline)
-# or
-target_link_libraries(your_target PRIVATE spline::spline)
-```
-
-### 4. **stb_dxt** (Interface Library)
+### 3. **stb_dxt** (Interface Library)
- **Type**: Interface library (header-only)
- **Target**: `stb_dxt` or `stb_dxt::stb_dxt`
- **Headers**: `stb_dxt.h`
@@ -53,10 +42,9 @@ target_link_libraries(your_target PRIVATE stb_dxt::stb_dxt)
1. **In your CMakeLists.txt**, simply link the library:
```cmake
add_executable(my_app main.cpp)
-target_link_libraries(my_app
- PRIVATE
+target_link_libraries(my_app
+ PRIVATE
semver::semver # For version parsing
- spline::spline # For spline interpolation
stb_dxt::stb_dxt # For DXT texture compression
hints # For hints functionality
)
@@ -67,9 +55,6 @@ target_link_libraries(my_app
// For semver
#include
-// For spline
-#include
-
// For stb_dxt
#include
@@ -100,7 +85,6 @@ target_link_libraries(mycomponent
PUBLIC
semver::semver # Version handling is part of public API
PRIVATE
- spline::spline # Used internally for interpolation
stb_dxt::stb_dxt # Used internally for texture compression
)
diff --git a/deps_src/clipper2/CMakeLists.txt b/deps_src/clipper2/CMakeLists.txt
new file mode 100644
index 0000000000..c604002da7
--- /dev/null
+++ b/deps_src/clipper2/CMakeLists.txt
@@ -0,0 +1,54 @@
+cmake_minimum_required(VERSION 3.10)
+project(Clipper2 VERSION 1.5.2 LANGUAGES C CXX)
+
+set(CMAKE_POSITION_INDEPENDENT_CODE ON)
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_CXX_EXTENSIONS OFF)
+set_property(GLOBAL PROPERTY USE_FOLDERS OFF)
+
+option(BUILD_SHARED_LIBS "Build shared libs" OFF)
+
+include(GNUInstallDirs)
+
+set(CLIPPER2_INC
+ Clipper2Lib/include/clipper2/clipper.h
+ Clipper2Lib/include/clipper2/clipper.core.h
+ Clipper2Lib/include/clipper2/clipper.engine.h
+ Clipper2Lib/include/clipper2/clipper.export.h
+ Clipper2Lib/include/clipper2/clipper.minkowski.h
+ Clipper2Lib/include/clipper2/clipper.offset.h
+ Clipper2Lib/include/clipper2/clipper.rectclip.h
+ Clipper2Lib/include/clipper2/clipper2_z.hpp
+)
+
+set(CLIPPER2_SRC
+ Clipper2Lib/src/clipper.engine.cpp
+ Clipper2Lib/src/clipper.offset.cpp
+ Clipper2Lib/src/clipper.rectclip.cpp
+ Clipper2Lib/src/clipper2_z.cpp
+)
+
+# 2d version of Clipper2
+add_library(Clipper2 ${CLIPPER2_INC} ${CLIPPER2_SRC})
+
+target_include_directories(Clipper2
+ PUBLIC Clipper2Lib/include
+)
+
+if (WIN32)
+ target_compile_options(Clipper2 PRIVATE /W4 /WX)
+else()
+ target_compile_options(Clipper2 PRIVATE -Wall -Wextra -Wpedantic -Werror)
+ target_link_libraries(Clipper2 PUBLIC -lm)
+ if (CMAKE_COMPILER_IS_GNUCC AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 14.1)
+ target_compile_options(Clipper2 PRIVATE -Wno-error=template-id-cdtor)
+ endif()
+endif()
+
+set_target_properties(Clipper2 PROPERTIES FOLDER Libraries
+ VERSION ${PROJECT_VERSION}
+ SOVERSION ${PROJECT_VERSION_MAJOR}
+ PUBLIC_HEADER "${CLIPPER2_INC}"
+)
+
diff --git a/deps_src/clipper2/Clipper2Lib/include/clipper2/clipper.core.h b/deps_src/clipper2/Clipper2Lib/include/clipper2/clipper.core.h
new file mode 100644
index 0000000000..6d00f8fa07
--- /dev/null
+++ b/deps_src/clipper2/Clipper2Lib/include/clipper2/clipper.core.h
@@ -0,0 +1,1080 @@
+/*******************************************************************************
+* Author : Angus Johnson *
+* Date : 12 May 2024 *
+* Website : https://www.angusj.com *
+* Copyright : Angus Johnson 2010-2024 *
+* Purpose : Core Clipper Library structures and functions *
+* License : https://www.boost.org/LICENSE_1_0.txt *
+*******************************************************************************/
+
+#ifndef CLIPPER_CORE_H
+#define CLIPPER_CORE_H
+
+#include "clipper2/clipper.version.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifdef USINGZ
+namespace Clipper2Lib_Z {
+#else
+namespace Clipper2Lib {
+#endif
+
+#if (defined(__cpp_exceptions) && __cpp_exceptions) || (defined(__EXCEPTIONS) && __EXCEPTIONS)
+
+ class Clipper2Exception : public std::exception {
+ public:
+ explicit Clipper2Exception(const char* description) :
+ m_descr(description) {}
+ virtual const char* what() const noexcept override { return m_descr.c_str(); }
+ private:
+ std::string m_descr;
+ };
+
+ static const char* precision_error =
+ "Precision exceeds the permitted range";
+ static const char* range_error =
+ "Values exceed permitted range";
+ static const char* scale_error =
+ "Invalid scale (either 0 or too large)";
+ static const char* non_pair_error =
+ "There must be 2 values for each coordinate";
+ static const char* undefined_error =
+ "There is an undefined error in Clipper2";
+#endif
+
+ // error codes (2^n)
+ const int precision_error_i = 1; // non-fatal
+ const int scale_error_i = 2; // non-fatal
+ const int non_pair_error_i = 4; // non-fatal
+ const int undefined_error_i = 32; // fatal
+ const int range_error_i = 64;
+
+#ifndef PI
+ static const double PI = 3.141592653589793238;
+#endif
+
+#ifdef CLIPPER2_MAX_DECIMAL_PRECISION
+ const int CLIPPER2_MAX_DEC_PRECISION = CLIPPER2_MAX_DECIMAL_PRECISION;
+#else
+ const int CLIPPER2_MAX_DEC_PRECISION = 8; // see Discussions #564
+#endif
+
+ static const int64_t MAX_COORD = INT64_MAX >> 2;
+ static const int64_t MIN_COORD = -MAX_COORD;
+ static const int64_t INVALID = INT64_MAX;
+ const double max_coord = static_cast(MAX_COORD);
+ const double min_coord = static_cast(MIN_COORD);
+
+ static const double MAX_DBL = (std::numeric_limits::max)();
+
+ static void DoError([[maybe_unused]] int error_code)
+ {
+#if (defined(__cpp_exceptions) && __cpp_exceptions) || (defined(__EXCEPTIONS) && __EXCEPTIONS)
+ switch (error_code)
+ {
+ case precision_error_i:
+ throw Clipper2Exception(precision_error);
+ case scale_error_i:
+ throw Clipper2Exception(scale_error);
+ case non_pair_error_i:
+ throw Clipper2Exception(non_pair_error);
+ case undefined_error_i:
+ throw Clipper2Exception(undefined_error);
+ case range_error_i:
+ throw Clipper2Exception(range_error);
+ // Should never happen, but adding this to stop a compiler warning
+ default:
+ throw Clipper2Exception("Unknown error");
+ }
+#else
+ ++error_code; // only to stop compiler warning
+#endif
+ }
+
+ // can we call std::round on T? (default false) (#824)
+ template
+ struct is_round_invocable : std::false_type {};
+
+ template
+ struct is_round_invocable()))>> : std::true_type {};
+
+
+ //By far the most widely used filling rules for polygons are EvenOdd
+ //and NonZero, sometimes called Alternate and Winding respectively.
+ //https://en.wikipedia.org/wiki/Nonzero-rule
+ enum class FillRule { EvenOdd, NonZero, Positive, Negative };
+
+#ifdef USINGZ
+ using z_type = int64_t;
+#endif
+
+ // Point ------------------------------------------------------------------------
+
+ template
+ struct Point {
+ T x;
+ T y;
+#ifdef USINGZ
+ z_type z;
+
+ template
+ inline void Init(const T2 x_ = 0, const T2 y_ = 0, const z_type z_ = 0)
+ {
+ if constexpr (std::is_integral_v &&
+ is_round_invocable::value && !std::is_integral_v)
+ {
+ x = static_cast(std::round(x_));
+ y = static_cast(std::round(y_));
+ z = z_;
+ }
+ else
+ {
+ x = static_cast(x_);
+ y = static_cast(y_);
+ z = z_;
+ }
+ }
+
+ explicit Point() : x(0), y(0), z(0) {};
+
+ template
+ Point(const T2 x_, const T2 y_, const z_type z_ = 0)
+ {
+ Init(x_, y_);
+ z = z_;
+ }
+
+ template
+ explicit Point(const Point& p)
+ {
+ Init(p.x, p.y, p.z);
+ }
+
+ template
+ explicit Point(const Point& p, z_type z_)
+ {
+ Init(p.x, p.y, z_);
+ }
+
+ Point operator * (const double scale) const
+ {
+ return Point(x * scale, y * scale, z);
+ }
+
+ void SetZ(const z_type z_value) { z = z_value; }
+
+ friend std::ostream& operator<<(std::ostream& os, const Point& point)
+ {
+ os << point.x << "," << point.y << "," << point.z;
+ return os;
+ }
+
+#else
+
+ template
+ inline void Init(const T2 x_ = 0, const T2 y_ = 0)
+ {
+ if constexpr (std::is_integral_v &&
+ is_round_invocable::value && !std::is_integral_v)
+ {
+ x = static_cast(std::round(x_));
+ y = static_cast(std::round(y_));
+ }
+ else
+ {
+ x = static_cast(x_);
+ y = static_cast(y_);
+ }
+ }
+
+ explicit Point() : x(0), y(0) {};
+
+ template
+ Point(const T2 x_, const T2 y_) { Init(x_, y_); }
+
+ template
+ explicit Point(const Point& p) { Init(p.x, p.y); }
+
+ Point operator * (const double scale) const
+ {
+ return Point(x * scale, y * scale);
+ }
+
+ friend std::ostream& operator<<(std::ostream& os, const Point& point)
+ {
+ os << point.x << "," << point.y;
+ return os;
+ }
+#endif
+
+ friend bool operator==(const Point& a, const Point& b)
+ {
+ return a.x == b.x && a.y == b.y;
+ }
+
+ friend bool operator!=(const Point& a, const Point& b)
+ {
+ return !(a == b);
+ }
+
+ inline Point operator-() const
+ {
+ return Point(-x, -y);
+ }
+
+ inline Point operator+(const Point& b) const
+ {
+ return Point(x + b.x, y + b.y);
+ }
+
+ inline Point operator-(const Point& b) const
+ {
+ return Point(x - b.x, y - b.y);
+ }
+
+ inline void Negate() { x = -x; y = -y; }
+
+ };
+
+ //nb: using 'using' here (instead of typedef) as they can be used in templates
+ using Point64 = Point;
+ using PointD = Point;
+
+ template
+ using Path = std::vector>;
+ template
+ using Paths = std::vector>;
+
+ using Path64 = Path;
+ using PathD = Path;
+ using Paths64 = std::vector< Path64>;
+ using PathsD = std::vector< PathD>;
+
+ static const Point64 InvalidPoint64 = Point64(
+ (std::numeric_limits::max)(),
+ (std::numeric_limits::max)());
+ static const PointD InvalidPointD = PointD(
+ (std::numeric_limits::max)(),
+ (std::numeric_limits::max)());
+
+ template
+ static inline Point MidPoint(const Point& p1, const Point& p2)
+ {
+ Point result;
+ result.x = (p1.x + p2.x) / 2;
+ result.y = (p1.y + p2.y) / 2;
+ return result;
+ }
+
+ // Rect ------------------------------------------------------------------------
+
+ template
+ struct Rect;
+
+ using Rect64 = Rect;
+ using RectD = Rect;
+
+ template
+ struct Rect {
+ T left;
+ T top;
+ T right;
+ T bottom;
+
+ Rect(T l, T t, T r, T b) :
+ left(l),
+ top(t),
+ right(r),
+ bottom(b) {}
+
+ Rect(bool is_valid = true)
+ {
+ if (is_valid)
+ {
+ left = right = top = bottom = 0;
+ }
+ else
+ {
+ left = top = (std::numeric_limits::max)();
+ right = bottom = std::numeric_limits::lowest();
+ }
+ }
+
+ static Rect InvalidRect()
+ {
+ return {
+ (std::numeric_limits::max)(),
+ (std::numeric_limits::max)(),
+ std::numeric_limits::lowest(),
+ std::numeric_limits::lowest() };
+ }
+
+ bool IsValid() const { return left != (std::numeric_limits::max)(); }
+
+ T Width() const { return right - left; }
+ T Height() const { return bottom - top; }
+ void Width(T width) { right = left + width; }
+ void Height(T height) { bottom = top + height; }
+
+ Point MidPoint() const
+ {
+ return Point((left + right) / 2, (top + bottom) / 2);
+ }
+
+ Path AsPath() const
+ {
+ Path result;
+ result.reserve(4);
+ result.emplace_back(left, top);
+ result.emplace_back(right, top);
+ result.emplace_back(right, bottom);
+ result.emplace_back(left, bottom);
+ return result;
+ }
+
+ bool Contains(const Point& pt) const
+ {
+ return pt.x > left && pt.x < right&& pt.y > top && pt.y < bottom;
+ }
+
+ bool Contains(const Rect& rec) const
+ {
+ return rec.left >= left && rec.right <= right &&
+ rec.top >= top && rec.bottom <= bottom;
+ }
+
+ void Scale(double scale) {
+ left *= scale;
+ top *= scale;
+ right *= scale;
+ bottom *= scale;
+ }
+
+ bool IsEmpty() const { return bottom <= top || right <= left; };
+
+ bool Intersects(const Rect& rec) const
+ {
+ return ((std::max)(left, rec.left) <= (std::min)(right, rec.right)) &&
+ ((std::max)(top, rec.top) <= (std::min)(bottom, rec.bottom));
+ };
+
+ bool operator==(const Rect& other) const {
+ return left == other.left && right == other.right &&
+ top == other.top && bottom == other.bottom;
+ }
+
+ Rect& operator+=(const Rect& other)
+ {
+ left = (std::min)(left, other.left);
+ top = (std::min)(top, other.top);
+ right = (std::max)(right, other.right);
+ bottom = (std::max)(bottom, other.bottom);
+ return *this;
+ }
+
+ Rect operator+(const Rect& other) const
+ {
+ Rect result = *this;
+ result += other;
+ return result;
+ }
+
+ friend std::ostream& operator<<(std::ostream& os, const Rect& rect) {
+ os << "(" << rect.left << "," << rect.top << "," << rect.right << "," << rect.bottom << ") ";
+ return os;
+ }
+ };
+
+ template
+ inline Rect ScaleRect(const Rect& rect, double scale)
+ {
+ Rect result;
+
+ if constexpr (std::is_integral_v &&
+ is_round_invocable::value && !std::is_integral_v)
+ {
+ result.left = static_cast(std::round(rect.left * scale));
+ result.top = static_cast(std::round(rect.top * scale));
+ result.right = static_cast(std::round(rect.right * scale));
+ result.bottom = static_cast(std::round(rect.bottom * scale));
+ }
+ else
+ {
+ result.left = static_cast(rect.left * scale);
+ result.top = static_cast(rect.top * scale);
+ result.right = static_cast(rect.right * scale);
+ result.bottom = static_cast(rect.bottom * scale);
+ }
+ return result;
+ }
+
+ static const Rect64 InvalidRect64 = Rect64::InvalidRect();
+ static const RectD InvalidRectD = RectD::InvalidRect();
+
+ template
+ Rect GetBounds(const Path& path)
+ {
+ T xmin = (std::numeric_limits::max)();
+ T ymin = (std::numeric_limits::max)();
+ T xmax = std::numeric_limits::lowest();
+ T ymax = std::numeric_limits::lowest();
+ for (const auto& p : path)
+ {
+ if (p.x < xmin) xmin = p.x;
+ if (p.x > xmax) xmax = p.x;
+ if (p.y < ymin) ymin = p.y;
+ if (p.y > ymax) ymax = p.y;
+ }
+ return Rect(xmin, ymin, xmax, ymax);
+ }
+
+ template
+ Rect GetBounds(const Paths& paths)
+ {
+ T xmin = (std::numeric_limits::max)();
+ T ymin = (std::numeric_limits::max)();
+ T xmax = std::numeric_limits::lowest();
+ T ymax = std::numeric_limits::lowest();
+ for (const Path& path : paths)
+ for (const Point& p : path)
+ {
+ if (p.x < xmin) xmin = p.x;
+ if (p.x > xmax) xmax = p.x;
+ if (p.y < ymin) ymin = p.y;
+ if (p.y > ymax) ymax = p.y;
+ }
+ return Rect(xmin, ymin, xmax, ymax);
+ }
+
+ template
+ Rect GetBounds(const Path& path)
+ {
+ T xmin = (std::numeric_limits::max)();
+ T ymin = (std::numeric_limits::max)();
+ T xmax = std::numeric_limits::lowest();
+ T ymax = std::numeric_limits::lowest();
+ for (const auto& p : path)
+ {
+ if (p.x < xmin) xmin = static_cast(p.x);
+ if (p.x > xmax) xmax = static_cast(p.x);
+ if (p.y < ymin) ymin = static_cast(p.y);
+ if (p.y > ymax) ymax = static_cast(p.y);
+ }
+ return Rect(xmin, ymin, xmax, ymax);
+ }
+
+ template
+ Rect GetBounds(const Paths& paths)
+ {
+ T xmin = (std::numeric_limits::max)();
+ T ymin = (std::numeric_limits::max)();
+ T xmax = std::numeric_limits::lowest();
+ T ymax = std::numeric_limits::lowest();
+ for (const Path& path : paths)
+ for (const Point& p : path)
+ {
+ if (p.x < xmin) xmin = static_cast(p.x);
+ if (p.x > xmax) xmax = static_cast(p.x);
+ if (p.y < ymin) ymin = static_cast(p.y);
+ if (p.y > ymax) ymax = static_cast(p.y);
+ }
+ return Rect(xmin, ymin, xmax, ymax);
+ }
+
+ template
+ std::ostream& operator << (std::ostream& outstream, const Path& path)
+ {
+ if (!path.empty())
+ {
+ auto pt = path.cbegin(), last = path.cend() - 1;
+ while (pt != last)
+ outstream << *pt++ << ", ";
+ outstream << *last << std::endl;
+ }
+ return outstream;
+ }
+
+ template
+ std::ostream& operator << (std::ostream& outstream, const Paths& paths)
+ {
+ for (auto p : paths)
+ outstream << p;
+ return outstream;
+ }
+
+
+ template
+ inline Path ScalePath(const Path& path,
+ double scale_x, double scale_y, int& error_code)
+ {
+ Path result;
+ if (scale_x == 0 || scale_y == 0)
+ {
+ error_code |= scale_error_i;
+ DoError(scale_error_i);
+ // if no exception, treat as non-fatal error
+ if (scale_x == 0) scale_x = 1.0;
+ if (scale_y == 0) scale_y = 1.0;
+ }
+
+ result.reserve(path.size());
+#ifdef USINGZ
+ std::transform(path.begin(), path.end(), back_inserter(result),
+ [scale_x, scale_y](const auto& pt)
+ { return Point(pt.x * scale_x, pt.y * scale_y, pt.z); });
+#else
+ std::transform(path.begin(), path.end(), back_inserter(result),
+ [scale_x, scale_y](const auto& pt)
+ { return Point(pt.x * scale_x, pt.y * scale_y); });
+#endif
+ return result;
+ }
+
+ template
+ inline Path ScalePath(const Path& path,
+ double scale, int& error_code)
+ {
+ return ScalePath(path, scale, scale, error_code);
+ }
+
+ template
+ inline Paths ScalePaths(const Paths& paths,
+ double scale_x, double scale_y, int& error_code)
+ {
+ Paths result;
+
+ if constexpr (std::is_integral_v)
+ {
+ RectD r = GetBounds(paths);
+ if ((r.left * scale_x) < min_coord ||
+ (r.right * scale_x) > max_coord ||
+ (r.top * scale_y) < min_coord ||
+ (r.bottom * scale_y) > max_coord)
+ {
+ error_code |= range_error_i;
+ DoError(range_error_i);
+ return result; // empty path
+ }
+ }
+
+ result.reserve(paths.size());
+ std::transform(paths.begin(), paths.end(), back_inserter(result),
+ [=, &error_code](const auto& path)
+ { return ScalePath(path, scale_x, scale_y, error_code); });
+ return result;
+ }
+
+ template
+ inline Paths ScalePaths(const Paths& paths,
+ double scale, int& error_code)
+ {
+ return ScalePaths(paths, scale, scale, error_code);
+ }
+
+ template
+ inline Path TransformPath(const Path& path)
+ {
+ Path result;
+ result.reserve(path.size());
+ std::transform(path.cbegin(), path.cend(), std::back_inserter(result),
+ [](const Point& pt) {return Point(pt); });
+ return result;
+ }
+
+ template
+ inline Paths TransformPaths(const Paths& paths)
+ {
+ Paths result;
+ std::transform(paths.cbegin(), paths.cend(), std::back_inserter(result),
+ [](const Path& path) {return TransformPath(path); });
+ return result;
+ }
+
+ template
+ inline double Sqr(T val)
+ {
+ return static_cast(val) * static_cast(val);
+ }
+
+ template
+ inline bool NearEqual(const Point& p1,
+ const Point& p2, double max_dist_sqrd)
+ {
+ return Sqr(p1.x - p2.x) + Sqr(p1.y - p2.y) < max_dist_sqrd;
+ }
+
+ template
+ inline Path StripNearEqual(const Path& path,
+ double max_dist_sqrd, bool is_closed_path)
+ {
+ if (path.size() == 0) return Path();
+ Path result;
+ result.reserve(path.size());
+ typename Path::const_iterator path_iter = path.cbegin();
+ Point first_pt = *path_iter++, last_pt = first_pt;
+ result.emplace_back(first_pt);
+ for (; path_iter != path.cend(); ++path_iter)
+ {
+ if (!NearEqual(*path_iter, last_pt, max_dist_sqrd))
+ {
+ last_pt = *path_iter;
+ result.emplace_back(last_pt);
+ }
+ }
+ if (!is_closed_path) return result;
+ while (result.size() > 1 &&
+ NearEqual(result.back(), first_pt, max_dist_sqrd)) result.pop_back();
+ return result;
+ }
+
+ template
+ inline Paths StripNearEqual(const Paths& paths,
+ double max_dist_sqrd, bool is_closed_path)
+ {
+ Paths result;
+ result.reserve(paths.size());
+ for (typename Paths::const_iterator paths_citer = paths.cbegin();
+ paths_citer != paths.cend(); ++paths_citer)
+ {
+ result.emplace_back(std::move(StripNearEqual(*paths_citer, max_dist_sqrd, is_closed_path)));
+ }
+ return result;
+ }
+
+ template
+ inline void StripDuplicates( Path& path, bool is_closed_path)
+ {
+ //https://stackoverflow.com/questions/1041620/whats-the-most-efficient-way-to-erase-duplicates-and-sort-a-vector#:~:text=Let%27s%20compare%20three%20approaches%3A
+ path.erase(std::unique(path.begin(), path.end()), path.end());
+ if (is_closed_path)
+ while (path.size() > 1 && path.back() == path.front()) path.pop_back();
+ }
+
+ template
+ inline void StripDuplicates( Paths& paths, bool is_closed_path)
+ {
+ for (typename Paths::iterator paths_citer = paths.begin();
+ paths_citer != paths.end(); ++paths_citer)
+ {
+ StripDuplicates(*paths_citer, is_closed_path);
+ }
+ }
+
+ // Miscellaneous ------------------------------------------------------------
+
+ inline void CheckPrecisionRange(int& precision, int& error_code)
+ {
+ if (precision >= -CLIPPER2_MAX_DEC_PRECISION &&
+ precision <= CLIPPER2_MAX_DEC_PRECISION) return;
+ error_code |= precision_error_i; // non-fatal error
+ DoError(precision_error_i); // does nothing when exceptions are disabled
+ precision = precision > 0 ? CLIPPER2_MAX_DEC_PRECISION : -CLIPPER2_MAX_DEC_PRECISION;
+ }
+
+ inline void CheckPrecisionRange(int& precision)
+ {
+ int error_code = 0;
+ CheckPrecisionRange(precision, error_code);
+ }
+
+ inline int TriSign(int64_t x) // returns 0, 1 or -1
+ {
+ return (x > 0) - (x < 0);
+ }
+
+ struct MultiplyUInt64Result
+ {
+ const uint64_t result = 0;
+ const uint64_t carry = 0;
+
+ bool operator==(const MultiplyUInt64Result& other) const
+ {
+ return result == other.result && carry == other.carry;
+ };
+ };
+
+ inline MultiplyUInt64Result Multiply(uint64_t a, uint64_t b) // #834, #835
+ {
+ const auto lo = [](uint64_t x) { return x & 0xFFFFFFFF; };
+ const auto hi = [](uint64_t x) { return x >> 32; };
+
+ const uint64_t x1 = lo(a) * lo(b);
+ const uint64_t x2 = hi(a) * lo(b) + hi(x1);
+ const uint64_t x3 = lo(a) * hi(b) + lo(x2);
+ const uint64_t result = lo(x3) << 32 | lo(x1);
+ const uint64_t carry = hi(a) * hi(b) + hi(x2) + hi(x3);
+
+ return { result, carry };
+ }
+
+ // returns true if (and only if) a * b == c * d
+ inline bool ProductsAreEqual(int64_t a, int64_t b, int64_t c, int64_t d)
+ {
+#if (defined(__clang__) || defined(__GNUC__)) && UINTPTR_MAX >= UINT64_MAX
+ const auto ab = static_cast<__int128_t>(a) * static_cast<__int128_t>(b);
+ const auto cd = static_cast<__int128_t>(c) * static_cast<__int128_t>(d);
+ return ab == cd;
+#else
+ // nb: unsigned values needed for calculating overflow carry
+ const auto abs_a = static_cast(std::abs(a));
+ const auto abs_b = static_cast(std::abs(b));
+ const auto abs_c = static_cast(std::abs(c));
+ const auto abs_d = static_cast(std::abs(d));
+
+ const auto abs_ab = Multiply(abs_a, abs_b);
+ const auto abs_cd = Multiply(abs_c, abs_d);
+
+ // nb: it's important to differentiate 0 values here from other values
+ const auto sign_ab = TriSign(a) * TriSign(b);
+ const auto sign_cd = TriSign(c) * TriSign(d);
+
+ return abs_ab == abs_cd && sign_ab == sign_cd;
+#endif
+ }
+
+ template
+ inline bool IsCollinear(const Point& pt1,
+ const Point& sharedPt, const Point& pt2) // #777
+ {
+ const auto a = sharedPt.x - pt1.x;
+ const auto b = pt2.y - sharedPt.y;
+ const auto c = sharedPt.y - pt1.y;
+ const auto d = pt2.x - sharedPt.x;
+ // When checking for collinearity with very large coordinate values
+ // then ProductsAreEqual is more accurate than using CrossProduct.
+ return ProductsAreEqual(a, b, c, d);
+ }
+
+
+ template
+ inline double CrossProduct(const Point& pt1, const Point& pt2, const Point& pt3) {
+ return (static_cast(pt2.x - pt1.x) * static_cast(pt3.y -
+ pt2.y) - static_cast(pt2.y - pt1.y) * static_cast(pt3.x - pt2.x));
+ }
+
+ template
+ inline double CrossProduct(const Point& vec1, const Point& vec2)
+ {
+ return static_cast(vec1.y * vec2.x) - static_cast(vec2.y * vec1.x);
+ }
+
+ template
+ inline double DotProduct(const Point& pt1, const Point& pt2, const Point& pt3) {
+ return (static_cast(pt2.x - pt1.x) * static_cast(pt3.x - pt2.x) +
+ static_cast(pt2.y - pt1.y) * static_cast(pt3.y - pt2.y));
+ }
+
+ template
+ inline double DotProduct(const Point& vec1, const Point& vec2)
+ {
+ return static_cast(vec1.x * vec2.x) + static_cast(vec1.y * vec2.y);
+ }
+
+ template
+ inline double DistanceSqr(const Point