mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-07-11 09:44:17 +02:00
Compare commits
235 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| eb5e3fcd13 | |||
| 8f8968cbb1 | |||
| ac83e93426 | |||
| 78d0cf4a4f | |||
| 2444c6090b | |||
| 7e49bc5a50 | |||
| 457719d0cc | |||
| c3e63d5a0e | |||
| 8c1b3f8ce3 | |||
| 55b37b794c | |||
| 1aca396e34 | |||
| cb000a5101 | |||
| 1ae2a96747 | |||
| 6834086c37 | |||
| b33b493c6e | |||
| 437fe1e442 | |||
| 2a348dcff9 | |||
| 2821986fb2 | |||
| 1a13f9707b | |||
| ff1b47942c | |||
| 13e4973b48 | |||
| fd46054fb7 | |||
| f618f39bee | |||
| 603486ad2f | |||
| a4b11651a4 | |||
| b6e9a04433 | |||
| 05a2bbbf35 | |||
| 16b6572826 | |||
| 806f06fba6 | |||
| 7a90caedec | |||
| 017b4d07da | |||
| 05015bc476 | |||
| 1f0f3b92b3 | |||
| fe3ce7f578 | |||
| 51c995168a | |||
| f83e4ff4bf | |||
| b67e793283 | |||
| d87ec54a5f | |||
| a6b1040caf | |||
| 9650c4b79a | |||
| 3f8eb5adf0 | |||
| 99a78f9a55 | |||
| c3ace64205 | |||
| 3b2c1ec6e3 | |||
| dba432639e | |||
| 166c4491c2 | |||
| d1cd5a62ed | |||
| b11a406519 | |||
| c7042e1877 | |||
| 896e0b82c2 | |||
| 7856757087 | |||
| b0ce5d7582 | |||
| e23416aa92 | |||
| 9a9cfca706 | |||
| 59feb88ef7 | |||
| 247cda0e26 | |||
| 9f3233224e | |||
| ef14238b4e | |||
| 13b7345189 | |||
| 48ca476a2f | |||
| 57ef8e7c25 | |||
| d09ce46700 | |||
| 3afc1c2663 | |||
| 5821762870 | |||
| 86b7a19f19 | |||
| cc85cef17c | |||
| 5f08f523c2 | |||
| b612959682 | |||
| aea83d5ece | |||
| 07aa5786e5 | |||
| 5bd70aff90 | |||
| 22b8d52311 | |||
| ee6c7e6286 | |||
| 66ea4c4967 | |||
| a6769818fd | |||
| 95535215aa | |||
| eadb46c5ac | |||
| b2b7943dbe | |||
| a0a261db50 | |||
| 8e73dea7e2 | |||
| e2a3670d65 | |||
| 342db51523 | |||
| 414f1660ed | |||
| cd9530eec3 | |||
| 53675cf5ce | |||
| e0566546c6 | |||
| 6c4a8efe25 | |||
| a8db6587cb | |||
| 1d8fb3d407 | |||
| 2d09d53805 | |||
| f5310f0ca4 | |||
| 972fcfa0f0 | |||
| b0582f6ea3 | |||
| 8b6c28b374 | |||
| 0a3c27765d | |||
| 040a8b8fc6 | |||
| 9f67f72d3c | |||
| 04438ace57 | |||
| e16236e450 | |||
| 3807517e02 | |||
| ab8bd8e754 | |||
| 65d63085f8 | |||
| 2c8ecc3ea7 | |||
| 5fbc79c466 | |||
| 8fe4183856 | |||
| 0d52608f1d | |||
| 5df3c54b84 | |||
| b2db2e71b6 | |||
| 7978370b39 | |||
| d187c61599 | |||
| fa745a58b2 | |||
| 16592f3a6e | |||
| 2b5d3510c3 | |||
| 76f690d96e | |||
| d5f75c9e42 | |||
| 13d3491571 | |||
| 8a6d6818fb | |||
| d7c1cbbc4e | |||
| 5644ca09c4 | |||
| 863307d871 | |||
| 904a0942f0 | |||
| 7f20ff60ea | |||
| 1ce246e05d | |||
| f79461b407 | |||
| bbfe32e963 | |||
| 06c67b0319 | |||
| c68753d776 | |||
| 15172303e4 | |||
| 9017ad626d | |||
| ef18567d9f | |||
| d0c2097cd4 | |||
| b5ed65ddd6 | |||
| 673917ae66 | |||
| e31f57a02f | |||
| ee57382d6e | |||
| 6683f84da0 | |||
| d2cb0aaf63 | |||
| 51a5e10b4e | |||
| c2dfc10c18 | |||
| 6628de5262 | |||
| 37f2837a55 | |||
| 4b76157b9e | |||
| 3b2962fe1c | |||
| 20721b05fb | |||
| 75187d69c6 | |||
| 3df128d9f9 | |||
| 426d77a932 | |||
| b3b1ff0f50 | |||
| 88029a1411 | |||
| 57e46f07fe | |||
| 254d955f89 | |||
| e490685b42 | |||
| 7b0c39a20d | |||
| 059d631a6d | |||
| 7c255bd58d | |||
| bbcd5ec25e | |||
| 5369d6b38e | |||
| b3834427bc | |||
| d7002433a2 | |||
| e1291d5b7c | |||
| e1fd632ba3 | |||
| fbaba52bc2 | |||
| 224e82f33e | |||
| 8df49d7676 | |||
| 88d8c561db | |||
| 78697466e0 | |||
| 5e150cd3eb | |||
| 23dd23b468 | |||
| 7d47dab728 | |||
| 74f2f73ce6 | |||
| 1e2f60a9b8 | |||
| bf892e9ece | |||
| a44fe80caa | |||
| 093287f6bf | |||
| e0365c1d10 | |||
| 6cb2086dfc | |||
| 3f4b424200 | |||
| 051fdd55b0 | |||
| 29f4318ef8 | |||
| 30d7fed0e5 | |||
| f0177a879c | |||
| 88af1e54a4 | |||
| d3ba0542f2 | |||
| 4d25bdcabb | |||
| 02c5f8f648 | |||
| fc23783224 | |||
| 7ade24fc77 | |||
| db16fa4403 | |||
| 1bc08722fd | |||
| 3a0a9f6705 | |||
| ae0b5834a0 | |||
| 55eddba08f | |||
| 0783ec1b9c | |||
| fc77fa1389 | |||
| 0f9b8afe04 | |||
| d39457951a | |||
| 9fcb526aca | |||
| 9cd0ec1634 | |||
| 0e178aecb8 | |||
| 66f764cf02 | |||
| 63f2d8d880 | |||
| b123f016ab | |||
| f08f679ba7 | |||
| 054e0509c4 | |||
| f86cd4c3d2 | |||
| a19b3747ea | |||
| 30440099c2 | |||
| 30dd35a743 | |||
| 4f1dab7b5f | |||
| baad1891eb | |||
| 6ea9e4a5b0 | |||
| 534330aa99 | |||
| 58a0ced8be | |||
| e18d5b7183 | |||
| b006366ea3 | |||
| 1db914f964 | |||
| 6b34999a51 | |||
| 85ea218b5d | |||
| 137f4f2666 | |||
| 4cc2a81f00 | |||
| da340c9e92 | |||
| a7356d3765 | |||
| 3aa0685786 | |||
| 2f8c98dccf | |||
| 59e422c538 | |||
| 5ef5e41e69 | |||
| 58facc8ab1 | |||
| 3341514bb4 | |||
| 0434aba3a8 | |||
| c1cb214a03 | |||
| 3233a3cf8f | |||
| 469a3d60b2 | |||
| bb35bed104 | |||
| 624acf5533 | |||
| f71f0b9cb0 |
@@ -8,4 +8,4 @@
|
||||
<!-- If applicable, including examples you've already tested with / recommendations for how to test further is very helpful! -->
|
||||
|
||||
### Did you use AI to help find, test, or implement this issue or feature?
|
||||
<!-- Answer yes or no. If you answer yes, please provide a brief explanation how. -->
|
||||
<!-- Answer yes or no. If you answer yes, please provide a brief explanation as to how you used it. Please see the Large Language Model (LLM) Usage Policy for more information: https://pcsx2.net/docs/contributing/#large-language-model-llm-usage-policy -->
|
||||
@@ -11,7 +11,7 @@ jobs:
|
||||
name: "Update Base Translation"
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- name: Update Base Translation
|
||||
run: ./.github/workflows/scripts/common/update_base_translation.sh
|
||||
|
||||
@@ -9,7 +9,7 @@ jobs:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- name: Get Latest DB and Prepare DB File
|
||||
run: |
|
||||
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Install Packages
|
||||
run: |
|
||||
|
||||
@@ -51,7 +51,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
set-safe-directory: ${{ env.GITHUB_WORKSPACE }}
|
||||
# 10 here, since the odds of having 10 untagged commits in a row should be slim to none
|
||||
@@ -157,4 +157,21 @@ jobs:
|
||||
with:
|
||||
name: ${{ steps.artifact-metadata.outputs.artifact-name }}
|
||||
path: ci-artifacts
|
||||
report-error:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build_linux
|
||||
if: always() && needs.build_linux.result == 'failure' && inputs.publish == true
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- name: Push Discord Webhook
|
||||
env:
|
||||
OWNER: PCSX2
|
||||
REPO: pcsx2
|
||||
DISCORD_BUILD_WEBHOOK: ${{ secrets.DISCORD_BUILD_WEBHOOK }}
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
cd ./.github/workflows/scripts/releases/announce-release
|
||||
npm ci
|
||||
FLATHUB_FAILURE=1 node index.js
|
||||
|
||||
@@ -20,6 +20,18 @@ jobs:
|
||||
cmakeflags: ""
|
||||
buildAppImage: true
|
||||
secrets: inherit
|
||||
build_linux_debug:
|
||||
name: "Debug"
|
||||
if: github.repository != 'PCSX2/pcsx2' || github.event_name == 'pull_request'
|
||||
uses: ./.github/workflows/linux_build_qt.yml
|
||||
with:
|
||||
jobName: "Debug Build"
|
||||
artifactPrefixName: "PCSX2-linux-Qt-x64-debug"
|
||||
compiler: clang
|
||||
cmakeflags: ""
|
||||
buildAppImage: true
|
||||
cmakeBuildType: Debug
|
||||
secrets: inherit
|
||||
build_linux_flatpak:
|
||||
name: "Flatpak"
|
||||
if: github.repository != 'PCSX2/pcsx2' || github.event_name == 'pull_request'
|
||||
|
||||
@@ -39,6 +39,10 @@ on:
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
cmakeBuildType:
|
||||
required: false
|
||||
type: string
|
||||
default: Release
|
||||
|
||||
jobs:
|
||||
build_linux:
|
||||
@@ -55,7 +59,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
@@ -129,7 +133,7 @@ jobs:
|
||||
ADDITIONAL_CMAKE_ARGS: ${{ inputs.cmakeflags }}
|
||||
run: |
|
||||
cmake -B build -G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_BUILD_TYPE="${{ inputs.cmakeBuildType }}" \
|
||||
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON \
|
||||
-DCMAKE_PREFIX_PATH="$HOME/deps" \
|
||||
-DCMAKE_C_COMPILER=clang-17 \
|
||||
|
||||
@@ -52,7 +52,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
# actions/checkout elides tags, fetch them primarily for releases
|
||||
- name: Fetch Tags
|
||||
|
||||
@@ -35,7 +35,7 @@ jobs:
|
||||
outputs:
|
||||
new_tag: ${{ steps.tag_version.outputs.new_tag }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
# Docs - https://github.com/mathieudutour/github-tag-action
|
||||
- name: Bump Version and Push Tag
|
||||
@@ -176,7 +176,7 @@ jobs:
|
||||
name: "Upload Artifacts"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- name: Prepare Artifact Folder
|
||||
run: mkdir ./ci-artifacts/
|
||||
@@ -209,6 +209,7 @@ jobs:
|
||||
gh release upload "${TAG_VAL}" ${{ github.WORKSPACE }}/ci-artifacts/out/* --repo PCSX2/pcsx2 --clobber
|
||||
|
||||
- name: Publish Release
|
||||
if: github.event_name != 'workflow_dispatch' || inputs.is_prerelease == 'true'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
|
||||
@@ -18,16 +18,16 @@ if [ "${INSTALLDIR:0:1}" != "/" ]; then
|
||||
INSTALLDIR="$PWD/$INSTALLDIR"
|
||||
fi
|
||||
|
||||
QT=6.11.0
|
||||
QT=6.11.1
|
||||
QTAPNG=1.3.0
|
||||
|
||||
FFMPEG=8.1
|
||||
LIBBACKTRACE=ad106d5fdd5d960bd33fae1c48a351af567fd075
|
||||
LIBJPEGTURBO=3.1.4.1
|
||||
LIBJPEGTURBO=3.2.0
|
||||
LIBPNG=1.6.58
|
||||
LIBWEBP=1.6.0
|
||||
NVENC=13.0.19.0
|
||||
SDL=SDL3-3.4.8
|
||||
SDL=SDL3-3.4.12
|
||||
LZ4=1.10.0
|
||||
VULKAN=1.4.328.1
|
||||
ZSTD=1.5.7
|
||||
@@ -47,20 +47,20 @@ cd deps-build
|
||||
export PKG_CONFIG_PATH="$INSTALLDIR/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||
|
||||
grep . > SHASUMS <<EOF
|
||||
231ad85979864d914dc9568a1b71c91d6cf20d7b2021d059103bf0eb51cb755e qtbase-everywhere-src-$QT.tar.xz
|
||||
d3adb02ac5e2fe24068dbdaee0d7cc68cc3fa8553291c1bfce77c9fe8e940cc8 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
dfa8d653be07087d9407ed4a4ebae847f8953e0b7abd829f089803ab652a30e6 qtsvg-everywhere-src-$QT.tar.xz
|
||||
cfb1993d7a10848965b01b9cf33a54b8a4ba4e5e3a6d28d59483e73f10d9fc76 qttools-everywhere-src-$QT.tar.xz
|
||||
54f48b2fe4316892ff930195f170a5385644acc7393505f3155c066b8e1ffe56 qttranslations-everywhere-src-$QT.tar.xz
|
||||
e710e6e760f92922b86e4dd68f6bbe94ef6510919519d1b0068e874b5ad84d37 qtwayland-everywhere-src-$QT.tar.xz
|
||||
d9594a31228aa23ad6b531719a29b45f0f3989fe6c136d45767ea179f233c1ac qtbase-everywhere-src-$QT.tar.xz
|
||||
b2bf6c6845ac175ed7f819145483ba4676f617aaa6a5012c8efee63c8bbac413 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
7f3cf02f4824bf03c2c5859ea6db173bf1482a1daf24e6cdf7bc78cfa26a8a94 qtsvg-everywhere-src-$QT.tar.xz
|
||||
8e61835a679c93fa9c6065b142353c2071ba68e297898937c32a03777fcaf50d qttools-everywhere-src-$QT.tar.xz
|
||||
37c02c81206594c7bb4edca85ac93e8e55a9836b70c960fde6cb0f8623ec5677 qttranslations-everywhere-src-$QT.tar.xz
|
||||
95788aa502f75441d4edf65932b235f76523084e13dbbb7b9ee2d207b32bd9b3 qtwayland-everywhere-src-$QT.tar.xz
|
||||
f1d3be3489f758efe1a8f12118a212febbe611aa670af32e0159fa3c1feab2a6 QtApng-$QTAPNG.tar.gz
|
||||
|
||||
b072aed6871998cce9b36e7774033105ca29e33632be5b6347f3206898e0756a ffmpeg-$FFMPEG.tar.xz
|
||||
96e5c2d7f2c482a60d5804da48a2eb9a0db0719b2c65dcc169fbfdcf37f3a45d libbacktrace-$LIBBACKTRACE.tar.gz
|
||||
ecae8008e2cc9ade2f2c1bb9d5e6d4fb73e7c433866a056bd82980741571a022 libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
6f30092cef9fb839779646608f4ee14ae3cbac989c47fa05e841b0841f09878e libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
28eb403f51f0f7405249132cecfe82ea5c0ef97f1b32c5a65828814ae0d34775 libpng-$LIBPNG.tar.xz
|
||||
e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWEBP.tar.gz
|
||||
e9fff7467fb60f037e6708da18b25560649e4c63edc2a69bb871b960d9cbfbba $SDL.tar.gz
|
||||
f07b958a9ac5020fb7a44cadb957f658b2149c3c8abb4f63145fac9303249db7 $SDL.tar.gz
|
||||
eee7dea22ed502868017971c86c63c4ed1e6085de0baebfdcc3d3322f00f3eb0 libpng-$LIBPNG-apng.patch.gz
|
||||
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
|
||||
13da39edb3a40ed9713ae390ca89faa2f1202c9dda869ef306a8d4383e242bee nv-codec-headers-$NVENC.tar.gz
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://libsdl.org/release/SDL3-3.4.8.tar.gz",
|
||||
"sha256": "e9fff7467fb60f037e6708da18b25560649e4c63edc2a69bb871b960d9cbfbba"
|
||||
"url": "https://libsdl.org/release/SDL3-3.4.12.tar.gz",
|
||||
"sha256": "f07b958a9ac5020fb7a44cadb957f658b2149c3c8abb4f63145fac9303249db7"
|
||||
}
|
||||
],
|
||||
"cleanup": [
|
||||
|
||||
@@ -43,16 +43,16 @@ if [ "${INSTALLDIR:0:1}" != "/" ]; then
|
||||
INSTALLDIR="$PWD/$INSTALLDIR"
|
||||
fi
|
||||
|
||||
QT=6.11.0
|
||||
QT=6.11.1
|
||||
QTAPNG=1.3.0
|
||||
|
||||
FREETYPE=2.14.3
|
||||
SDL=SDL3-3.4.8
|
||||
SDL=SDL3-3.4.12
|
||||
HARFBUZZ=14.2.0
|
||||
ZSTD=1.5.7
|
||||
LZ4=1.10.0
|
||||
LIBPNG=1.6.58
|
||||
LIBJPEGTURBO=3.1.4.1
|
||||
LIBJPEGTURBO=3.2.0
|
||||
LIBWEBP=1.6.0
|
||||
FFMPEG=8.1
|
||||
MOLTENVK=1.4.1
|
||||
@@ -85,22 +85,22 @@ CMAKE_ARCH_ARM64=-DCMAKE_OSX_ARCHITECTURES="arm64"
|
||||
CMAKE_ARCH_UNIVERSAL=-DCMAKE_OSX_ARCHITECTURES="x86_64;arm64"
|
||||
|
||||
grep . > SHASUMS <<EOF
|
||||
231ad85979864d914dc9568a1b71c91d6cf20d7b2021d059103bf0eb51cb755e qtbase-everywhere-src-$QT.tar.xz
|
||||
d3adb02ac5e2fe24068dbdaee0d7cc68cc3fa8553291c1bfce77c9fe8e940cc8 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
dfa8d653be07087d9407ed4a4ebae847f8953e0b7abd829f089803ab652a30e6 qtsvg-everywhere-src-$QT.tar.xz
|
||||
cfb1993d7a10848965b01b9cf33a54b8a4ba4e5e3a6d28d59483e73f10d9fc76 qttools-everywhere-src-$QT.tar.xz
|
||||
54f48b2fe4316892ff930195f170a5385644acc7393505f3155c066b8e1ffe56 qttranslations-everywhere-src-$QT.tar.xz
|
||||
d9594a31228aa23ad6b531719a29b45f0f3989fe6c136d45767ea179f233c1ac qtbase-everywhere-src-$QT.tar.xz
|
||||
b2bf6c6845ac175ed7f819145483ba4676f617aaa6a5012c8efee63c8bbac413 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
7f3cf02f4824bf03c2c5859ea6db173bf1482a1daf24e6cdf7bc78cfa26a8a94 qtsvg-everywhere-src-$QT.tar.xz
|
||||
8e61835a679c93fa9c6065b142353c2071ba68e297898937c32a03777fcaf50d qttools-everywhere-src-$QT.tar.xz
|
||||
37c02c81206594c7bb4edca85ac93e8e55a9836b70c960fde6cb0f8623ec5677 qttranslations-everywhere-src-$QT.tar.xz
|
||||
f1d3be3489f758efe1a8f12118a212febbe611aa670af32e0159fa3c1feab2a6 QtApng-$QTAPNG.tar.gz
|
||||
|
||||
36bc4f1cc413335368ee656c42afca65c5a3987e8768cc28cf11ba775e785a5f freetype-$FREETYPE.tar.xz
|
||||
e9fff7467fb60f037e6708da18b25560649e4c63edc2a69bb871b960d9cbfbba $SDL.tar.gz
|
||||
f07b958a9ac5020fb7a44cadb957f658b2149c3c8abb4f63145fac9303249db7 $SDL.tar.gz
|
||||
c652d5d94971031654ab3989891a490a895d3e3f2b71171c62692b28e94b1b93 harfbuzz-$HARFBUZZ.tar.gz
|
||||
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
|
||||
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
|
||||
28eb403f51f0f7405249132cecfe82ea5c0ef97f1b32c5a65828814ae0d34775 libpng-$LIBPNG.tar.xz
|
||||
e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWEBP.tar.gz
|
||||
eee7dea22ed502868017971c86c63c4ed1e6085de0baebfdcc3d3322f00f3eb0 libpng-$LIBPNG-apng.patch.gz
|
||||
ecae8008e2cc9ade2f2c1bb9d5e6d4fb73e7c433866a056bd82980741571a022 libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
6f30092cef9fb839779646608f4ee14ae3cbac989c47fa05e841b0841f09878e libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
b072aed6871998cce9b36e7774033105ca29e33632be5b6347f3206898e0756a ffmpeg-$FFMPEG.tar.xz
|
||||
9985f141902a17de818e264d17c1ce334b748e499ee02fcb4703e4dc0038f89c MoltenVK-$MOLTENVK.tar.gz
|
||||
51dbf24fe72e43dd7cb9a289d3cab47112010f1a2ed69b6fc8ac0dff31991ed2 KDDockWidgets-$KDDOCKWIDGETS.tar.gz
|
||||
|
||||
@@ -20,16 +20,16 @@ if [ "${INSTALLDIR:0:1}" != "/" ]; then
|
||||
INSTALLDIR="$PWD/$INSTALLDIR"
|
||||
fi
|
||||
|
||||
QT=6.11.0
|
||||
QT=6.11.1
|
||||
QTAPNG=1.3.0
|
||||
|
||||
FREETYPE=2.14.3
|
||||
SDL=SDL3-3.4.8
|
||||
SDL=SDL3-3.4.12
|
||||
HARFBUZZ=14.2.0
|
||||
ZSTD=1.5.7
|
||||
LZ4=1.10.0
|
||||
LIBPNG=1.6.58
|
||||
LIBJPEGTURBO=3.1.4.1
|
||||
LIBJPEGTURBO=3.2.0
|
||||
LIBWEBP=1.6.0
|
||||
FFMPEG=8.1
|
||||
MOLTENVK=1.4.1
|
||||
@@ -61,22 +61,22 @@ CMAKE_COMMON=(
|
||||
)
|
||||
|
||||
grep . > SHASUMS <<EOF
|
||||
231ad85979864d914dc9568a1b71c91d6cf20d7b2021d059103bf0eb51cb755e qtbase-everywhere-src-$QT.tar.xz
|
||||
d3adb02ac5e2fe24068dbdaee0d7cc68cc3fa8553291c1bfce77c9fe8e940cc8 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
dfa8d653be07087d9407ed4a4ebae847f8953e0b7abd829f089803ab652a30e6 qtsvg-everywhere-src-$QT.tar.xz
|
||||
cfb1993d7a10848965b01b9cf33a54b8a4ba4e5e3a6d28d59483e73f10d9fc76 qttools-everywhere-src-$QT.tar.xz
|
||||
54f48b2fe4316892ff930195f170a5385644acc7393505f3155c066b8e1ffe56 qttranslations-everywhere-src-$QT.tar.xz
|
||||
d9594a31228aa23ad6b531719a29b45f0f3989fe6c136d45767ea179f233c1ac qtbase-everywhere-src-$QT.tar.xz
|
||||
b2bf6c6845ac175ed7f819145483ba4676f617aaa6a5012c8efee63c8bbac413 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
7f3cf02f4824bf03c2c5859ea6db173bf1482a1daf24e6cdf7bc78cfa26a8a94 qtsvg-everywhere-src-$QT.tar.xz
|
||||
8e61835a679c93fa9c6065b142353c2071ba68e297898937c32a03777fcaf50d qttools-everywhere-src-$QT.tar.xz
|
||||
37c02c81206594c7bb4edca85ac93e8e55a9836b70c960fde6cb0f8623ec5677 qttranslations-everywhere-src-$QT.tar.xz
|
||||
f1d3be3489f758efe1a8f12118a212febbe611aa670af32e0159fa3c1feab2a6 QtApng-$QTAPNG.tar.gz
|
||||
|
||||
36bc4f1cc413335368ee656c42afca65c5a3987e8768cc28cf11ba775e785a5f freetype-$FREETYPE.tar.xz
|
||||
e9fff7467fb60f037e6708da18b25560649e4c63edc2a69bb871b960d9cbfbba $SDL.tar.gz
|
||||
f07b958a9ac5020fb7a44cadb957f658b2149c3c8abb4f63145fac9303249db7 $SDL.tar.gz
|
||||
c652d5d94971031654ab3989891a490a895d3e3f2b71171c62692b28e94b1b93 harfbuzz-$HARFBUZZ.tar.gz
|
||||
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
|
||||
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
|
||||
28eb403f51f0f7405249132cecfe82ea5c0ef97f1b32c5a65828814ae0d34775 libpng-$LIBPNG.tar.xz
|
||||
e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWEBP.tar.gz
|
||||
eee7dea22ed502868017971c86c63c4ed1e6085de0baebfdcc3d3322f00f3eb0 libpng-$LIBPNG-apng.patch.gz
|
||||
ecae8008e2cc9ade2f2c1bb9d5e6d4fb73e7c433866a056bd82980741571a022 libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
6f30092cef9fb839779646608f4ee14ae3cbac989c47fa05e841b0841f09878e libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
b072aed6871998cce9b36e7774033105ca29e33632be5b6347f3206898e0756a ffmpeg-$FFMPEG.tar.xz
|
||||
9985f141902a17de818e264d17c1ce334b748e499ee02fcb4703e4dc0038f89c v$MOLTENVK.tar.gz
|
||||
51dbf24fe72e43dd7cb9a289d3cab47112010f1a2ed69b6fc8ac0dff31991ed2 KDDockWidgets-$KDDOCKWIDGETS.tar.gz
|
||||
|
||||
@@ -38,39 +38,54 @@ const octokit = new Octokit({
|
||||
}
|
||||
});
|
||||
|
||||
if (process.env.TAG_VAL === undefined || process.env.TAG_VAL === "") {
|
||||
console.log(`Not announcing - TAG_VAL not defined`);
|
||||
process.exit(1);
|
||||
let embed;
|
||||
|
||||
if (process.env.FLATHUB_FAILURE === undefined)
|
||||
{
|
||||
if (process.env.TAG_VAL === undefined || process.env.TAG_VAL === "") {
|
||||
console.log(`Not announcing - TAG_VAL not defined`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const { data: releaseInfo } = await octokit.rest.repos.getReleaseByTag({
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
tag: process.env.TAG_VAL,
|
||||
});
|
||||
|
||||
if (releaseInfo === undefined) {
|
||||
console.log(`Not announcing - could not locate release with tag ${process.env.TAG_VAL}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!releaseInfo.prerelease) {
|
||||
console.log("Not announcing - release was not a pre-release (aka a Nightly)");
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Publish Webhook
|
||||
embed = new MessageEmbed()
|
||||
.setColor('#FF8000')
|
||||
.setTitle('New PCSX2 Nightly Build Available!')
|
||||
.setDescription("To download the latest or previous builds, [visit the official downloads page](https://pcsx2.net/downloads/).")
|
||||
.addFields(
|
||||
{ name: 'Version', value: releaseInfo.tag_name, inline: true },
|
||||
{ name: 'Installation Steps', value: '[See Here](https://pcsx2.net/docs/category/setup)', inline: true },
|
||||
{ name: 'Included Changes', value: releaseInfo.body, inline: false }
|
||||
);
|
||||
console.log(embed);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Flathub upload failure
|
||||
|
||||
const { data: releaseInfo } = await octokit.rest.repos.getReleaseByTag({
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
tag: process.env.TAG_VAL,
|
||||
});
|
||||
|
||||
if (releaseInfo === undefined) {
|
||||
console.log(`Not announcing - could not locate release with tag ${process.env.TAG_VAL}`);
|
||||
process.exit(1);
|
||||
embed = new MessageEmbed()
|
||||
.setColor('#FF0000')
|
||||
.setTitle('PCSX2 Failed to Build/Upload to FlatHub')
|
||||
.setDescription("Please check the latest Flathub build job to determine the root cause.")
|
||||
console.log(embed);
|
||||
}
|
||||
|
||||
if (!releaseInfo.prerelease) {
|
||||
console.log("Not announcing - release was not a pre-release (aka a Nightly)");
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Publish Webhook
|
||||
const embed = new MessageEmbed()
|
||||
.setColor('#FF8000')
|
||||
.setTitle('New PCSX2 Nightly Build Available!')
|
||||
.setDescription("To download the latest or previous builds, [visit the official downloads page](https://pcsx2.net/downloads/).")
|
||||
.addFields(
|
||||
{ name: 'Version', value: releaseInfo.tag_name, inline: true },
|
||||
{ name: 'Installation Steps', value: '[See Here](https://pcsx2.net/docs/category/setup)', inline: true },
|
||||
{ name: 'Included Changes', value: releaseInfo.body, inline: false }
|
||||
);
|
||||
console.log(embed);
|
||||
|
||||
// Get all webhooks, simple comma-sep string
|
||||
const webhookUrls = process.env.DISCORD_BUILD_WEBHOOK.split(",");
|
||||
|
||||
|
||||
Regular → Executable
+10
-10
@@ -54,14 +54,14 @@ echo INSTALLDIR=%INSTALLDIR%
|
||||
|
||||
cd "%BUILDDIR%"
|
||||
|
||||
set QT=6.11.0
|
||||
set QT=6.11.1
|
||||
set QTMINOR=6.11
|
||||
set QTAPNG=1.3.0
|
||||
|
||||
set FREETYPE=2.14.3
|
||||
set HARFBUZZ=14.2.0
|
||||
set SDL=SDL3-3.4.8
|
||||
set LIBJPEGTURBO=3.1.4.1
|
||||
set SDL=SDL3-3.4.12
|
||||
set LIBJPEGTURBO=3.2.0
|
||||
set LIBPNG=1658
|
||||
set LIBPNGLONG=1.6.58
|
||||
set LZ4=1.10.0
|
||||
@@ -81,20 +81,20 @@ set SHADERC_SPIRVTOOLS=6337eb62cadd7d124ac6789bf39c0f71148f0a73
|
||||
|
||||
set AGILITYSDK=1.619.2
|
||||
|
||||
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 590d5ae246c85fa14d6458a36ff75a11236acfe8987c2475090aab1770acbdf8 || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" 5dfb3c0cb84d2c935c1716b3b86358ca496fb9216676e7e28fee1357fb4a050e || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" c92e1b46170b8671bbd46c783939f0c2dba4986882c5ebd37aaa9eba5b224fbe || goto error
|
||||
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" ded4420823cb7b1bc49f38c5c56dd43ec27b6577ccbc7f620790abfabcc33b62 || goto error
|
||||
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" f9c4fd4fd73dff51e9043d2825b04361b678f63798ed798021ef47f1ff0bfccf || goto error
|
||||
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 3529cc37297a5a7aae4486843b9fd41c30df1d79a770f85e240b537dcc327ca5 || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" 37fba768f2780580dfae535ad6654cb9dc0bf2272e71b9b9781988de9ed0dac0 || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" 767730188d4610a89bf8da502f87acf1c8881a3ac54f1e0eb167ab1e08b03a75 || goto error
|
||||
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" 2d6ed2a98f458152e3cb17bf0be0494250194933a2d937b5a434e5b2006efca9 || goto error
|
||||
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" eef43700ffd079f5893e435aca1330c8bdbf2a94ae45013e3fc63870df53d3b0 || goto error
|
||||
call :downloadfile "QtApng-%QTAPNG%.zip" "https://github.com/jurplel/QtApng/archive/refs/tags/%QTAPNG%.zip" 5176082cdd468047a7eb1ec1f106b032f57df207aa318d559b29606b00d159ac || goto error
|
||||
|
||||
call :downloadfile "freetype-%FREETYPE%.tar.gz" https://sourceforge.net/projects/freetype/files/freetype2/%FREETYPE%/freetype-%FREETYPE%.tar.gz/download e61b31ab26358b946e767ed7eb7f4bb2e507da1cfefeb7a8861ace7fd5c899a1 || goto error
|
||||
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip bb2f83255706b1c92d731541c7cefaf98bb5b93e8f76d16f6deda05225ff20ee || goto error
|
||||
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1658.zip b32f170855dbbe3e6d9e645af40b538137041773672c3ba3e02db5816c82d376 || goto error
|
||||
call :downloadfile "lpng%LIBPNG%-apng.patch.gz" https://download.sourceforge.net/libpng-apng/libpng-%LIBPNGLONG%-apng.patch.gz eee7dea22ed502868017971c86c63c4ed1e6085de0baebfdcc3d3322f00f3eb0 || goto error
|
||||
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" ecae8008e2cc9ade2f2c1bb9d5e6d4fb73e7c433866a056bd82980741571a022 || goto error
|
||||
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" 6f30092cef9fb839779646608f4ee14ae3cbac989c47fa05e841b0841f09878e || goto error
|
||||
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 || goto error
|
||||
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 506206e02f90c1f37e048eacaf9e8a3a7dc682fd27783eb0ff15a7d2dcc9c2af || goto error
|
||||
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 3d4de8967a49c0451e775a0c1e9022092c19fdef41ba38a83fcf031c5a6496e2 || goto error
|
||||
call :downloadfile "lz4-%LZ4%.zip" "https://github.com/lz4/lz4/archive/refs/tags/v%LZ4%.zip" 3224b4c80f351f194984526ef396f6079bd6332dd9825c72ac0d7a37b3cdc565 || goto error
|
||||
call :downloadfile "zlib%ZLIBSHORT%.zip" "https://github.com/madler/zlib/releases/download/v%ZLIB%/zlib%ZLIBSHORT%.zip" e8bf55f3017aa181690990cb58a994e77885da140609fc8f94abe9b65d2cae28 || goto error
|
||||
call :downloadfile "zstd-%ZSTD%.zip" "https://github.com/facebook/zstd/archive/refs/tags/v%ZSTD%.zip" 7897bc5d620580d9b7cd3539c44b59d78f3657d33663fe97a145e07b4ebd69a4 || goto error
|
||||
|
||||
Regular → Executable
+22
-10
@@ -61,7 +61,7 @@ set "PATH=%PATH%;%INSTALLDIR%\bin"
|
||||
|
||||
cd "%BUILDDIR%"
|
||||
|
||||
set QT=6.11.0
|
||||
set QT=6.11.1
|
||||
set QTMINOR=6.11
|
||||
set QTAPNG=1.3.0
|
||||
|
||||
@@ -77,8 +77,8 @@ set LIBX264=b35605ace3ddf7c1a5d67a2eb553f034aef41d55
|
||||
|
||||
set FREETYPE=2.14.3
|
||||
set HARFBUZZ=14.2.0
|
||||
set SDL=SDL3-3.4.8
|
||||
set LIBJPEGTURBO=3.1.4.1
|
||||
set SDL=SDL3-3.4.12
|
||||
set LIBJPEGTURBO=3.2.0
|
||||
set LIBPNG=1658
|
||||
set LIBPNGLONG=1.6.58
|
||||
set LZ4=1.10.0
|
||||
@@ -97,12 +97,13 @@ set SHADERC_SPIRVHEADERS=58006c901d1d5c37dece6b6610e9af87fa951375
|
||||
set SHADERC_SPIRVTOOLS=6337eb62cadd7d124ac6789bf39c0f71148f0a73
|
||||
|
||||
set AGILITYSDK=1.619.2
|
||||
set DXHEADERS=1.619.1
|
||||
|
||||
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 590d5ae246c85fa14d6458a36ff75a11236acfe8987c2475090aab1770acbdf8 || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" 5dfb3c0cb84d2c935c1716b3b86358ca496fb9216676e7e28fee1357fb4a050e || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" c92e1b46170b8671bbd46c783939f0c2dba4986882c5ebd37aaa9eba5b224fbe || goto error
|
||||
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" ded4420823cb7b1bc49f38c5c56dd43ec27b6577ccbc7f620790abfabcc33b62 || goto error
|
||||
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" f9c4fd4fd73dff51e9043d2825b04361b678f63798ed798021ef47f1ff0bfccf || goto error
|
||||
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 3529cc37297a5a7aae4486843b9fd41c30df1d79a770f85e240b537dcc327ca5 || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" 37fba768f2780580dfae535ad6654cb9dc0bf2272e71b9b9781988de9ed0dac0 || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" 767730188d4610a89bf8da502f87acf1c8881a3ac54f1e0eb167ab1e08b03a75 || goto error
|
||||
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" 2d6ed2a98f458152e3cb17bf0be0494250194933a2d937b5a434e5b2006efca9 || goto error
|
||||
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" eef43700ffd079f5893e435aca1330c8bdbf2a94ae45013e3fc63870df53d3b0 || goto error
|
||||
call :downloadfile "QtApng-%QTAPNG%.zip" "https://github.com/jurplel/QtApng/archive/refs/tags/%QTAPNG%.zip" 5176082cdd468047a7eb1ec1f106b032f57df207aa318d559b29606b00d159ac || goto error
|
||||
|
||||
call :downloadfile "ffmpeg-%FFMPEG%.tar.xz" "https://ffmpeg.org/releases/ffmpeg-%FFMPEG%.tar.xz" b072aed6871998cce9b36e7774033105ca29e33632be5b6347f3206898e0756a || goto error
|
||||
@@ -119,9 +120,9 @@ call :downloadfile "freetype-%FREETYPE%.tar.gz" https://sourceforge.net/projects
|
||||
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip bb2f83255706b1c92d731541c7cefaf98bb5b93e8f76d16f6deda05225ff20ee || goto error
|
||||
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1658.zip b32f170855dbbe3e6d9e645af40b538137041773672c3ba3e02db5816c82d376 || goto error
|
||||
call :downloadfile "lpng%LIBPNG%-apng.patch.gz" https://download.sourceforge.net/libpng-apng/libpng-%LIBPNGLONG%-apng.patch.gz eee7dea22ed502868017971c86c63c4ed1e6085de0baebfdcc3d3322f00f3eb0 || goto error
|
||||
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" ecae8008e2cc9ade2f2c1bb9d5e6d4fb73e7c433866a056bd82980741571a022 || goto error
|
||||
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" 6f30092cef9fb839779646608f4ee14ae3cbac989c47fa05e841b0841f09878e || goto error
|
||||
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 || goto error
|
||||
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 506206e02f90c1f37e048eacaf9e8a3a7dc682fd27783eb0ff15a7d2dcc9c2af || goto error
|
||||
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 3d4de8967a49c0451e775a0c1e9022092c19fdef41ba38a83fcf031c5a6496e2 || goto error
|
||||
call :downloadfile "lz4-%LZ4%.zip" "https://github.com/lz4/lz4/archive/refs/tags/v%LZ4%.zip" 3224b4c80f351f194984526ef396f6079bd6332dd9825c72ac0d7a37b3cdc565 || goto error
|
||||
call :downloadfile "zlib%ZLIBSHORT%.zip" "https://github.com/madler/zlib/releases/download/v%ZLIB%/zlib%ZLIBSHORT%.zip" e8bf55f3017aa181690990cb58a994e77885da140609fc8f94abe9b65d2cae28 || goto error
|
||||
call :downloadfile "zstd-%ZSTD%.zip" "https://github.com/facebook/zstd/archive/refs/tags/v%ZSTD%.zip" 7897bc5d620580d9b7cd3539c44b59d78f3657d33663fe97a145e07b4ebd69a4 || goto error
|
||||
@@ -129,6 +130,7 @@ call :downloadfile "KDDockWidgets-%KDDOCKWIDGETS%.zip" "https://github.com/KDAB/
|
||||
call :downloadfile "plutovg-%PLUTOVG%.zip" "https://github.com/sammycage/plutovg/archive/v%PLUTOVG%.zip" 4fe4e48f28aa80171b2166d45c0976ab0f21eecedb52cd4c3ef73b5afb48fac9 || goto error
|
||||
call :downloadfile "plutosvg-%PLUTOSVG%.zip" "https://github.com/sammycage/plutosvg/archive/v%PLUTOSVG%.zip" 82dee2c57ad712bdd6d6d81d3e76249d89caa4b5a4214353660fd5adff12201a || goto error
|
||||
call :downloadfile "agility-sdk-%AGILITYSDK%.nupkg" "https://www.nuget.org/api/v2/package/Microsoft.Direct3D.D3D12/%AGILITYSDK%" eb92d90bb23b2ec23410c41d791e41dbdbec942ab946924d1fdcb31eac6f0735 || goto error
|
||||
call :downloadfile "DirectX-Headers-%DXHEADERS%.zip" "https://github.com/microsoft/DirectX-Headers/archive/v%DXHEADERS%.zip" 9eb8b102a90a42e4ea72a825f7d249d55ec90d164f030966c9b7784b93374927 || goto error
|
||||
call :downloadfile "rapidyaml-%RAPIDYAML%-src.zip" "https://github.com/biojppm/rapidyaml/releases/download/v%RAPIDYAML%/rapidyaml-%RAPIDYAML%-src.zip" 96276f55b9fa7837ac8f3f72fd52965879cbb5d5d2e6af548c69a177fb078304 || goto error
|
||||
|
||||
call :downloadfile "shaderc-%SHADERC%.zip" "https://github.com/google/shaderc/archive/refs/tags/v%SHADERC%.zip" f9401cc5cb36c276cd1e072b6595dbd728148e8dba389e50f7339e2d388dbc08 || goto error
|
||||
@@ -506,6 +508,16 @@ if %DEBUG%==1 (
|
||||
)
|
||||
cd .. || goto error
|
||||
|
||||
rem DirectX Headers include a CMakeList file, which is absent in the Nuget package
|
||||
echo Unpacking DirectX Headers
|
||||
rmdir /S /Q "DirectX-Headers-%DXHEADERS%"
|
||||
%SEVENZIP% x "DirectX-Headers-%DXHEADERS%.zip" || goto error
|
||||
cd "DirectX-Headers-%DXHEADERS%" || goto error
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DDXHEADERS_BUILD_TEST=OFF -DDXHEADERS_BUILD_GOOGLE_TEST=OFF -B build -G Ninja || goto error
|
||||
cmake --build build --parallel || goto error
|
||||
ninja -C build install || goto error
|
||||
cd .. || goto error
|
||||
|
||||
echo Building shaderc...
|
||||
rmdir /S /Q "shaderc-%SHADERC%"
|
||||
%SEVENZIP% x "shaderc-%SHADERC%.zip" || goto error
|
||||
|
||||
@@ -13,10 +13,10 @@ jobs:
|
||||
lint_vs_proj_files:
|
||||
name: Lint VS Project Files
|
||||
if: github.repository != 'PCSX2/pcsx2' || github.event_name == 'pull_request'
|
||||
runs-on: windows-2025
|
||||
runs-on: windows-2025-vs2026
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
- name: Verify VS Project Files
|
||||
run: .github\workflows\scripts\windows\validate-vs-filters.ps1
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ on:
|
||||
os:
|
||||
required: false
|
||||
type: string
|
||||
default: windows-2025
|
||||
default: windows-2025-vs2026
|
||||
platform:
|
||||
required: false
|
||||
type: string
|
||||
@@ -56,7 +56,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Configure MSBuild Clang Version
|
||||
if: inputs.configuration != 'CMake'
|
||||
|
||||
Vendored
+2
@@ -361,6 +361,8 @@ enum cpuinfo_uarch {
|
||||
cpuinfo_uarch_raptor_cove = 0x0010020F,
|
||||
/** Intel Redwood Cove microarchitecture (Granite Rapids). */
|
||||
cpuinfo_uarch_redwood_cove = 0x00100210,
|
||||
/** Intel Coyote Cove microarchitecture. */
|
||||
cpuinfo_uarch_coyote_cove = 0x00100211,
|
||||
|
||||
/** Pentium 4 with Willamette, Northwood, or Foster cores. */
|
||||
cpuinfo_uarch_willamette = 0x00100300,
|
||||
|
||||
Vendored
+3
@@ -1,3 +1,6 @@
|
||||
/* for syscall() */
|
||||
#define _DEFAULT_SOURCE
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
Vendored
+2
@@ -36,6 +36,7 @@ enum cpuinfo_arm_chipset_vendor {
|
||||
cpuinfo_arm_chipset_vendor_texas_instruments,
|
||||
cpuinfo_arm_chipset_vendor_unisoc,
|
||||
cpuinfo_arm_chipset_vendor_wondermedia,
|
||||
cpuinfo_arm_chipset_vendor_google,
|
||||
cpuinfo_arm_chipset_vendor_max,
|
||||
};
|
||||
|
||||
@@ -73,6 +74,7 @@ enum cpuinfo_arm_chipset_series {
|
||||
cpuinfo_arm_chipset_series_unisoc_t,
|
||||
cpuinfo_arm_chipset_series_unisoc_ums,
|
||||
cpuinfo_arm_chipset_series_wondermedia_wm,
|
||||
cpuinfo_arm_chipset_series_google_tensor,
|
||||
cpuinfo_arm_chipset_series_max,
|
||||
};
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -366,7 +366,7 @@ CPUINFO_INTERNAL struct cpuinfo_arm_chipset cpuinfo_arm_android_decode_chipset_f
|
||||
CPUINFO_INTERNAL struct cpuinfo_arm_chipset cpuinfo_arm_android_decode_chipset_from_ro_hardware_chipname(
|
||||
const char ro_hardware_chipname[restrict static CPUINFO_BUILD_PROP_VALUE_MAX]);
|
||||
CPUINFO_INTERNAL struct cpuinfo_arm_chipset cpuinfo_arm_android_decode_chipset_from_ro_soc_model(
|
||||
const char ro_soc_model[restrict static CPUINFO_BUILD_PROP_VALUE_MAX]);
|
||||
const char soc_model[restrict static CPUINFO_BUILD_PROP_VALUE_MAX]);
|
||||
#else
|
||||
CPUINFO_INTERNAL struct cpuinfo_arm_chipset cpuinfo_arm_linux_decode_chipset_from_proc_cpuinfo_revision(
|
||||
const char proc_cpuinfo_revision[restrict static CPUINFO_REVISION_VALUE_MAX]);
|
||||
|
||||
+61
-10
@@ -3492,9 +3492,20 @@ struct cpuinfo_arm_chipset cpuinfo_arm_android_decode_chipset_from_ro_chipname(
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* Decodes chipset name from ro.soc.model Android system property.
|
||||
*
|
||||
* @param[in] soc_model - ro.soc.model value.
|
||||
*
|
||||
* @returns Decoded chipset name. If chipset could not be decoded, the resulting
|
||||
* structure would use `unknown` vendor and series identifiers.
|
||||
*/
|
||||
struct cpuinfo_arm_chipset cpuinfo_arm_android_decode_chipset_from_ro_soc_model(
|
||||
const char soc_model[restrict static CPUINFO_BUILD_PROP_VALUE_MAX]) {
|
||||
struct cpuinfo_arm_chipset chipset;
|
||||
struct cpuinfo_arm_chipset chipset = {
|
||||
.vendor = cpuinfo_arm_chipset_vendor_unknown,
|
||||
.series = cpuinfo_arm_chipset_series_unknown,
|
||||
};
|
||||
const size_t soc_model_length = strnlen(soc_model, CPUINFO_BUILD_PROP_VALUE_MAX);
|
||||
const char* soc_model_end = soc_model + soc_model_length;
|
||||
|
||||
@@ -3516,10 +3527,28 @@ struct cpuinfo_arm_chipset cpuinfo_arm_android_decode_chipset_from_ro_soc_model(
|
||||
return chipset;
|
||||
}
|
||||
|
||||
return (struct cpuinfo_arm_chipset){
|
||||
.vendor = cpuinfo_arm_chipset_vendor_unknown,
|
||||
.series = cpuinfo_arm_chipset_series_unknown,
|
||||
};
|
||||
if (soc_model[0] != '\0') {
|
||||
if (strncmp(soc_model, "Tensor", 6) == 0) {
|
||||
chipset.vendor = cpuinfo_arm_chipset_vendor_google;
|
||||
chipset.series = cpuinfo_arm_chipset_series_google_tensor;
|
||||
const char* suffix_start = soc_model + 6;
|
||||
while (*suffix_start == ' ') {
|
||||
suffix_start++;
|
||||
}
|
||||
const size_t suffix_length = strnlen(suffix_start, CPUINFO_ARM_CHIPSET_SUFFIX_MAX);
|
||||
if (suffix_length > 0) {
|
||||
strncpy(chipset.suffix, suffix_start, suffix_length);
|
||||
}
|
||||
return chipset;
|
||||
} else if (strncmp(soc_model, "GS201", 5) == 0) {
|
||||
chipset.vendor = cpuinfo_arm_chipset_vendor_google;
|
||||
chipset.series = cpuinfo_arm_chipset_series_google_tensor;
|
||||
strncpy(chipset.suffix, "G2", 2);
|
||||
return chipset;
|
||||
}
|
||||
}
|
||||
|
||||
return chipset;
|
||||
}
|
||||
#endif /* __ANDROID__ */
|
||||
|
||||
@@ -3858,6 +3887,7 @@ static const char* chipset_vendor_string[cpuinfo_arm_chipset_vendor_max] = {
|
||||
[cpuinfo_arm_chipset_vendor_texas_instruments] = "Texas Instruments",
|
||||
[cpuinfo_arm_chipset_vendor_unisoc] = "Unisoc",
|
||||
[cpuinfo_arm_chipset_vendor_wondermedia] = "WonderMedia",
|
||||
[cpuinfo_arm_chipset_vendor_google] = "Google",
|
||||
};
|
||||
|
||||
/* Map from ARM chipset series ID to its string representation */
|
||||
@@ -3895,6 +3925,7 @@ static const char* chipset_series_string[cpuinfo_arm_chipset_series_max] = {
|
||||
[cpuinfo_arm_chipset_series_unisoc_t] = "T",
|
||||
[cpuinfo_arm_chipset_series_unisoc_ums] = "UMS",
|
||||
[cpuinfo_arm_chipset_series_wondermedia_wm] = "WM",
|
||||
[cpuinfo_arm_chipset_series_google_tensor] = "Tensor",
|
||||
};
|
||||
|
||||
/* Convert chipset name represented by cpuinfo_arm_chipset structure to a string
|
||||
@@ -3913,14 +3944,35 @@ void cpuinfo_arm_chipset_to_string(
|
||||
const char* vendor_string = chipset_vendor_string[vendor];
|
||||
const char* series_string = chipset_series_string[series];
|
||||
const uint32_t model = chipset->model;
|
||||
const size_t suffix_length = strnlen(chipset->suffix, CPUINFO_ARM_CHIPSET_SUFFIX_MAX);
|
||||
if (model == 0) {
|
||||
if (series == cpuinfo_arm_chipset_series_unknown) {
|
||||
strncpy(name, vendor_string, CPUINFO_ARM_CHIPSET_NAME_MAX);
|
||||
if (suffix_length > 0) {
|
||||
if (series == cpuinfo_arm_chipset_series_unknown) {
|
||||
snprintf(
|
||||
name,
|
||||
CPUINFO_ARM_CHIPSET_NAME_MAX,
|
||||
"%s %.*s",
|
||||
vendor_string,
|
||||
(int)suffix_length,
|
||||
chipset->suffix);
|
||||
} else {
|
||||
snprintf(
|
||||
name,
|
||||
CPUINFO_ARM_CHIPSET_NAME_MAX,
|
||||
"%s %s %.*s",
|
||||
vendor_string,
|
||||
series_string,
|
||||
(int)suffix_length,
|
||||
chipset->suffix);
|
||||
}
|
||||
} else {
|
||||
snprintf(name, CPUINFO_ARM_CHIPSET_NAME_MAX, "%s %s", vendor_string, series_string);
|
||||
if (series == cpuinfo_arm_chipset_series_unknown) {
|
||||
strncpy(name, vendor_string, CPUINFO_ARM_CHIPSET_NAME_MAX);
|
||||
} else {
|
||||
snprintf(name, CPUINFO_ARM_CHIPSET_NAME_MAX, "%s %s", vendor_string, series_string);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const size_t suffix_length = strnlen(chipset->suffix, CPUINFO_ARM_CHIPSET_SUFFIX_MAX);
|
||||
snprintf(
|
||||
name,
|
||||
CPUINFO_ARM_CHIPSET_NAME_MAX,
|
||||
@@ -4051,7 +4103,6 @@ static enum cpuinfo_arm_chipset_vendor disambiguate_chipset_vendor(
|
||||
(vendor_a == cpuinfo_arm_chipset_vendor_spreadtrum && vendor_b == cpuinfo_arm_chipset_vendor_unisoc)) {
|
||||
return cpuinfo_arm_chipset_vendor_unisoc;
|
||||
}
|
||||
|
||||
return cpuinfo_arm_chipset_vendor_unknown;
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -256,12 +256,12 @@ void cpuinfo_arm_linux_init(void) {
|
||||
}
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
struct cpuinfo_android_properties android_properties;
|
||||
struct cpuinfo_android_properties android_properties = {0};
|
||||
cpuinfo_arm_android_parse_properties(&android_properties);
|
||||
#else
|
||||
char proc_cpuinfo_hardware[CPUINFO_HARDWARE_VALUE_MAX];
|
||||
char proc_cpuinfo_hardware[CPUINFO_HARDWARE_VALUE_MAX] = {0};
|
||||
#endif
|
||||
char proc_cpuinfo_revision[CPUINFO_REVISION_VALUE_MAX];
|
||||
char proc_cpuinfo_revision[CPUINFO_REVISION_VALUE_MAX] = {0};
|
||||
|
||||
if (!cpuinfo_arm_linux_parse_proc_cpuinfo(
|
||||
#if defined(__ANDROID__)
|
||||
|
||||
Vendored
+49
@@ -11,6 +11,11 @@ void cpuinfo_arm_decode_vendor_uarch(
|
||||
#endif /* CPUINFO_ARCH_ARM */
|
||||
enum cpuinfo_vendor vendor[RESTRICT_STATIC 1],
|
||||
enum cpuinfo_uarch uarch[RESTRICT_STATIC 1]) {
|
||||
/* Ensure the out-parameters are always initialized, including for
|
||||
* implementers that are not handled in the switch below. */
|
||||
*vendor = cpuinfo_vendor_unknown;
|
||||
*uarch = cpuinfo_uarch_unknown;
|
||||
|
||||
switch (midr_get_implementer(midr)) {
|
||||
case 'A':
|
||||
*vendor = cpuinfo_vendor_arm;
|
||||
@@ -438,6 +443,50 @@ void cpuinfo_arm_decode_vendor_uarch(
|
||||
midr_get_part(midr));
|
||||
}
|
||||
break;
|
||||
case 'a':
|
||||
*vendor = cpuinfo_vendor_apple;
|
||||
switch (midr_get_part(midr)) {
|
||||
case 0x022:
|
||||
case 0x024:
|
||||
case 0x028:
|
||||
*uarch = cpuinfo_uarch_icestorm;
|
||||
break;
|
||||
case 0x023:
|
||||
case 0x025:
|
||||
case 0x029:
|
||||
*uarch = cpuinfo_uarch_firestorm;
|
||||
break;
|
||||
case 0x032:
|
||||
case 0x034:
|
||||
case 0x038:
|
||||
*uarch = cpuinfo_uarch_blizzard;
|
||||
break;
|
||||
case 0x033:
|
||||
case 0x035:
|
||||
case 0x039:
|
||||
*uarch = cpuinfo_uarch_avalanche;
|
||||
break;
|
||||
case 0x042:
|
||||
case 0x044:
|
||||
case 0x048:
|
||||
*uarch = cpuinfo_uarch_coll_sawtooth;
|
||||
break;
|
||||
case 0x043:
|
||||
case 0x045:
|
||||
case 0x049:
|
||||
*uarch = cpuinfo_uarch_coll_everest;
|
||||
break;
|
||||
case 0x052:
|
||||
*uarch = cpuinfo_uarch_donan_sawtooth;
|
||||
break;
|
||||
case 0x053:
|
||||
*uarch = cpuinfo_uarch_donan_everest;
|
||||
break;
|
||||
default:
|
||||
cpuinfo_log_warning(
|
||||
"unknown Apple CPU part 0x%03" PRIx32 " ignored", midr_get_part(midr));
|
||||
}
|
||||
break;
|
||||
#if CPUINFO_ARCH_ARM
|
||||
case 'V':
|
||||
*vendor = cpuinfo_vendor_marvell;
|
||||
|
||||
Vendored
+9
@@ -307,6 +307,15 @@ static bool transform_token(char* token_start, char* token_end, struct parser_st
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
/*
|
||||
* Erase everything starting with "with" on AMD
|
||||
* processors, e.g. "AMD Ryzen 5 PRO 6650U with Radeon
|
||||
* Graphics"
|
||||
*/
|
||||
if (erase_matching(token_start, token_length, "with")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Remember to erase "Dual Core" in "AMD Athlon(tm) 64
|
||||
* X2 Dual Core Processor 3800+" */
|
||||
if (memcmp(token_start, "Dual", token_length) == 0) {
|
||||
|
||||
Vendored
+7
@@ -270,8 +270,15 @@ enum cpuinfo_uarch cpuinfo_x86_decode_uarch(
|
||||
return cpuinfo_uarch_prescott;
|
||||
}
|
||||
break;
|
||||
case 0x12:
|
||||
switch (model_info->model) {
|
||||
case 0x01: // Nova Lake P-core (Coyote Cove)
|
||||
return cpuinfo_uarch_coyote_cove;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case cpuinfo_vendor_amd:
|
||||
switch (model_info->family) {
|
||||
#if CPUINFO_ARCH_X86
|
||||
|
||||
-2
@@ -265,8 +265,6 @@ BOOL CALLBACK cpuinfo_x86_windows_init(PINIT_ONCE init_once, PVOID parameter, PV
|
||||
* APIC order */
|
||||
const uint32_t core_id = cores_count++;
|
||||
uint32_t smt_id = 0;
|
||||
/* Reconstruct core part of APIC ID */
|
||||
const uint32_t core_apic_id = (core_id & core_bits_mask) << x86_processor.topology.core_bits_offset;
|
||||
/* Iterate processor groups and set the core & SMT parts of APIC
|
||||
* ID */
|
||||
for (uint32_t i = 0; i < core_info->Processor.GroupCount; i++) {
|
||||
|
||||
+2
@@ -3,5 +3,7 @@ add_library(D3D12MemAlloc
|
||||
src/D3D12MemAlloc.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(D3D12MemAlloc PRIVATE Microsoft::DirectX-Headers)
|
||||
|
||||
target_include_directories(D3D12MemAlloc PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
|
||||
disable_compiler_warnings_for_target(D3D12MemAlloc)
|
||||
|
||||
+3
-2
@@ -20,6 +20,7 @@
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="..\DefaultProjectRootDir.props" />
|
||||
<Import Project="..\3rdparty.props" />
|
||||
<Import Project="..\..\common\vsprops\DepsDir.props" />
|
||||
<Import Condition="$(Configuration.Contains(Debug))" Project="..\..\common\vsprops\CodeGen_Debug.props" />
|
||||
<Import Condition="$(Configuration.Contains(Devel))" Project="..\..\common\vsprops\CodeGen_Devel.props" />
|
||||
<Import Condition="$(Configuration.Contains(Release))" Project="..\..\common\vsprops\CodeGen_Release.props" />
|
||||
@@ -37,9 +38,9 @@
|
||||
</ItemGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>D3D12MA_USING_DIRECTX_HEADERS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<WarningLevel>TurnOffAllWarnings</WarningLevel>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)include;$(ProjectDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(DepsIncludeDir);$(ProjectDir)include;$(ProjectDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
|
||||
+12
-3
@@ -24,7 +24,7 @@
|
||||
|
||||
/** \mainpage D3D12 Memory Allocator
|
||||
|
||||
<b>Version 3.1.0</b> (2026-02-23)
|
||||
<b>Version 3.2.0</b> (2026-06-05)
|
||||
|
||||
Copyright (c) 2019-2026 Advanced Micro Devices, Inc. All rights reserved. \n
|
||||
License: MIT
|
||||
@@ -889,10 +889,17 @@ enum POOL_FLAGS
|
||||
*/
|
||||
POOL_FLAG_MSAA_TEXTURES_ALWAYS_COMMITTED = 0x2,
|
||||
/** Every allocation made in this pool will be created as a committed resource - will have its own memory block.
|
||||
|
||||
|
||||
There is also an equivalent flag for the entire allocator: D3D12MA::ALLOCATOR_FLAG_ALWAYS_COMMITTED.
|
||||
*/
|
||||
POOL_FLAG_ALWAYS_COMMITTED = 0x4,
|
||||
/** Disables tight resource alignment for all resources created from this pool.
|
||||
|
||||
When tight alignment is supported and enabled for the allocator, resources created from custom pools
|
||||
normally use it automatically. Specify this flag to restore pre-tight-alignment behavior for this pool:
|
||||
tight alignment won't be requested and small buffers may again be preferred as committed resources.
|
||||
*/
|
||||
POOL_FLAG_DONT_USE_TIGHT_ALIGNMENT = 0x8,
|
||||
|
||||
// Bit mask to extract only `ALGORITHM` bits from entire set of flags.
|
||||
POOL_FLAG_ALGORITHM_MASK = POOL_FLAG_ALGORITHM_LINEAR
|
||||
@@ -1114,7 +1121,8 @@ enum ALLOCATOR_FLAGS
|
||||
It can also be disabled for a single allocation by using #ALLOCATION_FLAG_STRATEGY_MIN_TIME.
|
||||
|
||||
If the tight resource alignment feature is used by the library (which happens automatically whenever supported,
|
||||
unless you use flag #ALLOCATOR_FLAG_DONT_USE_TIGHT_ALIGNMENT), then small buffers are not preferred as committed.
|
||||
unless you use flag #ALLOCATOR_FLAG_DONT_USE_TIGHT_ALIGNMENT or
|
||||
#POOL_FLAG_DONT_USE_TIGHT_ALIGNMENT on a custom pool), then small buffers are not preferred as committed.
|
||||
Long story short, you don't need to specify any of these flags.
|
||||
The library chooses the most optimal method automatically.
|
||||
*/
|
||||
@@ -2892,6 +2900,7 @@ as it is no longer needed.
|
||||
|
||||
You can check if the tight alignment it is available in the current system by calling D3D12MA::Allocator::IsTightAlignmentSupported().
|
||||
You can tell the library to not use it by specifying D3D12MA::ALLOCATOR_FLAG_DONT_USE_TIGHT_ALIGNMENT.
|
||||
Custom pools can opt out independently by specifying D3D12MA::POOL_FLAG_DONT_USE_TIGHT_ALIGNMENT.
|
||||
Typically, you don't need to do any of those.
|
||||
|
||||
The library automatically aligns all buffers to at least 256 B, even when the system supports smaller alignment.
|
||||
|
||||
+249
-57
@@ -163,6 +163,14 @@ especially to test compatibility with D3D12_RESOURCE_HEAP_TIER_1 on modern GPUs.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef D3D12MA_OPTIONS4_SUPPORTED
|
||||
#ifdef __ID3D12Device5_INTERFACE_DEFINED__
|
||||
#define D3D12MA_OPTIONS4_SUPPORTED 1
|
||||
#else
|
||||
#define D3D12MA_OPTIONS4_SUPPORTED 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef D3D12MA_DEBUG_LOG
|
||||
#define D3D12MA_DEBUG_LOG(format, ...)
|
||||
/*
|
||||
@@ -703,6 +711,13 @@ static UINT GetBitsPerPixel(DXGI_FORMAT format)
|
||||
case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
|
||||
case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
|
||||
return 32;
|
||||
case DXGI_FORMAT_B8G8R8A8_UNORM:
|
||||
case DXGI_FORMAT_B8G8R8X8_UNORM:
|
||||
case DXGI_FORMAT_B8G8R8A8_TYPELESS:
|
||||
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
|
||||
case DXGI_FORMAT_B8G8R8X8_TYPELESS:
|
||||
case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
|
||||
return 32;
|
||||
case DXGI_FORMAT_R8G8_TYPELESS:
|
||||
case DXGI_FORMAT_R8G8_UNORM:
|
||||
case DXGI_FORMAT_R8G8_UINT:
|
||||
@@ -717,6 +732,9 @@ static UINT GetBitsPerPixel(DXGI_FORMAT format)
|
||||
case DXGI_FORMAT_R16_SNORM:
|
||||
case DXGI_FORMAT_R16_SINT:
|
||||
return 16;
|
||||
case DXGI_FORMAT_B5G6R5_UNORM:
|
||||
case DXGI_FORMAT_B5G5R5A1_UNORM:
|
||||
return 16;
|
||||
case DXGI_FORMAT_R8_TYPELESS:
|
||||
case DXGI_FORMAT_R8_UNORM:
|
||||
case DXGI_FORMAT_R8_UINT:
|
||||
@@ -767,46 +785,175 @@ static ResourceClass ResourceDescToResourceClass(const D3D12_RESOURCE_DESC_T& re
|
||||
(resDesc.Flags & (D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL)) != 0;
|
||||
return isRenderTargetOrDepthStencil ? ResourceClass::RT_DS_Texture : ResourceClass::Non_RT_DS_Texture;
|
||||
}
|
||||
|
||||
static bool ResourceDimensionIsTexture(D3D12_RESOURCE_DIMENSION dimension)
|
||||
{
|
||||
return dimension == D3D12_RESOURCE_DIMENSION_TEXTURE1D ||
|
||||
dimension == D3D12_RESOURCE_DIMENSION_TEXTURE2D ||
|
||||
dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D;
|
||||
}
|
||||
|
||||
static bool ResourceFlagsContainRenderTargetOrDepthStencil(D3D12_RESOURCE_FLAGS flags)
|
||||
{
|
||||
return (flags & (D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL)) != 0;
|
||||
}
|
||||
|
||||
// This algorithm is overly conservative.
|
||||
struct SmallAlignmentTileShape
|
||||
{
|
||||
UINT Width;
|
||||
UINT Height;
|
||||
UINT Depth;
|
||||
};
|
||||
|
||||
static bool GetSmallAlignmentTileShape(
|
||||
D3D12_RESOURCE_DIMENSION dimension,
|
||||
bool isMsaa,
|
||||
UINT bitsPerUnit,
|
||||
SmallAlignmentTileShape& outTileShape)
|
||||
{
|
||||
if (isMsaa)
|
||||
{
|
||||
if (dimension != D3D12_RESOURCE_DIMENSION_TEXTURE2D)
|
||||
return false;
|
||||
|
||||
switch (bitsPerUnit)
|
||||
{
|
||||
case 8: outTileShape = { 256, 256, 1 }; return true;
|
||||
case 16: outTileShape = { 256, 128, 1 }; return true;
|
||||
case 32: outTileShape = { 128, 128, 1 }; return true;
|
||||
case 64: outTileShape = { 128, 64, 1 }; return true;
|
||||
case 128: outTileShape = { 64, 64, 1 }; return true;
|
||||
case 256: outTileShape = { 64, 32, 1 }; return true;
|
||||
case 512: outTileShape = { 32, 32, 1 }; return true;
|
||||
case 1024: outTileShape = { 32, 16, 1 }; return true;
|
||||
case 2048: outTileShape = { 16, 16, 1 }; return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
switch (dimension)
|
||||
{
|
||||
case D3D12_RESOURCE_DIMENSION_TEXTURE1D:
|
||||
switch (bitsPerUnit)
|
||||
{
|
||||
case 8: outTileShape = { 4096, 1, 1 }; return true;
|
||||
case 16: outTileShape = { 2048, 1, 1 }; return true;
|
||||
case 32: outTileShape = { 1024, 1, 1 }; return true;
|
||||
case 64: outTileShape = { 512, 1, 1 }; return true;
|
||||
case 128: outTileShape = { 256, 1, 1 }; return true;
|
||||
default: return false;
|
||||
}
|
||||
|
||||
case D3D12_RESOURCE_DIMENSION_TEXTURE2D:
|
||||
switch (bitsPerUnit)
|
||||
{
|
||||
case 8: outTileShape = { 64, 64, 1 }; return true;
|
||||
case 16: outTileShape = { 64, 32, 1 }; return true;
|
||||
case 32: outTileShape = { 32, 32, 1 }; return true;
|
||||
case 64: outTileShape = { 32, 16, 1 }; return true;
|
||||
case 128: outTileShape = { 16, 16, 1 }; return true;
|
||||
default: return false;
|
||||
}
|
||||
|
||||
case D3D12_RESOURCE_DIMENSION_TEXTURE3D:
|
||||
// 4 KB counterparts of the documented 64 KB volume-tile shapes.
|
||||
switch (bitsPerUnit)
|
||||
{
|
||||
case 8: outTileShape = { 16, 16, 16 }; return true;
|
||||
case 16: outTileShape = { 16, 16, 8 }; return true;
|
||||
case 32: outTileShape = { 16, 8, 8 }; return true;
|
||||
case 64: outTileShape = { 8, 8, 8 }; return true;
|
||||
case 128: outTileShape = { 8, 8, 4 }; return true;
|
||||
default: return false;
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// This algorithm is overly conservative and applies only to the legacy small-alignment heuristic path.
|
||||
template<typename D3D12_RESOURCE_DESC_T>
|
||||
static bool CanUseSmallAlignment(const D3D12_RESOURCE_DESC_T& resourceDesc)
|
||||
{
|
||||
if (resourceDesc.Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE2D)
|
||||
if (resourceDesc.SampleDesc.Count == 0 ||
|
||||
resourceDesc.Layout != D3D12_TEXTURE_LAYOUT_UNKNOWN ||
|
||||
resourceDesc.Width > UINT_MAX)
|
||||
{
|
||||
return false;
|
||||
if ((resourceDesc.Flags & (D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL)) != 0)
|
||||
}
|
||||
|
||||
const bool isMsaa = resourceDesc.SampleDesc.Count > 1;
|
||||
const bool isRtDs = ResourceFlagsContainRenderTargetOrDepthStencil(resourceDesc.Flags);
|
||||
if (isMsaa && !isRtDs)
|
||||
{
|
||||
return false;
|
||||
if (resourceDesc.SampleDesc.Count > 1)
|
||||
return false;
|
||||
if (resourceDesc.DepthOrArraySize != 1)
|
||||
}
|
||||
if (!isMsaa &&
|
||||
isRtDs)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
UINT sizeX = (UINT)resourceDesc.Width;
|
||||
UINT sizeY = resourceDesc.Height;
|
||||
UINT bitsPerPixel = GetBitsPerPixel(resourceDesc.Format);
|
||||
if (bitsPerPixel == 0)
|
||||
UINT sizeY = 1;
|
||||
UINT sizeZ = 1;
|
||||
UINT bitsPerUnit = GetBitsPerPixel(resourceDesc.Format);
|
||||
if (bitsPerUnit == 0)
|
||||
return false;
|
||||
|
||||
if (IsFormatCompressed(resourceDesc.Format))
|
||||
switch (resourceDesc.Dimension)
|
||||
{
|
||||
sizeX = DivideRoundingUp(sizeX, 4u);
|
||||
sizeY = DivideRoundingUp(sizeY, 4u);
|
||||
bitsPerPixel *= 16;
|
||||
case D3D12_RESOURCE_DIMENSION_TEXTURE1D:
|
||||
if (isMsaa)
|
||||
return false;
|
||||
// For 1D arrays, small-alignment eligibility depends on the mip0 slice size, not array size.
|
||||
if (IsFormatCompressed(resourceDesc.Format))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case D3D12_RESOURCE_DIMENSION_TEXTURE2D:
|
||||
// For 2D arrays, small-alignment eligibility depends on mip0 width/height, not array size.
|
||||
sizeY = resourceDesc.Height;
|
||||
if (isMsaa && IsFormatCompressed(resourceDesc.Format))
|
||||
return false;
|
||||
if (IsFormatCompressed(resourceDesc.Format))
|
||||
{
|
||||
sizeX = DivideRoundingUp(sizeX, 4u);
|
||||
sizeY = DivideRoundingUp(sizeY, 4u);
|
||||
bitsPerUnit *= 16;
|
||||
}
|
||||
break;
|
||||
|
||||
case D3D12_RESOURCE_DIMENSION_TEXTURE3D:
|
||||
if (isMsaa)
|
||||
return false;
|
||||
sizeY = resourceDesc.Height;
|
||||
sizeZ = resourceDesc.DepthOrArraySize;
|
||||
if (IsFormatCompressed(resourceDesc.Format))
|
||||
{
|
||||
sizeX = DivideRoundingUp(sizeX, 4u);
|
||||
sizeY = DivideRoundingUp(sizeY, 4u);
|
||||
bitsPerUnit *= 16;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
UINT tileSizeX = 0, tileSizeY = 0;
|
||||
switch (bitsPerPixel)
|
||||
{
|
||||
case 8: tileSizeX = 64; tileSizeY = 64; break;
|
||||
case 16: tileSizeX = 64; tileSizeY = 32; break;
|
||||
case 32: tileSizeX = 32; tileSizeY = 32; break;
|
||||
case 64: tileSizeX = 32; tileSizeY = 16; break;
|
||||
case 128: tileSizeX = 16; tileSizeY = 16; break;
|
||||
default: return false;
|
||||
}
|
||||
bitsPerUnit *= resourceDesc.SampleDesc.Count;
|
||||
|
||||
const UINT tileCount = DivideRoundingUp(sizeX, tileSizeX) * DivideRoundingUp(sizeY, tileSizeY);
|
||||
return tileCount <= 16;
|
||||
SmallAlignmentTileShape tileShape = {};
|
||||
if (!GetSmallAlignmentTileShape(resourceDesc.Dimension, isMsaa, bitsPerUnit, tileShape))
|
||||
return false;
|
||||
|
||||
const UINT64 tileCount =
|
||||
UINT64(DivideRoundingUp(sizeX, tileShape.Width)) *
|
||||
UINT64(DivideRoundingUp(sizeY, tileShape.Height)) *
|
||||
UINT64(DivideRoundingUp(sizeZ, tileShape.Depth));
|
||||
// Non-MSAA compares 64 KB against 4 KB tiles => 16 pages. MSAA compares 4 MB against 64 KB tiles => 64 pages.
|
||||
return tileCount <= (isMsaa ? 64 : 16);
|
||||
}
|
||||
|
||||
static bool ValidateAllocateMemoryParameters(
|
||||
@@ -5988,6 +6135,7 @@ public:
|
||||
BOOL IsCacheCoherentUMA() const { return m_D3D12Architecture.CacheCoherentUMA; }
|
||||
bool SupportsResourceHeapTier2() const { return m_D3D12Options.ResourceHeapTier >= D3D12_RESOURCE_HEAP_TIER_2; }
|
||||
bool IsGPUUploadHeapSupported() const { return m_GPUUploadHeapSupported != FALSE; }
|
||||
bool IsMsaa64KBAlignedTextureSupported() const { return m_MSAA64KBAlignedTextureSupported != FALSE; }
|
||||
bool IsTightAlignmentSupported() const { return m_TightAlignmentSupported != FALSE; }
|
||||
bool IsTightAlignmentEnabled() const { return IsTightAlignmentSupported() && m_UseTightAlignment; }
|
||||
bool UseMutex() const { return m_UseMutex; }
|
||||
@@ -6076,7 +6224,7 @@ private:
|
||||
const bool m_UseMutex;
|
||||
const bool m_AlwaysCommitted;
|
||||
const bool m_MsaaAlwaysCommitted;
|
||||
bool m_PreferSmallBuffersCommitted;
|
||||
const bool m_PreferSmallBuffersCommitted;
|
||||
const bool m_UseTightAlignment;
|
||||
bool m_DefaultPoolsNotZeroed = false;
|
||||
ID3D12Device* m_Device; // AddRef
|
||||
@@ -6105,6 +6253,7 @@ private:
|
||||
DXGI_ADAPTER_DESC m_AdapterDesc;
|
||||
D3D12_FEATURE_DATA_D3D12_OPTIONS m_D3D12Options;
|
||||
BOOL m_GPUUploadHeapSupported = FALSE;
|
||||
BOOL m_MSAA64KBAlignedTextureSupported = FALSE;
|
||||
BOOL m_TightAlignmentSupported = FALSE;
|
||||
D3D12_FEATURE_DATA_ARCHITECTURE m_D3D12Architecture;
|
||||
AllocationObjectAllocator m_AllocationObjectAllocator;
|
||||
@@ -6121,7 +6270,7 @@ private:
|
||||
*/
|
||||
template<typename D3D12_RESOURCE_DESC_T>
|
||||
bool PrefersCommittedAllocation(const D3D12_RESOURCE_DESC_T& resourceDesc,
|
||||
ALLOCATION_FLAGS strategy);
|
||||
ALLOCATION_FLAGS strategy, bool useTightAlignment) const;
|
||||
|
||||
// Allocates and registers new committed resource with implicit heap, as dedicated allocation.
|
||||
// Creates and returns Allocation object and optionally D3D12 resource.
|
||||
@@ -6141,6 +6290,7 @@ private:
|
||||
template<typename D3D12_RESOURCE_DESC_T>
|
||||
HRESULT CalcAllocationParams(const ALLOCATION_DESC& allocDesc, UINT64 allocSize,
|
||||
const D3D12_RESOURCE_DESC_T* resDesc, // Optional
|
||||
bool useTightAlignment,
|
||||
BlockVector*& outBlockVector, CommittedAllocationParameters& outCommittedAllocationParams, bool& outPreferCommitted);
|
||||
|
||||
// Returns UINT32_MAX if index cannot be calculcated.
|
||||
@@ -6174,7 +6324,10 @@ private:
|
||||
template<typename D3D12_RESOURCE_DESC_T>
|
||||
HRESULT GetResourceAllocationInfo(D3D12_RESOURCE_DESC_T& inOutResourceDesc,
|
||||
UINT32 NumCastableFormats, const DXGI_FORMAT* pCastableFormats,
|
||||
D3D12_RESOURCE_ALLOCATION_INFO& outAllocInfo) const;
|
||||
D3D12_RESOURCE_ALLOCATION_INFO& outAllocInfo,
|
||||
bool useTightAlignment) const;
|
||||
|
||||
bool IsTightAlignmentEnabled(const ALLOCATION_DESC& allocDesc) const;
|
||||
|
||||
bool NewAllocationWithinBudget(D3D12_HEAP_TYPE heapType, UINT64 size);
|
||||
|
||||
@@ -6277,6 +6430,17 @@ HRESULT AllocatorPimpl::Init(const ALLOCATOR_DESC& desc)
|
||||
}
|
||||
#endif // #if D3D12MA_OPTIONS16_SUPPORTED
|
||||
|
||||
#if D3D12MA_OPTIONS4_SUPPORTED
|
||||
{
|
||||
D3D12_FEATURE_DATA_D3D12_OPTIONS4 options4 = {};
|
||||
hr = m_Device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS4, &options4, sizeof(options4));
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
m_MSAA64KBAlignedTextureSupported = options4.MSAA64KBAlignedTextureSupported;
|
||||
}
|
||||
}
|
||||
#endif // #if D3D12MA_OPTIONS4_SUPPORTED
|
||||
|
||||
#if D3D12MA_TIGHT_ALIGNMENT_SUPPORTED
|
||||
{
|
||||
D3D12_FEATURE_DATA_TIGHT_ALIGNMENT tightAlignment = {};
|
||||
@@ -6285,13 +6449,6 @@ HRESULT AllocatorPimpl::Init(const ALLOCATOR_DESC& desc)
|
||||
{
|
||||
m_TightAlignmentSupported = tightAlignment.SupportTier >= D3D12_TIGHT_ALIGNMENT_TIER_1;
|
||||
|
||||
// If tight alignment is supported (checked by the code above) and wasn't disabled by the developer
|
||||
// (with ALLOCATOR_FLAG_DONT_USE_TIGHT_ALIGNMENT), disable the preference for creating small buffers as committed,
|
||||
// as if ALLOCATOR_FLAG_DONT_PREFER_SMALL_BUFFERS_COMMITTED was specified.
|
||||
if (IsTightAlignmentEnabled())
|
||||
{
|
||||
m_PreferSmallBuffersCommitted = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // #if D3D12MA_TIGHT_ALIGNMENT_SUPPORTED
|
||||
@@ -6490,6 +6647,7 @@ HRESULT AllocatorPimpl::CreateResource(
|
||||
}
|
||||
|
||||
HRESULT hr = E_NOINTERFACE;
|
||||
const bool useTightAlignment = IsTightAlignmentEnabled(*pAllocDesc);
|
||||
CREATE_RESOURCE_PARAMS finalCreateParams = createParams;
|
||||
D3D12_RESOURCE_DESC finalResourceDesc;
|
||||
#ifdef __ID3D12Device8_INTERFACE_DEFINED__
|
||||
@@ -6500,7 +6658,7 @@ HRESULT AllocatorPimpl::CreateResource(
|
||||
{
|
||||
finalResourceDesc = *createParams.GetResourceDesc();
|
||||
finalCreateParams.AccessResourceDesc() = &finalResourceDesc;
|
||||
hr = GetResourceAllocationInfo(finalResourceDesc, 0, NULL, resAllocInfo);
|
||||
hr = GetResourceAllocationInfo(finalResourceDesc, 0, NULL, resAllocInfo, useTightAlignment);
|
||||
}
|
||||
#ifdef __ID3D12Device8_INTERFACE_DEFINED__
|
||||
else if (createParams.Variant == CREATE_RESOURCE_PARAMS::VARIANT_WITH_STATE_AND_DESC1)
|
||||
@@ -6509,7 +6667,7 @@ HRESULT AllocatorPimpl::CreateResource(
|
||||
{
|
||||
finalResourceDesc1 = *createParams.GetResourceDesc1();
|
||||
finalCreateParams.AccessResourceDesc1() = &finalResourceDesc1;
|
||||
hr = GetResourceAllocationInfo(finalResourceDesc1, 0, NULL, resAllocInfo);
|
||||
hr = GetResourceAllocationInfo(finalResourceDesc1, 0, NULL, resAllocInfo, useTightAlignment);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -6521,7 +6679,7 @@ HRESULT AllocatorPimpl::CreateResource(
|
||||
finalResourceDesc1 = *createParams.GetResourceDesc1();
|
||||
finalCreateParams.AccessResourceDesc1() = &finalResourceDesc1;
|
||||
hr = GetResourceAllocationInfo(finalResourceDesc1,
|
||||
createParams.GetNumCastableFormats(), createParams.GetCastableFormats(), resAllocInfo);
|
||||
createParams.GetNumCastableFormats(), createParams.GetCastableFormats(), resAllocInfo, useTightAlignment);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -6547,14 +6705,14 @@ HRESULT AllocatorPimpl::CreateResource(
|
||||
if (createParams.Variant >= CREATE_RESOURCE_PARAMS::VARIANT_WITH_STATE_AND_DESC1)
|
||||
{
|
||||
hr = CalcAllocationParams<D3D12_RESOURCE_DESC1>(*pAllocDesc, resAllocInfo.SizeInBytes,
|
||||
createParams.GetResourceDesc1(),
|
||||
createParams.GetResourceDesc1(), useTightAlignment,
|
||||
blockVector, committedAllocationParams, preferCommitted);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
hr = CalcAllocationParams<D3D12_RESOURCE_DESC>(*pAllocDesc, resAllocInfo.SizeInBytes,
|
||||
createParams.GetResourceDesc(),
|
||||
createParams.GetResourceDesc(), useTightAlignment,
|
||||
blockVector, committedAllocationParams, preferCommitted);
|
||||
}
|
||||
if (FAILED(hr))
|
||||
@@ -6601,6 +6759,7 @@ HRESULT AllocatorPimpl::AllocateMemory(
|
||||
bool preferCommitted = false;
|
||||
HRESULT hr = CalcAllocationParams<D3D12_RESOURCE_DESC>(*pAllocDesc, pAllocInfo->SizeInBytes,
|
||||
NULL, // pResDesc
|
||||
false, // useTightAlignment - irrelevant for AllocateMemory
|
||||
blockVector, committedAllocationParams, preferCommitted);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
@@ -6649,7 +6808,7 @@ HRESULT AllocatorPimpl::CreateAliasingResource(
|
||||
{
|
||||
finalResourceDesc = *createParams.GetResourceDesc();
|
||||
finalCreateParams.AccessResourceDesc() = &finalResourceDesc;
|
||||
hr = GetResourceAllocationInfo(finalResourceDesc, 0, NULL, resAllocInfo);
|
||||
hr = GetResourceAllocationInfo(finalResourceDesc, 0, NULL, resAllocInfo, IsTightAlignmentEnabled());
|
||||
}
|
||||
#ifdef __ID3D12Device8_INTERFACE_DEFINED__
|
||||
else if (createParams.Variant == CREATE_RESOURCE_PARAMS::VARIANT_WITH_STATE_AND_DESC1)
|
||||
@@ -6658,7 +6817,7 @@ HRESULT AllocatorPimpl::CreateAliasingResource(
|
||||
{
|
||||
finalResourceDesc1 = *createParams.GetResourceDesc1();
|
||||
finalCreateParams.AccessResourceDesc1() = &finalResourceDesc1;
|
||||
hr = GetResourceAllocationInfo(finalResourceDesc1, 0, NULL, resAllocInfo);
|
||||
hr = GetResourceAllocationInfo(finalResourceDesc1, 0, NULL, resAllocInfo, IsTightAlignmentEnabled());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -6670,7 +6829,7 @@ HRESULT AllocatorPimpl::CreateAliasingResource(
|
||||
finalResourceDesc1 = *createParams.GetResourceDesc1();
|
||||
finalCreateParams.AccessResourceDesc1() = &finalResourceDesc1;
|
||||
hr = GetResourceAllocationInfo(finalResourceDesc1,
|
||||
createParams.GetNumCastableFormats(), createParams.GetCastableFormats(), resAllocInfo);
|
||||
createParams.GetNumCastableFormats(), createParams.GetCastableFormats(), resAllocInfo, IsTightAlignmentEnabled());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -7305,13 +7464,14 @@ void AllocatorPimpl::FreeStatsString(WCHAR* pStatsString)
|
||||
|
||||
template<typename D3D12_RESOURCE_DESC_T>
|
||||
bool AllocatorPimpl::PrefersCommittedAllocation(const D3D12_RESOURCE_DESC_T& resourceDesc,
|
||||
ALLOCATION_FLAGS strategy)
|
||||
ALLOCATION_FLAGS strategy, bool useTightAlignment) const
|
||||
{
|
||||
// Prefer creating small buffers <= 32 KB as committed, because drivers pack them better,
|
||||
// while placed buffers require 64 KB alignment.
|
||||
if(resourceDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER &&
|
||||
resourceDesc.Width <= D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT / 2 &&
|
||||
strategy != ALLOCATION_FLAG_STRATEGY_MIN_TIME && // Creating as committed would be slower.
|
||||
!useTightAlignment &&
|
||||
m_PreferSmallBuffersCommitted)
|
||||
{
|
||||
return true;
|
||||
@@ -7526,7 +7686,7 @@ HRESULT AllocatorPimpl::AllocateHeap(
|
||||
|
||||
template<typename D3D12_RESOURCE_DESC_T>
|
||||
HRESULT AllocatorPimpl::CalcAllocationParams(const ALLOCATION_DESC& allocDesc, UINT64 allocSize,
|
||||
const D3D12_RESOURCE_DESC_T* resDesc,
|
||||
const D3D12_RESOURCE_DESC_T* resDesc, bool useTightAlignment,
|
||||
BlockVector*& outBlockVector, CommittedAllocationParameters& outCommittedAllocationParams, bool& outPreferCommitted)
|
||||
{
|
||||
outBlockVector = NULL;
|
||||
@@ -7599,7 +7759,7 @@ HRESULT AllocatorPimpl::CalcAllocationParams(const ALLOCATION_DESC& allocDesc, U
|
||||
{
|
||||
if (resDesc->SampleDesc.Count > 1 && msaaAlwaysCommitted)
|
||||
outBlockVector = NULL;
|
||||
if (!outPreferCommitted && PrefersCommittedAllocation(*resDesc, allocDesc.Flags & ALLOCATION_FLAG_STRATEGY_MASK))
|
||||
if (!outPreferCommitted && PrefersCommittedAllocation(*resDesc, allocDesc.Flags & ALLOCATION_FLAG_STRATEGY_MASK, useTightAlignment))
|
||||
outPreferCommitted = true;
|
||||
}
|
||||
|
||||
@@ -7810,12 +7970,13 @@ template<typename D3D12_RESOURCE_DESC_T>
|
||||
HRESULT AllocatorPimpl::GetResourceAllocationInfo(
|
||||
D3D12_RESOURCE_DESC_T& inOutResourceDesc,
|
||||
UINT32 NumCastableFormats, const DXGI_FORMAT* pCastableFormats,
|
||||
D3D12_RESOURCE_ALLOCATION_INFO& outAllocInfo) const
|
||||
D3D12_RESOURCE_ALLOCATION_INFO& outAllocInfo,
|
||||
bool useTightAlignment) const
|
||||
{
|
||||
#ifdef __ID3D12Device1_INTERFACE_DEFINED__
|
||||
|
||||
#if D3D12MA_TIGHT_ALIGNMENT_SUPPORTED
|
||||
if (IsTightAlignmentEnabled())
|
||||
if (useTightAlignment)
|
||||
{
|
||||
// Don't allow USE_TIGHT_ALIGNMENT together with ALLOW_CROSS_ADAPTER as there is a D3D Debug Layer error:
|
||||
// D3D12 ERROR: ID3D12Device::GetResourceAllocationInfo: D3D12_RESOURCE_DESC::Flag D3D12_RESOURCE_FLAG_USE_TIGHT_ALIGNMENT will be ignored since D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER is set. [ STATE_CREATION ERROR #599: CREATERESOURCE_INVALIDMISCFLAGS]
|
||||
@@ -7839,7 +8000,7 @@ HRESULT AllocatorPimpl::GetResourceAllocationInfo(
|
||||
*/
|
||||
if (inOutResourceDesc.Alignment == 0 &&
|
||||
inOutResourceDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER &&
|
||||
!IsTightAlignmentEnabled())
|
||||
!useTightAlignment)
|
||||
{
|
||||
outAllocInfo = {
|
||||
AlignUp<UINT64>(inOutResourceDesc.Width, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT), // SizeInBytes
|
||||
@@ -7852,16 +8013,33 @@ HRESULT AllocatorPimpl::GetResourceAllocationInfo(
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
#if D3D12MA_USE_SMALL_RESOURCE_PLACEMENT_ALIGNMENT
|
||||
if (inOutResourceDesc.Alignment == 0 &&
|
||||
(inOutResourceDesc.Flags & D3D12_RESOURCE_FLAG_USE_TIGHT_ALIGNMENT_COPY) == 0 &&
|
||||
(inOutResourceDesc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE1D ||
|
||||
inOutResourceDesc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE2D ||
|
||||
inOutResourceDesc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D) &&
|
||||
(inOutResourceDesc.Flags & (D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL)) == 0
|
||||
bool trySmallAlignment = false;
|
||||
|
||||
if (inOutResourceDesc.Alignment == 0
|
||||
&& (inOutResourceDesc.Flags & D3D12_RESOURCE_FLAG_USE_TIGHT_ALIGNMENT_COPY) == 0
|
||||
&& inOutResourceDesc.Layout == D3D12_TEXTURE_LAYOUT_UNKNOWN
|
||||
&& ResourceDimensionIsTexture(inOutResourceDesc.Dimension))
|
||||
{
|
||||
// MSAA texture.
|
||||
if(inOutResourceDesc.SampleDesc.Count > 1)
|
||||
{
|
||||
trySmallAlignment = IsMsaa64KBAlignedTextureSupported()
|
||||
&& ResourceFlagsContainRenderTargetOrDepthStencil(inOutResourceDesc.Flags)
|
||||
&& inOutResourceDesc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
||||
}
|
||||
// Non-MSAA texture.
|
||||
else
|
||||
{
|
||||
trySmallAlignment = !ResourceFlagsContainRenderTargetOrDepthStencil(inOutResourceDesc.Flags);
|
||||
}
|
||||
}
|
||||
|
||||
#if D3D12MA_USE_SMALL_RESOURCE_PLACEMENT_ALIGNMENT == 1
|
||||
&& CanUseSmallAlignment(inOutResourceDesc)
|
||||
if(trySmallAlignment)
|
||||
trySmallAlignment = CanUseSmallAlignment(inOutResourceDesc);
|
||||
#endif
|
||||
)
|
||||
|
||||
if (trySmallAlignment)
|
||||
{
|
||||
/*
|
||||
The algorithm here is based on Microsoft sample: "Small Resources Sample"
|
||||
@@ -7886,6 +8064,20 @@ HRESULT AllocatorPimpl::GetResourceAllocationInfo(
|
||||
inOutResourceDesc, NumCastableFormats, pCastableFormats, outAllocInfo);
|
||||
}
|
||||
|
||||
bool AllocatorPimpl::IsTightAlignmentEnabled(const ALLOCATION_DESC& allocDesc) const
|
||||
{
|
||||
if (!IsTightAlignmentEnabled())
|
||||
return false;
|
||||
|
||||
if (allocDesc.CustomPool != NULL &&
|
||||
(allocDesc.CustomPool->m_Pimpl->GetDesc().Flags & POOL_FLAG_DONT_USE_TIGHT_ALIGNMENT) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AllocatorPimpl::NewAllocationWithinBudget(D3D12_HEAP_TYPE heapType, UINT64 size)
|
||||
{
|
||||
Budget budget = {};
|
||||
|
||||
Vendored
+191
@@ -39,6 +39,197 @@ HOW TO UPDATE?
|
||||
and API updates have been a little more frequent lately. They are documented below and in imgui.cpp and should not affect all users.
|
||||
- Please report any issue!
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
VERSION 1.92.8 (Released 2026-05-12)
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.92.8
|
||||
|
||||
Breaking Changes:
|
||||
|
||||
- DrawList: swapped the last two arguments of `AddRect()`, `AddPolyline()`, `PathStroke()`.
|
||||
- Before: `void ImDrawList::AddRect(ImVec2 p_min, ImVec2 p_max, ImU32 col, float rounding = 0.0f, ImDrawFlags flags = 0, float thickness = 1.0f);`
|
||||
- After: `void ImDrawList::AddRect(ImVec2 p_min, ImVec2 p_max, ImU32 col, float rounding = 0.0f, float thickness = 1.0f, ImDrawFlags flags = 0);`
|
||||
- Before: `void ImDrawList::AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness);`
|
||||
- After: `void ImDrawList::AddPolyline(const ImVec2* points, int num_points, ImU32 col, float thickness, ImDrawFlags flags = 0);`
|
||||
- Before: `void ImDrawList::PathStroke(ImU32 col, ImDrawFlags flags = 0, float thickness = 1.0f);`
|
||||
- After: `void ImDrawList::PathStroke(ImU32 col, float thickness = 1.0f, ImDrawFlags flags = 0);`
|
||||
Added inline redirection functions when IMGUI_DISABLE_OBSOLETE_FUNCTIONS is off.
|
||||
Marked the old functions are =delete when IMGUI_DISABLE_OBSOLETE_FUNCTIONS is on, to allow for better type-checking.
|
||||
Effectively the typical call site is changing from:
|
||||
- Before: `window->DrawList->AddRect(p_min, p_max, color, rounding, ImDrawFlags_None, border_size);`
|
||||
- After: `window->DrawList->AddRect(p_min, p_max, color, rounding, border_size);`
|
||||
Notes:
|
||||
- Users of C++ and other languages with type-checking will be notified at compile-time of any mistakes.
|
||||
- Users of high-level bindings or languages with no type-checking will be notified at runtime via an assert for invalid flags value.
|
||||
If you are a binding maintainer consider doing something to facilitate transition or error detection.
|
||||
- This is perhaps the worst breaking change in our history :( but it makes ImDrawList function signatures consistent.
|
||||
As we are aiming to add flags and features to variety of ImDrawList functions, that consistency becomes more important.
|
||||
The new order is also more convenient as `flags` are less frequently used than `thickness` in real code.
|
||||
- As a general policy in Dear ImGui, all our flags default to 0 so ImDrawFlags_None was likely written 0 in some call sites.
|
||||
- Consider adding `#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS` in your imconfig.h, even temporarily, to clean up legacy code.
|
||||
- DrawList: obsoleted `ImDrawCallback_ResetRenderState` in favor of using `ImGui::GetPlatformIO().DrawCallback_ResetRenderState`,
|
||||
which is part of our new standard draw callbacks. (#9378)
|
||||
Redirecting the earlier value into the later one when set, so both old and new code should work.
|
||||
- Backends:
|
||||
- Vulkan: redesigned to use separate ImageView + Sampler instead of Combined Image Sampler. (#914)
|
||||
This change allows us to facilitate changing samplers, in line with other backends. [@yaz0r, @ocornut]
|
||||
- When creating your own descriptor pool (instead of letting backend creates its own):
|
||||
- Before: need at least `IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE` descriptors of type `VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER`.
|
||||
- After: need at least `IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE` descriptors of type `VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE`.
|
||||
+ `IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE` descriptors of type `VK_DESCRIPTOR_TYPE_SAMPLER`.
|
||||
- When registering custom textures: changed ImGui_ImplVulkan_AddTexture() signature to remove Sampler.
|
||||
- Before: `ImGui_ImplVulkan_AddTexture(VkSampler, VkImageView, VkImageLayout)`
|
||||
- After: `ImGui_ImplVulkan_AddTexture(VkImageView, VkImageLayout)`
|
||||
- Kept inline redirection function that ignores the sampler (will obsolete).
|
||||
- DirectX10, DirectX11, SDLGPU3, Vulkan: removed samplers from `ImGui_ImplXXXX_RenderState`.
|
||||
Prefer to use backend-agnostic DrawCallback_SetSamplerLinear which works everywhere! (#9378)
|
||||
If there is a legit need/request for them or any render state we can always add them back.
|
||||
|
||||
Other Changes:
|
||||
|
||||
- DrawList:
|
||||
- Added room in `ImGuiPlatformIO` for standard backend-agnostic draw callbacks. Those callbacks
|
||||
are setup/provided by the backend and available in most of our standard backends.
|
||||
They allow backend-agnostic code from e.g. switching to a Nearest/Point sampler without
|
||||
messing with custom Renderer-specific callbacks.
|
||||
platform_io.DrawCallback_ResetRenderState; // Request to reset the graphics/render state.
|
||||
platform_io.DrawCallback_SetSamplerLinear; // Request to set current texture sampling to Linear
|
||||
platform_io.DrawCallback_SetSamplerNearest; // Request to set current texture sampling to Nearest/Point
|
||||
Note that some backends might not support all callbacks.
|
||||
(#9378, #9371, #3590, #8926, #2973, #7485, #7468, #6969, #5118, #7616, #9173, #8322, #7230,
|
||||
#5999, #6452, #5156, #7342, #7592, #7511)
|
||||
- Made `AddCallback()` user data default to Null for convenience.
|
||||
- Added `AddLineH()`, `AddLineV()` helpers to draw horizontal and vertical lines. [@memononen]
|
||||
- InputText:
|
||||
- InputTextMultiline: fixed an issue processing deactivation logic when an active
|
||||
multi-line edit is clipped due to being out of view.
|
||||
- Fixed a crash when toggling ReadOnly while active. (#9354)
|
||||
- `CharFilter` callback event sets CursorPos/SelectionStart/SelectionEnd. (#816)
|
||||
- Tables:
|
||||
- Fixed issues reporting ideal size to parent window/container: (#9352, #7651)
|
||||
- When both scrollbars are visible but only one of ScrollX/ScrollY was explicitly requested.
|
||||
- When vertical scrollbar was not at the top, the computation was often incorrect.
|
||||
- Windows:
|
||||
- Fixed a single-axis auto-resizing feedback loop issue with nested containers
|
||||
and varying scrollbar visibility. (#9352)
|
||||
- Detect and report error when calling End() instead of EndPopup() on a popup. (#9351)
|
||||
- Child windows with only `ImGuiChildFlags_AutoResizeY` flag keep using the proportional
|
||||
default `ItemWidth`. (#9355)
|
||||
- Using mouse wheel to scroll takes and keeps ownership of the corresponding keys
|
||||
(e.g. `ImGuiKey_MouseWheelY`) while a wheeling window is locked. (#2604, #3795)
|
||||
- InputInt, InputFloat, InputScalar:
|
||||
- Reinstated `ImGuiInputTextFlags_EnterReturnsTrue` support which was removed in 1.91.4.
|
||||
(#8665, #9299, #8065, #3946, #6284, #9117)
|
||||
- Fixed the fact that it didn't return true when validating same value.
|
||||
- Fixed losing value when tabbing out or losing focus.
|
||||
- Made it that pressing +/- step buttons also return true, which is in line
|
||||
with 1.91.4 behavior.
|
||||
- In a majority of cases you should use `IsItemDeactivatedAfterEdit()` instead,
|
||||
but it still has a few edge cases flaws (to be addressed soon).
|
||||
- Allow passing a format string that does not display the scalar value.
|
||||
Parsing input with default format for the type. (#9385) [@FireFox2000000]
|
||||
- Multi-Select:
|
||||
- Fixed an issue using Multi-Select within a Table causing column width measurement to
|
||||
be invalid when trailing column contents is not submitted in the last row. (#9341, #8250)
|
||||
- Fixed an issue using Multi-Select within a Table with the right-most column visible,
|
||||
which could lead to an extra vertical offset in the Header row. (#8250)
|
||||
- Multi-Select + Box-Select:
|
||||
- Fixed an issue using `ImGuiMultiSelectFlags_BoxSelect1d` mode while scrolling.
|
||||
Notably, using mouse wheel while holding a box-selection could lead items close to windows
|
||||
edges from not being correctly unselected. (#7994, #8250, #7821, #7850, #7970)
|
||||
- Improved dirty/unclip rectangle logic for `ImGuiMultiSelectFlags_BoxSelect2d`.
|
||||
- Fixed an issue using `ImGuiMultiSelectFlags_BoxSelect2d` mode, where
|
||||
items out of view wouldn't be properly selected while scrolling while mouse cursor
|
||||
is hovering outside of selection scope. (#7994, #1861, #6518)
|
||||
- Fixed an issue where items out of horizontal view would sometimes lead
|
||||
to incorrect merging of sequential selection requests while also scrolling fast
|
||||
enough to overlap multiple rows during a frame. (#7994, #1861, #6518)
|
||||
- Fixed an issue using `ImGuiMultiSelectFlags_BoxSelect2d` mode in a Table
|
||||
while relying on the `TableNextColumn()` return value to perform coarse clipping. (#7994)
|
||||
- Disabled merging consecutive selection requests as we have no reliable
|
||||
way of detecting if user has submitted all consecutive items without clipping gaps,
|
||||
and `ImGuiSelectionUserData` is technically opaque storage. (#7994, #1861)
|
||||
(we will probably bring this back as a minor optimization if we have a way to for
|
||||
user to tell us `ImGuiSelectionUserData` are indices)
|
||||
- Fixes for using across nested child windows. (#8364)
|
||||
- Box-Select + Clipper: fixed an issue selecting items while scrolling while a clipper
|
||||
active. (#7994, #8250, #7821, #7850, #7970)
|
||||
- Box-Select + Tables: fixed an issue using box-selection in a tables with
|
||||
items straying out of columns boundaries. (#7994, #2221)
|
||||
- Box-Select + Tables: fixed an issue when calling `BeginMultiSelect()` in a table
|
||||
before layout has been locked (first row or headers row submitted). (#8250)
|
||||
- Menus:
|
||||
- BeginMenu()/MenuItem(): fixed accidental triggering of child menu items when
|
||||
opening a menu inside a small host window forcing the child menu window to be
|
||||
repositioned under the mouse cursor. (#8233, #9394)
|
||||
Done by reworking `BeginMenu()`/`MenuItem()`: they previously avoiding taking
|
||||
ActiveID + key/click ownership (in order to allow releasing button on another item).
|
||||
Now they take them and release them once the mouse is moved outside item boundaries.
|
||||
- Inputs:
|
||||
- SetItemKeyOwner(): return true if ownership has been requested, which typically
|
||||
needs to to checked for gating further tests. This is important as the function
|
||||
may fail. (#456, #2637, #2620, #2891, #3370, #3724, #4828, #5108, #5242, #5641)
|
||||
- SetItemKeyOwner(): does not set ownership is key is already taken. Effectively
|
||||
this makes using `SetItemKeyOwner(ImGuiKey_MouseWheelY)` over an item work as
|
||||
expected while not having item react if a scroll wheel is actively in progress.
|
||||
May be subject to further redesign, e.g. conditional flags. Feedback welcome!
|
||||
- Style:
|
||||
- Checkbox: added `ImGuiCol_CheckboxSelectedBg` to change or accentuate the
|
||||
background color of checked/mixed checkboxes. (#9392)
|
||||
- Added `ImGuiStyleVar_DragDropTargetRounding`. (#9056)
|
||||
- Fixed vertical scrollbar top coordinates when using thick borders on windows
|
||||
with no title bar and no menu bar. (#9366)
|
||||
- Fonts:
|
||||
- imgui_freetype: add FreeType headers & compiled version in 'About Dear ImGui' details.
|
||||
- Assert when using MergeMode with an explicit size over a target font with an implicit
|
||||
size, as scale factor are likely erroneous. (#9361)
|
||||
- Clipper:
|
||||
- Improved error reporting when misusing the clipper inside a table (prioritize
|
||||
reporting the common clipper error over a table sanity check assert). (#9350)
|
||||
- Tweaked assert triggering when first item height measurement fails, and made it
|
||||
a better recoverable error. (#9350)
|
||||
- Misc:
|
||||
- Minor optimization: reduce redundant label scanning in common widgets.
|
||||
- Added missing Test Engine hooks for `PlotLines()`, `PlotHistogram()`, `VSliderXXX()`
|
||||
and `TableHeader()` functions.
|
||||
- Demo:
|
||||
- Added simple demo for a scrollable/zoomable image viewer with a grid.
|
||||
Available in `Examples->Image Viewer` and `Widgets->Images`.
|
||||
- Backends:
|
||||
- Added support for new standardized draw callbacks in most backends: (#9378)
|
||||
- Allegro5: Reset n/a n/a
|
||||
- DX9: Reset SetSamplerLinear SetSamplerNearest
|
||||
- DX10: Reset SetSamplerLinear SetSamplerNearest
|
||||
- DX11: Reset SetSamplerLinear SetSamplerNearest
|
||||
- DX12: Reset SetSamplerLinear SetSamplerNearest
|
||||
- Metal: Reset SetSamplerLinear SetSamplerNearest
|
||||
- OpenGL2: Reset SetSamplerLinear SetSamplerNearest
|
||||
- OpenGL3+: Reset SetSamplerLinear SetSamplerNearest
|
||||
- SDLGPU3: Reset SetSamplerLinear SetSamplerNearest
|
||||
- SDLRenderer2: Reset n/a n/a
|
||||
- SDLRenderer3: Reset SetSamplerLinear SetSamplerNearest
|
||||
- Vulkan: Reset SetSamplerLinear SetSamplerNearest
|
||||
- WebGPU: Reset SetSamplerLinear SetSamplerNearest
|
||||
(Vulkan backend by @yaz0r, Metal by @ssh4net, others by @ocornut)
|
||||
- GLFW: added a Win32-specific implementation of `ImGui_ImplGlfw_GetContentScaleXXXX`
|
||||
functions for legacy GLFW 3.2. (#9003)
|
||||
- Metal: avoid redundant vertex buffer bind in `SetupRenderState()`, which leads
|
||||
to validation issue. (#9343) [@Hunam6]
|
||||
- Metal: use a dedicated `bufferCacheLock` to avoid crashing when `bufferCache` is
|
||||
replaced by a new object while being used for `@synchronize()`. (#9367) [@andygrundman]
|
||||
- SDL2: made `ImGui_ImplSDL2_GetContentScaleForWindow()`/`ImGui_ImplSDL2_GetContentScaleForDisplay()`
|
||||
helpers return a minimum of 1.0f, as some Linux setup seems to report <1.0f value
|
||||
and this breaks scaling border size. (#9369)
|
||||
- WebGPU: rework choice/detection of using WGSL/SPIR-V shader on WGVK. (#9316, #9246, #9257, #9387)
|
||||
- Examples:
|
||||
- Update VS toolset in all .vcxproj from VS2015 (v140) to VS2017 (v141). The later is the
|
||||
first that supports vcpkg. Onward we will likely stop testing building the library with VS2015.
|
||||
- GLFW+Vulkan, SDL2+Vulkan, SDL3+Vulkan, Win32+Vulkan: reworked to create a descriptor pool with:
|
||||
- `IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE` descriptors of type `VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE`.
|
||||
- `IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE` descriptors of type `VK_DESCRIPTOR_TYPE_SAMPLER`.
|
||||
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
VERSION 1.92.7 (Released 2026-04-02)
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
Vendored
+47
-30
@@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.92.7
|
||||
// dear imgui, v1.92.8
|
||||
// (headers)
|
||||
|
||||
// Help:
|
||||
@@ -29,8 +29,8 @@
|
||||
|
||||
// Library Version
|
||||
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
|
||||
#define IMGUI_VERSION "1.92.7"
|
||||
#define IMGUI_VERSION_NUM 19270
|
||||
#define IMGUI_VERSION "1.92.8"
|
||||
#define IMGUI_VERSION_NUM 19280
|
||||
#define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000
|
||||
#define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198
|
||||
|
||||
@@ -1092,10 +1092,11 @@ namespace ImGui
|
||||
// Inputs Utilities: Key/Input Ownership [BETA]
|
||||
// - One common use case would be to allow your items to disable standard inputs behaviors such
|
||||
// as Tab or Alt key handling, Mouse Wheel scrolling, etc.
|
||||
// e.g. Button(...); SetItemKeyOwner(ImGuiKey_MouseWheelY); to make hovering/activating a button disable wheel for scrolling.
|
||||
// e.g. `Button(...); if (SetItemKeyOwner(ImGuiKey_MouseWheelY)) { ... }` to make hovering/activating a button disable wheel for scrolling.
|
||||
// - Reminder ImGuiKey enum include access to mouse buttons and gamepad, so key ownership can apply to them.
|
||||
// - The return value of SetItemKeyOwner() says if ownership has been requested for the item, which is a shortcut to calling yet non-public TestKeyOwner() function.
|
||||
// - Many related features are still in imgui_internal.h. For instance, most IsKeyXXX()/IsMouseXXX() functions have an owner-id-aware version.
|
||||
IMGUI_API void SetItemKeyOwner(ImGuiKey key); // Set key owner to last item ID if it is hovered or active. Equivalent to 'if (IsItemHovered() || IsItemActive()) { SetKeyOwner(key, GetItemID());'.
|
||||
IMGUI_API bool SetItemKeyOwner(ImGuiKey key); // Set key owner to last item ID if it is hovered or active. Return true when ownership has been set. Roughly equivalent to 'if (TestKeyOwner(key, GetItemID()) && (IsItemHovered() || IsItemActive())) { SetKeyOwner(key, GetItemID());'.
|
||||
|
||||
// Inputs Utilities: Mouse
|
||||
// - To refer to a mouse button, you may use named enums in your code e.g. ImGuiMouseButton_Left, ImGuiMouseButton_Right.
|
||||
@@ -1401,7 +1402,7 @@ enum ImGuiTabBarFlags_
|
||||
ImGuiTabBarFlags_DrawSelectedOverline = 1 << 6, // Draw selected overline markers over selected tab
|
||||
|
||||
// Fitting/Resize policy
|
||||
ImGuiTabBarFlags_FittingPolicyMixed = 1 << 7, // Shrink down tabs when they don't fit, until width is style.TabMinWidthShrink, then enable scrolling buttons.
|
||||
ImGuiTabBarFlags_FittingPolicyMixed = 1 << 7, // Shrink down tabs when they don't fit, until width is style.TabMinWidthShrink, then enable scrolling. Setting TabMinWidthShrink to FLT_MAX makes this behave like ImGuiTabBarFlags_FittingPolicyScroll.
|
||||
ImGuiTabBarFlags_FittingPolicyShrink = 1 << 8, // Shrink down tabs when they don't fit
|
||||
ImGuiTabBarFlags_FittingPolicyScroll = 1 << 9, // Enable scrolling buttons when tabs don't fit
|
||||
ImGuiTabBarFlags_FittingPolicyMask_ = ImGuiTabBarFlags_FittingPolicyMixed | ImGuiTabBarFlags_FittingPolicyShrink | ImGuiTabBarFlags_FittingPolicyScroll,
|
||||
@@ -1755,6 +1756,7 @@ enum ImGuiCol_
|
||||
ImGuiCol_ScrollbarGrabHovered,
|
||||
ImGuiCol_ScrollbarGrabActive,
|
||||
ImGuiCol_CheckMark, // Checkbox tick and RadioButton circle
|
||||
ImGuiCol_CheckboxSelectedBg, // Checkbox background when Selected, otherwise use FrameBg
|
||||
ImGuiCol_SliderGrab,
|
||||
ImGuiCol_SliderGrabActive,
|
||||
ImGuiCol_Button,
|
||||
@@ -1852,6 +1854,7 @@ enum ImGuiStyleVar_
|
||||
ImGuiStyleVar_TableAngledHeadersTextAlign,// ImVec2 TableAngledHeadersTextAlign
|
||||
ImGuiStyleVar_TreeLinesSize, // float TreeLinesSize
|
||||
ImGuiStyleVar_TreeLinesRounding, // float TreeLinesRounding
|
||||
ImGuiStyleVar_DragDropTargetRounding, // float DragDropTargetRounding
|
||||
ImGuiStyleVar_ButtonTextAlign, // ImVec2 ButtonTextAlign
|
||||
ImGuiStyleVar_SelectableTextAlign, // ImVec2 SelectableTextAlign
|
||||
ImGuiStyleVar_SeparatorSize, // float SeparatorSize
|
||||
@@ -2319,7 +2322,7 @@ struct ImGuiStyle
|
||||
float TabBorderSize; // Thickness of border around tabs.
|
||||
float TabMinWidthBase; // Minimum tab width, to make tabs larger than their contents. TabBar buttons are not affected.
|
||||
float TabMinWidthShrink; // Minimum tab width after shrinking, when using ImGuiTabBarFlags_FittingPolicyMixed policy.
|
||||
float TabCloseButtonMinWidthSelected; // -1: always visible. 0.0f: visible when hovered. >0.0f: visible when hovered if minimum width.
|
||||
float TabCloseButtonMinWidthSelected; // -1: always visible. 0.0f: visible when hovered. >0.0f: visible when hovered if minimum width. FLT_MAX: never shrink, will behave like ImGuiTabBarFlags_FittingPolicyScroll.
|
||||
float TabCloseButtonMinWidthUnselected; // -1: always visible. 0.0f: visible when hovered. >0.0f: visible when hovered if minimum width. FLT_MAX: never show close button when unselected.
|
||||
float TabBarBorderSize; // Thickness of tab-bar separator, which takes on the tab active color to denote focus.
|
||||
float TabBarOverlineSize; // Thickness of tab-bar overline, which highlights the selected tab-bar.
|
||||
@@ -2328,14 +2331,14 @@ struct ImGuiStyle
|
||||
ImGuiTreeNodeFlags TreeLinesFlags; // Default way to draw lines connecting TreeNode hierarchy. ImGuiTreeNodeFlags_DrawLinesNone or ImGuiTreeNodeFlags_DrawLinesFull or ImGuiTreeNodeFlags_DrawLinesToNodes.
|
||||
float TreeLinesSize; // Thickness of outlines when using ImGuiTreeNodeFlags_DrawLines.
|
||||
float TreeLinesRounding; // Radius of lines connecting child nodes to the vertical line.
|
||||
float DragDropTargetRounding; // Radius of the drag and drop target frame.
|
||||
float DragDropTargetRounding; // Radius of the drag and drop target frame. When <0.0f: use FrameRounding.
|
||||
float DragDropTargetBorderSize; // Thickness of the drag and drop target border.
|
||||
float DragDropTargetPadding; // Size to expand the drag and drop target from actual target item size.
|
||||
float ColorMarkerSize; // Size of R/G/B/A color markers for ColorEdit4() and for Drags/Sliders when using ImGuiSliderFlags_ColorMarkers.
|
||||
ImGuiDir ColorButtonPosition; // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right.
|
||||
ImVec2 ButtonTextAlign; // Alignment of button text when button is larger than text. Defaults to (0.5f, 0.5f) (centered).
|
||||
ImVec2 SelectableTextAlign; // Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line.
|
||||
float SeparatorSize; // Thickness of border in Separator()
|
||||
float SeparatorSize; // Thickness of border in Separator(). Must be >= 1.0f.
|
||||
float SeparatorTextBorderSize; // Thickness of border in SeparatorText()
|
||||
ImVec2 SeparatorTextAlign; // Alignment of text within the separator. Defaults to (0.0f, 0.5f) (left aligned, center).
|
||||
ImVec2 SeparatorTextPadding; // Horizontal offset of text from each edge of the separator + spacing on other axis. Generally small values. .y is recommended to be == FramePadding.y.
|
||||
@@ -2365,7 +2368,7 @@ struct ImGuiStyle
|
||||
|
||||
// Functions
|
||||
IMGUI_API ImGuiStyle();
|
||||
IMGUI_API void ScaleAllSizes(float scale_factor); // Scale all spacing/padding/thickness values. Do not scale fonts.
|
||||
IMGUI_API void ScaleAllSizes(float scale_factor); // Scale all spacing/padding/thickness values. Do not scale fonts. See comments in definition. Consider not calling this if your initial scale factor if <1.0.
|
||||
|
||||
// Obsolete names
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
@@ -2642,7 +2645,7 @@ struct ImGuiInputTextCallbackData
|
||||
ImGuiInputTextFlags EventFlag; // One ImGuiInputTextFlags_Callback* // Read-only
|
||||
ImGuiInputTextFlags Flags; // What user passed to InputText() // Read-only
|
||||
void* UserData; // What user passed to InputText() // Read-only
|
||||
ImGuiID ID; // Widget ID // Read-only
|
||||
ImGuiID ID; // Widget ID // Read-only
|
||||
|
||||
// Arguments for the different callback events
|
||||
// - During Resize callback, Buf will be same as your input buffer.
|
||||
@@ -2656,9 +2659,9 @@ struct ImGuiInputTextCallbackData
|
||||
char* Buf; // Text buffer // Read-write // [Resize] Can replace pointer / [Completion,History,Always] Only write to pointed data, don't replace the actual pointer!
|
||||
int BufTextLen; // Text length (in bytes) // Read-write // [Resize,Completion,History,Always] Exclude zero-terminator storage. In C land: == strlen(some_text), in C++ land: string.length()
|
||||
int BufSize; // Buffer size (in bytes) = capacity+1 // Read-only // [Resize,Completion,History,Always] Include zero-terminator storage. In C land: == ARRAYSIZE(my_char_array), in C++ land: string.capacity()+1
|
||||
int CursorPos; // // Read-write // [Completion,History,Always]
|
||||
int SelectionStart; // // Read-write // [Completion,History,Always] == to SelectionEnd when no selection
|
||||
int SelectionEnd; // // Read-write // [Completion,History,Always]
|
||||
int CursorPos; // // Read-write // [Completion,History,Always,CharFilter]
|
||||
int SelectionStart; // // Read-write // [Completion,History,Always,CharFilter] == to SelectionEnd when no selection
|
||||
int SelectionEnd; // // Read-write // [Completion,History,Always,CharFilter]
|
||||
|
||||
// Helper functions for text manipulation.
|
||||
// Use those function to benefit from the CallbackResize behaviors. Calling those function reset the selection.
|
||||
@@ -3166,12 +3169,6 @@ typedef unsigned short ImDrawIdx; // Default: 16-bit (for maximum compatibilit
|
||||
typedef void (*ImDrawCallback)(const ImDrawList* parent_list, const ImDrawCmd* cmd);
|
||||
#endif
|
||||
|
||||
// Special Draw callback value to request renderer backend to reset the graphics/render state.
|
||||
// The renderer backend needs to handle this special value, otherwise it will crash trying to call a function at this address.
|
||||
// This is useful, for example, if you submitted callbacks which you know have altered the render state and you want it to be restored.
|
||||
// Render state is not reset by default because they are many perfectly useful way of altering render state (e.g. changing shader/blending settings before an Image call).
|
||||
#define ImDrawCallback_ResetRenderState (ImDrawCallback)(-8)
|
||||
|
||||
// Typically, 1 command = 1 GPU draw call (unless command is a callback)
|
||||
// - VtxOffset: When 'io.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset' is enabled,
|
||||
// this fields allow us to render meshes larger than 64K vertices while keeping 16-bit indices.
|
||||
@@ -3245,16 +3242,15 @@ struct ImDrawListSplitter
|
||||
};
|
||||
|
||||
// Flags for ImDrawList functions
|
||||
// (Legacy: bit 0 must always correspond to ImDrawFlags_Closed to be backward compatible with old API using a bool. Bits 1..3 must be unused)
|
||||
enum ImDrawFlags_
|
||||
{
|
||||
ImDrawFlags_None = 0,
|
||||
ImDrawFlags_Closed = 1 << 0, // PathStroke(), AddPolyline(): specify that shape should be closed (Important: this is always == 1 for legacy reason)
|
||||
ImDrawFlags_RoundCornersTopLeft = 1 << 4, // AddRect(), AddRectFilled(), PathRect(): enable rounding top-left corner only (when rounding > 0.0f, we default to all corners). Was 0x01.
|
||||
ImDrawFlags_RoundCornersTopRight = 1 << 5, // AddRect(), AddRectFilled(), PathRect(): enable rounding top-right corner only (when rounding > 0.0f, we default to all corners). Was 0x02.
|
||||
ImDrawFlags_RoundCornersBottomLeft = 1 << 6, // AddRect(), AddRectFilled(), PathRect(): enable rounding bottom-left corner only (when rounding > 0.0f, we default to all corners). Was 0x04.
|
||||
ImDrawFlags_RoundCornersBottomRight = 1 << 7, // AddRect(), AddRectFilled(), PathRect(): enable rounding bottom-right corner only (when rounding > 0.0f, we default to all corners). Wax 0x08.
|
||||
ImDrawFlags_RoundCornersNone = 1 << 8, // AddRect(), AddRectFilled(), PathRect(): disable rounding on all corners (when rounding > 0.0f). This is NOT zero, NOT an implicit flag!
|
||||
ImDrawFlags_Closed = 1 << 9, // PathStroke(), AddPolyline(): specify that shape should be closed (Important: this is always == 1 for legacy reason)
|
||||
ImDrawFlags_RoundCornersTop = ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersTopRight,
|
||||
ImDrawFlags_RoundCornersBottom = ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersBottomRight,
|
||||
ImDrawFlags_RoundCornersLeft = ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersTopLeft,
|
||||
@@ -3262,6 +3258,7 @@ enum ImDrawFlags_
|
||||
ImDrawFlags_RoundCornersAll = ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersTopRight | ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersBottomRight,
|
||||
ImDrawFlags_RoundCornersDefault_ = ImDrawFlags_RoundCornersAll, // Default to ALL corners if none of the _RoundCornersXX flags are specified.
|
||||
ImDrawFlags_RoundCornersMask_ = ImDrawFlags_RoundCornersAll | ImDrawFlags_RoundCornersNone,
|
||||
ImDrawFlags_InvalidMask_ = (ImDrawFlags)0x8000000F,
|
||||
};
|
||||
|
||||
// Flags for ImDrawList instance. Those are set automatically by ImGui:: functions from ImGuiIO settings, and generally not manipulated directly.
|
||||
@@ -3327,7 +3324,9 @@ struct ImDrawList
|
||||
// In future versions we will use textures to provide cheaper and higher-quality circles.
|
||||
// Use AddNgon() and AddNgonFilled() functions if you need to guarantee a specific number of sides.
|
||||
IMGUI_API void AddLine(const ImVec2& p1, const ImVec2& p2, ImU32 col, float thickness = 1.0f);
|
||||
IMGUI_API void AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding = 0.0f, ImDrawFlags flags = 0, float thickness = 1.0f); // a: upper-left, b: lower-right (== upper-left + size)
|
||||
IMGUI_API void AddLineH(float min_x, float max_x, float y, ImU32 col, float thickness = 1.0f);
|
||||
IMGUI_API void AddLineV(float x, float min_y, float max_y, ImU32 col, float thickness = 1.0f);
|
||||
IMGUI_API void AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding = 0.0f, float thickness = 1.0f, ImDrawFlags flags = 0); // a: upper-left, b: lower-right (== upper-left + size)
|
||||
IMGUI_API void AddRectFilled(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding = 0.0f, ImDrawFlags flags = 0); // a: upper-left, b: lower-right (== upper-left + size)
|
||||
IMGUI_API void AddRectFilledMultiColor(const ImVec2& p_min, const ImVec2& p_max, ImU32 col_upr_left, ImU32 col_upr_right, ImU32 col_bot_right, ImU32 col_bot_left);
|
||||
IMGUI_API void AddQuad(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness = 1.0f);
|
||||
@@ -3348,7 +3347,7 @@ struct ImDrawList
|
||||
// General polygon
|
||||
// - Only simple polygons are supported by filling functions (no self-intersections, no holes).
|
||||
// - Concave polygon fill is more expensive than convex one: it has O(N^2) complexity. Provided as a convenience for the user but not used by the main library.
|
||||
IMGUI_API void AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness);
|
||||
IMGUI_API void AddPolyline(const ImVec2* points, int num_points, ImU32 col, float thickness, ImDrawFlags flags = 0);
|
||||
IMGUI_API void AddConvexPolyFilled(const ImVec2* points, int num_points, ImU32 col);
|
||||
IMGUI_API void AddConcavePolyFilled(const ImVec2* points, int num_points, ImU32 col);
|
||||
|
||||
@@ -3368,7 +3367,7 @@ struct ImDrawList
|
||||
inline void PathLineToMergeDuplicate(const ImVec2& pos) { if (_Path.Size == 0 || memcmp(&_Path.Data[_Path.Size - 1], &pos, 8) != 0) _Path.push_back(pos); }
|
||||
inline void PathFillConvex(ImU32 col) { AddConvexPolyFilled(_Path.Data, _Path.Size, col); _Path.Size = 0; }
|
||||
inline void PathFillConcave(ImU32 col) { AddConcavePolyFilled(_Path.Data, _Path.Size, col); _Path.Size = 0; }
|
||||
inline void PathStroke(ImU32 col, ImDrawFlags flags = 0, float thickness = 1.0f) { AddPolyline(_Path.Data, _Path.Size, col, flags, thickness); _Path.Size = 0; }
|
||||
inline void PathStroke(ImU32 col, float thickness = 1.0f, ImDrawFlags flags = 0) { AddPolyline(_Path.Data, _Path.Size, col, thickness, flags); _Path.Size = 0; }
|
||||
IMGUI_API void PathArcTo(const ImVec2& center, float radius, float a_min, float a_max, int num_segments = 0);
|
||||
IMGUI_API void PathArcToFast(const ImVec2& center, float radius, int a_min_of_12, int a_max_of_12); // Use precomputed angles for a 12 steps circle
|
||||
IMGUI_API void PathEllipticalArcTo(const ImVec2& center, const ImVec2& radius, float rot, float a_min, float a_max, int num_segments = 0); // Ellipse
|
||||
@@ -3378,14 +3377,15 @@ struct ImDrawList
|
||||
|
||||
// Advanced: Draw Callbacks
|
||||
// - May be used to alter render state (change sampler, blending, current shader). May be used to emit custom rendering commands (difficult to do correctly, but possible).
|
||||
// - Use special ImDrawCallback_ResetRenderState callback to instruct backend to reset its render state to the default.
|
||||
// - Use special GetPlatformIO().DrawCallback_ResetRenderState callback to instruct backend to reset its render state to the default.
|
||||
// - See other standard callbacks in GetPlatformIO(), which may or not be supported by your backend.
|
||||
// - Your rendering loop must check for 'UserCallback' in ImDrawCmd and call the function instead of rendering triangles. All standard backends are honoring this.
|
||||
// - For some backends, the callback may access selected render-states exposed by the backend in a ImGui_ImplXXXX_RenderState structure pointed to by platform_io.Renderer_RenderState.
|
||||
// - IMPORTANT: please be mindful of the different level of indirection between using size==0 (copying argument) and using size>0 (copying pointed data into a buffer).
|
||||
// - If userdata_size == 0: we copy/store the 'userdata' argument as-is. It will be available unmodified in ImDrawCmd::UserCallbackData during render.
|
||||
// - If userdata_size > 0, we copy/store 'userdata_size' bytes pointed to by 'userdata'. We store them in a buffer stored inside the drawlist. ImDrawCmd::UserCallbackData will point inside that buffer so you have to retrieve data from there. Your callback may need to use ImDrawCmd::UserCallbackDataSize if you expect dynamically-sized data.
|
||||
// - Support for userdata_size > 0 was added in v1.91.4, October 2024. So earlier code always only allowed to copy/store a simple void*.
|
||||
IMGUI_API void AddCallback(ImDrawCallback callback, void* userdata, size_t userdata_size = 0);
|
||||
IMGUI_API void AddCallback(ImDrawCallback callback, void* userdata = NULL, size_t userdata_size = 0);
|
||||
|
||||
// Advanced: Miscellaneous
|
||||
IMGUI_API void AddDrawCmd(); // This is useful if you need to forcefully create a new draw call (to allow for dependent rendering / blending). Otherwise primitives are merged into the same draw-call as much as possible
|
||||
@@ -3415,8 +3415,15 @@ struct ImDrawList
|
||||
|
||||
// Obsolete names
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
inline void AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding, ImDrawFlags flags, float thickness) { AddRect(p_min, p_max, col, rounding, thickness, flags); } // OBSOLETED in 1.92.8: NEW FUNCTION SIGNATURE HAS 'thickness' AND 'flags' SWAPPED.
|
||||
inline void AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness) { AddPolyline(points, num_points, col, thickness, flags); } // OBSOLETED in 1.92.8: NEW FUNCTION SIGNATURE HAS 'thickness' AND 'flags' SWAPPED.
|
||||
inline void PathStroke(ImU32 col, ImDrawFlags flags, float thickness) { PathStroke(col, thickness, flags); } // OBSOLETED in 1.92.8: NEW FUNCTION SIGNATURE HAS 'thickness' AND 'flags' SWAPPED.
|
||||
inline void PushTextureID(ImTextureRef tex_ref) { PushTexture(tex_ref); } // RENAMED in 1.92.0
|
||||
inline void PopTextureID() { PopTexture(); } // RENAMED in 1.92.0
|
||||
#else
|
||||
IMGUI_API void AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding /*= 0.0f*/, ImDrawFlags flags /*= 0*/, float thickness /*= 1.0f*/) = delete;
|
||||
IMGUI_API void AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness) = delete;
|
||||
inline void PathStroke(ImU32 col, ImDrawFlags flags /*= 0*/, float thickness /*= 1.0f*/) = delete;
|
||||
#endif
|
||||
//inline void AddEllipse(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot = 0.0f, int num_segments = 0, float thickness = 1.0f) { AddEllipse(center, ImVec2(radius_x, radius_y), col, rot, num_segments, thickness); } // OBSOLETED in 1.90.5 (Mar 2024)
|
||||
//inline void AddEllipseFilled(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot = 0.0f, int num_segments = 0) { AddEllipseFilled(center, ImVec2(radius_x, radius_y), col, rot, num_segments); } // OBSOLETED in 1.90.5 (Mar 2024)
|
||||
@@ -3528,6 +3535,7 @@ struct ImTextureData
|
||||
bool WantDestroyNextFrame; // rw - // [Internal] Queued to set ImTextureStatus_WantDestroy next frame. May still be used in the current frame.
|
||||
|
||||
// Functions
|
||||
// - If GetPixels() functions asserts while being called by your render loop, it could be caused by calling ImFontAtlas::Clear() instead of ClearFonts()?
|
||||
ImTextureData() { memset((void*)this, 0, sizeof(*this)); Status = ImTextureStatus_Destroyed; TexID = ImTextureID_Invalid; }
|
||||
~ImTextureData() { DestroyPixels(); }
|
||||
IMGUI_API void Create(ImTextureFormat format, int w, int h);
|
||||
@@ -3684,13 +3692,13 @@ struct ImFontAtlas
|
||||
IMGUI_API ImFont* AddFontFromMemoryCompressedBase85TTF(const char* compressed_font_data_base85, float size_pixels = 0.0f, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data_base85' still owned by caller. Compress with binary_to_compressed_c.cpp with -base85 parameter.
|
||||
IMGUI_API void RemoveFont(ImFont* font);
|
||||
|
||||
IMGUI_API void Clear(); // Clear everything (input fonts, output glyphs/textures).
|
||||
IMGUI_API void Clear(); // Clear everything (fonts + textures). Don't call mid-frame!
|
||||
IMGUI_API void ClearFonts(); // Clear input+output font data/glyphs. You can call this mid-frame if you load new fonts afterwards!
|
||||
IMGUI_API void CompactCache(); // Compact cached glyphs and texture.
|
||||
IMGUI_API void SetFontLoader(const ImFontLoader* font_loader); // Change font loader at runtime.
|
||||
|
||||
// As we are transitioning toward a new font system, we expect to obsolete those soon:
|
||||
IMGUI_API void ClearInputData(); // [OBSOLETE] Clear input data (all ImFontConfig structures including sizes, TTF data, glyph ranges, etc.) = all the data used to build the texture and fonts.
|
||||
IMGUI_API void ClearFonts(); // [OBSOLETE] Clear input+output font data (same as ClearInputData() + glyphs storage, UV coordinates).
|
||||
IMGUI_API void ClearTexData(); // [OBSOLETE] Clear CPU-side copy of the texture data. Saves RAM once the texture has been copied to graphics memory.
|
||||
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
@@ -3862,6 +3870,7 @@ enum ImFontFlags_
|
||||
ImFontFlags_NoLoadError = 1 << 1, // Disable throwing an error/assert when calling AddFontXXX() with missing file/data. Calling code is expected to check AddFontXXX() return value.
|
||||
ImFontFlags_NoLoadGlyphs = 1 << 2, // [Internal] Disable loading new glyphs.
|
||||
ImFontFlags_LockBakedSizes = 1 << 3, // [Internal] Disable loading new baked sizes, disable garbage collecting current ones. e.g. if you want to lock a font to a single size. Important: if you use this to preload given sizes, consider the possibility of multiple font density used on Retina display.
|
||||
ImFontFlags_ImplicitRefSize = 1 << 4, // [Internal] Reference size was not set explicitly.
|
||||
};
|
||||
|
||||
// Font runtime data and rendering
|
||||
@@ -3876,7 +3885,7 @@ struct ImFont
|
||||
ImFontAtlas* OwnerAtlas; // 4-8 // What we have been loaded into.
|
||||
ImFontFlags Flags; // 4 // Font flags.
|
||||
float CurrentRasterizerDensity; // Current rasterizer density. This is a varying state of the font.
|
||||
float LineHeight; // 4 // Line Height
|
||||
float LineHeight; // 4 // Line Height
|
||||
|
||||
// [Internal] Members: Cold ~24-52 bytes
|
||||
// Conceptually Sources[] is the list of font sources merged to create this font.
|
||||
@@ -4023,6 +4032,12 @@ struct ImGuiPlatformIO
|
||||
// Written by some backends during ImGui_ImplXXXX_RenderDrawData() call to point backend_specific ImGui_ImplXXXX_RenderState* structure.
|
||||
void* Renderer_RenderState;
|
||||
|
||||
// Standard draw callbacks provided by renderer backend.
|
||||
ImDrawCallback DrawCallback_ResetRenderState; // Request to reset the graphics/render state.
|
||||
ImDrawCallback DrawCallback_SetSamplerLinear; // Request backend to set texture sampling to Linear.
|
||||
ImDrawCallback DrawCallback_SetSamplerNearest; // Request backend to set texture sampling to Nearest/Point.
|
||||
//ImDrawCallback DrawCallback_SetSamplerCustom; // Request backend to set texture sampling using Backend Specific data.
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Output
|
||||
//------------------------------------------------------------------
|
||||
@@ -4151,6 +4166,8 @@ namespace ImGui
|
||||
//static inline void SetScrollPosHere() { SetScrollHere(); } // OBSOLETED in 1.42
|
||||
}
|
||||
|
||||
#define ImDrawCallback_ResetRenderState (ImDrawCallback)(-8) // OBSOLETED in 1.92.8: Use ImGui::GetPlatformIO().DrawCallback_ResetRenderState
|
||||
|
||||
//-- OBSOLETED in 1.92.0: ImFontAtlasCustomRect becomes ImTextureRect
|
||||
// - ImFontAtlasCustomRect::X,Y --> ImTextureRect::x,y
|
||||
// - ImFontAtlasCustomRect::Width,Height --> ImTextureRect::w,h
|
||||
|
||||
+22
-6
@@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.92.7
|
||||
// dear imgui, v1.92.8
|
||||
// (internal structures/api)
|
||||
|
||||
// You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility.
|
||||
@@ -252,6 +252,9 @@ extern IMGUI_API ImGuiContext* GImGui; // Current implicit context pointer
|
||||
#define IMGUI_DEBUG_LOG_FONT(...) do { ImGuiContext* g2 = GImGui; if (g2 && g2->DebugLogFlags & ImGuiDebugLogFlags_EventFont) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) // Called from ImFontAtlas function which may operate without a context.
|
||||
#define IMGUI_DEBUG_LOG_INPUTROUTING(...) do{if (g.DebugLogFlags & ImGuiDebugLogFlags_EventInputRouting)IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
|
||||
|
||||
// Debug options (also see ones on top of imgui.cpp)
|
||||
//#define IMGUI_DEBUG_BOXSELECT
|
||||
|
||||
// Static Asserts
|
||||
#define IM_STATIC_ASSERT(_COND) static_assert(_COND, "")
|
||||
|
||||
@@ -506,7 +509,8 @@ inline double ImRsqrt(double x) { return 1.0 / sqrt(x); }
|
||||
template<typename T> T ImMin(T lhs, T rhs) { return lhs < rhs ? lhs : rhs; }
|
||||
template<typename T> T ImMax(T lhs, T rhs) { return lhs >= rhs ? lhs : rhs; }
|
||||
template<typename T> T ImClamp(T v, T mn, T mx) { return (v < mn) ? mn : (v > mx) ? mx : v; }
|
||||
template<typename T> T ImLerp(T a, T b, float t) { return (T)(a + (b - a) * t); }
|
||||
template<typename T> T ImLerp(double a, double b, float t) { return (T)(a + (b - a) * (double)t); }
|
||||
template<typename T> T ImLerp(T a, T b, float t) { return (T)((float)a + (float)(b - a) * t); }
|
||||
template<typename T> void ImSwap(T& a, T& b) { T tmp = a; a = b; b = tmp; }
|
||||
template<typename T> T ImAddClampOverflow(T a, T b, T mn, T mx) { if (b < 0 && (a < mn - b)) return mn; if (b > 0 && (a > mx - b)) return mx; return a + b; }
|
||||
template<typename T> T ImSubClampOverflow(T a, T b, T mn, T mx) { if (b > 0 && (a < mn + b)) return mn; if (b < 0 && (a > mx + b)) return mx; return a - b; }
|
||||
@@ -603,6 +607,8 @@ struct IMGUI_API ImRect
|
||||
bool Overlaps(const ImRect& r) const { return r.Min.y < Max.y && r.Max.y > Min.y && r.Min.x < Max.x && r.Max.x > Min.x; }
|
||||
void Add(const ImVec2& p) { if (Min.x > p.x) Min.x = p.x; if (Min.y > p.y) Min.y = p.y; if (Max.x < p.x) Max.x = p.x; if (Max.y < p.y) Max.y = p.y; }
|
||||
void Add(const ImRect& r) { if (Min.x > r.Min.x) Min.x = r.Min.x; if (Min.y > r.Min.y) Min.y = r.Min.y; if (Max.x < r.Max.x) Max.x = r.Max.x; if (Max.y < r.Max.y) Max.y = r.Max.y; }
|
||||
void AddX(float x) { if (Min.x > x) Min.x = x; if (Max.x < x) Max.x = x; }
|
||||
void AddY(float y) { if (Min.y > y) Min.y = y; if (Max.y < y) Max.y = y; }
|
||||
void Expand(const float amount) { Min.x -= amount; Min.y -= amount; Max.x += amount; Max.y += amount; }
|
||||
void Expand(const ImVec2& amount) { Min.x -= amount.x; Min.y -= amount.y; Max.x += amount.x; Max.y += amount.y; }
|
||||
void Translate(const ImVec2& d) { Min.x += d.x; Min.y += d.y; Max.x += d.x; Max.y += d.y; }
|
||||
@@ -999,6 +1005,7 @@ enum ImGuiItemStatusFlags_
|
||||
ImGuiItemStatusFlags_HasClipRect = 1 << 9, // g.LastItemData.ClipRect is valid.
|
||||
ImGuiItemStatusFlags_HasShortcut = 1 << 10, // g.LastItemData.Shortcut valid. Set by SetNextItemShortcut() -> ItemAdd().
|
||||
//ImGuiItemStatusFlags_FocusedByTabbing = 1 << 8, // Removed IN 1.90.1 (Dec 2023). The trigger is part of g.NavActivateId. See commit 54c1bdeceb.
|
||||
ImGuiItemStatusFlags_EditedInternal = 1 << 11, // Similar to ImGuiItemStatusFlags_Edited but bypassing ImGuiItemFlags_NoMarkEdited.
|
||||
|
||||
// Additional status + semantic for ImGuiTestEngine
|
||||
#ifdef IMGUI_ENABLE_TEST_ENGINE
|
||||
@@ -1204,6 +1211,7 @@ struct IMGUI_API ImGuiMenuColumns
|
||||
};
|
||||
|
||||
// Internal temporary state for deactivating InputText() instances.
|
||||
// Store as part of ImGuiDeactivatedItemData?
|
||||
struct IMGUI_API ImGuiInputTextDeactivatedState
|
||||
{
|
||||
ImGuiID ID; // widget id owning the text state (which just got deactivated)
|
||||
@@ -1449,6 +1457,7 @@ struct ImGuiPtrOrIndex
|
||||
};
|
||||
|
||||
// Data used by IsItemDeactivated()/IsItemDeactivatedAfterEdit() functions
|
||||
// Also see ImGuiInputTextDeactivatedState which is an extension for this for InputText()
|
||||
struct ImGuiDeactivatedItemData
|
||||
{
|
||||
ImGuiID ID;
|
||||
@@ -1890,6 +1899,7 @@ struct ImGuiBoxSelectState
|
||||
// Temporary/Transient data
|
||||
bool UnclipMode; // (Temp/Transient, here in hot area). Set/cleared by the BeginMultiSelect()/EndMultiSelect() owning active box-select.
|
||||
ImRect UnclipRect; // Rectangle where ItemAdd() clipping may be temporarily disabled. Need support by multi-select supporting widgets.
|
||||
ImRect UnclipRects[2]; // Per-axis versions.
|
||||
ImRect BoxSelectRectPrev; // Selection rectangle in absolute coordinates (derived every frame from BoxSelectStartPosRel and MousePos)
|
||||
ImRect BoxSelectRectCurr;
|
||||
|
||||
@@ -1912,7 +1922,8 @@ struct IMGUI_API ImGuiMultiSelectTempData
|
||||
ImGuiMultiSelectFlags Flags;
|
||||
ImVec2 ScopeRectMin;
|
||||
ImVec2 BackupCursorMaxPos;
|
||||
ImGuiSelectionUserData LastSubmittedItem; // Copy of last submitted item data, used to merge output ranges.
|
||||
//ImGuiSelectionUserData CurrSubmittedItem; // Copy of last submitted item data, used to merge output ranges.
|
||||
//ImGuiSelectionUserData PrevSubmittedItem; // Copy of previous submitted item data, used to merge output ranges.
|
||||
ImGuiID BoxSelectId;
|
||||
ImGuiKeyChord KeyMods;
|
||||
ImS8 LoopRequestSetAll; // -1: no operation, 0: clear all, 1: select all.
|
||||
@@ -2213,6 +2224,7 @@ struct ImGuiContext
|
||||
float CurrentDpiScale; // Current window/viewport DpiScale == CurrentViewport->DpiScale
|
||||
ImDrawListSharedData DrawListSharedData;
|
||||
ImGuiID WithinEndChildID; // Set within EndChild()
|
||||
ImGuiID WithinEndPopupID; // Set within EndPopup()
|
||||
void* TestEngine; // Test engine user data
|
||||
|
||||
// Inputs
|
||||
@@ -3205,7 +3217,7 @@ namespace ImGui
|
||||
IMGUI_API void SetNextWindowRefreshPolicy(ImGuiWindowRefreshFlags flags);
|
||||
|
||||
// Fonts, drawing
|
||||
IMGUI_API void RegisterUserTexture(ImTextureData* tex); // Register external texture. EXPERIMENTAL: DO NOT USE YET.
|
||||
IMGUI_API void RegisterUserTexture(ImTextureData* tex); // Register external texture. EXPERIMENTAL.
|
||||
IMGUI_API void UnregisterUserTexture(ImTextureData* tex);
|
||||
IMGUI_API void RegisterFontAtlas(ImFontAtlas* atlas);
|
||||
IMGUI_API void UnregisterFontAtlas(ImFontAtlas* atlas);
|
||||
@@ -3320,6 +3332,7 @@ namespace ImGui
|
||||
|
||||
// Childs
|
||||
IMGUI_API bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, ImGuiChildFlags child_flags, ImGuiWindowFlags window_flags);
|
||||
IMGUI_API ImGuiWindow* FindFrontMostVisibleChildWindow(ImGuiWindow* window);
|
||||
|
||||
// Popups, Modals
|
||||
IMGUI_API bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_window_flags);
|
||||
@@ -3425,7 +3438,7 @@ namespace ImGui
|
||||
IMGUI_API ImGuiID GetKeyOwner(ImGuiKey key);
|
||||
IMGUI_API void SetKeyOwner(ImGuiKey key, ImGuiID owner_id, ImGuiInputFlags flags = 0);
|
||||
IMGUI_API void SetKeyOwnersForKeyChord(ImGuiKeyChord key, ImGuiID owner_id, ImGuiInputFlags flags = 0);
|
||||
IMGUI_API void SetItemKeyOwner(ImGuiKey key, ImGuiInputFlags flags); // Set key owner to last item if it is hovered or active. Equivalent to 'if (IsItemHovered() || IsItemActive()) { SetKeyOwner(key, GetItemID());'.
|
||||
IMGUI_API bool SetItemKeyOwner(ImGuiKey key, ImGuiInputFlags flags);
|
||||
IMGUI_API bool TestKeyOwner(ImGuiKey key, ImGuiID owner_id); // Test that key is either not owned, either owned by 'owner_id'
|
||||
inline ImGuiKeyOwnerData* GetKeyOwnerData(ImGuiContext* ctx, ImGuiKey key) { if (key & ImGuiMod_Mask_) key = ConvertSingleModFlagToKey(key); IM_ASSERT(IsNamedKey(key)); return &ctx->KeysOwnerData[key - ImGuiKey_NamedKey_BEGIN]; }
|
||||
|
||||
@@ -3473,6 +3486,7 @@ namespace ImGui
|
||||
// We don't use the ID Stack for this as it is common to want them separate.
|
||||
IMGUI_API void PushFocusScope(ImGuiID id);
|
||||
IMGUI_API void PopFocusScope();
|
||||
IMGUI_API bool IsInNavFocusRoute(ImGuiID focus_scope_id);
|
||||
inline ImGuiID GetCurrentFocusScope() { ImGuiContext& g = *GImGui; return g.CurrentFocusScopeId; } // Focus scope we are outputting into, set by PushFocusScope()
|
||||
|
||||
// Drag and Drop
|
||||
@@ -3482,7 +3496,7 @@ namespace ImGui
|
||||
IMGUI_API void ClearDragDrop();
|
||||
IMGUI_API bool IsDragDropPayloadBeingAccepted();
|
||||
IMGUI_API void RenderDragDropTargetRectForItem(const ImRect& bb);
|
||||
IMGUI_API void RenderDragDropTargetRectEx(ImDrawList* draw_list, const ImRect& bb);
|
||||
IMGUI_API void RenderDragDropTargetRectEx(ImDrawList* draw_list, const ImRect& bb, float rounding);
|
||||
|
||||
// Typing-Select API
|
||||
// (provide Windows Explorer style "select items by typing partial name" + "cycle through items by typing same letter" feature)
|
||||
@@ -3539,6 +3553,7 @@ namespace ImGui
|
||||
IMGUI_API void TableUpdateLayout(ImGuiTable* table);
|
||||
IMGUI_API void TableUpdateBorders(ImGuiTable* table);
|
||||
IMGUI_API void TableUpdateColumnsWeightFromWidth(ImGuiTable* table);
|
||||
IMGUI_API void TableApplyExternalUnclipRect(ImGuiTable* table, ImRect& rect);
|
||||
IMGUI_API void TableDrawBorders(ImGuiTable* table);
|
||||
IMGUI_API void TableDrawDefaultContextMenu(ImGuiTable* table, ImGuiTableFlags flags_for_section_to_display);
|
||||
IMGUI_API bool TableBeginContextMenuPopup(ImGuiTable* table);
|
||||
@@ -3964,6 +3979,7 @@ IMGUI_API void ImFontAtlasTextureBlockFill(ImTextureData* dst_tex,
|
||||
IMGUI_API void ImFontAtlasTextureBlockCopy(ImTextureData* src_tex, int src_x, int src_y, ImTextureData* dst_tex, int dst_x, int dst_y, int w, int h);
|
||||
IMGUI_API void ImFontAtlasTextureBlockQueueUpload(ImFontAtlas* atlas, ImTextureData* tex, int x, int y, int w, int h);
|
||||
|
||||
IMGUI_API void ImTextureDataQueueUpload(ImTextureData* tex, int x, int y, int w, int h);
|
||||
IMGUI_API int ImTextureDataGetFormatBytesPerPixel(ImTextureFormat format);
|
||||
IMGUI_API const char* ImTextureDataGetStatusName(ImTextureStatus status);
|
||||
IMGUI_API const char* ImTextureDataGetFormatName(ImTextureFormat format);
|
||||
|
||||
Vendored
+171
-80
@@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.92.7
|
||||
// dear imgui, v1.92.8
|
||||
// (main code and documentation)
|
||||
|
||||
// Help:
|
||||
@@ -395,6 +395,31 @@ IMPLEMENTING SUPPORT for ImGuiBackendFlags_RendererHasTextures:
|
||||
When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files.
|
||||
You can read releases logs https://github.com/ocornut/imgui/releases for more details.
|
||||
|
||||
- 2026/05/07 (1.92.8) - DrawList: swapped the last two arguments of AddRect(), AddPolyline(), PathStroke().
|
||||
- Before: void ImDrawList::AddRect(ImVec2 p_min, ImVec2 p_max, ImU32 col, float rounding = 0.0f, ImDrawFlags flags = 0, float thickness = 1.0f);
|
||||
- After: void ImDrawList::AddRect(ImVec2 p_min, ImVec2 p_max, ImU32 col, float rounding = 0.0f, float thickness = 1.0f, ImDrawFlags flags = 0);
|
||||
- Before: void ImDrawList::AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness);
|
||||
- After: void ImDrawList::AddPolyline(const ImVec2* points, int num_points, ImU32 col, float thickness, ImDrawFlags flags = 0);
|
||||
- Before: void ImDrawList::PathStroke(ImU32 col, ImDrawFlags flags = 0, float thickness = 1.0f);
|
||||
- After: void ImDrawList::PathStroke(ImU32 col, float thickness = 1.0f, ImDrawFlags flags = 0);
|
||||
Added inline redirection functions when IMGUI_DISABLE_OBSOLETE_FUNCTIONS is off.
|
||||
Marked the old functions are =delete when IMGUI_DISABLE_OBSOLETE_FUNCTIONS is on, to allow for better type-checking.
|
||||
Effectively the typical call site is changing from:
|
||||
- Before: window->DrawList->AddRect(p_min, p_max, color, rounding, ImDrawFlags_None, border_size);
|
||||
- After: window->DrawList->AddRect(p_min, p_max, color, rounding, border_size);
|
||||
Notes:
|
||||
- Users of C++ and other languages with type-checking will be notified at compile-time of any mistakes.
|
||||
- Users of high-level bindings or languages with no type-checking will be notified at runtime via an assert for invalid flags value.
|
||||
If you are a binding maintainer consider doing something to facilitate transition or error detection.
|
||||
- This is perhaps the worst breaking change in our history :( but it makes ImDrawList function signatures consistent.
|
||||
As we are aiming to add flags and features to variety of ImDrawList functions, that consistency becomes more important.
|
||||
The new order is also more convenient as `flags` are less frequently used than `thickness` in real code.
|
||||
- As a general policy in Dear ImGui, all our flags default to 0 so ImDrawFlags_None was likely written 0 in some call sites.
|
||||
- Consider adding `#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS` in your imconfig.h, even temporarily, to clean up legacy code.
|
||||
- 2026/04/23 (1.92.8) - DrawList: obsoleted `ImDrawCallback_ResetRenderState` in favor of using `ImGui::GetPlatformIO().DrawCallback_ResetRenderState`, which is part of our new standard draw callbacks. (#9378)
|
||||
- 2026/04/22 (1.92.8) - Backends: Vulkan: redesigned to use separate ImageView + Sampler instead of Combined Image Sampler.
|
||||
- When registering custom textures: changed ImGui_ImplVulkan_AddTexture() signature to remove Sampler.
|
||||
- When creating your own descriptor pool (instead of letting backend creates its own): need at least IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE descriptors of type VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE descriptors of type VK_DESCRIPTOR_TYPE_SAMPLER.
|
||||
- 2026/03/19 (1.92.7) - MultiSelect: renamed ImGuiMultiSelectFlags_SelectOnClick to ImGuiMultiSelectFlags_SelectOnAuto.
|
||||
- 2026/02/26 (1.92.7) - Separator: fixed a legacy quirk where Separator() was submitting a zero-height item for layout purpose, even though it draws a 1-pixel separator.
|
||||
The fix could affect code e.g. computing height from multiple widgets in order to allocate vertical space for a footer or multi-line status bar. (#2657, #9263)
|
||||
@@ -1495,7 +1520,7 @@ ImGuiStyle::ImGuiStyle()
|
||||
TabRounding = 5.0f; // Radius of upper corners of a tab. Set to 0.0f to have rectangular tabs.
|
||||
TabBorderSize = 0.0f; // Thickness of border around tabs.
|
||||
TabMinWidthBase = 1.0f; // Minimum tab width, to make tabs larger than their contents. TabBar buttons are not affected.
|
||||
TabMinWidthShrink = 80.0f; // Minimum tab width after shrinking, when using ImGuiTabBarFlags_FittingPolicyMixed policy.
|
||||
TabMinWidthShrink = 80.0f; // Minimum tab width after shrinking, when using ImGuiTabBarFlags_FittingPolicyMixed policy. FLT_MAX: never shrink, will behave like ImGuiTabBarFlags_FittingPolicyScroll.
|
||||
TabCloseButtonMinWidthSelected = -1.0f; // -1: always visible. 0.0f: visible when hovered. >0.0f: visible when hovered if minimum width.
|
||||
TabCloseButtonMinWidthUnselected = 0.0f; // -1: always visible. 0.0f: visible when hovered. >0.0f: visible when hovered if minimum width. FLT_MAX: never show close button when unselected.
|
||||
TabBarBorderSize = 1.0f; // Thickness of tab-bar separator, which takes on the tab active color to denote focus.
|
||||
@@ -1542,6 +1567,7 @@ ImGuiStyle::ImGuiStyle()
|
||||
|
||||
|
||||
// Scale all spacing/padding/thickness values. Do not scale fonts.
|
||||
// Consider not calling this if your initial scale factor if <1.0.
|
||||
// Important: This operation is lossy because we round all sizes to integer. If you need to change your scale multiples, call this over a freshly initialized ImGuiStyle structure rather than scaling multiple times.
|
||||
void ImGuiStyle::ScaleAllSizes(float scale_factor)
|
||||
{
|
||||
@@ -3387,9 +3413,6 @@ static bool ImGuiListClipper_StepInternal(ImGuiListClipper* clipper)
|
||||
if (clipper->ItemsHeight <= 0.0f)
|
||||
{
|
||||
IM_ASSERT(data->StepNo == 1);
|
||||
if (table)
|
||||
IM_ASSERT(table->RowPosY1 == clipper->StartPosY && table->RowPosY2 == window->DC.CursorPos.y);
|
||||
|
||||
bool affected_by_floating_point_precision = ImIsFloatAboveGuaranteedIntegerPrecision((float)clipper->StartPosY) || ImIsFloatAboveGuaranteedIntegerPrecision(window->DC.CursorPos.y);
|
||||
if (affected_by_floating_point_precision)
|
||||
{
|
||||
@@ -3403,7 +3426,14 @@ static bool ImGuiListClipper_StepInternal(ImGuiListClipper* clipper)
|
||||
}
|
||||
if (clipper->ItemsHeight == 0.0f && clipper->ItemsCount == INT_MAX) // Accept that no item have been submitted if in indeterminate mode.
|
||||
return false;
|
||||
IM_ASSERT(clipper->ItemsHeight > 0.0f && "Unable to calculate item height! First item hasn't moved the cursor vertically!");
|
||||
if (clipper->ItemsHeight <= 0.0f)
|
||||
{
|
||||
IM_ASSERT_USER_ERROR(clipper->ItemsHeight > 0.0f, "ImGuiListClipper: Failed to calculate item height! First item hasn't been submitted by user code, or has not moved the cursor vertically!");
|
||||
return false;
|
||||
}
|
||||
if (table)
|
||||
IM_ASSERT(table->RowPosY1 == clipper->StartPosY && table->RowPosY2 == window->DC.CursorPos.y);
|
||||
|
||||
calc_clipping = true; // If item height had to be calculated, calculate clipping afterwards.
|
||||
}
|
||||
|
||||
@@ -3449,12 +3479,14 @@ static bool ImGuiListClipper_StepInternal(ImGuiListClipper* clipper)
|
||||
// FIXME: Selectable() use of half-ItemSpacing isn't consistent in matter of layout, as ItemAdd(bb) stray above ItemSize()'s CursorPos.
|
||||
// RangeSelect's BoxSelect relies on comparing overlap of previous and current rectangle and is sensitive to that.
|
||||
// As a workaround we currently half ItemSpacing worth on each side.
|
||||
min_y -= g.Style.ItemSpacing.y;
|
||||
max_y += g.Style.ItemSpacing.y;
|
||||
float pad_y = g.Style.ItemSpacing.y;
|
||||
min_y -= pad_y;
|
||||
max_y += pad_y;
|
||||
|
||||
// Box-select on 2D area requires different clipping.
|
||||
// (best adding pad_y here than in BeginBoxSelect() as we are closer to current state)
|
||||
if (bs->UnclipMode)
|
||||
data->Ranges.push_back(ImGuiListClipperRange::FromPositions(bs->UnclipRect.Min.y, bs->UnclipRect.Max.y, 0, 0));
|
||||
data->Ranges.push_back(ImGuiListClipperRange::FromPositions(bs->UnclipRect.Min.y - pad_y, bs->UnclipRect.Max.y + pad_y, 0, 0));
|
||||
}
|
||||
|
||||
// Add main visible range
|
||||
@@ -3648,6 +3680,7 @@ static const ImGuiStyleVarInfo GStyleVarsInfo[] =
|
||||
{ 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, TableAngledHeadersTextAlign)},// ImGuiStyleVar_TableAngledHeadersTextAlign
|
||||
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, TreeLinesSize)}, // ImGuiStyleVar_TreeLinesSize
|
||||
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, TreeLinesRounding)}, // ImGuiStyleVar_TreeLinesRounding
|
||||
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, DragDropTargetRounding)}, // ImGuiStyleVar_DragDropTargetRounding
|
||||
{ 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, ButtonTextAlign) }, // ImGuiStyleVar_ButtonTextAlign
|
||||
{ 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, SelectableTextAlign) }, // ImGuiStyleVar_SelectableTextAlign
|
||||
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, SeparatorSize)}, // ImGuiStyleVar_SeparatorSize
|
||||
@@ -3748,6 +3781,7 @@ const char* ImGui::GetStyleColorName(ImGuiCol idx)
|
||||
case ImGuiCol_ScrollbarGrabHovered: return "ScrollbarGrabHovered";
|
||||
case ImGuiCol_ScrollbarGrabActive: return "ScrollbarGrabActive";
|
||||
case ImGuiCol_CheckMark: return "CheckMark";
|
||||
case ImGuiCol_CheckboxSelectedBg: return "CheckboxSelectedBg";
|
||||
case ImGuiCol_SliderGrab: return "SliderGrab";
|
||||
case ImGuiCol_SliderGrabActive: return "SliderGrabActive";
|
||||
case ImGuiCol_Button: return "Button";
|
||||
@@ -3828,7 +3862,7 @@ void ImGui::RenderText(ImVec2 pos, const char* text, const char* text_end, bool
|
||||
else
|
||||
{
|
||||
if (!text_end)
|
||||
text_end = text + ImStrlen(text); // FIXME-OPT
|
||||
text_end = text + ImStrlen(text); // FIXME-OPT (not reached by our internal calls)
|
||||
text_display_end = text_end;
|
||||
}
|
||||
|
||||
@@ -3846,7 +3880,7 @@ void ImGui::RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
|
||||
if (!text_end)
|
||||
text_end = text + ImStrlen(text); // FIXME-OPT
|
||||
text_end = text + ImStrlen(text); // FIXME-OPT (not reached by our internal calls)
|
||||
|
||||
if (text != text_end)
|
||||
{
|
||||
@@ -3915,8 +3949,8 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, con
|
||||
text_end_full = FindRenderedTextEnd(text);
|
||||
const ImVec2 text_size = text_size_if_known ? *text_size_if_known : CalcTextSize(text, text_end_full, false, 0.0f);
|
||||
|
||||
//draw_list->AddLine(ImVec2(pos_max.x, pos_min.y - 4), ImVec2(pos_max.x, pos_max.y + 6), IM_COL32(0, 0, 255, 255));
|
||||
//draw_list->AddLine(ImVec2(ellipsis_max_x, pos_min.y - 2), ImVec2(ellipsis_max_x, pos_max.y + 3), IM_COL32(0, 255, 0, 255));
|
||||
//draw_list->AddLineV(pos_max.x, pos_min.y - 4, pos_max.y + 6, IM_COL32(0, 0, 255, 255));
|
||||
//draw_list->AddLineV(ellipsis_max_x, pos_min.y - 2, pos_max.y + 3, IM_COL32(0, 255, 0, 255));
|
||||
|
||||
// FIXME: We could technically remove (last_glyph->AdvanceX - last_glyph->X1) from text_size.x here and save a few pixels.
|
||||
if (text_size.x > pos_max.x - pos_min.x)
|
||||
@@ -3961,8 +3995,8 @@ void ImGui::RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool borders
|
||||
const float border_size = g.Style.FrameBorderSize;
|
||||
if (borders && border_size > 0.0f)
|
||||
{
|
||||
window->DrawList->AddRect(p_min + ImVec2(1, 1), p_max + ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow), rounding, 0, border_size);
|
||||
window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, 0, border_size);
|
||||
window->DrawList->AddRect(p_min + ImVec2(1, 1), p_max + ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow), rounding, border_size);
|
||||
window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, border_size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3973,8 +4007,8 @@ void ImGui::RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding)
|
||||
const float border_size = g.Style.FrameBorderSize;
|
||||
if (border_size > 0.0f)
|
||||
{
|
||||
window->DrawList->AddRect(p_min + ImVec2(1, 1), p_max + ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow), rounding, 0, border_size);
|
||||
window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, 0, border_size);
|
||||
window->DrawList->AddRect(p_min + ImVec2(1, 1), p_max + ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow), rounding, border_size);
|
||||
window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, border_size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4009,7 +4043,7 @@ void ImGui::RenderNavCursor(const ImRect& bb, ImGuiID id, ImGuiNavRenderCursorFl
|
||||
const float thickness = 2.0f;
|
||||
if (flags & ImGuiNavRenderCursorFlags_Compact)
|
||||
{
|
||||
window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavCursor), rounding, 0, thickness);
|
||||
window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavCursor), rounding, thickness);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -4018,7 +4052,7 @@ void ImGui::RenderNavCursor(const ImRect& bb, ImGuiID id, ImGuiNavRenderCursorFl
|
||||
bool fully_visible = window->ClipRect.Contains(display_rect);
|
||||
if (!fully_visible)
|
||||
window->DrawList->PushClipRect(display_rect.Min, display_rect.Max);
|
||||
window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavCursor), rounding, 0, thickness);
|
||||
window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavCursor), rounding, thickness);
|
||||
if (!fully_visible)
|
||||
window->DrawList->PopClipRect();
|
||||
}
|
||||
@@ -4052,7 +4086,7 @@ void ImGui::RenderMouseCursor(ImVec2 base_pos, float base_scale, ImGuiMouseCurso
|
||||
float a_min = ImFmod((float)g.Time * 5.0f, 2.0f * IM_PI);
|
||||
float a_max = a_min + IM_PI * 1.65f;
|
||||
draw_list->PathArcTo(pos + ImVec2(14, -1) * scale, 6.0f * scale, a_min, a_max);
|
||||
draw_list->PathStroke(col_fill, ImDrawFlags_None, 3.0f * scale);
|
||||
draw_list->PathStroke(col_fill, 3.0f * scale);
|
||||
}
|
||||
draw_list->PopTexture();
|
||||
}
|
||||
@@ -4150,7 +4184,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
|
||||
IO.Fonts = shared_font_atlas ? shared_font_atlas : IM_NEW(ImFontAtlas)();
|
||||
if (shared_font_atlas == NULL)
|
||||
IO.Fonts->OwnerContext = this;
|
||||
WithinEndChildID = 0;
|
||||
WithinEndChildID = WithinEndPopupID = 0;
|
||||
TestEngine = NULL;
|
||||
|
||||
InputEventsNextMouseSource = ImGuiMouseSource_Mouse;
|
||||
@@ -4686,7 +4720,8 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window)
|
||||
g.ActiveIdIsJustActivated = (g.ActiveId != id);
|
||||
if (g.ActiveIdIsJustActivated)
|
||||
{
|
||||
IMGUI_DEBUG_LOG_ACTIVEID("SetActiveID() old:0x%08X (window \"%s\") -> new:0x%08X (window \"%s\")\n", g.ActiveId, g.ActiveIdWindow ? g.ActiveIdWindow->Name : "", id, window ? window->Name : "");
|
||||
IMGUI_DEBUG_LOG_ACTIVEID("SetActiveID() 0x%08X in \"%s\"%*s(previously 0x%08X in \"%s\")\n", id, window ? window->Name : "",
|
||||
ImMax(0, 20 - (int)(window ? strlen(window->Name) : 0)), "", g.ActiveId, g.ActiveIdWindow ? g.ActiveIdWindow->Name : "");
|
||||
g.ActiveIdTimer = 0.0f;
|
||||
g.ActiveIdHasBeenPressedBefore = false;
|
||||
g.ActiveIdHasBeenEditedBefore = false;
|
||||
@@ -4742,8 +4777,12 @@ void ImGui::MarkItemEdited(ImGuiID id)
|
||||
// This marking is to be able to provide info for IsItemDeactivatedAfterEdit().
|
||||
// ActiveId might have been released by the time we call this (as in the typical press/release button behavior) but still need to fill the data.
|
||||
ImGuiContext& g = *GImGui;
|
||||
|
||||
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_EditedInternal;
|
||||
if (g.LastItemData.ItemFlags & ImGuiItemFlags_NoMarkEdited)
|
||||
return;
|
||||
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited;
|
||||
|
||||
if (g.ActiveId == id || g.ActiveId == 0)
|
||||
{
|
||||
// FIXME: Can't we fully rely on LastItemData yet?
|
||||
@@ -4757,9 +4796,6 @@ void ImGui::MarkItemEdited(ImGuiID id)
|
||||
// We accept 'ActiveIdPreviousFrame == id' for InputText() returning an edit after it has been taken ActiveId away (#4714)
|
||||
// FIXME: This assert is getting a bit meaningless over time. It helped detect some unusual use cases but eventually it is becoming an unnecessary restriction.
|
||||
IM_ASSERT(g.DragDropActive || g.ActiveId == id || g.ActiveId == 0 || g.ActiveIdPreviousFrame == id || g.NavJustMovedToId || (g.CurrentMultiSelect != NULL && g.BoxSelectState.IsActive));
|
||||
|
||||
//IM_ASSERT(g.CurrentWindow->DC.LastItemId == id);
|
||||
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited;
|
||||
}
|
||||
|
||||
bool ImGui::IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFlags flags)
|
||||
@@ -4924,7 +4960,7 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id, ImGuiItemFlags item_flag
|
||||
{
|
||||
g.HoveredIdPreviousFrameItemCount++;
|
||||
if (g.DebugDrawIdConflictsId == id)
|
||||
window->DrawList->AddRect(bb.Min - ImVec2(1,1), bb.Max + ImVec2(1,1), IM_COL32(255, 0, 0, 255), 0.0f, ImDrawFlags_None, 2.0f);
|
||||
window->DrawList->AddRect(bb.Min - ImVec2(1,1), bb.Max + ImVec2(1,1), IM_COL32(255, 0, 0, 255), 0.0f, 2.0f);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -5721,7 +5757,7 @@ void ImGui::NewFrame()
|
||||
g.CurrentWindowStack.resize(0);
|
||||
g.BeginPopupStack.resize(0);
|
||||
g.ItemFlagsStack.resize(0);
|
||||
g.ItemFlagsStack.push_back(ImGuiItemFlags_AutoClosePopups); // Default flags
|
||||
g.ItemFlagsStack.push_back(ImGuiItemFlags_Default_); // Default flags
|
||||
g.CurrentItemFlags = g.ItemFlagsStack.back();
|
||||
g.GroupStack.resize(0);
|
||||
|
||||
@@ -5956,7 +5992,7 @@ static void ImGui::RenderDimmedBackgrounds()
|
||||
if (window->DrawList->CmdBuffer.Size == 0)
|
||||
window->DrawList->AddDrawCmd();
|
||||
window->DrawList->PushClipRect(viewport->Pos, viewport->Pos + viewport->Size);
|
||||
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha), window->WindowRounding, 0, 3.0f); // FIXME-DPI
|
||||
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha), window->WindowRounding, 3.0f); // FIXME-DPI
|
||||
window->DrawList->PopClipRect();
|
||||
}
|
||||
}
|
||||
@@ -6432,7 +6468,7 @@ bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, I
|
||||
window_flags |= ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_NoTitleBar;
|
||||
window_flags |= (parent_window->Flags & ImGuiWindowFlags_NoMove); // Inherit the NoMove flag
|
||||
if (child_flags & (ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize))
|
||||
window_flags |= ImGuiWindowFlags_AlwaysAutoResize;
|
||||
window_flags |= ImGuiWindowFlags_AlwaysAutoResize; // FIXME: Would be sane to not make single-axis flag set this. (#9355)
|
||||
if ((child_flags & (ImGuiChildFlags_ResizeX | ImGuiChildFlags_ResizeY)) == 0)
|
||||
window_flags |= ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings;
|
||||
|
||||
@@ -6581,6 +6617,14 @@ void ImGui::EndChild()
|
||||
g.LogLinePosY = -FLT_MAX; // To enforce a carriage return
|
||||
}
|
||||
|
||||
ImGuiWindow* ImGui::FindFrontMostVisibleChildWindow(ImGuiWindow* window)
|
||||
{
|
||||
for (int n = window->DC.ChildWindows.Size - 1; n >= 0; n--)
|
||||
if (IsWindowActiveAndVisible(window->DC.ChildWindows[n]))
|
||||
return FindFrontMostVisibleChildWindow(window->DC.ChildWindows[n]);
|
||||
return window;
|
||||
}
|
||||
|
||||
static void SetWindowConditionAllowFlags(ImGuiWindow* window, ImGuiCond flags, bool enabled)
|
||||
{
|
||||
window->SetWindowPosAllowFlags = enabled ? (window->SetWindowPosAllowFlags | flags) : (window->SetWindowPosAllowFlags & ~flags);
|
||||
@@ -6744,8 +6788,8 @@ static ImVec2 CalcWindowAutoFitSize(ImGuiWindow* window, const ImVec2& size_cont
|
||||
const float decoration_h_without_scrollbars = window->DecoOuterSizeY1 + window->DecoOuterSizeY2 - window->ScrollbarSizes.y;
|
||||
ImVec2 size_pad = window->WindowPadding * 2.0f;
|
||||
ImVec2 size_desired;
|
||||
size_desired[ImGuiAxis_X] = (axis_mask & 1) ? size_contents.x + size_pad.x + decoration_w_without_scrollbars : window->Size.x;
|
||||
size_desired[ImGuiAxis_Y] = (axis_mask & 2) ? size_contents.y + size_pad.y + decoration_h_without_scrollbars : window->Size.y;
|
||||
size_desired.x = (axis_mask & 1) ? size_contents.x + size_pad.x + decoration_w_without_scrollbars : window->Size.x;
|
||||
size_desired.y = (axis_mask & 2) ? size_contents.y + size_pad.y + decoration_h_without_scrollbars : window->Size.y;
|
||||
|
||||
// Determine maximum window size
|
||||
// Child windows are laid within their parent (unless they are also popups/menus) and thus have no restriction
|
||||
@@ -6764,8 +6808,10 @@ static ImVec2 CalcWindowAutoFitSize(ImGuiWindow* window, const ImVec2& size_cont
|
||||
// When the window cannot fit all contents (either because of constraints, either because screen is too small),
|
||||
// we are growing the size on the other axis to compensate for expected scrollbar. FIXME: Might turn bigger than ViewportSize-WindowPadding.
|
||||
ImVec2 size_auto_fit_after_constraint = CalcWindowSizeAfterConstraint(window, size_auto_fit);
|
||||
bool will_have_scrollbar_x = (size_auto_fit_after_constraint.x - size_pad.x - decoration_w_without_scrollbars < size_contents.x && !(window->Flags & ImGuiWindowFlags_NoScrollbar) && (window->Flags & ImGuiWindowFlags_HorizontalScrollbar)) || (window->Flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar);
|
||||
bool will_have_scrollbar_y = (size_auto_fit_after_constraint.y - size_pad.y - decoration_h_without_scrollbars < size_contents.y && !(window->Flags & ImGuiWindowFlags_NoScrollbar)) || (window->Flags & ImGuiWindowFlags_AlwaysVerticalScrollbar);
|
||||
float size_contents_for_scrollbar_x = (axis_mask & 1) ? size_contents.x : window->ContentSize.x; // See #9352. In theory this should use same logic as `window->ScrollbarY = ...` codepath in Begin(). Needs some plumbling.
|
||||
float size_contents_for_scrollbar_y = (axis_mask & 2) ? size_contents.y : window->ContentSize.y;
|
||||
bool will_have_scrollbar_x = (size_auto_fit_after_constraint.x < size_contents_for_scrollbar_x + size_pad.x + decoration_w_without_scrollbars && !(window->Flags & ImGuiWindowFlags_NoScrollbar) && (window->Flags & ImGuiWindowFlags_HorizontalScrollbar)) || (window->Flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar);
|
||||
bool will_have_scrollbar_y = (size_auto_fit_after_constraint.y < size_contents_for_scrollbar_y + size_pad.y + decoration_h_without_scrollbars && !(window->Flags & ImGuiWindowFlags_NoScrollbar)) || (window->Flags & ImGuiWindowFlags_AlwaysVerticalScrollbar);
|
||||
if (will_have_scrollbar_x)
|
||||
size_auto_fit.y += style.ScrollbarSize;
|
||||
if (will_have_scrollbar_y)
|
||||
@@ -7106,7 +7152,7 @@ static void RenderWindowOuterSingleBorder(ImGuiWindow* window, int border_n, ImU
|
||||
const ImRect border_r = GetResizeBorderRect(window, border_n, rounding, 0.0f);
|
||||
window->DrawList->PathArcTo(ImLerp(border_r.Min, border_r.Max, def.SegmentN1) + ImVec2(0.5f, 0.5f) + def.InnerDir * rounding, rounding, def.OuterAngle - IM_PI * 0.25f, def.OuterAngle);
|
||||
window->DrawList->PathArcTo(ImLerp(border_r.Min, border_r.Max, def.SegmentN2) + ImVec2(0.5f, 0.5f) + def.InnerDir * rounding, rounding, def.OuterAngle, def.OuterAngle + IM_PI * 0.25f);
|
||||
window->DrawList->PathStroke(border_col, ImDrawFlags_None, border_size);
|
||||
window->DrawList->PathStroke(border_col, border_size);
|
||||
}
|
||||
|
||||
static void ImGui::RenderWindowOuterBorders(ImGuiWindow* window)
|
||||
@@ -7115,7 +7161,7 @@ static void ImGui::RenderWindowOuterBorders(ImGuiWindow* window)
|
||||
const float border_size = window->WindowBorderSize;
|
||||
const ImU32 border_col = GetColorU32(ImGuiCol_Border);
|
||||
if (border_size > 0.0f && (window->Flags & ImGuiWindowFlags_NoBackground) == 0)
|
||||
window->DrawList->AddRect(window->Pos, window->Pos + window->Size, border_col, window->WindowRounding, 0, window->WindowBorderSize);
|
||||
window->DrawList->AddRect(window->Pos, window->Pos + window->Size, border_col, window->WindowRounding, window->WindowBorderSize);
|
||||
else if (border_size > 0.0f)
|
||||
{
|
||||
if (window->ChildFlags & ImGuiChildFlags_ResizeX) // Similar code as 'resize_border_mask' computation in UpdateWindowManualResize() but we specifically only always draw explicit child resize border.
|
||||
@@ -7132,7 +7178,7 @@ static void ImGui::RenderWindowOuterBorders(ImGuiWindow* window)
|
||||
if (g.Style.FrameBorderSize > 0 && !(window->Flags & ImGuiWindowFlags_NoTitleBar))
|
||||
{
|
||||
float y = window->Pos.y + window->TitleBarHeight - 1;
|
||||
window->DrawList->AddLine(ImVec2(window->Pos.x + border_size * 0.5f, y), ImVec2(window->Pos.x + window->Size.x - border_size * 0.5f, y), border_col, g.Style.FrameBorderSize);
|
||||
window->DrawList->AddLineH(window->Pos.x + border_size * 0.5f, window->Pos.x + window->Size.x - border_size * 0.5f, y, border_col, g.Style.FrameBorderSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7180,7 +7226,7 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar
|
||||
if (bg_col & IM_COL32_A_MASK)
|
||||
{
|
||||
ImRect bg_rect(window->Pos + ImVec2(0, window->TitleBarHeight), window->Pos + window->Size);
|
||||
ImDrawFlags bg_rounding_flags = (flags & ImGuiWindowFlags_NoTitleBar) ? 0 : ImDrawFlags_RoundCornersBottom;
|
||||
ImDrawFlags bg_rounding_flags = (flags & ImGuiWindowFlags_NoTitleBar) ? ImDrawFlags_RoundCornersAll : ImDrawFlags_RoundCornersBottom;
|
||||
ImDrawList* bg_draw_list = window->DrawList;
|
||||
bg_draw_list->AddRectFilled(bg_rect.Min, bg_rect.Max, bg_col, window_rounding, bg_rounding_flags);
|
||||
}
|
||||
@@ -7200,7 +7246,7 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar
|
||||
menu_bar_rect.ClipWith(window->Rect()); // Soft clipping, in particular child window don't have minimum size covering the menu bar so this is useful for them.
|
||||
window->DrawList->AddRectFilled(menu_bar_rect.Min, menu_bar_rect.Max, GetColorU32(ImGuiCol_MenuBarBg), (flags & ImGuiWindowFlags_NoTitleBar) ? window_rounding : 0.0f, ImDrawFlags_RoundCornersTop);
|
||||
if (style.FrameBorderSize > 0.0f && menu_bar_rect.Max.y < window->Pos.y + window->Size.y)
|
||||
window->DrawList->AddLine(menu_bar_rect.GetBL() + ImVec2(window_border_size * 0.5f, 0.0f), menu_bar_rect.GetBR() - ImVec2(window_border_size * 0.5f, 0.0f), GetColorU32(ImGuiCol_Border), style.FrameBorderSize);
|
||||
window->DrawList->AddLineH(menu_bar_rect.Min.x + window_border_size * 0.5f, menu_bar_rect.Max.x - window_border_size * 0.5f, menu_bar_rect.Max.y, GetColorU32(ImGuiCol_Border), style.FrameBorderSize);
|
||||
}
|
||||
|
||||
// Scrollbars
|
||||
@@ -7844,12 +7890,12 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
||||
ImVec2 avail_size_from_current_frame = ImVec2(window->SizeFull.x, window->SizeFull.y - (window->DecoOuterSizeY1 + window->DecoOuterSizeY2));
|
||||
ImVec2 avail_size_from_last_frame = window->InnerRect.GetSize() + scrollbar_sizes_from_last_frame;
|
||||
ImVec2 needed_size_from_last_frame = window_just_created ? ImVec2(0, 0) : window->ContentSize + window->WindowPadding * 2.0f;
|
||||
float size_x_for_scrollbars = use_current_size_for_scrollbar_x ? avail_size_from_current_frame.x : avail_size_from_last_frame.x;
|
||||
float size_y_for_scrollbars = use_current_size_for_scrollbar_y ? avail_size_from_current_frame.y : avail_size_from_last_frame.y;
|
||||
float size_for_scrollbars_x = use_current_size_for_scrollbar_x ? avail_size_from_current_frame.x : avail_size_from_last_frame.x;
|
||||
float size_for_scrollbars_y = use_current_size_for_scrollbar_y ? avail_size_from_current_frame.y : avail_size_from_last_frame.y;
|
||||
bool scrollbar_x_prev = window->ScrollbarX;
|
||||
//bool scrollbar_y_from_last_frame = window->ScrollbarY; // FIXME: May want to use that in the ScrollbarX expression? How many pros vs cons?
|
||||
window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((needed_size_from_last_frame.y > size_y_for_scrollbars) && !(flags & ImGuiWindowFlags_NoScrollbar));
|
||||
window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((needed_size_from_last_frame.x > size_x_for_scrollbars - (window->ScrollbarY ? style.ScrollbarSize : 0.0f)) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar));
|
||||
window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((needed_size_from_last_frame.y > size_for_scrollbars_y) && !(flags & ImGuiWindowFlags_NoScrollbar));
|
||||
window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((needed_size_from_last_frame.x > size_for_scrollbars_x - (window->ScrollbarY ? style.ScrollbarSize : 0.0f)) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar));
|
||||
|
||||
// Track when ScrollbarX visibility keeps toggling, which is a sign of a feedback loop, and stabilize by enforcing visibility (#3285, #8488)
|
||||
// (Feedback loops of this sort can manifest in various situations, but combining horizontal + vertical scrollbar + using a clipper with varying width items is one frequent cause.
|
||||
@@ -7864,7 +7910,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
||||
window->ScrollbarXStabilizeEnabled = scrollbar_x_stabilize;
|
||||
|
||||
if (window->ScrollbarX && !window->ScrollbarY)
|
||||
window->ScrollbarY = (needed_size_from_last_frame.y > size_y_for_scrollbars - style.ScrollbarSize) && !(flags & ImGuiWindowFlags_NoScrollbar);
|
||||
window->ScrollbarY = (needed_size_from_last_frame.y > size_for_scrollbars_y - style.ScrollbarSize) && !(flags & ImGuiWindowFlags_NoScrollbar);
|
||||
window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f);
|
||||
|
||||
// Amend the partially filled window->DecorationXXX values.
|
||||
@@ -8029,9 +8075,14 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
||||
window->DC.LayoutType = ImGuiLayoutType_Vertical;
|
||||
window->DC.ParentLayoutType = parent_window ? parent_window->DC.LayoutType : ImGuiLayoutType_Vertical;
|
||||
|
||||
// Default item width. Make it proportional to window size if window manually resizes
|
||||
const bool is_resizable_window = (window->Size.x > 0.0f && !(flags & ImGuiWindowFlags_Tooltip) && !(flags & ImGuiWindowFlags_AlwaysAutoResize));
|
||||
if (is_resizable_window)
|
||||
// Default item width. Make it proportional to window size if window can be manually resized.
|
||||
// (we cannot use AutoFitFramesX/AutoFitFramesY which is a temporary state)
|
||||
bool is_resizable_width;
|
||||
if (flags & ImGuiWindowFlags_ChildWindow)
|
||||
is_resizable_width = (window->Size.x > 0.0f) && !(window->ChildFlags & (ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AlwaysAutoResize));
|
||||
else
|
||||
is_resizable_width = (window->Size.x > 0.0f) && !(flags & ImGuiWindowFlags_AlwaysAutoResize);
|
||||
if (is_resizable_width)
|
||||
window->DC.ItemWidthDefault = ImTrunc(window->Size.x * 0.65f);
|
||||
else
|
||||
window->DC.ItemWidthDefault = ImTrunc(g.FontSize * 16.0f);
|
||||
@@ -8201,6 +8252,8 @@ void ImGui::End()
|
||||
ImGuiWindowStackData& window_stack_data = g.CurrentWindowStack.back();
|
||||
|
||||
// Error checking: verify that user doesn't directly call End() on a child window.
|
||||
if (window->Flags & ImGuiWindowFlags_Popup)
|
||||
IM_ASSERT_USER_ERROR(g.WithinEndPopupID == window->ID, "Must call EndPopup() and not End()!");
|
||||
if (window->Flags & ImGuiWindowFlags_ChildWindow)
|
||||
IM_ASSERT_USER_ERROR(g.WithinEndChildID == window->ID, "Must call EndChild() and not End()!");
|
||||
|
||||
@@ -8738,6 +8791,17 @@ void ImGui::PopFocusScope()
|
||||
g.CurrentFocusScopeId = g.FocusScopeStack.Size ? g.FocusScopeStack.back().ID : 0;
|
||||
}
|
||||
|
||||
bool ImGui::IsInNavFocusRoute(ImGuiID focus_scope_id)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (g.NavFocusScopeId == focus_scope_id)
|
||||
return true;
|
||||
for (const ImGuiFocusScopeData& focus_scope : g.NavFocusRoute)
|
||||
if (focus_scope.ID == focus_scope_id)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void ImGui::SetNavFocusScope(ImGuiID focus_scope_id)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
@@ -8972,7 +9036,7 @@ ImFont* ImGui::GetDefaultFont()
|
||||
return g.IO.FontDefault ? g.IO.FontDefault : atlas->Fonts[0];
|
||||
}
|
||||
|
||||
// EXPERIMENTAL: DO NOT USE YET.
|
||||
// EXPERIMENTAL. Use ImTextureDataQueueUpload() to queue updates.
|
||||
void ImGui::RegisterUserTexture(ImTextureData* tex)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
@@ -9094,7 +9158,7 @@ void ImGui::UpdateCurrentFontSize(float restore_font_size_after_scaling)
|
||||
}
|
||||
|
||||
g.FontBaked = (g.Font != NULL && window != NULL) ? g.Font->GetFontBaked(final_size) : NULL;
|
||||
g.FontBakedScale = (g.Font != NULL && window != NULL) ? (g.FontSize / g.FontBaked->Size) : 0.0f;
|
||||
g.FontBakedScale = (g.FontBaked != NULL) ? (g.FontSize / g.FontBaked->Size) : 0.0f;
|
||||
g.DrawListSharedData.FontScale = g.FontBakedScale;
|
||||
}
|
||||
|
||||
@@ -10302,15 +10366,21 @@ void ImGui::UpdateMouseWheel()
|
||||
LockWheelingWindow(NULL, 0.0f);
|
||||
}
|
||||
|
||||
ImVec2 wheel;
|
||||
wheel.x = TestKeyOwner(ImGuiKey_MouseWheelX, ImGuiKeyOwner_NoOwner) ? g.IO.MouseWheelH : 0.0f;
|
||||
wheel.y = TestKeyOwner(ImGuiKey_MouseWheelY, ImGuiKeyOwner_NoOwner) ? g.IO.MouseWheel : 0.0f;
|
||||
|
||||
//IMGUI_DEBUG_LOG("MouseWheel X:%.3f Y:%.3f\n", wheel_x, wheel_y);
|
||||
ImGuiWindow* mouse_window = g.WheelingWindow ? g.WheelingWindow : g.HoveredWindow;
|
||||
if (!mouse_window || mouse_window->Collapsed)
|
||||
return;
|
||||
|
||||
ImGuiID owner_id = mouse_window->ID;
|
||||
ImVec2 wheel;
|
||||
wheel.x = TestKeyOwner(ImGuiKey_MouseWheelX, owner_id) ? g.IO.MouseWheelH : 0.0f;
|
||||
wheel.y = TestKeyOwner(ImGuiKey_MouseWheelY, owner_id) ? g.IO.MouseWheel : 0.0f;
|
||||
//IMGUI_DEBUG_LOG("MouseWheel X:%.3f Y:%.3f\n", wheel_x, wheel_y);
|
||||
if (g.WheelingWindow != NULL)
|
||||
{
|
||||
SetKeyOwner(ImGuiKey_MouseWheelX, owner_id);
|
||||
SetKeyOwner(ImGuiKey_MouseWheelY, owner_id);
|
||||
}
|
||||
|
||||
// Zoom / Scale window
|
||||
// FIXME-OBSOLETE: This is an old feature, it still works but pretty much nobody is using it and may be best redesigned.
|
||||
if (wheel.y != 0.0f && g.IO.KeyCtrl && g.IO.FontAllowUserScaling)
|
||||
@@ -10614,6 +10684,7 @@ bool ImGui::TestKeyOwner(ImGuiKey key, ImGuiID owner_id)
|
||||
// - SetKeyOwner(..., None) : clears owner
|
||||
// - SetKeyOwner(..., Any, !Lock) : illegal (assert)
|
||||
// - SetKeyOwner(..., Any or None, Lock) : set lock
|
||||
// Ownership is automatically released on the frame after a release, see code in UpdateKeyboardInputs().
|
||||
void ImGui::SetKeyOwner(ImGuiKey key, ImGuiID owner_id, ImGuiInputFlags flags)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
@@ -10640,30 +10711,34 @@ void ImGui::SetKeyOwnersForKeyChord(ImGuiKeyChord key_chord, ImGuiID owner_id, I
|
||||
if (key_chord & ~ImGuiMod_Mask_) { SetKeyOwner((ImGuiKey)(key_chord & ~ImGuiMod_Mask_), owner_id, flags); }
|
||||
}
|
||||
|
||||
// This is more or less equivalent to:
|
||||
// This is more or less equivalent to a fancier version of:
|
||||
// if (IsItemHovered() || IsItemActive())
|
||||
// SetKeyOwner(key, GetItemID());
|
||||
// Extensive uses of that (e.g. many calls for a single item) may want to manually perform the tests once and then call SetKeyOwner() multiple times.
|
||||
// More advanced usage scenarios may want to call SetKeyOwner() manually based on different condition.
|
||||
// Worth noting is that only one item can be hovered and only one item can be active, therefore this usage pattern doesn't need to bother with routing and priority.
|
||||
void ImGui::SetItemKeyOwner(ImGuiKey key, ImGuiInputFlags flags)
|
||||
bool ImGui::SetItemKeyOwner(ImGuiKey key, ImGuiInputFlags flags)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiID id = g.LastItemData.ID;
|
||||
if (id == 0 || (g.HoveredId != id && g.ActiveId != id))
|
||||
return;
|
||||
return false;
|
||||
if ((flags & ImGuiInputFlags_CondMask_) == 0)
|
||||
flags |= ImGuiInputFlags_CondDefault_;
|
||||
if ((g.HoveredId == id && (flags & ImGuiInputFlags_CondHovered)) || (g.ActiveId == id && (flags & ImGuiInputFlags_CondActive)))
|
||||
{
|
||||
IM_ASSERT((flags & ~ImGuiInputFlags_SupportedBySetItemKeyOwner) == 0); // Passing flags not supported by this function!
|
||||
if (!TestKeyOwner(key, id))
|
||||
return false;
|
||||
SetKeyOwner(key, id, flags & ~ImGuiInputFlags_CondMask_);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ImGui::SetItemKeyOwner(ImGuiKey key)
|
||||
bool ImGui::SetItemKeyOwner(ImGuiKey key)
|
||||
{
|
||||
SetItemKeyOwner(key, ImGuiInputFlags_None);
|
||||
return SetItemKeyOwner(key, ImGuiInputFlags_None);
|
||||
}
|
||||
|
||||
// This is the only public API until we expose owner_id versions of the API as replacements.
|
||||
@@ -10804,7 +10879,8 @@ bool ImGui::DebugCheckVersionAndDataLayout(const char* version, size_t sz_io, si
|
||||
// to extend contents size of our parent container (e.g. window contents size, which is used for auto-resizing
|
||||
// windows, table column contents size used for auto-resizing columns, group size).
|
||||
// This was causing issues and ambiguities and we needed to retire that.
|
||||
// From 1.89, extending contents size boundaries REQUIRES AN ITEM TO BE SUBMITTED.
|
||||
// 2022/08/05 (1.89): extending contents size boundaries REQUIRES AN ITEM TO BE SUBMITTED. However we gated the new logic behind a '#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS' block.
|
||||
// 2025/06/25 (1.92): removed the legacy path and turned into an assert. It was a mistake that there was a #ifndef before: our obsolescence schedule gets pushed back a bit more :(
|
||||
//
|
||||
// Previously this would make the window content size ~200x200:
|
||||
// Begin(...) + SetCursorScreenPos(GetCursorScreenPos() + ImVec2(200,200)) + End(); // NOT OK ANYMORE
|
||||
@@ -12413,6 +12489,17 @@ bool ImGui::BeginPopupMenuEx(ImGuiID id, const char* label, ImGuiWindowFlags ext
|
||||
return false;
|
||||
}
|
||||
|
||||
// As we bypass BeginChild(), set ImGuiChildFlags_AlwaysAutoResize as it is checked independently from ImGuiWindowFlags_AlwaysAutoResize for now (see #9355)
|
||||
// Ideally we should remove setting ImGuiWindowFlags_AlwaysAutoResize in BeginChild().
|
||||
if ((extra_window_flags & ImGuiWindowFlags_ChildWindow) && (extra_window_flags & ImGuiWindowFlags_AlwaysAutoResize))
|
||||
{
|
||||
if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasChildFlags)
|
||||
g.NextWindowData.ChildFlags |= ImGuiChildFlags_AlwaysAutoResize;
|
||||
else
|
||||
g.NextWindowData.ChildFlags = ImGuiChildFlags_AlwaysAutoResize;
|
||||
g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasChildFlags;
|
||||
}
|
||||
|
||||
char name[128];
|
||||
IM_ASSERT(extra_window_flags & ImGuiWindowFlags_ChildMenu);
|
||||
ImFormatString(name, IM_COUNTOF(name), "%s###Menu_%02d", label, g.BeginMenuDepth); // Recycle windows based on depth
|
||||
@@ -12485,10 +12572,13 @@ void ImGui::EndPopup()
|
||||
NavMoveRequestTryWrapping(window, ImGuiNavMoveFlags_LoopY);
|
||||
|
||||
// Child-popups don't need to be laid out
|
||||
const ImGuiID backup_within_end_popup_id = g.WithinEndPopupID;
|
||||
const ImGuiID backup_within_end_child_id = g.WithinEndChildID;
|
||||
g.WithinEndPopupID = window->ID;
|
||||
if (window->Flags & ImGuiWindowFlags_ChildWindow)
|
||||
g.WithinEndChildID = window->ID;
|
||||
End();
|
||||
g.WithinEndPopupID = backup_within_end_popup_id;
|
||||
g.WithinEndChildID = backup_within_end_child_id;
|
||||
}
|
||||
|
||||
@@ -13310,7 +13400,7 @@ static void ImGui::NavProcessItem()
|
||||
const ImGuiID id = g.LastItemData.ID;
|
||||
const ImGuiItemFlags item_flags = g.LastItemData.ItemFlags;
|
||||
|
||||
// When inside a container that isn't scrollable with Left<>Right, clip NavRect accordingly (#2221, #8816)
|
||||
// When inside a container that isn't scrollable with Left<>Right, clip NavRect accordingly (#2221, #8816, #7994)
|
||||
ImRect nav_bb = g.LastItemData.NavRect;
|
||||
if (window->DC.NavIsScrollPushableX == false)
|
||||
{
|
||||
@@ -15074,7 +15164,7 @@ const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDrop
|
||||
{
|
||||
ImRect bb = g.DragDropTargetRect;
|
||||
bb.Expand(-3.5f);
|
||||
RenderDragDropTargetRectEx(GetForegroundDrawList(), bb);
|
||||
RenderDragDropTargetRectEx(GetForegroundDrawList(), bb, g.Style.DragDropTargetRounding);
|
||||
}
|
||||
else if (draw_target_rect)
|
||||
{
|
||||
@@ -15105,16 +15195,16 @@ void ImGui::RenderDragDropTargetRectForItem(const ImRect& bb)
|
||||
bool push_clip_rect = !window->ClipRect.Contains(bb_display);
|
||||
if (push_clip_rect)
|
||||
window->DrawList->PushClipRectFullScreen();
|
||||
RenderDragDropTargetRectEx(window->DrawList, bb_display);
|
||||
RenderDragDropTargetRectEx(window->DrawList, bb_display, g.Style.DragDropTargetRounding);
|
||||
if (push_clip_rect)
|
||||
window->DrawList->PopClipRect();
|
||||
}
|
||||
|
||||
void ImGui::RenderDragDropTargetRectEx(ImDrawList* draw_list, const ImRect& bb)
|
||||
void ImGui::RenderDragDropTargetRectEx(ImDrawList* draw_list, const ImRect& bb, float rounding)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
draw_list->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_DragDropTargetBg), g.Style.DragDropTargetRounding, 0);
|
||||
draw_list->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_DragDropTarget), g.Style.DragDropTargetRounding, 0, g.Style.DragDropTargetBorderSize);
|
||||
draw_list->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_DragDropTargetBg), rounding, 0);
|
||||
draw_list->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_DragDropTarget), rounding, g.Style.DragDropTargetBorderSize);
|
||||
}
|
||||
|
||||
const ImGuiPayload* ImGui::GetDragDropPayload()
|
||||
@@ -15774,6 +15864,7 @@ void ImGuiPlatformIO::ClearRendererHandlers()
|
||||
{
|
||||
Renderer_TextureMaxWidth = Renderer_TextureMaxHeight = 0;
|
||||
Renderer_RenderState = NULL;
|
||||
DrawCallback_ResetRenderState = DrawCallback_SetSamplerLinear = DrawCallback_SetSamplerNearest = NULL;
|
||||
}
|
||||
|
||||
ImGuiViewport* ImGui::GetMainViewport()
|
||||
@@ -16215,7 +16306,7 @@ void ImGui::DebugRenderKeyboardPreview(ImDrawList* draw_list)
|
||||
draw_list->AddRect(key_min, key_max, IM_COL32(24, 24, 24, 255), key_rounding);
|
||||
ImVec2 face_min = ImVec2(key_min.x + key_face_pos.x, key_min.y + key_face_pos.y);
|
||||
ImVec2 face_max = ImVec2(face_min.x + key_face_size.x, face_min.y + key_face_size.y);
|
||||
draw_list->AddRect(face_min, face_max, IM_COL32(193, 193, 193, 255), key_face_rounding, ImDrawFlags_None, 2.0f);
|
||||
draw_list->AddRect(face_min, face_max, IM_COL32(193, 193, 193, 255), key_face_rounding, 2.0f);
|
||||
draw_list->AddRectFilled(face_min, face_max, IM_COL32(252, 252, 252, 255), key_face_rounding);
|
||||
ImVec2 label_min = ImVec2(key_min.x + key_label_pos.x, key_min.y + key_label_pos.y);
|
||||
draw_list->AddText(label_min, IM_COL32(64, 64, 64, 255), key_data->Label);
|
||||
@@ -16638,7 +16729,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
|
||||
BulletText("Table 0x%08X (%d columns, in '%s')", table->ID, table->ColumnsCount, table->OuterWindow->Name);
|
||||
if (IsItemHovered())
|
||||
GetForegroundDrawList(table->OuterWindow)->AddRect(table->OuterRect.Min - ImVec2(1, 1), table->OuterRect.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, 0, 2.0f);
|
||||
GetForegroundDrawList(table->OuterWindow)->AddRect(table->OuterRect.Min - ImVec2(1, 1), table->OuterRect.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, 2.0f);
|
||||
Indent();
|
||||
char buf[128];
|
||||
for (int rect_n = 0; rect_n < TRT_Count; rect_n++)
|
||||
@@ -16653,7 +16744,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
ImFormatString(buf, IM_COUNTOF(buf), "(%6.1f,%6.1f) (%6.1f,%6.1f) Size (%6.1f,%6.1f) Col %d %s", r.Min.x, r.Min.y, r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight(), column_n, trt_rects_names[rect_n]);
|
||||
Selectable(buf);
|
||||
if (IsItemHovered())
|
||||
GetForegroundDrawList(table->OuterWindow)->AddRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, 0, 2.0f);
|
||||
GetForegroundDrawList(table->OuterWindow)->AddRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, 2.0f);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -16662,7 +16753,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
ImFormatString(buf, IM_COUNTOF(buf), "(%6.1f,%6.1f) (%6.1f,%6.1f) Size (%6.1f,%6.1f) %s", r.Min.x, r.Min.y, r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight(), trt_rects_names[rect_n]);
|
||||
Selectable(buf);
|
||||
if (IsItemHovered())
|
||||
GetForegroundDrawList(table->OuterWindow)->AddRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, 0, 2.0f);
|
||||
GetForegroundDrawList(table->OuterWindow)->AddRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, 2.0f);
|
||||
}
|
||||
}
|
||||
Unindent();
|
||||
@@ -17070,7 +17161,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
ImRect r = Funcs::GetTableRect(table, cfg->ShowTablesRectsType, column_n);
|
||||
ImU32 col = (table->HoveredColumnBody == column_n) ? IM_COL32(255, 255, 128, 255) : IM_COL32(255, 0, 128, 255);
|
||||
float thickness = (table->HoveredColumnBody == column_n) ? 3.0f : 1.0f;
|
||||
draw_list->AddRect(r.Min, r.Max, col, 0.0f, 0, thickness);
|
||||
draw_list->AddRect(r.Min, r.Max, col, 0.0f, thickness);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -17247,7 +17338,7 @@ void ImGui::DebugNodeDrawList(ImGuiWindow* window, ImGuiViewportP* viewport, con
|
||||
{
|
||||
ImDrawListFlags backup_flags = fg_draw_list->Flags;
|
||||
fg_draw_list->Flags &= ~ImDrawListFlags_AntiAliasedLines; // Disable AA on triangle outlines is more readable for very large and thin triangles.
|
||||
fg_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), ImDrawFlags_Closed, 1.0f);
|
||||
fg_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), 1.0f, ImDrawFlags_Closed);
|
||||
fg_draw_list->Flags = backup_flags;
|
||||
}
|
||||
}
|
||||
@@ -17275,7 +17366,7 @@ void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list, co
|
||||
for (int n = 0; n < 3; n++, idx_n++)
|
||||
vtxs_rect.Add((triangle[n] = vtx_buffer[idx_buffer ? idx_buffer[idx_n] : idx_n].pos));
|
||||
if (show_mesh)
|
||||
out_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), ImDrawFlags_Closed, 1.0f); // In yellow: mesh triangles
|
||||
out_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), 1.0f, ImDrawFlags_Closed); // In yellow: mesh triangles
|
||||
}
|
||||
// Draw bounding boxes
|
||||
if (show_aabb)
|
||||
@@ -17556,8 +17647,8 @@ void ImGui::DebugNodeTabBar(ImGuiTabBar* tab_bar, const char* label)
|
||||
{
|
||||
ImDrawList* draw_list = GetForegroundDrawList(tab_bar->Window);
|
||||
draw_list->AddRect(tab_bar->BarRect.Min, tab_bar->BarRect.Max, IM_COL32(255, 255, 0, 255));
|
||||
draw_list->AddLine(ImVec2(tab_bar->ScrollingRectMinX, tab_bar->BarRect.Min.y), ImVec2(tab_bar->ScrollingRectMinX, tab_bar->BarRect.Max.y), IM_COL32(0, 255, 0, 255));
|
||||
draw_list->AddLine(ImVec2(tab_bar->ScrollingRectMaxX, tab_bar->BarRect.Min.y), ImVec2(tab_bar->ScrollingRectMaxX, tab_bar->BarRect.Max.y), IM_COL32(0, 255, 0, 255));
|
||||
draw_list->AddLineV(tab_bar->ScrollingRectMinX, tab_bar->BarRect.Min.y, tab_bar->BarRect.Max.y, IM_COL32(0, 255, 0, 255));
|
||||
draw_list->AddLineV(tab_bar->ScrollingRectMaxX, tab_bar->BarRect.Min.y, tab_bar->BarRect.Max.y, IM_COL32(0, 255, 0, 255));
|
||||
}
|
||||
if (open)
|
||||
{
|
||||
@@ -17886,8 +17977,8 @@ void ImGui::DebugDrawCursorPos(ImU32 col)
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
ImVec2 pos = window->DC.CursorPos;
|
||||
window->DrawList->AddLine(ImVec2(pos.x, pos.y - 3.0f), ImVec2(pos.x, pos.y + 4.0f), col, 1.0f);
|
||||
window->DrawList->AddLine(ImVec2(pos.x - 3.0f, pos.y), ImVec2(pos.x + 4.0f, pos.y), col, 1.0f);
|
||||
window->DrawList->AddLineV(pos.x, pos.y - 3.0f, pos.y + 4.0f, col, 1.0f);
|
||||
window->DrawList->AddLineH(pos.x - 3.0f, pos.x + 4.0f, pos.y, col, 1.0f);
|
||||
}
|
||||
|
||||
// Draw a 10px wide rectangle around CurposPos.x using Line Y1/Y2 in current window's DrawList
|
||||
@@ -17898,9 +17989,9 @@ void ImGui::DebugDrawLineExtents(ImU32 col)
|
||||
float curr_x = window->DC.CursorPos.x;
|
||||
float line_y1 = (window->DC.IsSameLine ? window->DC.CursorPosPrevLine.y : window->DC.CursorPos.y);
|
||||
float line_y2 = line_y1 + (window->DC.IsSameLine ? window->DC.PrevLineSize.y : window->DC.CurrLineSize.y);
|
||||
window->DrawList->AddLine(ImVec2(curr_x - 5.0f, line_y1), ImVec2(curr_x + 5.0f, line_y1), col, 1.0f);
|
||||
window->DrawList->AddLine(ImVec2(curr_x - 0.5f, line_y1), ImVec2(curr_x - 0.5f, line_y2), col, 1.0f);
|
||||
window->DrawList->AddLine(ImVec2(curr_x - 5.0f, line_y2), ImVec2(curr_x + 5.0f, line_y2), col, 1.0f);
|
||||
window->DrawList->AddLineH(curr_x - 5.0f, curr_x + 5.0f, line_y1, col, 1.0f);
|
||||
window->DrawList->AddLineV(curr_x - 0.5f, line_y1, line_y2, col, 1.0f);
|
||||
window->DrawList->AddLineH(curr_x - 5.0f, curr_x + 5.0f, line_y2, col, 1.0f);
|
||||
}
|
||||
|
||||
// Draw last item rect in ForegroundDrawList (so it is always visible)
|
||||
@@ -18270,7 +18361,7 @@ void ImGui::ShowFontSelector(const char* label)
|
||||
"- Load additional fonts with io.Fonts->AddFontXXX() functions.\n"
|
||||
"- The font atlas is built when calling io.Fonts->GetTexDataAsXXXX() or io.Fonts->Build().\n"
|
||||
"- Read FAQ and docs/FONTS.md for more details.\n"
|
||||
"- If you need to add/remove fonts at runtime (e.g. for DPI change), do it before calling NewFrame().");
|
||||
"- Legacy backend: if you need to add/remove fonts at runtime (e.g. for DPI change), do it before calling NewFrame().");
|
||||
}
|
||||
#endif // #if !defined(IMGUI_DISABLE_DEMO_WINDOWS) || !defined(IMGUI_DISABLE_DEBUG_TOOLS)
|
||||
|
||||
|
||||
Vendored
+154
-46
@@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.92.7
|
||||
// dear imgui, v1.92.8
|
||||
// (demo code)
|
||||
|
||||
// Help:
|
||||
@@ -73,6 +73,7 @@ Index of this file:
|
||||
// [SECTION] Demo Window / ShowDemoWindow()
|
||||
// [SECTION] DemoWindowMenuBar()
|
||||
// [SECTION] Helpers: ExampleTreeNode, ExampleMemberInfo (for use by Property Editor & Multi-Select demos)
|
||||
// [SECTION] Helpers: ExampleImageViewer
|
||||
// [SECTION] DemoWindowWidgetsBasic()
|
||||
// [SECTION] DemoWindowWidgetsBullets()
|
||||
// [SECTION] DemoWindowWidgetsCollapsingHeaders()
|
||||
@@ -108,6 +109,7 @@ Index of this file:
|
||||
// [SECTION] User Guide / ShowUserGuide()
|
||||
// [SECTION] Example App: Main Menu Bar / ShowExampleAppMainMenuBar()
|
||||
// [SECTION] Example App: Debug Console / ShowExampleAppConsole()
|
||||
// [SECTION] Example App: Image Viewer / ShowExampleAppImageViewer()
|
||||
// [SECTION] Example App: Debug Log / ShowExampleAppLog()
|
||||
// [SECTION] Example App: Simple Layout / ShowExampleAppLayout()
|
||||
// [SECTION] Example App: Property Editor / ShowExampleAppPropertyEditor()
|
||||
@@ -238,6 +240,7 @@ static void ShowExampleAppAssetsBrowser(bool* p_open);
|
||||
static void ShowExampleAppConsole(bool* p_open);
|
||||
static void ShowExampleAppCustomRendering(bool* p_open);
|
||||
static void ShowExampleAppDocuments(bool* p_open);
|
||||
static void ShowExampleAppImageViewer(bool* p_open);
|
||||
static void ShowExampleAppLog(bool* p_open);
|
||||
static void ShowExampleAppLayout(bool* p_open);
|
||||
static void ShowExampleAppPropertyEditor(bool* p_open, ImGuiDemoWindowData* demo_data);
|
||||
@@ -308,6 +311,7 @@ struct ImGuiDemoWindowData
|
||||
bool ShowAppConsole = false;
|
||||
bool ShowAppCustomRendering = false;
|
||||
bool ShowAppDocuments = false;
|
||||
bool ShowAppImageViewer = false;
|
||||
bool ShowAppLog = false;
|
||||
bool ShowAppLayout = false;
|
||||
bool ShowAppPropertyEditor = false;
|
||||
@@ -353,6 +357,7 @@ void ImGui::ShowDemoWindow(bool* p_open)
|
||||
if (demo_data.ShowAppAssetsBrowser) { ShowExampleAppAssetsBrowser(&demo_data.ShowAppAssetsBrowser); }
|
||||
if (demo_data.ShowAppConsole) { ShowExampleAppConsole(&demo_data.ShowAppConsole); }
|
||||
if (demo_data.ShowAppCustomRendering) { ShowExampleAppCustomRendering(&demo_data.ShowAppCustomRendering); }
|
||||
if (demo_data.ShowAppImageViewer) { ShowExampleAppImageViewer(&demo_data.ShowAppImageViewer); }
|
||||
if (demo_data.ShowAppLog) { ShowExampleAppLog(&demo_data.ShowAppLog); }
|
||||
if (demo_data.ShowAppLayout) { ShowExampleAppLayout(&demo_data.ShowAppLayout); }
|
||||
if (demo_data.ShowAppPropertyEditor) { ShowExampleAppPropertyEditor(&demo_data.ShowAppPropertyEditor, &demo_data); }
|
||||
@@ -677,6 +682,7 @@ static void DemoWindowMenuBar(ImGuiDemoWindowData* demo_data)
|
||||
ImGui::MenuItem("Console", NULL, &demo_data->ShowAppConsole);
|
||||
ImGui::MenuItem("Custom rendering", NULL, &demo_data->ShowAppCustomRendering);
|
||||
ImGui::MenuItem("Documents", NULL, &demo_data->ShowAppDocuments);
|
||||
ImGui::MenuItem("Image Viewer", NULL, &demo_data->ShowAppImageViewer);
|
||||
ImGui::MenuItem("Log", NULL, &demo_data->ShowAppLog);
|
||||
ImGui::MenuItem("Property editor", NULL, &demo_data->ShowAppPropertyEditor);
|
||||
ImGui::MenuItem("Simple layout", NULL, &demo_data->ShowAppLayout);
|
||||
@@ -708,7 +714,7 @@ static void DemoWindowMenuBar(ImGuiDemoWindowData* demo_data)
|
||||
ImGui::Checkbox("Highlight ID Conflicts", &io.ConfigDebugHighlightIdConflicts);
|
||||
ImGui::EndDisabled();
|
||||
ImGui::Checkbox("Assert on error recovery", &io.ConfigErrorRecoveryEnableAssert);
|
||||
ImGui::TextDisabled("(see Demo->Configuration for details & more)");
|
||||
ImGui::TextDisabled("(see Demo->Configuration for more)");
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
ImGui::MenuItem("Debug Log", NULL, &demo_data->ShowDebugLog, has_debug_tools);
|
||||
@@ -825,6 +831,87 @@ static ExampleTreeNode* ExampleTree_CreateDemoTree()
|
||||
return node_L0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Helpers: ExampleImageViewer
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
struct ExampleImageViewerData
|
||||
{
|
||||
ImU32 ImageBgColor = IM_COL32(100, 100, 100, 255);
|
||||
ImU32 GridColor = IM_COL32(255, 255, 255, 100);
|
||||
bool GridEnabled = true;
|
||||
bool ViewReset = true;
|
||||
ImVec2 ViewOffset; // in image space
|
||||
float Zoom = 10.0f;
|
||||
float ZoomMin = 1.0f;
|
||||
float ZoomMax = 10000.0f;
|
||||
};
|
||||
|
||||
static void ExampleImageViewer_DrawOptions(ExampleImageViewerData* data)
|
||||
{
|
||||
ImGui::SetNextItemShortcut(ImGuiKey_G, ImGuiInputFlags_Tooltip); // | ImGuiInputFlags_RouteGlobal
|
||||
ImGui::Checkbox("Grid", &data->GridEnabled);
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 10.0f);
|
||||
float zoom_100 = data->Zoom * 100.0f;
|
||||
if (ImGui::DragFloat("##Zoom", &zoom_100, 5.0f, data->ZoomMin * 100.0f, data->ZoomMax * 100.0f, "%.0f%%", ImGuiSliderFlags_AlwaysClamp))
|
||||
data->Zoom = zoom_100 / 100.0f;
|
||||
}
|
||||
|
||||
static void ExampleImageViewer_DrawCanvas(ExampleImageViewerData* data, ImVec2 canvas_size, ImTextureRef image_tex_ref, int image_w, int image_h)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
||||
IM_ASSERT(canvas_size.x >= 0.0f && canvas_size.y >= 0.0f);
|
||||
|
||||
// Layout canvas
|
||||
ImGui::InvisibleButton("##Canvas", canvas_size);
|
||||
ImVec2 canvas_min = ImGui::GetItemRectMin();
|
||||
ImVec2 canvas_max = ImGui::GetItemRectMax();
|
||||
|
||||
if (data->ViewReset)
|
||||
data->ViewOffset = ImVec2((canvas_size.x * 0.5f / data->Zoom) - 0.5f, (canvas_size.y * 0.5f / data->Zoom) - 0.5f); // Add half a pixel padding
|
||||
data->ViewReset = false;
|
||||
|
||||
// Handle inputs
|
||||
if (ImGui::SetItemKeyOwner(ImGuiKey_MouseWheelY))
|
||||
if (io.MouseWheel != 0.0f)
|
||||
data->Zoom = IM_CLAMP(data->Zoom * (1.0f + io.MouseWheel * 0.10f), data->ZoomMin, data->ZoomMax);
|
||||
float zoom = data->Zoom; // (float)(int)ViewZoom;
|
||||
if (ImGui::IsItemActive() && ImGui::IsMouseDragging(0))
|
||||
{
|
||||
data->ViewOffset.x -= io.MouseDelta.x / zoom;
|
||||
data->ViewOffset.y -= io.MouseDelta.y / zoom;
|
||||
}
|
||||
|
||||
// Display image
|
||||
ImVec2 image_min, image_max;
|
||||
image_min.x = (float)(int)((canvas_min.x - (data->ViewOffset.x * zoom)) + (canvas_size.x * 0.5f));
|
||||
image_min.y = (float)(int)((canvas_min.y - (data->ViewOffset.y * zoom)) + (canvas_size.y * 0.5f));
|
||||
image_max.x = (float)(int)(image_min.x + image_w * zoom);
|
||||
image_max.y = (float)(int)(image_min.y + image_h * zoom);
|
||||
draw_list->AddRect(ImVec2(canvas_min.x - 1.0f, canvas_min.y - 1.0f), ImVec2(canvas_max.x + 1.0f, canvas_max.y + 1.0f), IM_COL32(255, 255, 255, 255));
|
||||
draw_list->PushClipRect(canvas_min, canvas_max, true);
|
||||
draw_list->AddRectFilled(image_min, image_max, data->ImageBgColor);
|
||||
if (platform_io.DrawCallback_SetSamplerNearest != NULL)
|
||||
draw_list->AddCallback(platform_io.DrawCallback_SetSamplerNearest);
|
||||
draw_list->AddImage(image_tex_ref, image_min, image_max);
|
||||
if (platform_io.DrawCallback_SetSamplerLinear != NULL)
|
||||
draw_list->AddCallback(ImGui::GetPlatformIO().DrawCallback_SetSamplerLinear);
|
||||
|
||||
// Display grid lines for visible pixels
|
||||
if (data->GridEnabled && zoom > 6.0f)
|
||||
{
|
||||
const float step = (float)zoom;
|
||||
for (int px = (int)((canvas_min.x - image_min.x) / step); px <= (int)((canvas_max.x - image_min.x) / step); px++)
|
||||
draw_list->AddLineV(image_min.x + px * step, canvas_min.y, canvas_max.y, data->GridColor, 1.0f);
|
||||
for (int py = (int)((canvas_min.y - image_min.y) / step); py <= (int)((canvas_max.y - image_min.y) / step); py++)
|
||||
draw_list->AddLineH(canvas_min.x, canvas_max.x, image_min.y + py * step, data->GridColor, 1.0f);
|
||||
}
|
||||
draw_list->PopClipRect();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] DemoWindowWidgetsBasic()
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -1802,40 +1889,29 @@ static void DemoWindowWidgetsImages()
|
||||
// - Read https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples
|
||||
|
||||
// Grab the current texture identifier used by the font atlas.
|
||||
ImTextureRef my_tex_id = io.Fonts->TexRef;
|
||||
ImFontAtlas* atlas = io.Fonts;
|
||||
ImTextureRef my_tex_id = atlas->TexRef;
|
||||
float my_tex_w = (float)atlas->TexData->Width; // Regular user code should never have to care about TexData-> fields, but since we want to display the entire texture here, we pull Width/Height from it.
|
||||
float my_tex_h = (float)atlas->TexData->Height;
|
||||
ImGui::Text("%.0fx%.0f", my_tex_w, my_tex_h);
|
||||
|
||||
// Regular user code should never have to care about TexData-> fields, but since we want to display the entire texture here, we pull Width/Height from it.
|
||||
float my_tex_w = (float)io.Fonts->TexData->Width;
|
||||
float my_tex_h = (float)io.Fonts->TexData->Height;
|
||||
// Basic drawing
|
||||
ImGui::SeparatorText("Image()/ImageWithBg() function");
|
||||
ImVec2 uv_min = ImVec2(0.0f, 0.0f); // Top-left
|
||||
ImVec2 uv_max = ImVec2(1.0f, 1.0f); // Lower-right
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ImageBorderSize, IM_MAX(1.0f, ImGui::GetStyle().ImageBorderSize));
|
||||
ImGui::ImageWithBg(my_tex_id, ImVec2(my_tex_w, my_tex_h), uv_min, uv_max, ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
{
|
||||
ImGui::Text("%.0fx%.0f", my_tex_w, my_tex_h);
|
||||
ImVec2 pos = ImGui::GetCursorScreenPos();
|
||||
ImVec2 uv_min = ImVec2(0.0f, 0.0f); // Top-left
|
||||
ImVec2 uv_max = ImVec2(1.0f, 1.0f); // Lower-right
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ImageBorderSize, IM_MAX(1.0f, ImGui::GetStyle().ImageBorderSize));
|
||||
ImGui::ImageWithBg(my_tex_id, ImVec2(my_tex_w, my_tex_h), uv_min, uv_max, ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
if (ImGui::BeginItemTooltip())
|
||||
{
|
||||
float region_sz = 32.0f;
|
||||
float region_x = io.MousePos.x - pos.x - region_sz * 0.5f;
|
||||
float region_y = io.MousePos.y - pos.y - region_sz * 0.5f;
|
||||
float zoom = 4.0f;
|
||||
if (region_x < 0.0f) { region_x = 0.0f; }
|
||||
else if (region_x > my_tex_w - region_sz) { region_x = my_tex_w - region_sz; }
|
||||
if (region_y < 0.0f) { region_y = 0.0f; }
|
||||
else if (region_y > my_tex_h - region_sz) { region_y = my_tex_h - region_sz; }
|
||||
ImGui::Text("Min: (%.2f, %.2f)", region_x, region_y);
|
||||
ImGui::Text("Max: (%.2f, %.2f)", region_x + region_sz, region_y + region_sz);
|
||||
ImVec2 uv0 = ImVec2((region_x) / my_tex_w, (region_y) / my_tex_h);
|
||||
ImVec2 uv1 = ImVec2((region_x + region_sz) / my_tex_w, (region_y + region_sz) / my_tex_h);
|
||||
ImGui::ImageWithBg(my_tex_id, ImVec2(region_sz * zoom, region_sz * zoom), uv0, uv1, ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
// Fancy widget
|
||||
ImGui::SeparatorText("Interactive Image Viewer");
|
||||
static ExampleImageViewerData image_viewer;
|
||||
ImVec2 canvas_size(ImGui::GetContentRegionAvail().x, my_tex_h * 2.0f);
|
||||
ExampleImageViewer_DrawOptions(&image_viewer);
|
||||
ExampleImageViewer_DrawCanvas(&image_viewer, canvas_size, my_tex_id, (int)my_tex_w, (int)my_tex_h);
|
||||
|
||||
IMGUI_DEMO_MARKER("Widgets/Images/Textured buttons");
|
||||
ImGui::SeparatorText("Textured Buttons");
|
||||
ImGui::TextWrapped("And now some textured buttons..");
|
||||
static int pressed_count = 0;
|
||||
for (int i = 0; i < 8; i++)
|
||||
@@ -8827,7 +8903,7 @@ static void ShowExampleMenuFile()
|
||||
IMGUI_DEMO_MARKER("Examples/Menu/Options");
|
||||
static bool enabled = true;
|
||||
ImGui::MenuItem("Enabled", "", &enabled);
|
||||
ImGui::BeginChild("child", ImVec2(0, 60), ImGuiChildFlags_Borders);
|
||||
ImGui::BeginChild("child", ImVec2(0, ImGui::GetTextLineHeightWithSpacing() * 5.0f), ImGuiChildFlags_Borders);
|
||||
for (int i = 0; i < 10; i++)
|
||||
ImGui::Text("Scrolling Text %d", i);
|
||||
ImGui::EndChild();
|
||||
@@ -9239,6 +9315,28 @@ static void ShowExampleAppConsole(bool* p_open)
|
||||
console.Draw("Example: Console", p_open);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Example App: Image Viewer / ShowExampleAppImageViewer()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static void ShowExampleAppImageViewer(bool* p_open)
|
||||
{
|
||||
ImFontAtlas* atlas = ImGui::GetIO().Fonts;
|
||||
ImTextureRef tex_ref = atlas->TexRef; // We don't have access to other textures in this demo!
|
||||
int tex_w = atlas->TexData->Width;
|
||||
int tex_h = atlas->TexData->Height;
|
||||
if (ImGui::Begin("Example: Image Viewer", p_open))
|
||||
{
|
||||
static ExampleImageViewerData image_viewer;
|
||||
ExampleImageViewer_DrawOptions(&image_viewer);
|
||||
ImVec2 canvas_size = ImGui::GetContentRegionAvail();
|
||||
ImVec2 canvas_min_size = ImGui::IsWindowAppearing() ? ImVec2(3.0f * tex_w, 4.0f * tex_h) : ImVec2(1.0f, 1.0f);
|
||||
canvas_size = ImVec2(IM_MAX(canvas_size.x, canvas_min_size.x), IM_MAX(canvas_size.y, canvas_min_size.y));
|
||||
ExampleImageViewer_DrawCanvas(&image_viewer, canvas_size, tex_ref, tex_w, tex_h);
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Example App: Debug Log / ShowExampleAppLog()
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -10131,20 +10229,20 @@ static void ShowExampleAppCustomRendering(bool* p_open)
|
||||
draw_list->AddNgon(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, ngon_sides, th); x += sz + spacing; // N-gon
|
||||
draw_list->AddCircle(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, circle_segments, th); x += sz + spacing; // Circle
|
||||
draw_list->AddEllipse(ImVec2(x + sz*0.5f, y + sz*0.5f), ImVec2(sz*0.5f, sz*0.3f), col, -0.3f, circle_segments, th); x += sz + spacing; // Ellipse
|
||||
draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 0.0f, ImDrawFlags_None, th); x += sz + spacing; // Square
|
||||
draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, rounding, ImDrawFlags_None, th); x += sz + spacing; // Square with all rounded corners
|
||||
draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, rounding, corners_tl_br, th); x += sz + spacing; // Square with two rounded corners
|
||||
draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 0.0f, th); x += sz + spacing; // Square
|
||||
draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, rounding, th); x += sz + spacing; // Square with all rounded corners
|
||||
draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, rounding, th, corners_tl_br); x += sz + spacing; // Square with two rounded corners
|
||||
draw_list->AddTriangle(ImVec2(x+sz*0.5f,y), ImVec2(x+sz, y+sz-0.5f), ImVec2(x, y+sz-0.5f), col, th);x += sz + spacing; // Triangle
|
||||
//draw_list->AddTriangle(ImVec2(x+sz*0.2f,y), ImVec2(x, y+sz-0.5f), ImVec2(x+sz*0.4f, y+sz-0.5f), col, th);x+= sz*0.4f + spacing; // Thin triangle
|
||||
PathConcaveShape(draw_list, x, y, sz); draw_list->PathStroke(col, ImDrawFlags_Closed, th); x += sz + spacing; // Concave Shape
|
||||
PathConcaveShape(draw_list, x, y, sz); draw_list->PathStroke(col, th, ImDrawFlags_Closed); x += sz + spacing; // Concave Shape
|
||||
//draw_list->AddPolyline(concave_shape, IM_COUNTOF(concave_shape), col, ImDrawFlags_Closed, th);
|
||||
draw_list->AddLine(ImVec2(x, y), ImVec2(x + sz, y), col, th); x += sz + spacing; // Horizontal line (note: drawing a filled rectangle will be faster!)
|
||||
draw_list->AddLine(ImVec2(x, y), ImVec2(x, y + sz), col, th); x += spacing; // Vertical line (note: drawing a filled rectangle will be faster!)
|
||||
draw_list->AddLineH(x, x + sz, y, col, th); x += sz + spacing; // Horizontal line (note: drawing a filled rectangle will be faster!)
|
||||
draw_list->AddLineV(x, y, y + sz, col, th); x += spacing; // Vertical line (note: drawing a filled rectangle will be faster!)
|
||||
draw_list->AddLine(ImVec2(x, y), ImVec2(x + sz, y + sz), col, th); x += sz + spacing; // Diagonal line
|
||||
|
||||
// Path
|
||||
draw_list->PathArcTo(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, 3.141592f, 3.141592f * -0.5f);
|
||||
draw_list->PathStroke(col, ImDrawFlags_None, th);
|
||||
draw_list->PathStroke(col, th);
|
||||
x += sz + spacing;
|
||||
|
||||
// Quadratic Bezier Curve (3 control points)
|
||||
@@ -10278,9 +10376,9 @@ static void ShowExampleAppCustomRendering(bool* p_open)
|
||||
{
|
||||
const float GRID_STEP = 64.0f;
|
||||
for (float x = fmodf(scrolling.x, GRID_STEP); x < canvas_sz.x; x += GRID_STEP)
|
||||
draw_list->AddLine(ImVec2(canvas_p0.x + x, canvas_p0.y), ImVec2(canvas_p0.x + x, canvas_p1.y), IM_COL32(200, 200, 200, 40));
|
||||
draw_list->AddLineV(canvas_p0.x + x, canvas_p0.y, canvas_p1.y, IM_COL32(200, 200, 200, 40));
|
||||
for (float y = fmodf(scrolling.y, GRID_STEP); y < canvas_sz.y; y += GRID_STEP)
|
||||
draw_list->AddLine(ImVec2(canvas_p0.x, canvas_p0.y + y), ImVec2(canvas_p1.x, canvas_p0.y + y), IM_COL32(200, 200, 200, 40));
|
||||
draw_list->AddLineH(canvas_p0.x, canvas_p1.x, canvas_p0.y + y, IM_COL32(200, 200, 200, 40));
|
||||
}
|
||||
for (int n = 0; n < points.Size; n += 2)
|
||||
draw_list->AddLine(ImVec2(origin.x + points[n].x, origin.y + points[n].y), ImVec2(origin.x + points[n + 1].x, origin.y + points[n + 1].y), IM_COL32(255, 255, 0, 255), 2.0f);
|
||||
@@ -10724,10 +10822,11 @@ struct ExampleAssetsBrowser
|
||||
bool AllowBoxSelect = true; // Will set ImGuiMultiSelectFlags_BoxSelect2d
|
||||
bool AllowBoxSelectInsideSelection = false; // Will set ImGuiMultiSelectFlags_SelectOnClickAlways
|
||||
bool AllowDragUnselected = false; // Will set ImGuiMultiSelectFlags_SelectOnClickRelease
|
||||
float IconSize = 32.0f;
|
||||
float IconSize = 0;
|
||||
int IconSpacing = 10;
|
||||
int IconHitSpacing = 4; // Increase hit-spacing if you want to make it possible to clear or box-select from gaps. Some spacing is required to able to amend with Shift+box-select. Value is small in Explorer.
|
||||
int IconHitSpacing = 4; // Increase hit-spacing if you want to make it possible to clear or box-select from gaps. Some spacing is required to able to amend with Shift+box-select. Value is small in Explorer.
|
||||
bool StretchSpacing = true;
|
||||
bool UseScrollX = false; // Debug: submit twice the number of items per line (overflow horizontally to exercise ScrollX + box-select)
|
||||
|
||||
// State
|
||||
ImVector<ExampleAsset> Items; // Our items
|
||||
@@ -10778,12 +10877,15 @@ struct ExampleAssetsBrowser
|
||||
// Layout: calculate number of icon per line and number of lines
|
||||
LayoutItemSize = ImVec2(floorf(IconSize), floorf(IconSize));
|
||||
LayoutColumnCount = IM_MAX((int)(avail_width / (LayoutItemSize.x + LayoutItemSpacing)), 1);
|
||||
LayoutLineCount = (Items.Size + LayoutColumnCount - 1) / LayoutColumnCount;
|
||||
|
||||
// Layout: when stretching: allocate remaining space to more spacing. Round before division, so item_spacing may be non-integer.
|
||||
if (StretchSpacing && LayoutColumnCount > 1)
|
||||
LayoutItemSpacing = floorf(avail_width - LayoutItemSize.x * LayoutColumnCount) / LayoutColumnCount;
|
||||
|
||||
if (UseScrollX)
|
||||
LayoutColumnCount *= 2;
|
||||
LayoutLineCount = (Items.Size + LayoutColumnCount - 1) / LayoutColumnCount;
|
||||
|
||||
LayoutItemStep = ImVec2(LayoutItemSize.x + LayoutItemSpacing, LayoutItemSize.y + LayoutItemSpacing);
|
||||
LayoutSelectableSpacing = IM_MAX(floorf(LayoutItemSpacing) - IconHitSpacing, 0.0f);
|
||||
LayoutOuterPadding = floorf(LayoutItemSpacing * 0.5f);
|
||||
@@ -10791,6 +10893,9 @@ struct ExampleAssetsBrowser
|
||||
|
||||
void Draw(const char* title, bool* p_open)
|
||||
{
|
||||
if (IconSize <= 0.0f)
|
||||
IconSize = ImGui::CalcTextSize("99999").x;
|
||||
|
||||
ImGui::SetNextWindowSize(ImVec2(IconSize * 25, IconSize * 15), ImGuiCond_FirstUseEver);
|
||||
if (!ImGui::Begin(title, p_open, ImGuiWindowFlags_MenuBar))
|
||||
{
|
||||
@@ -10840,6 +10945,7 @@ struct ExampleAssetsBrowser
|
||||
ImGui::SliderInt("Icon Spacing", &IconSpacing, 0, 32);
|
||||
ImGui::SliderInt("Icon Hit Spacing", &IconHitSpacing, 0, 32);
|
||||
ImGui::Checkbox("Stretch Spacing", &StretchSpacing);
|
||||
ImGui::Checkbox("Use ScrollX", &UseScrollX);
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
@@ -10869,7 +10975,7 @@ struct ExampleAssetsBrowser
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGui::SetNextWindowContentSize(ImVec2(0.0f, LayoutOuterPadding + LayoutLineCount * (LayoutItemSize.y + LayoutItemSpacing)));
|
||||
if (ImGui::BeginChild("Assets", ImVec2(0.0f, -ImGui::GetTextLineHeightWithSpacing()), ImGuiChildFlags_Borders, ImGuiWindowFlags_NoMove))
|
||||
if (ImGui::BeginChild("Assets", ImVec2(0.0f, -ImGui::GetTextLineHeightWithSpacing()), ImGuiChildFlags_Borders, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_HorizontalScrollbar))
|
||||
{
|
||||
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
||||
|
||||
@@ -11013,6 +11119,8 @@ struct ExampleAssetsBrowser
|
||||
}
|
||||
}
|
||||
clipper.End();
|
||||
if (Items.Size == 0)
|
||||
ImGui::Dummy(ImVec2(0, 0));
|
||||
ImGui::PopStyleVar(); // ImGuiStyleVar_ItemSpacing
|
||||
|
||||
// Context menu
|
||||
|
||||
Vendored
+106
-71
@@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.92.7
|
||||
// dear imgui, v1.92.8
|
||||
// (drawing and font code)
|
||||
|
||||
/*
|
||||
@@ -208,6 +208,7 @@ void ImGui::StyleColorsDark(ImGuiStyle* dst)
|
||||
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f);
|
||||
colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.51f, 0.51f, 0.51f, 1.00f);
|
||||
colors[ImGuiCol_CheckMark] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
|
||||
colors[ImGuiCol_CheckboxSelectedBg] = ImLerp(colors[ImGuiCol_FrameBg], colors[ImGuiCol_FrameBgHovered], 0.65f);
|
||||
colors[ImGuiCol_SliderGrab] = ImVec4(0.24f, 0.52f, 0.88f, 1.00f);
|
||||
colors[ImGuiCol_SliderGrabActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
|
||||
colors[ImGuiCol_Button] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f);
|
||||
@@ -275,6 +276,7 @@ void ImGui::StyleColorsClassic(ImGuiStyle* dst)
|
||||
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.40f, 0.80f, 0.40f);
|
||||
colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.41f, 0.39f, 0.80f, 0.60f);
|
||||
colors[ImGuiCol_CheckMark] = ImVec4(0.90f, 0.90f, 0.90f, 0.50f);
|
||||
colors[ImGuiCol_CheckboxSelectedBg] = ImLerp(colors[ImGuiCol_FrameBg], colors[ImGuiCol_FrameBgActive], 0.65f);
|
||||
colors[ImGuiCol_SliderGrab] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f);
|
||||
colors[ImGuiCol_SliderGrabActive] = ImVec4(0.41f, 0.39f, 0.80f, 0.60f);
|
||||
colors[ImGuiCol_Button] = ImVec4(0.35f, 0.40f, 0.61f, 0.62f);
|
||||
@@ -343,6 +345,7 @@ void ImGui::StyleColorsLight(ImGuiStyle* dst)
|
||||
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.49f, 0.49f, 0.49f, 0.80f);
|
||||
colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.49f, 0.49f, 0.49f, 1.00f);
|
||||
colors[ImGuiCol_CheckMark] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
|
||||
colors[ImGuiCol_CheckboxSelectedBg] = ImVec4(0.95f, 0.97f, 1.00f, 1.00f);
|
||||
colors[ImGuiCol_SliderGrab] = ImVec4(0.26f, 0.59f, 0.98f, 0.78f);
|
||||
colors[ImGuiCol_SliderGrabActive] = ImVec4(0.46f, 0.54f, 0.80f, 0.60f);
|
||||
colors[ImGuiCol_Button] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f);
|
||||
@@ -528,9 +531,14 @@ void ImDrawList::_PopUnusedDrawCmd()
|
||||
|
||||
void ImDrawList::AddCallback(ImDrawCallback callback, void* userdata, size_t userdata_size)
|
||||
{
|
||||
IM_ASSERT(callback != NULL);
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
if (callback == ImDrawCallback_ResetRenderState && _Data->Context != NULL && _Data->Context->PlatformIO.DrawCallback_ResetRenderState != NULL)
|
||||
callback = _Data->Context->PlatformIO.DrawCallback_ResetRenderState; // == ImGui::GetPlatformIO().DrawCallback_ResetRenderState
|
||||
#endif
|
||||
|
||||
IM_ASSERT_PARANOID(CmdBuffer.Size > 0);
|
||||
ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
|
||||
IM_ASSERT(callback != NULL);
|
||||
IM_ASSERT(curr_cmd->UserCallback == NULL);
|
||||
if (curr_cmd->ElemCount != 0)
|
||||
{
|
||||
@@ -662,7 +670,7 @@ void ImDrawList::PushClipRect(const ImVec2& cr_min, const ImVec2& cr_max, bool i
|
||||
if (intersect_with_current_clip_rect)
|
||||
{
|
||||
ImVec4 current = _CmdHeader.ClipRect;
|
||||
if (cr.x < current.x) cr.x = current.x;
|
||||
if (cr.x < current.x) cr.x = current.x; // = ClipWith(). Note that passing inverted range wouldn't be fixed here.
|
||||
if (cr.y < current.y) cr.y = current.y;
|
||||
if (cr.z > current.z) cr.z = current.z;
|
||||
if (cr.w > current.w) cr.w = current.w;
|
||||
@@ -806,7 +814,7 @@ void ImDrawList::PrimQuadUV(const ImVec2& a, const ImVec2& b, const ImVec2& c, c
|
||||
|
||||
// TODO: Thickness anti-aliased lines cap are missing their AA fringe.
|
||||
// We avoid using the ImVec2 math operators here to reduce cost to a minimum for debug/non-inlined builds.
|
||||
void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 col, ImDrawFlags flags, float thickness)
|
||||
void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 col, float thickness, ImDrawFlags flags)
|
||||
{
|
||||
if (points_count < 2 || (col & IM_COL32_A_MASK) == 0)
|
||||
return;
|
||||
@@ -815,6 +823,7 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
|
||||
const ImVec2 opaque_uv = _Data->TexUvWhitePixel;
|
||||
const int count = closed ? points_count : points_count - 1; // The number of line segments we need to draw
|
||||
const bool thick_line = (thickness > _FringeScale);
|
||||
IM_ASSERT((flags & ImDrawFlags_InvalidMask_) == 0 && "Incorrect parameter. Did you swapped 'thickness' and 'flags'?");
|
||||
|
||||
if (Flags & ImDrawListFlags_AntiAliasedLines)
|
||||
{
|
||||
@@ -1432,35 +1441,13 @@ void ImDrawList::PathBezierQuadraticCurveTo(const ImVec2& p2, const ImVec2& p3,
|
||||
}
|
||||
}
|
||||
|
||||
static inline ImDrawFlags FixRectCornerFlags(ImDrawFlags flags)
|
||||
{
|
||||
/*
|
||||
IM_STATIC_ASSERT(ImDrawFlags_RoundCornersTopLeft == (1 << 4));
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
// Obsoleted in 1.82 (from February 2021). This code was stripped/simplified and mostly commented in 1.90 (from September 2023)
|
||||
// - Legacy Support for hard coded ~0 (used to be a suggested equivalent to ImDrawCornerFlags_All)
|
||||
if (flags == ~0) { return ImDrawFlags_RoundCornersAll; }
|
||||
// - Legacy Support for hard coded 0x01 to 0x0F (matching 15 out of 16 old flags combinations). Read details in older version of this code.
|
||||
if (flags >= 0x01 && flags <= 0x0F) { return (flags << 4); }
|
||||
// We cannot support hard coded 0x00 with 'float rounding > 0.0f' --> replace with ImDrawFlags_RoundCornersNone or use 'float rounding = 0.0f'
|
||||
#endif
|
||||
*/
|
||||
// If this assert triggers, please update your code replacing hardcoded values with new ImDrawFlags_RoundCorners* values.
|
||||
// Note that ImDrawFlags_Closed (== 0x01) is an invalid flag for AddRect(), AddRectFilled(), PathRect() etc. anyway.
|
||||
// See details in 1.82 Changelog as well as 2021/03/12 and 2023/09/08 entries in "API BREAKING CHANGES" section.
|
||||
IM_ASSERT((flags & 0x0F) == 0 && "Misuse of legacy hardcoded ImDrawCornerFlags values!");
|
||||
|
||||
if ((flags & ImDrawFlags_RoundCornersMask_) == 0)
|
||||
flags |= ImDrawFlags_RoundCornersAll;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
void ImDrawList::PathRect(const ImVec2& a, const ImVec2& b, float rounding, ImDrawFlags flags)
|
||||
{
|
||||
if (rounding >= 0.5f)
|
||||
{
|
||||
flags = FixRectCornerFlags(flags);
|
||||
if ((flags & ImDrawFlags_RoundCornersMask_) == 0)
|
||||
flags |= ImDrawFlags_RoundCornersAll;
|
||||
|
||||
rounding = ImMin(rounding, ImFabs(b.x - a.x) * (((flags & ImDrawFlags_RoundCornersTop) == ImDrawFlags_RoundCornersTop) || ((flags & ImDrawFlags_RoundCornersBottom) == ImDrawFlags_RoundCornersBottom) ? 0.5f : 1.0f) - 1.0f);
|
||||
rounding = ImMin(rounding, ImFabs(b.y - a.y) * (((flags & ImDrawFlags_RoundCornersLeft) == ImDrawFlags_RoundCornersLeft) || ((flags & ImDrawFlags_RoundCornersRight) == ImDrawFlags_RoundCornersRight) ? 0.5f : 1.0f) - 1.0f);
|
||||
}
|
||||
@@ -1490,20 +1477,48 @@ void ImDrawList::AddLine(const ImVec2& p1, const ImVec2& p2, ImU32 col, float th
|
||||
return;
|
||||
PathLineTo(p1 + ImVec2(0.5f, 0.5f));
|
||||
PathLineTo(p2 + ImVec2(0.5f, 0.5f));
|
||||
PathStroke(col, 0, thickness);
|
||||
PathStroke(col, thickness);
|
||||
}
|
||||
|
||||
void ImDrawList::AddLineH(float min_x, float max_x, float y, ImU32 col, float thickness)
|
||||
{
|
||||
if ((col & IM_COL32_A_MASK) == 0)
|
||||
return;
|
||||
PathLineTo(ImVec2(min_x + 0.5f, y + 0.5f)); // Same as AddLine() above.
|
||||
PathLineTo(ImVec2(max_x + 0.5f, y + 0.5f));
|
||||
PathStroke(col, thickness);
|
||||
}
|
||||
|
||||
void ImDrawList::AddLineV(float x, float min_y, float max_y, ImU32 col, float thickness)
|
||||
{
|
||||
if ((col & IM_COL32_A_MASK) == 0)
|
||||
return;
|
||||
PathLineTo(ImVec2(x + 0.5f, min_y + 0.5f)); // Same as AddLine() above.
|
||||
PathLineTo(ImVec2(x + 0.5f, max_y + 0.5f));
|
||||
PathStroke(col, thickness);
|
||||
}
|
||||
|
||||
// p_min = upper-left, p_max = lower-right
|
||||
// Note we don't render 1 pixels sized rectangles properly.
|
||||
void ImDrawList::AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding, ImDrawFlags flags, float thickness)
|
||||
void ImDrawList::AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding, float thickness, ImDrawFlags flags)
|
||||
{
|
||||
// If this assert triggers on legacy code:
|
||||
// - 1.92.8 (2025/04): swapped two last parameters order: flags, thickness --> thickness, flags. This should normally be caught by compile-time type-checking.
|
||||
// - 1.82.0 (2021/03): changed ImDrawCornerFlags to ImDrawFlags_RoundCornersXXX values.
|
||||
// If you used hard-coded 1 to 15 or ~0 in flags to configure corner rounding use the new flags!
|
||||
// - Hard coded support for ~0 == ImDrawFlags_RoundCornersAll.
|
||||
// - Hard coded support for values 0x01 to 0x0F (matching 15 out of 16 old flags combinations) --> see FixRectCornerFlags() in <1.90 code.
|
||||
// - Hard coded 0x00 with 'float rounding > 0.0f' --> replace with ImDrawFlags_RoundCornersNone or use 'float rounding = 0.0f'.
|
||||
// See "API BREAKING CHANGES" section for 1.82 and 1.90.
|
||||
IM_ASSERT((flags & ImDrawFlags_InvalidMask_) == 0 && "Incorrect parameter. Did you swapped 'thickness' and 'flags'?"); // Or misuse of legacy hard-coded ImDrawCornerFlags values
|
||||
|
||||
if ((col & IM_COL32_A_MASK) == 0)
|
||||
return;
|
||||
if (Flags & ImDrawListFlags_AntiAliasedLines)
|
||||
PathRect(p_min + ImVec2(0.50f, 0.50f), p_max - ImVec2(0.50f, 0.50f), rounding, flags);
|
||||
else
|
||||
PathRect(p_min + ImVec2(0.50f, 0.50f), p_max - ImVec2(0.49f, 0.49f), rounding, flags); // Better looking lower-right corner and rounded non-AA shapes.
|
||||
PathStroke(col, ImDrawFlags_Closed, thickness);
|
||||
PathStroke(col, thickness, ImDrawFlags_Closed);
|
||||
}
|
||||
|
||||
void ImDrawList::AddRectFilled(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding, ImDrawFlags flags)
|
||||
@@ -1547,7 +1562,7 @@ void ImDrawList::AddQuad(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, c
|
||||
PathLineTo(p2);
|
||||
PathLineTo(p3);
|
||||
PathLineTo(p4);
|
||||
PathStroke(col, ImDrawFlags_Closed, thickness);
|
||||
PathStroke(col, thickness, ImDrawFlags_Closed);
|
||||
}
|
||||
|
||||
void ImDrawList::AddQuadFilled(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col)
|
||||
@@ -1570,7 +1585,7 @@ void ImDrawList::AddTriangle(const ImVec2& p1, const ImVec2& p2, const ImVec2& p
|
||||
PathLineTo(p1);
|
||||
PathLineTo(p2);
|
||||
PathLineTo(p3);
|
||||
PathStroke(col, ImDrawFlags_Closed, thickness);
|
||||
PathStroke(col, thickness, ImDrawFlags_Closed);
|
||||
}
|
||||
|
||||
void ImDrawList::AddTriangleFilled(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col)
|
||||
@@ -1605,7 +1620,7 @@ void ImDrawList::AddCircle(const ImVec2& center, float radius, ImU32 col, int nu
|
||||
PathArcTo(center, radius - 0.5f, 0.0f, a_max, num_segments - 1);
|
||||
}
|
||||
|
||||
PathStroke(col, ImDrawFlags_Closed, thickness);
|
||||
PathStroke(col, thickness, ImDrawFlags_Closed);
|
||||
}
|
||||
|
||||
void ImDrawList::AddCircleFilled(const ImVec2& center, float radius, ImU32 col, int num_segments)
|
||||
@@ -1641,7 +1656,7 @@ void ImDrawList::AddNgon(const ImVec2& center, float radius, ImU32 col, int num_
|
||||
// Because we are filling a closed shape we remove 1 from the count of segments/points
|
||||
const float a_max = (IM_PI * 2.0f) * ((float)num_segments - 1.0f) / (float)num_segments;
|
||||
PathArcTo(center, radius - 0.5f, 0.0f, a_max, num_segments - 1);
|
||||
PathStroke(col, ImDrawFlags_Closed, thickness);
|
||||
PathStroke(col, thickness, ImDrawFlags_Closed);
|
||||
}
|
||||
|
||||
// Guaranteed to honor 'num_segments'
|
||||
@@ -1668,7 +1683,7 @@ void ImDrawList::AddEllipse(const ImVec2& center, const ImVec2& radius, ImU32 co
|
||||
// Because we are filling a closed shape we remove 1 from the count of segments/points
|
||||
const float a_max = IM_PI * 2.0f * ((float)num_segments - 1.0f) / (float)num_segments;
|
||||
PathEllipticalArcTo(center, radius, rot, 0.0f, a_max, num_segments - 1);
|
||||
PathStroke(col, true, thickness);
|
||||
PathStroke(col, thickness, ImDrawFlags_Closed);
|
||||
}
|
||||
|
||||
void ImDrawList::AddEllipseFilled(const ImVec2& center, const ImVec2& radius, ImU32 col, float rot, int num_segments)
|
||||
@@ -1693,7 +1708,7 @@ void ImDrawList::AddBezierCubic(const ImVec2& p1, const ImVec2& p2, const ImVec2
|
||||
|
||||
PathLineTo(p1);
|
||||
PathBezierCubicCurveTo(p2, p3, p4, num_segments);
|
||||
PathStroke(col, 0, thickness);
|
||||
PathStroke(col, thickness);
|
||||
}
|
||||
|
||||
// Quadratic Bezier takes 3 controls points
|
||||
@@ -1704,7 +1719,7 @@ void ImDrawList::AddBezierQuadratic(const ImVec2& p1, const ImVec2& p2, const Im
|
||||
|
||||
PathLineTo(p1);
|
||||
PathBezierQuadraticCurveTo(p2, p3, num_segments);
|
||||
PathStroke(col, 0, thickness);
|
||||
PathStroke(col, thickness);
|
||||
}
|
||||
|
||||
void ImDrawList::AddText(ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end, float wrap_width, const ImVec4* cpu_fine_clip_rect)
|
||||
@@ -1776,7 +1791,10 @@ void ImDrawList::AddImageRounded(ImTextureRef tex_ref, const ImVec2& p_min, cons
|
||||
if ((col & IM_COL32_A_MASK) == 0)
|
||||
return;
|
||||
|
||||
flags = FixRectCornerFlags(flags);
|
||||
IM_ASSERT((flags & 0x0F) == 0 && "Misuse of legacy hardcoded ImDrawCornerFlags values!"); // If this assert triggers on legacy code: see comments in ImDrawList::PathRect().
|
||||
if ((flags & ImDrawFlags_RoundCornersMask_) == 0)
|
||||
flags |= ImDrawFlags_RoundCornersAll;
|
||||
|
||||
if (rounding < 0.5f || (flags & ImDrawFlags_RoundCornersMask_) == ImDrawFlags_RoundCornersNone)
|
||||
{
|
||||
AddImage(tex_ref, p_min, p_max, uv_min, uv_max, col);
|
||||
@@ -2502,10 +2520,11 @@ void ImTextureData::DestroyPixels()
|
||||
// - Default texture data encoded in ASCII
|
||||
// - ImFontAtlas()
|
||||
// - ImFontAtlas::Clear()
|
||||
// - ImFontAtlas::CompactCache()
|
||||
// - ImFontAtlas::ClearFonts()
|
||||
// - ImFontAtlas::ClearInputData()
|
||||
// - ImFontAtlas::ClearTexData()
|
||||
// - ImFontAtlas::ClearFonts()
|
||||
// - ImFontAtlas::CompactCache()
|
||||
// - ImFontAtlas::SetFontLoader()
|
||||
//-----------------------------------------------------------------------------
|
||||
// - ImFontAtlasUpdateNewFrame()
|
||||
// - ImFontAtlasTextureBlockConvert()
|
||||
@@ -2666,7 +2685,9 @@ ImFontAtlas::~ImFontAtlas()
|
||||
TexData = NULL;
|
||||
}
|
||||
|
||||
// If you call this mid-frame, you would need to add new font and bind them!
|
||||
// You probably should not call this directly. It is not well specified.
|
||||
// If you want to replace all your fonts mid-frame, most likely you should instead call ClearFonts() then load the new fonts.
|
||||
// Calling this mid-frame will discard the CPU-side copy of the texture data which is generally unreliable as you may have textures queued for creation or updates.
|
||||
void ImFontAtlas::Clear()
|
||||
{
|
||||
bool backup_renderer_has_textures = RendererHasTextures;
|
||||
@@ -2676,20 +2697,27 @@ void ImFontAtlas::Clear()
|
||||
RendererHasTextures = backup_renderer_has_textures;
|
||||
}
|
||||
|
||||
void ImFontAtlas::CompactCache()
|
||||
void ImFontAtlas::ClearFonts()
|
||||
{
|
||||
ImFontAtlasTextureCompact(this);
|
||||
}
|
||||
|
||||
void ImFontAtlas::SetFontLoader(const ImFontLoader* font_loader)
|
||||
{
|
||||
ImFontAtlasBuildSetupFontLoader(this, font_loader);
|
||||
// FIXME-NEWATLAS: Illegal to remove currently bound font.
|
||||
IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas!");
|
||||
for (ImFont* font : Fonts)
|
||||
ImFontAtlasBuildNotifySetFont(this, font, NULL);
|
||||
ImFontAtlasBuildDestroy(this);
|
||||
ClearInputData();
|
||||
Fonts.clear_delete();
|
||||
TexIsBuilt = false;
|
||||
for (ImDrawListSharedData* shared_data : DrawListSharedDatas)
|
||||
if (shared_data->FontAtlas == this)
|
||||
{
|
||||
shared_data->Font = NULL;
|
||||
shared_data->FontScale = shared_data->FontSize = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void ImFontAtlas::ClearInputData()
|
||||
{
|
||||
IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas!");
|
||||
|
||||
for (ImFont* font : Fonts)
|
||||
ImFontAtlasFontDestroyOutput(this, font);
|
||||
for (ImFontConfig& font_cfg : Sources)
|
||||
@@ -2713,22 +2741,14 @@ void ImFontAtlas::ClearTexData()
|
||||
//Locked = true; // Hoped to be able to lock this down but some reload patterns may not be happy with it.
|
||||
}
|
||||
|
||||
void ImFontAtlas::ClearFonts()
|
||||
void ImFontAtlas::CompactCache()
|
||||
{
|
||||
// FIXME-NEWATLAS: Illegal to remove currently bound font.
|
||||
IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas!");
|
||||
for (ImFont* font : Fonts)
|
||||
ImFontAtlasBuildNotifySetFont(this, font, NULL);
|
||||
ImFontAtlasBuildDestroy(this);
|
||||
ClearInputData();
|
||||
Fonts.clear_delete();
|
||||
TexIsBuilt = false;
|
||||
for (ImDrawListSharedData* shared_data : DrawListSharedDatas)
|
||||
if (shared_data->FontAtlas == this)
|
||||
{
|
||||
shared_data->Font = NULL;
|
||||
shared_data->FontScale = shared_data->FontSize = 0.0f;
|
||||
}
|
||||
ImFontAtlasTextureCompact(this);
|
||||
}
|
||||
|
||||
void ImFontAtlas::SetFontLoader(const ImFontLoader* font_loader)
|
||||
{
|
||||
ImFontAtlasBuildSetupFontLoader(this, font_loader);
|
||||
}
|
||||
|
||||
static void ImFontAtlasBuildUpdateRendererHasTexturesFromContext(ImFontAtlas* atlas)
|
||||
@@ -2962,12 +2982,17 @@ void ImFontAtlasTextureBlockCopy(ImTextureData* src_tex, int src_x, int src_y, I
|
||||
memcpy(dst_tex->GetPixelsAt(dst_x, dst_y + y), src_tex->GetPixelsAt(src_x, src_y + y), w * dst_tex->BytesPerPixel);
|
||||
}
|
||||
|
||||
// Queue texture block update for renderer backend
|
||||
void ImFontAtlasTextureBlockQueueUpload(ImFontAtlas* atlas, ImTextureData* tex, int x, int y, int w, int h)
|
||||
{
|
||||
ImTextureDataQueueUpload(tex, x, y, w, h);
|
||||
atlas->TexIsBuilt = false;
|
||||
}
|
||||
|
||||
// Queue texture block update for renderer backend
|
||||
void ImTextureDataQueueUpload(ImTextureData* tex, int x, int y, int w, int h)
|
||||
{
|
||||
IM_ASSERT(tex->Status != ImTextureStatus_WantDestroy && tex->Status != ImTextureStatus_Destroyed);
|
||||
IM_ASSERT(x >= 0 && x <= 0xFFFF && y >= 0 && y <= 0xFFFF && w >= 0 && x + w <= 0x10000 && h >= 0 && y + h <= 0x10000);
|
||||
IM_UNUSED(atlas);
|
||||
|
||||
ImTextureRect req = { (unsigned short)x, (unsigned short)y, (unsigned short)w, (unsigned short)h };
|
||||
int new_x1 = ImMax(tex->UpdateRect.w == 0 ? 0 : tex->UpdateRect.x + tex->UpdateRect.w, req.x + req.w);
|
||||
@@ -2980,7 +3005,6 @@ void ImFontAtlasTextureBlockQueueUpload(ImFontAtlas* atlas, ImTextureData* tex,
|
||||
tex->UsedRect.y = ImMin(tex->UsedRect.y, req.y);
|
||||
tex->UsedRect.w = (unsigned short)(ImMax(tex->UsedRect.x + tex->UsedRect.w, req.x + req.w) - tex->UsedRect.x);
|
||||
tex->UsedRect.h = (unsigned short)(ImMax(tex->UsedRect.y + tex->UsedRect.h, req.y + req.h) - tex->UsedRect.y);
|
||||
atlas->TexIsBuilt = false;
|
||||
|
||||
// No need to queue if status is == ImTextureStatus_WantCreate
|
||||
if (tex->Status == ImTextureStatus_OK || tex->Status == ImTextureStatus_WantUpdates)
|
||||
@@ -3052,7 +3076,7 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg_in)
|
||||
}
|
||||
else
|
||||
{
|
||||
IM_ASSERT(Fonts.Size > 0 && "Cannot use MergeMode for the first font"); // When using MergeMode make sure that a font has already been added before.
|
||||
IM_ASSERT(Fonts.Size > 0 && "Cannot use MergeMode for the first font!"); // When using MergeMode make sure that a font has already been added before.
|
||||
font = font_cfg_in->DstFont ? font_cfg_in->DstFont : Fonts.back();
|
||||
ImFontAtlasFontDiscardBakes(this, font, 0); // Need to discard bakes if the font was already used, because baked->FontLoaderDatas[] will change size. (#9162)
|
||||
}
|
||||
@@ -3080,6 +3104,11 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg_in)
|
||||
IM_ASSERT(font_cfg->FontLoader->FontBakedLoadGlyph != NULL);
|
||||
IM_ASSERT(font_cfg->FontLoader->LoaderInit == NULL && font_cfg->FontLoader->LoaderShutdown == NULL); // FIXME-NEWATLAS: Unsupported yet.
|
||||
}
|
||||
// | Target w/ Implicit RefSize | Target w/ Explicit RefSize |
|
||||
// Adding w/ Implicit RefSize: | OK (same scale) | OK (same scale) |
|
||||
// Adding w/ Explicit RefSize: | KO | OK (custom scale) |
|
||||
if (font_cfg_in->MergeMode && font_cfg_in->SizePixels > 0)
|
||||
IM_ASSERT((font->Flags & ImFontFlags_ImplicitRefSize) == 0 && "Cannot use MergeMode with an explicit reference size when the destination font used an implicit reference size!");
|
||||
IM_ASSERT(font_cfg->FontLoaderData == NULL);
|
||||
|
||||
if (!ImFontAtlasFontSourceInit(this, font_cfg))
|
||||
@@ -3147,7 +3176,10 @@ ImFont* ImFontAtlas::AddFontDefaultBitmap(const ImFontConfig* font_cfg_template)
|
||||
if (!font_cfg_template)
|
||||
font_cfg.PixelSnapH = true; // Prevents sub-integer scaling factors at lower-level layers.
|
||||
if (font_cfg.SizePixels <= 0.0f)
|
||||
{
|
||||
font_cfg.SizePixels = 13.0f; // This only serves (1) as a reference for GlyphOffset.y setting and (2) as a default for pre-1.92 backend.
|
||||
font_cfg.Flags |= ImFontFlags_ImplicitRefSize;
|
||||
}
|
||||
if (font_cfg.Name[0] == '\0')
|
||||
ImFormatString(font_cfg.Name, IM_COUNTOF(font_cfg.Name), "ProggyClean.ttf");
|
||||
font_cfg.EllipsisChar = (ImWchar)0x0085;
|
||||
@@ -3172,7 +3204,10 @@ ImFont* ImFontAtlas::AddFontDefaultVector(const ImFontConfig* font_cfg_template)
|
||||
if (!font_cfg_template)
|
||||
font_cfg.PixelSnapH = true; // Precisely match ProggyClean, but prevents sub-integer scaling factors at lower-level layers.
|
||||
if (font_cfg.SizePixels <= 0.0f)
|
||||
{
|
||||
font_cfg.SizePixels = 13.0f;
|
||||
font_cfg.Flags |= ImFontFlags_ImplicitRefSize;
|
||||
}
|
||||
if (font_cfg.Name[0] == '\0')
|
||||
ImFormatString(font_cfg.Name, IM_COUNTOF(font_cfg.Name), "ProggyForever.ttf");
|
||||
font_cfg.ExtraSizeScale *= 1.015f; // Match ProggyClean
|
||||
@@ -6016,7 +6051,7 @@ void ImGui::RenderCheckMark(ImDrawList* draw_list, ImVec2 pos, ImU32 col, float
|
||||
draw_list->PathLineTo(ImVec2(bx - third, by - third));
|
||||
draw_list->PathLineTo(ImVec2(bx, by));
|
||||
draw_list->PathLineTo(ImVec2(bx + third * 2.0f, by - third * 2.0f));
|
||||
draw_list->PathStroke(col, 0, thickness);
|
||||
draw_list->PathStroke(col, thickness);
|
||||
}
|
||||
|
||||
// Render an arrow. 'pos' is position of the arrow tip. half_sz.x is length from base to tip. half_sz.y is length on each side.
|
||||
|
||||
+24
-13
@@ -95,6 +95,10 @@ static void* (*GImGuiFreeTypeAllocFunc)(size_t size, void* user_data) = ImGuiFre
|
||||
static void (*GImGuiFreeTypeFreeFunc)(void* ptr, void* user_data) = ImGuiFreeTypeDefaultFreeFunc;
|
||||
static void* GImGuiFreeTypeAllocatorUserData = nullptr;
|
||||
|
||||
// Load struct
|
||||
static ImFontLoader GImGuiFreeTypeLoader;
|
||||
static char GImGuiFreeTypeLoaderName[48] = "FreeType";
|
||||
|
||||
// Lunasvg support
|
||||
#ifdef IMGUI_ENABLE_FREETYPE_LUNASVG
|
||||
static FT_Error ImGuiLunasvgPortInit(FT_Pointer* state);
|
||||
@@ -146,6 +150,7 @@ struct ImGui_ImplFreeType_Data
|
||||
{
|
||||
FT_Library Library;
|
||||
FT_MemoryRec_ MemoryManager;
|
||||
char BackendName[48];
|
||||
ImGui_ImplFreeType_Data() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
@@ -359,6 +364,11 @@ static bool ImGui_ImplFreeType_LoaderInit(ImFontAtlas* atlas)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Update ImFontLoader::Name field with linked version
|
||||
FT_Int ver_linked_major, ver_linked_minor, ver_linked_patch;
|
||||
FT_Library_Version(bd->Library, &ver_linked_major, &ver_linked_minor, &ver_linked_patch);
|
||||
snprintf(GImGuiFreeTypeLoaderName, sizeof(GImGuiFreeTypeLoaderName), "FreeType (%d.%d.%d; %d.%d.%d)", FREETYPE_MAJOR, FREETYPE_MINOR, FREETYPE_PATCH, ver_linked_major, ver_linked_minor, ver_linked_patch);
|
||||
|
||||
// If you don't call FT_Add_Default_Modules() the rest of code may work, but FreeType won't use our custom allocator.
|
||||
FT_Add_Default_Modules(bd->Library);
|
||||
|
||||
@@ -418,8 +428,9 @@ static bool ImGui_ImplFreeType_FontBakedInit(ImFontAtlas* atlas, ImFontConfig* s
|
||||
{
|
||||
IM_UNUSED(atlas);
|
||||
float size = baked->Size;
|
||||
const float ref_size = baked->OwnerFont->Sources[0]->SizePixels;
|
||||
if (src->MergeMode && src->SizePixels != 0.0f)
|
||||
size *= (src->SizePixels / baked->OwnerFont->Sources[0]->SizePixels);
|
||||
size *= (src->SizePixels / ref_size);
|
||||
size *= src->ExtraSizeScale;
|
||||
|
||||
ImGui_ImplFreeType_FontSrcData* bd_font_data = (ImGui_ImplFreeType_FontSrcData*)src->FontLoaderData;
|
||||
@@ -569,18 +580,18 @@ static bool ImGui_ImplFreetype_FontSrcContainsGlyph(ImFontAtlas* atlas, ImFontCo
|
||||
|
||||
const ImFontLoader* ImGuiFreeType::GetFontLoader()
|
||||
{
|
||||
static ImFontLoader loader;
|
||||
loader.Name = "FreeType";
|
||||
loader.LoaderInit = ImGui_ImplFreeType_LoaderInit;
|
||||
loader.LoaderShutdown = ImGui_ImplFreeType_LoaderShutdown;
|
||||
loader.FontSrcInit = ImGui_ImplFreeType_FontSrcInit;
|
||||
loader.FontSrcDestroy = ImGui_ImplFreeType_FontSrcDestroy;
|
||||
loader.FontSrcContainsGlyph = ImGui_ImplFreetype_FontSrcContainsGlyph;
|
||||
loader.FontBakedInit = ImGui_ImplFreeType_FontBakedInit;
|
||||
loader.FontBakedDestroy = ImGui_ImplFreeType_FontBakedDestroy;
|
||||
loader.FontBakedLoadGlyph = ImGui_ImplFreeType_FontBakedLoadGlyph;
|
||||
loader.FontBakedSrcLoaderDataSize = sizeof(ImGui_ImplFreeType_FontSrcBakedData);
|
||||
return &loader;
|
||||
ImFontLoader* loader = &GImGuiFreeTypeLoader;
|
||||
loader->Name = GImGuiFreeTypeLoaderName; // Initially "FreeType" then updated during the call to ImGui_ImplFreeType_LoaderInit()
|
||||
loader->LoaderInit = ImGui_ImplFreeType_LoaderInit;
|
||||
loader->LoaderShutdown = ImGui_ImplFreeType_LoaderShutdown;
|
||||
loader->FontSrcInit = ImGui_ImplFreeType_FontSrcInit;
|
||||
loader->FontSrcDestroy = ImGui_ImplFreeType_FontSrcDestroy;
|
||||
loader->FontSrcContainsGlyph = ImGui_ImplFreetype_FontSrcContainsGlyph;
|
||||
loader->FontBakedInit = ImGui_ImplFreeType_FontBakedInit;
|
||||
loader->FontBakedDestroy = ImGui_ImplFreeType_FontBakedDestroy;
|
||||
loader->FontBakedLoadGlyph = ImGui_ImplFreeType_FontBakedLoadGlyph;
|
||||
loader->FontBakedSrcLoaderDataSize = sizeof(ImGui_ImplFreeType_FontSrcBakedData);
|
||||
return loader;
|
||||
}
|
||||
|
||||
void ImGuiFreeType::SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void (*free_func)(void* ptr, void* user_data), void* user_data)
|
||||
|
||||
Vendored
+50
-27
@@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.92.7
|
||||
// dear imgui, v1.92.8
|
||||
// (tables and columns code)
|
||||
|
||||
/*
|
||||
@@ -240,6 +240,7 @@ Index of this file:
|
||||
#pragma GCC diagnostic ignored "-Wformat" // warning: format '%p' expects argument of type 'int'/'void*', but argument X has type 'unsigned int'/'ImGuiWindow*'
|
||||
#pragma GCC diagnostic ignored "-Wstrict-overflow"
|
||||
#pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
|
||||
#pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may change value
|
||||
#pragma GCC diagnostic ignored "-Wsign-conversion" // warning: conversion to 'xxxx' from 'xxxx' may change the sign of the result
|
||||
#endif
|
||||
|
||||
@@ -1315,14 +1316,32 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
|
||||
table->InnerWindow->DecoInnerSizeY1 = table_instance->LastFrozenHeight;
|
||||
table_instance->LastFrozenHeight = 0.0f;
|
||||
|
||||
// Initial state
|
||||
ImGuiWindow* inner_window = table->InnerWindow;
|
||||
ImGuiBoxSelectState* bs = &g.BoxSelectState;
|
||||
if (bs->Window == inner_window && bs->UnclipMode)
|
||||
TableApplyExternalUnclipRect(table, bs->UnclipRect);
|
||||
|
||||
// Initial state
|
||||
if (table->Flags & ImGuiTableFlags_NoClip)
|
||||
table->DrawSplitter->SetCurrentChannel(inner_window->DrawList, TABLE_DRAW_CHANNEL_NOCLIP);
|
||||
else
|
||||
inner_window->DrawList->PushClipRect(inner_window->InnerClipRect.Min, inner_window->InnerClipRect.Max, false); // FIXME: use table->InnerClipRect?
|
||||
}
|
||||
|
||||
// When starting a BeginMultiSelect() after table has been layout we update IsRequestOutput fields.
|
||||
void ImGui::TableApplyExternalUnclipRect(ImGuiTable* table, ImRect& rect)
|
||||
{
|
||||
if (rect.IsInverted())
|
||||
return;
|
||||
for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
|
||||
{
|
||||
ImGuiTableColumn* column = &table->Columns[column_n];
|
||||
if (!column->IsRequestOutput)
|
||||
if (rect.Overlaps(ImRect(column->MinX, table->WorkRect.Min.y, column->MaxX, FLT_MAX)))
|
||||
column->IsRequestOutput = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Process hit-testing on resizing borders. Actual size change will be applied in EndTable()
|
||||
// - Set table->HoveredColumnBorder with a short delay/timer to reduce visual feedback noise.
|
||||
void ImGui::TableUpdateBorders(ImGuiTable* table)
|
||||
@@ -1436,12 +1455,12 @@ void ImGui::EndTable()
|
||||
if (table->Flags & ImGuiTableFlags_ScrollX)
|
||||
{
|
||||
const float outer_padding_for_border = (table->Flags & ImGuiTableFlags_BordersOuterV) ? TABLE_BORDER_SIZE : 0.0f;
|
||||
float max_pos_x = table->InnerWindow->DC.CursorMaxPos.x;
|
||||
float max_pos_x = inner_window->DC.CursorMaxPos.x;
|
||||
if (table->RightMostEnabledColumn != -1)
|
||||
max_pos_x = ImMax(max_pos_x, table->Columns[table->RightMostEnabledColumn].WorkMaxX + table->CellPaddingX + table->OuterPaddingX - outer_padding_for_border);
|
||||
if (table->ResizedColumn != -1)
|
||||
max_pos_x = ImMax(max_pos_x, table->ResizeLockMinContentsX2);
|
||||
table->InnerWindow->DC.CursorMaxPos.x = max_pos_x + table->TempData->AngledHeadersExtraWidth;
|
||||
inner_window->DC.CursorMaxPos.x = max_pos_x + table->TempData->AngledHeadersExtraWidth;
|
||||
}
|
||||
|
||||
// Pop clipping rect
|
||||
@@ -1550,7 +1569,7 @@ void ImGui::EndTable()
|
||||
}
|
||||
else
|
||||
{
|
||||
table->InnerWindow->DC.TreeDepth--;
|
||||
inner_window->DC.TreeDepth--;
|
||||
ItemSize(table->OuterRect.GetSize());
|
||||
ItemAdd(table->OuterRect, 0);
|
||||
}
|
||||
@@ -1565,13 +1584,12 @@ void ImGui::EndTable()
|
||||
}
|
||||
else if (temp_data->UserOuterSize.x <= 0.0f)
|
||||
{
|
||||
// Some references for this: #7651 + tests "table_reported_size", "table_reported_size_outer" equivalent Y block
|
||||
// - Checking for ImGuiTableFlags_ScrollX/ScrollY flag makes us a frame ahead when disabling those flags.
|
||||
// - FIXME-TABLE: Would make sense to pre-compute expected scrollbar visibility/sizes to generally save a frame of feedback.
|
||||
const float inner_content_max_x = table->OuterRect.Min.x + table->ColumnsAutoFitWidth; // Slightly misleading name but used for code symmetry with inner_content_max_y
|
||||
const float decoration_size = table->TempData->AngledHeadersExtraWidth + ((table->Flags & ImGuiTableFlags_ScrollY) ? inner_window->ScrollbarSizes.x : 0.0f);
|
||||
outer_window->DC.IdealMaxPos.x = ImMax(outer_window->DC.IdealMaxPos.x, inner_content_max_x + decoration_size - temp_data->UserOuterSize.x);
|
||||
outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, ImMin(table->OuterRect.Max.x, inner_content_max_x + decoration_size));
|
||||
// Some references for this: #7651 + tests "table_reported_size", "table_reported_size_outer" equivalent Y block, #9352
|
||||
// - FIXME-TABLE: Would make sense to pre-compute expected scrollbar visibility/sizes to generally save a frame of feedback? See broken test in 'table_reported_size_outer'
|
||||
const float outer_content_max_x = table->OuterRect.Min.x + table->ColumnsAutoFitWidth;
|
||||
const float decoration_size = table->TempData->AngledHeadersExtraWidth + ((inner_window != outer_window) ? inner_window->ScrollbarSizes.x : 0.0f);
|
||||
outer_window->DC.IdealMaxPos.x = ImMax(outer_window->DC.IdealMaxPos.x, outer_content_max_x + decoration_size - temp_data->UserOuterSize.x);
|
||||
outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, ImMin(table->OuterRect.Max.x, outer_content_max_x + decoration_size));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1579,9 +1597,12 @@ void ImGui::EndTable()
|
||||
}
|
||||
if (temp_data->UserOuterSize.y <= 0.0f)
|
||||
{
|
||||
const float decoration_size = (table->Flags & ImGuiTableFlags_ScrollX) ? inner_window->ScrollbarSizes.y : 0.0f;
|
||||
outer_window->DC.IdealMaxPos.y = ImMax(outer_window->DC.IdealMaxPos.y, inner_content_max_y + decoration_size - temp_data->UserOuterSize.y);
|
||||
outer_window->DC.CursorMaxPos.y = ImMax(backup_outer_max_pos.y, ImMin(table->OuterRect.Max.y, inner_content_max_y + decoration_size));
|
||||
// (same comment as above)
|
||||
const float outer_content_size_y = (inner_window == outer_window) ? (inner_content_max_y - table->InnerRect.Min.y) : (inner_content_max_y - inner_window->DC.CursorStartPos.y);
|
||||
const float outer_content_max_y = table->OuterRect.Min.y + outer_content_size_y;
|
||||
const float decoration_size = (inner_window != outer_window ? inner_window->ScrollbarSizes.y : 0.0f);
|
||||
outer_window->DC.IdealMaxPos.y = ImMax(outer_window->DC.IdealMaxPos.y, outer_content_max_y + decoration_size - temp_data->UserOuterSize.y);
|
||||
outer_window->DC.CursorMaxPos.y = ImMax(backup_outer_max_pos.y, ImMin(table->OuterRect.Max.y, outer_content_max_y + decoration_size));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1641,7 +1662,7 @@ void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, flo
|
||||
ImGuiTable* table = g.CurrentTable;
|
||||
IM_ASSERT_USER_ERROR_RET(table != NULL, "Call should only be done while in BeginTable() scope!");
|
||||
IM_ASSERT_USER_ERROR_RET(table->DeclColumnsCount < table->ColumnsCount, "TableSetupColumn(): called too many times!");
|
||||
IM_ASSERT_USER_ERROR_RET(table->IsLayoutLocked == false, "TableSetupColumn(): need to call before first row!");
|
||||
IM_ASSERT_USER_ERROR_RET(table->IsLayoutLocked == false, "TableSetupColumn(): need to call before first row!"); // Table layout is locked when submitting a row or when calling BeginMultiSelect() with box-select.
|
||||
IM_ASSERT((flags & ImGuiTableColumnFlags_StatusMask_) == 0 && "Illegal to pass StatusMask values to TableSetupColumn()");
|
||||
|
||||
ImGuiTableColumn* column = &table->Columns[table->DeclColumnsCount];
|
||||
@@ -2053,11 +2074,11 @@ void ImGui::TableEndRow(ImGuiTable* table)
|
||||
|
||||
// Draw top border
|
||||
if (top_border_col && bg_y1 >= table->BgClipRect.Min.y && bg_y1 < table->BgClipRect.Max.y)
|
||||
window->DrawList->AddLine(ImVec2(table->BorderX1, bg_y1), ImVec2(table->BorderX2, bg_y1), top_border_col, border_size);
|
||||
window->DrawList->AddLineH(table->BorderX1, table->BorderX2, bg_y1, top_border_col, border_size);
|
||||
|
||||
// Draw bottom border at the row unfreezing mark (always strong)
|
||||
if (draw_strong_bottom_border && bg_y2 >= table->BgClipRect.Min.y && bg_y2 < table->BgClipRect.Max.y)
|
||||
window->DrawList->AddLine(ImVec2(table->BorderX1, bg_y2), ImVec2(table->BorderX2, bg_y2), table->BorderColorStrong, border_size);
|
||||
window->DrawList->AddLineH(table->BorderX1, table->BorderX2, bg_y2, table->BorderColorStrong, border_size);
|
||||
}
|
||||
|
||||
// End frozen rows (when we are past the last frozen row line, teleport cursor and alter clipping rectangle)
|
||||
@@ -2834,7 +2855,7 @@ void ImGui::TableDrawBorders(ImGuiTable* table)
|
||||
else if ((table->Flags & (ImGuiTableFlags_NoBordersInBodyUntilResize | ImGuiTableFlags_NoBordersInBody)) == 0)
|
||||
draw_y2 = draw_y2_body;
|
||||
if (draw_y2 > draw_y1)
|
||||
inner_drawlist->AddLine(ImVec2(column->MaxX, draw_y1), ImVec2(column->MaxX, draw_y2), TableGetColumnBorderCol(table, order_n, column_n), border_size);
|
||||
inner_drawlist->AddLineV(column->MaxX, draw_y1, draw_y2, TableGetColumnBorderCol(table, order_n, column_n), border_size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2851,17 +2872,17 @@ void ImGui::TableDrawBorders(ImGuiTable* table)
|
||||
const ImU32 outer_col = table->BorderColorStrong;
|
||||
if ((table->Flags & ImGuiTableFlags_BordersOuter) == ImGuiTableFlags_BordersOuter)
|
||||
{
|
||||
inner_drawlist->AddRect(outer_border.Min, outer_border.Max, outer_col, 0.0f, 0, border_size);
|
||||
inner_drawlist->AddRect(outer_border.Min, outer_border.Max, outer_col, 0.0f, border_size);
|
||||
}
|
||||
else if (table->Flags & ImGuiTableFlags_BordersOuterV)
|
||||
{
|
||||
inner_drawlist->AddLine(outer_border.Min, ImVec2(outer_border.Min.x, outer_border.Max.y), outer_col, border_size);
|
||||
inner_drawlist->AddLine(ImVec2(outer_border.Max.x, outer_border.Min.y), outer_border.Max, outer_col, border_size);
|
||||
inner_drawlist->AddLineV(outer_border.Min.x, outer_border.Min.y, outer_border.Max.y, outer_col, border_size);
|
||||
inner_drawlist->AddLineV(outer_border.Max.x, outer_border.Min.y, outer_border.Max.y, outer_col, border_size);
|
||||
}
|
||||
else if (table->Flags & ImGuiTableFlags_BordersOuterH)
|
||||
{
|
||||
inner_drawlist->AddLine(outer_border.Min, ImVec2(outer_border.Max.x, outer_border.Min.y), outer_col, border_size);
|
||||
inner_drawlist->AddLine(ImVec2(outer_border.Min.x, outer_border.Max.y), outer_border.Max, outer_col, border_size);
|
||||
inner_drawlist->AddLineH(outer_border.Min.x, outer_border.Max.x, outer_border.Min.y, outer_col, border_size);
|
||||
inner_drawlist->AddLineH(outer_border.Min.x, outer_border.Max.x, outer_border.Max.y, outer_col, border_size);
|
||||
}
|
||||
}
|
||||
if ((table->Flags & ImGuiTableFlags_BordersInnerH) && table->RowPosY2 < table->OuterRect.Max.y)
|
||||
@@ -2869,7 +2890,7 @@ void ImGui::TableDrawBorders(ImGuiTable* table)
|
||||
// Draw bottom-most row border between it is above outer border.
|
||||
const float border_y = table->RowPosY2;
|
||||
if (border_y >= table->BgClipRect.Min.y && border_y < table->BgClipRect.Max.y)
|
||||
inner_drawlist->AddLine(ImVec2(table->BorderX1, border_y), ImVec2(table->BorderX2, border_y), table->BorderColorLight, border_size);
|
||||
inner_drawlist->AddLineH(table->BorderX1, table->BorderX2, border_y, table->BorderColorLight, border_size);
|
||||
}
|
||||
|
||||
inner_drawlist->PopClipRect();
|
||||
@@ -3174,7 +3195,7 @@ void ImGui::TableHeader(const char* label)
|
||||
if (label == NULL)
|
||||
label = "";
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
ImVec2 label_size = CalcTextSize(label, label_end, true);
|
||||
ImVec2 label_size = CalcTextSize(label, label_end, false);
|
||||
ImVec2 label_pos = window->DC.CursorPos;
|
||||
|
||||
// If we already got a row height, there's use that.
|
||||
@@ -3293,6 +3314,8 @@ void ImGui::TableHeader(const char* label)
|
||||
// We don't use BeginPopupContextItem() because we want the popup to stay up even after the column is hidden
|
||||
if (IsPopupOpenRequestForItem(ImGuiPopupFlags_None, id))
|
||||
TableOpenContextMenu(column_n);
|
||||
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
|
||||
}
|
||||
|
||||
// Unlike TableHeadersRow() it is not expected that you can reimplement or customize this with custom widgets.
|
||||
@@ -4595,7 +4618,7 @@ void ImGui::EndColumns()
|
||||
// Draw column
|
||||
const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : hovered ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator);
|
||||
const float xi = IM_TRUNC(x);
|
||||
window->DrawList->AddLine(ImVec2(xi, y1 + 1.0f), ImVec2(xi, y2), col);
|
||||
window->DrawList->AddLineV(xi, y1 + 1.0f, y2, col);
|
||||
}
|
||||
|
||||
// Apply dragging after drawing the column lines, so our rendered lines are in sync with how items were displayed during the frame.
|
||||
|
||||
Vendored
+256
-104
@@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.92.7
|
||||
// dear imgui, v1.92.8
|
||||
// (widgets code)
|
||||
|
||||
/*
|
||||
@@ -92,6 +92,7 @@ Index of this file:
|
||||
#pragma GCC diagnostic ignored "-Wstrict-overflow" // warning: assuming signed overflow does not occur when simplifying division / ..when changing X +- C1 cmp C2 to X cmp C2 -+ C1
|
||||
#pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
|
||||
#pragma GCC diagnostic ignored "-Wcast-qual" // warning: cast from type 'const xxxx *' to type 'xxxx *' casts away qualifiers
|
||||
#pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may change value
|
||||
#pragma GCC diagnostic ignored "-Wsign-conversion" // warning: conversion to 'xxxx' from 'xxxx' may change the sign of the result
|
||||
#endif
|
||||
|
||||
@@ -401,7 +402,8 @@ void ImGui::LabelTextV(const char* label, const char* fmt, va_list args)
|
||||
const char* value_text_begin, *value_text_end;
|
||||
ImFormatStringToTempBufferV(&value_text_begin, &value_text_end, fmt, args);
|
||||
const ImVec2 value_size = CalcTextSize(value_text_begin, value_text_end, false);
|
||||
const ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
const ImVec2 label_size = CalcTextSize(label, label_end, false);
|
||||
|
||||
const ImVec2 pos = window->DC.CursorPos;
|
||||
const ImRect value_bb(pos, pos + ImVec2(w, value_size.y + style.FramePadding.y * 2));
|
||||
@@ -413,7 +415,7 @@ void ImGui::LabelTextV(const char* label, const char* fmt, va_list args)
|
||||
// Render
|
||||
RenderTextClipped(value_bb.Min + style.FramePadding, value_bb.Max, value_text_begin, value_text_end, &value_size, ImVec2(0.0f, 0.0f));
|
||||
if (label_size.x > 0.0f)
|
||||
RenderText(ImVec2(value_bb.Max.x + style.ItemInnerSpacing.x, value_bb.Min.y + style.FramePadding.y), label);
|
||||
RenderText(ImVec2(value_bb.Max.x + style.ItemInnerSpacing.x, value_bb.Min.y + style.FramePadding.y), label, label_end, false);
|
||||
}
|
||||
|
||||
void ImGui::BulletText(const char* fmt, ...)
|
||||
@@ -788,7 +790,8 @@ bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags
|
||||
ImGuiContext& g = *GImGui;
|
||||
const ImGuiStyle& style = g.Style;
|
||||
const ImGuiID id = window->GetID(label);
|
||||
const ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
const ImVec2 label_size = CalcTextSize(label, label_end, false);
|
||||
|
||||
ImVec2 pos = window->DC.CursorPos;
|
||||
if ((flags & ImGuiButtonFlags_AlignTextBaseLine) && style.FramePadding.y < window->DC.CurrLineTextBaseOffset) // Try to vertically align buttons that are smaller/have no padding so that text baseline matches (bit hacky, since it shouldn't be a flag)
|
||||
@@ -810,7 +813,7 @@ bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags
|
||||
|
||||
if (g.LogEnabled)
|
||||
LogSetNextTextDecoration("[", "]");
|
||||
RenderTextClipped(bb.Min + style.FramePadding, bb.Max - style.FramePadding, label, NULL, &label_size, style.ButtonTextAlign, &bb);
|
||||
RenderTextClipped(bb.Min + style.FramePadding, bb.Max - style.FramePadding, label, label_end, &label_size, style.ButtonTextAlign, &bb);
|
||||
|
||||
// Automatically close popups
|
||||
//if (pressed && !(flags & ImGuiButtonFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup))
|
||||
@@ -975,7 +978,7 @@ ImRect ImGui::GetWindowScrollbarRect(ImGuiWindow* window, ImGuiAxis axis)
|
||||
const float scrollbar_size = window->ScrollbarSizes[axis ^ 1]; // (ScrollbarSizes.x = width of Y scrollbar; ScrollbarSizes.y = height of X scrollbar)
|
||||
IM_ASSERT(scrollbar_size >= 0.0f);
|
||||
const float border_size = IM_ROUND(window->WindowBorderSize * 0.5f);
|
||||
const float border_top = (window->Flags & ImGuiWindowFlags_MenuBar) ? IM_ROUND(g.Style.FrameBorderSize * 0.5f) : 0.0f;
|
||||
const float border_top = (window->Flags & ImGuiWindowFlags_MenuBar) ? IM_ROUND(g.Style.FrameBorderSize * 0.5f) : (window->Flags & ImGuiWindowFlags_NoTitleBar) ? border_size : 0;
|
||||
if (axis == ImGuiAxis_X)
|
||||
return ImRect(inner_rect.Min.x + border_size, ImMax(outer_rect.Min.y + border_size, outer_rect.Max.y - border_size - scrollbar_size), inner_rect.Max.x - border_size, outer_rect.Max.y - border_size);
|
||||
else
|
||||
@@ -1148,7 +1151,7 @@ void ImGui::ImageWithBg(ImTextureRef tex_ref, const ImVec2& image_size, const Im
|
||||
else
|
||||
window->DrawList->AddImage(tex_ref, bb.Min + padding, bb.Max - padding, uv0, uv1, GetColorU32(tint_col));
|
||||
if (g.Style.ImageBorderSize > 0.0f)
|
||||
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border), rounding, ImDrawFlags_None, g.Style.ImageBorderSize);
|
||||
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border), rounding, g.Style.ImageBorderSize);
|
||||
}
|
||||
|
||||
void ImGui::Image(ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1)
|
||||
@@ -1243,7 +1246,8 @@ bool ImGui::Checkbox(const char* label, bool* v)
|
||||
ImGuiContext& g = *GImGui;
|
||||
const ImGuiStyle& style = g.Style;
|
||||
const ImGuiID id = window->GetID(label);
|
||||
const ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
const ImVec2 label_size = CalcTextSize(label, label_end, false);
|
||||
|
||||
const float square_sz = GetFrameHeight();
|
||||
const ImVec2 pos = window->DC.CursorPos;
|
||||
@@ -1284,8 +1288,9 @@ bool ImGui::Checkbox(const char* label, bool* v)
|
||||
if (is_visible)
|
||||
{
|
||||
RenderNavCursor(total_bb, id);
|
||||
RenderFrame(check_bb.Min, check_bb.Max, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding);
|
||||
ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : (mixed_value || checked) ? ImGuiCol_CheckboxSelectedBg : ImGuiCol_FrameBg);
|
||||
ImU32 check_col = GetColorU32(ImGuiCol_CheckMark);
|
||||
RenderFrame(check_bb.Min, check_bb.Max, bg_col, true, style.FrameRounding);
|
||||
if (mixed_value)
|
||||
{
|
||||
// Undocumented tristate/mixed/indeterminate checkbox (#2644)
|
||||
@@ -1303,7 +1308,7 @@ bool ImGui::Checkbox(const char* label, bool* v)
|
||||
if (g.LogEnabled)
|
||||
LogRenderedText(&label_pos, mixed_value ? "[~]" : *v ? "[x]" : "[ ]");
|
||||
if (is_visible && label_size.x > 0.0f)
|
||||
RenderText(label_pos, label);
|
||||
RenderText(label_pos, label, label_end, false);
|
||||
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0));
|
||||
return pressed;
|
||||
@@ -1365,7 +1370,8 @@ bool ImGui::RadioButton(const char* label, bool active)
|
||||
ImGuiContext& g = *GImGui;
|
||||
const ImGuiStyle& style = g.Style;
|
||||
const ImGuiID id = window->GetID(label);
|
||||
const ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
const ImVec2 label_size = CalcTextSize(label, label_end, false);
|
||||
|
||||
const float square_sz = GetFrameHeight();
|
||||
const ImVec2 pos = window->DC.CursorPos;
|
||||
@@ -1404,7 +1410,7 @@ bool ImGui::RadioButton(const char* label, bool active)
|
||||
if (g.LogEnabled)
|
||||
LogRenderedText(&label_pos, active ? "(x)" : "( )");
|
||||
if (label_size.x > 0.0f)
|
||||
RenderText(label_pos, label);
|
||||
RenderText(label_pos, label, label_end, false);
|
||||
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
|
||||
return pressed;
|
||||
@@ -1520,7 +1526,7 @@ bool ImGui::TextLink(const char* label)
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
|
||||
ImVec2 pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
|
||||
ImVec2 size = CalcTextSize(label, label_end, true);
|
||||
ImVec2 size = CalcTextSize(label, label_end, false);
|
||||
ImRect bb(pos, pos + size);
|
||||
ItemSize(size, 0.0f);
|
||||
if (!ItemAdd(bb, id))
|
||||
@@ -1551,10 +1557,10 @@ bool ImGui::TextLink(const char* label)
|
||||
}
|
||||
|
||||
float line_y = bb.Max.y + ImFloor(g.FontBaked->Descent * g.FontBakedScale * 0.20f);
|
||||
window->DrawList->AddLine(ImVec2(bb.Min.x, line_y), ImVec2(bb.Max.x, line_y), GetColorU32(line_colf), 1.0f * (float)(int)g.Style._MainScale); // FIXME-TEXT: Underline mode // FIXME-DPI
|
||||
window->DrawList->AddLineH(bb.Min.x, bb.Max.x, line_y, GetColorU32(line_colf), 1.0f * (float)(int)g.Style._MainScale); // FIXME-TEXT: Underline mode // FIXME-DPI
|
||||
|
||||
PushStyleColor(ImGuiCol_Text, GetColorU32(text_colf));
|
||||
RenderText(bb.Min, label, label_end);
|
||||
RenderText(bb.Min, label, label_end, false);
|
||||
PopStyleColor();
|
||||
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
|
||||
@@ -1724,7 +1730,7 @@ void ImGui::Separator()
|
||||
if (window->DC.CurrentColumns)
|
||||
flags |= ImGuiSeparatorFlags_SpanAllColumns;
|
||||
|
||||
SeparatorEx(flags, g.Style.SeparatorSize);
|
||||
SeparatorEx(flags, ImMax(g.Style.SeparatorSize, 1.0f));
|
||||
}
|
||||
|
||||
void ImGui::SeparatorTextEx(ImGuiID id, const char* label, const char* label_end, float extra_w)
|
||||
@@ -1761,9 +1767,9 @@ void ImGui::SeparatorTextEx(ImGuiID id, const char* label, const char* label_end
|
||||
const float sep1_x2 = label_pos.x - style.ItemSpacing.x;
|
||||
const float sep2_x1 = label_pos.x + label_size.x + extra_w + style.ItemSpacing.x;
|
||||
if (sep1_x2 > sep1_x1 && separator_thickness > 0.0f)
|
||||
window->DrawList->AddLine(ImVec2(sep1_x1, seps_y), ImVec2(sep1_x2, seps_y), separator_col, separator_thickness);
|
||||
window->DrawList->AddLineH(sep1_x1, sep1_x2, seps_y, separator_col, separator_thickness);
|
||||
if (sep2_x2 > sep2_x1 && separator_thickness > 0.0f)
|
||||
window->DrawList->AddLine(ImVec2(sep2_x1, seps_y), ImVec2(sep2_x2, seps_y), separator_col, separator_thickness);
|
||||
window->DrawList->AddLineH(sep2_x1, sep2_x2, seps_y, separator_col, separator_thickness);
|
||||
if (g.LogEnabled)
|
||||
LogSetNextTextDecoration("---", NULL);
|
||||
RenderTextEllipsis(window->DrawList, label_pos, ImVec2(bb.Max.x, bb.Max.y + style.ItemSpacing.y), bb.Max.x, label, label_end, &label_size);
|
||||
@@ -1773,7 +1779,7 @@ void ImGui::SeparatorTextEx(ImGuiID id, const char* label, const char* label_end
|
||||
if (g.LogEnabled)
|
||||
LogText("---");
|
||||
if (separator_thickness > 0.0f)
|
||||
window->DrawList->AddLine(ImVec2(sep1_x1, seps_y), ImVec2(sep2_x2, seps_y), separator_col, separator_thickness);
|
||||
window->DrawList->AddLineH(sep1_x1, sep2_x2, seps_y, separator_col, separator_thickness);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1944,8 +1950,9 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF
|
||||
IM_ASSERT((flags & (ImGuiComboFlags_NoPreview | (ImGuiComboFlags)ImGuiComboFlags_CustomPreview)) == 0);
|
||||
|
||||
const float arrow_size = (flags & ImGuiComboFlags_NoArrowButton) ? 0.0f : GetFrameHeight();
|
||||
const ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
const float preview_width = ((flags & ImGuiComboFlags_WidthFitPreview) && (preview_value != NULL)) ? CalcTextSize(preview_value, NULL, true).x : 0.0f;
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
const ImVec2 label_size = CalcTextSize(label, label_end, false);
|
||||
const float preview_width = ((flags & ImGuiComboFlags_WidthFitPreview) && (preview_value != NULL)) ? CalcTextSize(preview_value, NULL, false).x : 0.0f;
|
||||
const float w = (flags & ImGuiComboFlags_NoPreview) ? arrow_size : ((flags & ImGuiComboFlags_WidthFitPreview) ? (arrow_size + preview_width + style.FramePadding.x * 2.0f) : CalcItemWidth());
|
||||
const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f));
|
||||
const ImRect total_bb(bb.Min, bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
|
||||
@@ -1996,7 +2003,7 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF
|
||||
RenderTextClipped(bb.Min + style.FramePadding, ImVec2(value_x2, bb.Max.y), preview_value, NULL, NULL);
|
||||
}
|
||||
if (label_size.x > 0)
|
||||
RenderText(ImVec2(bb.Max.x + style.ItemInnerSpacing.x, bb.Min.y + style.FramePadding.y), label);
|
||||
RenderText(ImVec2(bb.Max.x + style.ItemInnerSpacing.x, bb.Min.y + style.FramePadding.y), label, label_end, false);
|
||||
|
||||
if (!popup_open)
|
||||
return false;
|
||||
@@ -2369,12 +2376,17 @@ bool ImGui::DataTypeApplyFromText(const char* buf, ImGuiDataType data_type, void
|
||||
|
||||
// Sanitize format
|
||||
// - For float/double we have to ignore format with precision (e.g. "%.2f") because sscanf doesn't take them in, so force them into %f and %lf
|
||||
// - In theory could treat empty format as using default, but this would only cover rare/bizarre case of using InputScalar() + integer + format string without %.
|
||||
char format_sanitized[32];
|
||||
if (data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double)
|
||||
{
|
||||
format = type_info->ScanFmt;
|
||||
}
|
||||
else
|
||||
{
|
||||
format = ImParseFormatSanitizeForScanning(format, format_sanitized, IM_COUNTOF(format_sanitized));
|
||||
if (format[0] == '\0')
|
||||
format = type_info->ScanFmt; // Format doesn't want us to show the number currently, but we still need to parse the resulting input
|
||||
}
|
||||
|
||||
// Small types need a 32-bit buffer to receive the result from scanf()
|
||||
int v32 = 0;
|
||||
@@ -2709,7 +2721,8 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
|
||||
const float w = CalcItemWidth();
|
||||
const ImU32 color_marker = (g.NextItemData.HasFlags & ImGuiNextItemDataFlags_HasColorMarker) ? g.NextItemData.ColorMarker : 0;
|
||||
|
||||
const ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
const ImVec2 label_size = CalcTextSize(label, label_end, false);
|
||||
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f));
|
||||
const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
|
||||
|
||||
@@ -2785,7 +2798,7 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
|
||||
RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f));
|
||||
|
||||
if (label_size.x > 0.0f)
|
||||
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
|
||||
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, label_end, false);
|
||||
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | (temp_input_allowed ? ImGuiItemStatusFlags_Inputable : 0));
|
||||
return value_changed;
|
||||
@@ -3310,7 +3323,8 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
|
||||
const float w = CalcItemWidth();
|
||||
const ImU32 color_marker = (g.NextItemData.HasFlags & ImGuiNextItemDataFlags_HasColorMarker) ? g.NextItemData.ColorMarker : 0;
|
||||
|
||||
const ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
const ImVec2 label_size = CalcTextSize(label, label_end, false);
|
||||
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f));
|
||||
const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
|
||||
|
||||
@@ -3382,7 +3396,7 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
|
||||
RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f));
|
||||
|
||||
if (label_size.x > 0.0f)
|
||||
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
|
||||
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, label_end, false);
|
||||
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | (temp_input_allowed ? ImGuiItemStatusFlags_Inputable : 0));
|
||||
return value_changed;
|
||||
@@ -3487,7 +3501,8 @@ bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType d
|
||||
const ImGuiStyle& style = g.Style;
|
||||
const ImGuiID id = window->GetID(label);
|
||||
|
||||
const ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
const ImVec2 label_size = CalcTextSize(label, label_end, false);
|
||||
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + size);
|
||||
const ImRect bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
|
||||
|
||||
@@ -3532,8 +3547,9 @@ bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType d
|
||||
const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_COUNTOF(value_buf), data_type, p_data, format);
|
||||
RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.0f));
|
||||
if (label_size.x > 0.0f)
|
||||
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
|
||||
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, label_end, false);
|
||||
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
|
||||
return value_changed;
|
||||
}
|
||||
|
||||
@@ -3556,7 +3572,8 @@ bool ImGui::VSliderInt(const char* label, const ImVec2& size, int* v, int v_min,
|
||||
// - ImParseFormatSanitizeForPrinting() [Internal]
|
||||
// - ImParseFormatSanitizeForScanning() [Internal]
|
||||
// - ImParseFormatPrecision() [Internal]
|
||||
// - TempInputTextScalar() [Internal]
|
||||
// - TempInputText() [Internal]
|
||||
// - TempInputScalar() [Internal]
|
||||
// - InputScalar()
|
||||
// - InputScalarN()
|
||||
// - InputFloat()
|
||||
@@ -3785,7 +3802,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
|
||||
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiStyle& style = g.Style;
|
||||
IM_ASSERT((flags & ImGuiInputTextFlags_EnterReturnsTrue) == 0); // Not supported by InputScalar(). Please open an issue if you this would be useful to you. Otherwise use IsItemDeactivatedAfterEdit()!
|
||||
//IM_ASSERT((flags & ImGuiInputTextFlags_EnterReturnsTrue) == 0); // Not supported by InputScalar(). Please open an issue if you this would be useful to you. Otherwise use IsItemDeactivatedAfterEdit()!
|
||||
|
||||
if (format == NULL)
|
||||
format = DataTypeGetInfo(data_type)->PrintFmt;
|
||||
@@ -3822,7 +3839,8 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
|
||||
}
|
||||
|
||||
// Apply
|
||||
bool value_changed = ret ? DataTypeApplyFromText(buf, data_type, p_data, format, (flags & ImGuiInputTextFlags_ParseEmptyRefVal) ? p_data_default : NULL) : false;
|
||||
bool input_edited = (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_EditedInternal) != 0; // We would be using 'ret' if ImGuiInputTextFlags_EnterReturnsTrue was not involved.
|
||||
bool value_changed = input_edited ? DataTypeApplyFromText(buf, data_type, p_data, format, (flags & ImGuiInputTextFlags_ParseEmptyRefVal) ? p_data_default : NULL) : false;
|
||||
|
||||
// Step buttons
|
||||
if (has_step_buttons)
|
||||
@@ -3836,13 +3854,13 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
|
||||
if (ButtonEx("-", ImVec2(button_size, button_size)))
|
||||
{
|
||||
DataTypeApplyOp(data_type, '-', p_data, p_data, g.IO.KeyCtrl && p_step_fast ? p_step_fast : p_step);
|
||||
value_changed = true;
|
||||
value_changed = ret = true;
|
||||
}
|
||||
SameLine(0, style.ItemInnerSpacing.x);
|
||||
if (ButtonEx("+", ImVec2(button_size, button_size)))
|
||||
{
|
||||
DataTypeApplyOp(data_type, '+', p_data, p_data, g.IO.KeyCtrl && p_step_fast ? p_step_fast : p_step);
|
||||
value_changed = true;
|
||||
value_changed = ret = true;
|
||||
}
|
||||
PopItemFlag();
|
||||
if (flags & ImGuiInputTextFlags_ReadOnly)
|
||||
@@ -3864,6 +3882,8 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
|
||||
if (value_changed)
|
||||
MarkItemEdited(g.LastItemData.ID);
|
||||
|
||||
if (flags & ImGuiInputTextFlags_EnterReturnsTrue)
|
||||
return ret;
|
||||
return value_changed;
|
||||
}
|
||||
|
||||
@@ -4513,6 +4533,9 @@ static bool InputTextFilterCharacter(ImGuiContext* ctx, ImGuiInputTextState* sta
|
||||
callback_data.EventFlag = ImGuiInputTextFlags_CallbackCharFilter;
|
||||
callback_data.EventChar = (ImWchar)c;
|
||||
callback_data.EventActivated = (g.ActiveId == state->ID && g.ActiveIdIsJustActivated);
|
||||
callback_data.CursorPos = state->Stb->cursor;
|
||||
callback_data.SelectionStart = state->Stb->select_start;
|
||||
callback_data.SelectionEnd = state->Stb->select_end;
|
||||
callback_data.UserData = user_data;
|
||||
if (callback(&callback_data) != 0)
|
||||
return false;
|
||||
@@ -4561,6 +4584,7 @@ void ImGui::InputTextDeactivateHook(ImGuiID id)
|
||||
ImGuiInputTextState* state = &g.InputTextState;
|
||||
if (id == 0 || state->ID != id)
|
||||
return;
|
||||
//IMGUI_DEBUG_LOG_ACTIVEID("InputTextDeactivateHook() id = 0x%08X\n", id);
|
||||
g.InputTextDeactivatedState.ID = state->ID;
|
||||
if (state->Flags & ImGuiInputTextFlags_ReadOnly)
|
||||
{
|
||||
@@ -4695,7 +4719,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
if (is_multiline) // Open group before calling GetID() because groups tracks id created within their scope (including the scrollbar)
|
||||
BeginGroup();
|
||||
const ImGuiID id = window->GetID(label);
|
||||
const ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
const ImVec2 label_size = CalcTextSize(label, label_end, false);
|
||||
const ImVec2 frame_size = CalcItemSize(size_arg, CalcItemWidth(), (is_multiline ? g.FontSize * 8.0f : label_size.y) + style.FramePadding.y * 2.0f); // Arbitrary default of 8 lines high for multi-line
|
||||
const ImVec2 total_size = ImVec2(frame_size.x + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), frame_size.y);
|
||||
|
||||
@@ -4709,7 +4734,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
{
|
||||
ImVec2 backup_pos = window->DC.CursorPos;
|
||||
ItemSize(total_bb, style.FramePadding.y);
|
||||
if (!ItemAdd(total_bb, id, &frame_bb, ImGuiItemFlags_Inputable))
|
||||
bool no_clip = (g.InputTextDeactivatedState.ID == id) || (g.ActiveId == id) || (id == g.NavActivateId); // Mimic some of ItemAdd() logic + add InputTextDeactivatedState.ID check.
|
||||
if (!ItemAdd(total_bb, id, &frame_bb, ImGuiItemFlags_Inputable) && !no_clip)
|
||||
{
|
||||
EndGroup();
|
||||
return false;
|
||||
@@ -4735,7 +4761,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
g.NavActivateId = backup_activate_id;
|
||||
PopStyleVar(3);
|
||||
PopStyleColor();
|
||||
if (!child_visible)
|
||||
if (!child_visible && !no_clip)
|
||||
{
|
||||
EndChild();
|
||||
EndGroup();
|
||||
@@ -4799,7 +4825,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
float scroll_y = is_multiline ? draw_window->Scroll.y : FLT_MAX;
|
||||
|
||||
const bool init_reload_from_user_buf = (state != NULL && state->WantReloadUserBuf);
|
||||
const bool init_changed_specs = (state != NULL && state->Stb->single_line != !is_multiline); // state != NULL means its our state.
|
||||
const bool init_changed_specs_multiline = (state != NULL && (state->Stb->single_line != !is_multiline)); // state != NULL means its our state.
|
||||
const bool init_changed_specs_readonly = (state != NULL && ((state->Flags ^ flags) & ImGuiInputTextFlags_ReadOnly)); // state != NULL means its our state.
|
||||
const bool init_make_active = (input_requested_by_user || input_requested_by_nav || input_requested_by_reactivate || user_scroll_finish);
|
||||
if (init_reload_from_user_buf)
|
||||
{
|
||||
@@ -4813,7 +4840,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
state->Stb->select_start = state->ReloadSelectionStart;
|
||||
state->Stb->cursor = state->Stb->select_end = state->ReloadSelectionEnd; // will be clamped to bounds below
|
||||
}
|
||||
else if ((init_make_active && g.ActiveId != id) || init_changed_specs)
|
||||
else if ((init_make_active && g.ActiveId != id) || init_changed_specs_multiline || init_changed_specs_readonly)
|
||||
{
|
||||
// Access state even if we don't own it yet.
|
||||
state = &g.InputTextState;
|
||||
@@ -4834,8 +4861,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
|
||||
// Preserve cursor position and undo/redo stack if we come back to same widget
|
||||
// FIXME: Since we reworked this on 2022/06, may want to differentiate recycle_cursor vs recycle_undostate?
|
||||
bool recycle_state = (state->ID == id && !init_changed_specs);
|
||||
if (recycle_state && (state->TextLen != buf_len || (state->TextA.Data == NULL || strncmp(state->TextA.Data, buf, buf_len) != 0)))
|
||||
bool recycle_state = (state->ID == id && !init_changed_specs_multiline);
|
||||
if (recycle_state && !init_changed_specs_readonly && (state->TextLen != buf_len || (state->TextA.Data == NULL || strncmp(state->TextA.Data, buf, buf_len) != 0)))
|
||||
recycle_state = false;
|
||||
|
||||
// Start edition
|
||||
@@ -4873,7 +4900,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
}
|
||||
|
||||
const bool is_osx = io.ConfigMacOSXBehaviors;
|
||||
if (g.ActiveId != id && init_make_active)
|
||||
if (init_make_active && g.ActiveId != id)
|
||||
{
|
||||
IM_ASSERT(state && state->ID == id);
|
||||
SetActiveID(id, window);
|
||||
@@ -4944,13 +4971,17 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
if (is_password && !is_displaying_hint)
|
||||
PushPasswordFont();
|
||||
|
||||
// Word-wrapping: attempt to keep cursor in view while resizing frame/parent
|
||||
// FIXME-WORDWRAP: It would be better to preserve same relative offset.
|
||||
if (is_wordwrap && state != NULL && state->ID == id && state->WrapWidth != wrap_width)
|
||||
if (state != NULL && state->ID == id)
|
||||
{
|
||||
state->CursorCenterY = true;
|
||||
state->WrapWidth = wrap_width;
|
||||
render_cursor = true;
|
||||
state->Flags = flags;
|
||||
|
||||
// Word-wrapping: attempt to keep cursor in view while resizing frame/parent (FIXME-WORDWRAP: would be better to preserve same relative offset)
|
||||
if (is_wordwrap && state->WrapWidth != wrap_width)
|
||||
{
|
||||
state->CursorCenterY = true;
|
||||
state->WrapWidth = wrap_width;
|
||||
render_cursor = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Process mouse inputs and character inputs
|
||||
@@ -4959,7 +4990,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
IM_ASSERT(state != NULL);
|
||||
state->EditedThisFrame = false;
|
||||
state->BufCapacity = buf_size;
|
||||
state->Flags = flags;
|
||||
state->WrapWidth = wrap_width;
|
||||
|
||||
// Although we are active we don't prevent mouse from hovering other elements unless we are interacting right now with the widget.
|
||||
@@ -5611,7 +5641,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
ImVec2 cursor_screen_pos = ImTrunc(draw_pos + cursor_offset - draw_scroll);
|
||||
ImRect cursor_screen_rect(cursor_screen_pos.x, cursor_screen_pos.y - g.FontSize + 0.5f, cursor_screen_pos.x + 1.0f, cursor_screen_pos.y - 1.5f);
|
||||
if (cursor_is_visible && cursor_screen_rect.Overlaps(clip_rect))
|
||||
draw_window->DrawList->AddLine(cursor_screen_rect.Min, cursor_screen_rect.GetBL(), GetColorU32(ImGuiCol_InputTextCursor), 1.0f * (float)(int)style._MainScale); // FIXME-DPI: Cursor thickness (#7031)
|
||||
draw_window->DrawList->AddLineV(cursor_screen_rect.Min.x, cursor_screen_rect.Min.y, cursor_screen_rect.Max.y, GetColorU32(ImGuiCol_InputTextCursor), 1.0f * (float)(int)style._MainScale); // FIXME-DPI: Cursor thickness (#7031)
|
||||
|
||||
// Notify OS of text input position for advanced IME (-1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.)
|
||||
// This is required for some backends (SDL3) to start emitting character/text inputs.
|
||||
@@ -5659,7 +5689,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
}
|
||||
|
||||
if (label_size.x > 0)
|
||||
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
|
||||
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, label_end, false);
|
||||
|
||||
if (value_changed)
|
||||
MarkItemEdited(id);
|
||||
@@ -6325,7 +6355,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
|
||||
const float a1 = (n+1.0f)/6.0f * 2.0f * IM_PI + aeps;
|
||||
const int vert_start_idx = draw_list->VtxBuffer.Size;
|
||||
draw_list->PathArcTo(wheel_center, (wheel_r_inner + wheel_r_outer)*0.5f, a0, a1, segment_per_arc);
|
||||
draw_list->PathStroke(col_white, 0, wheel_thickness);
|
||||
draw_list->PathStroke(col_white, wheel_thickness);
|
||||
const int vert_end_idx = draw_list->VtxBuffer.Size;
|
||||
|
||||
// Paint colors over existing vertices
|
||||
@@ -6469,7 +6499,7 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl
|
||||
if (g.Style.FrameBorderSize > 0.0f)
|
||||
RenderFrameBorder(bb.Min, bb.Max, rounding);
|
||||
else
|
||||
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding, 0, 1.0f * (float)(int)g.Style._MainScale); // Color buttons are often in need of some sort of border // FIXME-DPI
|
||||
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding, 1.0f * (float)(int)g.Style._MainScale); // Color buttons are often in need of some sort of border // FIXME-DPI
|
||||
}
|
||||
|
||||
// Drag and Drop Source
|
||||
@@ -7142,11 +7172,11 @@ void ImGui::TreeNodeDrawLineToChildNode(const ImVec2& target_pos)
|
||||
window->DrawList->PathArcToFast(ImVec2(x1, y - rounding), rounding, 6, 3);
|
||||
if (x1 < x2)
|
||||
window->DrawList->PathLineTo(ImVec2(x2, y));
|
||||
window->DrawList->PathStroke(GetColorU32(ImGuiCol_TreeLines), ImDrawFlags_None, g.Style.TreeLinesSize);
|
||||
window->DrawList->PathStroke(GetColorU32(ImGuiCol_TreeLines), g.Style.TreeLinesSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
window->DrawList->AddLine(ImVec2(x1, y), ImVec2(x2, y), GetColorU32(ImGuiCol_TreeLines), g.Style.TreeLinesSize);
|
||||
window->DrawList->AddLineH(x1, x2, y, GetColorU32(ImGuiCol_TreeLines), g.Style.TreeLinesSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7172,7 +7202,7 @@ void ImGui::TreeNodeDrawLineToTreePop(const ImGuiTreeNodeStackData* data)
|
||||
float x = ImTrunc(data->DrawLinesX1);
|
||||
if (data->DrawLinesTableColumn != -1)
|
||||
TablePushColumnChannel(data->DrawLinesTableColumn);
|
||||
window->DrawList->AddLine(ImVec2(x, y1), ImVec2(x, y2), GetColorU32(ImGuiCol_TreeLines), g.Style.TreeLinesSize);
|
||||
window->DrawList->AddLineV(x, y1, y2, GetColorU32(ImGuiCol_TreeLines), g.Style.TreeLinesSize);
|
||||
if (data->DrawLinesTableColumn != -1)
|
||||
TablePopColumnChannel();
|
||||
}
|
||||
@@ -7331,7 +7361,8 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
|
||||
|
||||
// Submit label or explicit size to ItemSize(), whereas ItemAdd() will submit a larger/spanning rectangle.
|
||||
ImGuiID id = window->GetID(label);
|
||||
ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
ImVec2 label_size = CalcTextSize(label, label_end, false);
|
||||
ImVec2 size(size_arg.x != 0.0f ? size_arg.x : label_size.x, size_arg.y != 0.0f ? size_arg.y : label_size.y);
|
||||
ImVec2 pos = window->DC.CursorPos;
|
||||
pos.y += window->DC.CurrLineTextBaseOffset;
|
||||
@@ -7486,7 +7517,11 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
|
||||
|
||||
// Text stays at the submission position. Alignment/clipping extents ignore SpanAllColumns.
|
||||
if (is_visible)
|
||||
RenderTextClipped(pos, ImVec2(ImMin(pos.x + size.x, window->WorkRect.Max.x), pos.y + size.y), label, NULL, &label_size, style.SelectableTextAlign, &bb);
|
||||
RenderTextClipped(pos, ImVec2(ImMin(pos.x + size.x, window->WorkRect.Max.x), pos.y + size.y), label, label_end, &label_size, style.SelectableTextAlign, &bb);
|
||||
|
||||
#ifdef IMGUI_DEBUG_BOXSELECT
|
||||
if (g.BoxSelectState.UnclipMode) { GetForegroundDrawList()->AddText(pos, IM_COL32(255,255,0,200), label, label_end); }
|
||||
#endif
|
||||
|
||||
// Automatically close popups
|
||||
if (pressed && !auto_selected && (window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiSelectableFlags_NoAutoClosePopups) && (g.LastItemData.ItemFlags & ImGuiItemFlags_AutoClosePopups))
|
||||
@@ -7803,7 +7838,7 @@ bool ImGui::BeginBoxSelect(const ImRect& scope_rect, ImGuiWindow* window, ImGuiI
|
||||
return false;
|
||||
|
||||
// Current frame absolute prev/current rectangles are used to toggle selection.
|
||||
// They are derived from positions relative to scrolling space.
|
||||
// They are derived from positions relative to scrolling space, so "previous" rectangle is reprojected for current frame coordinates.
|
||||
ImVec2 start_pos_abs = WindowPosRelToAbs(window, bs->StartPosRel);
|
||||
ImVec2 prev_end_pos_abs = WindowPosRelToAbs(window, bs->EndPosRel); // Clamped already
|
||||
ImVec2 curr_end_pos_abs = g.IO.MousePos;
|
||||
@@ -7813,20 +7848,69 @@ bool ImGui::BeginBoxSelect(const ImRect& scope_rect, ImGuiWindow* window, ImGuiI
|
||||
bs->BoxSelectRectPrev.Max = ImMax(start_pos_abs, prev_end_pos_abs);
|
||||
bs->BoxSelectRectCurr.Min = ImMin(start_pos_abs, curr_end_pos_abs);
|
||||
bs->BoxSelectRectCurr.Max = ImMax(start_pos_abs, curr_end_pos_abs);
|
||||
//IMGUI_DEBUG_LOG("StartPosRel (%.2f,%.2f) EndPosRel (%.2f,%.2f) -> (%.2f,%.2f)\n", bs->StartPosRel.x, bs->StartPosRel.y, bs->EndPosRel.x, bs->EndPosRel.y, WindowPosAbsToRel(window, g.IO.MousePos).x, WindowPosAbsToRel(window, g.IO.MousePos).y);
|
||||
|
||||
// Box-select 2D mode detects horizontal changes (vertical ones are already picked by Clipper)
|
||||
// Storing an extra rect used by widgets supporting box-select.
|
||||
if (ms_flags & ImGuiMultiSelectFlags_BoxSelect2d)
|
||||
if (bs->BoxSelectRectPrev.Min.x != bs->BoxSelectRectCurr.Min.x || bs->BoxSelectRectPrev.Max.x != bs->BoxSelectRectCurr.Max.x)
|
||||
// Box-select 2D mode detects change of the rectangle.
|
||||
// Storing unclip rects which will be tested by widgets supporting box-select. Always update rectangles when active (even if we don't use them).
|
||||
// To facilitate understanding this: enable IMGUI_DEBUG_BOXSELECT and visualize all geometry.
|
||||
if (ms_flags & (ImGuiMultiSelectFlags_BoxSelect1d | ImGuiMultiSelectFlags_BoxSelect2d))
|
||||
{
|
||||
// For both sides, compute the area differing between Prev and Curr rectangles.
|
||||
bs->UnclipRects[0] = bs->UnclipRects[1] = ImRect(+FLT_MAX, +FLT_MAX, -FLT_MAX, -FLT_MAX);
|
||||
for (int side = 0; side < 2; side++)
|
||||
{
|
||||
bs->UnclipMode = true;
|
||||
bs->UnclipRect = bs->BoxSelectRectPrev; // FIXME-OPT: UnclipRect x coordinates could be intersection of Prev and Curr rect on X axis.
|
||||
bs->UnclipRect.Add(bs->BoxSelectRectCurr);
|
||||
ImVec2 d_min = (side == 0) ? ImMin(bs->BoxSelectRectCurr.Min, bs->BoxSelectRectPrev.Min) : ImMin(bs->BoxSelectRectCurr.Max, bs->BoxSelectRectPrev.Max);
|
||||
ImVec2 d_max = (side == 0) ? ImMax(bs->BoxSelectRectCurr.Min, bs->BoxSelectRectPrev.Min) : ImMax(bs->BoxSelectRectCurr.Max, bs->BoxSelectRectPrev.Max);
|
||||
if (d_min.x != d_max.x)
|
||||
{
|
||||
bs->UnclipRects[0].AddX(d_min.x);
|
||||
bs->UnclipRects[0].AddX(d_max.x);
|
||||
}
|
||||
if (d_min.y != d_max.y)
|
||||
{
|
||||
bs->UnclipRects[1].AddY(d_min.y);
|
||||
bs->UnclipRects[1].AddY(d_max.y);
|
||||
}
|
||||
}
|
||||
|
||||
//GetForegroundDrawList()->AddRect(bs->UnclipRect.Min, bs->UnclipRect.Max, IM_COL32(255,0,0,200), 0.0f, 0, 3.0f);
|
||||
ImRect box_select_intersection = bs->BoxSelectRectPrev;
|
||||
box_select_intersection.Add(bs->BoxSelectRectCurr);
|
||||
if (ms_flags & ImGuiMultiSelectFlags_BoxSelect2d)
|
||||
if (bs->BoxSelectRectPrev.Min.x != bs->BoxSelectRectCurr.Min.x || bs->BoxSelectRectPrev.Max.x != bs->BoxSelectRectCurr.Max.x)
|
||||
{
|
||||
bs->UnclipRects[0].AddY(box_select_intersection.Min.y);
|
||||
bs->UnclipRects[0].AddY(box_select_intersection.Max.y);
|
||||
}
|
||||
if (ms_flags & (ImGuiMultiSelectFlags_BoxSelect1d | ImGuiMultiSelectFlags_BoxSelect2d))
|
||||
if (bs->BoxSelectRectPrev.Min.y != bs->BoxSelectRectCurr.Min.y || bs->BoxSelectRectPrev.Max.y != bs->BoxSelectRectCurr.Max.y)
|
||||
{
|
||||
bs->UnclipRects[1].AddX(box_select_intersection.Min.x);
|
||||
bs->UnclipRects[1].AddX(box_select_intersection.Max.x);
|
||||
}
|
||||
|
||||
// Merge both rectangles into one.
|
||||
// FIXME-OPT: When UnclipRect.Area() is much larger than the sum of UnclipRects[0]/[1] Areas, widgets should
|
||||
// ideally first use UnclipRect as a first coarse cull layer + the individual ones as a second validation.
|
||||
bs->UnclipRect = bs->UnclipRects[0];
|
||||
bs->UnclipRect.Add(bs->UnclipRects[1]);
|
||||
if (!bs->UnclipRect.IsInverted() && (!window->ClipRect.Contains(bs->UnclipRect.Min) || !window->ClipRect.Contains(bs->UnclipRect.Max))) // !! Don't use Contains(ImRect)
|
||||
bs->UnclipMode = true;
|
||||
if (bs->UnclipMode && g.CurrentTable != NULL)
|
||||
TableApplyExternalUnclipRect(g.CurrentTable, bs->UnclipRect); // No need submitting both
|
||||
}
|
||||
|
||||
#ifdef IMGUI_DEBUG_BOXSELECT
|
||||
//GetForegroundDrawList()->AddRect(scope_rect.Min, scope_rect.Max, IM_COL32(0, 255, 0, 200), 0.0f, 0, 4.0f);
|
||||
//GetForegroundDrawList()->AddRect(bs->BoxSelectRectPrev.Min, bs->BoxSelectRectPrev.Max, IM_COL32(255,0,0,200), 0.0f, 0, 3.0f);
|
||||
//GetForegroundDrawList()->AddRect(bs->BoxSelectRectCurr.Min, bs->BoxSelectRectCurr.Max, IM_COL32(0,255,0,200), 0.0f, 0, 1.0f);
|
||||
if (ms_flags & (ImGuiMultiSelectFlags_BoxSelect1d | ImGuiMultiSelectFlags_BoxSelect2d))
|
||||
{
|
||||
for (ImRect& unclip_r : bs->UnclipRects)
|
||||
if (!unclip_r.IsInverted())
|
||||
GetForegroundDrawList()->AddRect(unclip_r.Min, unclip_r.Max, bs->UnclipMode ? IM_COL32(255, 255, 0, 200) : IM_COL32(255, 0, 0, 200), 0.0f, 0, 4.0f);
|
||||
GetForegroundDrawList()->AddRect(bs->UnclipRect.Min, bs->UnclipRect.Max, bs->UnclipMode ? IM_COL32(255, 255, 0, 200) : IM_COL32(255, 0, 0, 200), 0.0f, 0, 2.0f);
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -7842,8 +7926,9 @@ void ImGui::EndBoxSelect(const ImRect& scope_rect, ImGuiMultiSelectFlags ms_flag
|
||||
bs->EndPosRel = WindowPosAbsToRel(window, ImClamp(g.IO.MousePos, scope_rect.Min, scope_rect.Max)); // Clamp stored position according to current scrolling view
|
||||
ImRect box_select_r = bs->BoxSelectRectCurr;
|
||||
box_select_r.ClipWith(scope_rect);
|
||||
window->DrawList->AddRectFilled(box_select_r.Min, box_select_r.Max, GetColorU32(ImGuiCol_SeparatorHovered, 0.30f)); // FIXME-MULTISELECT: Styling
|
||||
window->DrawList->AddRect(box_select_r.Min, box_select_r.Max, GetColorU32(ImGuiCol_NavCursor)); // FIXME-MULTISELECT FIXME-DPI: Styling
|
||||
ImGuiWindow* draw_window = FindFrontMostVisibleChildWindow(window);
|
||||
draw_window->DrawList->AddRectFilled(box_select_r.Min, box_select_r.Max, GetColorU32(ImGuiCol_SeparatorHovered, 0.30f)); // FIXME-MULTISELECT: Styling
|
||||
draw_window->DrawList->AddRect(box_select_r.Min, box_select_r.Max, GetColorU32(ImGuiCol_NavCursor)); // FIXME-MULTISELECT FIXME-DPI: Styling
|
||||
|
||||
// Scroll
|
||||
const bool enable_scroll = (ms_flags & ImGuiMultiSelectFlags_ScopeWindow) && (ms_flags & ImGuiMultiSelectFlags_BoxSelectNoScroll) == 0;
|
||||
@@ -7883,18 +7968,18 @@ static void DebugLogMultiSelectRequests(const char* function, const ImGuiMultiSe
|
||||
|
||||
static ImRect CalcScopeRect(ImGuiMultiSelectTempData* ms, ImGuiWindow* window)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (ms->Flags & ImGuiMultiSelectFlags_ScopeRect)
|
||||
{
|
||||
// Warning: this depends on CursorMaxPos so it means to be called by EndMultiSelect() only
|
||||
// This probably doesn't work inside a table as there are ample ambiguities related to exact time of calling BeginMultiSelect()/EndMultiSelect().
|
||||
return ImRect(ms->ScopeRectMin, ImMax(window->DC.CursorMaxPos, ms->ScopeRectMin));
|
||||
}
|
||||
else
|
||||
{
|
||||
// When a table, pull HostClipRect, which allows us to predict ClipRect before first row/layout is performed. (#7970)
|
||||
//// When a table, pull HostClipRect, which allows us to predict ClipRect before first row/layout is performed. (#7970)
|
||||
ImRect scope_rect = window->InnerClipRect;
|
||||
if (g.CurrentTable != NULL)
|
||||
scope_rect = g.CurrentTable->HostClipRect;
|
||||
//if (g.CurrentTable != NULL)
|
||||
// scope_rect = g.CurrentTable->HostClipRect;
|
||||
|
||||
// Add inner table decoration (#7821) // FIXME: Why not baking in InnerClipRect?
|
||||
scope_rect.Min = ImMin(scope_rect.Min + ImVec2(window->DecoInnerSizeX1, window->DecoInnerSizeY1), scope_rect.Max);
|
||||
@@ -7930,18 +8015,24 @@ ImGuiMultiSelectIO* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags, int sel
|
||||
// FIXME: Workaround to the fact we override CursorMaxPos, meaning size measurement are lost. (#8250)
|
||||
// They should perhaps be stacked properly?
|
||||
if (ImGuiTable* table = g.CurrentTable)
|
||||
if (table->CurrentColumn != -1)
|
||||
{
|
||||
if (!table->IsLayoutLocked)
|
||||
TableUpdateLayout(table);
|
||||
else if (table->CurrentColumn != -1)
|
||||
TableEndCell(table); // This is currently safe to call multiple time. If that properly is lost we can extract the "save measurement" part of it.
|
||||
}
|
||||
|
||||
// FIXME: BeginFocusScope()
|
||||
const ImGuiID id = window->IDStack.back();
|
||||
ms->Clear();
|
||||
ms->FocusScopeId = id;
|
||||
ms->Flags = flags;
|
||||
ms->IsFocused = (ms->FocusScopeId == g.NavFocusScopeId);
|
||||
ms->BackupCursorMaxPos = window->DC.CursorMaxPos;
|
||||
ms->ScopeRectMin = window->DC.CursorMaxPos = window->DC.CursorPos;
|
||||
ms->ScopeRectMin = window->DC.CursorPos;
|
||||
if (flags & ImGuiMultiSelectFlags_ScopeRect)
|
||||
window->DC.CursorMaxPos = ms->ScopeRectMin; // CalcScopeRect() for ImGuiMultiSelectFlags_ScopeRect will measure in EndMultiSelect().
|
||||
PushFocusScope(ms->FocusScopeId);
|
||||
ms->IsFocused = IsInNavFocusRoute(g.CurrentFocusScopeId);
|
||||
if (flags & ImGuiMultiSelectFlags_ScopeWindow) // Mark parent child window as navigable into, with highlight. Assume user will always submit interactive items.
|
||||
window->DC.NavLayersActiveMask |= 1 << ImGuiNavLayer_Main;
|
||||
|
||||
@@ -8023,7 +8114,7 @@ ImGuiMultiSelectIO* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags, int sel
|
||||
storage->LastSelectionSize = 0;
|
||||
}
|
||||
ms->LoopRequestSetAll = request_select_all ? 1 : request_clear ? 0 : -1;
|
||||
ms->LastSubmittedItem = ImGuiSelectionUserData_Invalid;
|
||||
//ms->PrevSubmittedItem = ImGuiSelectionUserData_Invalid;
|
||||
|
||||
if (g.DebugLogFlags & ImGuiDebugLogFlags_EventSelection)
|
||||
DebugLogMultiSelectRequests("BeginMultiSelect", &ms->IO);
|
||||
@@ -8069,7 +8160,7 @@ ImGuiMultiSelectIO* ImGui::EndMultiSelect()
|
||||
// Clear selection when clicking void?
|
||||
// We specifically test for IsMouseDragPastThreshold(0) == false to allow box-selection!
|
||||
// The InnerRect test is necessary for non-child/decorated windows.
|
||||
bool scope_hovered = IsWindowHovered() && window->InnerRect.Contains(g.IO.MousePos);
|
||||
bool scope_hovered = window->InnerRect.Contains(g.IO.MousePos) && IsWindowHovered(ImGuiHoveredFlags_ChildWindows);
|
||||
if (scope_hovered && (ms->Flags & ImGuiMultiSelectFlags_ScopeRect))
|
||||
scope_hovered &= scope_rect.Contains(g.IO.MousePos);
|
||||
if (scope_hovered && g.HoveredId == 0 && g.ActiveId == 0)
|
||||
@@ -8095,10 +8186,13 @@ ImGuiMultiSelectIO* ImGui::EndMultiSelect()
|
||||
if (ms->Flags & ImGuiMultiSelectFlags_NavWrapX)
|
||||
{
|
||||
IM_ASSERT(ms->Flags & ImGuiMultiSelectFlags_ScopeWindow); // Only supported at window scope
|
||||
ImGui::NavMoveRequestTryWrapping(ImGui::GetCurrentWindow(), ImGuiNavMoveFlags_WrapX);
|
||||
NavMoveRequestTryWrapping(GetCurrentWindow(), ImGuiNavMoveFlags_WrapX);
|
||||
}
|
||||
|
||||
// Unwind
|
||||
if (ImGuiTable* table = g.CurrentTable)
|
||||
if (table->IsInsideRow)
|
||||
TableEndRow(table);
|
||||
window->DC.CursorMaxPos = ImMax(ms->BackupCursorMaxPos, window->DC.CursorMaxPos);
|
||||
PopFocusScope();
|
||||
|
||||
@@ -8126,6 +8220,8 @@ void ImGui::SetNextItemSelectionUserData(ImGuiSelectionUserData selection_user_d
|
||||
g.NextItemData.ItemFlags |= ImGuiItemFlags_HasSelectionUserData | ImGuiItemFlags_IsMultiSelect;
|
||||
if (ms->IO.RangeSrcItem == selection_user_data)
|
||||
ms->RangeSrcPassedBy = true;
|
||||
//ms->PrevSubmittedItem = ms->CurrSubmittedItem; // Can't rely on previous g.NextItemData.SelectionUserData because NextItemData is not restored on nested multi-select.
|
||||
//ms->CurrSubmittedItem = selection_user_data;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -8274,8 +8370,31 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed)
|
||||
if (ms->BoxSelectId != 0)
|
||||
if (ImGuiBoxSelectState* bs = GetBoxSelectState(ms->BoxSelectId))
|
||||
{
|
||||
const bool rect_overlap_curr = bs->BoxSelectRectCurr.Overlaps(g.LastItemData.Rect);
|
||||
const bool rect_overlap_prev = bs->BoxSelectRectPrev.Overlaps(g.LastItemData.Rect);
|
||||
ImRect item_rect = g.LastItemData.Rect;
|
||||
if (!window->DC.NavIsScrollPushableX) // FIXME: Rename to be more generic.
|
||||
if (ImGuiTable* table = g.CurrentTable)
|
||||
if (table->CurrentColumn != -1)
|
||||
{
|
||||
// FIXME: We cannot solely use current ClipRect as it includes HostClipRect.
|
||||
// However we account for ClipRect being larger than current column (e.g. when using SpanAllColumns)
|
||||
// A more generic version would be nice, but window->WorkRect.Min/Max exclude CellPadding. (#7994, #9383)
|
||||
ImGuiTableColumn* column = &table->Columns[table->CurrentColumn];
|
||||
float clip_min_x = (g.LastItemData.ItemFlags & ImGuiItemStatusFlags_HasClipRect) ? g.LastItemData.ClipRect.Min.x : window->ClipRect.Min.x;
|
||||
float clip_max_x = (g.LastItemData.ItemFlags & ImGuiItemStatusFlags_HasClipRect) ? g.LastItemData.ClipRect.Max.x : window->ClipRect.Max.x;
|
||||
if (clip_min_x != clip_max_x) // When zero sized we expect that bounds have been clamped and thus are unreliable
|
||||
{
|
||||
item_rect.Min.x = ImMax(item_rect.Min.x, ImMin(column->MinX, clip_min_x));
|
||||
item_rect.Max.x = ImMin(item_rect.Max.x, ImMax(column->MaxX, clip_max_x));
|
||||
}
|
||||
else
|
||||
{
|
||||
item_rect.Min.x = ImMax(item_rect.Min.x, column->MinX);
|
||||
item_rect.Max.x = ImMin(item_rect.Max.x, column->MaxX);
|
||||
}
|
||||
//GetForegroundDrawList()->AddRect(item_rect.Min, item_rect.Max, IM_COL32(255, 0, 255, 255));
|
||||
}
|
||||
const bool rect_overlap_curr = bs->BoxSelectRectCurr.Overlaps(item_rect);
|
||||
const bool rect_overlap_prev = bs->BoxSelectRectPrev.Overlaps(item_rect);
|
||||
if ((rect_overlap_curr && !rect_overlap_prev && !selected) || (rect_overlap_prev && !rect_overlap_curr))
|
||||
{
|
||||
if (storage->LastSelectionSize <= 0 && bs->IsStartedSetNavIdOnce)
|
||||
@@ -8287,6 +8406,9 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed)
|
||||
{
|
||||
selected = !selected;
|
||||
MultiSelectAddSetRange(ms, selected, +1, item_data, item_data);
|
||||
#ifdef IMGUI_DEBUG_BOXSELECT
|
||||
GetForegroundDrawList()->AddRectFilled(g.LastItemData.Rect.Min, g.LastItemData.Rect.Max, selected ? IM_COL32(0, 255, 0, 200) : IM_COL32(255, 0, 0, 200));
|
||||
#endif
|
||||
}
|
||||
storage->LastSelectionSize = ImMax(storage->LastSelectionSize + 1, 1);
|
||||
}
|
||||
@@ -8400,7 +8522,6 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed)
|
||||
}
|
||||
if (storage->NavIdItem == item_data)
|
||||
ms->NavIdPassedBy = true;
|
||||
ms->LastSubmittedItem = item_data;
|
||||
|
||||
*p_selected = selected;
|
||||
*p_pressed = pressed;
|
||||
@@ -8416,15 +8537,20 @@ void ImGui::MultiSelectAddSetAll(ImGuiMultiSelectTempData* ms, bool selected)
|
||||
void ImGui::MultiSelectAddSetRange(ImGuiMultiSelectTempData* ms, bool selected, int range_dir, ImGuiSelectionUserData first_item, ImGuiSelectionUserData last_item)
|
||||
{
|
||||
// Merge contiguous spans into same request (unless NoRangeSelect is set which guarantees single-item ranges)
|
||||
// FIXME-OPT: Disabled on 2026/04/09 as this would break with any form of coarse clipping that we don't know about (e.g. TableNextColumn() return value).
|
||||
// The low-hanging fruit would be to know that ImGuiSelectionUserData are sequential indices, in which case we can trivially compare PrevSubmittedItem + RangeDir == FirstItem.
|
||||
// User can always perform this merge if required.
|
||||
#if 0
|
||||
if (ms->IO.Requests.Size > 0 && first_item == last_item && (ms->Flags & ImGuiMultiSelectFlags_NoRangeSelect) == 0)
|
||||
{
|
||||
ImGuiSelectionRequest* prev = &ms->IO.Requests.Data[ms->IO.Requests.Size - 1];
|
||||
if (prev->Type == ImGuiSelectionRequestType_SetRange && prev->RangeLastItem == ms->LastSubmittedItem && prev->Selected == selected)
|
||||
if (prev->Type == ImGuiSelectionRequestType_SetRange && prev->RangeLastItem == ms->PrevSubmittedItem && prev->Selected == selected)
|
||||
{
|
||||
prev->RangeLastItem = last_item;
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
ImGuiSelectionRequest req = { ImGuiSelectionRequestType_SetRange, selected, (ImS8)range_dir, (range_dir > 0) ? first_item : last_item, (range_dir > 0) ? last_item : first_item };
|
||||
ms->IO.Requests.push_back(req); // Add new request
|
||||
@@ -8662,7 +8788,8 @@ bool ImGui::BeginListBox(const char* label, const ImVec2& size_arg)
|
||||
|
||||
const ImGuiStyle& style = g.Style;
|
||||
const ImGuiID id = GetID(label);
|
||||
const ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
const ImVec2 label_size = CalcTextSize(label, label_end, false);
|
||||
|
||||
// Size default to hold ~7.25 items.
|
||||
// Fractional number of items helps seeing that we can scroll down/up without looking at scrollbar.
|
||||
@@ -8685,7 +8812,7 @@ bool ImGui::BeginListBox(const char* label, const ImVec2& size_arg)
|
||||
if (label_size.x > 0.0f)
|
||||
{
|
||||
ImVec2 label_pos = ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y);
|
||||
RenderText(label_pos, label);
|
||||
RenderText(label_pos, label, label_end, false);
|
||||
window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, label_pos + label_size);
|
||||
AlignTextToFramePadding();
|
||||
}
|
||||
@@ -8766,9 +8893,7 @@ bool ImGui::ListBox(const char* label, int* current_item, const char* (*getter)(
|
||||
// - PlotHistogram()
|
||||
//-------------------------------------------------------------------------
|
||||
// Plot/Graph widgets are not very good.
|
||||
// Consider writing your own, or using a third-party one, see:
|
||||
// - ImPlot https://github.com/epezent/implot
|
||||
// - others https://github.com/ocornut/imgui/wiki/Useful-Extensions
|
||||
// Consider using ImPlot (https://github.com/epezent/implot) which is much better!
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
int ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, const ImVec2& size_arg)
|
||||
@@ -8781,7 +8906,8 @@ int ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_get
|
||||
const ImGuiStyle& style = g.Style;
|
||||
const ImGuiID id = window->GetID(label);
|
||||
|
||||
const ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
const ImVec2 label_size = CalcTextSize(label, label_end, false);
|
||||
const ImVec2 frame_size = CalcItemSize(size_arg, CalcItemWidth(), label_size.y + style.FramePadding.y * 2.0f);
|
||||
|
||||
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size);
|
||||
@@ -8880,10 +9006,11 @@ int ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_get
|
||||
RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, overlay_text, NULL, NULL, ImVec2(0.5f, 0.0f));
|
||||
|
||||
if (label_size.x > 0.0f)
|
||||
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, inner_bb.Min.y), label);
|
||||
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, inner_bb.Min.y), label, label_end, false);
|
||||
|
||||
// Return hovered index or -1 if none are hovered.
|
||||
// This is currently not exposed in the public API because we need a larger redesign of the whole thing, but in the short-term we are making it available in PlotEx().
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
|
||||
return idx_hovered;
|
||||
}
|
||||
|
||||
@@ -8913,6 +9040,7 @@ void ImGui::PlotLines(const char* label, float (*values_getter)(void* data, int
|
||||
PlotEx(ImGuiPlotType_Lines, label, values_getter, data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size);
|
||||
}
|
||||
|
||||
// Plot Histogram (the data provided _is_ histogram data. it doesn't compute the histogram of your data)
|
||||
void ImGui::PlotHistogram(const char* label, const float* values, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size, int stride)
|
||||
{
|
||||
ImGuiPlotArrayGetterData data(values, stride);
|
||||
@@ -9245,7 +9373,8 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
|
||||
// Tag menu as used. Next time BeginMenu() with same ID is called it will append to existing menu
|
||||
g.MenusIdSubmittedThisFrame.push_back(id);
|
||||
|
||||
ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
ImVec2 label_size = CalcTextSize(label, label_end, false);
|
||||
|
||||
// Odd hack to allow hovering across menus of a same menu-set (otherwise we wouldn't be able to hover parent without always being a Child window)
|
||||
// This is only done for items for the menu set and not the full parent window.
|
||||
@@ -9264,8 +9393,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
|
||||
|
||||
bool pressed;
|
||||
|
||||
// We use ImGuiSelectableFlags_NoSetKeyOwner to allow down on one menu item, move, up on another.
|
||||
const ImGuiSelectableFlags selectable_flags = ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_NoSetKeyOwner | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_NoAutoClosePopups;
|
||||
const ImGuiSelectableFlags selectable_flags = ImGuiSelectableFlags_NoAutoClosePopups | (ImGuiSelectableFlags)ImGuiSelectableFlags_SelectOnClick;
|
||||
ImGuiMenuColumns* offsets = &window->DC.MenuColumns;
|
||||
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
|
||||
{
|
||||
@@ -9277,7 +9405,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
|
||||
ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, pos.y + window->DC.CurrLineTextBaseOffset);
|
||||
pressed = Selectable("", menu_is_open, selectable_flags, label_size);
|
||||
LogSetNextTextDecoration("[", "]");
|
||||
RenderText(text_pos, label);
|
||||
RenderText(text_pos, label, label_end, false);
|
||||
PopStyleVar();
|
||||
window->DC.CursorPos.x += IM_TRUNC(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar().
|
||||
popup_pos = ImVec2(pos.x - 1.0f - IM_TRUNC(style.ItemSpacing.x * 0.5f), text_pos.y - style.FramePadding.y + window->MenuBarHeight);
|
||||
@@ -9294,7 +9422,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
|
||||
ImVec2 text_pos(window->DC.CursorPos.x, pos.y + window->DC.CurrLineTextBaseOffset);
|
||||
pressed = Selectable("", menu_is_open, selectable_flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, label_size.y));
|
||||
LogSetNextTextDecoration("", ">");
|
||||
RenderText(ImVec2(text_pos.x + offsets->OffsetLabel, text_pos.y), label);
|
||||
RenderText(ImVec2(text_pos.x + offsets->OffsetLabel, text_pos.y), label, label_end, false);
|
||||
if (icon_w > 0.0f)
|
||||
RenderText(ImVec2(text_pos.x + offsets->OffsetIcon, text_pos.y), icon);
|
||||
RenderArrow(window->DrawList, ImVec2(text_pos.x + offsets->OffsetMark + extra_w + g.FontSize * 0.30f, text_pos.y), GetColorU32(ImGuiCol_Text), ImGuiDir_Right);
|
||||
@@ -9303,6 +9431,14 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
|
||||
if (!enabled)
|
||||
EndDisabled();
|
||||
|
||||
// Once dragged, release ActiveId + key ownership. This is to allow the idiom of mouse down a menu, dragging elsewhere, up on some other MenuItem(). (#8233, #9394)
|
||||
// Could move logic into lower-level ImGuiButtonFlags_AutoReleaseActiveId + ImGuiButtonFlags_AutoReleaseKeyOwner? Easier once we get rid of the Selectable() middle-man here.
|
||||
if (g.ActiveId == id && g.HoveredId != id && g.ActiveIdSource == ImGuiInputSource_Mouse && IsMouseDragging(0))
|
||||
{
|
||||
ClearActiveID();
|
||||
SetKeyOwner(ImGuiKey_MouseLeft, ImGuiKeyOwner_NoOwner);
|
||||
}
|
||||
|
||||
const bool hovered = (g.HoveredId == id) && enabled && !g.NavHighlightItemUnderNav;
|
||||
if (menuset_is_open)
|
||||
PopItemFlag();
|
||||
@@ -9383,6 +9519,9 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Openable | (menu_is_open ? ImGuiItemStatusFlags_Opened : 0));
|
||||
PopID();
|
||||
|
||||
if (g.ActiveId == id && want_open)
|
||||
g.ActiveIdNoClearOnFocusLoss = true;
|
||||
|
||||
if (want_open && !menu_is_open && g.OpenPopupStack.Size > g.BeginPopupStack.Size)
|
||||
{
|
||||
// Don't reopen/recycle same menu level in the same frame if it is a different menu ID, first close the other menu and yield for a frame.
|
||||
@@ -9459,7 +9598,8 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiStyle& style = g.Style;
|
||||
ImVec2 pos = window->DC.CursorPos;
|
||||
ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
ImVec2 label_size = CalcTextSize(label, label_end, false);
|
||||
|
||||
// See BeginMenuEx() for comments about this.
|
||||
const bool menuset_is_open = IsRootOfOpenMenuSet();
|
||||
@@ -9474,7 +9614,7 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
|
||||
BeginDisabled();
|
||||
|
||||
// We use ImGuiSelectableFlags_NoSetKeyOwner to allow down on one menu item, move, up on another.
|
||||
const ImGuiSelectableFlags selectable_flags = ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_SelectOnRelease | ImGuiSelectableFlags_NoSetKeyOwner | ImGuiSelectableFlags_SetNavIdOnHover;
|
||||
const ImGuiSelectableFlags selectable_flags = (ImGuiSelectableFlags)ImGuiSelectableFlags_SelectOnRelease | (ImGuiSelectableFlags)ImGuiSelectableFlags_SetNavIdOnHover;
|
||||
ImGuiMenuColumns* offsets = &window->DC.MenuColumns;
|
||||
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
|
||||
{
|
||||
@@ -9486,7 +9626,7 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
|
||||
pressed = Selectable("", selected, selectable_flags, ImVec2(label_size.x, 0.0f));
|
||||
PopStyleVar();
|
||||
if (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Visible)
|
||||
RenderText(text_pos, label);
|
||||
RenderText(text_pos, label, label_end, false);
|
||||
window->DC.CursorPos.x += IM_TRUNC(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar().
|
||||
}
|
||||
else
|
||||
@@ -9503,7 +9643,7 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
|
||||
pressed = Selectable("", false, selectable_flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, label_size.y));
|
||||
if (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Visible)
|
||||
{
|
||||
RenderText(text_pos + ImVec2(offsets->OffsetLabel, 0.0f), label);
|
||||
RenderText(text_pos + ImVec2(offsets->OffsetLabel, 0.0f), label, label_end, false);
|
||||
if (icon_w > 0.0f)
|
||||
RenderText(text_pos + ImVec2(offsets->OffsetIcon, 0.0f), icon);
|
||||
if (shortcut_w > 0.0f)
|
||||
@@ -9517,6 +9657,17 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
|
||||
RenderCheckMark(window->DrawList, text_pos + ImVec2(offsets->OffsetMark + stretch_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), GetColorU32(ImGuiCol_Text), g.FontSize * 0.866f);
|
||||
}
|
||||
}
|
||||
|
||||
// Once dragged, release ActiveId + key ownership. This is to allow the idiom of mouse down a menu, dragging elsewhere, up on some other MenuItem(). (#8233, #9394)
|
||||
// Could move logic into lower-level ImGuiButtonFlags_AutoReleaseActiveId + ImGuiButtonFlags_AutoReleaseKeyOwner? Easier once we get rid of the Selectable() middle-man here.
|
||||
const ImGuiID id = g.LastItemData.ID;
|
||||
if (g.ActiveId == id && g.HoveredId != id && g.ActiveIdSource == ImGuiInputSource_Mouse && IsMouseDragging(0))
|
||||
{
|
||||
ClearActiveID();
|
||||
SetKeyOwner(ImGuiKey_MouseLeft, ImGuiKeyOwner_NoOwner);
|
||||
}
|
||||
|
||||
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(g.LastItemData.ID, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (selected ? ImGuiItemStatusFlags_Checked : 0));
|
||||
if (!enabled)
|
||||
EndDisabled();
|
||||
@@ -10557,7 +10708,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
|
||||
// We don't have CPU clipping primitives to clip the CloseButton (until it becomes a texture), so need to add an extra draw call (temporary in the case of vertical animation)
|
||||
const bool want_clip_rect = is_central_section && (bb.Min.x < tab_bar->ScrollingRectMinX || bb.Max.x > tab_bar->ScrollingRectMaxX);
|
||||
if (want_clip_rect)
|
||||
PushClipRect(ImVec2(ImMax(bb.Min.x, tab_bar->ScrollingRectMinX), bb.Min.y - 1), ImVec2(tab_bar->ScrollingRectMaxX, bb.Max.y), true);
|
||||
PushClipRect(ImVec2(ImClamp(bb.Min.x, tab_bar->ScrollingRectMinX, tab_bar->ScrollingRectMaxX), bb.Min.y - 1), ImVec2(tab_bar->ScrollingRectMaxX, bb.Max.y), true);
|
||||
|
||||
ImVec2 backup_cursor_max_pos = window->DC.CursorMaxPos;
|
||||
ItemSize(bb.GetSize(), style.FramePadding.y);
|
||||
@@ -10629,7 +10780,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
|
||||
float rounding = style.TabRounding;
|
||||
display_draw_list->PathArcToFast(tl + ImVec2(+rounding, +rounding), rounding, 7, 9);
|
||||
display_draw_list->PathArcToFast(tr + ImVec2(-rounding, +rounding), rounding, 9, 11);
|
||||
display_draw_list->PathStroke(overline_col, 0, style.TabBarOverlineSize);
|
||||
display_draw_list->PathStroke(overline_col, style.TabBarOverlineSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -10733,7 +10884,7 @@ void ImGui::TabItemBackground(ImDrawList* draw_list, const ImRect& bb, ImGuiTabI
|
||||
draw_list->PathArcToFast(ImVec2(bb.Min.x + rounding + 0.5f, y1 + rounding + 0.5f), rounding, 6, 9);
|
||||
draw_list->PathArcToFast(ImVec2(bb.Max.x - rounding - 0.5f, y1 + rounding + 0.5f), rounding, 9, 12);
|
||||
draw_list->PathLineTo(ImVec2(bb.Max.x - 0.5f, y2));
|
||||
draw_list->PathStroke(GetColorU32(ImGuiCol_Border), 0, g.Style.TabBorderSize);
|
||||
draw_list->PathStroke(GetColorU32(ImGuiCol_Border), g.Style.TabBorderSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10742,7 +10893,8 @@ void ImGui::TabItemBackground(ImDrawList* draw_list, const ImRect& bb, ImGuiTabI
|
||||
void ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, ImVec2 frame_padding, const char* label, ImGuiID tab_id, ImGuiID close_button_id, bool is_contents_visible, bool* out_just_closed, bool* out_text_clipped)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
ImVec2 label_size = CalcTextSize(label, label_end, false);
|
||||
|
||||
if (out_just_closed)
|
||||
*out_just_closed = false;
|
||||
@@ -10827,7 +10979,7 @@ void ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb,
|
||||
}
|
||||
}
|
||||
LogSetNextTextDecoration("/", "\\");
|
||||
RenderTextEllipsis(draw_list, text_ellipsis_clip_bb.Min, text_ellipsis_clip_bb.Max, ellipsis_max_x, label, NULL, &label_size);
|
||||
RenderTextEllipsis(draw_list, text_ellipsis_clip_bb.Min, text_ellipsis_clip_bb.Max, ellipsis_max_x, label, label_end, &label_size);
|
||||
|
||||
#if 0
|
||||
if (!is_contents_visible)
|
||||
|
||||
Vendored
+4
-3
@@ -1,12 +1,13 @@
|
||||
Copyright 2015-2023 The Khronos Group Inc.
|
||||
Copyright 2015-2026 The Khronos Group Inc.
|
||||
|
||||
Files in this repository fall under one of these licenses:
|
||||
|
||||
- `Apache-2.0`
|
||||
- `MIT`
|
||||
|
||||
Note: With the exception of `parse_dependency.py` the files using `MIT` license
|
||||
also fall under `Apache-2.0`. Example:
|
||||
Note: With the exception of `parse_dependency.py`, which is based on an
|
||||
external file, files using the `MIT` license also fall under `Apache-2.0`.
|
||||
Example:
|
||||
|
||||
```
|
||||
SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
** SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
** SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
** SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
** SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
** SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
** SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
** SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
** SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
** SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
** SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
** SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
** SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
+1
-2
@@ -2,8 +2,7 @@
|
||||
* Copyright 2015-2023 The Khronos Group Inc.
|
||||
* Copyright 2015-2023 Valve Corporation
|
||||
* Copyright 2015-2023 LunarG, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
||||
+1
-2
@@ -2,8 +2,7 @@
|
||||
* Copyright 2015-2023 The Khronos Group Inc.
|
||||
* Copyright 2015-2023 Valve Corporation
|
||||
* Copyright 2015-2023 LunarG, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
||||
+1
-2
@@ -3,8 +3,7 @@
|
||||
//
|
||||
/*
|
||||
** Copyright 2014-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
** SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
|
||||
|
||||
+1
-2
@@ -3,8 +3,7 @@
|
||||
|
||||
/*
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
** SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
#include "vk_platform.h"
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
** SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
** SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
+994
-43
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
** SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
** SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
** SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
** SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
** SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
** SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
** SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
** SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
** SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
** SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
** SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
** SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
** SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
/*
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
** SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
+901
-632
File diff suppressed because it is too large
Load Diff
@@ -683,7 +683,7 @@
|
||||
03000000a306000020f6000000000000,Saitek PS2700 PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000300f00001101000000000000,Saitek Rumble,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,
|
||||
03000000e804000000a0000000000000,Samsung EIGP20,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000bd12000010d1000000000000,Sanwa 4Button,a:b0,b:b1,x:b2,y:b3,dpup:-a1,dpdown:+a1,dpleft:-a0,dpright:+a0,platform:Windows,
|
||||
03000000bd12000010d1000000000000,Sanwa 4Button,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,x:b2,y:b3,platform:Windows,
|
||||
03000000c01100000252000000000000,Sanwa Easy Grip,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows,
|
||||
03000000c01100004350000000000000,Sanwa Micro Grip P3,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,x:b3,y:b2,platform:Windows,
|
||||
03000000411200004550000000000000,Sanwa Micro Grip Pro,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a1,righty:a2,start:b9,x:b1,y:b3,platform:Windows,
|
||||
@@ -697,14 +697,14 @@
|
||||
030000004f04000028b3000000000000,Score A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000952e00002577000000000000,Scuf PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
|
||||
03000000a30c00002500000000000000,Sega Genesis Mini 3B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Windows,
|
||||
03000000a30c00002400000000000000,Sega Mega Drive Mini 6B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,
|
||||
03000000a30c00002400000000000000,Sega Mega Drive Mini 6B Controller,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,
|
||||
03000000d804000086e6000000000000,Sega Multi Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:a2,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows,
|
||||
0300000000050000289b000000000000,Sega Saturn Adapter,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,
|
||||
0300000000f000000800000000000000,Sega Saturn Controller,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b7,righttrigger:b3,start:b0,x:b5,y:b6,platform:Windows,
|
||||
03000000730700000601000000000000,Sega Saturn Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows,
|
||||
03000000b40400000a01000000000000,Sega Saturn Controller,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows,
|
||||
030000003b07000004a1000000000000,SFX,a:b0,b:b2,back:b7,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b5,start:b8,x:b1,y:b3,platform:Windows,
|
||||
03000000632500002705000000000000,ShanWan Q36,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,righttrigger:b9,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000632500002705000000000000,ShanWan Gamepad,+lefty:+a2,-lefty:-a1,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,rightshoulder:b7,rightstick:b14,righttrigger:b9,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000f82100001900000000000000,Shogun Bros Chameleon X1,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
|
||||
03000000120c00001c1e000000000000,SnakeByte 4S PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
|
||||
03000000140300000918000000000000,SNES Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows,
|
||||
@@ -733,6 +733,7 @@
|
||||
03000000120c0000160e000000000000,Steel Play Metaltech PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
|
||||
03000000110100001914000000000000,SteelSeries,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000381000001214000000000000,SteelSeries Free,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000381000004114000000000000,SteelSeries Nimbus Cloud,a:b0,b:b1,x:b3,y:b4,back:b10,guide:b15,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,paddle1:b5,paddle2:b2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b8,righttrigger:b9,platform:Windows,
|
||||
03000000110100003114000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000381000003014000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
03000000381000003114000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
@@ -776,6 +777,7 @@
|
||||
030000005f140000c501000000000000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
|
||||
03000000b80500000210000000000000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
|
||||
030000005f1400002a01000000000000,Trust Predator GM1200,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,x:b3,y:b4,platform:Windows,
|
||||
03000000580400000a10000000000000,Trust Sight Fighter,a:b0,b:b1,back:b5,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,start:b2,x:b3,y:b4,platform:Windows,
|
||||
030000004f04000087b6000000000000,TWCS Throttle,dpdown:b8,dpleft:b9,dpright:b7,dpup:b6,leftstick:b5,lefttrigger:-a5,leftx:a0,lefty:a1,righttrigger:+a5,platform:Windows,
|
||||
03000000411200000450000000000000,Twin Shock,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a4,start:b11,x:b3,y:b0,platform:Windows,
|
||||
03000000d90400000200000000000000,TwinShock PS2 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
|
||||
@@ -939,6 +941,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000503200000110000045010000,Atari VCS Classic,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b3,start:b2,platform:Mac OS X,
|
||||
03000000503200000110000047010000,Atari VCS Classic Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b3,start:b2,platform:Mac OS X,
|
||||
03000000503200000210000047010000,Atari VCS Modern Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a2,righty:a3,start:b8,x:b2,y:b3,platform:Mac OS X,
|
||||
03000000e30500008106000000010000,Austgame GameCube Adapter,a:b0,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:+a4,leftx:a0,lefty:a1,misc3:b5,misc4:b6,rightshoulder:b4,righttrigger:-a4,rightx:a2,righty:a3,start:b7,x:b1,y:b3,platform:Mac OS X,
|
||||
030000008a3500000102000000010000,Backbone One,a:b0,b:b1,back:b16,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b17,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b15,x:b2,y:b3,platform:Mac OS X,
|
||||
030000008a3500000201000000010000,Backbone One,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
030000008a3500000202000000010000,Backbone One,a:b0,b:b1,back:b16,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b17,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b15,x:b2,y:b3,platform:Mac OS X,
|
||||
@@ -1116,6 +1119,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000110100002014000000000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X,
|
||||
03000000110100002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X,
|
||||
03000000381000002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X,
|
||||
03000000381000004114000000010000,SteelSeries Nimbus Cloud,a:b0,b:b1,x:b3,y:b4,back:b10,guide:b15,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,paddle1:b5,paddle2:b2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4,platform:Mac OS X,
|
||||
05000000484944204465766963650000,SteelSeries Nimbus Plus,a:b0,b:b1,back:b15,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b14,x:b2,y:b3,platform:Mac OS X,
|
||||
050000004e696d6275732b0000000000,SteelSeries Nimbus Plus,a:b0,b:b1,back:b15,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b14,x:b2,y:b3,platform:Mac OS X,
|
||||
03000000381000003014000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
|
||||
@@ -1249,12 +1253,16 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000c82d00001230000011010000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000c82d00001330000011010000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
05000000c82d00001230000000010000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000c82d00001260000011010000,8BitDo Ultimate 2,a:b0,b:b1,x:b3,y:b4,back:b10,guide:b12,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,paddle1:b17,paddle2:b16,paddle3:b2,paddle4:b5,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4,platform:Linux,
|
||||
03000000c82d00000b31000014010000,8BitDo Ultimate 2,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,
|
||||
05000000c82d00001260000001000000,8BitDo Ultimate 2,a:b0,b:b1,x:b3,y:b4,back:b10,guide:b12,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,paddle1:b17,paddle2:b16,paddle3:b2,paddle4:b5,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4,platform:Linux,
|
||||
03000000c82d00000a31000014010000,8BitDo Ultimate 2C,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000c82d00001d30000011010000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
05000000c82d00001b30000001000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000c82d00001530000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000c82d00001630000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000c82d00001730000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
06000000c82d00000320000007010000,8BitDo Ultimate Wired Controller for Xbox,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,
|
||||
03000000c82d00000121000011010000,8BitDo Xbox One SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
05000000c82d00000121000000010000,8BitDo Xbox One SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
05000000a00500003232000001000000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux,
|
||||
@@ -1276,6 +1284,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000020500000913000010010000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000373500000710000010010000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
05000000373500004610000001000000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
19000000010000000100000000010000,Anbernic RG28XX Controller,a:b4,b:b3,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b7,misc1:b1,rightshoulder:b8,leftstick:b12,rightstick:b13,start:b10,x:b5,y:b6,platform:Linux,
|
||||
03000000190e00000110000010010000,Aquaplus Piece,a:b1,b:b0,back:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b2,platform:Linux,
|
||||
03000000790000003018000011010000,Arcade Fightstick F300,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
|
||||
03000000a30c00002700000011010000,Astro City Mini,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,
|
||||
@@ -1338,7 +1347,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000b40400001124000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b14,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000b40400001224000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b2,paddle1:b16,paddle2:b17,paddle3:b14,paddle4:b15,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
05000000151900004000000001000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b14,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
06000000d73700000124000000000000,Flydigi Vader 5 Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,misc2:b12,misc3:b13,misc4:b14,misc5:b19,paddle1:b15,paddle2:b17,paddle3:b16,paddle4:b18,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000defa000001c0000000000000,Flydigi Vader 5 Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,misc2:b12,misc3:b13,misc4:b14,misc5:b19,paddle1:b15,paddle2:b16,paddle3:b17,paddle4:b18,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000007e0500003703000000000000,GameCube Adapter,a:b0,b:b1,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux,
|
||||
19000000030000000300000002030000,GameForce Controller,a:b1,b:b0,back:b8,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b14,lefttrigger:b6,leftx:a1,lefty:a0,rightshoulder:b5,rightstick:b15,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
|
||||
03000000373500000b10000019010000,GameSir Cyclone 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
@@ -1348,6 +1357,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
05000000ac0500002d0200001b010000,GameSir G4s,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b33,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000ac0500007a05000011010000,GameSir G5,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b16,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000373500009710000001020000,GameSir Kaleid Flux,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000373500005810000001020000,GameSir K1,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000ac0500001a06000011010000,GameSir T3 2.02,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000373500000410000044010000,GameSir T4 Kaleid,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000bc2000005656000011010000,GameSir T4w,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
@@ -1446,6 +1456,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000242f00008a00000011010000,JYS Adapter,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Linux,
|
||||
03000000314100001935000000010000,LeadJoy Xeno Plus,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:+a5,rightx:a4,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000006f0e00000103000000020000,Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000006f0e000001f5000010010000,Logic3 Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000006d040000d1ca000000000000,Logitech Chillstream,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
030000006d040000d1ca000011010000,Logitech Chillstream,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
030000006d04000016c2000010010000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
@@ -1536,10 +1547,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000853200000706000012010000,Nacon GC100,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000006b140000010c000010010000,Nacon GC400ES,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
|
||||
05000000853200000503000000010000,Nacon MGX Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
0300000085320000170d000011010000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
|
||||
0300000085320000190d000011010000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
|
||||
0300000085320000180d000011010000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
|
||||
0300000085320000160d000011010000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
|
||||
0300000085320000170d000011010000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
|
||||
0300000085320000180d000011010000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
|
||||
0300000085320000190d000011010000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
|
||||
030000000d0f00000900000010010000,Natec Genesis P44,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
030000004f1f00000800000011010000,NeoGeo PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
|
||||
0300000092120000474e000000010000,NeoGeo X Arcade Stick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b3,y:b2,platform:Linux,
|
||||
@@ -1618,6 +1629,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000d62000000520000050010000,PowerA Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000d62000000b20000001010000,PowerA Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000d62000000f20000001010000,PowerA Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000d62000006520000002010000,PowerA Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000006d040000d2ca000011010000,Precision Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
03000000250900000017000010010000,PS SS N64 Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b5,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2~,righty:a3,start:b8,platform:Linux,
|
||||
03000000ff1100004133000010010000,PS2 Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,
|
||||
@@ -1751,6 +1763,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
030000005e0400008e02000073050000,Speedlink Torid,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e0400008e02000020200000,SpeedLink Xeox Pro Analog,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000de280000ff11000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
05000000381000001214000001000000,SteelSeries Free,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a3,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
05000000381000004114000000010000,SteelSeries Nimbus Cloud,a:b0,b:b1,x:b3,y:b4,back:b10,guide:b15,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,paddle1:b5,paddle2:b2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4,platform:Linux,
|
||||
050000004e696d6275732b0000000000,SteelSeries Nimbus Plus,a:b0,b:b1,back:b10,guide:b11,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,platform:Linux,
|
||||
03000000381000003014000075010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000381000003114000075010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
@@ -1796,9 +1810,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000e00d00000300000003000000,TRBot Virtual Joypad,a:b11,b:b12,back:b15,dpdown:b6,dpleft:b3,dpright:b4,dpup:b5,leftshoulder:b17,leftstick:b21,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b22,righttrigger:a2,rightx:a3,righty:a4,start:b16,x:b13,y:b14,platform:Linux,
|
||||
03000000f00600000300000003000000,TRBot Virtual Joypad,a:b11,b:b12,back:b15,dpdown:b6,dpleft:b3,dpright:b4,dpup:b5,leftshoulder:b17,leftstick:b21,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b22,righttrigger:a2,rightx:a3,righty:a4,start:b16,x:b13,y:b14,platform:Linux,
|
||||
030000005f140000c501000010010000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
|
||||
03000000f51000001370000000000000,Turtle Beach ReactR,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000f51000001370000000010000,Turtle Beach ReactR,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
06000000f51000000870000003010000,Turtle Beach Recon,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000f51000001370000000010000,Turtle Beach ReactR,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,
|
||||
03000000f51000001370000000000000,Turtle Beach ReactR,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,
|
||||
05000000f51000008f01000001000000,Turtle Beach Rematch Nintendo Switch Controller,a:b0,b:b1,x:b2,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Linux,
|
||||
03000000100800000100000010010000,Twin PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,
|
||||
03000000c0160000e105000010010000,Ultimate Atari Fight Stick,a:b1,b:b2,back:b9,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b4,righttrigger:b5,start:b8,x:b0,y:b3,platform:Linux,
|
||||
03000000151900005678000010010000,Uniplay U6,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-az" viewBox="0 0 640 480">
|
||||
<path fill="#3f9c35" d="M.1 0h640v480H.1z"/>
|
||||
<path fill="#ed2939" d="M.1 0h640v320H.1z"/>
|
||||
<path fill="#00b9e4" d="M.1 0h640v160H.1z"/>
|
||||
<circle cx="304" cy="240" r="72" fill="#fff"/>
|
||||
<circle cx="320" cy="240" r="60" fill="#ed2939"/>
|
||||
<path fill="#fff" d="m384 200 7.7 21.5 20.6-9.8-9.8 20.7L424 240l-21.5 7.7 9.8 20.6-20.6-9.8L384 280l-7.7-21.5-20.6 9.8 9.8-20.6L344 240l21.5-7.7-9.8-20.6 20.6 9.8z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 501 B |
@@ -1,6 +1,8 @@
|
||||
// SPDX-FileCopyrightText: 2002-2026 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#if defined(VERTEX_SHADER)
|
||||
|
||||
struct VS_INPUT
|
||||
{
|
||||
float4 p : POSITION;
|
||||
@@ -15,6 +17,21 @@ struct VS_OUTPUT
|
||||
float4 c : COLOR;
|
||||
};
|
||||
|
||||
VS_OUTPUT vs_main(VS_INPUT input)
|
||||
{
|
||||
VS_OUTPUT output;
|
||||
|
||||
output.p = input.p;
|
||||
output.t = input.t;
|
||||
output.c = input.c;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
#endif // VERTEX_SHADER
|
||||
|
||||
#if defined(PIXEL_SHADER)
|
||||
|
||||
cbuffer cb0 : register(b0)
|
||||
{
|
||||
float4 BGColor;
|
||||
@@ -33,11 +50,22 @@ static const float3x3 rgb2yuv =
|
||||
Texture2D Texture;
|
||||
SamplerState TextureSampler;
|
||||
|
||||
#if HAS_FLOAT32_INPUT
|
||||
|
||||
float sample_c(float2 uv)
|
||||
{
|
||||
return Texture.Sample(TextureSampler, uv).r;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
float4 sample_c(float2 uv)
|
||||
{
|
||||
return Texture.Sample(TextureSampler, uv);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
struct PS_INPUT
|
||||
{
|
||||
float4 p : SV_Position;
|
||||
@@ -45,36 +73,117 @@ struct PS_INPUT
|
||||
float4 c : COLOR;
|
||||
};
|
||||
|
||||
#if HAS_INTEGER_OUTPUT
|
||||
#define OUTPUT_TYPE uint
|
||||
#define OUTPUT_SV SV_Target
|
||||
#elif HAS_DEPTH_OUTPUT
|
||||
#define OUTPUT_TYPE float
|
||||
#define OUTPUT_SV SV_Depth
|
||||
#elif HAS_FLOAT32_OUTPUT
|
||||
#define OUTPUT_TYPE float
|
||||
#define OUTPUT_SV SV_Target
|
||||
#else
|
||||
#define OUTPUT_TYPE float4
|
||||
#define OUTPUT_SV SV_Target
|
||||
#endif
|
||||
|
||||
struct PS_OUTPUT
|
||||
{
|
||||
float4 c : SV_Target0;
|
||||
OUTPUT_TYPE o : OUTPUT_SV;
|
||||
};
|
||||
|
||||
VS_OUTPUT vs_main(VS_INPUT input)
|
||||
uint rgba8_to_uint(float4 c)
|
||||
{
|
||||
VS_OUTPUT output;
|
||||
|
||||
output.p = input.p;
|
||||
output.t = input.t;
|
||||
output.c = input.c;
|
||||
|
||||
return output;
|
||||
uint4 i = uint4(c * 255.5f) & 0xFFu;
|
||||
return i.r | (i.g << 8) | (i.b << 16) | (i.a << 24);
|
||||
}
|
||||
|
||||
PS_OUTPUT ps_copy(PS_INPUT input)
|
||||
uint rgb5a1_to_uint(float4 c)
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
|
||||
output.c = sample_c(input.t);
|
||||
|
||||
return output;
|
||||
uint4 i = uint4(c * 255.5f) & uint4(0xF8u, 0xF8u, 0xF8u, 0x80u);
|
||||
return (i.r >> 3) | (i.g << 2) | (i.b << 7) | (i.a << 8);
|
||||
}
|
||||
|
||||
float ps_depth_copy(PS_INPUT input) : SV_Depth
|
||||
uint depth_to_uint(float d)
|
||||
{
|
||||
return sample_c(input.t).r;
|
||||
return uint(d * exp2(32.0f));
|
||||
}
|
||||
|
||||
float4 uint_to_rgba8(uint i)
|
||||
{
|
||||
return float4((i & 0xFFu), ((i >> 8) & 0xFFu), ((i >> 16) & 0xFFu), ((i >> 24) & 0xFFu)) / 255.0f;
|
||||
}
|
||||
|
||||
float4 uint_to_rgb5a1(uint i)
|
||||
{
|
||||
return float4(uint4(i << 3, i >> 2, i >> 7, i >> 8) & uint4(0xF8u, 0xF8u, 0xF8u, 0x80u)) / 255.0f;
|
||||
}
|
||||
|
||||
float uint_to_depth32(uint i)
|
||||
{
|
||||
return float(i) * exp2(-32.0f);
|
||||
}
|
||||
|
||||
float uint_to_depth24(uint i)
|
||||
{
|
||||
return float(i & 0xFFFFFFu) * exp2(-32.0f);
|
||||
}
|
||||
|
||||
float uint_to_depth16(uint i)
|
||||
{
|
||||
return float(i & 0xFFFFu) * exp2(-32.0f);
|
||||
}
|
||||
|
||||
float rgba8_to_depth32(float4 val)
|
||||
{
|
||||
return uint_to_depth32(rgba8_to_uint(val));
|
||||
}
|
||||
|
||||
float rgba8_to_depth24(float4 val)
|
||||
{
|
||||
return uint_to_depth24(rgba8_to_uint(val));
|
||||
}
|
||||
|
||||
float rgba8_to_depth16(float4 val)
|
||||
{
|
||||
return uint_to_depth16(rgba8_to_uint(val));
|
||||
}
|
||||
|
||||
float rgb5a1_to_depth16(float4 val)
|
||||
{
|
||||
return uint_to_depth16(rgb5a1_to_uint(val));
|
||||
}
|
||||
|
||||
float4 depth32_to_rgba8(float d)
|
||||
{
|
||||
return uint_to_rgba8(depth_to_uint(d));
|
||||
}
|
||||
|
||||
float4 depth16_to_rgb5a1(float d)
|
||||
{
|
||||
return uint_to_rgb5a1(depth_to_uint(d));
|
||||
}
|
||||
|
||||
float depth32_to_depth24(float d)
|
||||
{
|
||||
return uint_to_depth24(depth_to_uint(d));
|
||||
}
|
||||
|
||||
#if defined(__ps_copy__)
|
||||
OUTPUT_TYPE ps_copy(PS_INPUT input) : OUTPUT_SV
|
||||
{
|
||||
return sample_c(input.t);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__ps_depth_copy__)
|
||||
OUTPUT_TYPE ps_depth_copy(PS_INPUT input) : OUTPUT_SV
|
||||
{
|
||||
return sample_c(input.t);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__ps_downsample_copy__)
|
||||
PS_OUTPUT ps_downsample_copy(PS_INPUT input)
|
||||
{
|
||||
int DownsampleFactor = DOFFSET;
|
||||
@@ -85,179 +194,134 @@ PS_OUTPUT ps_downsample_copy(PS_INPUT input)
|
||||
int2 coord = max(int2(input.p.xy) * DownsampleFactor, ClampMin);
|
||||
|
||||
PS_OUTPUT output;
|
||||
output.c = (float4)0;
|
||||
output.o = (float4)0;
|
||||
for (int yoff = 0; yoff < DownsampleFactor; yoff++)
|
||||
{
|
||||
for (int xoff = 0; xoff < DownsampleFactor; xoff++)
|
||||
output.c += Texture.Load(int3(coord + int2(xoff * step_multiplier, yoff * step_multiplier), 0));
|
||||
output.o += Texture.Load(int3(coord + int2(xoff * step_multiplier, yoff * step_multiplier), 0));
|
||||
}
|
||||
output.c /= Weight;
|
||||
output.o /= Weight;
|
||||
return output;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__ps_filter_transparency__)
|
||||
PS_OUTPUT ps_filter_transparency(PS_INPUT input)
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
float4 c = sample_c(input.t);
|
||||
output.c = float4(c.rgb, 1.0);
|
||||
output.o = float4(c.rgb, 1.0);
|
||||
return output;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Need to be careful with precision here, it can break games like Spider-Man 3 and Dogs Life
|
||||
uint ps_convert_rgba8_16bits(PS_INPUT input) : SV_Target0
|
||||
#if defined(__ps_convert_rgb5a1_16bits__)
|
||||
OUTPUT_TYPE ps_convert_rgb5a1_16bits(PS_INPUT input) : OUTPUT_SV
|
||||
{
|
||||
uint4 i = sample_c(input.t) * float4(255.5f, 255.5f, 255.5f, 255.5f);
|
||||
|
||||
return ((i.x & 0x00F8u) >> 3) | ((i.y & 0x00F8u) << 2) | ((i.z & 0x00f8u) << 7) | ((i.w & 0x80u) << 8);
|
||||
// Need to be careful with precision here, it can break games like Spider-Man 3 and Dogs Life
|
||||
return rgb5a1_to_uint(sample_c(input.t));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__ps_datm1__)
|
||||
void ps_datm1(PS_INPUT input)
|
||||
{
|
||||
clip(sample_c(input.t).a - 127.5f / 255); // >= 0x80 pass
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__ps_datm0__)
|
||||
void ps_datm0(PS_INPUT input)
|
||||
{
|
||||
clip(127.5f / 255 - sample_c(input.t).a); // < 0x80 pass (== 0x80 should not pass)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__ps_datm1_rta_correction__)
|
||||
void ps_datm1_rta_correction(PS_INPUT input)
|
||||
{
|
||||
clip(sample_c(input.t).a - 254.5f / 255); // >= 0x80 pass
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__ps_datm0_rta_correction__)
|
||||
void ps_datm0_rta_correction(PS_INPUT input)
|
||||
{
|
||||
clip(254.5f / 255 - sample_c(input.t).a); // < 0x80 pass (== 0x80 should not pass)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__ps_rta_correction__)
|
||||
PS_OUTPUT ps_rta_correction(PS_INPUT input)
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
float4 value = sample_c(input.t);
|
||||
output.c = float4(value.rgb, value.a / (128.25f / 255.0f));
|
||||
output.o = float4(value.rgb, value.a / (128.25f / 255.0f));
|
||||
return output;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__ps_rta_decorrection__)
|
||||
PS_OUTPUT ps_rta_decorrection(PS_INPUT input)
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
float4 value = sample_c(input.t);
|
||||
output.c = float4(value.rgb, value.a * (128.25f / 255.0f));
|
||||
output.o = float4(value.rgb, value.a * (128.25f / 255.0f));
|
||||
return output;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__ps_colclip_init__)
|
||||
PS_OUTPUT ps_colclip_init(PS_INPUT input)
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
float4 value = sample_c(input.t);
|
||||
output.c = float4(round(value.rgb * 255) / 65535, value.a);
|
||||
output.o = float4(round(value.rgb * 255) / 65535, value.a);
|
||||
return output;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__ps_colclip_resolve__)
|
||||
PS_OUTPUT ps_colclip_resolve(PS_INPUT input)
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
float4 value = sample_c(input.t);
|
||||
output.c = float4(float3(uint3(value.rgb * 65535.5) & 255) / 255, value.a);
|
||||
output.o = float4(float3(uint3(value.rgb * 65535.5) & 255) / 255, value.a);
|
||||
return output;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint ps_convert_float32_32bits(PS_INPUT input) : SV_Target0
|
||||
#if defined(__ps_convert_depth32_32bits__)
|
||||
OUTPUT_TYPE ps_convert_depth32_32bits(PS_INPUT input) : OUTPUT_SV
|
||||
{
|
||||
// Convert a FLOAT32 depth texture into a 32 bits UINT texture
|
||||
return uint(exp2(32.0f) * sample_c(input.t).r);
|
||||
// Convert a depth texture into a 32 bits UINT texture
|
||||
return depth_to_uint(sample_c(input.t));
|
||||
}
|
||||
#endif
|
||||
|
||||
PS_OUTPUT ps_convert_float32_rgba8(PS_INPUT input)
|
||||
#if defined(__ps_convert_depth32_rgba8__)
|
||||
OUTPUT_TYPE ps_convert_depth32_rgba8(PS_INPUT input) : OUTPUT_SV
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
|
||||
// Convert a FLOAT32 depth texture into a RGBA color texture
|
||||
uint d = uint(sample_c(input.t).r * exp2(32.0f));
|
||||
output.c = float4(uint4((d & 0xFFu), ((d >> 8) & 0xFFu), ((d >> 16) & 0xFFu), (d >> 24))) / 255.0f;
|
||||
|
||||
return output;
|
||||
// Convert a depth texture into a RGBA color texture
|
||||
return depth32_to_rgba8(sample_c(input.t));
|
||||
}
|
||||
#endif
|
||||
|
||||
PS_OUTPUT ps_convert_float16_rgb5a1(PS_INPUT input)
|
||||
#if defined(__ps_convert_depth16_rgb5a1__)
|
||||
OUTPUT_TYPE ps_convert_depth16_rgb5a1(PS_INPUT input) : OUTPUT_SV
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
|
||||
// Convert a FLOAT32 (only 16 lsb) depth into a RGB5A1 color texture
|
||||
uint d = uint(sample_c(input.t).r * exp2(32.0f));
|
||||
output.c = float4(uint4(d << 3, d >> 2, d >> 7, d >> 8) & uint4(0xf8, 0xf8, 0xf8, 0x80)) / 255.0f;
|
||||
return output;
|
||||
// Convert depth (only 16 lsb) into a RGB5A1 color texture
|
||||
return depth16_to_rgb5a1(sample_c(input.t));
|
||||
}
|
||||
#endif
|
||||
|
||||
float rgba8_to_depth32(float4 val)
|
||||
{
|
||||
uint4 c = uint4(val * 255.5f);
|
||||
return float(c.r | (c.g << 8) | (c.b << 16) | (c.a << 24)) * exp2(-32.0f);
|
||||
}
|
||||
|
||||
float rgba8_to_depth24(float4 val)
|
||||
{
|
||||
uint3 c = uint3(val.rgb * 255.5f);
|
||||
return float(c.r | (c.g << 8) | (c.b << 16)) * exp2(-32.0f);
|
||||
}
|
||||
|
||||
float rgba8_to_depth16(float4 val)
|
||||
{
|
||||
uint2 c = uint2(val.rg * 255.5f);
|
||||
return float(c.r | (c.g << 8)) * exp2(-32.0f);
|
||||
}
|
||||
|
||||
float rgb5a1_to_depth16(float4 val)
|
||||
{
|
||||
uint4 c = uint4(val * 255.5f);
|
||||
return float(((c.r & 0xF8u) >> 3) | ((c.g & 0xF8u) << 2) | ((c.b & 0xF8u) << 7) | ((c.a & 0x80u) << 8)) * exp2(-32.0f);
|
||||
}
|
||||
|
||||
float ps_convert_float32_depth_to_color(PS_INPUT input) : SV_Target0
|
||||
{
|
||||
return sample_c(input.t).r;
|
||||
}
|
||||
|
||||
float ps_convert_float32_color_to_depth(PS_INPUT input) : SV_Depth
|
||||
{
|
||||
return sample_c(input.t).r;
|
||||
}
|
||||
|
||||
float ps_convert_float32_float24(PS_INPUT input) : SV_Depth
|
||||
#if defined(__ps_convert_depth32_depth24__)
|
||||
OUTPUT_TYPE ps_convert_depth32_depth24(PS_INPUT input) : OUTPUT_SV
|
||||
{
|
||||
// Truncates depth value to 24bits
|
||||
uint d = uint(sample_c(input.t).r * exp2(32.0f)) & 0xFFFFFFu;
|
||||
return float(d) * exp2(-32.0f);
|
||||
}
|
||||
|
||||
float ps_convert_rgba8_float32(PS_INPUT input) : SV_Depth
|
||||
{
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
return rgba8_to_depth32(sample_c(input.t));
|
||||
}
|
||||
|
||||
float ps_convert_rgba8_float24(PS_INPUT input) : SV_Depth
|
||||
{
|
||||
// Same as above but without the alpha channel (24 bits Z)
|
||||
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
return rgba8_to_depth24(sample_c(input.t));
|
||||
}
|
||||
|
||||
float ps_convert_rgba8_float16(PS_INPUT input) : SV_Depth
|
||||
{
|
||||
// Same as above but without the A/B channels (16 bits Z)
|
||||
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
return rgba8_to_depth16(sample_c(input.t));
|
||||
}
|
||||
|
||||
float ps_convert_rgb5a1_float16(PS_INPUT input) : SV_Depth
|
||||
{
|
||||
// Convert an RGB5A1 (saved as RGBA8) color to a 16 bit Z
|
||||
return rgb5a1_to_depth16(sample_c(input.t));
|
||||
return depth32_to_depth24(sample_c(input.t));
|
||||
}
|
||||
#endif
|
||||
|
||||
#define SAMPLE_RGBA_DEPTH_BILN(CONVERT_FN) \
|
||||
uint width, height; \
|
||||
@@ -272,34 +336,57 @@ float ps_convert_rgb5a1_float16(PS_INPUT input) : SV_Depth
|
||||
float depthBR = CONVERT_FN(Texture.Load(int3(coords.zw, 0))); \
|
||||
return lerp(lerp(depthTL, depthTR, mix_vals.x), lerp(depthBL, depthBR, mix_vals.x), mix_vals.y);
|
||||
|
||||
float ps_convert_rgba8_float32_biln(PS_INPUT input) : SV_Depth
|
||||
#if defined(__ps_convert_rgba8_depth32__)
|
||||
OUTPUT_TYPE ps_convert_rgba8_depth32(PS_INPUT input) : OUTPUT_SV
|
||||
{
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
#if HAS_BILN
|
||||
SAMPLE_RGBA_DEPTH_BILN(rgba8_to_depth32);
|
||||
#else
|
||||
return rgba8_to_depth32(sample_c(input.t));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
float ps_convert_rgba8_float24_biln(PS_INPUT input) : SV_Depth
|
||||
#if defined(__ps_convert_rgba8_depth24__)
|
||||
OUTPUT_TYPE ps_convert_rgba8_depth24(PS_INPUT input) : OUTPUT_SV
|
||||
{
|
||||
// Same as above but without the alpha channel (24 bits Z)
|
||||
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
#if HAS_BILN
|
||||
SAMPLE_RGBA_DEPTH_BILN(rgba8_to_depth24);
|
||||
#else
|
||||
return rgba8_to_depth24(sample_c(input.t));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
float ps_convert_rgba8_float16_biln(PS_INPUT input) : SV_Depth
|
||||
#if defined(__ps_convert_rgba8_depth16__)
|
||||
OUTPUT_TYPE ps_convert_rgba8_depth16(PS_INPUT input) : OUTPUT_SV
|
||||
{
|
||||
// Same as above but without the A/B channels (16 bits Z)
|
||||
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
#if HAS_BILN
|
||||
SAMPLE_RGBA_DEPTH_BILN(rgba8_to_depth16);
|
||||
#else
|
||||
return rgba8_to_depth16(sample_c(input.t));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
float ps_convert_rgb5a1_float16_biln(PS_INPUT input) : SV_Depth
|
||||
#if defined(__ps_convert_rgb5a1_depth16__)
|
||||
OUTPUT_TYPE ps_convert_rgb5a1_depth16(PS_INPUT input) : OUTPUT_SV
|
||||
{
|
||||
// Convert an RGB5A1 (saved as RGBA8) color to a 16 bit Z
|
||||
#if HAS_BILN
|
||||
SAMPLE_RGBA_DEPTH_BILN(rgb5a1_to_depth16);
|
||||
#else
|
||||
return rgb5a1_to_depth16(sample_c(input.t));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__ps_convert_rgb5a1_8i__)
|
||||
PS_OUTPUT ps_convert_rgb5a1_8i(PS_INPUT input)
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
@@ -406,7 +493,7 @@ PS_OUTPUT ps_convert_rgb5a1_8i(PS_INPUT input)
|
||||
uint red = (denorm_c.r >> 3) & 0x1Fu;
|
||||
uint green = (denorm_c.g >> 3) & 0x1Fu;
|
||||
|
||||
output.c = (float4)(((float)(((green << 5) | red) & 0xFFu)) / 255.0f);
|
||||
output.o = (float4)(((float)(((green << 5) | red) & 0xFFu)) / 255.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -414,11 +501,13 @@ PS_OUTPUT ps_convert_rgb5a1_8i(PS_INPUT input)
|
||||
uint blue = (denorm_c.b >> 3) & 0x1Fu;
|
||||
uint alpha = denorm_c.a & 0x80u;
|
||||
|
||||
output.c = (float4)(((float)((alpha | (blue << 2) | (green >> 3)) & 0xFFu)) / 255.0f);
|
||||
output.o = (float4)(((float)((alpha | (blue << 2) | (green >> 3)) & 0xFFu)) / 255.0f);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__ps_convert_rgba_8i__)
|
||||
PS_OUTPUT ps_convert_rgba_8i(PS_INPUT input)
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
@@ -462,10 +551,12 @@ PS_OUTPUT ps_convert_rgba_8i(PS_INPUT input)
|
||||
float4 pixel = Texture.Load(int3(int2(coord), 0));
|
||||
float2 sel0 = (pos.y & 2u) == 0u ? pixel.rb : pixel.ga;
|
||||
float sel1 = (pos.x & 8u) == 0u ? sel0.x : sel0.y;
|
||||
output.c = (float4)(sel1); // Divide by something here?
|
||||
output.o = (float4)(sel1); // Divide by something here?
|
||||
return output;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__ps_convert_clut_4__)
|
||||
PS_OUTPUT ps_convert_clut_4(PS_INPUT input)
|
||||
{
|
||||
// Borrowing the YUV constant buffer.
|
||||
@@ -478,10 +569,12 @@ PS_OUTPUT ps_convert_clut_4(PS_INPUT input)
|
||||
|
||||
int2 final = int2(floor(float2(offset + pos) * scale));
|
||||
PS_OUTPUT output;
|
||||
output.c = Texture.Load(int3(final, 0), 0);
|
||||
output.o = Texture.Load(int3(final, 0), 0);
|
||||
return output;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__ps_convert_clut_8__)
|
||||
PS_OUTPUT ps_convert_clut_8(PS_INPUT input)
|
||||
{
|
||||
float scale = BGColor.x;
|
||||
@@ -497,10 +590,12 @@ PS_OUTPUT ps_convert_clut_8(PS_INPUT input)
|
||||
|
||||
int2 final = int2(floor(float2(offset + pos) * scale));
|
||||
PS_OUTPUT output;
|
||||
output.c = Texture.Load(int3(final, 0), 0);
|
||||
output.o = Texture.Load(int3(final, 0), 0);
|
||||
return output;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__ps_yuv__)
|
||||
PS_OUTPUT ps_yuv(PS_INPUT input)
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
@@ -515,41 +610,43 @@ PS_OUTPUT ps_yuv(PS_INPUT input)
|
||||
switch (EMODA)
|
||||
{
|
||||
case 0:
|
||||
output.c.a = i.a;
|
||||
output.o.a = i.a;
|
||||
break;
|
||||
case 1:
|
||||
output.c.a = Y;
|
||||
output.o.a = Y;
|
||||
break;
|
||||
case 2:
|
||||
output.c.a = Y / 2.0f;
|
||||
output.o.a = Y / 2.0f;
|
||||
break;
|
||||
case 3:
|
||||
default:
|
||||
output.c.a = 0.0f;
|
||||
output.o.a = 0.0f;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (EMODC)
|
||||
{
|
||||
case 0:
|
||||
output.c.rgb = i.rgb;
|
||||
output.o.rgb = i.rgb;
|
||||
break;
|
||||
case 1:
|
||||
output.c.rgb = float3(Y, Y, Y);
|
||||
output.o.rgb = float3(Y, Y, Y);
|
||||
break;
|
||||
case 2:
|
||||
output.c.rgb = float3(Y, Cb, Cr);
|
||||
output.o.rgb = float3(Y, Cb, Cr);
|
||||
break;
|
||||
case 3:
|
||||
default:
|
||||
output.c.rgb = float3(i.a, i.a, i.a);
|
||||
output.o.rgb = float3(i.a, i.a, i.a);
|
||||
break;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
#endif
|
||||
|
||||
float ps_stencil_image_init_0(PS_INPUT input) : SV_Target
|
||||
#if defined(__ps_primid_image_init_0__)
|
||||
float ps_primid_image_init_0(PS_INPUT input) : SV_Target
|
||||
{
|
||||
float c;
|
||||
if ((127.5f / 255.0f) < sample_c(input.t).a) // < 0x80 pass (== 0x80 should not pass)
|
||||
@@ -558,8 +655,10 @@ float ps_stencil_image_init_0(PS_INPUT input) : SV_Target
|
||||
c = float(0x7FFFFFFF);
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
|
||||
float ps_stencil_image_init_1(PS_INPUT input) : SV_Target
|
||||
#if defined(__ps_primid_image_init_1__)
|
||||
float ps_primid_image_init_1(PS_INPUT input) : SV_Target
|
||||
{
|
||||
float c;
|
||||
if (sample_c(input.t).a < (127.5f / 255.0f)) // >= 0x80 pass
|
||||
@@ -568,9 +667,10 @@ float ps_stencil_image_init_1(PS_INPUT input) : SV_Target
|
||||
c = float(0x7FFFFFFF);
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
|
||||
float ps_stencil_image_init_2(PS_INPUT input)
|
||||
: SV_Target
|
||||
#if defined(__ps_primid_image_init_2__)
|
||||
float ps_primid_image_init_2(PS_INPUT input) : SV_Target
|
||||
{
|
||||
float c;
|
||||
if ((254.5f / 255.0f) < sample_c(input.t).a) // < 0x80 pass (== 0x80 should not pass)
|
||||
@@ -579,9 +679,10 @@ float ps_stencil_image_init_2(PS_INPUT input)
|
||||
c = float(0x7FFFFFFF);
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
|
||||
float ps_stencil_image_init_3(PS_INPUT input)
|
||||
: SV_Target
|
||||
#if defined(__ps_primid_image_init_3__)
|
||||
float ps_primid_image_init_3(PS_INPUT input) : SV_Target
|
||||
{
|
||||
float c;
|
||||
if (sample_c(input.t).a < (254.5f / 255.0f)) // >= 0x80 pass
|
||||
@@ -590,3 +691,6 @@ float ps_stencil_image_init_3(PS_INPUT input)
|
||||
c = float(0x7FFFFFFF);
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // PIXEL_SHADER
|
||||
+420
-140
@@ -50,6 +50,12 @@
|
||||
#define PS_AA1_TRIANGLE_SW_Z 3
|
||||
#endif
|
||||
|
||||
#ifndef PS_ROV_DEPTH_NONE
|
||||
#define PS_ROV_DEPTH_NONE 0
|
||||
#define PS_ROV_DEPTH_READ_WRITE 1
|
||||
#define PS_ROV_DEPTH_READ_ONLY 2
|
||||
#endif
|
||||
|
||||
#ifndef PS_FST
|
||||
#define PS_IIP 0
|
||||
#define PS_FST 0
|
||||
@@ -111,6 +117,8 @@
|
||||
#define PS_TEX_IS_FB 0
|
||||
#define PS_AA1 0
|
||||
#define PS_ABE 0
|
||||
#define PS_ROV_COLOR 0
|
||||
#define PS_ROV_DEPTH 0
|
||||
#endif
|
||||
|
||||
#ifndef VS_EXPAND_NONE
|
||||
@@ -132,6 +140,12 @@
|
||||
#define SW_DEPTH (NEEDS_DEPTH_FOR_AFAIL || NEEDS_DEPTH_FOR_ZTST || NEEDS_DEPTH_FOR_AA1)
|
||||
#define ZWRITE (PS_ZFLOOR || PS_ZCLAMP || SW_DEPTH)
|
||||
|
||||
#define PS_RETURN_COLOR_ROV (!PS_NO_COLOR && PS_ROV_COLOR)
|
||||
#define PS_RETURN_COLOR (!PS_NO_COLOR && !PS_ROV_COLOR)
|
||||
#define PS_RETURN_DEPTH_ROV (PS_ROV_DEPTH == PS_ROV_DEPTH_READ_WRITE)
|
||||
#define PS_RETURN_DEPTH (ZWRITE && !PS_ROV_DEPTH)
|
||||
#define PS_ROV_EARLYDEPTHSTENCIL (PS_ROV_COLOR && !PS_ROV_DEPTH && !ZWRITE)
|
||||
|
||||
struct VS_INPUT
|
||||
{
|
||||
float2 st : TEXCOORD0;
|
||||
@@ -181,21 +195,26 @@ struct PS_INPUT
|
||||
struct PS_OUTPUT
|
||||
{
|
||||
#define NUM_RTS 0
|
||||
#if !PS_NO_COLOR
|
||||
#if PS_DATE == 1 || PS_DATE == 2
|
||||
float c : SV_Target;
|
||||
#else
|
||||
float4 c0 : SV_Target0;
|
||||
#undef NUM_RTS
|
||||
#define NUM_RTS 1
|
||||
#if !PS_NO_COLOR1
|
||||
float4 c1 : SV_Target1;
|
||||
|
||||
#if PS_RETURN_COLOR
|
||||
#if PS_DATE == 1 || PS_DATE == 2
|
||||
float c : SV_Target;
|
||||
#else
|
||||
|
||||
float4 c0 : SV_Target0;
|
||||
|
||||
#undef NUM_RTS
|
||||
#define NUM_RTS 1
|
||||
|
||||
#if !PS_NO_COLOR1
|
||||
float4 c1 : SV_Target1;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#if ZWRITE
|
||||
|
||||
#if PS_RETURN_DEPTH
|
||||
// In DX12 we do depth feedback loops with a color copy.
|
||||
#if SW_DEPTH && PS_NO_COLOR1 && DX12
|
||||
#if SW_DEPTH && PS_NO_COLOR1 && PS_DEPTH_FEEDBACK_SUPPORT == 2
|
||||
#if NUM_RTS > 0
|
||||
float depth_color : SV_Target1;
|
||||
#else
|
||||
@@ -208,16 +227,31 @@ struct PS_OUTPUT
|
||||
float depth : SV_Depth;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#undef NUM_RTS
|
||||
};
|
||||
|
||||
Texture2D<float4> Texture : register(t0);
|
||||
Texture2D<float4> Palette : register(t1);
|
||||
#if !PS_ROV_COLOR
|
||||
Texture2D<float4> RtTexture : register(t2);
|
||||
#endif
|
||||
Texture2D<float> PrimMinTexture : register(t3);
|
||||
#if !PS_ROV_DEPTH
|
||||
Texture2D<float> DepthTexture : register(t4);
|
||||
#endif
|
||||
SamplerState TextureSampler : register(s0);
|
||||
|
||||
#if PS_ROV_COLOR
|
||||
RasterizerOrderedTexture2D<unorm float4> RtTextureRov : register(u0);
|
||||
static float4 rov_rt_value;
|
||||
#endif
|
||||
|
||||
#if PS_ROV_DEPTH
|
||||
RasterizerOrderedTexture2D<float> DepthTextureRov : register(u1);
|
||||
static float rov_depth_value;
|
||||
#endif
|
||||
|
||||
#ifdef DX12
|
||||
cbuffer cb1 : register(b1)
|
||||
#else
|
||||
@@ -242,8 +276,46 @@ cbuffer cb1
|
||||
float4x4 DitherMatrix;
|
||||
float ScaledScaleFactor;
|
||||
float RcpScaleFactor;
|
||||
float _pad0_cb1;
|
||||
float _pad1_cb1;
|
||||
float LineCovScale;
|
||||
float _pad2_cb1;
|
||||
float _pad3_cb1;
|
||||
float _pad4_cb1;
|
||||
};
|
||||
|
||||
float4 RtLoad(int2 xy)
|
||||
{
|
||||
#if PS_ROV_COLOR
|
||||
return rov_rt_value;
|
||||
#else
|
||||
return RtTexture.Load(int3(int2(xy), 0));
|
||||
#endif
|
||||
}
|
||||
|
||||
float DepthLoad(int2 xy)
|
||||
{
|
||||
#if PS_ROV_DEPTH
|
||||
return rov_depth_value;
|
||||
#else
|
||||
return DepthTexture.Load(int3(int2(xy), 0));
|
||||
#endif
|
||||
}
|
||||
|
||||
void RtWrite(int2 xy, float4 c)
|
||||
{
|
||||
#if PS_ROV_COLOR
|
||||
RtTextureRov[xy] = c;
|
||||
#endif
|
||||
}
|
||||
|
||||
void DepthWrite(int2 xy, float d)
|
||||
{
|
||||
#if PS_ROV_DEPTH
|
||||
DepthTextureRov[xy] = d;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if (PS_AUTOMATIC_LOD != 1) && (PS_MANUAL_LOD == 1)
|
||||
float manual_lod(float uv_w)
|
||||
{
|
||||
@@ -261,69 +333,92 @@ float manual_lod(float uv_w)
|
||||
#endif
|
||||
|
||||
#if PS_ANISOTROPIC_FILTERING > 1
|
||||
bool2 nan_or_inf(float2 xy)
|
||||
{
|
||||
// FXC (<=SM5.1) may optimise away isnan and isinf.
|
||||
// DXC (>=SM6.0) will preserve them.
|
||||
#ifdef __hlsl_dx_compiler
|
||||
return isinf(xy) | isnan(xy);
|
||||
#else
|
||||
return (asuint(xy) & 0x7f800000) == 0x7f800000;
|
||||
#endif
|
||||
}
|
||||
|
||||
float4 sample_c_af(float2 uv, float uv_w)
|
||||
{
|
||||
// HW sampler will reject bad UVs, match that here.
|
||||
uv = any(isnan(uv) | isinf(uv)) ? float2(0, 0) : uv;
|
||||
uv = any(nan_or_inf(uv)) ? float2(0.0f, 0.0f) : uv;
|
||||
|
||||
// Large floating point values risk NaN/Inf values.
|
||||
// Above this value floats lose decimal precision, so seems a resonable limit for UVs.
|
||||
uv = clamp(uv, -8388608.0f, 8388608.0f);
|
||||
|
||||
// Below taken from https://microsoft.github.io/DirectX-Specs/d3d/archive/D3D11_3_FunctionalSpec.htm#7.18.11%20LOD%20Calculations
|
||||
// And https://registry.khronos.org/OpenGL/extensions/EXT/EXT_texture_filter_anisotropic.txt
|
||||
// With guidance from https://pema.dev/2025/05/09/mipmaps-too-much-detail/
|
||||
float2 sz;
|
||||
Texture.GetDimensions(sz.x, sz.y);
|
||||
float2 dX = ddx(uv) * sz;
|
||||
float2 dY = ddy(uv) * sz;
|
||||
|
||||
float length_x = length(dX);
|
||||
float length_y = length(dY);
|
||||
|
||||
// Calculate Ellipse Transform
|
||||
bool d_zero = length(dX) == 0 || length(dY) == 0;
|
||||
bool d_par = (dX.x * dY.y - dY.x * dX.y) == 0;
|
||||
bool d_per = dot(dX, dY) == 0;
|
||||
bool d_inf_nan = any(isinf(dX) | isinf(dY) | isnan(dX) | isnan(dY));
|
||||
bool d_zero = length_x < 0.001f || length_y < 0.001f;
|
||||
float f = (dX.x * dY.y - dX.y * dY.x);
|
||||
bool d_par = f < 0.001f;
|
||||
bool d_per = dot(dX, dY) < 0.001f;
|
||||
bool d_inf_nan = any(nan_or_inf(dX) | nan_or_inf(dY));
|
||||
|
||||
if (!(d_zero || d_par || d_per || d_inf_nan))
|
||||
{
|
||||
float A = dX.y * dX.y + dY.y * dY.y;
|
||||
float B = -2 * (dX.x * dX.y + dY.x * dY.y);
|
||||
float C = dX.x * dX.x + dY.x * dY.x;
|
||||
float f = (dX.x * dY.y - dY.x * dX.y);
|
||||
float F = f * f;
|
||||
|
||||
float p = A - C;
|
||||
float q = A + C;
|
||||
float t = sqrt(p * p + B * B);
|
||||
|
||||
float sqrt_num_plus = sqrt(F * (t + p));
|
||||
float sqrt_num_minus = sqrt(F * (t - p));
|
||||
|
||||
float inv_sqrt_denom_plus = rsqrt(t * (q + t));
|
||||
float inv_sqrt_denom_minus = rsqrt(t * (q - t));
|
||||
|
||||
float signB = sign(B);
|
||||
|
||||
float2 new_dX = float2(
|
||||
sqrt(F * (t + p) / (t * (q + t))),
|
||||
sqrt(F * (t - p) / (t * (q + t))) * sign(B)
|
||||
sqrt_num_plus * inv_sqrt_denom_plus,
|
||||
sqrt_num_minus * inv_sqrt_denom_plus * signB
|
||||
);
|
||||
|
||||
|
||||
float2 new_dY = float2(
|
||||
sqrt(F * (t - p) / (t * (q - t))) * -sign(B),
|
||||
sqrt(F * (t + p) / (t * (q - t)))
|
||||
sqrt_num_minus * inv_sqrt_denom_minus * -signB,
|
||||
sqrt_num_plus * inv_sqrt_denom_minus
|
||||
);
|
||||
|
||||
d_inf_nan = any(isinf(new_dX) | isinf(new_dY) | isnan(new_dX) | isnan(new_dY));
|
||||
|
||||
d_inf_nan = any(nan_or_inf(new_dX) | nan_or_inf(new_dY));
|
||||
if (!d_inf_nan)
|
||||
{
|
||||
dX = new_dX;
|
||||
dY = new_dY;
|
||||
length_x = length(dX);
|
||||
length_y = length(dY);
|
||||
}
|
||||
}
|
||||
|
||||
// Compute AF values
|
||||
float squared_length_x = dX.x * dX.x + dX.y * dX.y;
|
||||
float squared_length_y = dY.x * dY.x + dY.y * dY.y;
|
||||
float determinant = abs(dX.x * dY.y - dX.y * dY.x);
|
||||
bool is_major_x = squared_length_x > squared_length_y;
|
||||
float squared_length_major = is_major_x ? squared_length_x : squared_length_y;
|
||||
float length_major = sqrt(squared_length_major);
|
||||
bool is_major_x = length_x > length_y;
|
||||
float length_major = is_major_x ? length_x : length_y;
|
||||
float length_minor = is_major_x ? length_y : length_x;
|
||||
|
||||
float aniso_ratio;
|
||||
float length_lod;
|
||||
float2 aniso_line;
|
||||
|
||||
if (length_major <= 1.0f)
|
||||
{
|
||||
// A zero length_major would result in NaN Lod and break sampling.
|
||||
@@ -331,57 +426,44 @@ float4 sample_c_af(float2 uv, float uv_w)
|
||||
// Perform isotropic filtering instead.
|
||||
aniso_ratio = 1.0f;
|
||||
length_lod = length_major;
|
||||
aniso_line = float2(0, 0);
|
||||
aniso_line = float2(0.0f, 0.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
float norm_major = 1.0f / length_major;
|
||||
|
||||
float2 aniso_line_dir = float2(
|
||||
(is_major_x ? dX.x : dY.x) * norm_major,
|
||||
(is_major_x ? dX.y : dY.y) * norm_major
|
||||
);
|
||||
|
||||
aniso_ratio = squared_length_major / determinant;
|
||||
float2 aniso_line_dir = is_major_x ? dX : dY;
|
||||
|
||||
// Calculate the minor length of the ellipse for Lod, while also clamping the ratio of anisotropy.
|
||||
if (aniso_ratio > PS_ANISOTROPIC_FILTERING)
|
||||
{
|
||||
// ratio is clamped - Lod is based on ratio (preserves area)
|
||||
aniso_ratio = PS_ANISOTROPIC_FILTERING;
|
||||
length_lod = length_major / PS_ANISOTROPIC_FILTERING;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ratio not clamped - Lod is based on area
|
||||
length_lod = determinant / length_major;
|
||||
}
|
||||
aniso_ratio = min(length_major / length_minor, PS_ANISOTROPIC_FILTERING);
|
||||
length_lod = length_major / aniso_ratio;
|
||||
|
||||
// clamp to top Lod
|
||||
if (length_lod < 1.0f)
|
||||
aniso_ratio = max(1.0f, aniso_ratio * length_lod);
|
||||
|
||||
aniso_ratio = round(aniso_ratio);
|
||||
aniso_line = aniso_line_dir * 0.5f * length_major * (1.0f / sz);
|
||||
|
||||
aniso_line = aniso_line_dir * 0.5f * (1.0f / sz);
|
||||
}
|
||||
|
||||
|
||||
#if PS_AUTOMATIC_LOD == 1
|
||||
float lod = log2(length_lod);
|
||||
#elif PS_MANUAL_LOD == 1
|
||||
float lod = manual_lod(uv_w);
|
||||
#else
|
||||
float lod = 0; // No Lod
|
||||
float lod = 0.0f; // No Lod
|
||||
#endif
|
||||
|
||||
|
||||
float4 colour;
|
||||
if (aniso_ratio == 1.0f)
|
||||
colour = Texture.SampleLevel(TextureSampler, uv, lod);
|
||||
else
|
||||
{
|
||||
float4 num = float4(0, 0, 0, 0);
|
||||
for (int i = 0; i < aniso_ratio; i++)
|
||||
{
|
||||
float2 d = -aniso_line + (0.5f + i) * (2.0f * aniso_line) / aniso_ratio;
|
||||
float4 num = float4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
float2 segment = (2.0f * aniso_line) / aniso_ratio;
|
||||
|
||||
int aniso_ratio_i = (int)aniso_ratio;
|
||||
for (int i = 0; i < aniso_ratio_i; i++)
|
||||
{
|
||||
float2 d = -aniso_line + (0.5f + i) * segment;
|
||||
float2 uv_sample = uv + d;
|
||||
float4 sample_colour = Texture.SampleLevel(TextureSampler, uv_sample, lod);
|
||||
num += sample_colour;
|
||||
@@ -396,7 +478,7 @@ float4 sample_c_af(float2 uv, float uv_w)
|
||||
float4 sample_c(float2 uv, float uv_w, int2 xy)
|
||||
{
|
||||
#if PS_TEX_IS_FB == 1
|
||||
return RtTexture.Load(int3(int2(xy), 0));
|
||||
return RtLoad(xy);
|
||||
#elif PS_REGION_RECT == 1
|
||||
return Texture.Load(int3(int2(uv), 0));
|
||||
#else
|
||||
@@ -591,7 +673,7 @@ float4x4 sample_4p(uint4 u)
|
||||
uint fetch_raw_depth(int2 xy)
|
||||
{
|
||||
#if PS_TEX_IS_FB == 1
|
||||
float4 col = RtTexture.Load(int3(xy, 0));
|
||||
float4 col = RtLoad(xy);
|
||||
#else
|
||||
float4 col = Texture.Load(int3(xy, 0));
|
||||
#endif
|
||||
@@ -601,7 +683,7 @@ uint fetch_raw_depth(int2 xy)
|
||||
float4 fetch_raw_color(int2 xy)
|
||||
{
|
||||
#if PS_TEX_IS_FB == 1
|
||||
return RtTexture.Load(int3(xy, 0));
|
||||
return RtLoad(xy);
|
||||
#else
|
||||
return Texture.Load(int3(xy, 0));
|
||||
#endif
|
||||
@@ -610,7 +692,7 @@ float4 fetch_raw_color(int2 xy)
|
||||
float4 fetch_c(int2 uv)
|
||||
{
|
||||
#if PS_TEX_IS_FB == 1
|
||||
return RtTexture.Load(int3(uv, 0));
|
||||
return RtLoad(uv);
|
||||
#else
|
||||
return Texture.Load(int3(uv, 0));
|
||||
#endif
|
||||
@@ -696,7 +778,7 @@ float4 sample_depth(float2 st, float2 pos)
|
||||
}
|
||||
else if (PS_DEPTH_FMT == 1)
|
||||
{
|
||||
// Based on ps_convert_float32_rgba8 of convert
|
||||
// Based on ps_convert_depth32_rgba8 of convert
|
||||
|
||||
// Convert a FLOAT32 depth texture into a RGBA color texture
|
||||
uint d = uint(fetch_c(uv).r * exp2(32.0f));
|
||||
@@ -704,7 +786,7 @@ float4 sample_depth(float2 st, float2 pos)
|
||||
}
|
||||
else if (PS_DEPTH_FMT == 2)
|
||||
{
|
||||
// Based on ps_convert_float16_rgb5a1 of convert
|
||||
// Based on ps_convert_depth16_rgb5a1 of convert
|
||||
|
||||
// Convert a FLOAT32 (only 16 lsb) depth into a RGB5A1 color texture
|
||||
uint d = uint(fetch_c(uv).r * exp2(32.0f));
|
||||
@@ -1016,7 +1098,7 @@ void ps_fbmask(inout float4 C, float2 pos_xy)
|
||||
if (PS_FBMASK)
|
||||
{
|
||||
float multi = PS_COLCLIP_HW ? 65535.0f : 255.0f;
|
||||
float4 RT = trunc(RtTexture.Load(int3(pos_xy, 0)) * multi + 0.1f);
|
||||
float4 RT = trunc(RtLoad(int2(pos_xy)) * multi + 0.1f);
|
||||
C = (float4)(((uint4)C & ~FbMask) | ((uint4)RT & FbMask));
|
||||
}
|
||||
}
|
||||
@@ -1092,7 +1174,7 @@ void ps_blend(inout float4 Color, inout float4 As_rgba, float2 pos_xy)
|
||||
As_rgba.rgb = (float3)1.0f;
|
||||
}
|
||||
|
||||
float4 RT = SW_BLEND_NEEDS_RT ? RtTexture.Load(int3(pos_xy, 0)) : (float4)0.0f;
|
||||
float4 RT = SW_BLEND_NEEDS_RT ? RtLoad(int2(pos_xy)) : (float4)0.0f;
|
||||
|
||||
if (PS_SHUFFLE && SW_BLEND_NEEDS_RT)
|
||||
{
|
||||
@@ -1225,24 +1307,63 @@ void ps_blend(inout float4 Color, inout float4 As_rgba, float2 pos_xy)
|
||||
}
|
||||
}
|
||||
|
||||
#if PS_ROV_EARLYDEPTHSTENCIL
|
||||
[earlydepthstencil]
|
||||
#endif
|
||||
|
||||
#if PS_ROV_COLOR || PS_ROV_DEPTH
|
||||
#define DISCARD { rov_discard_color = true; rov_discard_depth = true; }
|
||||
#define DISCARD_COLOR rov_discard_color = true
|
||||
#define DISCARD_DEPTH rov_discard_depth = true
|
||||
#else
|
||||
#define DISCARD discard
|
||||
#define DISCARD_COLOR o_col0 = RtLoad(input.p.xy)
|
||||
#define DISCARD_DEPTH input.p.z = DepthLoad(input.p.xy)
|
||||
#endif
|
||||
|
||||
#if (PS_RETURN_COLOR || PS_RETURN_DEPTH)
|
||||
PS_OUTPUT ps_main(PS_INPUT input)
|
||||
#else
|
||||
void ps_main(PS_INPUT input)
|
||||
#endif
|
||||
{
|
||||
// Must floor before depth testing.
|
||||
#if PS_ZFLOOR
|
||||
input.p.z = floor(input.p.z * exp2(32.0f)) * exp2(-32.0f);
|
||||
#endif
|
||||
|
||||
#if PS_ZTST == ZTST_GEQUAL
|
||||
if (input.p.z < DepthTexture.Load(int3(input.p.xy, 0)).r)
|
||||
discard;
|
||||
#elif PS_ZTST == ZTST_GREATER
|
||||
if (input.p.z <= DepthTexture.Load(int3(input.p.xy, 0)).r)
|
||||
discard;
|
||||
#if PS_ROV_COLOR
|
||||
rov_rt_value = RtTextureRov[input.p.xy];
|
||||
#endif
|
||||
|
||||
#if PS_ROV_DEPTH
|
||||
rov_depth_value = DepthTextureRov[input.p.xy];
|
||||
#endif
|
||||
|
||||
#if PS_ROV_COLOR || PS_ROV_DEPTH
|
||||
bool rov_discard_color = false;
|
||||
bool rov_discard_depth = false;
|
||||
#endif
|
||||
|
||||
// Use ROV discard macro for since we cannot do
|
||||
// conditional discard based on value read from ROV.
|
||||
#if PS_ZTST == ZTST_GEQUAL
|
||||
if (input.p.z < DepthLoad(input.p.xy))
|
||||
DISCARD;
|
||||
#elif PS_ZTST == ZTST_GREATER
|
||||
if (input.p.z <= DepthLoad(input.p.xy))
|
||||
DISCARD;
|
||||
#endif
|
||||
|
||||
float4 C = ps_color(input);
|
||||
|
||||
#if PS_AA1
|
||||
float cov = clamp(1.0f - abs(input.inv_cov), 0.0f, 1.0f);
|
||||
#if PS_AA1 == PS_AA1_LINE
|
||||
// Blur only outer part of the line by scaling coverage.
|
||||
float cov = clamp(LineCovScale * (1.0f - abs(input.inv_cov)), 0.0f, 1.0f);
|
||||
#else
|
||||
float cov = clamp(1.0f - abs(input.inv_cov), 0.0f, 1.0f);
|
||||
#endif
|
||||
#if PS_ABE
|
||||
if (floor(C.a) == 128.0f) // The coverage is only used if the fragment alpha is 128.
|
||||
C.a = 128.0f * cov;
|
||||
@@ -1256,13 +1377,11 @@ PS_OUTPUT ps_main(PS_INPUT input)
|
||||
|
||||
bool atst_pass = atst(C);
|
||||
|
||||
#if PS_AFAIL == AFAIL_KEEP
|
||||
#if PS_ATST != PS_ATST_NONE && PS_AFAIL == AFAIL_KEEP
|
||||
if (!atst_pass)
|
||||
discard;
|
||||
#endif
|
||||
|
||||
PS_OUTPUT output;
|
||||
|
||||
if (PS_SCANMSK & 2)
|
||||
{
|
||||
// fail depth test on prohibited lines
|
||||
@@ -1273,7 +1392,7 @@ PS_OUTPUT ps_main(PS_INPUT input)
|
||||
float4 alpha_blend = (float4)0.0f;
|
||||
if (SW_AD_TO_HW)
|
||||
{
|
||||
float4 RT = PS_RTA_CORRECTION ? trunc(RtTexture.Load(int3(input.p.xy, 0)) * 128.0f + 0.1f) : trunc(RtTexture.Load(int3(input.p.xy, 0)) * 255.0f + 0.1f);
|
||||
float4 RT = PS_RTA_CORRECTION ? trunc(RtLoad(input.p.xy) * 128.0f + 0.1f) : trunc(RtLoad(input.p.xy) * 255.0f + 0.1f);
|
||||
alpha_blend = (float4)(RT.a / 128.0f);
|
||||
}
|
||||
else
|
||||
@@ -1297,9 +1416,9 @@ PS_OUTPUT ps_main(PS_INPUT input)
|
||||
|
||||
#if PS_WRITE_RG == 1
|
||||
// Pseudo 16 bits access.
|
||||
float rt_a = RtTexture.Load(int3(input.p.xy, 0)).g;
|
||||
float rt_a = RtLoad(input.p.xy).g;
|
||||
#else
|
||||
float rt_a = RtTexture.Load(int3(input.p.xy, 0)).a;
|
||||
float rt_a = RtLoad(input.p.xy).a;
|
||||
#endif
|
||||
|
||||
#if (PS_DATE & 3) == 1
|
||||
@@ -1318,9 +1437,8 @@ PS_OUTPUT ps_main(PS_INPUT input)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (bad)
|
||||
discard;
|
||||
|
||||
if (bad)
|
||||
discard;
|
||||
#endif
|
||||
|
||||
#if PS_DATE == 3
|
||||
@@ -1331,17 +1449,29 @@ PS_OUTPUT ps_main(PS_INPUT input)
|
||||
discard;
|
||||
#endif
|
||||
|
||||
// Output values
|
||||
#if !PS_NO_COLOR
|
||||
#if PS_DATE == 1 || PS_DATE == 2
|
||||
float o_col0;
|
||||
#else
|
||||
float4 o_col0;
|
||||
#if !PS_NO_COLOR1
|
||||
float4 o_col1;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Get first primitive that will write a failling alpha value
|
||||
#if PS_DATE == 1
|
||||
// DATM == 0
|
||||
// Pixel with alpha equal to 1 will failed (128-255)
|
||||
output.c = (C.a > 127.5f) ? float(input.primid) : float(0x7FFFFFFF);
|
||||
o_col0 = (C.a > 127.5f) ? float(input.primid) : float(0x7FFFFFFF);
|
||||
|
||||
#elif PS_DATE == 2
|
||||
|
||||
// DATM == 1
|
||||
// Pixel with alpha equal to 0 will failed (0-127)
|
||||
output.c = (C.a < 127.5f) ? float(input.primid) : float(0x7FFFFFFF);
|
||||
o_col0 = (C.a < 127.5f) ? float(input.primid) : float(0x7FFFFFFF);
|
||||
|
||||
#else
|
||||
// Not primid DATE setup
|
||||
@@ -1416,32 +1546,32 @@ PS_OUTPUT ps_main(PS_INPUT input)
|
||||
alpha_blend.a = float(atst_pass);
|
||||
#endif
|
||||
|
||||
// Output color scaling
|
||||
#if !PS_NO_COLOR
|
||||
output.c0.a = PS_RTA_CORRECTION ? C.a / 128.0f : C.a / 255.0f;
|
||||
output.c0.rgb = PS_COLCLIP_HW ? float3(C.rgb / 65535.0f) : C.rgb / 255.0f;
|
||||
o_col0.a = PS_RTA_CORRECTION ? C.a / 128.0f : C.a / 255.0f;
|
||||
o_col0.rgb = PS_COLCLIP_HW ? float3(C.rgb / 65535.0f) : C.rgb / 255.0f;
|
||||
#if !PS_NO_COLOR1
|
||||
output.c1 = alpha_blend;
|
||||
o_col1 = alpha_blend;
|
||||
#endif
|
||||
#endif // !PS_NO_COLOR
|
||||
|
||||
// Alpha test with feedback
|
||||
#if PS_AFAIL == AFAIL_FB_ONLY
|
||||
if (!atst_pass)
|
||||
input.p.z = DepthTexture.Load(int3(input.p.xy, 0)).r;
|
||||
DISCARD_DEPTH;
|
||||
#elif PS_AFAIL == AFAIL_ZB_ONLY
|
||||
if (!atst_pass)
|
||||
output.c0 = RtTexture.Load(int3(input.p.xy, 0));
|
||||
DISCARD_COLOR;
|
||||
#elif PS_AFAIL == AFAIL_RGB_ONLY || PS_AFAIL == AFAIL_RGB_ONLY_SW_Z
|
||||
if (!atst_pass)
|
||||
{
|
||||
output.c0.a = RtTexture.Load(int3(input.p.xy, 0)).a;
|
||||
o_col0.a = RtLoad(input.p.xy).a; // discard alpha
|
||||
#if PS_AFAIL == AFAIL_RGB_ONLY_SW_Z
|
||||
input.p.z = DepthTexture.Load(int3(input.p.xy, 0)).r;
|
||||
DISCARD_DEPTH;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // !PS_NO_COLOR
|
||||
|
||||
#endif // PS_DATE != 1/2
|
||||
|
||||
#if PS_ZCLAMP
|
||||
@@ -1450,18 +1580,40 @@ PS_OUTPUT ps_main(PS_INPUT input)
|
||||
|
||||
#if PS_AA1 == PS_AA1_TRIANGLE_SW_Z
|
||||
if (!bool(input.interior))
|
||||
input.p.z = DepthTexture.Load(int3(input.p.xy, 0)).r; // No depth update for triangle edges.
|
||||
DISCARD_DEPTH; // No depth update for triangle edges.
|
||||
#endif
|
||||
|
||||
#if ZWRITE
|
||||
#if SW_DEPTH && PS_NO_COLOR1 && DX12
|
||||
// Output color clone for feedback as well as real depth.
|
||||
output.depth_color = input.p.z;
|
||||
#if (PS_RETURN_COLOR || PS_RETURN_DEPTH)
|
||||
PS_OUTPUT output;
|
||||
#endif
|
||||
|
||||
// Color write back
|
||||
#if PS_RETURN_COLOR
|
||||
output.c0 = o_col0;
|
||||
#if !PS_NO_COLOR1
|
||||
output.c1 = o_col1;
|
||||
#endif
|
||||
#elif PS_RETURN_COLOR_ROV
|
||||
o_col0 = (FbMask == 0xFFu) ? RtLoad(input.p.xy) : o_col0; // channel masking
|
||||
if (!rov_discard_color)
|
||||
RtWrite(input.p.xy, o_col0);
|
||||
#endif
|
||||
|
||||
// Depth write back
|
||||
#if PS_RETURN_DEPTH
|
||||
output.depth = input.p.z;
|
||||
#if SW_DEPTH && PS_NO_COLOR1 && PS_DEPTH_FEEDBACK_SUPPORT == 2
|
||||
// Output color clone for feedback.
|
||||
output.depth_color = input.p.z;
|
||||
#endif
|
||||
#elif PS_RETURN_DEPTH_ROV
|
||||
if (!rov_discard_depth)
|
||||
DepthWrite(input.p.xy, input.p.z);
|
||||
#endif
|
||||
|
||||
#if (PS_RETURN_COLOR || PS_RETURN_DEPTH)
|
||||
return output;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // PIXEL_SHADER
|
||||
@@ -1484,7 +1636,7 @@ cbuffer cb0
|
||||
float2 TextureOffset;
|
||||
float2 PointSize;
|
||||
uint MaxDepth;
|
||||
uint _cb0_pad0;
|
||||
float LineAA1Width;
|
||||
};
|
||||
|
||||
#ifdef DX12
|
||||
@@ -1594,6 +1746,110 @@ VS_INPUT load_vertex(uint index)
|
||||
return vert;
|
||||
}
|
||||
|
||||
// Convert XY from NDC to GS pixel coordinates (i.e. 1.0 = 1 GS pixel).
|
||||
float2 get_xy_unscaled(float2 xy)
|
||||
{
|
||||
return round(xy / VertexScale) / 16.0f;
|
||||
}
|
||||
|
||||
// Get the XY deltas in GS pixel coordinates, using first vertex as the origin.
|
||||
float2x2 get_xy_deltas_unscaled(VS_OUTPUT v0, VS_OUTPUT v1, VS_OUTPUT v2)
|
||||
{
|
||||
float2 xy0 = get_xy_unscaled(v0.p.xy);
|
||||
float2 xy1 = get_xy_unscaled(v1.p.xy);
|
||||
float2 xy2 = get_xy_unscaled(v2.p.xy);
|
||||
return float2x2(xy1 - xy0, xy2 - xy0);
|
||||
}
|
||||
|
||||
// Get the AA1 outward expand direction to the edge formed by the first two vertices.
|
||||
// This is up or down for shallow (X dominant) edges, and right or left for steep (Y dominant) edges.
|
||||
// Similar expansion to line AA1 except instead of expanding on both sides of the line,
|
||||
// expand on on the side towards the outside of the triangle.
|
||||
float2 get_aa1_triangle_expand_dir(VS_OUTPUT v0, VS_OUTPUT v1, VS_OUTPUT v2)
|
||||
{
|
||||
float2x2 xy_deltas = get_xy_deltas_unscaled(v0, v1, v2);
|
||||
float2 line_delta = xy_deltas[0];
|
||||
float2 line_opposite = xy_deltas[1];
|
||||
|
||||
float2 line_normal = float2(line_delta.y, -line_delta.x);
|
||||
float2 line_expand = abs(line_delta.x) >= abs(line_delta.y) ? float2(0.0f, 1.0f) : float2(1.0f, 0.0f);
|
||||
|
||||
if ((dot(line_expand, line_normal) >= 0.0f) == (dot(line_opposite, line_normal) >= 0.0f))
|
||||
{
|
||||
// Expand direction point towards the interior so flip it.
|
||||
line_expand = -line_expand;
|
||||
}
|
||||
|
||||
return line_expand;
|
||||
}
|
||||
|
||||
float2x2 get_inverse(float2x2 mat, float det)
|
||||
{
|
||||
return float2x2(mat[1][1], -mat[0][1], -mat[1][0], mat[0][0]) * (1 / det);
|
||||
}
|
||||
|
||||
// Extrapolate triangle attributes from the first vertex along the given direction.
|
||||
// dp_mat is derived from the input vertices, it is passed in to avoid recomputing.
|
||||
void extrapolate_aa1_triangle_edge(inout VS_OUTPUT v0, VS_OUTPUT v1, VS_OUTPUT v2, float2x2 dp_mat, float2 dp)
|
||||
{
|
||||
// Get texture deltas
|
||||
#if VS_TME
|
||||
#if VS_FST
|
||||
float2x2 dt = float2x2(v1.ti.zw - v0.ti.zw, v2.ti.zw - v0.ti.zw);
|
||||
#else
|
||||
float2x2 dt = float2x2(v1.t.xy - v0.t.xy, v2.t.xy - v0.t.xy);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Get color delta if interpolating
|
||||
#if VS_IIP
|
||||
float2x4 dc = float2x4(v1.c - v0.c, v2.c - v0.c);
|
||||
#endif
|
||||
|
||||
float2 dz = float2(v1.p.z - v0.p.z, v2.p.z - v0.p.z); // Z deltas
|
||||
|
||||
float2 df = float2(v1.t.z - v0.t.z, v2.t.z - v0.t.z); // Fog deltas
|
||||
|
||||
float2 dq = float2(v1.t.w - v0.t.w, v2.t.w - v0.t.w); // Q deltas
|
||||
|
||||
// To prevent unstable extrapolation, do not extrapolate if the
|
||||
// minimum perpendicular length of the triangle is < 2 pixels.
|
||||
float dp_det = determinant(dp_mat); // Twice signed triangle area.
|
||||
float len0 = length(dp_mat[0]);
|
||||
float len1 = length(dp_mat[1]);
|
||||
float len2 = length(dp_mat[1] - dp_mat[0]);
|
||||
float min_perp_length = abs(dp_det) / max(max(len0, len1), len2);
|
||||
|
||||
// Get the position -> barycentric weight matrix
|
||||
float2x2 inv_dp_mat = get_inverse(dp_mat, dp_det);
|
||||
|
||||
float2 weights = min_perp_length < 2 ? 0 : mul(dp, inv_dp_mat);
|
||||
|
||||
v0.p.xy += dp * PointSize; // Extrapolate position
|
||||
|
||||
// Extrapolate texture coords
|
||||
#if VS_TME
|
||||
#if VS_FST
|
||||
v0.ti.zw += mul(weights, dt);
|
||||
v0.ti.xy = v0.ti.zw * TextureScale;
|
||||
#else
|
||||
v0.t.xy += mul(weights, dt);
|
||||
v0.ti.zw = v0.t.xy / TextureScale;
|
||||
v0.t.w += dot(weights, dq);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Extrapolate and clamp color
|
||||
#if VS_IIP
|
||||
v0.c += mul(weights, dc);
|
||||
v0.c = clamp(v0.c, 0, 255);
|
||||
#endif
|
||||
|
||||
v0.p.z += dot(weights, dz); // Extrapolate depth
|
||||
|
||||
v0.t.z += dot(weights, df); // Extrapolate fog
|
||||
}
|
||||
|
||||
VS_OUTPUT vs_main_expand(uint vid : SV_VertexID)
|
||||
{
|
||||
#if VS_EXPAND == VS_EXPAND_POINT
|
||||
@@ -1622,13 +1878,10 @@ VS_OUTPUT vs_main_expand(uint vid : SV_VertexID)
|
||||
|
||||
// Use bottom minus top for delta regardless of which vertex we are expanding.
|
||||
float2 line_delta = is_bottom ? (vtx.p.xy - other.p.xy) : (other.p.xy - vtx.p.xy);
|
||||
float2 line_vector = normalize(line_delta);
|
||||
#if VS_EXPAND == VS_EXPAND_LINE
|
||||
float2 line_vector = normalize(line_delta / VertexScale);
|
||||
float2 line_expand = float2(line_vector.y, -line_vector.x);
|
||||
#elif VS_EXPAND == VS_EXPAND_LINE_AA1
|
||||
// Expand in y direction for shallow lines and x direction for steep lines.
|
||||
line_delta /= VertexScale;
|
||||
float2 line_expand = abs(line_delta.x) >= abs(line_delta.y) ? float2(0.0f, 2.0f) : float2(2.0f, 0.0f);
|
||||
#if VS_EXPAND == VS_EXPAND_LINE_AA1
|
||||
line_expand *= 2.0f * LineAA1Width;
|
||||
#endif
|
||||
float2 line_width = (line_expand * PointSize) / 2;
|
||||
float2 offset = is_right ? line_width : -line_width;
|
||||
@@ -1674,10 +1927,14 @@ VS_OUTPUT vs_main_expand(uint vid : SV_VertexID)
|
||||
// - Vertices 3-8: First edge expanded (2 triangles).
|
||||
// - Vertices 9-14: Second edge expanded (2 triangles).
|
||||
// - Vertices 15-20: Third edge expanded (2 triangles).
|
||||
// - Vertices 21-26: First corner cap (2 triangles).
|
||||
// - Vertices 27-32: Second corner cap (2 triangles).
|
||||
// - Vertices 33-38: Third corner cap (2 triangles).
|
||||
|
||||
uint prim_id = vid / 21;
|
||||
uint prim_offset = vid - 21 * prim_id; // range: 0-20
|
||||
uint prim_id = vid / 39;
|
||||
uint prim_offset = vid - 39 * prim_id; // range: 0-38
|
||||
bool interior = prim_offset < 3;
|
||||
bool edge = 3 <= prim_offset && prim_offset < 21;
|
||||
|
||||
VS_OUTPUT vtx;
|
||||
if (interior)
|
||||
@@ -1686,7 +1943,7 @@ VS_OUTPUT vs_main_expand(uint vid : SV_VertexID)
|
||||
vtx.inv_cov = 0.0f; // Full coverage
|
||||
vtx.interior = 1;
|
||||
}
|
||||
else
|
||||
else if (edge)
|
||||
{
|
||||
// Vertex indices for this edge. We need all 3 for determining exterior/interior.
|
||||
uint prim_offset_edges = prim_offset - 3; // range: 0-17
|
||||
@@ -1695,45 +1952,68 @@ VS_OUTPUT vs_main_expand(uint vid : SV_VertexID)
|
||||
uint i2 = (i0 >= 1) ? i0 - 1 : i0 + 2;
|
||||
uint edge_offset = prim_offset_edges - 6 * i0; // range: 0-5
|
||||
|
||||
// Note: order of top/bottom, inside/outside order is arbitrary,
|
||||
// Note: order of top/bottom, inside/outside is arbitrary,
|
||||
// as long as it assembles into two triangles forming a quad.
|
||||
bool is_bottom = (2 <= edge_offset) && (edge_offset <= 4);
|
||||
bool is_outside = edge_offset & 1;
|
||||
|
||||
vtx = vs_main(load_vertex(load_index(3 * prim_id + i0)));
|
||||
VS_OUTPUT other = vs_main(load_vertex(load_index(3 * prim_id + i1)));
|
||||
vtx = vs_main(load_vertex(load_index(3 * prim_id + (is_bottom ? i1 : i0))));
|
||||
VS_OUTPUT other = vs_main(load_vertex(load_index(3 * prim_id + (is_bottom ? i0 : i1))));
|
||||
VS_OUTPUT opposite = vs_main(load_vertex(load_index(3 * prim_id + i2)));
|
||||
|
||||
// Similar expansion to line AA1 except instead of expanding on both sides of
|
||||
// the line we expand on on the side towards the outside of the triangle.
|
||||
float2 line_delta = vtx.p.xy - other.p.xy;
|
||||
float2 line_normal = normalize(float2(line_delta.y, -line_delta.x));
|
||||
float2 line_expand = abs(line_delta.x) >= abs(line_delta.y) ? float2(0.0f, 2.0f) : float2(2.0f, 0.0f);
|
||||
if ((dot(line_expand, line_normal) >= 0.0f) == (dot(opposite.p.xy - vtx.p.xy, line_normal) >= 0.0f))
|
||||
{
|
||||
// Expand direction point towards the interior so flip it.
|
||||
line_expand = -line_expand;
|
||||
}
|
||||
float2 line_width = (line_expand * PointSize) / 2;
|
||||
float2x2 pos_deltas = get_xy_deltas_unscaled(vtx, other, opposite);
|
||||
|
||||
if (is_bottom)
|
||||
vtx = other;
|
||||
if (is_outside)
|
||||
{
|
||||
vtx.p.xy += line_width;
|
||||
vtx.inv_cov = 1.0f; // No coverage
|
||||
}
|
||||
else
|
||||
{
|
||||
vtx.inv_cov = 0.0f; // Full coverage
|
||||
}
|
||||
float2 expand_dir = is_outside ? get_aa1_triangle_expand_dir(vtx, other, opposite) : 0;
|
||||
|
||||
// Do actual extrapolation, or no-op if expand_dir == 0.
|
||||
extrapolate_aa1_triangle_edge(vtx, other, opposite, pos_deltas, expand_dir);
|
||||
|
||||
vtx.inv_cov = is_outside ? 1.0f : 0.0f; // No coverage on outside, otherwise full.
|
||||
|
||||
vtx.interior = 0;
|
||||
}
|
||||
else // Corner cap
|
||||
{
|
||||
// Vertex indices for this cap. We need all 3 for determining exterior/interior.
|
||||
uint prim_offset_cap = prim_offset - 21; // range: 0-8
|
||||
uint i0 = prim_offset_cap / 6;
|
||||
uint i1 = (i0 >= 2) ? i0 - 2 : i0 + 1;
|
||||
uint i2 = (i0 >= 1) ? i0 - 1 : i0 + 2;
|
||||
uint cap_offset = prim_offset_cap - 6 * i0; // range: 0-5
|
||||
|
||||
#if !VS_IIP
|
||||
// Get the provoking vertex color (first vertex in DX)
|
||||
vtx.c = i0 == 0 ? vtx.c : (i1 == 0 ? other.c : opposite.c);
|
||||
#endif
|
||||
bool is_near_corner = cap_offset == 0 || cap_offset == 3;
|
||||
bool is_far_corner = cap_offset == 2 || cap_offset == 5;
|
||||
bool is_first_tri = cap_offset < 3;
|
||||
|
||||
vtx = vs_main(load_vertex(load_index(3 * prim_id + i0)));
|
||||
VS_OUTPUT other = vs_main(load_vertex(load_index(3 * prim_id + (is_first_tri ? i1 : i2))));
|
||||
VS_OUTPUT opposite = vs_main(load_vertex(load_index(3 * prim_id + (is_first_tri ? i2 : i1))));
|
||||
|
||||
float2x2 pos_deltas = get_xy_deltas_unscaled(vtx, other, opposite);
|
||||
|
||||
// Get the edge expansion directions of both incident edges.
|
||||
float2 edge_expand_dir_0 = get_aa1_triangle_expand_dir(vtx, other, opposite);
|
||||
float2 edge_expand_dir_1 = get_aa1_triangle_expand_dir(vtx, opposite, other);
|
||||
|
||||
// Check if the corner is already filled by the expanded edges.
|
||||
// This happens if the expand directions are the same.
|
||||
// If so we output a degenerate triangle at this corner.
|
||||
bool corner_filled = all(edge_expand_dir_0 == edge_expand_dir_1);
|
||||
|
||||
// Nothing if corner is filled, otherwise opposite to the bisector of the corner angle.
|
||||
float2 far_corner_dir = corner_filled ? 0 : -normalize((pos_deltas[0] + pos_deltas[1]) / 2);
|
||||
|
||||
// Determine the expand direction.
|
||||
float2 expand_dir = is_near_corner ? 0 : // No extrapolation
|
||||
is_far_corner ? far_corner_dir : // Opposite to the angle bisector of corner
|
||||
edge_expand_dir_0; // Standard AA1 edge expansion
|
||||
|
||||
// Do the actual extrapolation (no-op if expand_dir == 0).
|
||||
extrapolate_aa1_triangle_edge(vtx, other, opposite, pos_deltas, expand_dir);
|
||||
|
||||
vtx.inv_cov = is_near_corner ? 0.0f : 1.0f; // Full coverage at near corner, otherwise none.
|
||||
|
||||
vtx.interior = 0;
|
||||
}
|
||||
|
||||
return vtx;
|
||||
|
||||
@@ -3,21 +3,12 @@
|
||||
|
||||
//#version 420 // Keep it for editor detection
|
||||
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout(location = 0) in vec2 POSITION;
|
||||
layout(location = 1) in vec2 TEXCOORD0;
|
||||
layout(location = 7) in vec4 COLOR;
|
||||
|
||||
// FIXME set the interpolation (don't know what dx do)
|
||||
// flat means that there is no interpolation. The value given to the fragment shader is based on the provoking vertex conventions.
|
||||
//
|
||||
// noperspective means that there will be linear interpolation in window-space. This is usually not what you want, but it can have its uses.
|
||||
//
|
||||
// smooth, the default, means to do perspective-correct interpolation.
|
||||
//
|
||||
// The centroid qualifier only matters when multisampling. If this qualifier is not present, then the value is interpolated to the pixel's center, anywhere in the pixel, or to one of the pixel's samples. This sample may lie outside of the actual primitive being rendered, since a primitive can cover only part of a pixel's area. The centroid qualifier is used to prevent this; the interpolation point must fall within both the pixel's area and the primitive's area.
|
||||
out vec4 PSin_p;
|
||||
out vec2 PSin_t;
|
||||
out vec4 PSin_c;
|
||||
@@ -40,31 +31,125 @@ in vec4 PSin_c;
|
||||
|
||||
layout(binding = 0) uniform sampler2D TextureSampler;
|
||||
|
||||
// Give a different name so I remember there is a special case!
|
||||
#if defined(ps_convert_rgba8_16bits) || defined(ps_convert_float32_32bits)
|
||||
layout(location = 0) out uint SV_Target1;
|
||||
#elif defined(ps_convert_float32_depth_to_color)
|
||||
layout(location = 0) out float SV_Target0;
|
||||
#if HAS_INTEGER_OUTPUT
|
||||
layout(location = 0) out uint o_col0;
|
||||
#define OUTPUT o_col0
|
||||
#elif HAS_DEPTH_OUTPUT
|
||||
out float gl_FragDepth;
|
||||
#define OUTPUT gl_FragDepth
|
||||
#elif HAS_FLOAT32_OUTPUT
|
||||
layout(location = 0) out float o_col0;
|
||||
#define OUTPUT o_col0
|
||||
#elif HAS_STENCIL_OUTPUT
|
||||
#else
|
||||
layout(location = 0) out vec4 SV_Target0;
|
||||
layout(location = 0) out vec4 o_col0;
|
||||
#define OUTPUT o_col0
|
||||
#endif
|
||||
|
||||
#if HAS_FLOAT32_INPUT
|
||||
|
||||
float sample_c()
|
||||
{
|
||||
return texture(TextureSampler, PSin_t).r;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
vec4 sample_c()
|
||||
{
|
||||
return texture(TextureSampler, PSin_t);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
uint rgba8_to_uint(vec4 c)
|
||||
{
|
||||
uvec4 i = uvec4(c * 255.5f) & 0xFFu;
|
||||
return i.r | (i.g << 8) | (i.b << 16) | (i.a << 24);
|
||||
}
|
||||
|
||||
uint rgb5a1_to_uint(vec4 c)
|
||||
{
|
||||
uvec4 i = uvec4(c * 255.5f) & uvec4(0xF8u, 0xF8u, 0xF8u, 0x80u);
|
||||
return (i.r >> 3) | (i.g << 2) | (i.b << 7) | (i.a << 8);
|
||||
}
|
||||
|
||||
uint depth_to_uint(float d)
|
||||
{
|
||||
return uint(d * exp2(32.0f));
|
||||
}
|
||||
|
||||
vec4 uint_to_rgba8(uint i)
|
||||
{
|
||||
return vec4((i & 0xFFu), ((i >> 8) & 0xFFu), ((i >> 16) & 0xFFu), ((i >> 24) & 0xFFu)) / 255.0f;
|
||||
}
|
||||
|
||||
vec4 uint_to_rgb5a1(uint i)
|
||||
{
|
||||
return vec4(uvec4(i << 3, i >> 2, i >> 7, i >> 8) & uvec4(0xF8u, 0xF8u, 0xF8u, 0x80u)) / 255.0f;
|
||||
}
|
||||
|
||||
float uint_to_depth32(uint i)
|
||||
{
|
||||
return float(i) * exp2(-32.0f);
|
||||
}
|
||||
|
||||
float uint_to_depth24(uint i)
|
||||
{
|
||||
return float(i & 0xFFFFFFu) * exp2(-32.0f);
|
||||
}
|
||||
|
||||
float uint_to_depth16(uint i)
|
||||
{
|
||||
return float(i & 0xFFFFu) * exp2(-32.0f);
|
||||
}
|
||||
|
||||
float rgba8_to_depth32(vec4 val)
|
||||
{
|
||||
return uint_to_depth32(rgba8_to_uint(val));
|
||||
}
|
||||
|
||||
float rgba8_to_depth24(vec4 val)
|
||||
{
|
||||
return uint_to_depth24(rgba8_to_uint(val));
|
||||
}
|
||||
|
||||
float rgba8_to_depth16(vec4 val)
|
||||
{
|
||||
return uint_to_depth16(rgba8_to_uint(val));
|
||||
}
|
||||
|
||||
float rgb5a1_to_depth16(vec4 val)
|
||||
{
|
||||
return uint_to_depth16(rgb5a1_to_uint(val));
|
||||
}
|
||||
|
||||
vec4 depth32_to_rgba8(float d)
|
||||
{
|
||||
return uint_to_rgba8(depth_to_uint(d));
|
||||
}
|
||||
|
||||
vec4 depth16_to_rgb5a1(float d)
|
||||
{
|
||||
return uint_to_rgb5a1(depth_to_uint(d));
|
||||
}
|
||||
|
||||
float depth32_to_depth24(float d)
|
||||
{
|
||||
return uint_to_depth24(depth_to_uint(d));
|
||||
}
|
||||
|
||||
#ifdef ps_copy
|
||||
void ps_copy()
|
||||
{
|
||||
SV_Target0 = sample_c();
|
||||
OUTPUT = sample_c();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_depth_copy
|
||||
void ps_depth_copy()
|
||||
{
|
||||
gl_FragDepth = sample_c().r;
|
||||
OUTPUT = sample_c();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -83,126 +168,47 @@ void ps_downsample_copy()
|
||||
for (int xoff = 0; xoff < DownsampleFactor; xoff++)
|
||||
result += texelFetch(TextureSampler, coord + ivec2(xoff * StepMultiplier, yoff * StepMultiplier), 0);
|
||||
}
|
||||
SV_Target0 = result / Weight;
|
||||
o_col0 = result / Weight;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba8_16bits
|
||||
// Need to be careful with precision here, it can break games like Spider-Man 3 and Dogs Life
|
||||
void ps_convert_rgba8_16bits()
|
||||
#ifdef ps_convert_rgb5a1_16bits
|
||||
void ps_convert_rgb5a1_16bits()
|
||||
{
|
||||
highp uvec4 i = uvec4(sample_c() * vec4(255.5f, 255.5f, 255.5f, 255.5f));
|
||||
|
||||
SV_Target1 = ((i.x & 0x00F8u) >> 3) | ((i.y & 0x00F8u) << 2) | ((i.z & 0x00f8u) << 7) | ((i.w & 0x80u) << 8);
|
||||
// Need to be careful with precision here, it can break games like Spider-Man 3 and Dogs Life
|
||||
OUTPUT = rgb5a1_to_uint(sample_c());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_float32_32bits
|
||||
void ps_convert_float32_32bits()
|
||||
#ifdef ps_convert_depth32_32bits
|
||||
void ps_convert_depth32_32bits()
|
||||
{
|
||||
// Convert a GL_FLOAT32 depth texture into a 32 bits UINT texture
|
||||
SV_Target1 = uint(exp2(32.0f) * sample_c().r);
|
||||
OUTPUT = depth_to_uint(sample_c());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_float32_rgba8
|
||||
void ps_convert_float32_rgba8()
|
||||
#ifdef ps_convert_depth32_rgba8
|
||||
void ps_convert_depth32_rgba8()
|
||||
{
|
||||
// Convert a GL_FLOAT32 depth texture into a RGBA color texture
|
||||
uint d = uint(sample_c().r * exp2(32.0f));
|
||||
SV_Target0 = vec4(uvec4((d & 0xFFu), ((d >> 8) & 0xFFu), ((d >> 16) & 0xFFu), (d >> 24))) / vec4(255.0);
|
||||
OUTPUT = depth32_to_rgba8(sample_c());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_float16_rgb5a1
|
||||
void ps_convert_float16_rgb5a1()
|
||||
#ifdef ps_convert_depth16_rgb5a1
|
||||
void ps_convert_depth16_rgb5a1()
|
||||
{
|
||||
// Convert a GL_FLOAT32 (only 16 lsb) depth into a RGB5A1 color texture
|
||||
uint d = uint(sample_c().r * exp2(32.0f));
|
||||
SV_Target0 = vec4(uvec4(d << 3, d >> 2, d >> 7, d >> 8) & uvec4(0xf8, 0xf8, 0xf8, 0x80)) / 255.0f;
|
||||
OUTPUT = depth16_to_rgb5a1(sample_c());
|
||||
}
|
||||
#endif
|
||||
|
||||
float rgba8_to_depth32(vec4 unorm)
|
||||
{
|
||||
uvec4 c = uvec4(unorm * vec4(255.5f));
|
||||
return float(c.r | (c.g << 8) | (c.b << 16) | (c.a << 24)) * exp2(-32.0f);
|
||||
}
|
||||
|
||||
float rgba8_to_depth24(vec4 unorm)
|
||||
{
|
||||
uvec3 c = uvec3(unorm.rgb * vec3(255.5f));
|
||||
return float(c.r | (c.g << 8) | (c.b << 16)) * exp2(-32.0f);
|
||||
}
|
||||
|
||||
float rgba8_to_depth16(vec4 unorm)
|
||||
{
|
||||
uvec2 c = uvec2(unorm.rg * vec2(255.5f));
|
||||
return float(c.r | (c.g << 8)) * exp2(-32.0f);
|
||||
}
|
||||
|
||||
float rgb5a1_to_depth16(vec4 unorm)
|
||||
{
|
||||
uvec4 c = uvec4(unorm * vec4(255.5f));
|
||||
return float(((c.r & 0xF8u) >> 3) | ((c.g & 0xF8u) << 2) | ((c.b & 0xF8u) << 7) | ((c.a & 0x80u) << 8)) * exp2(-32.0f);
|
||||
}
|
||||
|
||||
#ifdef ps_convert_float32_depth_to_color
|
||||
void ps_convert_float32_depth_to_color()
|
||||
{
|
||||
SV_Target0 = sample_c().r;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_float32_color_to_depth
|
||||
void ps_convert_float32_color_to_depth()
|
||||
{
|
||||
gl_FragDepth = sample_c().r;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_float32_float24
|
||||
void ps_convert_float32_float24()
|
||||
#ifdef ps_convert_depth32_depth24
|
||||
void ps_convert_depth32_depth24()
|
||||
{
|
||||
// Truncates depth value to 24bits
|
||||
uint d = uint(sample_c().r * exp2(32.0f)) & 0xFFFFFFu;
|
||||
gl_FragDepth = float(d) * exp2(-32.0f);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba8_float32
|
||||
void ps_convert_rgba8_float32()
|
||||
{
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
gl_FragDepth = rgba8_to_depth32(sample_c());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba8_float24
|
||||
void ps_convert_rgba8_float24()
|
||||
{
|
||||
// Same as above but without the alpha channel (24 bits Z)
|
||||
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
gl_FragDepth = rgba8_to_depth24(sample_c());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba8_float16
|
||||
void ps_convert_rgba8_float16()
|
||||
{
|
||||
// Same as above but without the A/B channels (16 bits Z)
|
||||
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
gl_FragDepth = rgba8_to_depth16(sample_c());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgb5a1_float16
|
||||
void ps_convert_rgb5a1_float16()
|
||||
{
|
||||
// Convert an RGB5A1 (saved as RGBA8) color to a 16 bit Z
|
||||
gl_FragDepth = rgb5a1_to_depth16(sample_c());
|
||||
OUTPUT = depth32_to_depth24(sample_c());
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -216,41 +222,55 @@ void ps_convert_rgb5a1_float16()
|
||||
float depthTR = CONVERT_FN(texelFetch(TextureSampler, coords.zy, 0)); \
|
||||
float depthBL = CONVERT_FN(texelFetch(TextureSampler, coords.xw, 0)); \
|
||||
float depthBR = CONVERT_FN(texelFetch(TextureSampler, coords.zw, 0)); \
|
||||
gl_FragDepth = mix(mix(depthTL, depthTR, mix_vals.x), mix(depthBL, depthBR, mix_vals.x), mix_vals.y);
|
||||
OUTPUT = mix(mix(depthTL, depthTR, mix_vals.x), mix(depthBL, depthBR, mix_vals.x), mix_vals.y);
|
||||
|
||||
#ifdef ps_convert_rgba8_float32_biln
|
||||
void ps_convert_rgba8_float32_biln()
|
||||
#ifdef ps_convert_rgba8_depth32
|
||||
void ps_convert_rgba8_depth32()
|
||||
{
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
#if HAS_BILN
|
||||
SAMPLE_RGBA_DEPTH_BILN(rgba8_to_depth32);
|
||||
#else
|
||||
OUTPUT = rgba8_to_depth32(sample_c());
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba8_float24_biln
|
||||
void ps_convert_rgba8_float24_biln()
|
||||
#ifdef ps_convert_rgba8_depth24
|
||||
void ps_convert_rgba8_depth24()
|
||||
{
|
||||
// Same as above but without the alpha channel (24 bits Z)
|
||||
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
#if HAS_BILN
|
||||
SAMPLE_RGBA_DEPTH_BILN(rgba8_to_depth24);
|
||||
#else
|
||||
OUTPUT = rgba8_to_depth24(sample_c());
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba8_float16_biln
|
||||
void ps_convert_rgba8_float16_biln()
|
||||
#ifdef ps_convert_rgba8_depth16
|
||||
void ps_convert_rgba8_depth16()
|
||||
{
|
||||
// Same as above but without the A/B channels (16 bits Z)
|
||||
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
#if HAS_BILN
|
||||
SAMPLE_RGBA_DEPTH_BILN(rgba8_to_depth16);
|
||||
#else
|
||||
OUTPUT = rgba8_to_depth16(sample_c());
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgb5a1_float16_biln
|
||||
void ps_convert_rgb5a1_float16_biln()
|
||||
#ifdef ps_convert_rgb5a1_depth16
|
||||
void ps_convert_rgb5a1_depth16()
|
||||
{
|
||||
// Convert an RGB5A1 (saved as RGBA8) color to a 16 bit Z
|
||||
#if HAS_BILN
|
||||
SAMPLE_RGBA_DEPTH_BILN(rgb5a1_to_depth16);
|
||||
#else
|
||||
OUTPUT = rgb5a1_to_depth16(sample_c());
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -360,7 +380,7 @@ void ps_convert_rgb5a1_8i()
|
||||
uint red = (denorm_c.r >> 3) & 0x1Fu;
|
||||
uint green = (denorm_c.g >> 3) & 0x1Fu;
|
||||
|
||||
SV_Target0 = vec4(float(((green << 5) | red) & 0xFFu) / 255.0f);
|
||||
o_col0 = vec4(float(((green << 5) | red) & 0xFFu) / 255.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -368,7 +388,7 @@ void ps_convert_rgb5a1_8i()
|
||||
uint blue = (denorm_c.b >> 3) & 0x1Fu;
|
||||
uint alpha = denorm_c.a & 0x80u;
|
||||
|
||||
SV_Target0 = vec4(float((alpha | (blue << 2) | (green >> 3)) & 0xFFu) / 255.0f);
|
||||
o_col0 = vec4(float((alpha | (blue << 2) | (green >> 3)) & 0xFFu) / 255.0f);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -417,7 +437,7 @@ void ps_convert_rgba_8i()
|
||||
vec4 pixel = texelFetch(TextureSampler, ivec2(coord), 0);
|
||||
vec2 sel0 = (pos.y & 2u) == 0u ? pixel.rb : pixel.ga;
|
||||
float sel1 = (pos.x & 8u) == 0u ? sel0.x : sel0.y;
|
||||
SV_Target0 = vec4(sel1);
|
||||
o_col0 = vec4(sel1);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -425,7 +445,7 @@ void ps_convert_rgba_8i()
|
||||
void ps_filter_transparency()
|
||||
{
|
||||
vec4 c = sample_c();
|
||||
SV_Target0 = vec4(c.rgb, 1.0);
|
||||
o_col0 = vec4(c.rgb, 1.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -473,7 +493,7 @@ void ps_datm0_rta_correction()
|
||||
void ps_rta_correction()
|
||||
{
|
||||
vec4 value = sample_c();
|
||||
SV_Target0 = vec4(value.rgb, value.a / (128.25f / 255.0f));
|
||||
o_col0 = vec4(value.rgb, value.a / (128.25f / 255.0f));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -481,7 +501,7 @@ void ps_rta_correction()
|
||||
void ps_rta_decorrection()
|
||||
{
|
||||
vec4 value = sample_c();
|
||||
SV_Target0 = vec4(value.rgb, value.a * (128.25f / 255.0f));
|
||||
o_col0 = vec4(value.rgb, value.a * (128.25f / 255.0f));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -489,7 +509,7 @@ void ps_rta_decorrection()
|
||||
void ps_colclip_init()
|
||||
{
|
||||
vec4 value = sample_c();
|
||||
SV_Target0 = vec4(round(value.rgb * 255.0f) / 65535.0f, value.a);
|
||||
o_col0 = vec4(round(value.rgb * 255.0f) / 65535.0f, value.a);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -497,7 +517,7 @@ void ps_colclip_init()
|
||||
void ps_colclip_resolve()
|
||||
{
|
||||
vec4 value = sample_c();
|
||||
SV_Target0 = vec4(vec3(uvec3(value.rgb * 65535.0f) & 255u) / 255.0f, value.a);
|
||||
o_col0 = vec4(vec3(uvec3(value.rgb * 65535.0f) & 255u) / 255.0f, value.a);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -512,7 +532,7 @@ void ps_convert_clut_4()
|
||||
uvec2 pos = uvec2(index % 8u, index / 8u);
|
||||
|
||||
ivec2 final = ivec2(floor(vec2(offset.xy + pos) * vec2(scale)));
|
||||
SV_Target0 = texelFetch(TextureSampler, final, 0);
|
||||
o_col0 = texelFetch(TextureSampler, final, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -532,7 +552,7 @@ void ps_convert_clut_8()
|
||||
pos.y = ((index / 32u) * 2u) + (subgroup % 2u);
|
||||
|
||||
ivec2 final = ivec2(floor(vec2(offset.xy + pos) * vec2(scale)));
|
||||
SV_Target0 = texelFetch(TextureSampler, final, 0);
|
||||
o_col0 = texelFetch(TextureSampler, final, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -587,31 +607,31 @@ void ps_yuv()
|
||||
break;
|
||||
}
|
||||
|
||||
SV_Target0 = o;
|
||||
o_col0 = o;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(ps_stencil_image_init_0) || defined(ps_stencil_image_init_1) || defined(ps_stencil_image_init_2) || defined(ps_stencil_image_init_3)
|
||||
#if defined(ps_primid_image_init_0) || defined(ps_primid_image_init_1) || defined(ps_primid_image_init_2) || defined(ps_primid_image_init_3)
|
||||
|
||||
void main()
|
||||
{
|
||||
SV_Target0 = vec4(0x7FFFFFFF);
|
||||
o_col0 = vec4(0x7FFFFFFF);
|
||||
|
||||
#ifdef ps_stencil_image_init_0
|
||||
#ifdef ps_primid_image_init_0
|
||||
if((127.5f / 255.0f) < sample_c().a) // < 0x80 pass (== 0x80 should not pass)
|
||||
SV_Target0 = vec4(-1);
|
||||
o_col0 = vec4(-1);
|
||||
#endif
|
||||
#ifdef ps_stencil_image_init_1
|
||||
#ifdef ps_primid_image_init_1
|
||||
if(sample_c().a < (127.5f / 255.0f)) // >= 0x80 pass
|
||||
SV_Target0 = vec4(-1);
|
||||
o_col0 = vec4(-1);
|
||||
#endif
|
||||
#ifdef ps_stencil_image_init_2
|
||||
#ifdef ps_primid_image_init_2
|
||||
if((254.5f / 255.0f) < sample_c().a) // < 0x80 pass (== 0x80 should not pass)
|
||||
SV_Target0 = vec4(-1);
|
||||
o_col0 = vec4(-1);
|
||||
#endif
|
||||
#ifdef ps_stencil_image_init_3
|
||||
#ifdef ps_primid_image_init_3
|
||||
if(sample_c().a < (254.5f / 255.0f)) // >= 0x80 pass
|
||||
SV_Target0 = vec4(-1);
|
||||
o_col0 = vec4(-1);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -54,12 +54,12 @@
|
||||
#define SW_AD_TO_HW (PS_BLEND_C == 1 && PS_A_MASKED)
|
||||
#define PS_PRIMID_INIT (PS_DATE == 1 || PS_DATE == 2)
|
||||
#define NEEDS_RT_EARLY (PS_TEX_IS_FB == 1 || PS_DATE >= 5)
|
||||
#define NEEDS_RT_FOR_AFAIL (PS_AFAIL == PS_ZB_ONLY || PS_AFAIL == AFAIL_RGB_ONLY || PS_AFAIL == AFAIL_RGB_ONLY_SW_Z)
|
||||
#define NEEDS_RT_FOR_AFAIL (PS_AFAIL == AFAIL_ZB_ONLY || PS_AFAIL == AFAIL_RGB_ONLY || PS_AFAIL == AFAIL_RGB_ONLY_SW_Z)
|
||||
#define NEEDS_DEPTH_FOR_AFAIL (PS_AFAIL == AFAIL_FB_ONLY || PS_AFAIL == AFAIL_RGB_ONLY_SW_Z)
|
||||
#define NEEDS_DEPTH_FOR_ZTST (PS_ZTST == ZTST_GEQUAL || PS_ZTST == ZTST_GREATER)
|
||||
#define NEEDS_DEPTH_FOR_AA1 (PS_AA1 == PS_AA1_TRIANGLE_SW_Z)
|
||||
|
||||
#define NEEDS_RT (NEEDS_RT_EARLY || NEEDS_RT_FOR_AFAIL || (!PS_PRIMID_INIT && (PS_FBMASK || SW_BLEND_NEEDS_RT || SW_AD_TO_HW)) || PS_COLOR_FEEDBACK)
|
||||
#define NEEDS_RT (NEEDS_RT_EARLY || NEEDS_RT_FOR_AFAIL || (!PS_PRIMID_INIT && (PS_FBMASK || SW_BLEND_NEEDS_RT || SW_AD_TO_HW)))
|
||||
#define NEEDS_TEX (PS_TFX != 4)
|
||||
#define SW_DEPTH (NEEDS_DEPTH_FOR_AFAIL || NEEDS_DEPTH_FOR_ZTST || NEEDS_DEPTH_FOR_AA1)
|
||||
#define ZWRITE (SW_DEPTH || PS_ZCLAMP || PS_ZFLOOR)
|
||||
@@ -93,6 +93,13 @@ layout(std140, binding = 0) uniform cb21
|
||||
|
||||
float ScaledScaleFactor;
|
||||
float RcpScaleFactor;
|
||||
float _pad0_cb1;
|
||||
float _pad1_cb1;
|
||||
|
||||
float LineCovScale;
|
||||
float _pad2_cb1;
|
||||
float _pad3_cb1;
|
||||
float _pad4_cb1;
|
||||
};
|
||||
|
||||
in SHADER
|
||||
@@ -121,7 +128,7 @@ in SHADER
|
||||
#if defined(GL_EXT_shader_framebuffer_fetch)
|
||||
#undef TARGET_0_QUALIFIER
|
||||
#define TARGET_0_QUALIFIER inout
|
||||
#define LAST_FRAG_COLOR SV_Target0
|
||||
#define LAST_FRAG_COLOR o_col0
|
||||
#elif defined(GL_ARM_shader_framebuffer_fetch)
|
||||
#define LAST_FRAG_COLOR gl_LastFragColorARM
|
||||
#endif
|
||||
@@ -129,20 +136,20 @@ in SHADER
|
||||
|
||||
#if !PS_NO_COLOR && !PS_NO_COLOR1
|
||||
// Same buffer but 2 colors for dual source blending
|
||||
layout(location = 0, index = 0) TARGET_0_QUALIFIER vec4 SV_Target0;
|
||||
layout(location = 0, index = 1) out vec4 SV_Target1;
|
||||
layout(location = 0, index = 0) TARGET_0_QUALIFIER vec4 o_col0;
|
||||
layout(location = 0, index = 1) out vec4 o_col1;
|
||||
#elif !PS_NO_COLOR
|
||||
layout(location = 0) TARGET_0_QUALIFIER vec4 SV_Target0;
|
||||
layout(location = 0) TARGET_0_QUALIFIER vec4 o_col0;
|
||||
#endif
|
||||
|
||||
// Depth feedback mode 2 is for depth as color.
|
||||
// Use FB fetch for the feedback if it's available.
|
||||
#if SW_DEPTH && PS_NO_COLOR1 && (DEPTH_FEEDBACK_SUPPORT == 2)
|
||||
#if HAS_FRAMEBUFFER_FETCH
|
||||
layout(location = 1) inout float SV_Target1;
|
||||
#else
|
||||
layout(location = 1) out float SV_Target1;
|
||||
#endif
|
||||
#if HAS_FRAMEBUFFER_FETCH
|
||||
layout(location = 1) inout float o_col1;
|
||||
#else
|
||||
layout(location = 1) out float o_col1;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if NEEDS_TEX
|
||||
@@ -180,14 +187,14 @@ vec4 sample_from_rt()
|
||||
#endif
|
||||
}
|
||||
|
||||
vec4 sample_from_depth()
|
||||
float sample_from_depth()
|
||||
{
|
||||
#if !SW_DEPTH
|
||||
return vec4(0.0);
|
||||
return 0.0f;
|
||||
#elif HAS_FRAMEBUFFER_FETCH && (DEPTH_FEEDBACK_SUPPORT == 2)
|
||||
return SV_Target1;
|
||||
return o_col1;
|
||||
#else
|
||||
return texelFetch(DepthSampler, ivec2(gl_FragCoord.xy), 0);
|
||||
return texelFetch(DepthSampler, ivec2(gl_FragCoord.xy), 0).r;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -213,22 +220,27 @@ float manual_lod(float uv_w)
|
||||
vec4 sample_c_af(vec2 uv, float uv_w)
|
||||
{
|
||||
// HW sampler will reject bad UVs, match that here.
|
||||
uv = (any(isnan(uv)) || any(isinf(uv))) ? vec2(0, 0) : uv;
|
||||
uv = (any(isnan(uv)) || any(isinf(uv))) ? vec2(0.0f, 0.0f) : uv;
|
||||
|
||||
// Large floating point values risk NaN/Inf values.
|
||||
// Above this value floats lose decimal precision, so seems a resonable limit for UVs.
|
||||
uv = clamp(uv, -8388608.0f, 8388608.0f);
|
||||
|
||||
// Below taken from https://microsoft.github.io/DirectX-Specs/d3d/archive/D3D11_3_FunctionalSpec.htm#7.18.11%20LOD%20Calculations
|
||||
// And https://registry.khronos.org/OpenGL/extensions/EXT/EXT_texture_filter_anisotropic.txt
|
||||
// With guidance from https://pema.dev/2025/05/09/mipmaps-too-much-detail/
|
||||
vec2 sz = textureSize(TextureSampler, 0);
|
||||
vec2 dX = dFdx(uv) * sz;
|
||||
vec2 dY = dFdy(uv) * sz;
|
||||
|
||||
float length_x = length(dX);
|
||||
float length_y = length(dY);
|
||||
|
||||
// Calculate Ellipse Transform
|
||||
bool d_zero = length(dX) == 0 || length(dY) == 0;
|
||||
bool d_par = (dX.x * dY.y - dY.x * dX.y) == 0;
|
||||
bool d_per = dot(dX, dY) == 0;
|
||||
bool d_zero = length_x < 0.001f || length_y < 0.001f;
|
||||
float f = (dX.x * dY.y - dX.y * dY.x);
|
||||
bool d_par = f < 0.001f;
|
||||
bool d_per = dot(dX, dY) < 0.001f;
|
||||
bool d_inf_nan = any(isinf(dX)) || any(isinf(dY)) || any(isnan(dX)) || any(isnan(dY));
|
||||
|
||||
if (!(d_zero || d_par || d_per || d_inf_nan))
|
||||
@@ -236,38 +248,46 @@ vec4 sample_c_af(vec2 uv, float uv_w)
|
||||
float A = dX.y * dX.y + dY.y * dY.y;
|
||||
float B = -2 * (dX.x * dX.y + dY.x * dY.y);
|
||||
float C = dX.x * dX.x + dY.x * dY.x;
|
||||
float f = (dX.x * dY.y - dY.x * dX.y);
|
||||
float F = f * f;
|
||||
|
||||
float p = A - C;
|
||||
float q = A + C;
|
||||
float t = sqrt(p * p + B * B);
|
||||
|
||||
float signB = sign(B);
|
||||
float denom_plus = t * (q + t);
|
||||
float denom_minus = t * (q - t);
|
||||
|
||||
float sqrtA = sqrt(F * (t + p));
|
||||
float sqrtB = sqrt(F * (t - p));
|
||||
|
||||
float inv_sqrt_denom_plus = inversesqrt(denom_plus);
|
||||
float inv_sqrt_denom_minus = inversesqrt(denom_minus);
|
||||
|
||||
vec2 new_dX = vec2(
|
||||
sqrt(F * (t + p) / (t * (q + t))),
|
||||
sqrt(F * (t - p) / (t * (q + t))) * sign(B)
|
||||
sqrtA * inv_sqrt_denom_plus,
|
||||
sqrtB * inv_sqrt_denom_plus * signB
|
||||
);
|
||||
|
||||
|
||||
vec2 new_dY = vec2(
|
||||
sqrt(F * (t - p) / (t * (q - t))) * -sign(B),
|
||||
sqrt(F * (t + p) / (t * (q - t)))
|
||||
sqrtB * inv_sqrt_denom_minus * -signB,
|
||||
sqrtA * inv_sqrt_denom_minus
|
||||
);
|
||||
|
||||
|
||||
d_inf_nan = any(isinf(new_dX)) || any(isinf(new_dY)) || any(isnan(new_dX)) || any(isnan(new_dY));
|
||||
if (!d_inf_nan)
|
||||
{
|
||||
dX = new_dX;
|
||||
dY = new_dY;
|
||||
length_x = length(dX);
|
||||
length_y = length(dY);
|
||||
}
|
||||
}
|
||||
|
||||
// Compute AF values
|
||||
float squared_length_x = dX.x * dX.x + dX.y * dX.y;
|
||||
float squared_length_y = dY.x * dY.x + dY.y * dY.y;
|
||||
float determinant = abs(dX.x * dY.y - dX.y * dY.x);
|
||||
bool is_major_x = squared_length_x > squared_length_y;
|
||||
float squared_length_major = is_major_x ? squared_length_x : squared_length_y;
|
||||
float length_major = sqrt(squared_length_major);
|
||||
bool is_major_x = length_x > length_y;
|
||||
float length_major = is_major_x ? length_x : length_y;
|
||||
float length_minor = is_major_x ? length_y : length_x;
|
||||
|
||||
float aniso_ratio;
|
||||
float length_lod;
|
||||
@@ -279,57 +299,42 @@ vec4 sample_c_af(vec2 uv, float uv_w)
|
||||
// Perform isotropic filtering instead.
|
||||
aniso_ratio = 1.0f;
|
||||
length_lod = length_major;
|
||||
aniso_line = vec2(0, 0);
|
||||
aniso_line = vec2(0.0f, 0.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
float norm_major = 1.0f / length_major;
|
||||
|
||||
vec2 aniso_line_dir = vec2(
|
||||
(is_major_x ? dX.x : dY.x) * norm_major,
|
||||
(is_major_x ? dX.y : dY.y) * norm_major
|
||||
);
|
||||
|
||||
aniso_ratio = squared_length_major / determinant;
|
||||
vec2 aniso_line_dir = is_major_x ? dX : dY;
|
||||
|
||||
// Calculate the minor length of the ellipse for Lod, while also clamping the ratio of anisotropy.
|
||||
if (aniso_ratio > PS_ANISOTROPIC_FILTERING)
|
||||
{
|
||||
// ratio is clamped - Lod is based on ratio (preserves area)
|
||||
aniso_ratio = PS_ANISOTROPIC_FILTERING;
|
||||
length_lod = length_major / PS_ANISOTROPIC_FILTERING;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ratio not clamped - Lod is based on area
|
||||
length_lod = determinant / length_major;
|
||||
}
|
||||
aniso_ratio = min(length_major / length_minor, PS_ANISOTROPIC_FILTERING);
|
||||
length_lod = length_major / aniso_ratio;
|
||||
|
||||
// clamp to top Lod
|
||||
if (length_lod < 1.0f)
|
||||
aniso_ratio = max(1.0f, aniso_ratio * length_lod);
|
||||
|
||||
aniso_ratio = round(aniso_ratio);
|
||||
aniso_line = aniso_line_dir * 0.5f * length_major * (1.0f / sz);
|
||||
|
||||
aniso_line = aniso_line_dir * 0.5f * (1.0f / sz);
|
||||
}
|
||||
|
||||
|
||||
#if PS_AUTOMATIC_LOD == 1
|
||||
float lod = log2(length_lod);
|
||||
#elif PS_MANUAL_LOD == 1
|
||||
float lod = manual_lod(uv_w);
|
||||
#else
|
||||
float lod = 0; // No Lod
|
||||
float lod = 0.0f; // No Lod
|
||||
#endif
|
||||
|
||||
|
||||
vec4 colour;
|
||||
if (aniso_ratio == 1.0f)
|
||||
colour = textureLod(TextureSampler, uv, lod);
|
||||
else
|
||||
{
|
||||
vec4 num = vec4(0, 0, 0, 0);
|
||||
vec4 num = vec4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
vec2 segment = (2.0f * aniso_line) / aniso_ratio;
|
||||
for (int i = 0; i < aniso_ratio; i++)
|
||||
{
|
||||
vec2 d = -aniso_line + (0.5f + i) * (2.0f * aniso_line) / aniso_ratio;
|
||||
{
|
||||
vec2 d = -aniso_line + (0.5f + i) * segment;
|
||||
vec2 uv_sample = uv + d;
|
||||
vec4 sample_colour = textureLod(TextureSampler, uv_sample, lod);
|
||||
num += sample_colour;
|
||||
@@ -621,13 +626,13 @@ vec4 sample_depth(vec2 st)
|
||||
|
||||
|
||||
#elif PS_DEPTH_FMT == 1
|
||||
// Based on ps_convert_float32_rgba8 of convert
|
||||
// Based on ps_convert_depth32_rgba8 of convert
|
||||
// Convert a GL_FLOAT32 depth texture into a RGBA color texture
|
||||
uint d = uint(fetch_c(uv).r * exp2(32.0f));
|
||||
t = vec4(uvec4((d & 0xFFu), ((d >> 8) & 0xFFu), ((d >> 16) & 0xFFu), (d >> 24)));
|
||||
|
||||
#elif PS_DEPTH_FMT == 2
|
||||
// Based on ps_convert_float16_rgb5a1 of convert
|
||||
// Based on ps_convert_depth16_rgb5a1 of convert
|
||||
// Convert a GL_FLOAT32 (only 16 lsb) depth into a RGB5A1 color texture
|
||||
uint d = uint(fetch_c(uv).r * exp2(32.0f));
|
||||
t = vec4(uvec4((d & 0x1Fu), ((d >> 5) & 0x1Fu), ((d >> 10) & 0x1Fu), (d >> 15) & 0x01u)) * vec4(8.0f, 8.0f, 8.0f, 128.0f);
|
||||
@@ -1193,10 +1198,10 @@ void ps_main()
|
||||
#endif
|
||||
|
||||
#if PS_ZTST == ZTST_GEQUAL
|
||||
if (input_z < sample_from_depth().r)
|
||||
if (input_z < sample_from_depth())
|
||||
discard;
|
||||
#elif PS_ZTST == ZTST_GREATER
|
||||
if (input_z <= sample_from_depth().r)
|
||||
if (input_z <= sample_from_depth())
|
||||
discard;
|
||||
#endif
|
||||
|
||||
@@ -1250,7 +1255,12 @@ void ps_main()
|
||||
vec4 C = ps_color();
|
||||
|
||||
#if PS_AA1
|
||||
float cov = clamp(1.0f - abs(PSin.inv_cov), 0.0f, 1.0f);
|
||||
#if PS_AA1 == PS_AA1_LINE
|
||||
// Blur only outer part of the line by scaling coverage.
|
||||
float cov = clamp(LineCovScale * (1.0f - abs(PSin.inv_cov)), 0.0f, 1.0f);
|
||||
#else
|
||||
float cov = clamp(1.0f - abs(PSin.inv_cov), 0.0f, 1.0f);
|
||||
#endif
|
||||
#if PS_ABE
|
||||
if (floor(C.a) == 128.0f) // The coverage is only used if the fragment alpha is 128.
|
||||
C.a = 128.0f * cov;
|
||||
@@ -1264,7 +1274,7 @@ void ps_main()
|
||||
|
||||
bool atst_pass = atst(C);
|
||||
|
||||
#if PS_AFAIL == AFAIL_KEEP
|
||||
#if PS_ATST != PS_ATST_NONE && PS_AFAIL == AFAIL_KEEP
|
||||
if (!atst_pass)
|
||||
discard;
|
||||
#endif
|
||||
@@ -1293,12 +1303,12 @@ void ps_main()
|
||||
#if PS_DATE == 1
|
||||
// DATM == 0
|
||||
// Pixel with alpha equal to 1 will failed (128-255)
|
||||
SV_Target0 = (C.a > 127.5f) ? vec4(gl_PrimitiveID) : vec4(0x7FFFFFFF);
|
||||
o_col0 = (C.a > 127.5f) ? vec4(gl_PrimitiveID) : vec4(0x7FFFFFFF);
|
||||
return;
|
||||
#elif PS_DATE == 2
|
||||
// DATM == 1
|
||||
// Pixel with alpha equal to 0 will failed (0-127)
|
||||
SV_Target0 = (C.a < 127.5f) ? vec4(gl_PrimitiveID) : vec4(0x7FFFFFFF);
|
||||
o_col0 = (C.a < 127.5f) ? vec4(gl_PrimitiveID) : vec4(0x7FFFFFFF);
|
||||
return;
|
||||
#endif
|
||||
|
||||
@@ -1372,7 +1382,7 @@ void ps_main()
|
||||
// Alpha test with feedback
|
||||
#if PS_AFAIL == AFAIL_FB_ONLY
|
||||
if (!atst_pass)
|
||||
input_z = sample_from_depth().r;
|
||||
input_z = sample_from_depth();
|
||||
#elif PS_AFAIL == AFAIL_ZB_ONLY
|
||||
if (!atst_pass)
|
||||
C = sample_from_rt();
|
||||
@@ -1381,17 +1391,17 @@ void ps_main()
|
||||
{
|
||||
C.a = sample_from_rt().a;
|
||||
#if PS_AFAIL == AFAIL_RGB_ONLY_SW_Z
|
||||
input_z = sample_from_depth().r;
|
||||
input_z = sample_from_depth();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
// Warning: do not write SV_Target0 until the end since the value might be needed for
|
||||
// Warning: do not write o_col0 until the end since the value might be needed for
|
||||
// FB fetch in sample_from_rt().
|
||||
SV_Target0 = C;
|
||||
o_col0 = C;
|
||||
|
||||
#if !PS_NO_COLOR1
|
||||
SV_Target1 = alpha_blend;
|
||||
o_col1 = alpha_blend;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -1401,16 +1411,17 @@ void ps_main()
|
||||
|
||||
#if PS_AA1 == PS_AA1_TRIANGLE_SW_Z
|
||||
if (!bool(PSin.interior))
|
||||
input_z = sample_from_depth().r; // No depth update for triangle edges.
|
||||
input_z = sample_from_depth(); // No depth update for triangle edges.
|
||||
#endif
|
||||
|
||||
// Writing back depth
|
||||
#if ZWRITE
|
||||
#if SW_DEPTH && PS_NO_COLOR1 && (DEPTH_FEEDBACK_SUPPORT == 2)
|
||||
// Depth as color write. For depth as color feedback we write to both
|
||||
// color copy and real depth to avoid having to copy back to real depth.
|
||||
// Warning: do not write SV_Target1 until the end since the value might
|
||||
// Warning: do not write o_col1 until the end since the value might
|
||||
// be needed for FB fetch in sample_from_depth().
|
||||
SV_Target1 = input_z;
|
||||
o_col1 = input_z;
|
||||
#endif
|
||||
// Standard depth write.
|
||||
gl_FragDepth = input_z;
|
||||
|
||||
@@ -12,8 +12,9 @@ layout(std140, binding = 1) uniform cb20
|
||||
vec2 TextureOffset;
|
||||
|
||||
vec2 PointSize;
|
||||
|
||||
uint MaxDepth;
|
||||
uint pad_cb20;
|
||||
float LineAA1Width;
|
||||
};
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
@@ -83,7 +84,13 @@ void vs_main()
|
||||
// example: 133.0625 (133 + 1/16) should start from line 134, ceil(133.0625 - 0.05) still above 133
|
||||
gl_Position.xy = vec2(i_p) - vec2(0.05f, 0.05f);
|
||||
gl_Position.xy = gl_Position.xy * VertexScale - VertexOffset;
|
||||
gl_Position.z = float(z) * exp_min32;
|
||||
|
||||
#if HAS_CLIP_CONTROL
|
||||
gl_Position.z = float(z) * exp_min32;
|
||||
#else
|
||||
gl_Position.z = (float(z) * exp_min32) * 2.0f - 1.0f;
|
||||
#endif
|
||||
|
||||
gl_Position.w = 1.0f;
|
||||
|
||||
texture_coord();
|
||||
@@ -160,7 +167,13 @@ ProcessedVertex load_vertex(uint index)
|
||||
uint z = min(i_z, MaxDepth);
|
||||
vtx.p.xy = vec2(i_p) - vec2(0.05f, 0.05f);
|
||||
vtx.p.xy = vtx.p.xy * VertexScale - VertexOffset;
|
||||
vtx.p.z = float(z) * exp_min32;
|
||||
|
||||
#if HAS_CLIP_CONTROL
|
||||
vtx.p.z = float(z) * exp_min32;
|
||||
#else
|
||||
vtx.p.z = (float(z) * exp_min32) * 2.0f - 1.0f;
|
||||
#endif
|
||||
|
||||
vtx.p.w = 1.0f;
|
||||
|
||||
vec2 uv = vec2(i_uv) - TextureOffset;
|
||||
@@ -182,6 +195,110 @@ ProcessedVertex load_vertex(uint index)
|
||||
return vtx;
|
||||
}
|
||||
|
||||
// Convert XY from NDC to GS pixel coordinates (i.e. 1.0 = 1 GS pixel).
|
||||
vec2 get_xy_unscaled(vec2 xy)
|
||||
{
|
||||
return round(xy / VertexScale) / 16.0f;
|
||||
}
|
||||
|
||||
// Get the XY deltas in GS pixel coordinates, using first vertex as the origin.
|
||||
mat2 get_xy_deltas_unscaled(ProcessedVertex v0, ProcessedVertex v1, ProcessedVertex v2)
|
||||
{
|
||||
vec2 xy0 = get_xy_unscaled(v0.p.xy);
|
||||
vec2 xy1 = get_xy_unscaled(v1.p.xy);
|
||||
vec2 xy2 = get_xy_unscaled(v2.p.xy);
|
||||
return mat2(xy1 - xy0, xy2 - xy0);
|
||||
}
|
||||
|
||||
// Get the AA1 outward expand direction to the edge formed by the first two vertices.
|
||||
// This is up or down for shallow (X dominant) edges, and right or left for steep (Y dominant) edges.
|
||||
// Similar expansion to line AA1 except instead of expanding on both sides of the line,
|
||||
// expand on on the side towards the outside of the triangle.
|
||||
vec2 get_aa1_triangle_expand_dir(ProcessedVertex v0, ProcessedVertex v1, ProcessedVertex v2)
|
||||
{
|
||||
mat2 xy_deltas = get_xy_deltas_unscaled(v0, v1, v2);
|
||||
vec2 line_delta = xy_deltas[0];
|
||||
vec2 line_opposite = xy_deltas[1];
|
||||
|
||||
vec2 line_normal = vec2(line_delta.y, -line_delta.x);
|
||||
vec2 line_expand = abs(line_delta.x) >= abs(line_delta.y) ? vec2(0.0f, 1.0f) : vec2(1.0f, 0.0f);
|
||||
|
||||
if ((dot(line_expand, line_normal) >= 0.0f) == (dot(line_opposite, line_normal) >= 0.0f))
|
||||
{
|
||||
// Expand direction point towards the interior so flip it.
|
||||
line_expand = -line_expand;
|
||||
}
|
||||
|
||||
return line_expand;
|
||||
}
|
||||
|
||||
mat2 get_inverse(mat2 mat, float det)
|
||||
{
|
||||
return mat2(mat[1][1], -mat[0][1], -mat[1][0], mat[0][0]) * (1 / det);
|
||||
}
|
||||
|
||||
// Extrapolate triangle attributes from the first vertex along the given direction.
|
||||
// dp_mat is derived from the input vertices, it is passed in to avoid recomputing.
|
||||
void extrapolate_aa1_triangle_edge(inout ProcessedVertex v0, ProcessedVertex v1, ProcessedVertex v2, mat2 dp_mat, vec2 dp)
|
||||
{
|
||||
// Get texture deltas
|
||||
#if VS_TME
|
||||
#if VS_FST
|
||||
mat2 dt = mat2(v1.t_int.zw - v0.t_int.zw, v2.t_int.zw - v0.t_int.zw);
|
||||
#else
|
||||
mat2 dt = mat2(v1.t_float.xy - v0.t_float.xy, v2.t_float.xy - v0.t_float.xy);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Get color delta if interpolating
|
||||
#if VS_IIP
|
||||
mat2x4 dc = mat2x4(v1.c - v0.c, v2.c - v0.c);
|
||||
#endif
|
||||
|
||||
vec2 dz = vec2(v1.p.z - v0.p.z, v2.p.z - v0.p.z); // Z deltas
|
||||
|
||||
vec2 df = vec2(v1.t_float.z - v0.t_float.z, v2.t_float.z - v0.t_float.z); // Fog deltas
|
||||
|
||||
vec2 dq = vec2(v1.t_float.w - v0.t_float.w, v2.t_float.w - v0.t_float.w); // Q deltas
|
||||
|
||||
// To prevent unstable extrapolation, do not extrapolate if the
|
||||
// minimum perpendicular length of the triangle is < 2 pixels.
|
||||
float dp_det = determinant(dp_mat); // Twice signed triangle area.
|
||||
float len0 = length(dp_mat[0]);
|
||||
float len1 = length(dp_mat[1]);
|
||||
float len2 = length(dp_mat[1] - dp_mat[0]);
|
||||
float min_perp_length = abs(dp_det) / max(max(len0, len1), len2);
|
||||
|
||||
// Get the position -> barycentric weight matrix
|
||||
mat2 inv_dp_mat = get_inverse(dp_mat, dp_det);
|
||||
|
||||
vec2 weights = min_perp_length < 2 ? vec2(0) : inv_dp_mat * dp;
|
||||
|
||||
v0.p.xy += dp * PointSize; // Extrapolate position
|
||||
|
||||
// Extrapolate texture coords
|
||||
#if VS_TME
|
||||
#if VS_FST
|
||||
v0.t_int.zw += dt * weights;
|
||||
v0.t_int.xy = v0.t_int.zw * TextureScale;
|
||||
#else
|
||||
v0.t_float.xy += dt * weights;
|
||||
v0.t_int.zw = v0.t_float.xy / TextureScale;
|
||||
v0.t_float.w += dot(dq, weights);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Extrapolate and clamp color
|
||||
#if VS_IIP
|
||||
v0.c += dc * weights;
|
||||
v0.c = clamp(v0.c, vec4(0), vec4(255));
|
||||
#endif
|
||||
|
||||
v0.p.z += dot(dz, weights); // Extrapolate depth
|
||||
|
||||
v0.t_float.z += dot(df, weights); // Extrapolate fog
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
ProcessedVertex vtx;
|
||||
@@ -206,13 +323,10 @@ void main()
|
||||
|
||||
// Use bottom minus top for delta regardless of which vertex we are expanding.
|
||||
vec2 line_delta = is_bottom ? (vtx.p.xy - other.p.xy) : (other.p.xy - vtx.p.xy);
|
||||
vec2 line_vector = normalize(line_delta);
|
||||
#if VS_EXPAND == VS_EXPAND_LINE
|
||||
vec2 line_vector = normalize(line_delta / VertexScale);
|
||||
vec2 line_expand = vec2(line_vector.y, -line_vector.x);
|
||||
#elif VS_EXPAND == VS_EXPAND_LINE_AA1
|
||||
// Expand in y direction for shallow lines and x direction for steep lines.
|
||||
line_delta /= VertexScale;
|
||||
vec2 line_expand = abs(line_delta.x) >= abs(line_delta.y) ? vec2(0.0f, 2.0f) : vec2(2.0f, 0.0f);
|
||||
#if VS_EXPAND == VS_EXPAND_LINE_AA1
|
||||
line_expand *= 2.0f * LineAA1Width;
|
||||
#endif
|
||||
vec2 line_width = (line_expand * PointSize) / 2;
|
||||
vec2 offset = is_right ? line_width : -line_width;
|
||||
@@ -254,10 +368,14 @@ void main()
|
||||
// - Vertices 3-8: First edge expanded (2 triangles).
|
||||
// - Vertices 9-14: Second edge expanded (2 triangles).
|
||||
// - Vertices 15-20: Third edge expanded (2 triangles).
|
||||
// - Vertices 21-26: First corner cap (2 triangles).
|
||||
// - Vertices 27-32: Second corner cap (2 triangles).
|
||||
// - Vertices 33-38: Third corner cap (2 triangles).
|
||||
|
||||
uint prim_id = vid / 21;
|
||||
uint prim_offset = vid - 21 * prim_id; // range: 0-20
|
||||
uint prim_id = vid / 39;
|
||||
uint prim_offset = vid - 39 * prim_id; // range: 0-38
|
||||
bool interior = prim_offset < 3;
|
||||
bool edge = 3 <= prim_offset && prim_offset < 21;
|
||||
|
||||
if (interior)
|
||||
{
|
||||
@@ -265,7 +383,7 @@ void main()
|
||||
VSout.inv_cov = 0.0f; // Full coverage
|
||||
VSout.interior = 1;
|
||||
}
|
||||
else
|
||||
else if (edge)
|
||||
{
|
||||
// Vertex indices for this edge. We need all 3 for determining exterior/interior.
|
||||
uint prim_offset_edges = prim_offset - 3; // range: 0-17
|
||||
@@ -274,45 +392,69 @@ void main()
|
||||
uint i2 = (i0 >= 1) ? i0 - 1 : i0 + 2;
|
||||
uint edge_offset = prim_offset_edges - 6 * i0; // range: 0-5
|
||||
|
||||
// Note: order of top/bottom, inside/outside order is arbitrary,
|
||||
// Note: order of top/bottom, inside/outside is arbitrary,
|
||||
// as long as it assembles into two triangles forming a quad.
|
||||
bool is_bottom = (2 <= edge_offset) && (edge_offset <= 4);
|
||||
bool is_outside = (edge_offset & 1) != 0;
|
||||
bool is_outside = (edge_offset & 1u) != 0;
|
||||
|
||||
vtx = load_vertex(load_index(3 * prim_id + i0));
|
||||
ProcessedVertex other = load_vertex(load_index(3 * prim_id + i1));
|
||||
vtx = load_vertex(load_index(3 * prim_id + (is_bottom ? i1 : i0)));
|
||||
ProcessedVertex other = load_vertex(load_index(3 * prim_id + (is_bottom ? i0 : i1)));
|
||||
ProcessedVertex opposite = load_vertex(load_index(3 * prim_id + i2));
|
||||
|
||||
// Similar expansion to line AA1 except instead of expanding on both sides of
|
||||
// the line we expand on on the side towards the outside of the triangle.
|
||||
vec2 line_delta = vtx.p.xy - other.p.xy;
|
||||
vec2 line_normal = normalize(vec2(line_delta.y, -line_delta.x));
|
||||
vec2 line_expand = abs(line_delta.x) >= abs(line_delta.y) ? vec2(0.0f, 2.0f) : vec2(2.0f, 0.0f);
|
||||
if ((dot(line_expand, line_normal) >= 0.0f) == (dot(opposite.p.xy - vtx.p.xy, line_normal) >= 0.0f))
|
||||
{
|
||||
// Expand direction point towards the interior so flip it.
|
||||
line_expand = -line_expand;
|
||||
}
|
||||
vec2 line_width = (line_expand * PointSize) / 2;
|
||||
mat2 pos_deltas = get_xy_deltas_unscaled(vtx, other, opposite);
|
||||
|
||||
if (is_bottom)
|
||||
vtx = other;
|
||||
if (is_outside)
|
||||
{
|
||||
vtx.p.xy += line_width;
|
||||
VSout.inv_cov = 1.0f; // No coverage
|
||||
}
|
||||
else
|
||||
{
|
||||
VSout.inv_cov = 0.0f; // Full coverage
|
||||
}
|
||||
vec2 expand_dir = is_outside ? get_aa1_triangle_expand_dir(vtx, other, opposite) : vec2(0);
|
||||
|
||||
// Do actual extrapolation, or no-op if expand_dir == 0.
|
||||
extrapolate_aa1_triangle_edge(vtx, other, opposite, pos_deltas, expand_dir);
|
||||
|
||||
VSout.inv_cov = is_outside ? 1.0f : 0.0f; // No coverage on outside, otherwise full.
|
||||
|
||||
VSout.interior = 0;
|
||||
}
|
||||
else // Corner cap
|
||||
{
|
||||
// Vertex indices for this cap. We need all 3 for determining exterior/interior.
|
||||
uint prim_offset_cap = prim_offset - 21; // range: 0-8
|
||||
uint i0 = prim_offset_cap / 6;
|
||||
uint i1 = (i0 >= 2) ? i0 - 2 : i0 + 1;
|
||||
uint i2 = (i0 >= 1) ? i0 - 1 : i0 + 2;
|
||||
uint cap_offset = prim_offset_cap - 6 * i0; // range: 0-5
|
||||
|
||||
#if !VS_IIP
|
||||
// Get the provoking vertex color (last vertex in GL)
|
||||
vtx.c = i0 == 2 ? vtx.c : (i1 == 2 ? other.c : opposite.c);
|
||||
#endif
|
||||
bool is_near_corner = cap_offset == 0 || cap_offset == 3;
|
||||
bool is_far_corner = cap_offset == 2 || cap_offset == 5;
|
||||
bool is_first_tri = cap_offset < 3;
|
||||
|
||||
// First triangle is on the side of vertex i1 and second is on the side of vertex i2.
|
||||
vtx = load_vertex(load_index(3 * prim_id + i0));
|
||||
ProcessedVertex other = load_vertex(load_index(3 * prim_id + (is_first_tri ? i1 : i2)));
|
||||
ProcessedVertex opposite = load_vertex(load_index(3 * prim_id + (is_first_tri ? i2 : i1)));
|
||||
|
||||
mat2 pos_deltas = get_xy_deltas_unscaled(vtx, other, opposite);
|
||||
|
||||
// Get the edge expansion directions of both incident edges.
|
||||
vec2 edge_expand_dir_0 = get_aa1_triangle_expand_dir(vtx, other, opposite);
|
||||
vec2 edge_expand_dir_1 = get_aa1_triangle_expand_dir(vtx, opposite, other);
|
||||
|
||||
// Check if the corner is already filled by the expanded edges.
|
||||
// This happens if the expand directions are the same.
|
||||
// If so we output a degenerate triangle at this corner.
|
||||
bool corner_filled = all(equal(edge_expand_dir_0, edge_expand_dir_1));
|
||||
|
||||
// Nothing if corner is filled, otherwise opposite to the bisector of the corner angle.
|
||||
vec2 far_corner_dir = corner_filled ? vec2(0) : -normalize((pos_deltas[0] + pos_deltas[1]) / 2);
|
||||
|
||||
// Determine the expand direction.
|
||||
vec2 expand_dir = is_near_corner ? vec2(0) : // No extrapolation
|
||||
is_far_corner ? far_corner_dir : // Opposite to the angle bisector of corner
|
||||
edge_expand_dir_0; // Standard AA1 edge expansion
|
||||
|
||||
// Do the actual extrapolation (no-op if expand_dir == 0).
|
||||
extrapolate_aa1_triangle_edge(vtx, other, opposite, pos_deltas, expand_dir);
|
||||
|
||||
VSout.inv_cov = is_near_corner ? 0.0f : 1.0f; // Full coverage at near corner, otherwise none.
|
||||
|
||||
VSout.interior = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -20,44 +20,127 @@ void main()
|
||||
|
||||
layout(location = 0) in vec2 v_tex;
|
||||
|
||||
#if defined(ps_convert_rgba8_16bits) || defined(ps_convert_float32_32bits)
|
||||
layout(location = 0) out uint o_col0;
|
||||
#elif defined(ps_convert_float32_depth_to_color)
|
||||
layout(location = 0) out float o_col0;
|
||||
#elif !defined(ps_datm1) && \
|
||||
!defined(ps_datm0) && \
|
||||
!defined(ps_datm1_rta_correction) && \
|
||||
!defined(ps_datm0_rta_correction) && \
|
||||
!defined(ps_convert_rgba8_float32) && \
|
||||
!defined(ps_convert_rgba8_float24) && \
|
||||
!defined(ps_convert_rgba8_float16) && \
|
||||
!defined(ps_convert_rgb5a1_float16) && \
|
||||
!defined(ps_convert_rgba8_float32_biln) && \
|
||||
!defined(ps_convert_rgba8_float24_biln) && \
|
||||
!defined(ps_convert_rgba8_float16_biln) && \
|
||||
!defined(ps_convert_rgb5a1_float16_biln) && \
|
||||
!defined(ps_depth_copy)
|
||||
layout(location = 0) out vec4 o_col0;
|
||||
#if HAS_INTEGER_OUTPUT
|
||||
layout(location = 0) out uint o_col0;
|
||||
#define OUTPUT o_col0
|
||||
#elif HAS_DEPTH_OUTPUT
|
||||
out float gl_FragDepth;
|
||||
#define OUTPUT gl_FragDepth
|
||||
#elif HAS_FLOAT32_OUTPUT
|
||||
layout(location = 0) out float o_col0;
|
||||
#define OUTPUT o_col0
|
||||
#elif HAS_STENCIL_OUTPUT
|
||||
#else
|
||||
layout(location = 0) out vec4 o_col0;
|
||||
#define OUTPUT o_col0
|
||||
#endif
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D samp0;
|
||||
|
||||
#if HAS_FLOAT32_INPUT
|
||||
|
||||
float sample_c(vec2 uv)
|
||||
{
|
||||
return texture(samp0, uv).r;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
vec4 sample_c(vec2 uv)
|
||||
{
|
||||
return texture(samp0, uv);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
uint rgba8_to_uint(vec4 c)
|
||||
{
|
||||
uvec4 i = uvec4(c * 255.5f) & 0xFFu;
|
||||
return i.r | (i.g << 8) | (i.b << 16) | (i.a << 24);
|
||||
}
|
||||
|
||||
uint rgb5a1_to_uint(vec4 c)
|
||||
{
|
||||
uvec4 i = uvec4(c * 255.5f) & uvec4(0xF8u, 0xF8u, 0xF8u, 0x80u);
|
||||
return (i.r >> 3) | (i.g << 2) | (i.b << 7) | (i.a << 8);
|
||||
}
|
||||
|
||||
uint depth_to_uint(float d)
|
||||
{
|
||||
return uint(d * exp2(32.0f));
|
||||
}
|
||||
|
||||
vec4 uint_to_rgba8(uint i)
|
||||
{
|
||||
return vec4((i & 0xFFu), ((i >> 8) & 0xFFu), ((i >> 16) & 0xFFu), ((i >> 24) & 0xFFu)) / 255.0f;
|
||||
}
|
||||
|
||||
vec4 uint_to_rgb5a1(uint i)
|
||||
{
|
||||
return vec4(uvec4(i << 3, i >> 2, i >> 7, i >> 8) & uvec4(0xF8u, 0xF8u, 0xF8u, 0x80u)) / 255.0f;
|
||||
}
|
||||
|
||||
float uint_to_depth32(uint i)
|
||||
{
|
||||
return float(i) * exp2(-32.0f);
|
||||
}
|
||||
|
||||
float uint_to_depth24(uint i)
|
||||
{
|
||||
return float(i & 0xFFFFFFu) * exp2(-32.0f);
|
||||
}
|
||||
|
||||
float uint_to_depth16(uint i)
|
||||
{
|
||||
return float(i & 0xFFFFu) * exp2(-32.0f);
|
||||
}
|
||||
|
||||
float rgba8_to_depth32(vec4 val)
|
||||
{
|
||||
return uint_to_depth32(rgba8_to_uint(val));
|
||||
}
|
||||
|
||||
float rgba8_to_depth24(vec4 val)
|
||||
{
|
||||
return uint_to_depth24(rgba8_to_uint(val));
|
||||
}
|
||||
|
||||
float rgba8_to_depth16(vec4 val)
|
||||
{
|
||||
return uint_to_depth16(rgba8_to_uint(val));
|
||||
}
|
||||
|
||||
float rgb5a1_to_depth16(vec4 val)
|
||||
{
|
||||
return uint_to_depth16(rgb5a1_to_uint(val));
|
||||
}
|
||||
|
||||
vec4 depth32_to_rgba8(float d)
|
||||
{
|
||||
return uint_to_rgba8(depth_to_uint(d));
|
||||
}
|
||||
|
||||
vec4 depth16_to_rgb5a1(float d)
|
||||
{
|
||||
return uint_to_rgb5a1(depth_to_uint(d));
|
||||
}
|
||||
|
||||
float depth32_to_depth24(float d)
|
||||
{
|
||||
return uint_to_depth24(depth_to_uint(d));
|
||||
}
|
||||
|
||||
#ifdef ps_copy
|
||||
void ps_copy()
|
||||
{
|
||||
o_col0 = sample_c(v_tex);
|
||||
OUTPUT = sample_c(v_tex);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_depth_copy
|
||||
void ps_depth_copy()
|
||||
{
|
||||
gl_FragDepth = sample_c(v_tex).r;
|
||||
OUTPUT = sample_c(v_tex);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -82,7 +165,7 @@ void ps_downsample_copy()
|
||||
result += texelFetch(samp0, coord + ivec2(xoff * step_multiplier, yoff * step_multiplier), 0);
|
||||
}
|
||||
}
|
||||
o_col0 = result / Weight;
|
||||
OUTPUT = result / Weight;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -90,17 +173,15 @@ void ps_downsample_copy()
|
||||
void ps_filter_transparency()
|
||||
{
|
||||
vec4 c = sample_c(v_tex);
|
||||
o_col0 = vec4(c.rgb, 1.0);
|
||||
OUTPUT = vec4(c.rgb, 1.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba8_16bits
|
||||
// Need to be careful with precision here, it can break games like Spider-Man 3 and Dogs Life
|
||||
void ps_convert_rgba8_16bits()
|
||||
#ifdef ps_convert_rgb5a1_16bits
|
||||
void ps_convert_rgb5a1_16bits()
|
||||
{
|
||||
uvec4 i = uvec4(sample_c(v_tex) * vec4(255.5f, 255.5f, 255.5f, 255.5f));
|
||||
|
||||
o_col0 = ((i.x & 0x00F8u) >> 3) | ((i.y & 0x00F8u) << 2) | ((i.z & 0x00f8u) << 7) | ((i.w & 0x80u) << 8);
|
||||
// Need to be careful with precision here, it can break games like Spider-Man 3 and Dogs Life
|
||||
OUTPUT = rgb5a1_to_uint(sample_c(v_tex));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -140,7 +221,7 @@ void ps_datm0_rta_correction()
|
||||
void ps_rta_correction()
|
||||
{
|
||||
vec4 value = sample_c(v_tex);
|
||||
o_col0 = vec4(value.rgb, value.a / (128.25f / 255.0f));
|
||||
OUTPUT = vec4(value.rgb, value.a / (128.25f / 255.0f));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -148,7 +229,7 @@ void ps_rta_correction()
|
||||
void ps_rta_decorrection()
|
||||
{
|
||||
vec4 value = sample_c(v_tex);
|
||||
o_col0 = vec4(value.rgb, value.a * (128.25f / 255.0f));
|
||||
OUTPUT = vec4(value.rgb, value.a * (128.25f / 255.0f));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -156,7 +237,7 @@ void ps_rta_decorrection()
|
||||
void ps_colclip_init()
|
||||
{
|
||||
vec4 value = sample_c(v_tex);
|
||||
o_col0 = vec4(roundEven(value.rgb * 255.0f) / 65535.0f, value.a);
|
||||
OUTPUT = vec4(roundEven(value.rgb * 255.0f) / 65535.0f, value.a);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -164,116 +245,39 @@ void ps_colclip_init()
|
||||
void ps_colclip_resolve()
|
||||
{
|
||||
vec4 value = sample_c(v_tex);
|
||||
o_col0 = vec4(vec3(uvec3(value.rgb * 65535.5f) & 255u) / 255.0f, value.a);
|
||||
OUTPUT = vec4(vec3(uvec3(value.rgb * 65535.5f) & 255u) / 255.0f, value.a);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_float32_depth_to_color
|
||||
void ps_convert_float32_depth_to_color()
|
||||
{
|
||||
o_col0 = sample_c(v_tex).r;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_float32_color_to_depth
|
||||
void ps_convert_float32_color_to_depth()
|
||||
{
|
||||
gl_FragDepth = sample_c(v_tex).r;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_float32_32bits
|
||||
void ps_convert_float32_32bits()
|
||||
#ifdef ps_convert_depth32_32bits
|
||||
void ps_convert_depth32_32bits()
|
||||
{
|
||||
// Convert a vec32 depth texture into a 32 bits UINT texture
|
||||
o_col0 = uint(exp2(32.0f) * sample_c(v_tex).r);
|
||||
OUTPUT = depth_to_uint(sample_c(v_tex));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_float32_rgba8
|
||||
void ps_convert_float32_rgba8()
|
||||
#ifdef ps_convert_depth32_rgba8
|
||||
void ps_convert_depth32_rgba8()
|
||||
{
|
||||
// Convert a vec32 depth texture into a RGBA color texture
|
||||
uint d = uint(sample_c(v_tex).r * exp2(32.0f));
|
||||
o_col0 = vec4(uvec4((d & 0xFFu), ((d >> 8) & 0xFFu), ((d >> 16) & 0xFFu), (d >> 24))) / vec4(255.0);
|
||||
OUTPUT = depth32_to_rgba8(sample_c(v_tex));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_float16_rgb5a1
|
||||
void ps_convert_float16_rgb5a1()
|
||||
#ifdef ps_convert_depth16_rgb5a1
|
||||
void ps_convert_depth16_rgb5a1()
|
||||
{
|
||||
// Convert a vec32 (only 16 lsb) depth into a RGB5A1 color texture
|
||||
uint d = uint(sample_c(v_tex).r * exp2(32.0f));
|
||||
o_col0 = vec4(uvec4(d << 3, d >> 2, d >> 7, d >> 8) & uvec4(0xf8, 0xf8, 0xf8, 0x80)) / 255.0f;
|
||||
OUTPUT = depth16_to_rgb5a1(sample_c(v_tex));
|
||||
}
|
||||
#endif
|
||||
|
||||
float rgba8_to_depth32(vec4 unorm)
|
||||
{
|
||||
uvec4 c = uvec4(unorm * vec4(255.5f));
|
||||
return float(c.r | (c.g << 8) | (c.b << 16) | (c.a << 24)) * exp2(-32.0f);
|
||||
}
|
||||
|
||||
float rgba8_to_depth24(vec4 unorm)
|
||||
{
|
||||
uvec3 c = uvec3(unorm.rgb * vec3(255.5f));
|
||||
return float(c.r | (c.g << 8) | (c.b << 16)) * exp2(-32.0f);
|
||||
}
|
||||
|
||||
float rgba8_to_depth16(vec4 unorm)
|
||||
{
|
||||
uvec2 c = uvec2(unorm.rg * vec2(255.5f));
|
||||
return float(c.r | (c.g << 8)) * exp2(-32.0f);
|
||||
}
|
||||
|
||||
float rgb5a1_to_depth16(vec4 unorm)
|
||||
{
|
||||
uvec4 c = uvec4(unorm * vec4(255.5f));
|
||||
return float(((c.r & 0xF8u) >> 3) | ((c.g & 0xF8u) << 2) | ((c.b & 0xF8u) << 7) | ((c.a & 0x80u) << 8)) * exp2(-32.0f);
|
||||
}
|
||||
|
||||
#ifdef ps_convert_float32_float24
|
||||
void ps_convert_float32_float24()
|
||||
#ifdef ps_convert_depth32_depth24
|
||||
void ps_convert_depth32_depth24()
|
||||
{
|
||||
// Truncates depth value to 24bits
|
||||
uint d = uint(sample_c(v_tex).r * exp2(32.0f)) & 0xFFFFFFu;
|
||||
gl_FragDepth = float(d) * exp2(-32.0f);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba8_float32
|
||||
void ps_convert_rgba8_float32()
|
||||
{
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
gl_FragDepth = rgba8_to_depth32(sample_c(v_tex));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba8_float24
|
||||
void ps_convert_rgba8_float24()
|
||||
{
|
||||
// Same as above but without the alpha channel (24 bits Z)
|
||||
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
gl_FragDepth = rgba8_to_depth24(sample_c(v_tex));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba8_float16
|
||||
void ps_convert_rgba8_float16()
|
||||
{
|
||||
// Same as above but without the A/B channels (16 bits Z)
|
||||
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
gl_FragDepth = rgba8_to_depth16(sample_c(v_tex));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgb5a1_float16
|
||||
void ps_convert_rgb5a1_float16()
|
||||
{
|
||||
// Convert an RGB5A1 (saved as RGBA8) color to a 16 bit Z
|
||||
gl_FragDepth = rgb5a1_to_depth16(sample_c(v_tex));
|
||||
OUTPUT = depth32_to_depth24(sample_c(v_tex));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -287,41 +291,53 @@ void ps_convert_rgb5a1_float16()
|
||||
float depthTR = CONVERT_FN(texelFetch(samp0, coords.zy, 0)); \
|
||||
float depthBL = CONVERT_FN(texelFetch(samp0, coords.xw, 0)); \
|
||||
float depthBR = CONVERT_FN(texelFetch(samp0, coords.zw, 0)); \
|
||||
gl_FragDepth = mix(mix(depthTL, depthTR, mix_vals.x), mix(depthBL, depthBR, mix_vals.x), mix_vals.y);
|
||||
OUTPUT = mix(mix(depthTL, depthTR, mix_vals.x), mix(depthBL, depthBR, mix_vals.x), mix_vals.y);
|
||||
|
||||
#ifdef ps_convert_rgba8_float32_biln
|
||||
void ps_convert_rgba8_float32_biln()
|
||||
#ifdef ps_convert_rgba8_depth32
|
||||
void ps_convert_rgba8_depth32()
|
||||
{
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
#if HAS_BILN
|
||||
SAMPLE_RGBA_DEPTH_BILN(rgba8_to_depth32);
|
||||
#else
|
||||
OUTPUT = rgba8_to_depth32(sample_c(v_tex));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba8_float24_biln
|
||||
void ps_convert_rgba8_float24_biln()
|
||||
#ifdef ps_convert_rgba8_depth24
|
||||
void ps_convert_rgba8_depth24()
|
||||
{
|
||||
// Same as above but without the alpha channel (24 bits Z)
|
||||
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
#if HAS_BILN
|
||||
SAMPLE_RGBA_DEPTH_BILN(rgba8_to_depth24);
|
||||
#else
|
||||
OUTPUT = rgba8_to_depth24(sample_c(v_tex));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba8_float16_biln
|
||||
void ps_convert_rgba8_float16_biln()
|
||||
#ifdef ps_convert_rgba8_depth16
|
||||
void ps_convert_rgba8_depth16()
|
||||
{
|
||||
// Same as above but without the A/B channels (16 bits Z)
|
||||
|
||||
// Convert an RGBA texture into a float depth texture
|
||||
#if HAS_BILN
|
||||
SAMPLE_RGBA_DEPTH_BILN(rgba8_to_depth16);
|
||||
#else
|
||||
OUTPUT = rgba8_to_depth16(sample_c(v_tex));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgb5a1_float16_biln
|
||||
void ps_convert_rgb5a1_float16_biln()
|
||||
#ifdef ps_convert_rgb5a1_depth16
|
||||
void ps_convert_rgb5a1_depth16()
|
||||
{
|
||||
// Convert an RGB5A1 (saved as RGBA8) color to a 16 bit Z
|
||||
#if HAS_BILN
|
||||
SAMPLE_RGBA_DEPTH_BILN(rgb5a1_to_depth16);
|
||||
#else
|
||||
OUTPUT = rgb5a1_to_depth16(sample_c(v_tex));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -608,25 +624,25 @@ void ps_yuv()
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(ps_stencil_image_init_0) || defined(ps_stencil_image_init_1) || defined(ps_stencil_image_init_2) || defined(ps_stencil_image_init_3)
|
||||
#if defined(ps_primid_image_init_0) || defined(ps_primid_image_init_1) || defined(ps_primid_image_init_2) || defined(ps_primid_image_init_3)
|
||||
|
||||
void main()
|
||||
{
|
||||
o_col0 = vec4(0x7FFFFFFF);
|
||||
|
||||
#ifdef ps_stencil_image_init_0
|
||||
#ifdef ps_primid_image_init_0
|
||||
if((127.5f / 255.0f) < sample_c(v_tex).a) // < 0x80 pass (== 0x80 should not pass)
|
||||
o_col0 = vec4(-1);
|
||||
#endif
|
||||
#ifdef ps_stencil_image_init_1
|
||||
#ifdef ps_primid_image_init_1
|
||||
if(sample_c(v_tex).a < (127.5f / 255.0f)) // >= 0x80 pass
|
||||
o_col0 = vec4(-1);
|
||||
#endif
|
||||
#ifdef ps_stencil_image_init_2
|
||||
#ifdef ps_primid_image_init_2
|
||||
if((254.5f / 255.0f) < sample_c(v_tex).a) // < 0x80 pass (== 0x80 should not pass)
|
||||
o_col0 = vec4(-1);
|
||||
#endif
|
||||
#ifdef ps_stencil_image_init_3
|
||||
#ifdef ps_primid_image_init_3
|
||||
if(sample_c(v_tex).a < (254.5f / 255.0f)) // >= 0x80 pass
|
||||
o_col0 = vec4(-1);
|
||||
#endif
|
||||
|
||||
@@ -24,7 +24,7 @@ layout(std140, set = 0, binding = 0) uniform cb0
|
||||
vec2 TextureOffset;
|
||||
vec2 PointSize;
|
||||
uint MaxDepth;
|
||||
uint pad_cb0;
|
||||
float LineAA1Width;
|
||||
};
|
||||
|
||||
layout(location = 0) out VSOutput
|
||||
@@ -189,6 +189,110 @@ ProcessedVertex load_vertex(uint index)
|
||||
return vtx;
|
||||
}
|
||||
|
||||
// Convert XY from NDC to GS pixel coordinates (i.e. 1.0 = 1 GS pixel).
|
||||
vec2 get_xy_unscaled(vec2 xy)
|
||||
{
|
||||
return round(xy / VertexScale) / 16.0f;
|
||||
}
|
||||
|
||||
// Get the XY deltas in GS pixel coordinates, using first vertex as the origin.
|
||||
mat2 get_xy_deltas_unscaled(ProcessedVertex v0, ProcessedVertex v1, ProcessedVertex v2)
|
||||
{
|
||||
vec2 xy0 = get_xy_unscaled(v0.p.xy);
|
||||
vec2 xy1 = get_xy_unscaled(v1.p.xy);
|
||||
vec2 xy2 = get_xy_unscaled(v2.p.xy);
|
||||
return mat2(xy1 - xy0, xy2 - xy0);
|
||||
}
|
||||
|
||||
// Get the AA1 outward expand direction to the edge formed by the first two vertices.
|
||||
// This is up or down for shallow (X dominant) edges, and right or left for steep (Y dominant) edges.
|
||||
// Similar expansion to line AA1 except instead of expanding on both sides of the line,
|
||||
// expand on on the side towards the outside of the triangle.
|
||||
vec2 get_aa1_triangle_expand_dir(ProcessedVertex v0, ProcessedVertex v1, ProcessedVertex v2)
|
||||
{
|
||||
mat2 xy_deltas = get_xy_deltas_unscaled(v0, v1, v2);
|
||||
vec2 line_delta = xy_deltas[0];
|
||||
vec2 line_opposite = xy_deltas[1];
|
||||
|
||||
vec2 line_normal = vec2(line_delta.y, -line_delta.x);
|
||||
vec2 line_expand = abs(line_delta.x) >= abs(line_delta.y) ? vec2(0.0f, 1.0f) : vec2(1.0f, 0.0f);
|
||||
|
||||
if ((dot(line_expand, line_normal) >= 0.0f) == (dot(line_opposite, line_normal) >= 0.0f))
|
||||
{
|
||||
// Expand direction point towards the interior so flip it.
|
||||
line_expand = -line_expand;
|
||||
}
|
||||
|
||||
return line_expand;
|
||||
}
|
||||
|
||||
mat2 get_inverse(mat2 mat, float det)
|
||||
{
|
||||
return mat2(mat[1][1], -mat[0][1], -mat[1][0], mat[0][0]) * (1 / det);
|
||||
}
|
||||
|
||||
// Extrapolate triangle attributes from the first vertex along the given direction.
|
||||
// dp_mat is derived from the input vertices, it is passed in to avoid recomputing.
|
||||
void extrapolate_aa1_triangle_edge(inout ProcessedVertex v0, ProcessedVertex v1, ProcessedVertex v2, mat2 dp_mat, vec2 dp)
|
||||
{
|
||||
// Get texture deltas
|
||||
#if VS_TME
|
||||
#if VS_FST
|
||||
mat2 dt = mat2(v1.ti.zw - v0.ti.zw, v2.ti.zw - v0.ti.zw);
|
||||
#else
|
||||
mat2 dt = mat2(v1.t.xy - v0.t.xy, v2.t.xy - v0.t.xy);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Get color delta if interpolating
|
||||
#if VS_IIP
|
||||
mat2x4 dc = mat2x4(v1.c - v0.c, v2.c - v0.c);
|
||||
#endif
|
||||
|
||||
vec2 dz = vec2(v1.p.z - v0.p.z, v2.p.z - v0.p.z); // Z deltas
|
||||
|
||||
vec2 df = vec2(v1.t.z - v0.t.z, v2.t.z - v0.t.z); // Fog deltas
|
||||
|
||||
vec2 dq = vec2(v1.t.w - v0.t.w, v2.t.w - v0.t.w); // Q deltas
|
||||
|
||||
// To prevent unstable extrapolation, do not extrapolate if the
|
||||
// minimum perpendicular length of the triangle is < 2 pixels.
|
||||
float dp_det = determinant(dp_mat); // Twice signed triangle area.
|
||||
float len0 = length(dp_mat[0]);
|
||||
float len1 = length(dp_mat[1]);
|
||||
float len2 = length(dp_mat[1] - dp_mat[0]);
|
||||
float min_perp_length = abs(dp_det) / max(max(len0, len1), len2);
|
||||
|
||||
// Get the position -> barycentric weight matrix
|
||||
mat2 inv_dp_mat = get_inverse(dp_mat, dp_det);
|
||||
|
||||
vec2 weights = min_perp_length < 2 ? vec2(0) : inv_dp_mat * dp;
|
||||
|
||||
v0.p.xy += dp * PointSize; // Extrapolate position
|
||||
|
||||
// Extrapolate texture coords
|
||||
#if VS_TME
|
||||
#if VS_FST
|
||||
v0.ti.zw += dt * weights;
|
||||
v0.ti.xy = v0.ti.zw * TextureScale;
|
||||
#else
|
||||
v0.t.xy += dt * weights;
|
||||
v0.ti.zw = v0.t.xy / TextureScale;
|
||||
v0.t.w += dot(dq, weights);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Extrapolate and clamp color
|
||||
#if VS_IIP
|
||||
v0.c += dc * weights;
|
||||
v0.c = clamp(v0.c, vec4(0), vec4(255));
|
||||
#endif
|
||||
|
||||
v0.p.z += dot(dz, weights); // Extrapolate depth
|
||||
|
||||
v0.t.z += dot(df, weights); // Extrapolate fog
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
ProcessedVertex vtx;
|
||||
@@ -214,13 +318,10 @@ void main()
|
||||
|
||||
// Use bottom minus top for delta regardless of which vertex we are expanding.
|
||||
vec2 line_delta = is_bottom ? (vtx.p.xy - other.p.xy) : (other.p.xy - vtx.p.xy);
|
||||
vec2 line_vector = normalize(line_delta);
|
||||
#if VS_EXPAND == VS_EXPAND_LINE
|
||||
vec2 line_vector = normalize(line_delta / VertexScale);
|
||||
vec2 line_expand = vec2(line_vector.y, -line_vector.x);
|
||||
#elif VS_EXPAND == VS_EXPAND_LINE_AA1
|
||||
// Expand in y direction for shallow lines and x direction for steep lines.
|
||||
line_delta /= VertexScale;
|
||||
vec2 line_expand = abs(line_delta.x) >= abs(line_delta.y) ? vec2(0.0f, 2.0f) : vec2(2.0f, 0.0f);
|
||||
#if VS_EXPAND == VS_EXPAND_LINE_AA1
|
||||
line_expand *= 2.0f * LineAA1Width;
|
||||
#endif
|
||||
vec2 line_width = (line_expand * PointSize) / 2;
|
||||
vec2 offset = is_right ? line_width : -line_width;
|
||||
@@ -262,10 +363,14 @@ void main()
|
||||
// - Vertices 3-8: First edge expanded (2 triangles).
|
||||
// - Vertices 9-14: Second edge expanded (2 triangles).
|
||||
// - Vertices 15-20: Third edge expanded (2 triangles).
|
||||
// - Vertices 21-26: First corner cap (2 triangles).
|
||||
// - Vertices 27-32: Second corner cap (2 triangles).
|
||||
// - Vertices 33-38: Third corner cap (2 triangles).
|
||||
|
||||
uint prim_id = vid / 21;
|
||||
uint prim_offset = vid - 21 * prim_id; // range: 0-20
|
||||
uint prim_id = vid / 39;
|
||||
uint prim_offset = vid - 39 * prim_id; // range: 0-38
|
||||
bool interior = prim_offset < 3;
|
||||
bool edge = 3 <= prim_offset && prim_offset < 21;
|
||||
|
||||
if (interior)
|
||||
{
|
||||
@@ -273,7 +378,7 @@ void main()
|
||||
vsOut.inv_cov = 0.0f; // Full coverage
|
||||
vsOut.interior = 1;
|
||||
}
|
||||
else
|
||||
else if (edge)
|
||||
{
|
||||
// Vertex indices for this edge. We need all 3 for determining exterior/interior.
|
||||
uint prim_offset_edges = prim_offset - 3; // range: 0-17
|
||||
@@ -282,45 +387,69 @@ void main()
|
||||
uint i2 = (i0 >= 1) ? i0 - 1 : i0 + 2;
|
||||
uint edge_offset = prim_offset_edges - 6 * i0; // range: 0-5
|
||||
|
||||
// Note: order of top/bottom, inside/outside order is arbitrary,
|
||||
// Note: order of top/bottom, inside/outside is arbitrary,
|
||||
// as long as it assembles into two triangles forming a quad.
|
||||
bool is_bottom = (2 <= edge_offset) && (edge_offset <= 4);
|
||||
bool is_outside = (edge_offset & 1) != 0;
|
||||
|
||||
vtx = load_vertex(load_index(3 * prim_id + i0));
|
||||
ProcessedVertex other = load_vertex(load_index(3 * prim_id + i1));
|
||||
vtx = load_vertex(load_index(3 * prim_id + (is_bottom ? i1 : i0)));
|
||||
ProcessedVertex other = load_vertex(load_index(3 * prim_id + (is_bottom ? i0 : i1)));
|
||||
ProcessedVertex opposite = load_vertex(load_index(3 * prim_id + i2));
|
||||
|
||||
// Similar expansion to line AA1 except instead of expanding on both sides of
|
||||
// the line we expand on on the side towards the outside of the triangle.
|
||||
vec2 line_delta = vtx.p.xy - other.p.xy;
|
||||
vec2 line_normal = normalize(vec2(line_delta.y, -line_delta.x));
|
||||
vec2 line_expand = abs(line_delta.x) >= abs(line_delta.y) ? vec2(0.0f, 2.0f) : vec2(2.0f, 0.0f);
|
||||
if ((dot(line_expand, line_normal) >= 0.0f) == (dot(opposite.p.xy - vtx.p.xy, line_normal) >= 0.0f))
|
||||
{
|
||||
// Expand direction point towards the interior so flip it.
|
||||
line_expand = -line_expand;
|
||||
}
|
||||
vec2 line_width = (line_expand * PointSize) / 2;
|
||||
mat2 pos_deltas = get_xy_deltas_unscaled(vtx, other, opposite);
|
||||
|
||||
if (is_bottom)
|
||||
vtx = other;
|
||||
if (is_outside)
|
||||
{
|
||||
vtx.p.xy += line_width;
|
||||
vsOut.inv_cov = 1.0f; // No coverage
|
||||
}
|
||||
else
|
||||
{
|
||||
vsOut.inv_cov = 0.0f; // Full coverage
|
||||
}
|
||||
vec2 expand_dir = is_outside ? get_aa1_triangle_expand_dir(vtx, other, opposite) : vec2(0);
|
||||
|
||||
// Do actual extrapolation, or no-op if expand_dir == 0.
|
||||
extrapolate_aa1_triangle_edge(vtx, other, opposite, pos_deltas, expand_dir);
|
||||
|
||||
vsOut.inv_cov = is_outside ? 1.0f : 0.0f; // No coverage on outside, otherwise full.
|
||||
|
||||
vsOut.interior = 0;
|
||||
}
|
||||
else // Corner cap
|
||||
{
|
||||
// Vertex indices for this cap. We need all 3 for determining exterior/interior.
|
||||
uint prim_offset_cap = prim_offset - 21; // range: 0-8
|
||||
uint i0 = prim_offset_cap / 6;
|
||||
uint i1 = (i0 >= 2) ? i0 - 2 : i0 + 1;
|
||||
uint i2 = (i0 >= 1) ? i0 - 1 : i0 + 2;
|
||||
uint cap_offset = prim_offset_cap - 6 * i0; // range: 0-5
|
||||
|
||||
#if !VS_IIP
|
||||
// Get the provoking vertex color (last vertex in VK)
|
||||
vtx.c = i0 == 2 ? vtx.c : (i1 == 2 ? other.c : opposite.c);
|
||||
#endif
|
||||
bool is_near_corner = cap_offset == 0 || cap_offset == 3;
|
||||
bool is_far_corner = cap_offset == 2 || cap_offset == 5;
|
||||
bool is_first_tri = cap_offset < 3;
|
||||
|
||||
// First triangle is on the side of vertex i1 and second is on the side of vertex i2.
|
||||
vtx = load_vertex(load_index(3 * prim_id + i0));
|
||||
ProcessedVertex other = load_vertex(load_index(3 * prim_id + (is_first_tri ? i1 : i2)));
|
||||
ProcessedVertex opposite = load_vertex(load_index(3 * prim_id + (is_first_tri ? i2 : i1)));
|
||||
|
||||
mat2 pos_deltas = get_xy_deltas_unscaled(vtx, other, opposite);
|
||||
|
||||
// Get the edge expansion directions of both incident edges.
|
||||
vec2 edge_expand_dir_0 = get_aa1_triangle_expand_dir(vtx, other, opposite);
|
||||
vec2 edge_expand_dir_1 = get_aa1_triangle_expand_dir(vtx, opposite, other);
|
||||
|
||||
// Check if the corner is already filled by the expanded edges.
|
||||
// This happens if the expand directions are the same.
|
||||
// If so we output a degenerate triangle at this corner.
|
||||
bool corner_filled = all(equal(edge_expand_dir_0, edge_expand_dir_1));
|
||||
|
||||
// Nothing if corner is filled, otherwise opposite to the bisector of the corner angle.
|
||||
vec2 far_corner_dir = corner_filled ? vec2(0) : -normalize((pos_deltas[0] + pos_deltas[1]) / 2);
|
||||
|
||||
// Determine the expand direction.
|
||||
vec2 expand_dir = is_near_corner ? vec2(0) : // No extrapolation
|
||||
is_far_corner ? far_corner_dir : // Opposite to the angle bisector of corner
|
||||
edge_expand_dir_0; // Standard AA1 edge expansion
|
||||
|
||||
// Do the actual extrapolation (no-op if expand_dir == 0).
|
||||
extrapolate_aa1_triangle_edge(vtx, other, opposite, pos_deltas, expand_dir);
|
||||
|
||||
vsOut.inv_cov = is_near_corner ? 0.0f : 1.0f; // Full coverage at near corner, otherwise none.
|
||||
|
||||
vsOut.interior = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -386,6 +515,12 @@ void main()
|
||||
#define PS_AA1_TRIANGLE_SW_Z 3
|
||||
#endif
|
||||
|
||||
#ifndef PS_ROV_DEPTH_NONE
|
||||
#define PS_ROV_DEPTH_NONE 0
|
||||
#define PS_ROV_DEPTH_READ_WRITE 1
|
||||
#define PS_ROV_DEPTH_READ_ONLY 2
|
||||
#endif
|
||||
|
||||
#ifndef PS_FST
|
||||
#define PS_FST 0
|
||||
#define PS_WMS 0
|
||||
@@ -438,6 +573,8 @@ void main()
|
||||
#define PS_NO_COLOR1 0
|
||||
#define PS_DATE 0
|
||||
#define PS_TEX_IS_FB 0
|
||||
#define PS_ROV_COLOR 0
|
||||
#define PS_ROV_DEPTH 0
|
||||
#endif
|
||||
|
||||
#define SW_BLEND (PS_BLEND_A || PS_BLEND_B || PS_BLEND_D)
|
||||
@@ -450,7 +587,13 @@ void main()
|
||||
|
||||
#define PS_FEEDBACK_LOOP_IS_NEEDED_RT (PS_TEX_IS_FB == 1 || AFAIL_NEEDS_RT || PS_FBMASK || SW_BLEND_NEEDS_RT || SW_AD_TO_HW || (PS_DATE >= 5))
|
||||
#define PS_FEEDBACK_LOOP_IS_NEEDED_DEPTH (AFAIL_NEEDS_DEPTH || ZTST_NEEDS_DEPTH || AA1_NEEDS_DEPTH)
|
||||
#define ZWRITE (PS_ZCLAMP || PS_ZFLOOR || PS_FEEDBACK_LOOP_IS_NEEDED_DEPTH)
|
||||
#define ZWRITE (PS_ZCLAMP || PS_ZFLOOR || SW_DEPTH || PS_FEEDBACK_LOOP_IS_NEEDED_DEPTH)
|
||||
|
||||
#define PS_RETURN_COLOR_ROV (!PS_NO_COLOR && PS_ROV_COLOR)
|
||||
#define PS_RETURN_COLOR (!PS_NO_COLOR && !PS_ROV_COLOR)
|
||||
#define PS_RETURN_DEPTH_ROV (PS_ROV_DEPTH == PS_ROV_DEPTH_READ_WRITE)
|
||||
#define PS_RETURN_DEPTH (ZWRITE && !PS_ROV_DEPTH)
|
||||
#define PS_ROV_EARLYDEPTHSTENCIL (PS_ROV_COLOR && !PS_ROV_DEPTH && !ZWRITE)
|
||||
|
||||
#define NEEDS_TEX (PS_TFX != 4)
|
||||
|
||||
@@ -474,6 +617,12 @@ layout(std140, set = 0, binding = 1) uniform cb1
|
||||
mat4 DitherMatrix;
|
||||
float ScaledScaleFactor;
|
||||
float RcpScaleFactor;
|
||||
float _pad0_cb1;
|
||||
float _pad1_cb1;
|
||||
float LineCovScale;
|
||||
float _pad2_cb1;
|
||||
float _pad3_cb1;
|
||||
float _pad4_cb1;
|
||||
};
|
||||
|
||||
layout(location = 0) in VSOutput
|
||||
@@ -489,11 +638,27 @@ layout(location = 0) in VSOutput
|
||||
flat uint interior; // 1 for triangle interior; 0 for edge;
|
||||
} vsIn;
|
||||
|
||||
#if !PS_NO_COLOR && !PS_NO_COLOR1
|
||||
layout(location = 0, index = 0) out vec4 o_col0;
|
||||
layout(location = 0, index = 1) out vec4 o_col1;
|
||||
#elif !PS_NO_COLOR
|
||||
layout(location = 0) out vec4 o_col0;
|
||||
#if PS_RETURN_COLOR
|
||||
#if !PS_NO_COLOR1
|
||||
layout(location = 0, index = 0) out vec4 o_col0;
|
||||
layout(location = 0, index = 1) out vec4 o_col1;
|
||||
#elif !PS_NO_COLOR
|
||||
layout(location = 0) out vec4 o_col0;
|
||||
#endif
|
||||
#elif PS_RETURN_COLOR_ROV
|
||||
vec4 o_col0;
|
||||
#endif
|
||||
|
||||
#if PS_ROV_COLOR
|
||||
layout(set = 1, binding = 5, rgba8) uniform restrict coherent image2D RtImageRov;
|
||||
vec4 rov_rt_value;
|
||||
vec4 sample_from_rt() { return rov_rt_value; }
|
||||
#endif
|
||||
|
||||
#if PS_ROV_DEPTH
|
||||
layout(set = 1, binding = 6, r32f) uniform restrict coherent image2D DepthImageRov;
|
||||
float rov_depth_value;
|
||||
float sample_from_depth() { return rov_depth_value; }
|
||||
#endif
|
||||
|
||||
#if NEEDS_TEX
|
||||
@@ -503,27 +668,27 @@ layout(set = 1, binding = 1) uniform texture2D Palette;
|
||||
|
||||
#if PS_FEEDBACK_LOOP_IS_NEEDED_RT || PS_FEEDBACK_LOOP_IS_NEEDED_DEPTH
|
||||
#if defined(DISABLE_TEXTURE_BARRIER) || defined(HAS_FEEDBACK_LOOP_LAYOUT)
|
||||
#if PS_FEEDBACK_LOOP_IS_NEEDED_RT
|
||||
#if (PS_FEEDBACK_LOOP_IS_NEEDED_RT && !PS_ROV_COLOR)
|
||||
layout(set = 1, binding = 2) uniform texture2D RtSampler;
|
||||
vec4 sample_from_rt() { return texelFetch(RtSampler, ivec2(gl_FragCoord.xy), 0); }
|
||||
#endif
|
||||
#if PS_FEEDBACK_LOOP_IS_NEEDED_DEPTH
|
||||
#if (PS_FEEDBACK_LOOP_IS_NEEDED_DEPTH && !PS_ROV_DEPTH)
|
||||
layout(set = 1, binding = 4) uniform texture2D DepthSampler;
|
||||
vec4 sample_from_depth() { return texelFetch(DepthSampler, ivec2(gl_FragCoord.xy), 0); }
|
||||
float sample_from_depth() { return texelFetch(DepthSampler, ivec2(gl_FragCoord.xy), 0).r; }
|
||||
#endif
|
||||
#else
|
||||
// Must consider each case separately since the input attachment indices must be consecutive.
|
||||
#if PS_FEEDBACK_LOOP_IS_NEEDED_RT && PS_FEEDBACK_LOOP_IS_NEEDED_DEPTH
|
||||
#if (PS_FEEDBACK_LOOP_IS_NEEDED_RT && !PS_ROV_COLOR) && (PS_FEEDBACK_LOOP_IS_NEEDED_DEPTH && !PS_ROV_DEPTH)
|
||||
layout(input_attachment_index = 0, set = 1, binding = 2) uniform subpassInput RtSampler;
|
||||
layout(input_attachment_index = 1, set = 1, binding = 4) uniform subpassInput DepthSampler;
|
||||
vec4 sample_from_rt() { return subpassLoad(RtSampler); }
|
||||
vec4 sample_from_depth() { return subpassLoad(DepthSampler); }
|
||||
#elif PS_FEEDBACK_LOOP_IS_NEEDED_RT
|
||||
float sample_from_depth() { return subpassLoad(DepthSampler).r; }
|
||||
#elif (PS_FEEDBACK_LOOP_IS_NEEDED_RT && !PS_ROV_COLOR)
|
||||
layout(input_attachment_index = 0, set = 1, binding = 2) uniform subpassInput RtSampler;
|
||||
vec4 sample_from_rt() { return subpassLoad(RtSampler); }
|
||||
#elif PS_FEEDBACK_LOOP_IS_NEEDED_DEPTH
|
||||
#elif (PS_FEEDBACK_LOOP_IS_NEEDED_DEPTH && !PS_ROV_DEPTH)
|
||||
layout(input_attachment_index = 0, set = 1, binding = 4) uniform subpassInput DepthSampler;
|
||||
vec4 sample_from_depth() { return subpassLoad(DepthSampler); }
|
||||
float sample_from_depth() { return subpassLoad(DepthSampler).r; }
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
@@ -558,22 +723,27 @@ float manual_lod(float uv_w)
|
||||
vec4 sample_c_af(vec2 uv, float uv_w)
|
||||
{
|
||||
// HW sampler will reject bad UVs, match that here.
|
||||
uv = (any(isnan(uv)) || any(isinf(uv))) ? vec2(0, 0) : uv;
|
||||
uv = (any(isnan(uv)) || any(isinf(uv))) ? vec2(0.0f, 0.0f) : uv;
|
||||
|
||||
// Large floating point values risk NaN/Inf values.
|
||||
// Above this value floats lose decimal precision, so seems a resonable limit for UVs.
|
||||
uv = clamp(uv, -8388608.0f, 8388608.0f);
|
||||
|
||||
// Below taken from https://microsoft.github.io/DirectX-Specs/d3d/archive/D3D11_3_FunctionalSpec.htm#7.18.11%20LOD%20Calculations
|
||||
// And https://registry.khronos.org/OpenGL/extensions/EXT/EXT_texture_filter_anisotropic.txt
|
||||
// With guidance from https://pema.dev/2025/05/09/mipmaps-too-much-detail/
|
||||
vec2 sz = textureSize(Texture, 0);
|
||||
vec2 dX = dFdx(uv) * sz;
|
||||
vec2 dY = dFdy(uv) * sz;
|
||||
|
||||
float length_x = length(dX);
|
||||
float length_y = length(dY);
|
||||
|
||||
// Calculate Ellipse Transform
|
||||
bool d_zero = length(dX) == 0 || length(dY) == 0;
|
||||
bool d_par = (dX.x * dY.y - dY.x * dX.y) == 0;
|
||||
bool d_per = dot(dX, dY) == 0;
|
||||
bool d_zero = length_x < 0.001f || length_y < 0.001f;
|
||||
float f = (dX.x * dY.y - dX.y * dY.x);
|
||||
bool d_par = f < 0.001f;
|
||||
bool d_per = dot(dX, dY) < 0.001f;
|
||||
bool d_inf_nan = any(isinf(dX)) || any(isinf(dY)) || any(isnan(dX)) || any(isnan(dY));
|
||||
|
||||
if (!(d_zero || d_par || d_per || d_inf_nan))
|
||||
@@ -588,31 +758,40 @@ vec4 sample_c_af(vec2 uv, float uv_w)
|
||||
float q = A + C;
|
||||
float t = sqrt(p * p + B * B);
|
||||
|
||||
float signB = sign(B);
|
||||
float denom_plus = t * (q + t);
|
||||
float denom_minus = t * (q - t);
|
||||
|
||||
float sqrtA = sqrt(F * (t + p));
|
||||
float sqrtB = sqrt(F * (t - p));
|
||||
|
||||
float inv_sqrt_denom_plus = inversesqrt(denom_plus);
|
||||
float inv_sqrt_denom_minus = inversesqrt(denom_minus);
|
||||
|
||||
vec2 new_dX = vec2(
|
||||
sqrt(F * (t + p) / (t * (q + t))),
|
||||
sqrt(F * (t - p) / (t * (q + t))) * sign(B)
|
||||
sqrtA * inv_sqrt_denom_plus,
|
||||
sqrtB * inv_sqrt_denom_plus * signB
|
||||
);
|
||||
|
||||
|
||||
vec2 new_dY = vec2(
|
||||
sqrt(F * (t - p) / (t * (q - t))) * -sign(B),
|
||||
sqrt(F * (t + p) / (t * (q - t)))
|
||||
sqrtB * inv_sqrt_denom_minus * -signB,
|
||||
sqrtA * inv_sqrt_denom_minus
|
||||
);
|
||||
|
||||
|
||||
d_inf_nan = any(isinf(new_dX)) || any(isinf(new_dY)) || any(isnan(new_dX)) || any(isnan(new_dY));
|
||||
if (!d_inf_nan)
|
||||
{
|
||||
dX = new_dX;
|
||||
dY = new_dY;
|
||||
length_x = length(dX);
|
||||
length_y = length(dY);
|
||||
}
|
||||
}
|
||||
|
||||
// Compute AF values
|
||||
float squared_length_x = dX.x * dX.x + dX.y * dX.y;
|
||||
float squared_length_y = dY.x * dY.x + dY.y * dY.y;
|
||||
float determinant = abs(dX.x * dY.y - dX.y * dY.x);
|
||||
bool is_major_x = squared_length_x > squared_length_y;
|
||||
float squared_length_major = is_major_x ? squared_length_x : squared_length_y;
|
||||
float length_major = sqrt(squared_length_major);
|
||||
bool is_major_x = length_x > length_y;
|
||||
float length_major = is_major_x ? length_x : length_y;
|
||||
float length_minor = is_major_x ? length_y : length_x;
|
||||
|
||||
float aniso_ratio;
|
||||
float length_lod;
|
||||
@@ -624,57 +803,42 @@ vec4 sample_c_af(vec2 uv, float uv_w)
|
||||
// Perform isotropic filtering instead.
|
||||
aniso_ratio = 1.0f;
|
||||
length_lod = length_major;
|
||||
aniso_line = vec2(0, 0);
|
||||
aniso_line = vec2(0.0f, 0.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
float norm_major = 1.0f / length_major;
|
||||
|
||||
vec2 aniso_line_dir = vec2(
|
||||
(is_major_x ? dX.x : dY.x) * norm_major,
|
||||
(is_major_x ? dX.y : dY.y) * norm_major
|
||||
);
|
||||
|
||||
aniso_ratio = squared_length_major / determinant;
|
||||
vec2 aniso_line_dir = is_major_x ? dX : dY;
|
||||
|
||||
// Calculate the minor length of the ellipse for Lod, while also clamping the ratio of anisotropy.
|
||||
if (aniso_ratio > PS_ANISOTROPIC_FILTERING)
|
||||
{
|
||||
// ratio is clamped - Lod is based on ratio (preserves area)
|
||||
aniso_ratio = PS_ANISOTROPIC_FILTERING;
|
||||
length_lod = length_major / PS_ANISOTROPIC_FILTERING;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ratio not clamped - Lod is based on area
|
||||
length_lod = determinant / length_major;
|
||||
}
|
||||
aniso_ratio = min(length_major / length_minor, PS_ANISOTROPIC_FILTERING);
|
||||
length_lod = length_major / aniso_ratio;
|
||||
|
||||
// clamp to top Lod
|
||||
if (length_lod < 1.0f)
|
||||
aniso_ratio = max(1.0f, aniso_ratio * length_lod);
|
||||
|
||||
aniso_ratio = round(aniso_ratio);
|
||||
aniso_line = aniso_line_dir * 0.5f * length_major * (1.0f / sz);
|
||||
|
||||
aniso_line = aniso_line_dir * 0.5f * (1.0f / sz);
|
||||
}
|
||||
|
||||
|
||||
#if PS_AUTOMATIC_LOD == 1
|
||||
float lod = log2(length_lod);
|
||||
#elif PS_MANUAL_LOD == 1
|
||||
float lod = manual_lod(uv_w);
|
||||
#else
|
||||
float lod = 0; // No Lod
|
||||
float lod = 0.0f; // No Lod
|
||||
#endif
|
||||
|
||||
|
||||
vec4 colour;
|
||||
if (aniso_ratio == 1.0f)
|
||||
colour = textureLod(Texture, uv, lod);
|
||||
else
|
||||
{
|
||||
vec4 num = vec4(0, 0, 0, 0);
|
||||
vec4 num = vec4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
vec2 segment = (2.0f * aniso_line) / aniso_ratio;
|
||||
for (int i = 0; i < aniso_ratio; i++)
|
||||
{
|
||||
vec2 d = -aniso_line + (0.5f + i) * (2.0f * aniso_line) / aniso_ratio;
|
||||
{
|
||||
vec2 d = -aniso_line + (0.5f + i) * segment;
|
||||
vec2 uv_sample = uv + d;
|
||||
vec4 sample_colour = textureLod(Texture, uv_sample, lod);
|
||||
num += sample_colour;
|
||||
@@ -978,7 +1142,7 @@ vec4 sample_depth(vec2 st, ivec2 pos)
|
||||
}
|
||||
#elif (PS_DEPTH_FMT == 1)
|
||||
{
|
||||
// Based on ps_convert_float32_rgba8 of convert
|
||||
// Based on ps_convert_depth32_rgba8 of convert
|
||||
|
||||
// Convert a vec32 depth texture into a RGBA color texture
|
||||
uint d = uint(fetch_c(uv).r * exp2(32.0f));
|
||||
@@ -986,7 +1150,7 @@ vec4 sample_depth(vec2 st, ivec2 pos)
|
||||
}
|
||||
#elif (PS_DEPTH_FMT == 2)
|
||||
{
|
||||
// Based on ps_convert_float16_rgb5a1 of convert
|
||||
// Based on ps_convert_depth16_rgb5a1 of convert
|
||||
|
||||
// Convert a vec32 (only 16 lsb) depth into a RGB5A1 color texture
|
||||
uint d = uint(fetch_c(uv).r * exp2(32.0f));
|
||||
@@ -1468,7 +1632,7 @@ void ps_blend(inout vec4 Color, inout vec4 As_rgba)
|
||||
#elif PS_BLEND_MIX == 1
|
||||
Color.rgb = ((A - B) * C_clamped + D) - (124.0f/256.0f);
|
||||
#else
|
||||
Color.rgb = trunc((A - B) * C + D);
|
||||
Color.rgb = trunc((A - B) * C + D);
|
||||
#endif
|
||||
|
||||
#if PS_BLEND_HW == 1
|
||||
@@ -1542,6 +1706,24 @@ void ps_blend(inout vec4 Color, inout vec4 As_rgba)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if PS_ROV_COLOR || PS_ROV_DEPTH
|
||||
layout(pixel_interlock_ordered) in;
|
||||
#endif
|
||||
|
||||
#if PS_ROV_EARLYDEPTHSTENCIL
|
||||
layout(early_fragment_tests) in;
|
||||
#endif
|
||||
|
||||
#if PS_ROV_COLOR || PS_ROV_DEPTH
|
||||
#define DISCARD { rov_discard_color = true; rov_discard_depth = true; }
|
||||
#define DISCARD_COLOR rov_discard_color = true
|
||||
#define DISCARD_DEPTH rov_discard_depth = true
|
||||
#else
|
||||
#define DISCARD discard
|
||||
#define DISCARD_COLOR o_col0 = sample_from_rt()
|
||||
#define DISCARD_DEPTH input_z = sample_from_depth()
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
float input_z = gl_FragCoord.z;
|
||||
@@ -1551,18 +1733,35 @@ void main()
|
||||
input_z = floor(input_z * exp2(32.0f)) * exp2(-32.0f);
|
||||
#endif
|
||||
|
||||
#if PS_ROV_COLOR || PS_ROV_DEPTH
|
||||
beginInvocationInterlockARB();
|
||||
#endif
|
||||
|
||||
#if PS_ROV_COLOR
|
||||
rov_rt_value = imageLoad(RtImageRov, ivec2(gl_FragCoord.xy));
|
||||
#endif
|
||||
|
||||
#if PS_ROV_DEPTH
|
||||
rov_depth_value = imageLoad(DepthImageRov, ivec2(gl_FragCoord.xy)).r;
|
||||
#endif
|
||||
|
||||
#if PS_ROV_COLOR || PS_ROV_DEPTH
|
||||
bool rov_discard_color = gl_HelperInvocation;
|
||||
bool rov_discard_depth = gl_HelperInvocation;
|
||||
#endif
|
||||
|
||||
#if PS_ZTST == ZTST_GEQUAL
|
||||
if (input_z < sample_from_depth().r)
|
||||
discard;
|
||||
if (input_z < sample_from_depth())
|
||||
DISCARD;
|
||||
#elif PS_ZTST == ZTST_GREATER
|
||||
if (input_z <= sample_from_depth().r)
|
||||
discard;
|
||||
if (input_z <= sample_from_depth())
|
||||
DISCARD;
|
||||
#endif
|
||||
|
||||
#if PS_SCANMSK & 2
|
||||
// fail depth test on prohibited lines
|
||||
if ((int(gl_FragCoord.y) & 1) == (PS_SCANMSK & 1))
|
||||
discard;
|
||||
DISCARD;
|
||||
#endif
|
||||
#if PS_DATE >= 5
|
||||
|
||||
@@ -1590,7 +1789,7 @@ void main()
|
||||
#endif
|
||||
|
||||
if (bad) {
|
||||
discard;
|
||||
DISCARD;
|
||||
}
|
||||
|
||||
#endif // PS_DATE >= 5
|
||||
@@ -1601,14 +1800,19 @@ void main()
|
||||
// the bad alpha value so we must keep it.
|
||||
|
||||
if (gl_PrimitiveID > stencil_ceil) {
|
||||
discard;
|
||||
DISCARD;
|
||||
}
|
||||
#endif
|
||||
|
||||
vec4 C = ps_color();
|
||||
|
||||
#if PS_AA1
|
||||
float cov = clamp(1.0f - abs(vsIn.inv_cov), 0.0f, 1.0f);
|
||||
#if PS_AA1 == PS_AA1_LINE
|
||||
// Blur only outer part of the line by scaling coverage.
|
||||
float cov = clamp(LineCovScale * (1.0f - abs(vsIn.inv_cov)), 0.0f, 1.0f);
|
||||
#else
|
||||
float cov = clamp(1.0f - abs(vsIn.inv_cov), 0.0f, 1.0f);
|
||||
#endif
|
||||
#if PS_ABE
|
||||
if (floor(C.a) == 128.0f) // The coverage is only used if the fragment alpha is 128.
|
||||
C.a = 128.0f * cov;
|
||||
@@ -1622,9 +1826,10 @@ void main()
|
||||
|
||||
bool atst_pass = atst(C);
|
||||
|
||||
#if PS_AFAIL == AFAIL_KEEP
|
||||
if (!atst_pass)
|
||||
discard;
|
||||
#if PS_ATST != PS_ATST_NONE && PS_AFAIL == AFAIL_KEEP
|
||||
if (!atst_pass) {
|
||||
DISCARD;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SW_AD_TO_HW
|
||||
@@ -1716,6 +1921,7 @@ void main()
|
||||
alpha_blend.a = float(atst_pass);
|
||||
#endif
|
||||
|
||||
// Output color scaling
|
||||
#if !PS_NO_COLOR
|
||||
#if PS_RTA_CORRECTION
|
||||
o_col0.a = C.a / 128.0f;
|
||||
@@ -1734,16 +1940,16 @@ void main()
|
||||
// Alpha test with feedback
|
||||
#if PS_AFAIL == AFAIL_FB_ONLY
|
||||
if (!atst_pass)
|
||||
input_z = sample_from_depth().r;
|
||||
DISCARD_DEPTH;
|
||||
#elif PS_AFAIL == AFAIL_ZB_ONLY
|
||||
if (!atst_pass)
|
||||
o_col0 = sample_from_rt();
|
||||
DISCARD_COLOR;
|
||||
#elif (PS_AFAIL == AFAIL_RGB_ONLY || PS_AFAIL == AFAIL_RGB_ONLY_SW_Z)
|
||||
if (!atst_pass)
|
||||
{
|
||||
o_col0.a = sample_from_rt().a;
|
||||
o_col0.a = sample_from_rt().a; // discard alpha
|
||||
#if PS_AFAIL == AFAIL_RGB_ONLY_SW_Z
|
||||
input_z = sample_from_depth().r;
|
||||
DISCARD_DEPTH;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@@ -1755,11 +1961,27 @@ void main()
|
||||
|
||||
#if PS_AA1 == PS_AA1_TRIANGLE_SW_Z
|
||||
if (!bool(vsIn.interior))
|
||||
input_z = sample_from_depth().r; // No depth update for triangle edges.
|
||||
DISCARD_DEPTH; // No depth update for triangle edges.
|
||||
#endif
|
||||
|
||||
#if ZWRITE
|
||||
// Writing back color (result already written to o_col0 for non-ROV)
|
||||
#if PS_RETURN_COLOR_ROV
|
||||
o_col0 = mix(o_col0, sample_from_rt(), equal(FbMask, uvec4(0xFFu))); // channel masking
|
||||
|
||||
if (!rov_discard_color)
|
||||
imageStore(RtImageRov, ivec2(gl_FragCoord.xy), o_col0);
|
||||
#endif
|
||||
|
||||
// Writing back depth
|
||||
#if PS_RETURN_DEPTH
|
||||
gl_FragDepth = input_z;
|
||||
#elif PS_RETURN_DEPTH_ROV
|
||||
if (!rov_discard_depth)
|
||||
imageStore(DepthImageRov, ivec2(gl_FragCoord.xy), vec4(input_z, 0, 0, 1.0f));
|
||||
#endif
|
||||
|
||||
#if PS_ROV_COLOR || PS_ROV_DEPTH
|
||||
endInvocationInterlockARB();
|
||||
#endif
|
||||
#endif // PS_DATE
|
||||
}
|
||||
|
||||
@@ -300,8 +300,8 @@ else()
|
||||
if(CMAKE_INTERPROCEDURAL_OPTIMIZATION)
|
||||
message(WARNING
|
||||
"The CMAKE_INTERPROCEDURAL_OPTIMIZATION option is enabled but the "
|
||||
"CMAKE_POSITION_INDEPENDENT_CODE option is disabled. This has been "
|
||||
"found to result in broken builds on certain platforms.")
|
||||
"POSITION_INDEPENDENT_CODE option is disabled. This has been found "
|
||||
"to result in broken builds on certain platforms.")
|
||||
endif()
|
||||
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE OFF)
|
||||
|
||||
@@ -22,6 +22,9 @@ find_package(Freetype 2.10 REQUIRED) # 2.10 is the first with COLRv0 support, wh
|
||||
find_package(plutovg 1.1.0 REQUIRED)
|
||||
find_package(plutosvg 0.0.7 REQUIRED)
|
||||
find_package(ryml REQUIRED)
|
||||
if (WIN32)
|
||||
find_package(DirectX-Headers 1.618.1 REQUIRED)
|
||||
endif()
|
||||
|
||||
if(USE_VULKAN)
|
||||
find_package(Shaderc REQUIRED)
|
||||
|
||||
+13
-3
@@ -98,14 +98,25 @@ __ri void Log::WriteToConsole(LOGLEVEL level, ConsoleColors color, std::string_v
|
||||
|
||||
static constexpr size_t BUFFER_SIZE = 512;
|
||||
|
||||
#ifdef _WIN32
|
||||
constexpr bool supports_color_codes = true;
|
||||
#else
|
||||
const int fd = (level <= LOGLEVEL_WARNING) ? STDERR_FILENO : STDOUT_FILENO;
|
||||
const bool supports_color_codes = static_cast<bool>(isatty(fd));
|
||||
#endif
|
||||
|
||||
SmallStackString<BUFFER_SIZE> buffer;
|
||||
buffer.reserve(static_cast<u32>(32 + message.length()));
|
||||
buffer.append(s_ansi_color_codes[color]);
|
||||
if (supports_color_codes)
|
||||
buffer.append(s_ansi_color_codes[color]);
|
||||
|
||||
if (s_log_timestamps)
|
||||
buffer.append_format(TIMESTAMP_FORMAT_STRING, Log::GetCurrentMessageTime());
|
||||
|
||||
buffer.append(message);
|
||||
|
||||
if (supports_color_codes)
|
||||
buffer.append(s_ansi_color_codes[Color_Default]);
|
||||
buffer.append('\n');
|
||||
|
||||
#ifdef _WIN32
|
||||
@@ -134,7 +145,6 @@ cleanup:
|
||||
if (wmessage_buf != wbuf)
|
||||
std::free(wmessage_buf);
|
||||
#else
|
||||
const int fd = (level <= LOGLEVEL_WARNING) ? STDERR_FILENO : STDOUT_FILENO;
|
||||
write(fd, buffer.data(), buffer.length());
|
||||
#endif
|
||||
}
|
||||
@@ -157,7 +167,7 @@ void Log::SetConsoleOutputLevel(LOGLEVEL level)
|
||||
if (was_enabled == now_enabled)
|
||||
return;
|
||||
|
||||
// Worst that happens here is we write to a bad handle..
|
||||
// Worst that happens here is we write to a bad handle..
|
||||
|
||||
#if defined(_WIN32)
|
||||
static constexpr auto enable_virtual_terminal_processing = [](HANDLE hConsole) {
|
||||
|
||||
@@ -56,6 +56,11 @@ bool HTTPDownloaderWinHttp::Initialize(std::string user_agent)
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD timeout_ms = 15000;
|
||||
WinHttpSetOption(m_hSession, WINHTTP_OPTION_CONNECT_TIMEOUT, &timeout_ms, sizeof(timeout_ms));
|
||||
WinHttpSetOption(m_hSession, WINHTTP_OPTION_SEND_TIMEOUT, &timeout_ms, sizeof(timeout_ms));
|
||||
WinHttpSetOption(m_hSession, WINHTTP_OPTION_RECEIVE_TIMEOUT, &timeout_ms, sizeof(timeout_ms));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -290,10 +295,13 @@ bool HTTPDownloaderWinHttp::StartRequest(HTTPDownloader::Request* request)
|
||||
req->status_code = HTTP_STATUS_ERROR;
|
||||
req->state.store(Request::State::Complete);
|
||||
}
|
||||
else
|
||||
{
|
||||
DevCon.WriteLn("Started HTTP request for '%s'", req->url.c_str());
|
||||
req->state = Request::State::Started;
|
||||
req->start_time = Common::Timer::GetCurrentValue();
|
||||
}
|
||||
|
||||
DevCon.WriteLn("Started HTTP request for '%s'", req->url.c_str());
|
||||
req->state = Request::State::Started;
|
||||
req->start_time = Common::Timer::GetCurrentValue();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,34 @@ Value MemoryInterface::Read(u32 address, bool* valid)
|
||||
return Value(0);
|
||||
}
|
||||
|
||||
std::optional<std::string> MemoryInterface::ReadString(u32 address, u32 max_size, ReadStringFlags flags)
|
||||
{
|
||||
std::string string;
|
||||
|
||||
for (u32 i = 0; i < max_size; i++)
|
||||
{
|
||||
bool valid;
|
||||
char c = Read8(address + i, &valid);
|
||||
if (!valid)
|
||||
return std::nullopt;
|
||||
|
||||
if (c == '\0')
|
||||
return string;
|
||||
else if (!(flags & ALLOW_NON_PRINTABLE_CHARACTERS) && (c < ' ' || c > '~'))
|
||||
return std::nullopt;
|
||||
|
||||
string += c;
|
||||
}
|
||||
|
||||
if (flags & ALLOW_LONG_STRINGS)
|
||||
{
|
||||
string += '~';
|
||||
return string;
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
template <MemoryAccessType Value>
|
||||
bool MemoryInterface::Write(u32 address, Value value)
|
||||
{
|
||||
@@ -62,6 +90,17 @@ bool MemoryInterface::Write(u32 address, Value value)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MemoryInterface::WriteString(u32 address, std::string_view string)
|
||||
{
|
||||
if (!WriteBytes(address, string.data(), static_cast<u32>(string.size())))
|
||||
return false;
|
||||
|
||||
if (!Write8(address + static_cast<u32>(string.size()), '\0'))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MemoryInterface::IdempotentWrite8(u32 address, u8 value)
|
||||
{
|
||||
bool valid;
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
|
||||
#include "Pcsx2Types.h"
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
|
||||
template <typename Value>
|
||||
@@ -31,16 +34,27 @@ public:
|
||||
template <MemoryAccessType Value>
|
||||
Value Read(u32 address, bool* valid = nullptr);
|
||||
|
||||
enum ReadStringFlags
|
||||
{
|
||||
NO_FLAGS = 0,
|
||||
ALLOW_LONG_STRINGS = 1 << 0,
|
||||
ALLOW_NON_PRINTABLE_CHARACTERS = 1 << 1
|
||||
};
|
||||
|
||||
std::optional<std::string> ReadString(u32 address, u32 max_size = 256, ReadStringFlags flags = NO_FLAGS);
|
||||
|
||||
virtual bool Write8(u32 address, u8 value) = 0;
|
||||
virtual bool Write16(u32 address, u16 value) = 0;
|
||||
virtual bool Write32(u32 address, u32 value) = 0;
|
||||
virtual bool Write64(u32 address, u64 value) = 0;
|
||||
virtual bool Write128(u32 address, u128 value) = 0;
|
||||
virtual bool WriteBytes(u32 address, void* src, u32 size) = 0;
|
||||
virtual bool WriteBytes(u32 address, const void* src, u32 size) = 0;
|
||||
|
||||
template <MemoryAccessType Value>
|
||||
bool Write(u32 address, Value value);
|
||||
|
||||
bool WriteString(u32 address, std::string_view string);
|
||||
|
||||
bool IdempotentWrite8(u32 address, u8 value);
|
||||
bool IdempotentWrite16(u32 address, u16 value);
|
||||
bool IdempotentWrite32(u32 address, u32 value);
|
||||
@@ -51,5 +65,5 @@ public:
|
||||
template <MemoryAccessType Value>
|
||||
bool IdempotentWrite(u32 address, Value value);
|
||||
|
||||
virtual bool CompareBytes(u32 address, void* src, u32 size) = 0;
|
||||
virtual bool CompareBytes(u32 address, const void* src, u32 size) = 0;
|
||||
};
|
||||
|
||||
+88
-26
@@ -17,7 +17,7 @@ struct RapidYAMLContext
|
||||
Error* error = nullptr;
|
||||
};
|
||||
|
||||
std::optional<ryml::Tree> ParseYAMLFromString(ryml::csubstr yaml, ryml::csubstr file_name, Error* error)
|
||||
std::optional<ryml::Tree> ParseYAMLFromString(ryml::csubstr yaml, ryml::csubstr file_name, Error* error, bool resolve_anchors)
|
||||
{
|
||||
RapidYAMLContext context;
|
||||
context.error = error;
|
||||
@@ -28,40 +28,93 @@ std::optional<ryml::Tree> ParseYAMLFromString(ryml::csubstr yaml, ryml::csubstr
|
||||
callbacks.set_user_data(static_cast<void*>(&context));
|
||||
|
||||
callbacks.set_error_basic([](ryml::csubstr msg, const ryml::ErrorDataBasic& errdata, void* user_data) {
|
||||
std::string description;
|
||||
auto callback = [&description](ryml::csubstr string) {
|
||||
description.append(string.str, string.len);
|
||||
};
|
||||
ryml::err_basic_format(std::move(callback), msg, errdata);
|
||||
RapidYAMLContext* context = static_cast<RapidYAMLContext*>(user_data);
|
||||
// This scope needs to stay, so all objects destruct before std::longjump
|
||||
{
|
||||
std::string description;
|
||||
auto callback = [&description](ryml::csubstr string) {
|
||||
description.append(string.str, string.len);
|
||||
};
|
||||
ryml::err_basic_format(std::move(callback), msg, errdata);
|
||||
|
||||
// We might have already returned, so don't try to recover.
|
||||
pxFailRel(description.c_str());
|
||||
std::abort();
|
||||
if (context != nullptr)
|
||||
{
|
||||
Error::SetString(context->error, std::move(description));
|
||||
}
|
||||
else
|
||||
{
|
||||
pxFailRel(description.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (context != nullptr)
|
||||
{
|
||||
std::longjmp(context->env, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::terminate();
|
||||
}
|
||||
});
|
||||
|
||||
callbacks.set_error_parse([](ryml::csubstr msg, const ryml::ErrorDataParse& errdata, void* user_data) {
|
||||
RapidYAMLContext* context = static_cast<RapidYAMLContext*>(user_data);
|
||||
// This scope needs to stay, so all objects destruct before std::longjump
|
||||
{
|
||||
std::string description;
|
||||
auto callback = [&description](ryml::csubstr string) {
|
||||
description.append(string.str, string.len);
|
||||
};
|
||||
ryml::err_parse_format(std::move(callback), msg, errdata);
|
||||
|
||||
std::string description;
|
||||
auto callback = [&description](ryml::csubstr string) {
|
||||
description.append(string.str, string.len);
|
||||
};
|
||||
ryml::err_parse_format(std::move(callback), msg, errdata);
|
||||
if (context != nullptr)
|
||||
{
|
||||
Error::SetString(context->error, std::move(description));
|
||||
}
|
||||
else
|
||||
{
|
||||
pxFailRel(description.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
Error::SetString(context->error, std::move(description));
|
||||
std::longjmp(context->env, 1);
|
||||
if (context != nullptr)
|
||||
{
|
||||
std::longjmp(context->env, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::terminate();
|
||||
}
|
||||
});
|
||||
|
||||
callbacks.set_error_visit([](ryml::csubstr msg, const ryml::ErrorDataVisit& errdata, void* user_data) {
|
||||
std::string description;
|
||||
auto callback = [&description](ryml::csubstr string) {
|
||||
description.append(string.str, string.len);
|
||||
};
|
||||
ryml::err_visit_format(std::move(callback), msg, errdata);
|
||||
RapidYAMLContext* context = static_cast<RapidYAMLContext*>(user_data);
|
||||
// This scope needs to stay, so all objects destruct before std::longjump
|
||||
{
|
||||
std::string description;
|
||||
auto callback = [&description](ryml::csubstr string) {
|
||||
description.append(string.str, string.len);
|
||||
};
|
||||
ryml::err_visit_format(std::move(callback), msg, errdata);
|
||||
|
||||
// We've probably already returned, so don't try to recover.
|
||||
pxFailRel(description.c_str());
|
||||
std::abort();
|
||||
if (context != nullptr)
|
||||
{
|
||||
Error::SetString(context->error, std::move(description));
|
||||
}
|
||||
else
|
||||
{
|
||||
pxFailRel(description.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (context != nullptr)
|
||||
{
|
||||
std::longjmp(context->env, 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::terminate();
|
||||
}
|
||||
});
|
||||
#else
|
||||
callbacks.m_user_data = static_cast<void*>(&context);
|
||||
@@ -76,15 +129,24 @@ std::optional<ryml::Tree> ParseYAMLFromString(ryml::csubstr yaml, ryml::csubstr
|
||||
ryml::EventHandlerTree event_handler(callbacks);
|
||||
ryml::Parser parser(&event_handler);
|
||||
|
||||
ryml::Tree tree;
|
||||
ryml::Tree tree(callbacks);
|
||||
|
||||
// The only options RapidYAML provides for recovering from errors are
|
||||
// throwing an exception or using setjmp/longjmp. Since we have exceptions
|
||||
// disabled we have to use the latter option.
|
||||
if (setjmp(context.env))
|
||||
if (setjmp(context.env) != 0)
|
||||
return std::nullopt;
|
||||
|
||||
ryml::parse_in_arena(&parser, file_name, yaml, &tree);
|
||||
if (resolve_anchors)
|
||||
{
|
||||
tree.resolve();
|
||||
}
|
||||
|
||||
// Callbacks passed to ryml::Tree are used for value parsing errors later,
|
||||
// so we need to clear the context before it goes out of scope.
|
||||
callbacks.set_user_data(nullptr);
|
||||
tree.callbacks(callbacks);
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
+3
-1
@@ -14,4 +14,6 @@
|
||||
/// parsing errors (as is recommended by the documentation for cases where
|
||||
/// exceptions are disabled). The file_name parameter is only used for error
|
||||
/// messages, which are returned via the error parameter.
|
||||
std::optional<ryml::Tree> ParseYAMLFromString(ryml::csubstr yaml, ryml::csubstr file_name, Error* error);
|
||||
/// If resolve_anchors is set to true, YAML anchors and aliases will be resolved.
|
||||
/// It's a potentially slow operation, so it's opt-in.
|
||||
std::optional<ryml::Tree> ParseYAMLFromString(ryml::csubstr yaml, ryml::csubstr file_name, Error* error, bool resolve_anchors = false);
|
||||
|
||||
@@ -163,6 +163,7 @@
|
||||
<ClInclude Include="WindowInfo.h" />
|
||||
<ClInclude Include="YAML.h" />
|
||||
<ClInclude Include="Threading.h" />
|
||||
<ClInclude Include="EnumOps.h" />
|
||||
<ClInclude Include="emitter\implement\avx.h" />
|
||||
<ClInclude Include="emitter\implement\bmi.h" />
|
||||
<ClInclude Include="emitter\instructions.h" />
|
||||
|
||||
@@ -30,8 +30,6 @@ namespace x86Emitter
|
||||
extern void EmitRex(SIMDInstructionInfo info, const xRegisterBase& reg1, const xRegisterBase& reg2);
|
||||
extern void EmitRex(SIMDInstructionInfo info, const xRegisterBase& reg1, const xIndirectVoid& sib);
|
||||
|
||||
extern void _xMovRtoR(const xRegisterInt& to, const xRegisterInt& from);
|
||||
|
||||
template <typename T>
|
||||
inline void xWrite(T val)
|
||||
{
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
namespace x86Emitter
|
||||
{
|
||||
|
||||
void _xMovRtoR(const xRegisterInt& to, const xRegisterInt& from)
|
||||
void xImpl_Mov::operator()(const xRegisterInt& to, const xRegisterInt& from) const
|
||||
{
|
||||
pxAssert(to.GetOperandSize() == from.GetOperandSize());
|
||||
|
||||
@@ -32,12 +32,6 @@ namespace x86Emitter
|
||||
xOpWrite(from.GetPrefix16(), from.Is8BitOp() ? 0x88 : 0x89, from, to);
|
||||
}
|
||||
|
||||
void xImpl_Mov::operator()(const xRegisterInt& to, const xRegisterInt& from) const
|
||||
{
|
||||
// FIXME WTF?
|
||||
_xMovRtoR(to, from);
|
||||
}
|
||||
|
||||
void xImpl_Mov::operator()(const xIndirectVoid& dest, const xRegisterInt& from) const
|
||||
{
|
||||
// mov eax has a special from when writing directly to a DISP32 address
|
||||
|
||||
@@ -1045,7 +1045,7 @@ const xRegister32
|
||||
}
|
||||
else if (displacement_size == 0)
|
||||
{
|
||||
_xMovRtoR(to, src.Index.MatchSizeTo(to));
|
||||
xMOV(to, src.Index.MatchSizeTo(to));
|
||||
return;
|
||||
}
|
||||
else if (!preserve_flags)
|
||||
@@ -1053,7 +1053,7 @@ const xRegister32
|
||||
// encode as MOV and ADD combo. Make sure to use the immediate on the
|
||||
// ADD since it can encode as an 8-bit sign-extended value.
|
||||
|
||||
_xMovRtoR(to, src.Index.MatchSizeTo(to));
|
||||
xMOV(to, src.Index.MatchSizeTo(to));
|
||||
xADD(to, src.Displacement);
|
||||
return;
|
||||
}
|
||||
@@ -1071,7 +1071,7 @@ const xRegister32
|
||||
// (this does not apply to older model P4s with the broken barrel shifter,
|
||||
// but we currently aren't optimizing for that target anyway).
|
||||
|
||||
_xMovRtoR(to, src.Index);
|
||||
xMOV(to, src.Index);
|
||||
xSHL(to, src.Scale);
|
||||
return;
|
||||
}
|
||||
@@ -1085,14 +1085,14 @@ const xRegister32
|
||||
if (src.Index == rsp)
|
||||
{
|
||||
// ESP is not encodable as an index (ix86 ignores it), thus:
|
||||
_xMovRtoR(to, src.Base.MatchSizeTo(to)); // will do the trick!
|
||||
xMOV(to, src.Base.MatchSizeTo(to)); // will do the trick!
|
||||
if (src.Displacement)
|
||||
xADD(to, src.Displacement);
|
||||
return;
|
||||
}
|
||||
else if (src.Displacement == 0)
|
||||
{
|
||||
_xMovRtoR(to, src.Base.MatchSizeTo(to));
|
||||
xMOV(to, src.Base.MatchSizeTo(to));
|
||||
xADD(to, src.Index.MatchSizeTo(to));
|
||||
return;
|
||||
}
|
||||
@@ -1102,7 +1102,7 @@ const xRegister32
|
||||
// special case handling of ESP as Index, which is replaceable with
|
||||
// a single MOV even when preserve_flags is set! :D
|
||||
|
||||
_xMovRtoR(to, src.Base.MatchSizeTo(to));
|
||||
xMOV(to, src.Base.MatchSizeTo(to));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<DepsRootDir Condition="'$(Platform)'=='x64'">$(SolutionDir)deps\</DepsRootDir>
|
||||
<DepsRootDir Condition="'$(Platform)'=='ARM64'">$(SolutionDir)deps-arm64\</DepsRootDir>
|
||||
<DepsBinDir>$(DepsRootDir)bin\</DepsBinDir>
|
||||
<DepsLibDir>$(DepsRootDir)lib\</DepsLibDir>
|
||||
<DepsIncludeDir>$(DepsRootDir)include\</DepsIncludeDir>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -1,5 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="DepsDir.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros">
|
||||
<SSEString />
|
||||
<SSEString Condition="$(Configuration.Contains(AVX2))">-avx2</SSEString>
|
||||
@@ -15,11 +18,6 @@
|
||||
<PropertyGroup>
|
||||
<OutDir>$(SolutionDir)build\lib-$(PlatformName)-$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)build\obj-$(ProjectName)-$(PlatformName)-$(Configuration)\</IntDir>
|
||||
<DepsRootDir Condition="'$(Platform)'=='x64'">$(SolutionDir)deps\</DepsRootDir>
|
||||
<DepsRootDir Condition="'$(Platform)'=='ARM64'">$(SolutionDir)deps-arm64\</DepsRootDir>
|
||||
<DepsBinDir>$(DepsRootDir)bin\</DepsBinDir>
|
||||
<DepsLibDir>$(DepsRootDir)lib\</DepsLibDir>
|
||||
<DepsIncludeDir>$(DepsRootDir)include\</DepsIncludeDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
|
||||
+17
-10
@@ -91,6 +91,9 @@ static double s_last_barriers = 0;
|
||||
static double s_last_copies = 0;
|
||||
static double s_last_uploads = 0;
|
||||
static double s_last_readbacks = 0;
|
||||
static double s_last_depth_copies_rov = 0;
|
||||
static double s_last_draws_rov = 0;
|
||||
static double s_last_barriers_rov = 0;
|
||||
static u64 s_total_internal_draws = 0;
|
||||
static u64 s_total_draws = 0;
|
||||
static u64 s_total_render_passes = 0;
|
||||
@@ -98,6 +101,9 @@ static u64 s_total_barriers = 0;
|
||||
static u64 s_total_copies = 0;
|
||||
static u64 s_total_uploads = 0;
|
||||
static u64 s_total_readbacks = 0;
|
||||
static u64 s_total_copies_rov = 0;
|
||||
static u64 s_total_draws_rov = 0;
|
||||
static u64 s_total_barriers_rov = 0;
|
||||
static u32 s_total_frames = 0;
|
||||
static u32 s_total_drawn_frames = 0;
|
||||
|
||||
@@ -216,6 +222,11 @@ bool Host::CopyTextToClipboard(const std::string_view text)
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string Host::GetTextFromClipboard()
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
|
||||
void Host::BeginTextInput()
|
||||
{
|
||||
// noop
|
||||
@@ -287,6 +298,9 @@ void Host::BeginPresentFrame()
|
||||
update_stat(GSPerfMon::TextureCopies, s_total_copies, s_last_copies);
|
||||
update_stat(GSPerfMon::TextureUploads, s_total_uploads, s_last_uploads);
|
||||
update_stat(GSPerfMon::Readbacks, s_total_readbacks, s_last_readbacks);
|
||||
update_stat(GSPerfMon::TextureCopiesROV, s_total_copies_rov, s_last_depth_copies_rov);
|
||||
update_stat(GSPerfMon::DrawCallsROV, s_total_draws_rov, s_last_draws_rov);
|
||||
update_stat(GSPerfMon::BarriersROV, s_total_barriers_rov, s_last_barriers_rov);
|
||||
|
||||
const bool idle_frame = s_total_frames && (last_draws == s_total_internal_draws && last_uploads == s_total_uploads);
|
||||
|
||||
@@ -419,16 +433,6 @@ void Host::OnAchievementsRefreshed()
|
||||
// noop
|
||||
}
|
||||
|
||||
void Host::OnCoverDownloaderOpenRequested()
|
||||
{
|
||||
// noop
|
||||
}
|
||||
|
||||
void Host::OnCreateMemoryCardOpenRequested()
|
||||
{
|
||||
// noop
|
||||
}
|
||||
|
||||
bool Host::InBatchMode()
|
||||
{
|
||||
return false;
|
||||
@@ -913,6 +917,9 @@ void GSRunner::DumpStats()
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Copies: {} (avg {})", s_total_copies, static_cast<u64>(std::ceil(s_total_copies / static_cast<double>(s_total_drawn_frames)))));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Uploads: {} (avg {})", s_total_uploads, static_cast<u64>(std::ceil(s_total_uploads / static_cast<double>(s_total_drawn_frames)))));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Readbacks: {} (avg {})", s_total_readbacks, static_cast<u64>(std::ceil(s_total_readbacks / static_cast<double>(s_total_drawn_frames)))));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Copies (ROV): {} (avg {})", s_total_copies_rov, static_cast<u64>(std::ceil(s_total_copies_rov / static_cast<double>(s_total_drawn_frames)))));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Draws Calls (ROV): {} (avg {})", s_total_draws_rov, static_cast<u64>(std::ceil(s_total_draws_rov / static_cast<double>(s_total_drawn_frames)))));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Barriers (ROV): {} (avg {})", s_total_barriers_rov, static_cast<u64>(std::ceil(s_total_barriers_rov / static_cast<double>(s_total_drawn_frames)))));
|
||||
if (s_perf_enable)
|
||||
{
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Minimum Frame Time: {:.3f} ms ({:.3f} FPS)", PerformanceMetrics::GetMinimumFrameTime(), 1000.0f / PerformanceMetrics::GetMinimumFrameTime()));
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user