mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-03-31 05:15:55 -05:00
Compare commits
291 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a8f19cc90 | ||
|
|
854535fec6 | ||
|
|
a109e14ee3 | ||
|
|
eca7597aca | ||
|
|
936b5b6312 | ||
|
|
cea63f6561 | ||
|
|
7083b6ab3e | ||
|
|
432e16e0c4 | ||
|
|
8d691b2e6a | ||
|
|
f3ccbb9b84 | ||
|
|
a4af283a37 | ||
|
|
27935b1234 | ||
|
|
ea0b97a066 | ||
|
|
e668feb807 | ||
|
|
21a94d67c2 | ||
|
|
fbd6d6b9fc | ||
|
|
257d122a9f | ||
|
|
f7f70a16da | ||
|
|
aa5a83444d | ||
|
|
d25c80c0a5 | ||
|
|
6f83b050cd | ||
|
|
72e177aafc | ||
|
|
5648378837 | ||
|
|
c1cdef7ca1 | ||
|
|
4b07f7745b | ||
|
|
a2fc9325c9 | ||
|
|
380b1dbce3 | ||
|
|
04a8bd6798 | ||
|
|
0cf27b9e9e | ||
|
|
4a091f452e | ||
|
|
ffa8b0d0db | ||
|
|
ff65217b7e | ||
|
|
1b90bb2c34 | ||
|
|
1018aea395 | ||
|
|
d20d6736b3 | ||
|
|
5333a33775 | ||
|
|
0d9ea8a1d1 | ||
|
|
b6a90aa89d | ||
|
|
060f0e6e56 | ||
|
|
800a24b42e | ||
|
|
a5008722aa | ||
|
|
a0b0082d98 | ||
|
|
f476842008 | ||
|
|
d39d107de4 | ||
|
|
7f889a75bb | ||
|
|
70fdbd4a48 | ||
|
|
71c71c5bbf | ||
|
|
ade8c8f68d | ||
|
|
16b02caf7a | ||
|
|
dc1c205fb1 | ||
|
|
b974533f96 | ||
|
|
81e561d47b | ||
|
|
b9e0a9f0e6 | ||
|
|
954bcadd75 | ||
|
|
d6781e7f93 | ||
|
|
fc38c27769 | ||
|
|
96a5a5d34c | ||
|
|
928e0f227a | ||
|
|
93fc6f2de1 | ||
|
|
cdc260b45c | ||
|
|
0e41813cfc | ||
|
|
a7e94e31c9 | ||
|
|
2903a97941 | ||
|
|
753e1ceff6 | ||
|
|
06f4d12f10 | ||
|
|
684c2e66fb | ||
|
|
4a311ed69f | ||
|
|
220b5f9772 | ||
|
|
42fd5b0fef | ||
|
|
c28492e51d | ||
|
|
d8ff84672c | ||
|
|
2af967d788 | ||
|
|
8cb23e8200 | ||
|
|
9a058efc79 | ||
|
|
06c8cb51e3 | ||
|
|
01e8ae1b5c | ||
|
|
b052cb001c | ||
|
|
d004eb3048 | ||
|
|
dccd74667e | ||
|
|
6b6470850f | ||
|
|
f09b1aae23 | ||
|
|
68487bc903 | ||
|
|
ebd78e1526 | ||
|
|
6d0dfcfe2e | ||
|
|
5b01d23ed7 | ||
|
|
d9eb01b526 | ||
|
|
9e165ac4a1 | ||
|
|
25ab371a81 | ||
|
|
d62abaed8d | ||
|
|
1fb7a318ed | ||
|
|
e29ae631fc | ||
|
|
3cc0b9294e | ||
|
|
e80f7fa14f | ||
|
|
9261fd7190 | ||
|
|
58c714b350 | ||
|
|
5cd3f5c255 | ||
|
|
0d443d7d00 | ||
|
|
38fecca489 | ||
|
|
f655ea59a8 | ||
|
|
aa7daa5c54 | ||
|
|
f4b2be9334 | ||
|
|
edbd8a811e | ||
|
|
ea9b197d36 | ||
|
|
a0a049a920 | ||
|
|
550fe8e4aa | ||
|
|
2064aea3b6 | ||
|
|
3411bc4577 | ||
|
|
6eedb469e9 | ||
|
|
684373b88b | ||
|
|
08aa03bab6 | ||
|
|
62bc953d53 | ||
|
|
5263f81487 | ||
|
|
8272ebf68f | ||
|
|
90d8e03f2c | ||
|
|
0d34edc7f6 | ||
|
|
63fd61e245 | ||
|
|
58fe8a22a9 | ||
|
|
03dd20c263 | ||
|
|
712a125be7 | ||
|
|
49e14e6e7c | ||
|
|
e8a6e102c3 | ||
|
|
b2cc09852d | ||
|
|
60627b8325 | ||
|
|
8fc2d6b225 | ||
|
|
051cdfa305 | ||
|
|
bfa807ca8b | ||
|
|
598914a67a | ||
|
|
3274649b77 | ||
|
|
5756105347 | ||
|
|
ed583d8bd1 | ||
|
|
731cf10207 | ||
|
|
cb898ce8cf | ||
|
|
892334e31a | ||
|
|
a16e16853f | ||
|
|
5cec83b3ef | ||
|
|
a628784c6d | ||
|
|
fd8b70fb12 | ||
|
|
3dad5a43a1 | ||
|
|
89dea86b3b | ||
|
|
42da24e31d | ||
|
|
5b9b5d4f1f | ||
|
|
5332a26294 | ||
|
|
54d9f8ec5c | ||
|
|
73a17308cc | ||
|
|
b835c48a0c | ||
|
|
40b604c6e4 | ||
|
|
1fd3580f97 | ||
|
|
e28f3b75a4 | ||
|
|
53153ca3e0 | ||
|
|
a496b14a0f | ||
|
|
da6e7240d6 | ||
|
|
89981c6994 | ||
|
|
fe22a43e09 | ||
|
|
3e1a797ea7 | ||
|
|
b23ce7ba18 | ||
|
|
6165f891ca | ||
|
|
7df4b1157c | ||
|
|
64cbd5fc8d | ||
|
|
ba7e789a80 | ||
|
|
d6d70ca076 | ||
|
|
88c37bb7d9 | ||
|
|
59b4f4efce | ||
|
|
ed1f120b0b | ||
|
|
bf461abfec | ||
|
|
d42665db88 | ||
|
|
33c4dc3347 | ||
|
|
6d976fb785 | ||
|
|
39b43cec2d | ||
|
|
691b56b4ac | ||
|
|
bf1f613052 | ||
|
|
721ed9f2a2 | ||
|
|
f760b1ba83 | ||
|
|
1dba144fca | ||
|
|
ebc1b531ff | ||
|
|
5ecf122686 | ||
|
|
56ed18882c | ||
|
|
86c555d053 | ||
|
|
49ec30899e | ||
|
|
d4a2b617bd | ||
|
|
8e7bd4b98a | ||
|
|
ea359285e0 | ||
|
|
d4bfa5d284 | ||
|
|
4433006842 | ||
|
|
646ebcdd00 | ||
|
|
8b53b36b20 | ||
|
|
64db392699 | ||
|
|
bff78704cc | ||
|
|
40651e8dfd | ||
|
|
e5d9d9ec9e | ||
|
|
4e628826c3 | ||
|
|
018bedb2bd | ||
|
|
33e315709a | ||
|
|
8b14a4775b | ||
|
|
fa8fdb0170 | ||
|
|
f856e16917 | ||
|
|
3b5271ab77 | ||
|
|
428fbddbbb | ||
|
|
5774837a6e | ||
|
|
17c2dfcbd0 | ||
|
|
a1711ccfa6 | ||
|
|
261610dcf1 | ||
|
|
92cfdf1145 | ||
|
|
155465b8c6 | ||
|
|
6f49bbdd41 | ||
|
|
3badaa5cba | ||
|
|
a66747a0d0 | ||
|
|
c376759be0 | ||
|
|
1c17f3ee43 | ||
|
|
5f549cc8aa | ||
|
|
f97be02087 | ||
|
|
2d82776e62 | ||
|
|
fdee0ac3e3 | ||
|
|
d775b80a44 | ||
|
|
2047a41498 | ||
|
|
f88890a052 | ||
|
|
5500faa57e | ||
|
|
89004574d3 | ||
|
|
c11c05a399 | ||
|
|
baa3329e7f | ||
|
|
e696d384c2 | ||
|
|
932c281223 | ||
|
|
858fe0384e | ||
|
|
e904cd749f | ||
|
|
6b16f39be4 | ||
|
|
021c7e5fdb | ||
|
|
c161a5c71b | ||
|
|
76ccdbccea | ||
|
|
553ee89787 | ||
|
|
cb6247b16e | ||
|
|
cfac7ff0ba | ||
|
|
49bbe7dc77 | ||
|
|
07b6fa0e2e | ||
|
|
67396f2009 | ||
|
|
a20ff87cc9 | ||
|
|
e02e57a729 | ||
|
|
225dc53795 | ||
|
|
e7404376db | ||
|
|
d6aec341fe | ||
|
|
3a3c2fb204 | ||
|
|
e9b5cdbccf | ||
|
|
3f30e63d95 | ||
|
|
f9c6866c7b | ||
|
|
388dccfd9f | ||
|
|
1676342e28 | ||
|
|
62732de227 | ||
|
|
63e777c84c | ||
|
|
ab95cdf3e5 | ||
|
|
827b5b01dd | ||
|
|
bfa9788099 | ||
|
|
de25ce7fbb | ||
|
|
21e61bfce6 | ||
|
|
82e168c438 | ||
|
|
48583a2b6e | ||
|
|
0db0982fa7 | ||
|
|
6a28ce9e4b | ||
|
|
1db79f6117 | ||
|
|
f234103320 | ||
|
|
45c382a19a | ||
|
|
fb7ef61d06 | ||
|
|
2586645d02 | ||
|
|
e23cb5509d | ||
|
|
5cbd53ae7a | ||
|
|
a4ee590875 | ||
|
|
495608ed7c | ||
|
|
4d10d9a195 | ||
|
|
4914a34dd9 | ||
|
|
ab0fb3131d | ||
|
|
7922d3b3cb | ||
|
|
6427f53b5a | ||
|
|
994df0a3a4 | ||
|
|
e6eee55810 | ||
|
|
855e4c4913 | ||
|
|
c2e07bf7b2 | ||
|
|
77b9e3eac8 | ||
|
|
790487eea6 | ||
|
|
eb83354179 | ||
|
|
9ba8754f97 | ||
|
|
84346119b3 | ||
|
|
2b3abd06db | ||
|
|
8267aad79e | ||
|
|
3f9ce561b9 | ||
|
|
347fc3ed9f | ||
|
|
0488c996e9 | ||
|
|
37bfd97d93 | ||
|
|
c8652b0576 | ||
|
|
1208d2eb5e | ||
|
|
ab34fed0c5 | ||
|
|
0906e5f9cf | ||
|
|
47b1c603b3 | ||
|
|
4bda321e7a | ||
|
|
691ff11fbc |
43
.clang-tidy
43
.clang-tidy
@@ -1,3 +1,10 @@
|
||||
# All rules should have a comment associated
|
||||
# Directives that do not have any effect (e.g. disabling a rule that is not enabled) can be done to add an explanation comment.
|
||||
# Or at least an empty comment # to show they were put here explicitely,
|
||||
# and not as part of the historical CLion-generated rules
|
||||
# Note: `- -X` means disable X
|
||||
# CLI usage: go to the build directory and run: `run-clang-tidy -allow-no-checks -source-filter ".*/lib/.*" -fix -j`
|
||||
|
||||
Checks:
|
||||
- -*
|
||||
- mpi-*
|
||||
@@ -12,24 +19,25 @@ Checks:
|
||||
- -bugprone-unhandled-exception-at-new
|
||||
- -bugprone-infinite-loop
|
||||
- -bugprone-easily-swappable-parameters
|
||||
- -bugprone-float-loop-counter #
|
||||
- -bugprone-unchecked-string-to-number-conversion # Unfortunately no alternative
|
||||
- -bugprone-branch-clone # Mostly warns about one-line duplicates
|
||||
- cert-err52-cpp
|
||||
- cert-err60-cpp
|
||||
- cert-err34-c
|
||||
- cert-str34-c
|
||||
- cert-dcl21-cpp
|
||||
- cert-msc50-cpp
|
||||
- cert-msc51-cpp
|
||||
- cert-dcl58-cpp
|
||||
- cert-flp30-c
|
||||
- cppcoreguidelines-avoid-const-or-ref-data-members
|
||||
- cppcoreguidelines-pro-type-member-init
|
||||
- cppcoreguidelines-pro-type-member-init # We want to use default member initializers
|
||||
- cppcoreguidelines-slicing
|
||||
- cppcoreguidelines-interfaces-global-init
|
||||
- cppcoreguidelines-pro-type-static-cast-downcast
|
||||
- cppcoreguidelines-narrowing-conversions
|
||||
- google-default-arguments
|
||||
- -cppcoreguidelines-pro-type-static-cast-downcast # dynamic_cast has a runtime overhead
|
||||
- -cppcoreguidelines-narrowing-conversions #
|
||||
- google-runtime-operator
|
||||
- google-explicit-constructor
|
||||
- -google-default-arguments # Provider and ViewProvider read() is a good example of why this is useful
|
||||
- hicpp-multiway-paths-covered
|
||||
- hicpp-exception-baseclass
|
||||
- misc-*
|
||||
@@ -43,8 +51,13 @@ Checks:
|
||||
- -misc-static-assert
|
||||
- -misc-no-recursion
|
||||
- -misc-const-correctness
|
||||
- -misc-use-internal-linkage # False positives if header where function is defined is not included
|
||||
- -misc-include-cleaner # Allow indirect includes
|
||||
- -misc-non-private-member-variables-in-classes #
|
||||
- modernize-*
|
||||
- -modernize-use-trailing-return-type
|
||||
- -modernize-use-std-print # We want to use fmt::print instead
|
||||
- -modernize-use-integer-sign-comparison # Too much occurrences to change
|
||||
- openmp-use-default-none
|
||||
- performance-*
|
||||
- -performance-no-int-to-ptr
|
||||
@@ -64,5 +77,21 @@ Checks:
|
||||
- -readability-redundant-access-specifiers
|
||||
- -readability-function-cognitive-complexity
|
||||
- -readability-identifier-naming
|
||||
- '*-include-cleaner'
|
||||
- -readability-qualified-auto
|
||||
- -readability-use-std-min-max # Less readable imo
|
||||
- -readability-math-missing-parentheses # Basic math
|
||||
- -readability-implicit-bool-conversion # Not much of a problem ?
|
||||
- -readability-convert-member-functions-to-static #
|
||||
- -readability-use-concise-preprocessor-directives # We do not use #ifdef
|
||||
- -readability-uppercase-literal-suffix # Not important enough
|
||||
- -readability-redundant-string-cstr # Sometimes used to stop at first null byte
|
||||
- -readability-static-accessed-through-instance #
|
||||
- -readability-ambiguous-smartptr-reset-call # Fix is hard to read
|
||||
|
||||
# Will fix later
|
||||
- -modernize-avoid-c-arrays
|
||||
- -readability-make-member-function-const # idk + lots of occurences
|
||||
- -readability-misleading-indentation # We need to handle cases with #if defined()
|
||||
- -bugprone-unchecked-optional-access
|
||||
- -performance-unnecessary-value-param # idk
|
||||
- -readability-avoid-nested-conditional-operator
|
||||
|
||||
4
.github/FUNDING.yml
vendored
4
.github/FUNDING.yml
vendored
@@ -1,5 +1,5 @@
|
||||
# Sponsor links
|
||||
|
||||
patreon: werwolv
|
||||
custom: https://werwolv.net/donate
|
||||
github: WerWolv
|
||||
ko_fi: WerWolv
|
||||
custom: "https://werwolv.net/donate"
|
||||
|
||||
7
.github/scripts/delete-artifact.sh
vendored
Executable file
7
.github/scripts/delete-artifact.sh
vendored
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
set -xe
|
||||
ARTIFACT_NAME="$1"
|
||||
|
||||
ARTIFACT_ID=$(gh api repos/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID/artifacts --jq ".artifacts[] | select(.name==\"$ARTIFACT_NAME\") | .id")
|
||||
gh api -X DELETE repos/$GITHUB_REPOSITORY/actions/artifacts/$ARTIFACT_ID
|
||||
echo "Deleted artifact $ARTIFACT_NAME with ID $ARTIFACT_ID"
|
||||
230
.github/workflows/build.yml
vendored
230
.github/workflows/build.yml
vendored
@@ -53,7 +53,7 @@ jobs:
|
||||
submodules: recursive
|
||||
|
||||
- name: 📜 Setup ccache
|
||||
uses: hendrikmuhs/ccache-action@main
|
||||
uses: hendrikmuhs/ccache-action@v1
|
||||
id: cache-ccache
|
||||
with:
|
||||
key: ${{ runner.os }}-mingw-ccache-${{ github.run_id }}
|
||||
@@ -109,8 +109,8 @@ jobs:
|
||||
|
||||
- name: 🕯️ Install WiX Toolkit
|
||||
run: |
|
||||
"C:/Program Files/dotnet/dotnet.exe" tool install --global wix
|
||||
"$(echo "$USERPROFILE" | tr '\\' '/')/.dotnet/tools/wix" extension add -g WixToolset.UI.wixext
|
||||
"C:/Program Files/dotnet/dotnet.exe" tool install --global wix@6.0.2
|
||||
"$(echo "$USERPROFILE" | tr '\\' '/')/.dotnet/tools/wix" extension add --global WixToolset.UI.wixext/6.0.2
|
||||
|
||||
- name: 🪲 Create PDBs for MSI
|
||||
run: |
|
||||
@@ -237,7 +237,7 @@ jobs:
|
||||
arch: ${{ matrix.vs_arch }}
|
||||
|
||||
- name: 📜 Setup ccache
|
||||
uses: hendrikmuhs/ccache-action@main
|
||||
uses: hendrikmuhs/ccache-action@v1
|
||||
id: cache-ccache
|
||||
with:
|
||||
key: ${{ runner.os }}-msvc-${{ matrix.vs_arch }}-ccache-${{ github.run_id }}
|
||||
@@ -246,12 +246,11 @@ jobs:
|
||||
|
||||
- name: 📦 Install vcpkg
|
||||
uses: friendlyanon/setup-vcpkg@v1
|
||||
with: { committish: ef7dbf94b9198bc58f45951adcf1f041fcbc5ea0 }
|
||||
with: { committish: 66c0373dc7fca549e5803087b9487edfe3aca0a1 }
|
||||
|
||||
- name: ⬇️ Install dependencies
|
||||
run: |
|
||||
cp dist/vcpkg.json vcpkg.json
|
||||
vcpkg install
|
||||
|
||||
- name: ⬇️ Install CMake and Ninja
|
||||
uses: lukka/get-cmake@latest
|
||||
@@ -294,8 +293,8 @@ jobs:
|
||||
|
||||
- name: 🕯️ Install WiX Toolkit
|
||||
run: |
|
||||
& "C:/Program Files/dotnet/dotnet.exe" tool install --global wix
|
||||
& "$($env:USERPROFILE -replace '\\','/')/.dotnet/tools/wix" extension add -g WixToolset.UI.wixext
|
||||
& "C:/Program Files/dotnet/dotnet.exe" tool install --global wix@6.0.2
|
||||
& "$($env:USERPROFILE -replace '\\','/')/.dotnet/tools/wix" extension add --global WixToolset.UI.wixext/6.0.2
|
||||
|
||||
- name: 📦 Bundle MSI
|
||||
run: |
|
||||
@@ -390,18 +389,7 @@ jobs:
|
||||
id-token: write
|
||||
attestations: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- file_suffix: "-NoGPU"
|
||||
name_suffix: "NoGPU"
|
||||
custom_glfw: true
|
||||
- file_suffix: ""
|
||||
name_suffix: ""
|
||||
custom_glfw: false
|
||||
|
||||
name: 🍎 macOS 15 x86_64 ${{ matrix.name_suffix }}
|
||||
name: 🍎 macOS 10.15 x86_64
|
||||
|
||||
steps:
|
||||
- name: 🧰 Checkout
|
||||
@@ -416,76 +404,55 @@ jobs:
|
||||
- name: 📜 Setup ccache
|
||||
uses: hendrikmuhs/ccache-action@v1
|
||||
with:
|
||||
key: ${{ runner.os }}${{ matrix.file_suffix }}-ccache-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}${{ matrix.file_suffix }}-ccache
|
||||
key: ${{ runner.os }}-ccache-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-ccache
|
||||
max-size: 1G
|
||||
|
||||
- name: Set Xcode version
|
||||
run: sudo xcode-select -s /Library/Developer/CommandLineTools
|
||||
run: |
|
||||
sudo xcode-select --install || true
|
||||
sudo xcode-select -s /Library/Developer/CommandLineTools
|
||||
|
||||
- name: 📦 Install MacPorts
|
||||
run: |
|
||||
wget https://github.com/macports/macports-base/releases/download/v2.11.6/MacPorts-2.11.6-15-Sequoia.pkg
|
||||
sudo installer -pkg MacPorts-2.11.6-15-Sequoia.pkg -target /
|
||||
export PATH=/opt/local/bin:/opt/local/sbin:$PATH
|
||||
echo "PATH=/opt/local/bin:/opt/local/sbin:$PATH" >> $GITHUB_ENV
|
||||
echo "MACOSX_DEPLOYMENT_TARGET=10.15" >> $GITHUB_ENV
|
||||
echo "universal_target 10.15" | sudo tee -a /opt/local/etc/macports/macports.conf
|
||||
echo "macos_deployment_target 10.15" | sudo tee -a /opt/local/etc/macports/macports.conf
|
||||
echo "macosx_sdk_version 10.15" | sudo tee -a /opt/local/etc/macports/macports.conf
|
||||
sudo port selfupdate
|
||||
|
||||
- name: ⬇️ Install dependencies
|
||||
env:
|
||||
# Make brew not display useless errors
|
||||
HOMEBREW_TESTS: 1
|
||||
run: |
|
||||
brew reinstall python --quiet || true
|
||||
brew link --overwrite --quiet python 2>/dev/null || true
|
||||
brew bundle --quiet --file dist/macOS/Brewfile || true
|
||||
rm -rf /usr/local/Cellar/capstone
|
||||
|
||||
- name: ⬇️ Install classic glfw
|
||||
if: ${{! matrix.custom_glfw }}
|
||||
run: |
|
||||
brew install --quiet glfw || true
|
||||
brew install llvm@21 automake
|
||||
sudo -E port install mbedtls3 nlohmann-json ccache freetype libmagic pkgconfig curl glfw ninja zlib xz bzip2 zstd libssh2 md4c
|
||||
|
||||
- name: ⬇️ Install .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: '8.0.100'
|
||||
|
||||
- name: 🧰 Checkout glfw
|
||||
if: ${{ matrix.custom_glfw }}
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: glfw/glfw
|
||||
path: glfw
|
||||
|
||||
# GLFW custom build (to allow software rendering)
|
||||
- name: ⬇️ Patch and install custom glfw
|
||||
if: ${{ matrix.custom_glfw }}
|
||||
run: |
|
||||
set -x
|
||||
cd glfw
|
||||
git apply ../dist/macOS/0001-glfw-SW.patch
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
|
||||
cmake -G "Ninja" \
|
||||
-DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \
|
||||
-DBUILD_SHARED_LIBS=ON \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
|
||||
..
|
||||
ninja install
|
||||
|
||||
# MacOS cmake build
|
||||
- name: 🛠️ Configure CMake
|
||||
run: |
|
||||
set -x
|
||||
mkdir -p build
|
||||
cd build
|
||||
CC=$(brew --prefix llvm)/bin/clang \
|
||||
CXX=$(brew --prefix llvm)/bin/clang++ \
|
||||
OBJC=$(brew --prefix llvm)/bin/clang \
|
||||
OBJCXX=$(brew --prefix llvm)/bin/clang++ \
|
||||
PKG_CONFIG_PATH="$(brew --prefix openssl)/lib/pkgconfig":"$(brew --prefix)/lib/pkgconfig" \
|
||||
CC=$(brew --prefix llvm@21)/bin/clang \
|
||||
CXX=$(brew --prefix llvm@21)/bin/clang++ \
|
||||
OBJC=$(brew --prefix llvm@21)/bin/clang \
|
||||
OBJCXX=$(brew --prefix llvm@21)/bin/clang++ \
|
||||
cmake -G "Ninja" \
|
||||
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 \
|
||||
-DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \
|
||||
-DIMHEX_GENERATE_PACKAGE=ON \
|
||||
-DIMHEX_SYSTEM_LIBRARY_PATH="$(brew --prefix llvm)/lib;$(brew --prefix llvm)/lib/unwind;$(brew --prefix llvm)/lib/c++;$(brew --prefix)/lib" \
|
||||
-DIMHEX_SYSTEM_LIBRARY_PATH="$(brew --prefix llvm@21)/lib;$(brew --prefix llvm@21)/lib/unwind;$(brew --prefix llvm@21)/lib/c++;$(brew --prefix)/lib" \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
|
||||
@@ -503,7 +470,6 @@ jobs:
|
||||
run: |
|
||||
set -x
|
||||
cd build/install
|
||||
mv imhex.app ImHex.app
|
||||
codesign --remove-signature ImHex.app
|
||||
codesign --force --deep --sign - ImHex.app
|
||||
|
||||
@@ -532,7 +498,7 @@ jobs:
|
||||
break;
|
||||
fi
|
||||
done
|
||||
mv *.dmg ../../imhex-${{ env.IMHEX_VERSION }}-macOS${{ matrix.file_suffix }}-x86_64.dmg
|
||||
mv *.dmg ../../imhex-${{ env.IMHEX_VERSION }}-macOS-x86_64.dmg
|
||||
|
||||
- name: 🗝️ Generate build provenance attestations
|
||||
uses: actions/attest-build-provenance@v2
|
||||
@@ -545,12 +511,12 @@ jobs:
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
if-no-files-found: error
|
||||
name: macOS DMG ${{ matrix.name_suffix }} x86_64
|
||||
name: macOS DMG x86_64
|
||||
path: ./*.dmg
|
||||
|
||||
macos-arm64:
|
||||
runs-on: ubuntu-24.04
|
||||
name: 🍎 macOS 15 arm64
|
||||
name: 🍎 macOS 11 arm64
|
||||
|
||||
outputs:
|
||||
IMHEX_VERSION: ${{ steps.build.outputs.IMHEX_VERSION }}
|
||||
@@ -598,7 +564,7 @@ jobs:
|
||||
|
||||
macos-arm64-package:
|
||||
runs-on: macos-15-intel
|
||||
name: 🍎 macOS 15 arm64 Packaging
|
||||
name: 🍎 macOS 11 arm64 Packaging
|
||||
needs: macos-arm64
|
||||
|
||||
env:
|
||||
@@ -624,7 +590,6 @@ jobs:
|
||||
run: |
|
||||
set -x
|
||||
cd out
|
||||
mv imhex.app ImHex.app
|
||||
codesign --remove-signature ImHex.app
|
||||
codesign --force --deep --entitlements Entitlements.plist --sign - ImHex.app
|
||||
|
||||
@@ -675,14 +640,21 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- release_num: "24.04"
|
||||
- release_num: "25.04"
|
||||
- name: "Ubuntu"
|
||||
release_num: "24.04"
|
||||
image: "ubuntu:24.04"
|
||||
- name: "Ubuntu"
|
||||
release_num: "25.10"
|
||||
image: "ubuntu:25.10"
|
||||
- name: "Debian"
|
||||
release_num: "13"
|
||||
image: "debian:13"
|
||||
|
||||
name: 🐧 Ubuntu ${{ matrix.release_num }}
|
||||
name: 🐧 ${{ matrix.name }} ${{ matrix.release_num }} x86_64
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
container:
|
||||
image: "ubuntu:${{ matrix.release_num }}"
|
||||
image: "${{ matrix.image }}"
|
||||
options: --privileged
|
||||
|
||||
permissions:
|
||||
@@ -701,8 +673,8 @@ jobs:
|
||||
- name: 📜 Setup ccache
|
||||
uses: hendrikmuhs/ccache-action@v1
|
||||
with:
|
||||
key: Ubuntu-${{ matrix.release_num }}-ccache-${{ github.run_id }}
|
||||
restore-keys: Ubuntu-${{ matrix.release_num }}-ccache
|
||||
key: ${{ matrix.image }}-ccache-${{ github.run_id }}
|
||||
restore-keys: ${{ matrix.image }}-ccache
|
||||
max-size: 1G
|
||||
|
||||
- name: ⬇️ Install dependencies
|
||||
@@ -747,7 +719,7 @@ jobs:
|
||||
run: |
|
||||
cp -r build/DEBIAN build/DebDir
|
||||
dpkg-deb -Zzstd --build build/DebDir
|
||||
mv build/DebDir.deb imhex-${{ env.IMHEX_VERSION }}-Ubuntu-${{ matrix.release_num }}-x86_64.deb
|
||||
mv build/DebDir.deb imhex-${{ env.IMHEX_VERSION }}-${{ matrix.name }}-${{ matrix.release_num }}-x86_64.deb
|
||||
|
||||
- name: 🗝️ Generate build provenance attestations
|
||||
uses: actions/attest-build-provenance@v2
|
||||
@@ -760,7 +732,7 @@ jobs:
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
if-no-files-found: error
|
||||
name: Ubuntu ${{ matrix.release_num }} DEB x86_64
|
||||
name: ${{ matrix.name }} ${{ matrix.release_num }} DEB x86_64
|
||||
path: '*.deb'
|
||||
|
||||
# AppImage build
|
||||
@@ -835,7 +807,7 @@ jobs:
|
||||
|
||||
# ArchLinux build
|
||||
archlinux-build:
|
||||
name: 🐧 ArchLinux
|
||||
name: 🐧 ArchLinux x86_64
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
container:
|
||||
@@ -950,23 +922,11 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- name: Fedora
|
||||
release_num: rawhide
|
||||
mock_config: fedora-rawhide
|
||||
- name: Fedora
|
||||
release_num: 43
|
||||
mock_config: fedora-43
|
||||
- name: Fedora
|
||||
release_num: 42
|
||||
mock_config: fedora-42
|
||||
- name: Fedora
|
||||
release_num: 41
|
||||
mock_config: fedora-41
|
||||
- name: RHEL-AlmaLinux
|
||||
release_num: 9
|
||||
mock_config: "alma+epel-9"
|
||||
|
||||
name: 🐧 ${{ matrix.name }} ${{ matrix.release_num }}
|
||||
name: 🐧 ${{ matrix.name }} ${{ matrix.release_num }} x86_64
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
container:
|
||||
@@ -1229,10 +1189,6 @@ jobs:
|
||||
webassembly-build:
|
||||
runs-on: ubuntu-24.04
|
||||
name: 🌍 Web
|
||||
permissions:
|
||||
pages: write
|
||||
id-token: write
|
||||
actions: write
|
||||
steps:
|
||||
- name: 🧰 Checkout
|
||||
uses: actions/checkout@v4
|
||||
@@ -1252,17 +1208,20 @@ jobs:
|
||||
cache-source: cache
|
||||
cache-target: /cache
|
||||
|
||||
- name: 🛠️ Build using docker
|
||||
- name: 🔨 Copy necessary files
|
||||
run: |
|
||||
mkdir -p out/nightly
|
||||
cp dist/web/serve.py out/nightly/start_imhex_web.py
|
||||
|
||||
- name: 🛠️ Build using docker
|
||||
run: |
|
||||
docker buildx build . -f dist/web/Dockerfile --progress=plain --build-arg 'JOBS=4' --output out/nightly --target raw
|
||||
|
||||
- name: ⬇️ Download Release
|
||||
- name: ⬇️ Download Release artifact
|
||||
if: ${{ github.event.repository.fork == false }}
|
||||
uses: robinraju/release-downloader@v1
|
||||
with:
|
||||
latest: true
|
||||
fileName: 'imhex-*-Web.zip'
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: gh --repo $GITHUB_REPOSITORY release download --pattern "imhex-*-Web.zip"
|
||||
|
||||
- name: 🔨 Fix permissions
|
||||
if: ${{ github.event.repository.fork == false }}
|
||||
@@ -1275,10 +1234,6 @@ jobs:
|
||||
with:
|
||||
path: out/
|
||||
|
||||
- name: 🔨 Copy necessary files
|
||||
run: |
|
||||
cp dist/web/serve.py out/nightly/start_imhex_web.py
|
||||
|
||||
- name: ⬆️ Upload package
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
@@ -1297,7 +1252,7 @@ jobs:
|
||||
|
||||
webassembly-deploy:
|
||||
environment:
|
||||
name: github-pages
|
||||
name: ImHex Web
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
permissions:
|
||||
pages: write
|
||||
@@ -1310,11 +1265,64 @@ jobs:
|
||||
needs: webassembly-build
|
||||
|
||||
steps:
|
||||
- name: 🧰 Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: 🌍 Deploy WebAssembly Build to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v4
|
||||
|
||||
- name: 🗑️ Delete artifact
|
||||
uses: geekyeggo/delete-artifact@v5
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
.github/scripts/delete-artifact.sh "github-pages"
|
||||
|
||||
webassembly-docker-image-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref == 'refs/heads/master'
|
||||
needs: webassembly-build
|
||||
name: 🐋 Deploy to ghcr.io
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- name: 🧰 Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: ⬇️ Download artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: github-pages
|
||||
name: ImHex Web
|
||||
path: out
|
||||
|
||||
- name: 📜 Login to ghcr.io
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: ⛓️ Extract metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ghcr.io/${{ github.repository }}/imhex-web
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=pr
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=sha
|
||||
|
||||
- name: 🔨 Build and push Docker image
|
||||
uses: docker/build-push-action@v6
|
||||
env:
|
||||
DOCKER_BUILD_RECORD_UPLOAD: false
|
||||
with:
|
||||
context: .
|
||||
file: dist/web/Host.Dockerfile
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
|
||||
47
.github/workflows/dl-cache.yml
vendored
Normal file
47
.github/workflows/dl-cache.yml
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
# https://gist.github.com/iTrooz/d5bacca32c0974edc6c1ac3ad3ee82f3
|
||||
# See https://github.com/cli/cli/issues/9125
|
||||
# Extract archive with `tar -xf cache.tzst --transform 's@\.\./@#@g' -P` to avoid ../ errors
|
||||
name: Download cache key
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
cache_key:
|
||||
description: 'Cache key'
|
||||
required: true
|
||||
type: string
|
||||
jobs:
|
||||
cache-download:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Query cache version
|
||||
id: version
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
VERSION=$(gh api repos/$GITHUB_REPOSITORY/actions/caches \
|
||||
--jq "
|
||||
.actions_caches[]
|
||||
| select(.ref == \"refs/heads/$GITHUB_REF_NAME\")
|
||||
| select(.key == \"${{ github.event.inputs.cache_key }}\")
|
||||
| .version
|
||||
")
|
||||
echo "version=$VERSION" | tee $GITHUB_OUTPUT
|
||||
|
||||
- name: Restore cache
|
||||
uses: iTrooz/cache/restore@restore_with_version
|
||||
with:
|
||||
# Path won't be actually used, we will match by 'version'.
|
||||
path: .
|
||||
key: ${{ github.event.inputs.cache_key }}
|
||||
version: ${{ steps.version.outputs.version }}
|
||||
|
||||
- name: Upload cached folder as artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: cache-artifact
|
||||
path: |
|
||||
/home/runner/work/**/*.tzst
|
||||
59
.github/workflows/nightly_release.yml
vendored
59
.github/workflows/nightly_release.yml
vendored
@@ -37,13 +37,14 @@ jobs:
|
||||
run: |
|
||||
project_version=`cat ImHex/VERSION`
|
||||
echo "IMHEX_VERSION=$project_version" >> $GITHUB_ENV
|
||||
|
||||
|
||||
# TODO: Replace by Github CLI when github.com/cli/cli/pull/12435 is closed
|
||||
- name: ⬇️ Download artifacts from latest workflow
|
||||
uses: dawidd6/action-download-artifact@v6
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
workflow: build.yml
|
||||
branch: ${{ github.event.release.target_commitish }}
|
||||
branch: master
|
||||
workflow_conclusion: success
|
||||
skip_unpack: true
|
||||
|
||||
@@ -82,43 +83,6 @@ jobs:
|
||||
git fetch --tags --recurse-submodules=no
|
||||
git log nightly..origin/master --oneline --no-merges --pretty=format:'* %s' >> changelog.md
|
||||
|
||||
- name: ⬆️ Upload Unsigned x86_64 Windows Installer
|
||||
if: false
|
||||
uses: actions/upload-artifact@v4
|
||||
id: upload-installer-x86_64
|
||||
with:
|
||||
if-no-files-found: error
|
||||
name: Windows Installer ${{ matrix.architecture_name }}
|
||||
path: |
|
||||
imhex-*-x86_64.msi
|
||||
|
||||
- name: ⬆️ Upload Unsigned ARM64 Windows Installer
|
||||
if: false
|
||||
uses: actions/upload-artifact@v4
|
||||
id: upload-installer-arm64
|
||||
with:
|
||||
if-no-files-found: error
|
||||
name: Windows Installer ${{ matrix.architecture_name }}
|
||||
path: |
|
||||
imhex-*-arm64.msi
|
||||
|
||||
- name: 🗑️ Delete unsigned installers
|
||||
if: false
|
||||
run: |
|
||||
rm imhex-*.msi
|
||||
|
||||
- name: 🗝️ Sign Installer
|
||||
if: false
|
||||
uses: signpath/github-action-submit-signing-request@v1
|
||||
with:
|
||||
api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
|
||||
organization-id: 'f605a0e8-86cd-411c-bb6f-e05025afcc33'
|
||||
project-slug: 'ImHex'
|
||||
signing-policy-slug: 'release-signing'
|
||||
github-artifact-id: '${{ steps.upload-installer.outputs.artifact-id }}'
|
||||
wait-for-completion: true
|
||||
output-artifact-directory: '.'
|
||||
|
||||
- name: 📦 Update Pre-Release
|
||||
if: ${{ steps.check_commits.outputs.should_run == 'true' }}
|
||||
run: |
|
||||
@@ -162,4 +126,19 @@ jobs:
|
||||
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_STORE_LOGIN }}
|
||||
with:
|
||||
snap: imhex-${{ env.IMHEX_VERSION }}-arm64.snap
|
||||
release: edge
|
||||
release: edge
|
||||
|
||||
website_update:
|
||||
name: 🌍 Update ImHex Landing Website
|
||||
needs: nightly-release
|
||||
runs-on: ubuntu-24.04
|
||||
env:
|
||||
WEBSITE_DISPATCH_TOKEN: ${{ secrets.WEBSITE_DISPATCH_TOKEN }}
|
||||
steps:
|
||||
- name: ✉️ Dispatch Landing page update
|
||||
if: ${{ env.WEBSITE_DISPATCH_TOKEN != '' }}
|
||||
uses: peter-evans/repository-dispatch@v4
|
||||
with:
|
||||
token: ${{ secrets.WEBSITE_DISPATCH_TOKEN }}
|
||||
repository: WerWolv/ImHexWebsite
|
||||
event-type: update_page
|
||||
7
.github/workflows/release.yml
vendored
7
.github/workflows/release.yml
vendored
@@ -190,6 +190,11 @@ jobs:
|
||||
needs: release-upload-artifacts
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: 🧰 Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: ImHex
|
||||
|
||||
- name: ⬇️ Download artifacts
|
||||
run: |
|
||||
tagname=${GITHUB_REF#refs/tags/}
|
||||
@@ -217,7 +222,7 @@ jobs:
|
||||
pkgname: imhex-bin
|
||||
pkgbuild: ./PKGBUILD
|
||||
commit_username: iTrooz
|
||||
commit_email: itrooz@protonmail.com
|
||||
commit_email: hey@itrooz.fr
|
||||
ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
|
||||
commit_message: Bump to version ${{ needs.release-upload-artifacts.outputs.IMHEX_VERSION }}
|
||||
ssh_keyscan_types: rsa,ecdsa,ed25519
|
||||
|
||||
@@ -12,7 +12,8 @@ option(IMHEX_BUNDLE_DOTNET "Bundle .NET runtime"
|
||||
option(IMHEX_ENABLE_LTO "Enables Link Time Optimizations if possible" OFF)
|
||||
option(IMHEX_USE_DEFAULT_BUILD_SETTINGS "Use default build settings" OFF)
|
||||
option(IMHEX_BUILD_HARDENING "Enable hardening flags for build" ON )
|
||||
option(IMHEX_GENERATE_PACKAGE "Specify if a native package should be built. (Windows and MacOS only)" OFF)
|
||||
option(IMHEX_GENERATE_PACKAGE "Specify if a cpack package should be built. (Windows only)" OFF)
|
||||
option(IMHEX_MACOS_CREATE_BUNDLE "Creates a macOS .app bundle when building (macOS only)" ON )
|
||||
option(IMHEX_ENABLE_UNITY_BUILD "Enables building ImHex as a unity build." OFF)
|
||||
option(IMHEX_ENABLE_PRECOMPILED_HEADERS "Enable precompiled headers" OFF)
|
||||
option(IMHEX_ENABLE_CXX_MODULES "Enable C++20 Module compilation. Testing only!" OFF)
|
||||
|
||||
@@ -29,11 +29,11 @@
|
||||
|
||||
## Supporting
|
||||
|
||||
If you like my work, please consider supporting me on GitHub Sponsors, Patreon or PayPal. Thanks a lot!
|
||||
If you like my work, please consider supporting me on GitHub Sponsors, Ko-Fi or PayPal. Thanks a lot!
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/sponsors/WerWolv"><img src="https://werwolv.net/assets/github_banner.png" alt="GitHub donate button" /></a>
|
||||
<a href="https://www.patreon.com/werwolv"><img src="https://c5.patreon.com/external/logo/become_a_patron_button.png" alt="Patreon donate button" /></a>
|
||||
<a href="https://ko-fi.com/WerWolv"><img src="https://werwolv.net/assets/kofi_banner.png" alt="Ko-Fi donate button" /></a>
|
||||
<a href="https://werwolv.net/donate"><img src="https://werwolv.net/assets/paypal_banner.png" alt="PayPal donate button" /></a>
|
||||
</p>
|
||||
|
||||
|
||||
@@ -202,12 +202,16 @@ macro(configurePackingResources)
|
||||
set(CPACK_PACKAGE_NAME "ImHex")
|
||||
set(CPACK_PACKAGE_VENDOR "WerWolv")
|
||||
set(CPACK_WIX_VERSION 4)
|
||||
set(CPACK_WIX_PRODUCT_GUID "*")
|
||||
set(CPACK_WIX_UPGRADE_GUID "05000E99-9659-42FD-A1CF-05C554B39285")
|
||||
set(CPACK_WIX_PRODUCT_ICON "${PROJECT_SOURCE_DIR}/resources/dist/windows/icon.ico")
|
||||
set(CPACK_WIX_UI_BANNER "${PROJECT_SOURCE_DIR}/resources/dist/windows/wix_banner.png")
|
||||
set(CPACK_WIX_UI_DIALOG "${PROJECT_SOURCE_DIR}/resources/dist/windows/wix_dialog.png")
|
||||
set(CPACK_WIX_CULTURES "en-US;de-DE;ja-JP;it-IT;pt-BR;zh-CN;zh-TW;ru-RU")
|
||||
set(CPACK_WIX_PATCH_FILE "${PROJECT_SOURCE_DIR}/resources/dist/windows/wix_patch.xml")
|
||||
set(CPACK_WIX_TEMPLATE "${PROJECT_SOURCE_DIR}/resources/dist/windows/WIX.template.in")
|
||||
set(CPACK_WIX_EXTENSIONS "WixToolset.UI.wixext")
|
||||
|
||||
file(GLOB_RECURSE CPACK_WIX_EXTRA_SOURCES "${PROJECT_SOURCE_DIR}/resources/dist/windows/wix/*.wxs")
|
||||
|
||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY "ImHex")
|
||||
set_property(INSTALL "$<TARGET_FILE_NAME:main>"
|
||||
@@ -217,9 +221,9 @@ macro(configurePackingResources)
|
||||
endif()
|
||||
elseif (APPLE OR ${CMAKE_HOST_SYSTEM_NAME} MATCHES "Darwin")
|
||||
set(IMHEX_ICON "${IMHEX_BASE_FOLDER}/resources/dist/macos/AppIcon.icns")
|
||||
set(BUNDLE_NAME "imhex.app")
|
||||
set(BUNDLE_NAME "ImHex.app")
|
||||
|
||||
if (IMHEX_GENERATE_PACKAGE)
|
||||
if (IMHEX_MACOS_CREATE_BUNDLE)
|
||||
set(APPLICATION_TYPE MACOSX_BUNDLE)
|
||||
set_source_files_properties(${IMHEX_ICON} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
|
||||
set(MACOSX_BUNDLE_ICON_FILE "AppIcon.icns")
|
||||
@@ -235,9 +239,9 @@ macro(configurePackingResources)
|
||||
string(TIMESTAMP CURR_YEAR "%Y")
|
||||
set(MACOSX_BUNDLE_COPYRIGHT "Copyright © 2020 - ${CURR_YEAR} WerWolv. All rights reserved." )
|
||||
if ("${CMAKE_GENERATOR}" STREQUAL "Xcode")
|
||||
set (IMHEX_BUNDLE_PATH "${CMAKE_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${BUNDLE_NAME}")
|
||||
set(IMHEX_BUNDLE_PATH "${CMAKE_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${BUNDLE_NAME}")
|
||||
else ()
|
||||
set (IMHEX_BUNDLE_PATH "${CMAKE_BINARY_DIR}/${BUNDLE_NAME}")
|
||||
set(IMHEX_BUNDLE_PATH "${CMAKE_BINARY_DIR}/${BUNDLE_NAME}")
|
||||
endif()
|
||||
|
||||
set(PLUGINS_INSTALL_LOCATION "${IMHEX_BUNDLE_PATH}/Contents/MacOS/plugins")
|
||||
@@ -255,7 +259,7 @@ macro(addPluginDirectories)
|
||||
set_target_properties(${plugin} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${IMHEX_MAIN_OUTPUT_DIRECTORY}/plugins")
|
||||
|
||||
if (APPLE)
|
||||
if (IMHEX_GENERATE_PACKAGE)
|
||||
if (IMHEX_MACOS_CREATE_BUNDLE)
|
||||
set_target_properties(${plugin} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PLUGINS_INSTALL_LOCATION})
|
||||
endif ()
|
||||
else ()
|
||||
@@ -347,24 +351,21 @@ macro(createPackage)
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
if (IMHEX_GENERATE_PACKAGE)
|
||||
if (IMHEX_MACOS_CREATE_BUNDLE)
|
||||
set(EXTRA_BUNDLE_LIBRARY_PATHS ${EXTRA_BUNDLE_LIBRARY_PATHS} "${IMHEX_SYSTEM_LIBRARY_PATH}")
|
||||
include(PostprocessBundle)
|
||||
|
||||
set_target_properties(libimhex PROPERTIES SOVERSION ${IMHEX_VERSION})
|
||||
|
||||
set_property(TARGET main PROPERTY MACOSX_BUNDLE_INFO_PLIST ${MACOSX_BUNDLE_INFO_PLIST})
|
||||
set_property(TARGET main PROPERTY MACOSX_BUNDLE_BUNDLE_NAME "${MACOSX_BUNDLE_BUNDLE_NAME}")
|
||||
|
||||
# Fix rpath
|
||||
install(CODE "execute_process(COMMAND ${CMAKE_INSTALL_NAME_TOOL} -add_rpath \"@executable_path/../Frameworks/\" $<TARGET_FILE:main>)")
|
||||
install(CODE "execute_process(COMMAND ${CMAKE_INSTALL_NAME_TOOL} -add_rpath \"@executable_path/../Frameworks/\" $<TARGET_FILE:updater>)")
|
||||
|
||||
add_custom_target(build-time-make-plugins-directory ALL COMMAND ${CMAKE_COMMAND} -E make_directory "${IMHEX_BUNDLE_PATH}/Contents/MacOS/plugins")
|
||||
add_custom_target(build-time-make-resources-directory ALL COMMAND ${CMAKE_COMMAND} -E make_directory "${IMHEX_BUNDLE_PATH}/Contents/Resources")
|
||||
|
||||
downloadImHexPatternsFiles("${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME}/Contents/MacOS")
|
||||
|
||||
install(FILES ${IMHEX_ICON} DESTINATION "${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME}/Contents/Resources")
|
||||
install(TARGETS main BUNDLE DESTINATION ".")
|
||||
install(TARGETS updater DESTINATION "${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME}/Contents/MacOS")
|
||||
install(
|
||||
@@ -430,7 +431,7 @@ macro(createPackage)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (IMHEX_GENERATE_PACKAGE)
|
||||
if (IMHEX_MACOS_CREATE_BUNDLE)
|
||||
set(CPACK_BUNDLE_NAME "ImHex")
|
||||
|
||||
include(CPack)
|
||||
|
||||
@@ -2,11 +2,7 @@ find_path(LIBMAGIC_INCLUDE_DIR magic.h)
|
||||
|
||||
find_library(LIBMAGIC_LIBRARY NAMES magic)
|
||||
|
||||
if (LIBMAGIC_INCLUDE_DIR AND LIBMAGIC_LIBRARY)
|
||||
set(LIBMAGIC_FOUND TRUE)
|
||||
endif (LIBMAGIC_INCLUDE_DIR AND LIBMAGIC_LIBRARY)
|
||||
|
||||
find_package_handle_standard_args("libmagic" DEFAULT_MSG
|
||||
find_package_handle_standard_args(Magic DEFAULT_MSG
|
||||
LIBMAGIC_LIBRARY
|
||||
LIBMAGIC_INCLUDE_DIR
|
||||
)
|
||||
@@ -14,5 +10,5 @@ find_package_handle_standard_args("libmagic" DEFAULT_MSG
|
||||
mark_as_advanced(
|
||||
LIBMAGIC_INCLUDE_DIR
|
||||
LIBMAGIC_LIBRARY
|
||||
LIBMAGIC_FOUND
|
||||
)
|
||||
Magic_FOUND
|
||||
)
|
||||
|
||||
2
dist/ImHex.run.xml
vendored
2
dist/ImHex.run.xml
vendored
@@ -8,6 +8,6 @@
|
||||
</method>
|
||||
</configuration>
|
||||
<configuration default="false" name="CMake Debug" type="CMakeListConfigurationType" factoryName="CMakeListConfigurationFactory">
|
||||
<method v="2" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
4
dist/compiling/macos.md
vendored
4
dist/compiling/macos.md
vendored
@@ -3,7 +3,7 @@
|
||||
On macOS, ImHex is built through regular GCC and LLVM clang.
|
||||
|
||||
1. Clone the repo using `git clone https://github.com/WerWolv/ImHex --recurse-submodules`
|
||||
2. Install all the dependencies using `brew bundle --no-lock --file dist/macOS/Brewfile`
|
||||
2. Install all the dependencies using `brew bundle --file dist/macOS/Brewfile`
|
||||
3. Build ImHex itself using the following commands:
|
||||
```sh
|
||||
cd ImHex
|
||||
@@ -20,3 +20,5 @@ cmake -G "Ninja" \
|
||||
..
|
||||
ninja install
|
||||
```
|
||||
|
||||
If your MacOS installation doesn't have graphic acceleration, you can check the [MacOS NoGPU guide](./macos_nogpu.md)
|
||||
10
dist/compiling/macos_nogpu.md
vendored
Normal file
10
dist/compiling/macos_nogpu.md
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
### Compiling and running ImHex on macOS without a GPU
|
||||
|
||||
In order to run ImHex on a macOS installation without a GPU, you need a custom build of GLFW. You can build it this way:
|
||||
|
||||
Note: only tested on macOS x86
|
||||
|
||||
1. `git clone --depth 1 https://github.com/glfw/glfw`
|
||||
2. `git apply {IMHEX_DIR}/dist/macOS/0001-glfw-SW.patch` (file is [here](../macOS/0001-glfw-SW.patch) in the ImHex repository. [Source](https://github.com/glfw/glfw/issues/2080).)
|
||||
3. `cmake -G "Ninja" -DBUILD_SHARED_LIBS=ON ..`
|
||||
4. `ninja install`, or `ninja` and figure out how to make ImHex detect the shared library
|
||||
2
dist/macOS/0001-glfw-SW.patch
vendored
2
dist/macOS/0001-glfw-SW.patch
vendored
@@ -1,5 +1,5 @@
|
||||
From 9c8665af4c2e2ce66555c15c05c72027bfdf0cb6 Mon Sep 17 00:00:00 2001
|
||||
From: iTrooz <itrooz@protonmail.com>
|
||||
From: iTrooz <hey@itrooz.fr>
|
||||
Date: Mon, 29 Aug 2022 17:29:38 +0200
|
||||
Subject: [PATCH] Use software rendering on MacOS
|
||||
|
||||
|
||||
8
dist/macOS/arm64.Dockerfile
vendored
8
dist/macOS/arm64.Dockerfile
vendored
@@ -1,7 +1,7 @@
|
||||
# This base image is also known as "crosscompile". See arm64.crosscompile.Dockerfile
|
||||
FROM ghcr.io/werwolv/macos-crosscompile:4c4af2d1a6a102fab93cc9cd660280c2ec9d72af as build
|
||||
FROM ghcr.io/werwolv/macos-crosscompile:6d89b20ac5ebedb6f680f94637591c94cb36f40b as build
|
||||
|
||||
ENV MACOSX_DEPLOYMENT_TARGET 13.0
|
||||
ENV MACOSX_DEPLOYMENT_TARGET 11.0
|
||||
|
||||
# -- DOWNLOADING STUFF
|
||||
|
||||
@@ -132,6 +132,7 @@ if [ "$CUSTOM_GLFW" ]; then
|
||||
mkdir build
|
||||
cd build
|
||||
CC=o64-clang CXX=o64-clang++ cmake -G "Ninja" \
|
||||
-DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 \
|
||||
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
|
||||
-DBUILD_SHARED_LIBS=ON \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
@@ -168,6 +169,7 @@ RUN --mount=type=cache,target=/cache --mount=type=cache,target=/mnt/ImHex/build/
|
||||
-DIMHEX_STRICT_WARNINGS=OFF \
|
||||
-DIMHEX_PATTERNS_PULL_MASTER=ON \
|
||||
-DCMAKE_INSTALL_PREFIX=/mnt/ImHex/build/install \
|
||||
-DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 \
|
||||
-B build
|
||||
## Build ImHex
|
||||
RUN --mount=type=cache,target=/cache --mount=type=cache,target=/mnt/ImHex/build/_deps <<EOF
|
||||
@@ -182,4 +184,4 @@ EOF
|
||||
|
||||
|
||||
FROM scratch
|
||||
COPY --from=build /mnt/ImHex/build/install/imhex.app imhex.app
|
||||
COPY --from=build /mnt/ImHex/build/install/ImHex.app ImHex.app
|
||||
|
||||
11
dist/macOS/osx_10_15/x64-osx.cmake
vendored
Normal file
11
dist/macOS/osx_10_15/x64-osx.cmake
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
set(VCPKG_TARGET_ARCHITECTURE x64)
|
||||
set(VCPKG_BUILD_TYPE release)
|
||||
set(VCPKG_CRT_LINKAGE dynamic)
|
||||
set(VCPKG_LIBRARY_LINKAGE static)
|
||||
|
||||
set(VCPKG_CMAKE_SYSTEM_NAME Darwin)
|
||||
set(VCPKG_OSX_ARCHITECTURES x86_64)
|
||||
set(VCPKG_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "" FORCE)
|
||||
set(VCPKG_C_FLAGS "-mmacosx-version-min=10.15")
|
||||
set(VCPKG_CXX_FLAGS "-mmacosx-version-min=10.15")
|
||||
set(ENV{MACOSX_DEPLOYMENT_TARGET} "10.15")
|
||||
2
dist/vcpkg.json
vendored
2
dist/vcpkg.json
vendored
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "vcpkg",
|
||||
"version": "1.0.0",
|
||||
"builtin-baseline": "7e21420f775f72ae938bdeb5e6068f722088f06a",
|
||||
"builtin-baseline": "66c0373dc7fca549e5803087b9487edfe3aca0a1",
|
||||
"dependencies": [
|
||||
"libmagic",
|
||||
"freetype",
|
||||
|
||||
9
dist/web/Host.Dockerfile
vendored
Normal file
9
dist/web/Host.Dockerfile
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
FROM python:3.12-slim
|
||||
|
||||
WORKDIR /imhex
|
||||
|
||||
COPY ./out/ .
|
||||
|
||||
EXPOSE 9090
|
||||
|
||||
CMD [ "python", "/imhex/start_imhex_web.py" ]
|
||||
2
dist/web/serve.py
vendored
2
dist/web/serve.py
vendored
@@ -10,6 +10,6 @@ class MyHttpRequestHandler(http.server.SimpleHTTPRequestHandler):
|
||||
|
||||
if __name__ == '__main__':
|
||||
os.chdir(".")
|
||||
httpd = http.server.HTTPServer(("localhost", 9090), MyHttpRequestHandler)
|
||||
httpd = http.server.HTTPServer(("0.0.0.0", 9090), MyHttpRequestHandler)
|
||||
print(f"Serving {os.getcwd()} on http://{httpd.server_address[0]}:{httpd.server_address[1]}")
|
||||
httpd.serve_forever()
|
||||
|
||||
16
dist/web/source/index.html
vendored
16
dist/web/source/index.html
vendored
@@ -15,17 +15,17 @@
|
||||
|
||||
<!-- Open Graph / Facebook -->
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:url" content="https://imhex.werwolv.net/">
|
||||
<meta property="og:url" content="https://web.imhex.werwolv.net/">
|
||||
<meta property="og:title" content="ImHex Web - Online Hex Editor">
|
||||
<meta property="og:image" content="https://imhex.werwolv.net/assets/splash_wasm.png">
|
||||
<meta property="og:image" content="splash_wasm.png">
|
||||
|
||||
<!-- Twitter -->
|
||||
<meta property="twitter:card" content="summary_large_image">
|
||||
<meta property="twitter:url" content="https://imhex.werwolv.net/">
|
||||
<meta property="twitter:url" content="https://web.imhex.werwolv.net/">
|
||||
<meta property="twitter:title" content="ImHex Web - Online Hex Editor">
|
||||
<meta property="twitter:description"
|
||||
content="A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.">
|
||||
<meta property="twitter:image" content="https://imhex.werwolv.net/assets/splash_wasm.png">
|
||||
<meta property="twitter:image" content="splash_wasm.png">
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="style.css">
|
||||
|
||||
@@ -37,8 +37,8 @@
|
||||
"email": "hey@werwolv.net",
|
||||
"founder": "WerWolv",
|
||||
"slogan": "A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.",
|
||||
"url": "https://imhex.werwolv.net",
|
||||
"logo": "https://imhex.werwolv.net/assets/logos/logo.svg"
|
||||
"url": "https://web.imhex.werwolv.net",
|
||||
"logo": "https://web.imhex.werwolv.net/icon.svg"
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -96,7 +96,9 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
|
||||
<div id="canvas-wrapper" class="imhex-web-canvas-wrapper">
|
||||
<canvas class="imhex-web-canvas canvas-fixed" id="canvas" ></canvas>
|
||||
</div>
|
||||
|
||||
<script src="wasm-config.js"></script>
|
||||
<script async src="imhex.js"></script>
|
||||
|
||||
BIN
dist/web/source/splash_wasm.png
vendored
Normal file
BIN
dist/web/source/splash_wasm.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 478 KiB |
19
dist/web/source/style.css
vendored
19
dist/web/source/style.css
vendored
@@ -185,4 +185,23 @@ a:hover {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.imhex-web-canvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
image-rendering: smooth;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.imhex-web-canvas-wrapper {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
96
dist/web/source/wasm-config.js
vendored
96
dist/web/source/wasm-config.js
vendored
@@ -59,8 +59,14 @@ monkeyPatch((file, done) => {
|
||||
const mibTotal = (wasmSize / 1024**2).toFixed(1);
|
||||
|
||||
let root = document.querySelector(':root');
|
||||
root.style.setProperty("--progress", `${percent}%`)
|
||||
document.getElementById("progress-bar-content").innerHTML = `${percent}% [${mibNow} MiB / ${mibTotal} MiB]`;
|
||||
if (root != null) {
|
||||
root.style.setProperty("--progress", `${percent}%`)
|
||||
let progressBar = document.getElementById("progress-bar-content");
|
||||
|
||||
if (progressBar != null) {
|
||||
progressBar.innerHTML = `${percent}% [${mibNow} MiB / ${mibTotal} MiB]`;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function glfwSetCursorCustom(wnd, shape) {
|
||||
@@ -100,81 +106,17 @@ var notWorkingTimer = setTimeout(() => {
|
||||
}, 5000);
|
||||
|
||||
var Module = {
|
||||
preRun: [],
|
||||
preRun: () => {
|
||||
ENV.IMHEX_SKIP_SPLASH_SCREEN = "1";
|
||||
},
|
||||
postRun: function() {
|
||||
// Patch the emscripten GLFW module to send mouse and touch events in the right order
|
||||
// For ImGui interactions to correctly work with touch input, MousePos events need
|
||||
// to be processed first and then MouseButton events in the next frame. By default,
|
||||
// GLFW does the exact opposite, which causes buttons to require two taps to register
|
||||
// and windows get "stuck" to the cursor when dragged or resized
|
||||
GLFW.onMousemove = event => {
|
||||
if (event.type === "touchmove") {
|
||||
event.preventDefault();
|
||||
let primaryChanged = false;
|
||||
for (let i of event.changedTouches) {
|
||||
if (GLFW.primaryTouchId === i.identifier) {
|
||||
Browser.setMouseCoords(i.pageX, i.pageY);
|
||||
primaryChanged = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!primaryChanged) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
Browser.calculateMouseEvent(event);
|
||||
}
|
||||
};
|
||||
|
||||
GLFW.onMouseButtonChanged = (event, status) => {
|
||||
if (!GLFW.active) return;
|
||||
if (event.target != Module["canvas"]) return;
|
||||
const isTouchType = event.type === "touchstart" || event.type === "touchend" || event.type === "touchcancel";
|
||||
let eventButton = 0;
|
||||
if (isTouchType) {
|
||||
event.preventDefault();
|
||||
let primaryChanged = false;
|
||||
if (GLFW.primaryTouchId === null && event.type === "touchstart" && event.targetTouches.length > 0) {
|
||||
const chosenTouch = event.targetTouches[0];
|
||||
GLFW.primaryTouchId = chosenTouch.identifier;
|
||||
Browser.setMouseCoords(chosenTouch.pageX, chosenTouch.pageY);
|
||||
primaryChanged = true;
|
||||
} else if (event.type === "touchend" || event.type === "touchcancel") {
|
||||
for (let i of event.changedTouches) {
|
||||
if (GLFW.primaryTouchId === i.identifier) {
|
||||
GLFW.primaryTouchId = null;
|
||||
primaryChanged = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!primaryChanged) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
Browser.calculateMouseEvent(event);
|
||||
eventButton = GLFW.DOMToGLFWMouseButton(event);
|
||||
}
|
||||
if (status == 1) {
|
||||
GLFW.active.buttons |= (1 << eventButton);
|
||||
try {
|
||||
event.target.setCapture();
|
||||
} catch (e) {}
|
||||
} else {
|
||||
GLFW.active.buttons &= ~(1 << eventButton);
|
||||
}
|
||||
|
||||
if (GLFW.active.cursorPosFunc) {
|
||||
getWasmTableEntry(GLFW.active.cursorPosFunc)(GLFW.active.id, Browser.mouseX, Browser.mouseY);
|
||||
}
|
||||
if (GLFW.active.mouseButtonFunc) {
|
||||
getWasmTableEntry(GLFW.active.mouseButtonFunc)(GLFW.active.id, eventButton, status, GLFW.getModBits(GLFW.active));
|
||||
}
|
||||
};
|
||||
},
|
||||
onRuntimeInitialized: function() {
|
||||
// Triggered when the wasm module is loaded and ready to use.
|
||||
document.getElementById("loading").style.display = "none"
|
||||
let loading = document.getElementById("loading");
|
||||
if (loading != null)
|
||||
document.getElementById("loading").style.display = "none"
|
||||
document.getElementById("canvas").style.display = "initial"
|
||||
|
||||
clearTimeout(notWorkingTimer);
|
||||
@@ -257,16 +199,6 @@ if (urlParams.has("lang")) {
|
||||
Module["arguments"].push(urlParams.get("save-editor"));
|
||||
}
|
||||
|
||||
window.addEventListener('resize', js_resizeCanvas, false);
|
||||
function js_resizeCanvas() {
|
||||
let canvas = document.getElementById('canvas');
|
||||
|
||||
canvas.top = document.documentElement.clientTop;
|
||||
canvas.left = document.documentElement.clientLeft;
|
||||
canvas.width = Math.min(document.documentElement.clientWidth, window.innerWidth || 0);
|
||||
canvas.height = Math.min(document.documentElement.clientHeight, window.innerHeight || 0);
|
||||
}
|
||||
|
||||
// Prevent some default browser shortcuts from preventing ImHex ones to work
|
||||
document.addEventListener('keydown', e => {
|
||||
if (e.ctrlKey) {
|
||||
|
||||
2
lib/external/disassembler
vendored
2
lib/external/disassembler
vendored
Submodule lib/external/disassembler updated: 7235352627...c66e624157
2
lib/external/libwolv
vendored
2
lib/external/libwolv
vendored
Submodule lib/external/libwolv updated: c9108712ba...1063613e87
2
lib/external/pattern_language
vendored
2
lib/external/pattern_language
vendored
Submodule lib/external/pattern_language updated: fb6ea061f7...9adb36901a
@@ -57,6 +57,9 @@ set(LIBIMHEX_SOURCES
|
||||
source/ui/toast.cpp
|
||||
source/ui/banner.cpp
|
||||
|
||||
source/mcp/client.cpp
|
||||
source/mcp/server.cpp
|
||||
|
||||
source/subcommands/subcommands.cpp
|
||||
)
|
||||
|
||||
|
||||
@@ -145,62 +145,17 @@ EXPORT_MODULE namespace hex {
|
||||
* @brief Returns the icon of the achievement
|
||||
* @return Icon of the achievement
|
||||
*/
|
||||
[[nodiscard]] const ImGuiExt::Texture &getIcon() const {
|
||||
if (m_iconData.empty())
|
||||
return m_icon;
|
||||
|
||||
if (m_icon.isValid())
|
||||
return m_icon;
|
||||
|
||||
m_icon = ImGuiExt::Texture::fromImage(m_iconData.data(), m_iconData.size(), ImGuiExt::Texture::Filter::Linear);
|
||||
|
||||
return m_icon;
|
||||
[[nodiscard]] const char* getIcon() const {
|
||||
return m_icon.c_str();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the icon of the achievement
|
||||
* @param data Icon data
|
||||
* @param icon Icon glyph
|
||||
* @return Reference to the achievement
|
||||
*/
|
||||
Achievement& setIcon(std::span<const std::byte> data) {
|
||||
m_iconData.reserve(data.size());
|
||||
for (auto &byte : data)
|
||||
m_iconData.emplace_back(static_cast<u8>(byte));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the icon of the achievement
|
||||
* @param data Icon data
|
||||
* @return Reference to the achievement
|
||||
*/
|
||||
Achievement& setIcon(std::span<const u8> data) {
|
||||
m_iconData.assign(data.begin(), data.end());
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the icon of the achievement
|
||||
* @param data Icon data
|
||||
* @return Reference to the achievement
|
||||
*/
|
||||
Achievement& setIcon(std::vector<u8> data) {
|
||||
m_iconData = std::move(data);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the icon of the achievement
|
||||
* @param data Icon data
|
||||
* @return Reference to the achievement
|
||||
*/
|
||||
Achievement& setIcon(const std::vector<std::byte> &data) {
|
||||
m_iconData.reserve(data.size());
|
||||
for (auto &byte : data)
|
||||
m_iconData.emplace_back(static_cast<u8>(byte));
|
||||
Achievement& setIcon(std::string icon) {
|
||||
m_icon = std::move(icon);
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -284,8 +239,7 @@ EXPORT_MODULE namespace hex {
|
||||
|
||||
std::function<void(Achievement &)> m_clickCallback;
|
||||
|
||||
std::vector<u8> m_iconData;
|
||||
mutable ImGuiExt::Texture m_icon;
|
||||
std::string m_icon;
|
||||
|
||||
u32 m_progress = 0;
|
||||
u32 m_maxProgress = 1;
|
||||
|
||||
@@ -16,7 +16,7 @@ EXPORT_MODULE namespace hex {
|
||||
void stopServices();
|
||||
}
|
||||
|
||||
void registerService(const UnlocalizedString &unlocalizedString, const impl::Callback &callback);
|
||||
void registerService(const UnlocalizedString &unlocalizedName, const impl::Callback &callback);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,6 +7,8 @@
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include <hex/mcp/server.hpp>
|
||||
|
||||
EXPORT_MODULE namespace hex {
|
||||
|
||||
/* Network Communication Interface Registry. Allows adding new communication interface endpoints */
|
||||
@@ -22,4 +24,19 @@ EXPORT_MODULE namespace hex {
|
||||
|
||||
}
|
||||
|
||||
namespace ContentRegistry::MCP {
|
||||
|
||||
namespace impl {
|
||||
std::unique_ptr<mcp::Server>& getMcpServerInstance();
|
||||
|
||||
void setEnabled(bool enabled);
|
||||
}
|
||||
|
||||
bool isEnabled();
|
||||
bool isConnected();
|
||||
|
||||
void registerTool(std::string_view capabilities, std::function<nlohmann::json(const nlohmann::json ¶ms)> function);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <bit>
|
||||
|
||||
EXPORT_MODULE namespace hex {
|
||||
|
||||
@@ -22,8 +23,10 @@ EXPORT_MODULE namespace hex {
|
||||
|
||||
namespace impl {
|
||||
|
||||
struct DoNotUseThisByItselfTag {};
|
||||
|
||||
using DisplayFunction = std::function<std::string()>;
|
||||
using EditingFunction = std::function<std::vector<u8>(std::string, std::endian)>;
|
||||
using EditingFunction = std::function<std::optional<std::vector<u8>>(std::string&, std::endian, DoNotUseThisByItselfTag)>;
|
||||
using GeneratorFunction = std::function<DisplayFunction(const std::vector<u8> &, std::endian, NumberDisplayStyle)>;
|
||||
|
||||
struct Entry {
|
||||
@@ -38,6 +41,35 @@ EXPORT_MODULE namespace hex {
|
||||
|
||||
}
|
||||
|
||||
namespace EditWidget {
|
||||
|
||||
class Widget {
|
||||
public:
|
||||
using Function = std::function<std::vector<u8>(const std::string&, std::endian)>;
|
||||
|
||||
explicit Widget(const Function &function) : m_function(function) {}
|
||||
|
||||
virtual ~Widget() = default;
|
||||
virtual std::optional<std::vector<u8>> draw(std::string &value, std::endian endian) = 0;
|
||||
std::optional<std::vector<u8>> operator()(std::string &value, std::endian endian, impl::DoNotUseThisByItselfTag) {
|
||||
return draw(value, endian);
|
||||
}
|
||||
|
||||
std::vector<u8> getBytes(const std::string &value, std::endian endian) const {
|
||||
return m_function(value, endian);
|
||||
}
|
||||
|
||||
private:
|
||||
Function m_function;
|
||||
};
|
||||
|
||||
struct TextInput : Widget {
|
||||
explicit TextInput(const Function &function) : Widget(function) {}
|
||||
std::optional<std::vector<u8>> draw(std::string &value, std::endian endian) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds a new entry to the data inspector
|
||||
* @param unlocalizedName The unlocalized name of the entry
|
||||
|
||||
@@ -52,7 +52,7 @@ EXPORT_MODULE namespace hex {
|
||||
return *this;
|
||||
}
|
||||
|
||||
Interface& setTooltip(const std::string &tooltip) {
|
||||
Interface& setTooltip(const UnlocalizedString &tooltip) {
|
||||
m_tooltip = tooltip;
|
||||
|
||||
return *this;
|
||||
@@ -239,6 +239,14 @@ EXPORT_MODULE namespace hex {
|
||||
nlohmann::json store() override { return {}; }
|
||||
};
|
||||
|
||||
class Spacer : public Widget {
|
||||
public:
|
||||
bool draw(const std::string &name) override;
|
||||
|
||||
void load(const nlohmann::json &) override {}
|
||||
nlohmann::json store() override { return {}; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace impl {
|
||||
@@ -290,8 +298,8 @@ EXPORT_MODULE namespace hex {
|
||||
public:
|
||||
SettingsValue(nlohmann::json value) : m_value(std::move(value)) {}
|
||||
|
||||
template<typename T>
|
||||
T get(std::common_type_t<T> defaultValue) const {
|
||||
template<typename T> requires (!(std::is_reference_v<T> || std::is_const_v<T>))
|
||||
[[nodiscard]] T get(T defaultValue) const {
|
||||
try {
|
||||
auto result = m_value;
|
||||
if (result.is_number() && std::same_as<T, bool>)
|
||||
@@ -308,8 +316,8 @@ EXPORT_MODULE namespace hex {
|
||||
nlohmann::json m_value;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]] T read(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, const std::common_type_t<T> &defaultValue) {
|
||||
template<typename T> requires (!(std::is_reference_v<T> || std::is_const_v<T>))
|
||||
[[nodiscard]] T read(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, T defaultValue) {
|
||||
auto setting = impl::getSetting(unlocalizedCategory, unlocalizedName, defaultValue);
|
||||
|
||||
try {
|
||||
@@ -326,8 +334,8 @@ EXPORT_MODULE namespace hex {
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void write(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, const std::common_type_t<T> &value) {
|
||||
template<typename T> requires (!(std::is_reference_v<T> || std::is_const_v<T>))
|
||||
void write(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, T value) {
|
||||
impl::getSetting(unlocalizedCategory, unlocalizedName, value) = value;
|
||||
impl::runOnChangeHandlers(unlocalizedCategory, unlocalizedName, value);
|
||||
|
||||
@@ -336,10 +344,75 @@ EXPORT_MODULE namespace hex {
|
||||
|
||||
using OnChangeCallback = std::function<void(const SettingsValue &)>;
|
||||
u64 onChange(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, const OnChangeCallback &callback);
|
||||
void removeOnChangeHandler(u64 id);
|
||||
|
||||
using OnSaveCallback = std::function<void()>;
|
||||
u64 onSave(const OnSaveCallback &callback);
|
||||
|
||||
template<typename T, wolv::type::StaticString UnlocalizedCategory, wolv::type::StaticString UnlocalizedName>
|
||||
requires (!(std::is_reference_v<T> || std::is_const_v<T>))
|
||||
class SettingsVariable {
|
||||
public:
|
||||
explicit(false) SettingsVariable(T defaultValue) noexcept : m_defaultValue(std::move(defaultValue)) { }
|
||||
|
||||
SettingsVariable(const SettingsVariable&) = delete;
|
||||
SettingsVariable& operator=(const SettingsVariable&) = delete;
|
||||
|
||||
SettingsVariable(SettingsVariable&&) = delete;
|
||||
SettingsVariable& operator=(SettingsVariable&&) = delete;
|
||||
|
||||
~SettingsVariable() {
|
||||
if (m_onChangeId > 0)
|
||||
removeOnChangeHandler(m_onChangeId);
|
||||
}
|
||||
|
||||
[[nodiscard]] T get() const {
|
||||
registerChangeHandler();
|
||||
if (!m_value.has_value()) {
|
||||
m_value = read<T>(
|
||||
UnlocalizedCategory.value.data(),
|
||||
UnlocalizedName.value.data(),
|
||||
m_defaultValue
|
||||
);
|
||||
}
|
||||
|
||||
return m_value.value_or(m_defaultValue);
|
||||
}
|
||||
|
||||
void set(T value) {
|
||||
registerChangeHandler();
|
||||
write<T>(
|
||||
UnlocalizedCategory.value.data(),
|
||||
UnlocalizedName.value.data(),
|
||||
std::move(value)
|
||||
);
|
||||
}
|
||||
|
||||
explicit(false) operator T() const {
|
||||
return get();
|
||||
}
|
||||
|
||||
SettingsVariable& operator=(T value) {
|
||||
set(std::move(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
void registerChangeHandler() const {
|
||||
if (m_onChangeId > 0)
|
||||
return;
|
||||
|
||||
m_onChangeId = onChange(UnlocalizedCategory.value.data(), UnlocalizedName.value.data(), [this](const SettingsValue &value) {
|
||||
m_value = value.get<T>(m_defaultValue);
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
mutable std::optional<T> m_value;
|
||||
T m_defaultValue;
|
||||
mutable u64 m_onChangeId = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -68,6 +68,7 @@ EXPORT_MODULE namespace hex {
|
||||
|
||||
constexpr static auto SeparatorValue = "$SEPARATOR$";
|
||||
constexpr static auto SubMenuValue = "$SUBMENU$";
|
||||
constexpr static auto TaskBarMenuValue = "$TASKBAR$";
|
||||
|
||||
const std::multimap<u32, MainMenuItem>& getMainMenuItems();
|
||||
|
||||
@@ -199,6 +200,19 @@ EXPORT_MODULE namespace hex {
|
||||
*/
|
||||
void addMenuItemSeparator(std::vector<UnlocalizedString> unlocalizedMainMenuNames, u32 priority, View *view = nullptr);
|
||||
|
||||
/**
|
||||
* @brief Adds a new main menu entry
|
||||
* @param unlocalizedMainMenuNames The unlocalized names of the main menu entries
|
||||
* @param priority The priority of the entry. Lower values are displayed first
|
||||
* @param function The function to call when the entry is clicked
|
||||
* @param enabledCallback The function to call to determine if the entry is enabled
|
||||
*/
|
||||
void addTaskBarMenuItem(
|
||||
std::vector<UnlocalizedString> unlocalizedMainMenuNames,
|
||||
u32 priority,
|
||||
const impl::MenuCallback &function,
|
||||
const impl::EnabledCallback& enabledCallback
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Adds a new welcome screen entry
|
||||
@@ -220,10 +234,10 @@ EXPORT_MODULE namespace hex {
|
||||
|
||||
/**
|
||||
* @brief Adds a menu item to the toolbar
|
||||
* @param unlocalizedName Unlocalized name of the menu item
|
||||
* @param unlocalizedNames Unlocalized name of the menu item
|
||||
* @param color Color of the toolbar icon
|
||||
*/
|
||||
void addMenuItemToToolbar(const UnlocalizedString &unlocalizedName, ImGuiCustomCol color);
|
||||
void addMenuItemToToolbar(const std::vector<UnlocalizedString> &unlocalizedNames, ImGuiCustomCol color);
|
||||
|
||||
/**
|
||||
* @brief Reconstructs the toolbar items list after they have been modified
|
||||
|
||||
@@ -62,6 +62,7 @@ EXPORT_MODULE namespace hex {
|
||||
void setMainWindowSize(u32 width, u32 height);
|
||||
void setMainDockSpaceId(ImGuiID id);
|
||||
void setMainWindowHandle(GLFWwindow *window);
|
||||
void setMainWindowFocusState(bool focused);
|
||||
|
||||
void setGlobalScale(float scale);
|
||||
void setNativeScale(float scale);
|
||||
@@ -161,6 +162,12 @@ EXPORT_MODULE namespace hex {
|
||||
*/
|
||||
GLFWwindow* getMainWindowHandle();
|
||||
|
||||
/**
|
||||
* @brief Checks if the main window is currently focused
|
||||
* @return Whether the main window is focused
|
||||
*/
|
||||
bool isMainWindowFocused();
|
||||
|
||||
/**
|
||||
* @brief Checks if borderless window mode is enabled currently
|
||||
* @return Whether borderless window mode is enabled
|
||||
|
||||
@@ -23,7 +23,7 @@ EXPORT_MODULE namespace hex {
|
||||
class Task {
|
||||
public:
|
||||
Task() = default;
|
||||
Task(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, bool blocking, std::function<void(Task &)> function);
|
||||
Task(UnlocalizedString unlocalizedName, u64 maxValue, bool background, bool blocking, std::function<void(Task &)> function);
|
||||
|
||||
Task(const Task&) = delete;
|
||||
Task(Task &&other) noexcept;
|
||||
@@ -95,11 +95,15 @@ EXPORT_MODULE namespace hex {
|
||||
std::atomic_flag m_hadException;
|
||||
std::string m_exceptionMessage;
|
||||
|
||||
struct TaskInterruptor {
|
||||
struct TaskInterruptor: public std::exception {
|
||||
TaskInterruptor() {
|
||||
trace::disableExceptionCaptureForCurrentThread();
|
||||
}
|
||||
virtual ~TaskInterruptor() = default;
|
||||
|
||||
[[nodiscard]] const char* what() const noexcept override {
|
||||
return "Task Interrupted";
|
||||
}
|
||||
};
|
||||
|
||||
friend class TaskHolder;
|
||||
@@ -248,6 +252,8 @@ EXPORT_MODULE namespace hex {
|
||||
static const std::list<std::shared_ptr<Task>>& getRunningTasks();
|
||||
static void runDeferredCalls();
|
||||
|
||||
static void addTaskCompletionCallback(const std::function<void(Task&)>& function);
|
||||
|
||||
private:
|
||||
static TaskHolder createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, bool blocking, std::function<void(Task &)> function);
|
||||
};
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
|
||||
#include <hex/ui/imgui_imhex_extensions.h>
|
||||
|
||||
struct ImRect;
|
||||
|
||||
EXPORT_MODULE namespace hex {
|
||||
|
||||
class TutorialManager {
|
||||
@@ -22,6 +24,8 @@ EXPORT_MODULE namespace hex {
|
||||
Right = 8
|
||||
};
|
||||
|
||||
using DrawFunction = std::function<void()>;
|
||||
|
||||
struct Tutorial {
|
||||
Tutorial() = delete;
|
||||
Tutorial(const UnlocalizedString &unlocalizedName, const UnlocalizedString &unlocalizedDescription) :
|
||||
@@ -101,6 +105,7 @@ EXPORT_MODULE namespace hex {
|
||||
std::vector<Highlight> m_highlights;
|
||||
std::optional<Message> m_message;
|
||||
std::function<void()> m_onAppear, m_onComplete;
|
||||
DrawFunction m_drawFunction;
|
||||
};
|
||||
|
||||
Step& addStep();
|
||||
@@ -146,6 +151,7 @@ EXPORT_MODULE namespace hex {
|
||||
* @param unlocalizedName Name of tutorial to start
|
||||
*/
|
||||
static void startTutorial(const UnlocalizedString &unlocalizedName);
|
||||
static void stopCurrentTutorial();
|
||||
|
||||
static void startHelpHover();
|
||||
static void addInteractiveHelpText(std::initializer_list<std::variant<Lang, std::string, int>> &&ids, UnlocalizedString unlocalizedString);
|
||||
@@ -166,6 +172,10 @@ EXPORT_MODULE namespace hex {
|
||||
*/
|
||||
static void reset();
|
||||
|
||||
static void setRenderer(std::function<DrawFunction(const std::string &)> renderer);
|
||||
|
||||
static void postElementRendered(ImGuiID id, const ImRect &boundingBox);
|
||||
|
||||
private:
|
||||
TutorialManager() = delete;
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <set>
|
||||
#include <span>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <nlohmann/json_fwd.hpp>
|
||||
@@ -49,9 +50,15 @@ namespace hex::dp {
|
||||
virtual void store(nlohmann::json &j) const { std::ignore = j; }
|
||||
virtual void load(const nlohmann::json &j) { std::ignore = j; }
|
||||
|
||||
struct NodeError {
|
||||
struct NodeError: public std::exception {
|
||||
Node *node;
|
||||
std::string message;
|
||||
|
||||
NodeError(Node *node, std::string message) : node(node), message(std::move(message)) {}
|
||||
|
||||
[[nodiscard]] const char* what() const noexcept override {
|
||||
return this->message.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
void resetOutputData() {
|
||||
@@ -102,7 +109,7 @@ namespace hex::dp {
|
||||
void unmarkInputProcessed(u32 index);
|
||||
|
||||
protected:
|
||||
[[noreturn]] void throwNodeError(const std::string &message);
|
||||
[[noreturn]] void throwNodeError(const std::string &msg);
|
||||
|
||||
void setOverlayData(u64 address, const std::vector<u8> &data);
|
||||
void setAttributes(std::vector<Attribute> attributes);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/api/imhex_api/system.hpp>
|
||||
#include <hex/helpers/logger.hpp>
|
||||
|
||||
namespace hex {
|
||||
|
||||
@@ -9,6 +10,9 @@ namespace hex {
|
||||
class AutoResetBase {
|
||||
public:
|
||||
virtual ~AutoResetBase() = default;
|
||||
|
||||
private:
|
||||
friend void ImHexApi::System::impl::cleanup();
|
||||
virtual void reset() = 0;
|
||||
};
|
||||
|
||||
@@ -19,16 +23,20 @@ namespace hex {
|
||||
public:
|
||||
using Type = T;
|
||||
|
||||
AutoReset() {
|
||||
ImHexApi::System::impl::addAutoResetObject(this);
|
||||
AutoReset() noexcept {
|
||||
try {
|
||||
ImHexApi::System::impl::addAutoResetObject(this);
|
||||
} catch (std::exception &e) {
|
||||
log::error("Failed to register AutoReset object: {}", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
AutoReset(const T &value) : AutoReset() {
|
||||
explicit(false) AutoReset(const T &value) : AutoReset() {
|
||||
m_value = value;
|
||||
m_valid = true;
|
||||
}
|
||||
|
||||
AutoReset(T &&value) noexcept : AutoReset() {
|
||||
explicit(false) AutoReset(T &&value) noexcept : AutoReset() {
|
||||
m_value = std::move(value);
|
||||
m_valid = true;
|
||||
}
|
||||
@@ -61,29 +69,27 @@ namespace hex {
|
||||
return m_value;
|
||||
}
|
||||
|
||||
T& operator=(const T &value) {
|
||||
AutoReset& operator=(const T &value) {
|
||||
m_value = value;
|
||||
m_valid = true;
|
||||
return m_value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
T& operator=(T &&value) noexcept {
|
||||
AutoReset& operator=(T &&value) noexcept {
|
||||
m_value = std::move(value);
|
||||
m_valid = true;
|
||||
return m_value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool isValid() const {
|
||||
[[nodiscard]] bool isValid() const {
|
||||
return m_valid;
|
||||
}
|
||||
|
||||
private:
|
||||
friend void ImHexApi::System::impl::cleanup();
|
||||
|
||||
void reset() override {
|
||||
if constexpr (requires { m_value.reset(); }) {
|
||||
if constexpr (requires(T t) { t.reset(); }) {
|
||||
m_value.reset();
|
||||
} else if constexpr (requires { m_value.clear(); }) {
|
||||
} else if constexpr (requires(T t) { t.clear(); }) {
|
||||
m_value.clear();
|
||||
} else if constexpr (std::is_pointer_v<T>) {
|
||||
m_value = nullptr; // cppcheck-suppress nullPointer
|
||||
|
||||
@@ -12,6 +12,9 @@ namespace hex::menu {
|
||||
bool beginMenu(const char *label, bool enabled = true);
|
||||
void endMenu();
|
||||
|
||||
bool beginTaskBarMenu();
|
||||
void endTaskBarMenu();
|
||||
|
||||
bool beginMenuEx(const char* label, const char* icon, bool enabled = true);
|
||||
|
||||
bool menuItem(const char *label, const Shortcut &shortcut = Shortcut::None, bool selected = false, bool enabled = true);
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <numbers>
|
||||
#include <array>
|
||||
|
||||
#include <opengl_support.h>
|
||||
#include "imgui.h"
|
||||
@@ -935,7 +936,7 @@ namespace hex::gl {
|
||||
void attachTexture(const Texture &texture) const;
|
||||
|
||||
private:
|
||||
GLuint m_frameBuffer, m_renderBuffer;
|
||||
GLuint m_frameBuffer = 0, m_renderBuffer = 0;
|
||||
};
|
||||
|
||||
class AxesVectors {
|
||||
|
||||
@@ -99,6 +99,7 @@ namespace hex {
|
||||
void startProgram(const std::vector<std::string> &command);
|
||||
int executeCommand(const std::string &command);
|
||||
std::optional<std::string> executeCommandWithOutput(const std::string &command);
|
||||
void executeCommandDetach(const std::string &command);
|
||||
void openWebpage(std::string url);
|
||||
|
||||
extern "C" void registerFont(const char *fontName, const char *fontPath);
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
void macosInstallEventListener();
|
||||
|
||||
void toastMessageMacos(const char *title, const char *message);
|
||||
void macosSetupDockMenu(void);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
15
lib/libimhex/include/hex/mcp/client.hpp
Normal file
15
lib/libimhex/include/hex/mcp/client.hpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace hex::mcp {
|
||||
|
||||
class Client {
|
||||
public:
|
||||
Client() = default;
|
||||
~Client() = default;
|
||||
|
||||
int run(std::istream &input, std::ostream &output);
|
||||
};
|
||||
|
||||
}
|
||||
123
lib/libimhex/include/hex/mcp/server.hpp
Normal file
123
lib/libimhex/include/hex/mcp/server.hpp
Normal file
@@ -0,0 +1,123 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <wolv/net/socket_server.hpp>
|
||||
|
||||
namespace hex::mcp {
|
||||
|
||||
class JsonRpc {
|
||||
public:
|
||||
explicit JsonRpc(std::string request) : m_request(std::move(request)){ }
|
||||
|
||||
struct MethodNotFoundException : std::exception {};
|
||||
struct InvalidParametersException : std::exception {};
|
||||
|
||||
enum class ErrorCode: i16 {
|
||||
ParseError = -32700,
|
||||
InvalidRequest = -32600,
|
||||
MethodNotFound = -32601,
|
||||
InvalidParams = -32602,
|
||||
InternalError = -32603,
|
||||
};
|
||||
|
||||
using Callback = std::function<nlohmann::json(const std::string &method, const nlohmann::json ¶ms)>;
|
||||
std::optional<std::string> execute(const Callback &callback);
|
||||
void setError(ErrorCode code, std::string message);
|
||||
|
||||
private:
|
||||
std::optional<nlohmann::json> handleMessage(const nlohmann::json &request, const Callback &callback);
|
||||
std::optional<nlohmann::json> handleBatchedMessages(const nlohmann::json &request, const Callback &callback);
|
||||
|
||||
nlohmann::json createDefaultMessage();
|
||||
nlohmann::json createErrorMessage(ErrorCode code, const std::string &message);
|
||||
nlohmann::json createResponseMessage(const nlohmann::json &result);
|
||||
|
||||
private:
|
||||
std::string m_request;
|
||||
std::optional<int> m_id;
|
||||
|
||||
struct Error {
|
||||
ErrorCode code;
|
||||
std::string message;
|
||||
};
|
||||
std::optional<Error> m_error;
|
||||
};
|
||||
|
||||
struct TextContent {
|
||||
std::string text;
|
||||
|
||||
operator nlohmann::json() const {
|
||||
nlohmann::json result;
|
||||
result["content"] = nlohmann::json::array({
|
||||
nlohmann::json::object({
|
||||
{ "type", "text" },
|
||||
{ "text", text }
|
||||
})
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
struct StructuredContent {
|
||||
std::string text;
|
||||
nlohmann::json data;
|
||||
|
||||
operator nlohmann::json() const {
|
||||
nlohmann::json result;
|
||||
result["content"] = nlohmann::json::array({
|
||||
nlohmann::json::object({
|
||||
{ "type", "text" },
|
||||
{ "text", text }
|
||||
})
|
||||
});
|
||||
result["structuredContent"] = data;
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
class Server {
|
||||
public:
|
||||
constexpr static auto McpInternalPort = 19743;
|
||||
|
||||
Server();
|
||||
~Server();
|
||||
|
||||
void listen();
|
||||
void shutdown();
|
||||
void disconnect();
|
||||
bool isConnected();
|
||||
|
||||
void addPrimitive(std::string type, std::string_view capabilities, std::function<nlohmann::json(const nlohmann::json ¶ms)> function);
|
||||
|
||||
struct ClientInfo {
|
||||
std::string name;
|
||||
std::string version;
|
||||
std::string protocolVersion;
|
||||
};
|
||||
|
||||
const ClientInfo& getClientInfo() const {
|
||||
return m_clientInfo;
|
||||
}
|
||||
|
||||
private:
|
||||
nlohmann::json handleInitialize(const nlohmann::json ¶ms);
|
||||
void handleNotifications(const std::string &method, const nlohmann::json ¶ms);
|
||||
|
||||
struct Primitive {
|
||||
nlohmann::json capabilities;
|
||||
std::function<nlohmann::json(const nlohmann::json ¶ms)> function;
|
||||
};
|
||||
|
||||
std::map<std::string, std::map<std::string, Primitive>> m_primitives;
|
||||
|
||||
wolv::net::SocketServer m_server;
|
||||
bool m_connected = false;
|
||||
ClientInfo m_clientInfo;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -72,6 +72,21 @@ namespace hex::prv {
|
||||
[[nodiscard]] virtual std::vector<Description> getDataDescription() const = 0;
|
||||
};
|
||||
|
||||
class IProviderDataBackupable {
|
||||
public:
|
||||
explicit IProviderDataBackupable(Provider *provider);
|
||||
virtual ~IProviderDataBackupable() = default;
|
||||
|
||||
void createBackupIfNeeded(const std::fs::path &inputFilePath);
|
||||
private:
|
||||
Provider *m_provider = nullptr;
|
||||
bool m_backupCreated = false;
|
||||
|
||||
bool m_shouldCreateBackups = true;
|
||||
u64 m_maxSize;
|
||||
std::string m_backupExtension;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Represent the data source for a tab in the UI
|
||||
*/
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
namespace hex::prv {
|
||||
@@ -40,6 +41,8 @@ namespace hex::prv::undo {
|
||||
|
||||
bool add(std::unique_ptr<Operation> &&operation);
|
||||
|
||||
static std::recursive_mutex& getMutex();
|
||||
|
||||
const std::vector<std::unique_ptr<Operation>> &getAppliedOperations() const {
|
||||
return m_undoStack;
|
||||
}
|
||||
|
||||
@@ -319,6 +319,7 @@ namespace ImGuiExt {
|
||||
bool DimmedButtonToggle(const char *icon, bool *v, ImVec2 size = ImVec2(0, 0), ImVec2 iconOffset = ImVec2(0, 0));
|
||||
bool DimmedIconToggle(const char *icon, bool *v);
|
||||
bool DimmedIconToggle(const char *iconOn, const char *iconOff, bool *v);
|
||||
bool DimmedArrowButton(const char *id, ImGuiDir dir, ImVec2 size = ImVec2(ImGui::GetFrameHeight(), ImGui::GetFrameHeight()));
|
||||
|
||||
void TextOverlay(const char *text, ImVec2 pos, float maxWidth = -1);
|
||||
|
||||
|
||||
@@ -147,6 +147,7 @@ namespace hex {
|
||||
class View::Window : public View {
|
||||
public:
|
||||
explicit Window(UnlocalizedString unlocalizedName, const char *icon) : View(std::move(unlocalizedName), icon) {}
|
||||
[[nodiscard]] ImGuiWindow *getFocusedSubWindow() const { return m_focusedSubWindow; }
|
||||
|
||||
/**
|
||||
* @brief Draws help text for the view
|
||||
@@ -155,9 +156,15 @@ namespace hex {
|
||||
|
||||
void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) override;
|
||||
|
||||
virtual bool allowScroll() const {
|
||||
[[nodiscard]] virtual bool allowScroll() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
void handleFocusRestoration();
|
||||
|
||||
private:
|
||||
ImGuiWindow *m_focusedSubWindow{nullptr};
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -192,11 +199,9 @@ namespace hex {
|
||||
|
||||
void draw(ImGuiWindowFlags extraFlags = ImGuiWindowFlags_None) final;
|
||||
|
||||
bool allowScroll() const final {
|
||||
[[nodiscard]] bool allowScroll() const final {
|
||||
return true;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool shouldStoreWindowState() const override { return false; }
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -264,8 +264,7 @@ namespace hex {
|
||||
}
|
||||
}
|
||||
|
||||
if (json.empty())
|
||||
return;
|
||||
if (json.empty()) return;
|
||||
|
||||
#if defined(OS_WEB)
|
||||
auto data = json.dump();
|
||||
|
||||
@@ -594,6 +594,12 @@ namespace hex {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Spacer::draw(const std::string& name) {
|
||||
std::ignore = name;
|
||||
ImGui::NewLine();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -624,22 +630,22 @@ namespace hex {
|
||||
void add(Type type, const std::string &command, const UnlocalizedString &unlocalizedDescription, const impl::DisplayCallback &displayCallback, const impl::ExecuteCallback &executeCallback) {
|
||||
log::debug("Registered new command palette command: {}", command);
|
||||
|
||||
impl::s_entries->push_back(impl::Entry { type, command, unlocalizedDescription, displayCallback, executeCallback });
|
||||
impl::s_entries->push_back(impl::Entry { .type=type, .command=command, .unlocalizedDescription=unlocalizedDescription, .displayCallback=displayCallback, .executeCallback=executeCallback });
|
||||
}
|
||||
|
||||
void addHandler(Type type, const std::string &command, const impl::QueryCallback &queryCallback, const impl::DisplayCallback &displayCallback) {
|
||||
log::debug("Registered new command palette command handler: {}", command);
|
||||
|
||||
impl::s_handlers->push_back(impl::Handler { type, command, queryCallback, displayCallback });
|
||||
impl::s_handlers->push_back(impl::Handler { .type=type, .command=command, .queryCallback=queryCallback, .displayCallback=displayCallback });
|
||||
}
|
||||
|
||||
void setDisplayedContent(const impl::ContentDisplayCallback &displayCallback) {
|
||||
impl::s_displayedContent = impl::ContentDisplay { true, displayCallback };
|
||||
impl::s_displayedContent = impl::ContentDisplay { .showSearchBox=true, .callback=displayCallback };
|
||||
}
|
||||
|
||||
void openWithContent(const impl::ContentDisplayCallback &displayCallback) {
|
||||
RequestOpenCommandPalette::post();
|
||||
impl::s_displayedContent = impl::ContentDisplay { false, displayCallback };
|
||||
impl::s_displayedContent = impl::ContentDisplay { .showSearchBox=false, .callback=displayCallback };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -777,12 +783,12 @@ namespace hex {
|
||||
|
||||
void addVisualizer(const std::string &name, const impl::VisualizerFunctionCallback &function, pl::api::FunctionParameterCount parameterCount) {
|
||||
log::debug("Registered new pattern visualizer function: {}", name);
|
||||
(*impl::s_visualizers)[name] = impl::Visualizer { parameterCount, function };
|
||||
(*impl::s_visualizers)[name] = impl::Visualizer { .parameterCount=parameterCount, .callback=function };
|
||||
}
|
||||
|
||||
void addInlineVisualizer(const std::string &name, const impl::VisualizerFunctionCallback &function, pl::api::FunctionParameterCount parameterCount) {
|
||||
log::debug("Registered new inline pattern visualizer function: {}", name);
|
||||
(*impl::s_inlineVisualizers)[name] = impl::Visualizer { parameterCount, function };
|
||||
(*impl::s_inlineVisualizers)[name] = impl::Visualizer { .parameterCount=parameterCount, .callback=function };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -848,7 +854,7 @@ namespace hex {
|
||||
void add(const UnlocalizedString &unlocalizedName, const char *icon, const impl::Callback &function) {
|
||||
log::debug("Registered new tool: {}", unlocalizedName.get());
|
||||
|
||||
impl::s_tools->emplace_back(impl::Entry { unlocalizedName, icon, function });
|
||||
impl::s_tools->emplace_back(impl::Entry { .unlocalizedName=unlocalizedName, .icon=icon, .function=function });
|
||||
}
|
||||
|
||||
}
|
||||
@@ -864,6 +870,18 @@ namespace hex {
|
||||
|
||||
}
|
||||
|
||||
namespace EditWidget {
|
||||
std::optional<std::vector<u8>> TextInput::draw(std::string &value, std::endian endian) {
|
||||
if (ImGui::InputText("##InspectorLineEditing", value,
|
||||
ImGuiInputTextFlags_EnterReturnsTrue |
|
||||
ImGuiInputTextFlags_AutoSelectAll)) {
|
||||
return getBytes(value, endian);
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
void add(const UnlocalizedString &unlocalizedName, size_t requiredSize, impl::GeneratorFunction displayGeneratorFunction, std::optional<impl::EditingFunction> editingFunction) {
|
||||
log::debug("Registered new data inspector format: {}", unlocalizedName.get());
|
||||
|
||||
@@ -991,7 +1009,7 @@ namespace hex {
|
||||
coloredIcon.color = ImGuiCustomCol_ToolbarGray;
|
||||
|
||||
impl::s_menuItems->insert({
|
||||
priority, impl::MenuItem { unlocalizedMainMenuNames, coloredIcon, shortcut, view, function, enabledCallback, selectedCallback, -1 }
|
||||
priority, impl::MenuItem { .unlocalizedNames=unlocalizedMainMenuNames, .icon=coloredIcon, .shortcut=shortcut, .view=view, .callback=function, .enabledCallback=enabledCallback, .selectedCallback=selectedCallback, .toolbarIndex=-1 }
|
||||
});
|
||||
|
||||
if (shortcut != Shortcut::None) {
|
||||
@@ -1015,14 +1033,23 @@ namespace hex {
|
||||
|
||||
unlocalizedMainMenuNames.emplace_back(impl::SubMenuValue);
|
||||
impl::s_menuItems->insert({
|
||||
priority, impl::MenuItem { unlocalizedMainMenuNames, icon, showOnWelcomeScreen ? Shortcut({ ShowOnWelcomeScreen }) : Shortcut::None, view, function, enabledCallback, []{ return false; }, -1 }
|
||||
priority, impl::MenuItem { .unlocalizedNames=unlocalizedMainMenuNames, .icon=icon, .shortcut=showOnWelcomeScreen ? Shortcut({ ShowOnWelcomeScreen }) : Shortcut::None, .view=view, .callback=function, .enabledCallback=enabledCallback, .selectedCallback=[]{ return false; }, .toolbarIndex=-1 }
|
||||
});
|
||||
}
|
||||
|
||||
void addMenuItemSeparator(std::vector<UnlocalizedString> unlocalizedMainMenuNames, u32 priority, View *view) {
|
||||
unlocalizedMainMenuNames.emplace_back(impl::SeparatorValue);
|
||||
impl::s_menuItems->insert({
|
||||
priority, impl::MenuItem { unlocalizedMainMenuNames, "", Shortcut::None, view, []{}, []{ return true; }, []{ return false; }, -1 }
|
||||
priority, impl::MenuItem { .unlocalizedNames=unlocalizedMainMenuNames, .icon="", .shortcut=Shortcut::None, .view=view, .callback=[]{}, .enabledCallback=[]{ return true; }, .selectedCallback=[]{ return false; }, .toolbarIndex=-1 }
|
||||
});
|
||||
}
|
||||
|
||||
void addTaskBarMenuItem(std::vector<UnlocalizedString> unlocalizedMainMenuNames, u32 priority, const impl::MenuCallback &function, const impl::EnabledCallback& enabledCallback) {
|
||||
log::debug("Added new taskbar menu item to menu {} ", unlocalizedMainMenuNames[0].get());
|
||||
|
||||
unlocalizedMainMenuNames.insert(unlocalizedMainMenuNames.begin(), impl::TaskBarMenuValue);
|
||||
impl::s_menuItems->insert({
|
||||
priority, impl::MenuItem { .unlocalizedNames=unlocalizedMainMenuNames, .icon="", .shortcut=Shortcut::None, .view=nullptr, .callback=function, .enabledCallback=enabledCallback, .selectedCallback=[]{ return false; }, .toolbarIndex=-1 }
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1038,13 +1065,13 @@ namespace hex {
|
||||
impl::s_toolbarItems->push_back(function);
|
||||
}
|
||||
|
||||
void addMenuItemToToolbar(const UnlocalizedString& unlocalizedName, ImGuiCustomCol color) {
|
||||
void addMenuItemToToolbar(const std::vector<UnlocalizedString>& unlocalizedNames, ImGuiCustomCol color) {
|
||||
const auto maxIndex = std::ranges::max_element(impl::getMenuItems(), [](const auto &a, const auto &b) {
|
||||
return a.second.toolbarIndex < b.second.toolbarIndex;
|
||||
})->second.toolbarIndex;
|
||||
|
||||
for (auto &[priority, menuItem] : *impl::s_menuItems) {
|
||||
if (menuItem.unlocalizedNames.back() == unlocalizedName) {
|
||||
if (menuItem.unlocalizedNames == unlocalizedNames) {
|
||||
menuItem.toolbarIndex = maxIndex + 1;
|
||||
menuItem.icon.color = color;
|
||||
updateToolbarItems();
|
||||
@@ -1096,9 +1123,9 @@ namespace hex {
|
||||
|
||||
}
|
||||
|
||||
namespace ContentRegistry::Provider {
|
||||
|
||||
|
||||
namespace impl {
|
||||
namespace ContentRegistry::Provider::impl {
|
||||
|
||||
void add(const std::string &typeName, ProviderCreationFunction creationFunction) {
|
||||
(void)RequestCreateProvider::subscribe([expectedName = typeName, creationFunction](const std::string &name, bool skipLoadInterface, bool selectProvider, std::shared_ptr<prv::Provider> *provider) {
|
||||
@@ -1127,7 +1154,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
namespace ContentRegistry::DataFormatter {
|
||||
|
||||
@@ -1283,47 +1310,42 @@ namespace hex {
|
||||
|
||||
}
|
||||
|
||||
namespace ContentRegistry::Diffing {
|
||||
|
||||
namespace impl {
|
||||
namespace ContentRegistry::Diffing::impl {
|
||||
|
||||
static AutoReset<std::vector<std::unique_ptr<Algorithm>>> s_algorithms;
|
||||
const std::vector<std::unique_ptr<Algorithm>>& getAlgorithms() {
|
||||
return *s_algorithms;
|
||||
}
|
||||
|
||||
void addAlgorithm(std::unique_ptr<Algorithm> &&hash) {
|
||||
s_algorithms->emplace_back(std::move(hash));
|
||||
}
|
||||
static AutoReset<std::vector<std::unique_ptr<Algorithm>>> s_algorithms;
|
||||
const std::vector<std::unique_ptr<Algorithm>>& getAlgorithms() {
|
||||
return *s_algorithms;
|
||||
}
|
||||
|
||||
void addAlgorithm(std::unique_ptr<Algorithm> &&hash) {
|
||||
s_algorithms->emplace_back(std::move(hash));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace ContentRegistry::Hashes {
|
||||
|
||||
namespace impl {
|
||||
namespace ContentRegistry::Hashes::impl {
|
||||
|
||||
static AutoReset<std::vector<std::unique_ptr<Hash>>> s_hashes;
|
||||
const std::vector<std::unique_ptr<Hash>>& getHashes() {
|
||||
return *s_hashes;
|
||||
}
|
||||
|
||||
void add(std::unique_ptr<Hash> &&hash) {
|
||||
s_hashes->emplace_back(std::move(hash));
|
||||
}
|
||||
static AutoReset<std::vector<std::unique_ptr<Hash>>> s_hashes;
|
||||
const std::vector<std::unique_ptr<Hash>>& getHashes() {
|
||||
return *s_hashes;
|
||||
}
|
||||
|
||||
void add(std::unique_ptr<Hash> &&hash) {
|
||||
s_hashes->emplace_back(std::move(hash));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
namespace ContentRegistry::BackgroundServices {
|
||||
|
||||
namespace impl {
|
||||
|
||||
class Service {
|
||||
public:
|
||||
Service(const UnlocalizedString &unlocalizedName, std::jthread thread) : m_unlocalizedName(std::move(unlocalizedName)), m_thread(std::move(thread)) { }
|
||||
Service(UnlocalizedString unlocalizedName, std::jthread thread) : m_unlocalizedName(std::move(unlocalizedName)), m_thread(std::move(thread)) { }
|
||||
Service(const Service&) = delete;
|
||||
Service(Service &&) = default;
|
||||
~Service() {
|
||||
@@ -1395,6 +1417,40 @@ namespace hex {
|
||||
|
||||
}
|
||||
|
||||
namespace ContentRegistry::MCP {
|
||||
|
||||
namespace impl {
|
||||
|
||||
std::unique_ptr<mcp::Server>& getMcpServerInstance() {
|
||||
static std::unique_ptr<mcp::Server> server;
|
||||
|
||||
if (server == nullptr)
|
||||
server = std::make_unique<mcp::Server>();
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
static bool s_mcpEnabled = false;
|
||||
void setEnabled(bool enabled) {
|
||||
s_mcpEnabled = enabled;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool isEnabled() {
|
||||
return impl::s_mcpEnabled;
|
||||
}
|
||||
|
||||
bool isConnected() {
|
||||
return impl::getMcpServerInstance()->isConnected();
|
||||
}
|
||||
|
||||
void registerTool(std::string_view capabilities, std::function<nlohmann::json(const nlohmann::json ¶ms)> function) {
|
||||
impl::getMcpServerInstance()->addPrimitive("tools", capabilities, function);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace ContentRegistry::Experiments {
|
||||
|
||||
namespace impl {
|
||||
@@ -1488,22 +1544,19 @@ namespace hex {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
namespace ContentRegistry::Disassemblers {
|
||||
namespace ContentRegistry::Disassemblers::impl {
|
||||
|
||||
namespace impl {
|
||||
static AutoReset<std::map<std::string, impl::CreatorFunction>> s_architectures;
|
||||
|
||||
static AutoReset<std::map<std::string, impl::CreatorFunction>> s_architectures;
|
||||
|
||||
void addArchitectureCreator(impl::CreatorFunction function) {
|
||||
const auto arch = function();
|
||||
(*s_architectures)[arch->getName()] = std::move(function);
|
||||
}
|
||||
|
||||
const std::map<std::string, impl::CreatorFunction>& getArchitectures() {
|
||||
return *s_architectures;
|
||||
}
|
||||
void addArchitectureCreator(impl::CreatorFunction function) {
|
||||
const auto arch = function();
|
||||
(*s_architectures)[arch->getName()] = std::move(function);
|
||||
}
|
||||
|
||||
const std::map<std::string, impl::CreatorFunction>& getArchitectures() {
|
||||
return *s_architectures;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <algorithm>
|
||||
#include <hex/api/event_manager.hpp>
|
||||
|
||||
namespace hex {
|
||||
@@ -35,7 +36,7 @@ namespace hex {
|
||||
|
||||
void EventManager::unsubscribe(void *token, impl::EventId id) {
|
||||
auto &tokenStore = getTokenStore();
|
||||
auto iter = std::find_if(tokenStore.begin(), tokenStore.end(), [&](auto &item) {
|
||||
auto iter = std::ranges::find_if(tokenStore, [&](auto &item) {
|
||||
return item.first == token && item.second->first == id;
|
||||
});
|
||||
|
||||
|
||||
@@ -47,6 +47,10 @@
|
||||
|
||||
#if defined(OS_WEB)
|
||||
#include <emscripten.h>
|
||||
#elif defined(OS_MACOS)
|
||||
extern "C" {
|
||||
void macosRegisterFont(const unsigned char *data, size_t size);
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace hex {
|
||||
@@ -257,7 +261,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
void setSelection(u64 address, size_t size, prv::Provider *provider) {
|
||||
setSelection({ { address, size }, provider == nullptr ? Provider::get() : provider });
|
||||
setSelection({ { .address=address, .size=size }, provider == nullptr ? Provider::get() : provider });
|
||||
}
|
||||
|
||||
void addVirtualFile(const std::string &path, std::vector<u8> data, Region region) {
|
||||
@@ -281,7 +285,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
u64 add(u64 address, size_t size, const std::string &name, const std::string &comment, u32 color) {
|
||||
return add(Region { address, size }, name, comment, color);
|
||||
return add(Region { .address=address, .size=size }, name, comment, color);
|
||||
}
|
||||
|
||||
void remove(u64 id) {
|
||||
@@ -534,6 +538,11 @@ namespace hex {
|
||||
s_mainWindowHandle = window;
|
||||
}
|
||||
|
||||
static bool s_mainWindowFocused = false;
|
||||
void setMainWindowFocusState(bool focused) {
|
||||
s_mainWindowFocused = focused;
|
||||
}
|
||||
|
||||
|
||||
static float s_globalScale = 1.0;
|
||||
void setGlobalScale(float scale) {
|
||||
@@ -671,13 +680,15 @@ namespace hex {
|
||||
if (!sessionType.has_value() || sessionType == "x11")
|
||||
return 1.0F;
|
||||
else {
|
||||
float xScale = 0, yScale = 0;
|
||||
glfwGetMonitorContentScale(glfwGetPrimaryMonitor(), &xScale, &yScale);
|
||||
int windowW, windowH;
|
||||
int displayW, displayH;
|
||||
glfwGetWindowSize(getMainWindowHandle(), &windowW, &windowH);
|
||||
glfwGetFramebufferSize(getMainWindowHandle(), &displayW, &displayH);
|
||||
|
||||
return std::midpoint(xScale, yScale);
|
||||
return (windowW > 0) ? float(displayW) / windowW : 1.0f;
|
||||
}
|
||||
#elif defined(OS_WEB)
|
||||
return 1.0F;
|
||||
return emscripten_get_device_pixel_ratio();
|
||||
#else
|
||||
return 1.0F;
|
||||
#endif
|
||||
@@ -704,6 +715,10 @@ namespace hex {
|
||||
return impl::s_mainWindowHandle;
|
||||
}
|
||||
|
||||
bool isMainWindowFocused() {
|
||||
return impl::s_mainWindowFocused;
|
||||
}
|
||||
|
||||
bool isBorderlessWindowModeEnabled() {
|
||||
return impl::s_borderlessWindowMode;
|
||||
}
|
||||
@@ -900,7 +915,7 @@ namespace hex {
|
||||
}
|
||||
}
|
||||
|
||||
return { { name, version } };
|
||||
return { { .name=name, .version=version } };
|
||||
}
|
||||
|
||||
const SemanticVersion& getImHexVersion() {
|
||||
@@ -1205,6 +1220,10 @@ namespace hex {
|
||||
offset,
|
||||
fontSizeMultiplier
|
||||
);
|
||||
|
||||
#if defined(OS_MACOS)
|
||||
macosRegisterFont(data.data(), data.size_bytes());
|
||||
#endif
|
||||
}
|
||||
|
||||
void registerFont(const Font& font) {
|
||||
@@ -1216,7 +1235,7 @@ namespace hex {
|
||||
|
||||
if (it == impl::s_fontDefinitions->end()) {
|
||||
const auto defaultFont = ImGui::GetDefaultFont();
|
||||
return { defaultFont, defaultFont, defaultFont };
|
||||
return { .regular=defaultFont, .bold=defaultFont, .italic=defaultFont };
|
||||
} else
|
||||
return it->second;
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
void LayoutManager::lockLayout(bool locked) {
|
||||
log::info("Layout {}", locked ? "locked" : "unlocked");
|
||||
log::debug("Layout {}", locked ? "locked" : "unlocked");
|
||||
s_layoutLocked = locked;
|
||||
}
|
||||
|
||||
|
||||
@@ -50,13 +50,13 @@ namespace hex {
|
||||
definition.fallbackLanguageId = item["fallback"].get<std::string>();
|
||||
}
|
||||
|
||||
if (item.contains("hidden") && item["hidden"].get<bool>() == true) {
|
||||
if (item.contains("hidden") && item["hidden"].get<bool>()) {
|
||||
definition.hidden = true;
|
||||
}
|
||||
|
||||
const auto path = item["path"].get<std::string>();
|
||||
|
||||
definition.languageFilePaths.emplace_back(PathEntry{ path, callback });
|
||||
definition.languageFilePaths.emplace_back(PathEntry{ .path=path, .callback=callback });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,9 +104,21 @@ namespace hex {
|
||||
|
||||
for (const auto &entry : json.items()) {
|
||||
auto value = entry.value().get<std::string>();
|
||||
|
||||
// Skip empty values
|
||||
if (value.empty())
|
||||
continue;
|
||||
|
||||
// Handle references to files
|
||||
if (value.starts_with("#@")) {
|
||||
try {
|
||||
value = path.callback(value.substr(2));
|
||||
} catch (std::exception &e) {
|
||||
log::error("Failed to load localization file reference '{}': {}", entry.key(), e.what());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
localizations.try_emplace(LangConst::hash(entry.key()), std::move(value));
|
||||
}
|
||||
} catch (std::exception &e) {
|
||||
@@ -143,7 +155,7 @@ namespace hex {
|
||||
static AutoReset<std::unordered_map<std::size_t, std::string>> loadedLocalization;
|
||||
static std::mutex mutex;
|
||||
|
||||
std::lock_guard lock(mutex);
|
||||
std::scoped_lock lock(mutex);
|
||||
if (*currentLanguageId != languageId) {
|
||||
currentLanguageId = languageId;
|
||||
loadedLocalization->clear();
|
||||
|
||||
@@ -85,7 +85,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
Plugin::Plugin(const std::string &name, const hex::PluginFunctions &functions) :
|
||||
m_handle(0), m_path(name), m_addedManually(true), m_functions(functions) { }
|
||||
m_path(name), m_addedManually(true), m_functions(functions) { }
|
||||
|
||||
|
||||
Plugin::Plugin(Plugin &&other) noexcept {
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
std::fs::path ProjectFile::getPath() {
|
||||
return s_currProjectPath;
|
||||
return *s_currProjectPath;
|
||||
}
|
||||
|
||||
void ProjectFile::setPath(const std::fs::path &path) {
|
||||
|
||||
@@ -281,25 +281,25 @@ namespace hex {
|
||||
|
||||
void ShortcutManager::addGlobalShortcut(const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const std::function<void()> &callback, const EnabledCallback &enabledCallback) {
|
||||
log::debug("Adding global shortcut {} for {}", shortcut.toString(), unlocalizedName.back().get());
|
||||
auto [it, inserted] = s_globalShortcuts->insert({ shortcut, { shortcut, unlocalizedName, callback, enabledCallback } });
|
||||
auto [it, inserted] = s_globalShortcuts->insert({ shortcut, { .shortcut=shortcut, .unlocalizedName=unlocalizedName, .callback=callback, .enabledCallback=enabledCallback } });
|
||||
if (!inserted) log::error("Failed to add shortcut!");
|
||||
}
|
||||
|
||||
void ShortcutManager::addGlobalShortcut(const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const std::function<void()> &callback, const EnabledCallback &enabledCallback) {
|
||||
log::debug("Adding global shortcut {} for {}", shortcut.toString(), unlocalizedName.get());
|
||||
auto [it, inserted] = s_globalShortcuts->insert({ shortcut, { shortcut, { unlocalizedName }, callback, enabledCallback } });
|
||||
auto [it, inserted] = s_globalShortcuts->insert({ shortcut, { .shortcut=shortcut, .unlocalizedName={ unlocalizedName }, .callback=callback, .enabledCallback=enabledCallback } });
|
||||
if (!inserted) log::error("Failed to add shortcut!");
|
||||
}
|
||||
|
||||
void ShortcutManager::addShortcut(View *view, const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const std::function<void()> &callback, const EnabledCallback &enabledCallback) {
|
||||
log::debug("Adding shortcut {} for {}", shortcut.toString(), unlocalizedName.back().get());
|
||||
auto [it, inserted] = view->m_shortcuts.insert({ shortcut + CurrentView, { shortcut, unlocalizedName, callback, enabledCallback } });
|
||||
auto [it, inserted] = view->m_shortcuts.insert({ shortcut + CurrentView, { .shortcut=shortcut, .unlocalizedName=unlocalizedName, .callback=callback, .enabledCallback=enabledCallback } });
|
||||
if (!inserted) log::error("Failed to add shortcut!");
|
||||
}
|
||||
|
||||
void ShortcutManager::addShortcut(View *view, const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const std::function<void()> &callback, const EnabledCallback &enabledCallback) {
|
||||
log::debug("Adding shortcut {} for {}", shortcut.toString(), unlocalizedName.get());
|
||||
auto [it, inserted] = view->m_shortcuts.insert({ shortcut + CurrentView, { shortcut, { unlocalizedName }, callback, enabledCallback } });
|
||||
auto [it, inserted] = view->m_shortcuts.insert({ shortcut + CurrentView, { .shortcut=shortcut, .unlocalizedName={ unlocalizedName }, .callback=callback, .enabledCallback=enabledCallback } });
|
||||
if (!inserted) log::error("Failed to add shortcut!");
|
||||
}
|
||||
|
||||
@@ -329,12 +329,13 @@ namespace hex {
|
||||
if (ImGui::IsPopupOpen(ImGuiID(0), ImGuiPopupFlags_AnyPopupId))
|
||||
return true;
|
||||
|
||||
const bool currentlyTyping = ImGui::GetIO().WantTextInput;
|
||||
|
||||
auto it = shortcuts.find(shortcut + AllowWhileTyping);
|
||||
if (!currentlyTyping && it == shortcuts.end()) {
|
||||
auto it = shortcuts.end();
|
||||
if (ImGui::GetIO().WantTextInput) {
|
||||
it = shortcuts.find(shortcut + AllowWhileTyping);
|
||||
} else {
|
||||
it = shortcuts.find(shortcut);
|
||||
if (it == shortcuts.end())
|
||||
it = shortcuts.find(shortcut);
|
||||
it = shortcuts.find(shortcut + AllowWhileTyping);
|
||||
}
|
||||
|
||||
if (it != shortcuts.end()) {
|
||||
@@ -366,7 +367,17 @@ namespace hex {
|
||||
if (keyCode != 0)
|
||||
s_prevShortcut = Shortcut(pressedShortcut.getKeys());
|
||||
|
||||
runShortcut(pressedShortcut, currentView);
|
||||
std::set<const View*> processedViews;
|
||||
while (true) {
|
||||
if (runShortcut(pressedShortcut, currentView)) {
|
||||
break;
|
||||
}
|
||||
|
||||
processedViews.insert(currentView);
|
||||
currentView = currentView->getMenuItemInheritView();
|
||||
if (currentView == nullptr || processedViews.contains(currentView))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ShortcutManager::processGlobals(bool ctrl, bool alt, bool shift, bool super, u32 keyCode) {
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <jthread.hpp>
|
||||
#include <hex/helpers/debugging.hpp>
|
||||
#include <hex/trace/exceptions.hpp>
|
||||
#include <utility>
|
||||
|
||||
#if defined(OS_WINDOWS)
|
||||
#include <windows.h>
|
||||
@@ -54,6 +55,7 @@ namespace hex {
|
||||
std::list<std::function<void()>> s_deferredCalls;
|
||||
std::unordered_map<SourceLocationWrapper, std::function<void()>> s_onceDeferredCalls;
|
||||
std::list<std::function<void()>> s_tasksFinishedCallbacks;
|
||||
std::list<std::function<void(Task&)>> s_taskCompletionCallbacks;
|
||||
|
||||
std::mutex s_queueMutex;
|
||||
std::condition_variable s_jobCondVar;
|
||||
@@ -66,8 +68,8 @@ namespace hex {
|
||||
}
|
||||
|
||||
|
||||
Task::Task(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, bool blocking, std::function<void(Task &)> function)
|
||||
: m_unlocalizedName(unlocalizedName),
|
||||
Task::Task(UnlocalizedString unlocalizedName, u64 maxValue, bool background, bool blocking, std::function<void(Task &)> function)
|
||||
: m_unlocalizedName(std::move(unlocalizedName)),
|
||||
m_maxValue(maxValue),
|
||||
m_function(std::move(function)),
|
||||
m_background(background), m_blocking(blocking) { }
|
||||
@@ -321,6 +323,13 @@ namespace hex {
|
||||
task->m_function(*task);
|
||||
|
||||
log::debug("Task '{}' finished", task->m_unlocalizedName.get());
|
||||
|
||||
{
|
||||
std::scoped_lock lock(s_tasksFinishedMutex);
|
||||
|
||||
for (const auto &callback : s_taskCompletionCallbacks)
|
||||
callback(*task);
|
||||
}
|
||||
} catch (const Task::TaskInterruptor &) {
|
||||
// Handle the task being interrupted by user request
|
||||
task->interruption();
|
||||
@@ -360,7 +369,10 @@ namespace hex {
|
||||
thread.request_stop();
|
||||
|
||||
// Wake up all the idle worker threads so they can exit
|
||||
s_jobCondVar.notify_all();
|
||||
{
|
||||
std::unique_lock lock(s_queueMutex);
|
||||
s_jobCondVar.notify_all();
|
||||
}
|
||||
|
||||
// Wait for all worker threads to exit
|
||||
s_workers.clear();
|
||||
@@ -371,6 +383,7 @@ namespace hex {
|
||||
s_deferredCalls.clear();
|
||||
s_onceDeferredCalls.clear();
|
||||
s_tasksFinishedCallbacks.clear();
|
||||
s_taskCompletionCallbacks.clear();
|
||||
}
|
||||
|
||||
TaskHolder TaskManager::createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, bool blocking, std::function<void(Task&)> function) {
|
||||
@@ -579,5 +592,13 @@ namespace hex {
|
||||
return s_mainThreadId == std::this_thread::get_id();
|
||||
}
|
||||
|
||||
void TaskManager::addTaskCompletionCallback(const std::function<void(Task &)> &function) {
|
||||
std::scoped_lock lock(s_tasksFinishedMutex);
|
||||
|
||||
for (const auto &task : s_tasks) {
|
||||
task->interrupt();
|
||||
}
|
||||
|
||||
s_taskCompletionCallbacks.push_back(function);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace hex {
|
||||
void ThemeManager::addThemeHandler(const std::string &name, const ColorMap &colorMap, const std::function<ImColor(u32)> &getFunction, const std::function<void(u32, ImColor)> &setFunction) {
|
||||
std::unique_lock lock(s_themeMutex);
|
||||
|
||||
(*s_themeHandlers)[name] = { colorMap, getFunction, setFunction };
|
||||
(*s_themeHandlers)[name] = { .colorMap=colorMap, .getFunction=getFunction, .setFunction=setFunction };
|
||||
}
|
||||
|
||||
void ThemeManager::addStyleHandler(const std::string &name, const StyleMap &styleMap) {
|
||||
|
||||
@@ -32,6 +32,8 @@ namespace hex {
|
||||
ImGuiID s_activeHelpId;
|
||||
bool s_helpHoverActive = false;
|
||||
|
||||
AutoReset<std::function<std::function<void()>(const std::string &)>> s_renderer;
|
||||
|
||||
|
||||
class IDStack {
|
||||
public:
|
||||
@@ -55,7 +57,7 @@ namespace hex {
|
||||
|
||||
void add(const void *pointer) {
|
||||
const ImGuiID seed = idStack.back();
|
||||
const ImGuiID id = ImHashData(&pointer, sizeof(pointer), seed);
|
||||
const ImGuiID id = ImHashData((const void*) &pointer, sizeof(pointer), seed);
|
||||
|
||||
idStack.push_back(id);
|
||||
}
|
||||
@@ -94,38 +96,47 @@ namespace hex {
|
||||
}
|
||||
|
||||
void TutorialManager::init() {
|
||||
EventImGuiElementRendered::subscribe([](ImGuiID id, const std::array<float, 4> bb){
|
||||
const auto boundingBox = ImRect(bb[0], bb[1], bb[2], bb[3]);
|
||||
if (*s_renderer == nullptr) {
|
||||
*s_renderer = [](const std::string &message) {
|
||||
return [message] {
|
||||
ImGui::PushTextWrapPos(300_scaled);
|
||||
ImGui::TextUnformatted(message.c_str());
|
||||
ImGui::PopTextWrapPos();
|
||||
ImGui::NewLine();
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (!ImGui::IsRectVisible(boundingBox.Min, boundingBox.Max))
|
||||
return;
|
||||
void TutorialManager::postElementRendered(ImGuiID id, const ImRect &boundingBox) {
|
||||
if (!ImGui::IsRectVisible(boundingBox.Min, boundingBox.Max))
|
||||
return;
|
||||
|
||||
{
|
||||
const auto element = hex::s_highlights->find(id);
|
||||
if (element != hex::s_highlights->end()) {
|
||||
hex::s_highlightDisplays->emplace_back(boundingBox, element->second);
|
||||
{
|
||||
const auto element = hex::s_highlights->find(id);
|
||||
if (element != hex::s_highlights->end()) {
|
||||
hex::s_highlightDisplays->emplace_back(boundingBox, element->second);
|
||||
|
||||
const auto window = ImGui::GetCurrentWindow();
|
||||
if (window != nullptr && window->DockNode != nullptr && window->DockNode->TabBar != nullptr)
|
||||
window->DockNode->TabBar->NextSelectedTabId = window->TabId;
|
||||
}
|
||||
const auto window = ImGui::GetCurrentWindow();
|
||||
if (window != nullptr && window->DockNode != nullptr && window->DockNode->TabBar != nullptr)
|
||||
window->DockNode->TabBar->NextSelectedTabId = window->TabId;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const auto element = s_interactiveHelpItems->find(id);
|
||||
if (element != s_interactiveHelpItems->end()) {
|
||||
(*s_interactiveHelpDisplays)[id] = boundingBox;
|
||||
}
|
||||
|
||||
{
|
||||
const auto element = s_interactiveHelpItems->find(id);
|
||||
if (element != s_interactiveHelpItems->end()) {
|
||||
(*s_interactiveHelpDisplays)[id] = boundingBox;
|
||||
}
|
||||
}
|
||||
|
||||
if (id != 0 && boundingBox.Contains(ImGui::GetMousePos())) {
|
||||
if ((s_hoveredRect.GetArea() == 0 || boundingBox.GetArea() < s_hoveredRect.GetArea()) && s_interactiveHelpItems->contains(id)) {
|
||||
s_hoveredRect = boundingBox;
|
||||
s_hoveredId = id;
|
||||
}
|
||||
|
||||
if (id != 0 && boundingBox.Contains(ImGui::GetMousePos())) {
|
||||
if ((s_hoveredRect.GetArea() == 0 || boundingBox.GetArea() < s_hoveredRect.GetArea()) && s_interactiveHelpItems->contains(id)) {
|
||||
s_hoveredRect = boundingBox;
|
||||
s_hoveredId = id;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const std::map<std::string, TutorialManager::Tutorial>& TutorialManager::getTutorials() {
|
||||
@@ -204,6 +215,10 @@ namespace hex {
|
||||
s_currentTutorial->second.start();
|
||||
}
|
||||
|
||||
void TutorialManager::stopCurrentTutorial() {
|
||||
s_currentTutorial = s_tutorials->end();
|
||||
}
|
||||
|
||||
void TutorialManager::drawHighlights() {
|
||||
if (s_helpHoverActive) {
|
||||
const auto &drawList = ImGui::GetForegroundDrawList(ImGui::GetMainViewport());
|
||||
@@ -303,10 +318,10 @@ namespace hex {
|
||||
|
||||
if (!message.has_value()) {
|
||||
message = Tutorial::Step::Message {
|
||||
Position::None,
|
||||
"",
|
||||
"",
|
||||
false
|
||||
.position=Position::None,
|
||||
.unlocalizedTitle="",
|
||||
.unlocalizedMessage="",
|
||||
.allowSkip=false
|
||||
};
|
||||
}
|
||||
|
||||
@@ -333,34 +348,39 @@ namespace hex {
|
||||
|
||||
ImGui::SetNextWindowPos(position, ImGuiCond_Always, pivot);
|
||||
ImGui::SetNextWindowViewport(ImGui::GetMainViewport()->ID);
|
||||
if (ImGui::Begin("##TutorialMessage", nullptr, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoFocusOnAppearing)) {
|
||||
ImGui::SetNextWindowSize(ImVec2(300_scaled, 0));
|
||||
|
||||
bool open = true;
|
||||
if (ImGui::Begin(message->unlocalizedTitle.empty() ? "##TutorialMessage" : Lang(message->unlocalizedTitle), &open, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoFocusOnAppearing)) {
|
||||
ImGui::BringWindowToDisplayFront(ImGui::GetCurrentWindowRead());
|
||||
|
||||
if (!message->unlocalizedTitle.empty())
|
||||
ImGuiExt::Header(Lang(message->unlocalizedTitle), true);
|
||||
|
||||
auto &step = s_currentTutorial->second.m_currentStep;
|
||||
if (!message->unlocalizedMessage.empty()) {
|
||||
ImGui::PushTextWrapPos(300_scaled);
|
||||
ImGui::TextUnformatted(Lang(message->unlocalizedMessage));
|
||||
ImGui::PopTextWrapPos();
|
||||
step->m_drawFunction();
|
||||
ImGui::NewLine();
|
||||
ImGui::NewLine();
|
||||
}
|
||||
|
||||
ImGui::BeginDisabled(s_currentTutorial->second.m_currentStep == s_currentTutorial->second.m_steps.begin());
|
||||
if (ImGui::ArrowButton("Backwards", ImGuiDir_Left)) {
|
||||
ImGui::BeginDisabled(step == s_currentTutorial->second.m_steps.begin());
|
||||
if (ImGuiExt::DimmedArrowButton("Backwards", ImGuiDir_Left)) {
|
||||
s_currentTutorial->second.m_currentStep->advance(-1);
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::BeginDisabled(!message->allowSkip && s_currentTutorial->second.m_currentStep == s_currentTutorial->second.m_latestStep);
|
||||
if (ImGui::ArrowButton("Forwards", ImGuiDir_Right)) {
|
||||
s_currentTutorial->second.m_currentStep->advance(1);
|
||||
ImGui::SetCursorPosX(ImGui::GetWindowWidth() - ImGui::GetFrameHeight() - ImGui::GetStyle().WindowPadding.x);
|
||||
ImGui::BeginDisabled(!message->allowSkip && step == s_currentTutorial->second.m_latestStep);
|
||||
if (ImGuiExt::DimmedArrowButton("Forwards", ImGuiDir_Right)) {
|
||||
step->advance(1);
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
ImGui::End();
|
||||
|
||||
if (!open) {
|
||||
stopCurrentTutorial();
|
||||
}
|
||||
}
|
||||
|
||||
void TutorialManager::drawTutorial() {
|
||||
@@ -387,6 +407,10 @@ namespace hex {
|
||||
s_highlightDisplays->clear();
|
||||
}
|
||||
|
||||
void TutorialManager::setRenderer(std::function<DrawFunction(const std::string &)> renderer) {
|
||||
s_renderer = std::move(renderer);
|
||||
}
|
||||
|
||||
TutorialManager::Tutorial::Step& TutorialManager::Tutorial::addStep() {
|
||||
auto &newStep = m_steps.emplace_back(this);
|
||||
m_currentStep = m_steps.end();
|
||||
@@ -402,6 +426,9 @@ namespace hex {
|
||||
return;
|
||||
|
||||
m_currentStep->addHighlights();
|
||||
|
||||
if (m_currentStep->m_message.has_value())
|
||||
m_currentStep->m_drawFunction = (*s_renderer)(Lang(m_currentStep->m_message->unlocalizedMessage));
|
||||
}
|
||||
|
||||
void TutorialManager::Tutorial::Step::addHighlights() const {
|
||||
@@ -426,8 +453,12 @@ namespace hex {
|
||||
std::advance(m_parent->m_latestStep, steps);
|
||||
std::advance(m_parent->m_currentStep, steps);
|
||||
|
||||
if (m_parent->m_currentStep != m_parent->m_steps.end())
|
||||
if (m_parent->m_currentStep != m_parent->m_steps.end()) {
|
||||
m_parent->m_currentStep->addHighlights();
|
||||
|
||||
if (m_message.has_value())
|
||||
m_parent->m_currentStep->m_drawFunction = (*s_renderer)(Lang(m_parent->m_currentStep->m_message->unlocalizedMessage));
|
||||
}
|
||||
else
|
||||
s_currentTutorial = s_tutorials->end();
|
||||
}
|
||||
@@ -450,10 +481,10 @@ namespace hex {
|
||||
|
||||
TutorialManager::Tutorial::Step& TutorialManager::Tutorial::Step::setMessage(const UnlocalizedString &unlocalizedTitle, const UnlocalizedString &unlocalizedMessage, Position position) {
|
||||
m_message = Message {
|
||||
position,
|
||||
unlocalizedTitle,
|
||||
unlocalizedMessage,
|
||||
false
|
||||
.position=position,
|
||||
.unlocalizedTitle=unlocalizedTitle,
|
||||
.unlocalizedMessage=unlocalizedMessage,
|
||||
.allowSkip=false
|
||||
};
|
||||
|
||||
return *this;
|
||||
@@ -464,10 +495,10 @@ namespace hex {
|
||||
m_message->allowSkip = true;
|
||||
} else {
|
||||
m_message = Message {
|
||||
Position::Bottom | Position::Right,
|
||||
"",
|
||||
"",
|
||||
true
|
||||
.position=Position::Bottom | Position::Right,
|
||||
.unlocalizedTitle="",
|
||||
.unlocalizedMessage="",
|
||||
.allowSkip=true
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -135,7 +135,7 @@ namespace hex {
|
||||
|
||||
void WorkspaceManager::process() {
|
||||
if (s_previousWorkspace != s_currentWorkspace) {
|
||||
log::info("Updating workspace");
|
||||
log::debug("Updating workspace");
|
||||
if (s_previousWorkspace != s_workspaces->end()) {
|
||||
auto newWorkspace = s_currentWorkspace;
|
||||
s_currentWorkspace = s_previousWorkspace;
|
||||
|
||||
@@ -151,8 +151,8 @@ namespace hex::dp {
|
||||
m_overlay->getData() = data;
|
||||
}
|
||||
|
||||
[[noreturn]] void Node::throwNodeError(const std::string &message) {
|
||||
throw NodeError { this, message };
|
||||
[[noreturn]] void Node::throwNodeError(const std::string &msg) {
|
||||
throw NodeError(this, msg);
|
||||
}
|
||||
|
||||
void Node::setAttributes(std::vector<Attribute> attributes) {
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace hex {
|
||||
namespace {
|
||||
|
||||
void skipWhitespace(std::string_view &string) {
|
||||
while (string.length() > 0) {
|
||||
while (!string.empty()) {
|
||||
if (!std::isspace(string.front()))
|
||||
break;
|
||||
string = string.substr(1);
|
||||
@@ -89,15 +89,15 @@ namespace hex {
|
||||
return { };
|
||||
|
||||
bool inString = false;
|
||||
while (string.length() > 0) {
|
||||
BinaryPattern::Pattern pattern = { 0, 0 };
|
||||
while (!string.empty()) {
|
||||
BinaryPattern::Pattern pattern = { .mask=0, .value=0 };
|
||||
|
||||
if (string.starts_with("\"")) {
|
||||
inString = !inString;
|
||||
string = string.substr(1);
|
||||
continue;
|
||||
} else if (inString) {
|
||||
pattern = { 0xFF, u8(string.front()) };
|
||||
pattern = { .mask=0xFF, .value=u8(string.front()) };
|
||||
string = string.substr(1);
|
||||
} else if (string.starts_with("u") || string.starts_with("s")) {
|
||||
auto newPatterns = parseValueExpression(string);
|
||||
@@ -106,7 +106,7 @@ namespace hex {
|
||||
std::ranges::move(newPatterns, std::back_inserter(result));
|
||||
continue;
|
||||
} else if (string.starts_with("??")) {
|
||||
pattern = { 0x00, 0x00 };
|
||||
pattern = { .mask=0x00, .value=0x00 };
|
||||
string = string.substr(2);
|
||||
} else if ((std::isxdigit(string.front()) || string.front() == '?') && string.length() >= 2) {
|
||||
const auto hex = string.substr(0, 2);
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#endif
|
||||
|
||||
#include <array>
|
||||
#include <functional>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <bit>
|
||||
@@ -82,7 +81,7 @@ namespace hex::crypt {
|
||||
|
||||
public:
|
||||
constexpr Crc(u64 polynomial, u64 init, u64 xorOut, bool reflectInput, bool reflectOutput)
|
||||
: m_value(0x00), m_init(init & ((0b10ull << (NumBits - 1)) - 1)), m_xorOut(xorOut & ((0b10ull << (NumBits - 1)) - 1)),
|
||||
: m_init(init & ((0b10ull << (NumBits - 1)) - 1)), m_xorOut(xorOut & ((0b10ull << (NumBits - 1)) - 1)),
|
||||
m_reflectInput(reflectInput), m_reflectOutput(reflectOutput),
|
||||
m_table([polynomial] {
|
||||
auto reflectedPoly = reflect(polynomial & ((0b10ull << (NumBits - 1)) - 1), NumBits);
|
||||
@@ -129,7 +128,7 @@ namespace hex::crypt {
|
||||
}
|
||||
|
||||
private:
|
||||
u64 m_value;
|
||||
u64 m_value = 0x00;
|
||||
|
||||
u64 m_init;
|
||||
u64 m_xorOut;
|
||||
@@ -144,7 +143,7 @@ namespace hex::crypt {
|
||||
using Crc = Crc<NumBits>;
|
||||
Crc crc(polynomial, init, xorout, reflectIn, reflectOut);
|
||||
|
||||
processDataByChunks(data, offset, size, std::bind(&Crc::processBytes, &crc, _1, _2));
|
||||
processDataByChunks(data, offset, size, [&crc](auto && data, auto && size) { crc.processBytes(data, size); });
|
||||
|
||||
return crc.checksum();
|
||||
}
|
||||
@@ -170,7 +169,7 @@ namespace hex::crypt {
|
||||
|
||||
mbedtls_md5_starts(&ctx);
|
||||
|
||||
processDataByChunks(data, offset, size, std::bind(mbedtls_md5_update, &ctx, _1, _2));
|
||||
processDataByChunks(data, offset, size, [&ctx](auto && data, auto && size) { return mbedtls_md5_update(&ctx, data, size); });
|
||||
|
||||
mbedtls_md5_finish(&ctx, result.data());
|
||||
|
||||
@@ -202,7 +201,7 @@ namespace hex::crypt {
|
||||
|
||||
mbedtls_sha1_starts(&ctx);
|
||||
|
||||
processDataByChunks(data, offset, size, std::bind(mbedtls_sha1_update, &ctx, _1, _2));
|
||||
processDataByChunks(data, offset, size, [&ctx](auto && data, auto && size) { return mbedtls_sha1_update(&ctx, data, size); });
|
||||
|
||||
mbedtls_sha1_finish(&ctx, result.data());
|
||||
|
||||
@@ -234,7 +233,7 @@ namespace hex::crypt {
|
||||
|
||||
mbedtls_sha256_starts(&ctx, true);
|
||||
|
||||
processDataByChunks(data, offset, size, std::bind(mbedtls_sha256_update, &ctx, _1, _2));
|
||||
processDataByChunks(data, offset, size, [&ctx](auto && data, auto && size) { return mbedtls_sha256_update(&ctx, data, size); });
|
||||
|
||||
mbedtls_sha256_finish(&ctx, result.data());
|
||||
|
||||
@@ -266,7 +265,7 @@ namespace hex::crypt {
|
||||
|
||||
mbedtls_sha256_starts(&ctx, false);
|
||||
|
||||
processDataByChunks(data, offset, size, std::bind(mbedtls_sha256_update, &ctx, _1, _2));
|
||||
processDataByChunks(data, offset, size, [&ctx](auto && data, auto && size) { return mbedtls_sha256_update(&ctx, data, size); });
|
||||
|
||||
mbedtls_sha256_finish(&ctx, result.data());
|
||||
|
||||
@@ -298,7 +297,7 @@ namespace hex::crypt {
|
||||
|
||||
mbedtls_sha512_starts(&ctx, true);
|
||||
|
||||
processDataByChunks(data, offset, size, std::bind(mbedtls_sha512_update, &ctx, _1, _2));
|
||||
processDataByChunks(data, offset, size, [&ctx](auto && data, auto && size) { return mbedtls_sha512_update(&ctx, data, size); });
|
||||
|
||||
mbedtls_sha512_finish(&ctx, result.data());
|
||||
|
||||
@@ -330,7 +329,7 @@ namespace hex::crypt {
|
||||
|
||||
mbedtls_sha512_starts(&ctx, false);
|
||||
|
||||
processDataByChunks(data, offset, size, std::bind(mbedtls_sha512_update, &ctx, _1, _2));
|
||||
processDataByChunks(data, offset, size, [&ctx](auto && data, auto && size) { return mbedtls_sha512_update(&ctx, data, size); });
|
||||
|
||||
mbedtls_sha512_finish(&ctx, result.data());
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
#include <algorithm>
|
||||
#include <hex/helpers/default_paths.hpp>
|
||||
|
||||
#include <hex/api/imhex_api/system.hpp>
|
||||
#include <hex/api/project_file_manager.hpp>
|
||||
|
||||
#include <ranges>
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
|
||||
#if defined(OS_WINDOWS)
|
||||
#include <windows.h>
|
||||
@@ -17,6 +18,13 @@ namespace hex::paths {
|
||||
|
||||
std::vector<std::fs::path> getDataPaths(bool includeSystemFolders) {
|
||||
std::vector<std::fs::path> paths;
|
||||
std::set<std::fs::path> uniquePaths;
|
||||
|
||||
const auto emplaceUniquePath = [&](const std::fs::path &path) {
|
||||
auto duplicate = uniquePaths.insert(path);
|
||||
if (duplicate.second)
|
||||
paths.emplace_back(path);
|
||||
};
|
||||
|
||||
#if defined(OS_WINDOWS)
|
||||
|
||||
@@ -25,21 +33,22 @@ namespace hex::paths {
|
||||
if (!ImHexApi::System::isPortableVersion()) {
|
||||
PWSTR wAppDataPath = nullptr;
|
||||
if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, nullptr, &wAppDataPath))) {
|
||||
paths.emplace_back(wAppDataPath);
|
||||
emplaceUniquePath(wAppDataPath);
|
||||
CoTaskMemFree(wAppDataPath);
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(OS_MACOS)
|
||||
|
||||
paths.push_back(wolv::io::fs::getApplicationSupportDirectoryPath() / "imhex");
|
||||
emplaceUniquePath(wolv::io::fs::getApplicationSupportDirectoryPath() / "imhex");
|
||||
|
||||
#elif defined(OS_LINUX) || defined(OS_WEB)
|
||||
|
||||
paths.push_back(xdg::DataHomeDir());
|
||||
emplaceUniquePath(xdg::DataHomeDir());
|
||||
|
||||
auto dataDirs = xdg::DataDirs();
|
||||
std::copy(dataDirs.begin(), dataDirs.end(), std::back_inserter(paths));
|
||||
for (const auto &path : dataDirs)
|
||||
emplaceUniquePath(path);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -47,18 +56,21 @@ namespace hex::paths {
|
||||
|
||||
if (includeSystemFolders) {
|
||||
if (auto executablePath = wolv::io::fs::getExecutablePath(); executablePath.has_value()) {
|
||||
paths.push_back(executablePath->parent_path());
|
||||
emplaceUniquePath(executablePath->parent_path());
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
for (auto &path : paths)
|
||||
uniquePaths.clear();
|
||||
for (auto &path : paths) {
|
||||
path = path / "imhex";
|
||||
uniquePaths.insert(path);
|
||||
}
|
||||
|
||||
if (ImHexApi::System::isPortableVersion() || includeSystemFolders) {
|
||||
if (auto executablePath = wolv::io::fs::getExecutablePath(); executablePath.has_value())
|
||||
paths.push_back(executablePath->parent_path());
|
||||
emplaceUniquePath(executablePath->parent_path());
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -66,11 +78,12 @@ namespace hex::paths {
|
||||
|
||||
// Add additional data directories to the path
|
||||
auto additionalDirs = ImHexApi::System::getAdditionalFolderPaths();
|
||||
std::ranges::copy(additionalDirs, std::back_inserter(paths));
|
||||
for (const auto &path : additionalDirs)
|
||||
emplaceUniquePath(path);
|
||||
|
||||
// Add the project file directory to the path, if one is loaded
|
||||
if (ProjectFile::hasPath()) {
|
||||
paths.push_back(ProjectFile::getPath().parent_path());
|
||||
emplaceUniquePath(ProjectFile::getPath().parent_path());
|
||||
}
|
||||
|
||||
return paths;
|
||||
@@ -108,7 +121,7 @@ namespace hex::paths {
|
||||
|
||||
// Add the system plugin directory to the path if one was provided at compile time
|
||||
#if defined(OS_LINUX) && defined(SYSTEM_PLUGINS_LOCATION)
|
||||
paths.push_back(SYSTEM_PLUGINS_LOCATION);
|
||||
paths.emplace_back(SYSTEM_PLUGINS_LOCATION);
|
||||
#endif
|
||||
|
||||
return paths;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <hex/helpers/utils.hpp>
|
||||
|
||||
#include <ranges>
|
||||
#include <wolv/io/file.hpp>
|
||||
#include <wolv/utils/string.hpp>
|
||||
|
||||
@@ -65,6 +66,9 @@ namespace hex {
|
||||
|
||||
|
||||
EncodingFile &EncodingFile::operator=(const hex::EncodingFile &other) {
|
||||
if(this == &other) {
|
||||
return *this;
|
||||
}
|
||||
m_mapping = std::make_unique<std::map<size_t, std::map<std::vector<u8>, std::string>>>(*other.m_mapping);
|
||||
m_tableContent = other.m_tableContent;
|
||||
m_longestSequence = other.m_longestSequence;
|
||||
@@ -89,9 +93,7 @@ namespace hex {
|
||||
|
||||
|
||||
std::pair<std::string_view, size_t> EncodingFile::getEncodingFor(std::span<const u8> buffer) const {
|
||||
for (auto riter = m_mapping->crbegin(); riter != m_mapping->crend(); ++riter) {
|
||||
const auto &[size, mapping] = *riter;
|
||||
|
||||
for (const auto &[size, mapping] : std::ranges::reverse_view(*m_mapping)) {
|
||||
if (size > buffer.size()) continue;
|
||||
|
||||
std::vector key(buffer.begin(), buffer.begin() + size);
|
||||
@@ -103,9 +105,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
u64 EncodingFile::getEncodingLengthFor(std::span<u8> buffer) const {
|
||||
for (auto riter = m_mapping->crbegin(); riter != m_mapping->crend(); ++riter) {
|
||||
const auto &[size, mapping] = *riter;
|
||||
|
||||
for (const auto& [size, mapping] : std::ranges::reverse_view(*m_mapping)) {
|
||||
if (size > buffer.size()) continue;
|
||||
|
||||
std::vector key(buffer.begin(), buffer.begin() + size);
|
||||
|
||||
@@ -13,8 +13,6 @@
|
||||
#include <xdg.hpp>
|
||||
# if defined(OS_FREEBSD)
|
||||
#include <sys/syslimits.h>
|
||||
# else
|
||||
#include <limits.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
@@ -3,13 +3,12 @@
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
|
||||
#include <array>
|
||||
#include <hex/api/tutorial_manager.hpp>
|
||||
|
||||
#if !defined(IMGUI_TEST_ENGINE)
|
||||
|
||||
void ImGuiTestEngineHook_ItemAdd(ImGuiContext*, ImGuiID id, const ImRect& bb, const ImGuiLastItemData*) {
|
||||
std::array<float, 4> boundingBox = { bb.Min.x, bb.Min.y, bb.Max.x, bb.Max.y };
|
||||
hex::EventImGuiElementRendered::post(id, boundingBox);
|
||||
hex::TutorialManager::postElementRendered(id, bb);
|
||||
}
|
||||
|
||||
void ImGuiTestEngineHook_ItemInfo(ImGuiContext*, ImGuiID, const char*, ImGuiItemStatusFlags) {}
|
||||
|
||||
@@ -118,8 +118,8 @@ namespace hex::log {
|
||||
|
||||
void addLogEntry(std::string_view project, std::string_view level, std::string message) {
|
||||
s_logEntries->emplace_back(
|
||||
std::move(project),
|
||||
std::move(level),
|
||||
project,
|
||||
level,
|
||||
std::move(message)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <objc/runtime.h>
|
||||
|
||||
struct KeyEquivalent {
|
||||
bool valid;
|
||||
@@ -61,7 +62,120 @@ void macosEndMainMenuBar(void) {
|
||||
s_constructingMenu = false;
|
||||
}
|
||||
|
||||
bool macosBeginMenu(const char* label, bool enabled) {
|
||||
|
||||
static NSMutableArray* g_RegisteredIconFontDescriptors = nil;
|
||||
void macosRegisterFont(const unsigned char* fontBytes, size_t fontLength) {
|
||||
if (!fontBytes || fontLength == 0 || fontLength > 100 * 1024 * 1024) { // Max 100MB sanity check
|
||||
NSLog(@"Invalid font data: bytes=%p, length=%zu", fontBytes, fontLength);
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize array on first use
|
||||
if (!g_RegisteredIconFontDescriptors) {
|
||||
g_RegisteredIconFontDescriptors = [[NSMutableArray alloc] init];
|
||||
}
|
||||
|
||||
// Create NSData - this will copy the bytes
|
||||
NSData *fontData = [NSData dataWithBytes:fontBytes length:fontLength];
|
||||
if (!fontData) {
|
||||
NSLog(@"Failed to create NSData from font bytes");
|
||||
return;
|
||||
}
|
||||
|
||||
CFErrorRef error = NULL;
|
||||
CFArrayRef descriptors = CTFontManagerCreateFontDescriptorsFromData((__bridge CFDataRef)fontData);
|
||||
|
||||
if (descriptors && CFArrayGetCount(descriptors) > 0) {
|
||||
// Register all descriptors from this font file
|
||||
CTFontManagerRegisterFontDescriptors(descriptors, kCTFontManagerScopeProcess, true, NULL);
|
||||
if (true) {
|
||||
// Store each descriptor for later use
|
||||
for (CFIndex i = 0; i < CFArrayGetCount(descriptors); i++) {
|
||||
CTFontDescriptorRef descriptor = (CTFontDescriptorRef)CFArrayGetValueAtIndex(descriptors, i);
|
||||
[g_RegisteredIconFontDescriptors addObject:(__bridge id)descriptor];
|
||||
|
||||
// Log the font name for debugging
|
||||
CTFontRef font = CTFontCreateWithFontDescriptor(descriptor, 16.0, NULL);
|
||||
if (font) {
|
||||
CFRelease(font);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
NSLog(@"Failed to register font descriptors");
|
||||
}
|
||||
|
||||
CFRelease(descriptors);
|
||||
} else {
|
||||
NSLog(@"Failed to create font descriptors from data (length: %zu)", fontLength);
|
||||
if (error) {
|
||||
NSLog(@"Error: %@", (__bridge NSError *)error);
|
||||
CFRelease(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static NSImage* imageFromIconFont(NSString* character,
|
||||
CGFloat size,
|
||||
NSColor* color) {
|
||||
|
||||
if (!character || [character length] == 0) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
if (!g_RegisteredIconFontDescriptors || [g_RegisteredIconFontDescriptors count] == 0) {
|
||||
NSLog(@"No icon fonts registered");
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSFont *font = nil;
|
||||
unichar unicode = [character characterAtIndex:0];
|
||||
|
||||
for (id descriptorObj in g_RegisteredIconFontDescriptors) {
|
||||
CTFontDescriptorRef descriptor = (__bridge CTFontDescriptorRef)descriptorObj;
|
||||
CTFontRef ctFont = CTFontCreateWithFontDescriptor(descriptor, size, NULL);
|
||||
|
||||
if (ctFont) {
|
||||
CGGlyph glyph;
|
||||
UniChar unichar = unicode;
|
||||
if (CTFontGetGlyphsForCharacters(ctFont, &unichar, &glyph, 1)) {
|
||||
font = (__bridge NSFont *)ctFont;
|
||||
break;
|
||||
}
|
||||
CFRelease(ctFont);
|
||||
}
|
||||
}
|
||||
|
||||
if (!font) {
|
||||
NSLog(@"No font found with glyph for character U+%04X (string: '%@', length: %lu)",
|
||||
unicode, character, (unsigned long)[character length]);
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSDictionary *attributes = @{
|
||||
NSFontAttributeName: font,
|
||||
NSForegroundColorAttributeName: color
|
||||
};
|
||||
NSAttributedString *attrString = [[NSAttributedString alloc]
|
||||
initWithString:character
|
||||
attributes:attributes];
|
||||
|
||||
NSSize stringSize = [attrString size];
|
||||
|
||||
NSImage *image = [[NSImage alloc] initWithSize:NSMakeSize(size, size)];
|
||||
|
||||
[image lockFocus];
|
||||
|
||||
NSPoint drawPoint = NSMakePoint((size - stringSize.width) / 2.0,
|
||||
(size - stringSize.height) / 2.0);
|
||||
[attrString drawAtPoint:drawPoint];
|
||||
|
||||
[image unlockFocus];
|
||||
[image setTemplate:YES];
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
bool macosBeginMenu(const char* label, const char *icon, bool enabled) {
|
||||
NSString* title = [NSString stringWithUTF8String:label];
|
||||
|
||||
// Search for menu item with the given name
|
||||
@@ -79,6 +193,17 @@ bool macosBeginMenu(const char* label, bool enabled) {
|
||||
menuItem.title = title;
|
||||
[menuItem setSubmenu:newMenu];
|
||||
|
||||
// Hide menus starting with '$' (used for special menus)
|
||||
if (label[0] == '$') {
|
||||
[menuItem setHidden:YES];
|
||||
}
|
||||
|
||||
if (icon != NULL) {
|
||||
NSString *iconString = [NSString stringWithUTF8String:icon];
|
||||
NSImage* iconImage = imageFromIconFont(iconString, 16.0, [NSColor blackColor]);
|
||||
[menuItem setImage:iconImage];
|
||||
}
|
||||
|
||||
// Add the new menu to the end of the list
|
||||
menuIndex = [s_menuStack[s_menuStackSize - 1] numberOfItems];
|
||||
|
||||
@@ -104,7 +229,7 @@ void macosEndMenu(void) {
|
||||
s_menuStackSize -= 1;
|
||||
}
|
||||
|
||||
bool macosMenuItem(const char* label, struct KeyEquivalent keyEquivalent, bool selected, bool enabled) {
|
||||
bool macosMenuItem(const char* label, const char *icon, struct KeyEquivalent keyEquivalent, bool selected, bool enabled) {
|
||||
NSString* title = [NSString stringWithUTF8String:label];
|
||||
|
||||
if (s_constructingMenu) {
|
||||
@@ -113,6 +238,12 @@ bool macosMenuItem(const char* label, struct KeyEquivalent keyEquivalent, bool s
|
||||
menuItem.action = @selector(OnClick:);
|
||||
menuItem.target = s_menuItemHandler;
|
||||
|
||||
if (icon != NULL) {
|
||||
NSString *iconString = [NSString stringWithUTF8String:icon];
|
||||
NSImage* iconImage = imageFromIconFont(iconString, 16.0, [NSColor blackColor]);
|
||||
[menuItem setImage:iconImage];
|
||||
}
|
||||
|
||||
[menuItem setTag:s_currTag];
|
||||
s_currTag += 1;
|
||||
|
||||
@@ -164,8 +295,8 @@ bool macosMenuItem(const char* label, struct KeyEquivalent keyEquivalent, bool s
|
||||
return false;
|
||||
}
|
||||
|
||||
bool macosMenuItemSelect(const char* label, struct KeyEquivalent keyEquivalent, bool* selected, bool enabled) {
|
||||
if (macosMenuItem(label, keyEquivalent, selected != NULL ? *selected : false, enabled)) {
|
||||
bool macosMenuItemSelect(const char* label, const char *icon, struct KeyEquivalent keyEquivalent, bool* selected, bool enabled) {
|
||||
if (macosMenuItem(label, icon, keyEquivalent, selected != NULL ? *selected : false, enabled)) {
|
||||
if (selected != NULL)
|
||||
*selected = !(*selected);
|
||||
|
||||
@@ -180,3 +311,94 @@ void macosSeparator(void) {
|
||||
[s_menuStack[s_menuStackSize - 1] addItem:separator];
|
||||
}
|
||||
}
|
||||
|
||||
@interface NSObject (DockMenuAddition)
|
||||
- (NSMenu *)imhexApplicationDockMenu:(NSApplication *)sender;
|
||||
@end
|
||||
|
||||
@implementation NSObject (DockMenuAddition)
|
||||
|
||||
- (NSMenu *)cloneMenu:(NSMenu *)originalMenu {
|
||||
NSMenu *clonedMenu = [[NSMenu alloc] initWithTitle:[originalMenu title]];
|
||||
|
||||
for (NSMenuItem *item in [originalMenu itemArray]) {
|
||||
NSMenuItem *clonedItem = [self cloneMenuItem:item];
|
||||
[clonedMenu addItem:clonedItem];
|
||||
}
|
||||
|
||||
return clonedMenu;
|
||||
}
|
||||
|
||||
- (NSMenuItem *)cloneMenuItem:(NSMenuItem *)original {
|
||||
if ([original isSeparatorItem]) {
|
||||
return [NSMenuItem separatorItem];
|
||||
}
|
||||
|
||||
// Create new item with same properties
|
||||
NSMenuItem *clone = [[NSMenuItem alloc] initWithTitle:[original title]
|
||||
action:[original action]
|
||||
keyEquivalent:[original keyEquivalent]];
|
||||
|
||||
// Copy other properties
|
||||
[clone setTarget:[original target]];
|
||||
[clone setEnabled:[original isEnabled]];
|
||||
[clone setImage:[original image]];
|
||||
[clone setTag:[original tag]];
|
||||
[clone setRepresentedObject:[original representedObject]];
|
||||
[clone setToolTip:[original toolTip]];
|
||||
[clone setState:[original state]];
|
||||
|
||||
// Handle submenus recursively
|
||||
if ([original hasSubmenu]) {
|
||||
NSMenu *clonedSubmenu = [self cloneMenu:[original submenu]];
|
||||
[clone setSubmenu:clonedSubmenu];
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
- (NSMenu *)imhexApplicationDockMenu:(NSApplication *)sender {
|
||||
NSMenu *dockMenu = [[NSMenu alloc] init];
|
||||
|
||||
NSInteger menuIndex = [s_menuStack[s_menuStackSize - 1] indexOfItemWithTitle:@"$TASKBAR$"];
|
||||
if (menuIndex == -1) {
|
||||
return dockMenu;
|
||||
}
|
||||
NSMenuItem *fileMenuItem = [s_menuStack[s_menuStackSize - 1] itemAtIndex:menuIndex];
|
||||
|
||||
// Get the File submenu
|
||||
NSMenu *fileSubmenu = [fileMenuItem submenu];
|
||||
|
||||
if (fileSubmenu) {
|
||||
// Clone each item from the File submenu directly into the dock menu
|
||||
for (NSMenuItem *item in [fileSubmenu itemArray]) {
|
||||
NSMenuItem *clonedItem = [self cloneMenuItem:item];
|
||||
[dockMenu addItem:clonedItem];
|
||||
}
|
||||
}
|
||||
|
||||
return dockMenu;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
void macosSetupDockMenu(void) {
|
||||
@autoreleasepool {
|
||||
// Get GLFW's delegate class
|
||||
Class delegateClass = objc_getClass("GLFWApplicationDelegate");
|
||||
|
||||
if (delegateClass != nil) {
|
||||
// Get our custom implementation
|
||||
Method customMethod = class_getInstanceMethod([NSObject class],
|
||||
@selector(imhexApplicationDockMenu:));
|
||||
|
||||
// Add the method to GLFW's delegate class
|
||||
class_addMethod(delegateClass,
|
||||
@selector(applicationDockMenu:),
|
||||
method_getImplementation(customMethod),
|
||||
method_getTypeEncoding(customMethod));
|
||||
} else {
|
||||
NSLog(@"ERROR: Could not find GLFWApplicationDelegate class");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
#include <cstddef>
|
||||
#include "wolv/types.hpp"
|
||||
#include <cmath>
|
||||
#include <hex/helpers/opengl.hpp>
|
||||
#include <opengl_support.h>
|
||||
|
||||
#include <hex/helpers/utils.hpp>
|
||||
#include <hex/helpers/logger.hpp>
|
||||
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
#include <span>
|
||||
#include <wolv/utils/guards.hpp>
|
||||
|
||||
#include <numbers>
|
||||
@@ -133,17 +138,18 @@ namespace hex::gl {
|
||||
|
||||
|
||||
GLint Shader::getUniformLocation(std::string_view name) {
|
||||
auto uniform = m_uniforms.find(name.data());
|
||||
auto nameStr = std::string(name);
|
||||
auto uniform = m_uniforms.find(nameStr);
|
||||
if (uniform == m_uniforms.end()) {
|
||||
auto location = glGetUniformLocation(m_program, name.data());
|
||||
auto location = glGetUniformLocation(m_program, nameStr.data());
|
||||
if (location == -1) {
|
||||
log::warn("Uniform '{}' not found in shader", name);
|
||||
m_uniforms[name.data()] = -1;
|
||||
m_uniforms[nameStr] = -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
m_uniforms[name.data()] = location;
|
||||
uniform = m_uniforms.find(name.data());
|
||||
m_uniforms[nameStr] = location;
|
||||
uniform = m_uniforms.find(nameStr);
|
||||
}
|
||||
|
||||
return uniform->second;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <algorithm>
|
||||
#include <hex/helpers/patches.hpp>
|
||||
|
||||
#include <hex/helpers/utils.hpp>
|
||||
@@ -5,7 +6,6 @@
|
||||
#include <hex/providers/provider.hpp>
|
||||
|
||||
#include <cstring>
|
||||
#include <string_view>
|
||||
|
||||
|
||||
namespace hex {
|
||||
@@ -83,7 +83,7 @@ namespace hex {
|
||||
|
||||
[[nodiscard]] UnlocalizedString getTypeName() const override { return ""; }
|
||||
|
||||
const std::map<u64, u8>& getPatches() const {
|
||||
[[nodiscard]] const std::map<u64, u8>& getPatches() const {
|
||||
return m_patches;
|
||||
}
|
||||
private:
|
||||
@@ -92,7 +92,7 @@ namespace hex {
|
||||
|
||||
|
||||
void pushStringBack(std::vector<u8> &buffer, const std::string &string) {
|
||||
std::copy(string.begin(), string.end(), std::back_inserter(buffer));
|
||||
std::ranges::copy(string, std::back_inserter(buffer));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#include <microtar.h>
|
||||
|
||||
#include "wolv/utils/string.hpp"
|
||||
|
||||
namespace hex {
|
||||
|
||||
using namespace hex::literals;
|
||||
@@ -22,13 +24,13 @@ namespace hex {
|
||||
|
||||
m_ctx = std::make_unique<mtar_t>();
|
||||
|
||||
auto shortPath = wolv::io::fs::toShortPath(path);
|
||||
auto shortPath = wolv::io::fs::toNormalizedPathString(wolv::io::fs::toShortPath(path));
|
||||
if (mode == Tar::Mode::Read)
|
||||
tarError = mtar_open(m_ctx.get(), shortPath.string().c_str(), "r");
|
||||
tarError = mtar_open(m_ctx.get(), shortPath.c_str(), "r");
|
||||
else if (mode == Tar::Mode::Write)
|
||||
tarError = mtar_open(m_ctx.get(), shortPath.string().c_str(), "a");
|
||||
tarError = mtar_open(m_ctx.get(), shortPath.c_str(), "a");
|
||||
else if (mode == Tar::Mode::Create)
|
||||
tarError = mtar_open(m_ctx.get(), shortPath.string().c_str(), "w");
|
||||
tarError = mtar_open(m_ctx.get(), shortPath.c_str(), "w");
|
||||
else
|
||||
tarError = MTAR_EFAILURE;
|
||||
|
||||
@@ -187,4 +189,4 @@ namespace hex {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
namespace hex {
|
||||
|
||||
UDPServer::UDPServer(u16 port, Callback callback)
|
||||
: m_port(port), m_callback(std::move(callback)), m_running(false), m_socketFd(-1) {
|
||||
: m_port(port), m_callback(std::move(callback)), m_running(false) {
|
||||
}
|
||||
|
||||
UDPServer::~UDPServer() {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <algorithm>
|
||||
#include <cwchar>
|
||||
#include <hex/helpers/utils.hpp>
|
||||
|
||||
@@ -29,10 +30,12 @@
|
||||
#elif defined(OS_LINUX)
|
||||
#include <unistd.h>
|
||||
#include <dlfcn.h>
|
||||
#include <spawn.h>
|
||||
#include <hex/helpers/utils_linux.hpp>
|
||||
#elif defined(OS_MACOS)
|
||||
#include <unistd.h>
|
||||
#include <dlfcn.h>
|
||||
#include <spawn.h>
|
||||
#include <hex/helpers/utils_macos.hpp>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#elif defined(OS_WEB)
|
||||
@@ -98,7 +101,7 @@ namespace hex {
|
||||
string = wolv::util::replaceStrings(string, ",", "");
|
||||
|
||||
// Check for non-hex characters
|
||||
bool isValidHexString = std::find_if(string.begin(), string.end(), [](char c) {
|
||||
bool isValidHexString = std::ranges::find_if(string, [](char c) {
|
||||
return !std::isxdigit(c) && !std::isspace(c);
|
||||
}) == string.end();
|
||||
|
||||
@@ -353,6 +356,42 @@ namespace hex {
|
||||
return result;
|
||||
}
|
||||
|
||||
void executeCommandDetach(const std::string &command) {
|
||||
#if defined(OS_WINDOWS)
|
||||
STARTUPINFOA si = { };
|
||||
PROCESS_INFORMATION pi = { };
|
||||
si.cb = sizeof(si);
|
||||
|
||||
DWORD flags = CREATE_NEW_PROCESS_GROUP | CREATE_NO_WINDOW;
|
||||
std::string cmdCopy = command;
|
||||
|
||||
BOOL result = ::CreateProcessA(
|
||||
nullptr,
|
||||
cmdCopy.data(),
|
||||
nullptr,
|
||||
nullptr,
|
||||
false,
|
||||
flags,
|
||||
nullptr,
|
||||
nullptr,
|
||||
&si,
|
||||
&pi
|
||||
);
|
||||
|
||||
if (result) {
|
||||
::CloseHandle(pi.hProcess);
|
||||
::CloseHandle(pi.hThread);
|
||||
}
|
||||
#elif defined(OS_MACOS) || defined(OS_LINUX)
|
||||
pid_t pid;
|
||||
const char* argv[] = { "sh", "-c", command.c_str(), nullptr };
|
||||
|
||||
::posix_spawnp(&pid, "sh", nullptr, nullptr, const_cast<char* const*>(argv), nullptr);
|
||||
#elif defined(OS_WEB)
|
||||
std::ignore = command;
|
||||
#endif
|
||||
}
|
||||
|
||||
void openWebpage(std::string url) {
|
||||
if (!url.contains("://"))
|
||||
url = "https://" + url;
|
||||
@@ -507,7 +546,7 @@ namespace hex {
|
||||
if (ch <= 0x7F) {
|
||||
unicode = ch;
|
||||
unicodeSize = 0;
|
||||
} else if (ch <= 0xBF) {
|
||||
} else if (ch <= 0xBF) { //NOLINT(bugprone-branch-clone)
|
||||
return { };
|
||||
} else if (ch <= 0xDF) {
|
||||
unicode = ch&0x1F;
|
||||
@@ -568,7 +607,7 @@ namespace hex {
|
||||
index += 1;
|
||||
|
||||
if (wch < 0xD800 || wch > 0xDFFF) {
|
||||
unicode = static_cast<u32>(wch);
|
||||
unicode = static_cast<u32>(wch); // NOLINT(cert-str34-c)
|
||||
} else if (wch >= 0xD800 && wch <= 0xDBFF) {
|
||||
if (index == utf16.size())
|
||||
return "";
|
||||
@@ -829,7 +868,7 @@ namespace hex {
|
||||
input.imbue(std::locale(std::setlocale(LC_ALL, nullptr)));
|
||||
|
||||
tm time = {};
|
||||
input >> std::get_time(&time, format.data());
|
||||
input >> std::get_time(&time, std::string(format).data());
|
||||
if (input.fail()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
@@ -868,10 +907,10 @@ namespace hex {
|
||||
|
||||
if (lang.has_value() && !lang->empty() && *lang != "C" && *lang != "C.UTF-8") {
|
||||
auto parts = wolv::util::splitString(*lang, ".");
|
||||
if (parts.size() > 0)
|
||||
if (!parts.empty())
|
||||
return parts[0];
|
||||
else
|
||||
return *lang;
|
||||
return lang;
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
@@ -949,6 +988,12 @@ namespace hex {
|
||||
nid.dwInfoFlags = NIIF_INFO;
|
||||
|
||||
Shell_NotifyIcon(NIM_ADD, &nid);
|
||||
|
||||
Sleep(100);
|
||||
|
||||
Shell_NotifyIcon(NIM_DELETE, &nid);
|
||||
CloseWindow(hwnd);
|
||||
DestroyWindow(hwnd);
|
||||
#elif defined(OS_MACOS)
|
||||
toastMessageMacos(title.c_str(), message.c_str());
|
||||
#elif defined(OS_LINUX)
|
||||
@@ -957,17 +1002,21 @@ namespace hex {
|
||||
}
|
||||
#elif defined(OS_WEB)
|
||||
EM_ASM({
|
||||
const t = UTF8ToString($0);
|
||||
const m = UTF8ToString($1);
|
||||
try {
|
||||
const t = UTF8ToString($0);
|
||||
const m = UTF8ToString($1);
|
||||
|
||||
if (Notification.permission === "granted") {
|
||||
new Notification(t, { body: m });
|
||||
} else if (Notification.permission !== "denied") {
|
||||
Notification.requestPermission().then(function(p) {
|
||||
if (p === "granted") {
|
||||
new Notification(t, { body: m });
|
||||
}
|
||||
});
|
||||
if (Notification.permission === "granted") {
|
||||
new Notification(t, { body: m });
|
||||
} else if (Notification.permission !== "denied") {
|
||||
Notification.requestPermission().then(function(p) {
|
||||
if (p === "granted") {
|
||||
new Notification(t, { body: m });
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}, title.c_str(), message.c_str());
|
||||
#endif
|
||||
|
||||
@@ -10,13 +10,14 @@ namespace hex {
|
||||
|
||||
void executeCmd(const std::vector<std::string> &argsVector) {
|
||||
std::vector<char*> cArgsVector;
|
||||
for (const auto &str : argsVector) {
|
||||
cArgsVector.reserve(argsVector.size());
|
||||
for (const auto &str : argsVector) {
|
||||
cArgsVector.push_back(const_cast<char*>(str.c_str()));
|
||||
}
|
||||
cArgsVector.push_back(nullptr);
|
||||
|
||||
if (fork() == 0) {
|
||||
execvp(cArgsVector[0], &cArgsVector[0]);
|
||||
execvp(cArgsVector[0], cArgsVector.data());
|
||||
log::error("execvp() failed: {}", strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#if defined(OS_MACOS)
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
|
||||
#include <CoreFoundation/CFBundle.h>
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#include <Foundation/NSUserDefaults.h>
|
||||
@@ -70,6 +73,49 @@
|
||||
cocoaWindow.titlebarAppearsTransparent = YES;
|
||||
cocoaWindow.styleMask |= NSWindowStyleMaskFullSizeContentView;
|
||||
|
||||
// Setup liquid glass background effect
|
||||
{
|
||||
NSView* glfwContentView = [cocoaWindow contentView];
|
||||
|
||||
NSOpenGLContext* context = [NSOpenGLContext currentContext];
|
||||
if (!context) {
|
||||
glfwMakeContextCurrent(window);
|
||||
context = [NSOpenGLContext currentContext];
|
||||
}
|
||||
|
||||
GLint opaque = 0;
|
||||
[context setValues:&opaque forParameter:NSOpenGLCPSurfaceOpacity];
|
||||
[context update];
|
||||
|
||||
NSView* containerView = [[NSView alloc] initWithFrame:[glfwContentView frame]];
|
||||
containerView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
|
||||
[containerView setWantsLayer:YES];
|
||||
|
||||
Class glassEffectClass = NSClassFromString(@"NSGlassEffectView");
|
||||
NSView* effectView = nil;
|
||||
if (glassEffectClass) {
|
||||
// Use the new liquid glass effect
|
||||
effectView = [[glassEffectClass alloc] initWithFrame:[containerView bounds]];
|
||||
} else {
|
||||
// Fall back to NSVisualEffectView for older systems
|
||||
NSVisualEffectView* visualEffectView = [[NSVisualEffectView alloc] initWithFrame:[containerView bounds]];
|
||||
visualEffectView.material = NSVisualEffectMaterialHUDWindow;
|
||||
visualEffectView.blendingMode = NSVisualEffectBlendingModeBehindWindow;
|
||||
visualEffectView.state = NSVisualEffectStateActive;
|
||||
effectView = visualEffectView;
|
||||
}
|
||||
|
||||
effectView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
|
||||
|
||||
[containerView addSubview:effectView];
|
||||
|
||||
[glfwContentView removeFromSuperview];
|
||||
glfwContentView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
|
||||
[containerView addSubview:glfwContentView];
|
||||
|
||||
[cocoaWindow setContentView:containerView];
|
||||
}
|
||||
|
||||
[cocoaWindow setOpaque:NO];
|
||||
[cocoaWindow setHasShadow:YES];
|
||||
[cocoaWindow setBackgroundColor:[NSColor colorWithWhite: 0 alpha: 0.001f]];
|
||||
@@ -370,6 +416,27 @@
|
||||
return [bundlePath.pathExtension.lowercaseString isEqualToString:@"app"];
|
||||
}
|
||||
|
||||
@interface NotificationDelegate : NSObject <UNUserNotificationCenterDelegate>
|
||||
@end
|
||||
|
||||
@implementation NotificationDelegate
|
||||
|
||||
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
|
||||
willPresentNotification:(UNNotification *)notification
|
||||
withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler {
|
||||
if (@available(macOS 11.0, *)) {
|
||||
completionHandler(UNNotificationPresentationOptionBanner |
|
||||
UNNotificationPresentationOptionSound |
|
||||
UNNotificationPresentationOptionList);
|
||||
} else {
|
||||
// For macOS 10.15 and earlier
|
||||
completionHandler(UNNotificationPresentationOptionAlert |
|
||||
UNNotificationPresentationOptionSound);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
void toastMessageMacos(const char *title, const char *message) {
|
||||
@autoreleasepool {
|
||||
// Only show notification if we're inside a bundle
|
||||
@@ -407,5 +474,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
#endif
|
||||
|
||||
48
lib/libimhex/source/mcp/client.cpp
Normal file
48
lib/libimhex/source/mcp/client.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
#include <hex/mcp/client.hpp>
|
||||
#include <hex/mcp/server.hpp>
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <cstdlib>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <hex/api/imhex_api/system.hpp>
|
||||
#include <hex/helpers/logger.hpp>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <wolv/literals.hpp>
|
||||
#include <wolv/net/socket_client.hpp>
|
||||
|
||||
namespace hex::mcp {
|
||||
|
||||
using namespace wolv::literals;
|
||||
|
||||
int Client::run(std::istream &input, std::ostream &output) {
|
||||
wolv::net::SocketClient client(wolv::net::SocketClient::Type::TCP, true);
|
||||
client.connect("127.0.0.1", Server::McpInternalPort);
|
||||
|
||||
while (true) {
|
||||
std::string request;
|
||||
std::getline(input, request);
|
||||
|
||||
if (ImHexApi::System::isMainInstance()) {
|
||||
JsonRpc response(request);
|
||||
response.setError(JsonRpc::ErrorCode::InternalError, "No other instance of ImHex is running. Make sure that you have ImHex open already.");
|
||||
output << response.execute([](auto, auto){ return nlohmann::json::object(); }).value_or("") << '\n';
|
||||
continue;
|
||||
}
|
||||
|
||||
client.writeString(request);
|
||||
auto response = client.readBytesUntil(0x00);
|
||||
if (!response.empty() && response.front() != 0x00)
|
||||
output << std::string(response.begin(), response.end()) << std::endl;
|
||||
|
||||
if (!client.isConnected())
|
||||
break;
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
}
|
||||
243
lib/libimhex/source/mcp/server.cpp
Normal file
243
lib/libimhex/source/mcp/server.cpp
Normal file
@@ -0,0 +1,243 @@
|
||||
#include <hex/mcp/server.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <hex/helpers/logger.hpp>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <utility>
|
||||
#include <hex/api/task_manager.hpp>
|
||||
#include <wolv/net/socket_client.hpp>
|
||||
#include <hex/api/imhex_api/system.hpp>
|
||||
|
||||
|
||||
namespace hex::mcp {
|
||||
|
||||
std::optional<std::string> JsonRpc::execute(const Callback &callback) {
|
||||
try {
|
||||
auto requestJson = nlohmann::json::parse(m_request);
|
||||
|
||||
if (requestJson.is_array()) {
|
||||
return handleBatchedMessages(requestJson, callback).transform([](const auto &response) { return response.dump(); });
|
||||
} else {
|
||||
return handleMessage(requestJson, callback).transform([](const auto &response) { return response.dump(); });
|
||||
}
|
||||
} catch (const nlohmann::json::exception &) {
|
||||
return createErrorMessage(ErrorCode::ParseError, "Parse error").dump();
|
||||
}
|
||||
}
|
||||
|
||||
void JsonRpc::setError(ErrorCode code, std::string message) {
|
||||
m_error = Error{ code, std::move(message) };
|
||||
}
|
||||
|
||||
std::optional<nlohmann::json> JsonRpc::handleMessage(const nlohmann::json &request, const Callback &callback) {
|
||||
try {
|
||||
// Validate JSON-RPC request
|
||||
if (!request.contains("jsonrpc") || request["jsonrpc"] != "2.0" ||
|
||||
!request.contains("method") || !request["method"].is_string()) {
|
||||
m_id = request.contains("id") ? std::optional(request["id"].get<int>()) : std::nullopt;
|
||||
|
||||
return createErrorMessage(ErrorCode::InvalidRequest, "Invalid Request");
|
||||
}
|
||||
|
||||
m_id = request.contains("id") ? std::optional(request["id"].get<int>()) : std::nullopt;
|
||||
|
||||
// Return a user-specified error if set
|
||||
if (m_error.has_value()) {
|
||||
return createErrorMessage(m_error->code, m_error->message);
|
||||
}
|
||||
|
||||
// Execute the method
|
||||
auto result = callback(request["method"].get<std::string>(), request.value("params", nlohmann::json::object()));
|
||||
|
||||
if (!m_id.has_value())
|
||||
return std::nullopt;
|
||||
|
||||
return createResponseMessage(result.is_null() ? nlohmann::json::object() : result);
|
||||
} catch (const MethodNotFoundException &) {
|
||||
return createErrorMessage(ErrorCode::MethodNotFound, "Method not found");
|
||||
} catch (const InvalidParametersException &) {
|
||||
return createErrorMessage(ErrorCode::InvalidParams, "Invalid params");
|
||||
} catch (const std::exception &e) {
|
||||
return createErrorMessage(ErrorCode::InternalError, e.what());
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<nlohmann::json> JsonRpc::handleBatchedMessages(const nlohmann::json &request, const Callback &callback) {
|
||||
if (!request.is_array()) {
|
||||
return createErrorMessage(ErrorCode::InvalidRequest, "Invalid Request");
|
||||
}
|
||||
|
||||
nlohmann::json responses = nlohmann::json::array();
|
||||
for (const auto &message : request) {
|
||||
auto response = handleMessage(message, callback);
|
||||
if (response.has_value())
|
||||
responses.push_back(*response);
|
||||
}
|
||||
|
||||
if (responses.empty())
|
||||
return std::nullopt;
|
||||
|
||||
return responses;
|
||||
}
|
||||
|
||||
nlohmann::json JsonRpc::createDefaultMessage() {
|
||||
nlohmann::json message;
|
||||
message["jsonrpc"] = "2.0";
|
||||
if (m_id.has_value())
|
||||
message["id"] = m_id.value();
|
||||
else
|
||||
message["id"] = nullptr;
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
nlohmann::json JsonRpc::createErrorMessage(ErrorCode code, const std::string &message) {
|
||||
auto json = createDefaultMessage();
|
||||
json["error"] = {
|
||||
{ "code", int(code) },
|
||||
{ "message", message }
|
||||
};
|
||||
return json;
|
||||
}
|
||||
|
||||
nlohmann::json JsonRpc::createResponseMessage(const nlohmann::json &result) {
|
||||
auto json = createDefaultMessage();
|
||||
json["result"] = result;
|
||||
return json;
|
||||
}
|
||||
|
||||
Server::Server() : m_server(McpInternalPort, 1024, 1, true) {
|
||||
|
||||
}
|
||||
|
||||
Server::~Server() {
|
||||
this->shutdown();
|
||||
}
|
||||
|
||||
void Server::listen() {
|
||||
m_server.accept([this](auto, const std::vector<u8> &data) -> std::vector<u8> {
|
||||
std::string request(data.begin(), data.end());
|
||||
|
||||
TaskManager::setCurrentThreadName("MCP Server");
|
||||
log::debug("MCP ----> {}", request);
|
||||
|
||||
JsonRpc rpc(request);
|
||||
auto response = rpc.execute([this](const std::string &method, const nlohmann::json ¶ms) -> nlohmann::json {
|
||||
if (method == "initialize") {
|
||||
return handleInitialize(params);
|
||||
} else if (method.starts_with("notifications/")) {
|
||||
handleNotifications(method.substr(14), params);
|
||||
return {};
|
||||
} else if (method.ends_with("/list")) {
|
||||
auto primitiveName = method.substr(0, method.size() - 5);
|
||||
if (m_primitives.contains(primitiveName)) {
|
||||
nlohmann::json capabilitiesList = nlohmann::json::array();
|
||||
for (const auto &[name, primitive] : m_primitives[primitiveName]) {
|
||||
capabilitiesList.push_back(primitive.capabilities);
|
||||
}
|
||||
|
||||
nlohmann::json result;
|
||||
result[primitiveName] = capabilitiesList;
|
||||
return result;
|
||||
}
|
||||
} else if (method.ends_with("/call")) {
|
||||
auto primitive = method.substr(0, method.size() - 5);
|
||||
if (auto primitiveIt = m_primitives.find(primitive); primitiveIt != m_primitives.end()) {
|
||||
auto name = params.value("name", "");
|
||||
if (auto functionIt = primitiveIt->second.find(name); functionIt != primitiveIt->second.end()) {
|
||||
auto result = functionIt->second.function(params.value("arguments", nlohmann::json::object()));
|
||||
|
||||
return result.is_null() ? nlohmann::json::object() : result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw JsonRpc::MethodNotFoundException();
|
||||
});
|
||||
|
||||
log::debug("MCP <---- {}", response.value_or("<Nothing>"));
|
||||
|
||||
if (response.has_value()) {
|
||||
response->push_back(0x00);
|
||||
return { response->begin(), response->end() };
|
||||
}
|
||||
else
|
||||
return std::vector<u8>{ 0x00 };
|
||||
}, [this](auto) {
|
||||
log::info("MCP client disconnected");
|
||||
m_connected = false;
|
||||
m_clientInfo = {};
|
||||
}, true);
|
||||
}
|
||||
|
||||
void Server::shutdown() {
|
||||
m_server.shutdown();
|
||||
}
|
||||
|
||||
void Server::disconnect() {
|
||||
m_server.disconnectClients();
|
||||
}
|
||||
|
||||
void Server::addPrimitive(std::string type, std::string_view capabilities, std::function<nlohmann::json(const nlohmann::json ¶ms)> function) {
|
||||
auto json = nlohmann::json::parse(capabilities);
|
||||
auto name = json["name"].get<std::string>();
|
||||
|
||||
m_primitives[type][name] = {
|
||||
.capabilities=json,
|
||||
.function=function
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
nlohmann::json Server::handleInitialize(const nlohmann::json ¶ms) {
|
||||
constexpr static auto ServerName = "ImHex";
|
||||
constexpr static auto ProtocolVersion = "2025-06-18";
|
||||
|
||||
m_clientInfo = {};
|
||||
|
||||
if (params.contains("protocolVersion")) {
|
||||
auto clientProtocolVersion = params["protocolVersion"].get<std::string>();
|
||||
m_clientInfo.protocolVersion = clientProtocolVersion;
|
||||
} else {
|
||||
throw JsonRpc::InvalidParametersException();
|
||||
}
|
||||
|
||||
if (params.contains("clientInfo")) {
|
||||
const auto &clientInfo = params["clientInfo"];
|
||||
m_clientInfo.name = clientInfo.value("name", "???");
|
||||
m_clientInfo.version = clientInfo.value("version", "???");
|
||||
|
||||
log::info("MCP client connected: {} v{} (protocol {})", m_clientInfo.name, m_clientInfo.version, m_clientInfo.protocolVersion);
|
||||
} else {
|
||||
log::info("MCP client connected: Unknown client info");
|
||||
}
|
||||
|
||||
return {
|
||||
{ "protocolVersion", ProtocolVersion },
|
||||
{
|
||||
"capabilities",
|
||||
{
|
||||
{ "tools", nlohmann::json::object() },
|
||||
},
|
||||
},
|
||||
{
|
||||
"serverInfo", {
|
||||
{ "name", ServerName },
|
||||
{ "version", ImHexApi::System::getImHexVersion().get() }
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void Server::handleNotifications(const std::string &method, [[maybe_unused]] const nlohmann::json ¶ms) {
|
||||
if (method == "initialized") {
|
||||
m_connected = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool Server::isConnected() {
|
||||
return m_connected;
|
||||
}
|
||||
}
|
||||
@@ -49,7 +49,7 @@ namespace hex::prv {
|
||||
|
||||
{
|
||||
std::unique_lock lock(m_cacheMutex);
|
||||
m_cache[cacheSlot] = Block{blockIndex, std::move(blockData), false};
|
||||
m_cache[cacheSlot] = Block{.index=blockIndex, .data=std::move(blockData), .dirty=false};
|
||||
std::copy_n(m_cache[cacheSlot]->data.begin() + blockOffset, toRead, out);
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ namespace hex::prv {
|
||||
if (!slot || slot->index != blockIndex) {
|
||||
std::vector<uint8_t> blockData(m_cacheBlockSize);
|
||||
readFromSource(blockIndex * m_cacheBlockSize, blockData.data(), m_cacheBlockSize);
|
||||
slot = Block { blockIndex, std::move(blockData), false };
|
||||
slot = Block { .index=blockIndex, .data=std::move(blockData), .dirty=false };
|
||||
}
|
||||
|
||||
std::copy_n(in, toWrite, slot->data.begin() + blockOffset);
|
||||
|
||||
@@ -7,12 +7,14 @@
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <optional>
|
||||
#include <hex/api/content_registry/settings.hpp>
|
||||
|
||||
#include <hex/helpers/magic.hpp>
|
||||
#include <wolv/io/file.hpp>
|
||||
#include <wolv/literals.hpp>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <wolv/utils/string.hpp>
|
||||
|
||||
namespace hex::prv {
|
||||
|
||||
@@ -24,6 +26,28 @@ namespace hex::prv {
|
||||
|
||||
}
|
||||
|
||||
IProviderDataBackupable::IProviderDataBackupable(Provider* provider) : m_provider(provider) {
|
||||
m_shouldCreateBackups = ContentRegistry::Settings::read<bool>("hex.builtin.setting.general", "hex.builtin.setting.general.backups.file_backup.enable", true);
|
||||
m_maxSize = ContentRegistry::Settings::read<u32>("hex.builtin.setting.general", "hex.builtin.setting.general.backups.file_backup.max_size", 1_MiB);
|
||||
m_backupExtension = ContentRegistry::Settings::read<std::string>("hex.builtin.setting.general", "hex.builtin.setting.general.backups.file_backup.extension", ".bak");
|
||||
}
|
||||
|
||||
void IProviderDataBackupable::createBackupIfNeeded(const std::fs::path &inputFilePath) {
|
||||
if (!m_shouldCreateBackups || m_backupCreated)
|
||||
return;
|
||||
|
||||
if (m_provider->getActualSize() > m_maxSize)
|
||||
return;
|
||||
|
||||
const std::fs::path backupFilePath = wolv::util::toUTF8String(inputFilePath) + m_backupExtension;
|
||||
if (wolv::io::fs::copyFile(inputFilePath, backupFilePath, std::fs::copy_options::overwrite_existing)) {
|
||||
if (wolv::io::fs::exists(backupFilePath)) {
|
||||
m_backupCreated = true;
|
||||
log::info("Created backup of provider data at '{}'", backupFilePath.string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Provider::Provider() : m_undoRedoStack(this), m_id(s_idCounter++) {
|
||||
|
||||
@@ -33,7 +57,7 @@ namespace hex::prv {
|
||||
m_overlays.clear();
|
||||
|
||||
if (auto selection = ImHexApi::HexEditor::getSelection(); selection.has_value() && selection->provider == this)
|
||||
EventRegionSelected::post(ImHexApi::HexEditor::ProviderRegion { { 0x00, 0x00 }, nullptr });
|
||||
EventRegionSelected::post(ImHexApi::HexEditor::ProviderRegion { { .address=0x00, .size=0x00 }, nullptr });
|
||||
}
|
||||
|
||||
void Provider::read(u64 offset, void *buffer, size_t size, bool overlays) {
|
||||
@@ -109,7 +133,6 @@ namespace hex::prv {
|
||||
this->resizeRaw(newSize);
|
||||
|
||||
std::vector<u8> buffer(0x1000, 0x00);
|
||||
const std::vector<u8> zeroBuffer(0x1000, 0x00);
|
||||
|
||||
auto position = oldSize;
|
||||
while (position > offset) {
|
||||
@@ -118,9 +141,18 @@ namespace hex::prv {
|
||||
position -= readSize;
|
||||
|
||||
this->readRaw(position, buffer.data(), readSize);
|
||||
this->writeRaw(position, zeroBuffer.data(), newSize - oldSize);
|
||||
this->writeRaw(position + size, buffer.data(), readSize);
|
||||
}
|
||||
|
||||
constexpr static std::array<u8, 0x1000> ZeroBuffer = {};
|
||||
auto zeroPosition = offset;
|
||||
auto remainingZeros = size;
|
||||
while (remainingZeros > 0) {
|
||||
const auto writeSize = std::min<size_t>(remainingZeros, ZeroBuffer.size());
|
||||
this->writeRaw(zeroPosition, ZeroBuffer.data(), writeSize);
|
||||
zeroPosition += writeSize;
|
||||
remainingZeros -= writeSize;
|
||||
}
|
||||
}
|
||||
|
||||
void Provider::removeRaw(u64 offset, u64 size) {
|
||||
@@ -265,19 +297,19 @@ namespace hex::prv {
|
||||
u64 absoluteAddress = address - this->getBaseAddress();
|
||||
|
||||
if (absoluteAddress < this->getActualSize())
|
||||
return { Region { this->getBaseAddress() + absoluteAddress, this->getActualSize() - absoluteAddress }, true };
|
||||
return { Region { .address=this->getBaseAddress() + absoluteAddress, .size=this->getActualSize() - absoluteAddress }, true };
|
||||
|
||||
|
||||
bool insideValidRegion = false;
|
||||
|
||||
std::optional<u64> nextRegionAddress;
|
||||
for (const auto &overlay : m_overlays) {
|
||||
Region overlayRegion = { overlay->getAddress(), overlay->getSize() };
|
||||
Region overlayRegion = { .address=overlay->getAddress(), .size=overlay->getSize() };
|
||||
if (!nextRegionAddress.has_value() || overlay->getAddress() < nextRegionAddress) {
|
||||
nextRegionAddress = overlayRegion.getStartAddress();
|
||||
}
|
||||
|
||||
if (Region { address, 1 }.overlaps(overlayRegion)) {
|
||||
if (Region { .address=address, .size=1 }.overlaps(overlayRegion)) {
|
||||
insideValidRegion = true;
|
||||
}
|
||||
}
|
||||
@@ -285,7 +317,7 @@ namespace hex::prv {
|
||||
if (!nextRegionAddress.has_value())
|
||||
return { Region::Invalid(), false };
|
||||
else
|
||||
return { Region { address, *nextRegionAddress - address }, insideValidRegion };
|
||||
return { Region { .address=address, .size=*nextRegionAddress - address }, insideValidRegion };
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -12,8 +12,7 @@ namespace hex::prv::undo {
|
||||
|
||||
namespace {
|
||||
|
||||
std::atomic<bool> s_locked;
|
||||
std::mutex s_mutex;
|
||||
std::recursive_mutex s_mutex;
|
||||
|
||||
}
|
||||
|
||||
@@ -21,12 +20,13 @@ namespace hex::prv::undo {
|
||||
|
||||
}
|
||||
|
||||
std::recursive_mutex& Stack::getMutex() {
|
||||
return s_mutex;
|
||||
}
|
||||
|
||||
|
||||
void Stack::undo(u32 count) {
|
||||
std::scoped_lock lock(s_mutex);
|
||||
|
||||
s_locked = true;
|
||||
ON_SCOPE_EXIT { s_locked = false; };
|
||||
std::lock_guard lock(s_mutex);
|
||||
|
||||
// If there are no operations, we can't undo anything.
|
||||
if (m_undoStack.empty())
|
||||
@@ -42,14 +42,12 @@ namespace hex::prv::undo {
|
||||
m_redoStack.emplace_back(std::move(m_undoStack.back()));
|
||||
m_redoStack.back()->undo(m_provider);
|
||||
m_undoStack.pop_back();
|
||||
EventDataChanged::post(m_provider);
|
||||
}
|
||||
}
|
||||
|
||||
void Stack::redo(u32 count) {
|
||||
std::scoped_lock lock(s_mutex);
|
||||
|
||||
s_locked = true;
|
||||
ON_SCOPE_EXIT { s_locked = false; };
|
||||
std::lock_guard lock(s_mutex);
|
||||
|
||||
// If there are no operations, we can't redo anything.
|
||||
if (m_redoStack.empty())
|
||||
@@ -65,10 +63,13 @@ namespace hex::prv::undo {
|
||||
m_undoStack.emplace_back(std::move(m_redoStack.back()));
|
||||
m_undoStack.back()->redo(m_provider);
|
||||
m_redoStack.pop_back();
|
||||
EventDataChanged::post(m_provider);
|
||||
}
|
||||
}
|
||||
|
||||
void Stack::groupOperations(u32 count, const UnlocalizedString &unlocalizedName) {
|
||||
std::lock_guard lock(s_mutex);
|
||||
|
||||
if (count <= 1)
|
||||
return;
|
||||
|
||||
@@ -94,14 +95,19 @@ namespace hex::prv::undo {
|
||||
}
|
||||
|
||||
void Stack::apply(const Stack &otherStack) {
|
||||
std::lock_guard lock(s_mutex);
|
||||
|
||||
for (const auto &operation : otherStack.m_undoStack) {
|
||||
this->add(operation->clone());
|
||||
}
|
||||
}
|
||||
|
||||
void Stack::reapply() {
|
||||
std::lock_guard lock(s_mutex);
|
||||
|
||||
for (const auto &operation : m_undoStack) {
|
||||
operation->redo(m_provider);
|
||||
EventDataChanged::post(m_provider);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,14 +115,7 @@ namespace hex::prv::undo {
|
||||
|
||||
|
||||
bool Stack::add(std::unique_ptr<Operation> &&operation) {
|
||||
// If we're already inside of an undo/redo operation, ignore new operations being added
|
||||
if (s_locked)
|
||||
return false;
|
||||
|
||||
s_locked = true;
|
||||
ON_SCOPE_EXIT { s_locked = false; };
|
||||
|
||||
std::scoped_lock lock(s_mutex);
|
||||
std::lock_guard lock(s_mutex);
|
||||
|
||||
// Clear the redo stack
|
||||
m_redoStack.clear();
|
||||
@@ -133,10 +132,14 @@ namespace hex::prv::undo {
|
||||
}
|
||||
|
||||
bool Stack::canUndo() const {
|
||||
std::lock_guard lock(s_mutex);
|
||||
|
||||
return !m_undoStack.empty();
|
||||
}
|
||||
|
||||
bool Stack::canRedo() const {
|
||||
std::lock_guard lock(s_mutex);
|
||||
|
||||
return !m_redoStack.empty();
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace hex::test {
|
||||
static std::map<std::string, Test> s_tests;
|
||||
int Tests::addTest(const std::string &name, Function func, bool shouldFail) noexcept {
|
||||
s_tests.insert({
|
||||
name, { func, shouldFail }
|
||||
name, { .function=func, .shouldFail=shouldFail }
|
||||
});
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <numbers>
|
||||
|
||||
#include <hex/api/imhex_api/system.hpp>
|
||||
|
||||
@@ -285,13 +286,11 @@ namespace ImGuiExt {
|
||||
}
|
||||
|
||||
void Texture::reset() {
|
||||
#if !defined(OS_WEB)
|
||||
if (glDeleteTextures == nullptr)
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (m_textureId != 0) {
|
||||
glDeleteTextures(1, reinterpret_cast<GLuint*>(&m_textureId));
|
||||
#if !defined(OS_WEB)
|
||||
if (glDeleteTextures != nullptr)
|
||||
glDeleteTextures(1, reinterpret_cast<GLuint*>(&m_textureId));
|
||||
#endif
|
||||
m_textureId = 0;
|
||||
}
|
||||
}
|
||||
@@ -1050,9 +1049,9 @@ namespace ImGuiExt {
|
||||
|
||||
if (no_progress) {
|
||||
auto time = (fmod(ImGui::GetTime() * 2, 1.8) - 0.4);
|
||||
RenderRectFilledRangeH(window->DrawList, bb, GetColorU32(ImGuiCol_PlotHistogram), ImSaturate(time), ImSaturate(time + 0.2), style.FrameRounding);
|
||||
RenderRectFilledInRangeH(window->DrawList, bb, GetColorU32(ImGuiCol_PlotHistogram), ImSaturate(time), ImSaturate(time + 0.2), style.FrameRounding);
|
||||
} else {
|
||||
RenderRectFilledRangeH(window->DrawList, bb, GetColorU32(ImGuiCol_PlotHistogram), 0.0F, fraction, style.FrameRounding);
|
||||
RenderRectFilledInRangeH(window->DrawList, bb, GetColorU32(ImGuiCol_PlotHistogram), 0.0F, fraction, style.FrameRounding);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1218,6 +1217,21 @@ namespace ImGuiExt {
|
||||
return res;
|
||||
}
|
||||
|
||||
bool DimmedArrowButton(const char *id, ImGuiDir dir, ImVec2 size) {
|
||||
PushStyleColor(ImGuiCol_ButtonHovered, GetCustomColorU32(ImGuiCustomCol_DescButtonHovered));
|
||||
PushStyleColor(ImGuiCol_Button, GetCustomColorU32(ImGuiCustomCol_DescButton));
|
||||
PushStyleColor(ImGuiCol_Text, GetColorU32(ImGuiCol_ButtonActive));
|
||||
PushStyleColor(ImGuiCol_ButtonActive, GetCustomColorU32(ImGuiCustomCol_DescButtonActive));
|
||||
PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.5 * hex::ImHexApi::System::getGlobalScale());
|
||||
|
||||
bool res = ArrowButtonEx(id, dir, size);
|
||||
|
||||
PopStyleColor(4);
|
||||
PopStyleVar(1);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool DimmedButtonToggle(const char *icon, bool *v, ImVec2 size, ImVec2 iconOffset) {
|
||||
bool pushed = false;
|
||||
bool toggled = false;
|
||||
@@ -1355,9 +1369,9 @@ namespace ImGuiExt {
|
||||
bool VSliderAngle(const char* label, const ImVec2& size, float* v_rad, float v_degrees_min, float v_degrees_max, const char* format, ImGuiSliderFlags flags) {
|
||||
if (format == nullptr)
|
||||
format = "%.0f deg";
|
||||
float v_deg = (*v_rad) * 360.0F / (2 * IM_PI);
|
||||
float v_deg = (*v_rad) * 360.0F / (2 * std::numbers::pi_v<float>);
|
||||
bool value_changed = ImGui::VSliderFloat(label, size, &v_deg, v_degrees_min, v_degrees_max, format, flags);
|
||||
*v_rad = v_deg * (2 * IM_PI) / 360.0F;
|
||||
*v_rad = v_deg * (2 * std::numbers::pi_v<float>) / 360.0F;
|
||||
return value_changed;
|
||||
}
|
||||
|
||||
@@ -1501,9 +1515,9 @@ namespace ImGuiExt {
|
||||
|
||||
bool IsDarkBackground(const ImColor& bgColor) {
|
||||
// Extract RGB components in 0–255 range
|
||||
int r = static_cast<int>(bgColor.Value.x * 255.0f);
|
||||
int g = static_cast<int>(bgColor.Value.y * 255.0f);
|
||||
int b = static_cast<int>(bgColor.Value.z * 255.0f);
|
||||
int r = static_cast<int>(bgColor.Value.x * 255.0F);
|
||||
int g = static_cast<int>(bgColor.Value.y * 255.0F);
|
||||
int b = static_cast<int>(bgColor.Value.z * 255.0F);
|
||||
|
||||
// Compute brightness using perceived luminance
|
||||
int brightness = (r * 299 + g * 587 + b * 114) / 1000;
|
||||
|
||||
@@ -5,11 +5,12 @@
|
||||
#include <hex/api/task_manager.hpp>
|
||||
#include <hex/api/tutorial_manager.hpp>
|
||||
|
||||
#include <hex/providers/provider.hpp>
|
||||
#include <imgui_internal.h>
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
#include <string>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
namespace hex {
|
||||
|
||||
@@ -117,14 +118,84 @@ namespace hex {
|
||||
return s_lastFocusedView;
|
||||
}
|
||||
|
||||
void View::Window::handleFocusRestoration() {
|
||||
const auto title = fmt::format("{} {}", this->getIcon(), View::toWindowName(this->getUnlocalizedName()));
|
||||
|
||||
const ImGuiContext& g = *ImGui::GetCurrentContext();
|
||||
bool foundTopFocused = false;
|
||||
ImGuiWindow *imguiFocusedWindow = nullptr;
|
||||
ImGuiWindow *focusedSubWindow = nullptr;
|
||||
|
||||
if (g.NavWindow != nullptr) {
|
||||
imguiFocusedWindow = g.NavWindow;
|
||||
foundTopFocused = true;
|
||||
}
|
||||
for (auto focusedWindow: g.WindowsFocusOrder | std::views::reverse) {
|
||||
if (focusedWindow == nullptr || !focusedWindow->WasActive)
|
||||
continue;
|
||||
std::string focusedWindowName = focusedWindow->Name;
|
||||
if (!foundTopFocused) {
|
||||
imguiFocusedWindow = focusedWindow;
|
||||
foundTopFocused = true;
|
||||
}
|
||||
if (imguiFocusedWindow == nullptr || !focusedWindowName.contains("###hex.builtin.view."))
|
||||
continue;
|
||||
if (auto focusedChild = focusedWindow->NavLastChildNavWindow; focusedChild != nullptr)
|
||||
focusedSubWindow = focusedChild;
|
||||
else if (focusedWindow == focusedWindow->RootWindow)
|
||||
focusedSubWindow = focusedWindow;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
std::string imguiFocusedWindowName = "NULL";
|
||||
if (imguiFocusedWindow != nullptr)
|
||||
imguiFocusedWindowName.assign(imguiFocusedWindow->Name);
|
||||
|
||||
std::string focusedSubWindowName;
|
||||
if (focusedSubWindow != nullptr || m_focusedSubWindow != nullptr) {
|
||||
if (glfwGetWindowAttrib(ImHexApi::System::getMainWindowHandle(), GLFW_FOCUSED)) {
|
||||
focusedSubWindowName = focusedSubWindow != nullptr ? focusedSubWindow->Name : m_focusedSubWindow->Name;
|
||||
if (focusedSubWindow != nullptr && m_focusedSubWindow != nullptr) {
|
||||
std::string_view windowName = m_focusedSubWindow->Name;
|
||||
auto stringsVector = wolv::util::splitString(focusedSubWindowName, "/");
|
||||
if (stringsVector.back().contains("resize") || (focusedSubWindow == focusedSubWindow->RootWindow && windowName.starts_with(focusedSubWindowName)))
|
||||
focusedSubWindowName = windowName;
|
||||
else
|
||||
m_focusedSubWindow = focusedSubWindow;
|
||||
} else if (focusedSubWindow != nullptr)
|
||||
m_focusedSubWindow = focusedSubWindow;
|
||||
|
||||
bool windowAlreadyFocused = focusedSubWindowName == imguiFocusedWindowName;
|
||||
bool titleFocused = focusedSubWindowName.starts_with(title);
|
||||
|
||||
if (titleFocused && !windowAlreadyFocused) {
|
||||
|
||||
bool windowMayNeedFocus = focusedSubWindowName.starts_with(imguiFocusedWindowName);
|
||||
std::string activeName = g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL";
|
||||
|
||||
if ((activeName == "NULL" || windowMayNeedFocus) && (imguiFocusedWindowName == "##MainMenuBar" || imguiFocusedWindowName.starts_with("ImHexDockSpace") || imguiFocusedWindowName.contains("###hex.builtin.view."))) {
|
||||
if (m_focusedSubWindow == m_focusedSubWindow->RootWindow)
|
||||
ImGui::FocusWindow(m_focusedSubWindow, ImGuiFocusRequestFlags_RestoreFocusedChild);
|
||||
else
|
||||
ImGui::FocusWindow(m_focusedSubWindow, ImGuiFocusRequestFlags_None);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void View::Window::draw(ImGuiWindowFlags extraFlags) {
|
||||
if (this->shouldDraw()) {
|
||||
const auto title = fmt::format("{} {}", this->getIcon(), View::toWindowName(this->getUnlocalizedName()));
|
||||
|
||||
handleFocusRestoration();
|
||||
|
||||
if (!allowScroll())
|
||||
extraFlags |= ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse;
|
||||
|
||||
ImGui::SetNextWindowSizeConstraints(this->getMinSize(), this->getMaxSize());
|
||||
const auto title = fmt::format("{} {}", this->getIcon(), View::toWindowName(this->getUnlocalizedName()));
|
||||
if (ImGui::Begin(title.c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse | extraFlags | this->getWindowFlags())) {
|
||||
TutorialManager::setLastItemInteractiveHelpPopup([this]{ this->drawHelpText(); });
|
||||
this->drawContent();
|
||||
@@ -177,4 +248,4 @@ namespace hex {
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
4
lib/third_party/imgui/backend/CMakeLists.txt
vendored
4
lib/third_party/imgui/backend/CMakeLists.txt
vendored
@@ -25,6 +25,10 @@ if (NOT IMHEX_EXTERNAL_PLUGIN_BUILD)
|
||||
target_link_libraries(imgui_backend PUBLIC ${X11_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if (EMSCRIPTEN)
|
||||
target_compile_options(imgui_backend PRIVATE --use-port=contrib.glfw3)
|
||||
endif()
|
||||
|
||||
find_package(GLFW QUIET)
|
||||
if (NOT GLFW_FOUND OR "${GLFW_LIBRARIES}" STREQUAL "")
|
||||
find_package(glfw3 QUIET)
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
// dear imgui: Platform Backend for GLFW
|
||||
// This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan, WebGPU..)
|
||||
// (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
|
||||
// (Requires: GLFW 3.1+. Prefer GLFW 3.3+ for full feature support.)
|
||||
// (Requires: GLFW 3.0+. Prefer GLFW 3.3+/3.4+ for full feature support.)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Platform: Clipboard support.
|
||||
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only).
|
||||
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values are obsolete since 1.87 and not supported since 1.91.5]
|
||||
// [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
|
||||
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Resizing cursors requires GLFW 3.4+! Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors) with GLFW 3.1+. Resizing cursors requires GLFW 3.4+! Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||
// [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
|
||||
// [X] Multiple Dear ImGui contexts support.
|
||||
// Missing features or Issues:
|
||||
// [ ] Touch events are only correctly identified as Touch on Windows. This create issues with some interactions. GLFW doesn't provide a way to identify touch inputs from mouse inputs, we cannot call io.AddMouseSourceEvent() to identify the source. We provide a Windows-specific workaround.
|
||||
// [ ] Missing ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress cursors.
|
||||
// [ ] Multi-viewport: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor).
|
||||
// [ ] Platform: Touch events are only correctly identified as Touch on Windows. This create issues with some interactions. GLFW doesn't provide a way to identify touch inputs from mouse inputs, we cannot call io.AddMouseSourceEvent() to identify the source. We provide a Windows-specific workaround.
|
||||
// [ ] Platform: Missing ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress cursors.
|
||||
// [ ] Platform: Multi-viewport: Missing ImGuiBackendFlags_HasParentViewport support. The viewport->ParentViewportID field is ignored, and therefore io.ConfigViewportsNoDefaultParent has no effect either.
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
@@ -50,7 +50,7 @@ IMGUI_IMPL_API void ImGui_ImplGlfw_InstallEmscriptenCallbacks(GLFWwindow* wi
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_InstallCallbacks(GLFWwindow* window);
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_RestoreCallbacks(GLFWwindow* window);
|
||||
|
||||
// GFLW callbacks options:
|
||||
// GLFW callbacks options:
|
||||
// - Set 'chain_for_all_windows=true' to enable chaining callbacks for all windows (including secondary viewports created by backends or by user)
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_SetCallbacksChainForAllWindows(bool chain_for_all_windows);
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ IMGUI_IMPL_API void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data);
|
||||
IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateDeviceObjects();
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyDeviceObjects();
|
||||
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually.
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL3_UpdateTexture(ImTextureData* tex);
|
||||
|
||||
// Configuration flags to add in your imconfig file:
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
// dear imgui: Platform Backend for GLFW
|
||||
// This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan, WebGPU..)
|
||||
// (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
|
||||
// (Requires: GLFW 3.1+. Prefer GLFW 3.3+ or GLFW 3.4+ for full feature support.)
|
||||
// (Requires: GLFW 3.0+. Prefer GLFW 3.3+/3.4+ for full feature support.)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Platform: Clipboard support.
|
||||
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only).
|
||||
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values are obsolete since 1.87 and not supported since 1.91.5]
|
||||
// [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
|
||||
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Resizing cursors requires GLFW 3.4+! Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors) with GLFW 3.1+. Resizing cursors requires GLFW 3.4+! Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||
// [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
|
||||
// [X] Multiple Dear ImGui contexts support.
|
||||
// Missing features or Issues:
|
||||
// [ ] Touch events are only correctly identified as Touch on Windows. This create issues with some interactions. GLFW doesn't provide a way to identify touch inputs from mouse inputs, we cannot call io.AddMouseSourceEvent() to identify the source. We provide a Windows-specific workaround.
|
||||
// [ ] Missing ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress cursors.
|
||||
// [ ] Multi-viewport: ParentViewportID not honored, and so io.ConfigViewportsNoDefaultParent has no effect (minor).
|
||||
// [ ] Platform: Touch events are only correctly identified as Touch on Windows. This create issues with some interactions. GLFW doesn't provide a way to identify touch inputs from mouse inputs, we cannot call io.AddMouseSourceEvent() to identify the source. We provide a Windows-specific workaround.
|
||||
// [ ] Platform: Missing ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress cursors.
|
||||
// [ ] Platform: Multi-viewport: Missing ImGuiBackendFlags_HasParentViewport support. The viewport->ParentViewportID field is ignored, and therefore io.ConfigViewportsNoDefaultParent has no effect either.
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
@@ -31,7 +31,14 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2025-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
||||
// 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
||||
// 2026-02-10: Try to set IMGUI_IMPL_GLFW_DISABLE_X11 / IMGUI_IMPL_GLFW_DISABLE_WAYLAND automatically if corresponding headers are not accessible. (#9225)
|
||||
// 2026-01-25: [Docking] Improve workarounds for cases where GLFW is unable to provide any reliable monitor info. Preserve existing monitor list when none of the new one is valid. (#9195, #7902, #5683)
|
||||
// 2026-01-18: [Docking] Dynamically load X11 functions to avoid -lx11 linking requirement introduced on 2025-09-10.
|
||||
// 2025-12-12: Added IMGUI_IMPL_GLFW_DISABLE_X11 / IMGUI_IMPL_GLFW_DISABLE_WAYLAND to forcefully disable either.
|
||||
// 2025-12-10: Avoid repeated glfwSetCursor()/glfwSetInputMode() calls when unnecessary. Lowers overhead for very high framerates (e.g. 10k+ FPS).
|
||||
// 2025-11-06: Lower minimum requirement to GLFW 3.0. Though a recent version e.g GLFW 3.4 is highly recommended.
|
||||
// 2025-09-18: Call platform_io.ClearPlatformHandlers() on shutdown.
|
||||
// 2025-09-15: Content Scales are always reported as 1.0 on Wayland. FramebufferScale are always reported as 1.0 on X11. (#8920, #8921)
|
||||
// 2025-09-10: [Docking] Improve multi-viewport behavior in tiling WMs on X11 via the ImGui_ImplGlfw_SetWindowFloating() function. Note: using GLFW backend on Linux/BSD etc. requires linking with -lX11. (#8884, #8474, #8289)
|
||||
// 2025-07-08: Made ImGui_ImplGlfw_GetContentScaleForWindow(), ImGui_ImplGlfw_GetContentScaleForMonitor() helpers return 1.0f on Emscripten and Android platforms, matching macOS logic. (#8742, #8733)
|
||||
@@ -108,13 +115,34 @@
|
||||
// Clang warnings with -Weverything
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast
|
||||
#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness
|
||||
#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast
|
||||
#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness
|
||||
#pragma clang diagnostic ignored "-Wexit-time-destructors" // warning: declaration requires an exit-time destructor // exit-time destruction order is undefined. if MemFree() leads to users code that has been disabled before exit it might cause problems. ImGui coding style welcomes static/globals.
|
||||
#pragma clang diagnostic ignored "-Wglobal-constructors" // warning: declaration requires a global destructor // similar to above, not sure what the exact difference is.
|
||||
#elif defined(__GNUC__)
|
||||
#pragma GCC diagnostic ignored "-Wfloat-equal" // warning: comparing floating-point with '==' or '!=' is unsafe
|
||||
#pragma GCC diagnostic ignored "-Wfloat-equal" // warning: comparing floating-point with '==' or '!=' is unsafe
|
||||
#endif
|
||||
|
||||
#if defined(__has_include)
|
||||
#if !__has_include(<X11/Xlib.h>) || !__has_include(<X11/extensions/Xrandr.h>)
|
||||
#define IMGUI_IMPL_GLFW_DISABLE_X11
|
||||
#endif
|
||||
#if !__has_include(<wayland-client.h>)
|
||||
#define IMGUI_IMPL_GLFW_DISABLE_WAYLAND
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// GLFW
|
||||
#if !defined(IMGUI_IMPL_GLFW_DISABLE_X11) && (defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__))
|
||||
#define GLFW_HAS_X11 1
|
||||
#else
|
||||
#define GLFW_HAS_X11 0
|
||||
#endif
|
||||
#if !defined(IMGUI_IMPL_GLFW_DISABLE_WAYLAND) && (defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__))
|
||||
#define GLFW_HAS_WAYLAND 1
|
||||
#else
|
||||
#define GLFW_HAS_WAYLAND 0
|
||||
#endif
|
||||
#include <GLFW/glfw3.h>
|
||||
#ifdef _WIN32
|
||||
#undef APIENTRY
|
||||
@@ -122,20 +150,19 @@
|
||||
#define GLFW_EXPOSE_NATIVE_WIN32
|
||||
#endif
|
||||
#include <GLFW/glfw3native.h>
|
||||
#elif defined(__APPLE__)
|
||||
#ifndef GLFW_EXPOSE_NATIVE_COCOA // for glfwGetCocoaWindow()
|
||||
#define GLFW_EXPOSE_NATIVE_COCOA
|
||||
#endif
|
||||
// IMHEX PATCH BEGIN
|
||||
// REASON: including this file means either including either ObjC (not supported by gcc)
|
||||
// or code with a non-standard C++ extension (Blocks)
|
||||
// Furthermore, we can't compile this file/ImGui with clang++ because the C++ ABI is not the same with clang and gcc
|
||||
//#ifdef __APPLE__
|
||||
//#define GLFW_EXPOSE_NATIVE_COCOA
|
||||
//#include <GLFW/glfw3native.h> // for glfwGetCocoaWindow()
|
||||
// #endif
|
||||
// IMHEX PATCH END
|
||||
|
||||
#if !defined(__EMSCRIPTEN__)
|
||||
#include <GLFW/glfw3native.h>
|
||||
#undef Status // X11 headers are leaking this.
|
||||
#include <GLFW/glfw3native.h>
|
||||
#elif GLFW_HAS_X11
|
||||
#ifndef GLFW_EXPOSE_NATIVE_X11 // for glfwGetX11Display(), glfwGetX11Window() on Freedesktop (Linux, BSD, etc.)
|
||||
#define GLFW_EXPOSE_NATIVE_X11
|
||||
#include <X11/Xatom.h>
|
||||
#include <dlfcn.h> // for dlopen()
|
||||
#endif
|
||||
#include <GLFW/glfw3native.h>
|
||||
#undef Status // X11 headers are leaking this.
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
@@ -166,6 +193,7 @@ static std::string clipboardContent;
|
||||
|
||||
// We gather version tests as define in order to easily see which features are version-dependent.
|
||||
#define GLFW_VERSION_COMBINED (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 + GLFW_VERSION_REVISION)
|
||||
#define GLFW_HAS_CREATECURSOR (GLFW_VERSION_COMBINED >= 3100) // 3.1+ glfwCreateCursor()
|
||||
#define GLFW_HAS_WINDOW_TOPMOST (GLFW_VERSION_COMBINED >= 3200) // 3.2+ GLFW_FLOATING
|
||||
#define GLFW_HAS_WINDOW_HOVERED (GLFW_VERSION_COMBINED >= 3300) // 3.3+ GLFW_HOVERED
|
||||
#define GLFW_HAS_WINDOW_ALPHA (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwSetWindowOpacity
|
||||
@@ -193,11 +221,6 @@ static std::string clipboardContent;
|
||||
#define GLFW_HAS_GETKEYNAME (GLFW_VERSION_COMBINED >= 3200) // 3.2+ glfwGetKeyName()
|
||||
#define GLFW_HAS_GETERROR (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwGetError()
|
||||
#define GLFW_HAS_GETPLATFORM (GLFW_VERSION_COMBINED >= 3400) // 3.4+ glfwGetPlatform()
|
||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
|
||||
#define GLFW_HAS_X11_OR_WAYLAND 1
|
||||
#else
|
||||
#define GLFW_HAS_X11_OR_WAYLAND 0
|
||||
#endif
|
||||
|
||||
// Map GLFWWindow* to ImGuiContext*.
|
||||
// - Would be simpler if we could use glfwSetWindowUserPointer()/glfwGetWindowUserPointer(), but this is a single and shared resource.
|
||||
@@ -206,7 +229,7 @@ static std::string clipboardContent;
|
||||
struct ImGui_ImplGlfw_WindowToContext { GLFWwindow* Window; ImGuiContext* Context; };
|
||||
static ImVector<ImGui_ImplGlfw_WindowToContext> g_ContextMap;
|
||||
static void ImGui_ImplGlfw_ContextMap_Add(GLFWwindow* window, ImGuiContext* ctx) { g_ContextMap.push_back(ImGui_ImplGlfw_WindowToContext{ window, ctx }); }
|
||||
static void ImGui_ImplGlfw_ContextMap_Remove(GLFWwindow* window) { for (ImGui_ImplGlfw_WindowToContext& entry : g_ContextMap) if (entry.Window == window) { g_ContextMap.erase_unsorted(&entry); return; } }
|
||||
static void ImGui_ImplGlfw_ContextMap_Remove(GLFWwindow* window) { for (ImGui_ImplGlfw_WindowToContext& entry : g_ContextMap) if (entry.Window == window) { g_ContextMap.erase_unsorted(&entry); if (g_ContextMap.empty()) g_ContextMap.clear(); return; } }
|
||||
static ImGuiContext* ImGui_ImplGlfw_ContextMap_Get(GLFWwindow* window) { for (ImGui_ImplGlfw_WindowToContext& entry : g_ContextMap) if (entry.Window == window) return entry.Context; return nullptr; }
|
||||
|
||||
enum GlfwClientApi
|
||||
@@ -216,6 +239,13 @@ enum GlfwClientApi
|
||||
GlfwClientApi_Unknown, // Anything else fits here.
|
||||
};
|
||||
|
||||
#if GLFW_HAS_X11
|
||||
typedef Atom (*PFN_XInternAtom)(Display*, const char* ,Bool);
|
||||
typedef int (*PFN_XChangeProperty)(Display*, Window, Atom, Atom, int, int, const unsigned char*, int);
|
||||
typedef int (*PFN_XChangeWindowAttributes)(Display*, Window, unsigned long, XSetWindowAttributes*);
|
||||
typedef int (*PFN_XFlush)(Display*);
|
||||
#endif
|
||||
|
||||
// GLFW data
|
||||
struct ImGui_ImplGlfw_Data
|
||||
{
|
||||
@@ -224,7 +254,10 @@ struct ImGui_ImplGlfw_Data
|
||||
GlfwClientApi ClientApi;
|
||||
double Time;
|
||||
GLFWwindow* MouseWindow;
|
||||
#if GLFW_HAS_CREATECURSOR
|
||||
GLFWcursor* MouseCursors[ImGuiMouseCursor_COUNT];
|
||||
GLFWcursor* LastMouseCursor;
|
||||
#endif
|
||||
bool MouseIgnoreButtonUpWaitForFocusLoss;
|
||||
bool MouseIgnoreButtonUp;
|
||||
ImVec2 LastValidMousePos;
|
||||
@@ -250,6 +283,15 @@ struct ImGui_ImplGlfw_Data
|
||||
WNDPROC PrevWndProc;
|
||||
#endif
|
||||
|
||||
#if GLFW_HAS_X11
|
||||
// Module and function pointers loaded at initialization to avoid linking statically with X11.
|
||||
void* X11Module;
|
||||
PFN_XInternAtom XInternAtom;
|
||||
PFN_XChangeProperty XChangeProperty;
|
||||
PFN_XChangeWindowAttributes XChangeWindowAttributes;
|
||||
PFN_XFlush XFlush;
|
||||
#endif
|
||||
|
||||
ImGui_ImplGlfw_Data() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
@@ -279,47 +321,24 @@ static void ImGui_ImplGlfw_InitMultiViewportSupport();
|
||||
static void ImGui_ImplGlfw_ShutdownMultiViewportSupport();
|
||||
|
||||
// Functions
|
||||
|
||||
static bool ImGui_ImplGlfw_IsWayland()
|
||||
{
|
||||
#if !GLFW_HAS_X11_OR_WAYLAND
|
||||
#if !GLFW_HAS_WAYLAND
|
||||
return false;
|
||||
#elif GLFW_HAS_GETPLATFORM
|
||||
return glfwGetPlatform() == GLFW_PLATFORM_WAYLAND;
|
||||
#else
|
||||
const char* version = glfwGetVersionString();
|
||||
if (strstr(version, "Wayland") == NULL) // e.g. Ubuntu 22.04 ships with GLFW 3.3.6 compiled without Wayland
|
||||
if (strstr(version, "Wayland") == nullptr) // e.g. Ubuntu 22.04 ships with GLFW 3.3.6 compiled without Wayland
|
||||
return false;
|
||||
#ifdef GLFW_EXPOSE_NATIVE_X11
|
||||
if (glfwGetX11Display() != NULL)
|
||||
if (glfwGetX11Display() != nullptr)
|
||||
return false;
|
||||
#endif
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
static const char* ImGui_ImplGlfw_GetClipboardText(void* user_data)
|
||||
{
|
||||
// IMHEX PATCH BEGIN
|
||||
#ifdef __EMSCRIPTEN__
|
||||
return clipboardContent.c_str();
|
||||
#else
|
||||
return glfwGetClipboardString((GLFWwindow*)user_data);
|
||||
#endif
|
||||
// IMHEX PATCH END
|
||||
}
|
||||
|
||||
static void ImGui_ImplGlfw_SetClipboardText(void* user_data, const char* text)
|
||||
{
|
||||
glfwSetClipboardString((GLFWwindow*)user_data, text);
|
||||
// IMHEX PATCH BEGIN
|
||||
#ifdef __EMSCRIPTEN__
|
||||
clipboardContent = text;
|
||||
emscripten_browser_clipboard::copy(clipboardContent);
|
||||
#endif
|
||||
// IMHEX PATCH END
|
||||
}
|
||||
|
||||
// Not static to allow third-party code to use that if they want to (but undocumented)
|
||||
ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int keycode, int scancode);
|
||||
ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int keycode, int scancode)
|
||||
@@ -465,10 +484,10 @@ static void ImGui_ImplGlfw_UpdateKeyModifiers(ImGuiIO& io, GLFWwindow* window, i
|
||||
}();
|
||||
|
||||
if (isX11) {
|
||||
io.AddKeyEvent(ImGuiMod_Ctrl, (glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS) || (glfwGetKey(window, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS));
|
||||
io.AddKeyEvent(ImGuiMod_Shift, (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) || (glfwGetKey(window, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS));
|
||||
io.AddKeyEvent(ImGuiMod_Alt, (glfwGetKey(window, GLFW_KEY_LEFT_ALT) == GLFW_PRESS) || (glfwGetKey(window, GLFW_KEY_RIGHT_ALT) == GLFW_PRESS));
|
||||
io.AddKeyEvent(ImGuiMod_Super, (glfwGetKey(window, GLFW_KEY_LEFT_SUPER) == GLFW_PRESS) || (glfwGetKey(window, GLFW_KEY_RIGHT_SUPER) == GLFW_PRESS));
|
||||
io.AddKeyEvent(ImGuiMod_Ctrl, (glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS) || (glfwGetKey(window, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS));
|
||||
io.AddKeyEvent(ImGuiMod_Shift, (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) || (glfwGetKey(window, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS));
|
||||
io.AddKeyEvent(ImGuiMod_Alt, (glfwGetKey(window, GLFW_KEY_LEFT_ALT) == GLFW_PRESS) || (glfwGetKey(window, GLFW_KEY_RIGHT_ALT) == GLFW_PRESS));
|
||||
io.AddKeyEvent(ImGuiMod_Super, (glfwGetKey(window, GLFW_KEY_LEFT_SUPER) == GLFW_PRESS) || (glfwGetKey(window, GLFW_KEY_RIGHT_SUPER) == GLFW_PRESS));
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
@@ -496,7 +515,9 @@ void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int acti
|
||||
return;
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO(bd->Context);
|
||||
// IMHEX PATCH BEGIN
|
||||
ImGui_ImplGlfw_UpdateKeyModifiers(io, window, mods);
|
||||
// IMHEX PATCH END
|
||||
if (button >= 0 && button < ImGuiMouseButton_COUNT)
|
||||
io.AddMouseButtonEvent(button, action == GLFW_PRESS);
|
||||
}
|
||||
@@ -537,7 +558,7 @@ static int ImGui_ImplGlfw_TranslateUntranslatedKey(int key, int scancode)
|
||||
{
|
||||
const char char_names[] = "`-=[]\\,;\'./";
|
||||
const int char_keys[] = { GLFW_KEY_GRAVE_ACCENT, GLFW_KEY_MINUS, GLFW_KEY_EQUAL, GLFW_KEY_LEFT_BRACKET, GLFW_KEY_RIGHT_BRACKET, GLFW_KEY_BACKSLASH, GLFW_KEY_COMMA, GLFW_KEY_SEMICOLON, GLFW_KEY_APOSTROPHE, GLFW_KEY_PERIOD, GLFW_KEY_SLASH, 0 };
|
||||
IM_ASSERT(IM_ARRAYSIZE(char_names) == IM_ARRAYSIZE(char_keys));
|
||||
IM_ASSERT(IM_COUNTOF(char_names) == IM_COUNTOF(char_keys));
|
||||
if (key_name[0] >= '0' && key_name[0] <= '9') { key = GLFW_KEY_0 + (key_name[0] - '0'); }
|
||||
else if (key_name[0] >= 'A' && key_name[0] <= 'Z') { key = GLFW_KEY_A + (key_name[0] - 'A'); }
|
||||
else if (key_name[0] >= 'a' && key_name[0] <= 'z') { key = GLFW_KEY_A + (key_name[0] - 'a'); }
|
||||
@@ -560,9 +581,11 @@ void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int keycode, int scancode, i
|
||||
return;
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO(bd->Context);
|
||||
// IMHEX PATCH BEGIN
|
||||
ImGui_ImplGlfw_UpdateKeyModifiers(io, window, mods);
|
||||
// IMHEX PATCH END
|
||||
|
||||
if (keycode >= 0 && keycode < IM_ARRAYSIZE(bd->KeyOwnerWindows))
|
||||
if (keycode >= 0 && keycode < IM_COUNTOF(bd->KeyOwnerWindows))
|
||||
bd->KeyOwnerWindows[keycode] = (action == GLFW_PRESS) ? window : nullptr;
|
||||
|
||||
keycode = ImGui_ImplGlfw_TranslateUntranslatedKey(keycode, scancode);
|
||||
@@ -736,7 +759,9 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
|
||||
snprintf(bd->BackendPlatformName, sizeof(bd->BackendPlatformName), "imgui_impl_glfw (%d)", GLFW_VERSION_COMBINED);
|
||||
io.BackendPlatformUserData = (void*)bd;
|
||||
io.BackendPlatformName = bd->BackendPlatformName;
|
||||
#if GLFW_HAS_CREATECURSOR
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
||||
#endif
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
|
||||
|
||||
bool has_viewports = false;
|
||||
@@ -785,6 +810,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
|
||||
// (By design, on X11 cursors are user configurable and some cursors may be missing. When a cursor doesn't exist,
|
||||
// GLFW will emit an error which will often be printed by the app, so we temporarily disable error reporting.
|
||||
// Missing cursors will return nullptr and our _UpdateMouseCursor() function will use the Arrow cursor instead.)
|
||||
#if GLFW_HAS_CREATECURSOR
|
||||
GLFWerrorfun prev_error_callback = glfwSetErrorCallback(nullptr);
|
||||
bd->MouseCursors[ImGuiMouseCursor_Arrow] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
|
||||
bd->MouseCursors[ImGuiMouseCursor_TextInput] = glfwCreateStandardCursor(GLFW_IBEAM_CURSOR);
|
||||
@@ -803,6 +829,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
|
||||
bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
|
||||
#endif
|
||||
glfwSetErrorCallback(prev_error_callback);
|
||||
#endif
|
||||
#if GLFW_HAS_GETERROR && !defined(__EMSCRIPTEN__) // Eat errors (see #5908)
|
||||
(void)glfwGetError(nullptr);
|
||||
#endif
|
||||
@@ -821,11 +848,8 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
|
||||
main_viewport->PlatformHandle = (void*)bd->Window;
|
||||
#ifdef _WIN32
|
||||
main_viewport->PlatformHandleRaw = glfwGetWin32Window(bd->Window);
|
||||
// IMHEX PATCH BEGIN
|
||||
// REASON: The patch with #include <GLFW/glfw3native.h>
|
||||
// #elif defined(__APPLE__)
|
||||
// main_viewport->PlatformHandleRaw = (void*)glfwGetCocoaWindow(bd->Window);
|
||||
// IMHEX PATCH END
|
||||
#elif defined(__APPLE__)
|
||||
main_viewport->PlatformHandleRaw = (void*)glfwGetCocoaWindow(bd->Window);
|
||||
#else
|
||||
IM_UNUSED(main_viewport);
|
||||
#endif
|
||||
@@ -841,6 +865,26 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
|
||||
::SetWindowLongPtrW((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC, (LONG_PTR)ImGui_ImplGlfw_WndProc);
|
||||
#endif
|
||||
|
||||
#if GLFW_HAS_X11
|
||||
if (!bd->IsWayland)
|
||||
{
|
||||
// Load X11 module dynamically. Copied from the way that GLFW does it in x11_init.c
|
||||
#if defined(__CYGWIN__)
|
||||
const char* x11_module_path = "libX11-6.so";
|
||||
#elif defined(__OpenBSD__) || defined(__NetBSD__)
|
||||
const char* x11_module_path = "libX11.so";
|
||||
#else
|
||||
const char* x11_module_path = "libX11.so.6";
|
||||
#endif
|
||||
bd->X11Module = dlopen(x11_module_path, RTLD_LAZY | RTLD_LOCAL);
|
||||
bd->XInternAtom = (PFN_XInternAtom)dlsym(bd->X11Module, "XInternAtom");
|
||||
bd->XChangeProperty = (PFN_XChangeProperty)dlsym(bd->X11Module, "XChangeProperty");
|
||||
bd->XChangeWindowAttributes = (PFN_XChangeWindowAttributes)dlsym(bd->X11Module, "XChangeWindowAttributes");
|
||||
bd->XFlush = (PFN_XFlush)dlsym(bd->X11Module, "XFlush");
|
||||
IM_ASSERT(bd->XInternAtom != nullptr && bd->XChangeProperty != nullptr && bd->XChangeWindowAttributes != nullptr && bd->XFlush != nullptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Emscripten: the same application can run on various platforms, so we detect the Apple platform at runtime
|
||||
// to override io.ConfigMacOSXBehaviors from its default (which is always false in Emscripten).
|
||||
#ifdef __EMSCRIPTEN__
|
||||
@@ -881,20 +925,21 @@ void ImGui_ImplGlfw_Shutdown()
|
||||
{
|
||||
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?");
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
|
||||
ImGui_ImplGlfw_ShutdownMultiViewportSupport();
|
||||
|
||||
if (bd->InstalledCallbacks)
|
||||
ImGui_ImplGlfw_RestoreCallbacks(bd->Window);
|
||||
#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3
|
||||
if (bd->CanvasSelector)
|
||||
emscripten_set_wheel_callback(bd->CanvasSelector, nullptr, false, nullptr);
|
||||
#endif
|
||||
|
||||
#if GLFW_HAS_CREATECURSOR
|
||||
for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)
|
||||
glfwDestroyCursor(bd->MouseCursors[cursor_n]);
|
||||
|
||||
#endif
|
||||
// Windows: restore our WndProc hook
|
||||
#ifdef _WIN32
|
||||
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
|
||||
@@ -903,9 +948,15 @@ void ImGui_ImplGlfw_Shutdown()
|
||||
bd->PrevWndProc = nullptr;
|
||||
#endif
|
||||
|
||||
#if GLFW_HAS_X11
|
||||
if (bd->X11Module != nullptr)
|
||||
dlclose(bd->X11Module);
|
||||
#endif
|
||||
|
||||
io.BackendPlatformName = nullptr;
|
||||
io.BackendPlatformUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_HasSetMousePos | ImGuiBackendFlags_HasGamepad | ImGuiBackendFlags_PlatformHasViewports | ImGuiBackendFlags_HasMouseHoveredViewport);
|
||||
platform_io.ClearPlatformHandlers();
|
||||
ImGui_ImplGlfw_ContextMap_Remove(bd->Window);
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
@@ -995,20 +1046,28 @@ static void ImGui_ImplGlfw_UpdateMouseCursor()
|
||||
GLFWwindow* window = (GLFWwindow*)platform_io.Viewports[n]->PlatformHandle;
|
||||
if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor)
|
||||
{
|
||||
// Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
|
||||
if (bd->LastMouseCursor != nullptr)
|
||||
{
|
||||
// Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
|
||||
bd->LastMouseCursor = nullptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Show OS mouse cursor
|
||||
// FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here.
|
||||
// IMHEX PATCH BEGIN
|
||||
#if !defined(_WIN32)
|
||||
glfwSetCursor(window, bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow]);
|
||||
#endif
|
||||
|
||||
// IMHEX PATCH BEGIN
|
||||
#if GLFW_HAS_CREATECURSOR && !defined(_WIN32)
|
||||
// IMHEX PATCH END
|
||||
GLFWcursor* cursor = bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow];
|
||||
if (bd->LastMouseCursor != cursor)
|
||||
{
|
||||
glfwSetCursor(window, cursor);
|
||||
bd->LastMouseCursor = cursor;
|
||||
}
|
||||
#endif
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||
// IMHEX PATCH END
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1069,13 +1128,10 @@ static void ImGui_ImplGlfw_UpdateGamepads()
|
||||
static void ImGui_ImplGlfw_UpdateMonitors()
|
||||
{
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
|
||||
int monitors_count = 0;
|
||||
GLFWmonitor** glfw_monitors = glfwGetMonitors(&monitors_count);
|
||||
if (monitors_count == 0) // Preserve existing monitor list if there are none. Happens on macOS sleeping (#5683)
|
||||
return;
|
||||
|
||||
platform_io.Monitors.resize(0);
|
||||
bool updated_monitors = false;
|
||||
for (int n = 0; n < monitors_count; n++)
|
||||
{
|
||||
ImGuiPlatformMonitor monitor;
|
||||
@@ -1084,6 +1140,8 @@ static void ImGui_ImplGlfw_UpdateMonitors()
|
||||
const GLFWvidmode* vid_mode = glfwGetVideoMode(glfw_monitors[n]);
|
||||
if (vid_mode == nullptr)
|
||||
continue; // Failed to get Video mode (e.g. Emscripten does not support this function)
|
||||
if (vid_mode->width <= 0 || vid_mode->height <= 0)
|
||||
continue; // Failed to query suitable monitor info (#9195)
|
||||
monitor.MainPos = monitor.WorkPos = ImVec2((float)x, (float)y);
|
||||
monitor.MainSize = monitor.WorkSize = ImVec2((float)vid_mode->width, (float)vid_mode->height);
|
||||
#if GLFW_HAS_MONITOR_WORK_AREA
|
||||
@@ -1097,9 +1155,15 @@ static void ImGui_ImplGlfw_UpdateMonitors()
|
||||
#endif
|
||||
float scale = ImGui_ImplGlfw_GetContentScaleForMonitor(glfw_monitors[n]);
|
||||
if (scale == 0.0f)
|
||||
continue; // Some accessibility applications are declaring virtual monitors with a DPI of 0, see #7902.
|
||||
continue; // Some accessibility applications are declaring virtual monitors with a DPI of 0 (#7902)
|
||||
monitor.DpiScale = scale;
|
||||
monitor.PlatformHandle = (void*)glfw_monitors[n]; // [...] GLFW doc states: "guaranteed to be valid only until the monitor configuration changes"
|
||||
|
||||
// Preserve existing monitor list until a valid one is added.
|
||||
// Happens on macOS sleeping (#5683) and seemingly occasionally on Windows (#9195)
|
||||
if (!updated_monitors)
|
||||
platform_io.Monitors.resize(0);
|
||||
updated_monitors = true;
|
||||
platform_io.Monitors.push_back(monitor);
|
||||
}
|
||||
}
|
||||
@@ -1109,7 +1173,7 @@ static void ImGui_ImplGlfw_UpdateMonitors()
|
||||
// - Some accessibility applications are declaring virtual monitors with a DPI of 0.0f, see #7902. We preserve this value for caller to handle.
|
||||
float ImGui_ImplGlfw_GetContentScaleForWindow(GLFWwindow* window)
|
||||
{
|
||||
#if GLFW_HAS_X11_OR_WAYLAND
|
||||
#if GLFW_HAS_WAYLAND
|
||||
if (ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(window))
|
||||
if (bd->IsWayland)
|
||||
return 1.0f;
|
||||
@@ -1126,7 +1190,7 @@ float ImGui_ImplGlfw_GetContentScaleForWindow(GLFWwindow* window)
|
||||
|
||||
float ImGui_ImplGlfw_GetContentScaleForMonitor(GLFWmonitor* monitor)
|
||||
{
|
||||
#if GLFW_HAS_X11_OR_WAYLAND
|
||||
#if GLFW_HAS_WAYLAND
|
||||
if (ImGui_ImplGlfw_IsWayland()) // We can't access our bd->IsWayland cache for a monitor.
|
||||
return 1.0f;
|
||||
#endif
|
||||
@@ -1146,9 +1210,9 @@ static void ImGui_ImplGlfw_GetWindowSizeAndFramebufferScale(GLFWwindow* window,
|
||||
int display_w, display_h;
|
||||
glfwGetWindowSize(window, &w, &h);
|
||||
glfwGetFramebufferSize(window, &display_w, &display_h);
|
||||
float fb_scale_x = (w > 0) ? (float)display_w / w : 1.0f;
|
||||
float fb_scale_y = (h > 0) ? (float)display_h / h : 1.0f;
|
||||
#if GLFW_HAS_X11_OR_WAYLAND
|
||||
float fb_scale_x = (w > 0) ? (float)display_w / (float)w : 1.0f;
|
||||
float fb_scale_y = (h > 0) ? (float)display_h / (float)h : 1.0f;
|
||||
#if GLFW_HAS_WAYLAND
|
||||
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(window);
|
||||
if (!bd->IsWayland)
|
||||
fb_scale_x = fb_scale_y = 1.0f;
|
||||
@@ -1313,20 +1377,20 @@ static void ImGui_ImplGlfw_WindowSizeCallback(GLFWwindow* window, int, int)
|
||||
|
||||
#if !defined(__APPLE__) && !defined(_WIN32) && !defined(__EMSCRIPTEN__) && GLFW_HAS_GETPLATFORM
|
||||
#define IMGUI_GLFW_HAS_SETWINDOWFLOATING
|
||||
static void ImGui_ImplGlfw_SetWindowFloating(GLFWwindow* window)
|
||||
static void ImGui_ImplGlfw_SetWindowFloating(ImGui_ImplGlfw_Data* bd, GLFWwindow* window)
|
||||
{
|
||||
#ifdef GLFW_EXPOSE_NATIVE_X11
|
||||
if (glfwGetPlatform() == GLFW_PLATFORM_X11)
|
||||
{
|
||||
Display* display = glfwGetX11Display();
|
||||
Window xwindow = glfwGetX11Window(window);
|
||||
Atom wm_type = XInternAtom(display, "_NET_WM_WINDOW_TYPE", False);
|
||||
Atom wm_type_dialog = XInternAtom(display, "_NET_WM_WINDOW_TYPE_DIALOG", False);
|
||||
XChangeProperty(display, xwindow, wm_type, XA_ATOM, 32, PropModeReplace, (unsigned char*)&wm_type_dialog, 1);
|
||||
Atom wm_type = bd->XInternAtom(display, "_NET_WM_WINDOW_TYPE", False);
|
||||
Atom wm_type_dialog = bd->XInternAtom(display, "_NET_WM_WINDOW_TYPE_DIALOG", False);
|
||||
bd->XChangeProperty(display, xwindow, wm_type, XA_ATOM, 32, PropModeReplace, (unsigned char*)&wm_type_dialog, 1);
|
||||
XSetWindowAttributes attrs;
|
||||
attrs.override_redirect = False;
|
||||
XChangeWindowAttributes(display, xwindow, CWOverrideRedirect, &attrs);
|
||||
XFlush(display);
|
||||
bd->XChangeWindowAttributes(display, xwindow, CWOverrideRedirect, &attrs);
|
||||
bd->XFlush(display);
|
||||
}
|
||||
#endif // GLFW_EXPOSE_NATIVE_X11
|
||||
#ifdef GLFW_EXPOSE_NATIVE_WAYLAND
|
||||
@@ -1363,7 +1427,7 @@ static void ImGui_ImplGlfw_CreateWindow(ImGuiViewport* viewport)
|
||||
ImGui_ImplGlfw_ContextMap_Add(vd->Window, bd->Context);
|
||||
viewport->PlatformHandle = (void*)vd->Window;
|
||||
#ifdef IMGUI_GLFW_HAS_SETWINDOWFLOATING
|
||||
ImGui_ImplGlfw_SetWindowFloating(vd->Window);
|
||||
ImGui_ImplGlfw_SetWindowFloating(bd, vd->Window);
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
viewport->PlatformHandleRaw = glfwGetWin32Window(vd->Window);
|
||||
@@ -1408,7 +1472,7 @@ static void ImGui_ImplGlfw_DestroyWindow(ImGuiViewport* viewport)
|
||||
|
||||
// Release any keys that were pressed in the window being destroyed and are still held down,
|
||||
// because we will not receive any release events after window is destroyed.
|
||||
for (int i = 0; i < IM_ARRAYSIZE(bd->KeyOwnerWindows); i++)
|
||||
for (int i = 0; i < IM_COUNTOF(bd->KeyOwnerWindows); i++)
|
||||
if (bd->KeyOwnerWindows[i] == vd->Window)
|
||||
ImGui_ImplGlfw_KeyCallback(vd->Window, i, 0, GLFW_RELEASE, 0); // Later params are only used for main viewport, on which this function is never called.
|
||||
|
||||
|
||||
@@ -24,7 +24,9 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2025-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
||||
// 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
||||
// 2025-12-11: OpenGL: Fixed embedded loader multiple init/shutdown cycles broken on some platforms. (#8792, #9112)
|
||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
||||
// 2025-07-22: OpenGL: Add and call embedded loader shutdown during ImGui_ImplOpenGL3_Shutdown() to facilitate multiple init/shutdown cycles in same process. (#8792)
|
||||
// 2025-07-15: OpenGL: Set GL_UNPACK_ALIGNMENT to 1 before updating textures (#8802) + restore non-WebGL/ES update path that doesn't require a CPU-side copy.
|
||||
// 2025-06-11: OpenGL: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplOpenGL3_CreateFontsTexture() and ImGui_ImplOpenGL3_DestroyFontsTexture().
|
||||
@@ -41,7 +43,7 @@
|
||||
// 2023-05-09: OpenGL: Support for glBindSampler() backup/restore on ES3. (#6375)
|
||||
// 2023-04-18: OpenGL: Restore front and back polygon mode separately when supported by context. (#6333)
|
||||
// 2023-03-23: OpenGL: Properly restoring "no shader program bound" if it was the case prior to running the rendering function. (#6267, #6220, #6224)
|
||||
// 2023-03-15: OpenGL: Fixed GL loader crash when GL_VERSION returns NULL. (#6154, #4445, #3530)
|
||||
// 2023-03-15: OpenGL: Fixed GL loader crash when GL_VERSION returns nullptr. (#6154, #4445, #3530)
|
||||
// 2023-03-06: OpenGL: Fixed restoration of a potentially deleted OpenGL program, by calling glIsProgram(). (#6220, #6224)
|
||||
// 2022-11-09: OpenGL: Reverted use of glBufferSubData(), too many corruptions issues + old issues seemingly can't be reproed with Intel drivers nowadays (revert 2021-12-15 and 2022-05-23 changes).
|
||||
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
|
||||
@@ -305,7 +307,8 @@ struct ImGui_ImplOpenGL3_VtxAttribState
|
||||
bool ImGui_ImplOpenGL3_InitLoader();
|
||||
bool ImGui_ImplOpenGL3_InitLoader()
|
||||
{
|
||||
// Initialize our loader
|
||||
// Lazily initialize our loader if not already done
|
||||
// (to facilitate handling multiple DLL boundaries and multiple context shutdowns we call this from all main entry points)
|
||||
#ifdef IMGUI_IMPL_OPENGL_LOADER_IMGL3W
|
||||
if (glGetIntegerv == nullptr && imgl3wInit() != 0)
|
||||
{
|
||||
@@ -316,6 +319,13 @@ bool ImGui_ImplOpenGL3_InitLoader()
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ImGui_ImplOpenGL3_ShutdownLoader()
|
||||
{
|
||||
#ifdef IMGUI_IMPL_OPENGL_LOADER_IMGL3W
|
||||
imgl3wShutdown();
|
||||
#endif
|
||||
}
|
||||
|
||||
// Functions
|
||||
bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
|
||||
{
|
||||
@@ -402,7 +412,7 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
|
||||
glsl_version = "#version 130";
|
||||
#endif
|
||||
}
|
||||
IM_ASSERT((int)strlen(glsl_version) + 2 < IM_ARRAYSIZE(bd->GlslVersionString));
|
||||
IM_ASSERT((int)strlen(glsl_version) + 2 < IM_COUNTOF(bd->GlslVersionString));
|
||||
strcpy(bd->GlslVersionString, glsl_version);
|
||||
strcat(bd->GlslVersionString, "\n");
|
||||
|
||||
@@ -440,17 +450,18 @@ void ImGui_ImplOpenGL3_Shutdown()
|
||||
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
|
||||
ImGui_ImplOpenGL3_ShutdownMultiViewportSupport();
|
||||
ImGui_ImplOpenGL3_DestroyDeviceObjects();
|
||||
|
||||
io.BackendRendererName = nullptr;
|
||||
io.BackendRendererUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures | ImGuiBackendFlags_RendererHasViewports);
|
||||
platform_io.ClearRendererHandlers();
|
||||
IM_DELETE(bd);
|
||||
|
||||
#ifdef IMGUI_IMPL_OPENGL_LOADER_IMGL3W
|
||||
imgl3wShutdown();
|
||||
#endif
|
||||
ImGui_ImplOpenGL3_ShutdownLoader();
|
||||
}
|
||||
|
||||
void ImGui_ImplOpenGL3_NewFrame()
|
||||
@@ -458,8 +469,7 @@ void ImGui_ImplOpenGL3_NewFrame()
|
||||
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplOpenGL3_Init()?");
|
||||
|
||||
ImGui_ImplOpenGL3_InitLoader(); // Lazily init loader if not already done for e.g. DLL boundaries.
|
||||
|
||||
ImGui_ImplOpenGL3_InitLoader();
|
||||
if (!bd->ShaderHandle)
|
||||
if (!ImGui_ImplOpenGL3_CreateDeviceObjects())
|
||||
IM_ASSERT(0 && "ImGui_ImplOpenGL3_CreateDeviceObjects() failed!");
|
||||
@@ -483,11 +493,11 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
|
||||
glEnable(GL_BLEND);
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
// IMHEX PATCH BEGIN
|
||||
#if !defined(__EMSCRIPTEN__)
|
||||
#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3)
|
||||
if (useFontShaders) {
|
||||
glBlendFuncSeparate(GL_SRC1_COLOR, GL_ONE_MINUS_SRC1_COLOR,GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
} else {
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
#else
|
||||
// IMHEX PATCH END
|
||||
@@ -575,7 +585,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
||||
if (fb_width <= 0 || fb_height <= 0)
|
||||
return;
|
||||
|
||||
ImGui_ImplOpenGL3_InitLoader(); // Lazily init loader if not already done for e.g. DLL boundaries.
|
||||
ImGui_ImplOpenGL3_InitLoader();
|
||||
|
||||
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
|
||||
|
||||
@@ -779,7 +789,7 @@ void ImGui_ImplOpenGL3_UpdateTexture(ImTextureData* tex)
|
||||
{
|
||||
// Create and upload new texture to graphics system
|
||||
//IMGUI_DEBUG_LOG("UpdateTexture #%03d: WantCreate %dx%d\n", tex->UniqueID, tex->Width, tex->Height);
|
||||
IM_ASSERT(tex->TexID == 0 && tex->BackendUserData == nullptr);
|
||||
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == nullptr);
|
||||
IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
|
||||
const void* pixels = tex->GetPixels();
|
||||
GLuint gl_texture_id = 0;
|
||||
@@ -878,6 +888,7 @@ static bool CheckProgram(GLuint handle, const char* desc)
|
||||
|
||||
bool ImGui_ImplOpenGL3_CreateDeviceObjects()
|
||||
{
|
||||
ImGui_ImplOpenGL3_InitLoader();
|
||||
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
|
||||
|
||||
// Backup GL state
|
||||
@@ -1000,7 +1011,7 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects()
|
||||
"{\n"
|
||||
// IMHEX PATCH BEGIN
|
||||
" if (!GammaCorrected)\n"
|
||||
" Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
|
||||
" Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
|
||||
" else {\n"
|
||||
" Out_Color = Frag_Color;\n"
|
||||
" SRC1_Color = vec4(texture(Texture, Frag_UV.st).rgb * Frag_Color.aaa,1.0);\n"
|
||||
@@ -1090,6 +1101,7 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects()
|
||||
|
||||
void ImGui_ImplOpenGL3_DestroyDeviceObjects()
|
||||
{
|
||||
ImGui_ImplOpenGL3_InitLoader();
|
||||
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
|
||||
if (bd->VboHandle) { glDeleteBuffers(1, &bd->VboHandle); bd->VboHandle = 0; }
|
||||
if (bd->ElementsHandle) { glDeleteBuffers(1, &bd->ElementsHandle); bd->ElementsHandle = 0; }
|
||||
|
||||
@@ -4729,7 +4729,6 @@ CIMGUI_API void ImRect_TranslateX(ImRect* self,float dx);
|
||||
CIMGUI_API void ImRect_TranslateY(ImRect* self,float dy);
|
||||
CIMGUI_API void ImRect_ClipWith(ImRect* self,const ImRect r);
|
||||
CIMGUI_API void ImRect_ClipWithFull(ImRect* self,const ImRect r);
|
||||
CIMGUI_API void ImRect_Floor(ImRect* self);
|
||||
CIMGUI_API bool ImRect_IsInverted(ImRect* self);
|
||||
CIMGUI_API void ImRect_ToVec4(ImVec4 *pOut,ImRect* self);
|
||||
CIMGUI_API size_t igImBitArrayGetStorageSizeInBytes(int bitcount);
|
||||
@@ -5261,7 +5260,6 @@ CIMGUI_API void igRenderBullet(ImDrawList* draw_list,ImVec2 pos,ImU32 col);
|
||||
CIMGUI_API void igRenderCheckMark(ImDrawList* draw_list,ImVec2 pos,ImU32 col,float sz);
|
||||
CIMGUI_API void igRenderArrowPointingAt(ImDrawList* draw_list,ImVec2 pos,ImVec2 half_sz,ImGuiDir direction,ImU32 col);
|
||||
CIMGUI_API void igRenderArrowDockMenu(ImDrawList* draw_list,ImVec2 p_min,float sz,ImU32 col);
|
||||
CIMGUI_API void igRenderRectFilledRangeH(ImDrawList* draw_list,const ImRect rect,ImU32 col,float x_start_norm,float x_end_norm,float rounding);
|
||||
CIMGUI_API void igRenderRectFilledWithHole(ImDrawList* draw_list,const ImRect outer,const ImRect inner,ImU32 col,float rounding);
|
||||
CIMGUI_API ImDrawFlags igCalcRoundingFlagsForRectInRect(const ImRect r_in,const ImRect r_outer,float threshold);
|
||||
CIMGUI_API void igTextEx(const char* text,const char* text_end,ImGuiTextFlags flags);
|
||||
@@ -5347,7 +5345,6 @@ CIMGUI_API void igDebugNodeDockNode(ImGuiDockNode* node,const char* label);
|
||||
CIMGUI_API void igDebugNodeDrawList(ImGuiWindow* window,ImGuiViewportP* viewport,const ImDrawList* draw_list,const char* label);
|
||||
CIMGUI_API void igDebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list,const ImDrawList* draw_list,const ImDrawCmd* draw_cmd,bool show_mesh,bool show_aabb);
|
||||
CIMGUI_API void igDebugNodeFont(ImFont* font);
|
||||
CIMGUI_API void igDebugNodeFontGlyphesForSrcMask(ImFont* font,ImFontBaked* baked,int src_mask);
|
||||
CIMGUI_API void igDebugNodeFontGlyph(ImFont* font,const ImFontGlyph* glyph);
|
||||
CIMGUI_API void igDebugNodeTexture(ImTextureData* tex,int int_id,const ImFontAtlasRect* highlight_rect);
|
||||
CIMGUI_API void igDebugNodeStorage(ImGuiStorage* storage,const char* label);
|
||||
|
||||
12
lib/third_party/imgui/cimgui/source/cimgui.cpp
vendored
12
lib/third_party/imgui/cimgui/source/cimgui.cpp
vendored
@@ -3469,10 +3469,6 @@ CIMGUI_API void ImRect_ClipWithFull(ImRect* self,const ImRect r)
|
||||
{
|
||||
return self->ClipWithFull(r);
|
||||
}
|
||||
CIMGUI_API void ImRect_Floor(ImRect* self)
|
||||
{
|
||||
return self->Floor();
|
||||
}
|
||||
CIMGUI_API bool ImRect_IsInverted(ImRect* self)
|
||||
{
|
||||
return self->IsInverted();
|
||||
@@ -5597,10 +5593,6 @@ CIMGUI_API void igRenderArrowDockMenu(ImDrawList* draw_list,ImVec2 p_min,float s
|
||||
{
|
||||
return ImGui::RenderArrowDockMenu(draw_list,p_min,sz,col);
|
||||
}
|
||||
CIMGUI_API void igRenderRectFilledRangeH(ImDrawList* draw_list,const ImRect rect,ImU32 col,float x_start_norm,float x_end_norm,float rounding)
|
||||
{
|
||||
return ImGui::RenderRectFilledRangeH(draw_list,rect,col,x_start_norm,x_end_norm,rounding);
|
||||
}
|
||||
CIMGUI_API void igRenderRectFilledWithHole(ImDrawList* draw_list,const ImRect outer,const ImRect inner,ImU32 col,float rounding)
|
||||
{
|
||||
return ImGui::RenderRectFilledWithHole(draw_list,outer,inner,col,rounding);
|
||||
@@ -5938,10 +5930,6 @@ CIMGUI_API void igDebugNodeFont(ImFont* font)
|
||||
{
|
||||
return ImGui::DebugNodeFont(font);
|
||||
}
|
||||
CIMGUI_API void igDebugNodeFontGlyphesForSrcMask(ImFont* font,ImFontBaked* baked,int src_mask)
|
||||
{
|
||||
return ImGui::DebugNodeFontGlyphesForSrcMask(font,baked,src_mask);
|
||||
}
|
||||
CIMGUI_API void igDebugNodeFontGlyph(ImFont* font,const ImFontGlyph* glyph)
|
||||
{
|
||||
return ImGui::DebugNodeFontGlyph(font,glyph);
|
||||
|
||||
238
lib/third_party/imgui/imgui/include/imgui.h
vendored
238
lib/third_party/imgui/imgui/include/imgui.h
vendored
@@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.92.5
|
||||
// dear imgui, v1.92.7 WIP
|
||||
// (headers)
|
||||
|
||||
// Help:
|
||||
@@ -20,7 +20,7 @@
|
||||
// - Software using Dear ImGui https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui
|
||||
// - Issues & support ........... https://github.com/ocornut/imgui/issues
|
||||
// - Test Engine & Automation ... https://github.com/ocornut/imgui_test_engine (test suite, test engine to automate your apps)
|
||||
// - Web version of the Demo .... https://pthom.github.io/imgui_manual_online/manual/imgui_manual.html (w/ source code browser)
|
||||
// - Web version of the Demo .... https://pthom.github.io/imgui_manual (w/ source code browser)
|
||||
|
||||
// For FIRST-TIME users having issues compiling/linking/running:
|
||||
// please post in https://github.com/ocornut/imgui/discussions if you cannot find a solution in resources above.
|
||||
@@ -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.5"
|
||||
#define IMGUI_VERSION_NUM 19250
|
||||
#define IMGUI_VERSION "1.92.7 WIP"
|
||||
#define IMGUI_VERSION_NUM 19265
|
||||
#define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000
|
||||
#define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198
|
||||
#define IMGUI_HAS_VIEWPORT // In 'docking' WIP branch.
|
||||
@@ -97,7 +97,7 @@ Index of this file:
|
||||
#include <assert.h>
|
||||
#define IM_ASSERT(_EXPR) assert(_EXPR) // You can override the default assert handler by editing imconfig.h
|
||||
#endif
|
||||
#define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR) / sizeof(*(_ARR)))) // Size of a static C-style array. Don't use on pointers!
|
||||
#define IM_COUNTOF(_ARR) ((int)(sizeof(_ARR) / sizeof(*(_ARR)))) // Size of a static C-style array. Don't use on pointers!
|
||||
#define IM_UNUSED(_VAR) ((void)(_VAR)) // Used to silence "unused variable warnings". Often useful as asserts may be stripped out from final builds.
|
||||
#define IM_STRINGIFY_HELPER(_EXPR) #_EXPR
|
||||
#define IM_STRINGIFY(_EXPR) IM_STRINGIFY_HELPER(_EXPR) // Preprocessor idiom to stringify e.g. an integer or a macro.
|
||||
@@ -345,16 +345,18 @@ IM_MSVC_RUNTIME_CHECKS_RESTORE
|
||||
typedef ImU64 ImTextureID; // Default: store up to 64-bits (any pointer or integer). A majority of backends are ok with that.
|
||||
#endif
|
||||
|
||||
// Define this if you need 0 to be a valid ImTextureID for your backend.
|
||||
// Define this if you need to change the invalid value for your backend.
|
||||
// - in v1.92.7 (2025/03/12): we changed default value from 0 to -1 as it is a better default, which supports storing offsets/indices.
|
||||
// - If this is causing problem with your custom ImTextureID definition, you can add '#define ImTextureID_Invalid' to your imconfig + please report this to GitHub.
|
||||
#ifndef ImTextureID_Invalid
|
||||
#define ImTextureID_Invalid ((ImTextureID)0)
|
||||
#define ImTextureID_Invalid ((ImTextureID)-1)
|
||||
#endif
|
||||
|
||||
// ImTextureRef = higher-level identifier for a texture. Store a ImTextureID _or_ a ImTextureData*.
|
||||
// The identifier is valid even before the texture has been uploaded to the GPU/graphics system.
|
||||
// This is what gets passed to functions such as `ImGui::Image()`, `ImDrawList::AddImage()`.
|
||||
// This is what gets stored in draw commands (`ImDrawCmd`) to identify a texture during rendering.
|
||||
// - When a texture is created by user code (e.g. custom images), we directly stores the low-level ImTextureID.
|
||||
// - When a texture is created by user code (e.g. custom images), we directly store the low-level ImTextureID.
|
||||
// Because of this, when displaying your own texture you are likely to ever only manage ImTextureID values on your side.
|
||||
// - When a texture is created by the backend, we stores a ImTextureData* which becomes an indirection
|
||||
// to extract the ImTextureID value during rendering, after texture upload has happened.
|
||||
@@ -764,6 +766,7 @@ namespace ImGui
|
||||
IMGUI_API bool CollapsingHeader(const char* label, bool* p_visible, ImGuiTreeNodeFlags flags = 0); // when 'p_visible != NULL': if '*p_visible==true' display an additional small close button on upper right of the header which will set the bool to false when clicked, if '*p_visible==false' don't display the header.
|
||||
IMGUI_API void SetNextItemOpen(bool is_open, ImGuiCond cond = 0); // set next TreeNode/CollapsingHeader open state.
|
||||
IMGUI_API void SetNextItemStorageID(ImGuiID storage_id); // set id to use for open/close storage (default to same as item id).
|
||||
IMGUI_API bool TreeNodeGetOpen(ImGuiID storage_id); // retrieve tree node open/close state.
|
||||
|
||||
// Widgets: Selectables
|
||||
// - A selectable highlights when hovered, and can display another color when selected.
|
||||
@@ -861,20 +864,23 @@ namespace ImGui
|
||||
// - CloseCurrentPopup() is called by default by Selectable()/MenuItem() when activated (FIXME: need some options).
|
||||
// - Use ImGuiPopupFlags_NoOpenOverExistingPopup to avoid opening a popup if there's already one at the same level. This is equivalent to e.g. testing for !IsAnyPopupOpen() prior to OpenPopup().
|
||||
// - Use IsWindowAppearing() after BeginPopup() to tell if a window just opened.
|
||||
// - IMPORTANT: Notice that for OpenPopupOnItemClick() we exceptionally default flags to 1 (== ImGuiPopupFlags_MouseButtonRight) for backward compatibility with older API taking 'int mouse_button = 1' parameter
|
||||
IMGUI_API void OpenPopup(const char* str_id, ImGuiPopupFlags popup_flags = 0); // call to mark popup as open (don't call every frame!).
|
||||
IMGUI_API void OpenPopup(ImGuiID id, ImGuiPopupFlags popup_flags = 0); // id overload to facilitate calling from nested stacks
|
||||
IMGUI_API void OpenPopupOnItemClick(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1); // helper to open popup when clicked on last item. Default to ImGuiPopupFlags_MouseButtonRight == 1. (note: actually triggers on the mouse _released_ event to be consistent with popup behaviors)
|
||||
IMGUI_API void OpenPopupOnItemClick(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 0); // helper to open popup when clicked on last item. Default to ImGuiPopupFlags_MouseButtonRight == 1. (note: actually triggers on the mouse _released_ event to be consistent with popup behaviors)
|
||||
IMGUI_API void CloseCurrentPopup(); // manually close the popup we have begin-ed into.
|
||||
|
||||
// Popups: open+begin combined functions helpers
|
||||
// Popups: Open+Begin popup combined functions helpers to create context menus.
|
||||
// - Helpers to do OpenPopup+BeginPopup where the Open action is triggered by e.g. hovering an item and right-clicking.
|
||||
// - They are convenient to easily create context menus, hence the name.
|
||||
// - IMPORTANT: Notice that BeginPopupContextXXX takes ImGuiPopupFlags just like OpenPopup() and unlike BeginPopup(). For full consistency, we may add ImGuiWindowFlags to the BeginPopupContextXXX functions in the future.
|
||||
// - IMPORTANT: Notice that we exceptionally default their flags to 1 (== ImGuiPopupFlags_MouseButtonRight) for backward compatibility with older API taking 'int mouse_button = 1' parameter, so if you add other flags remember to re-add the ImGuiPopupFlags_MouseButtonRight.
|
||||
IMGUI_API bool BeginPopupContextItem(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1); // open+begin popup when clicked on last item. Use str_id==NULL to associate the popup to previous item. If you want to use that on a non-interactive item such as Text() you need to pass in an explicit ID here. read comments in .cpp!
|
||||
IMGUI_API bool BeginPopupContextWindow(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1);// open+begin popup when clicked on current window.
|
||||
IMGUI_API bool BeginPopupContextVoid(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1); // open+begin popup when clicked in void (where there are no windows).
|
||||
// - IMPORTANT: If you ever used the left mouse button with BeginPopupContextXXX() helpers before 1.92.6:
|
||||
// - Before this version, OpenPopupOnItemClick(), BeginPopupContextItem(), BeginPopupContextWindow(), BeginPopupContextVoid() had 'a ImGuiPopupFlags popup_flags = 1' default value in their function signature.
|
||||
// - Before: Explicitly passing a literal 0 meant ImGuiPopupFlags_MouseButtonLeft. The default = 1 meant ImGuiPopupFlags_MouseButtonRight.
|
||||
// - After: The default = 0 means ImGuiPopupFlags_MouseButtonRight. Explicitly passing a literal 1 also means ImGuiPopupFlags_MouseButtonRight (if legacy behavior are enabled) or will assert (if legacy behavior are disabled).
|
||||
// - TL;DR: if you don't want to use right mouse button for popups, always specify it explicitly using a named ImGuiPopupFlags_MouseButtonXXXX value.
|
||||
// - Read "API BREAKING CHANGES" 2026/01/07 (1.92.6) entry in imgui.cpp or GitHub topic #9157 for all details.
|
||||
IMGUI_API bool BeginPopupContextItem(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 0); // open+begin popup when clicked on last item. Use str_id==NULL to associate the popup to previous item. If you want to use that on a non-interactive item such as Text() you need to pass in an explicit ID here. read comments in .cpp!
|
||||
IMGUI_API bool BeginPopupContextWindow(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 0);// open+begin popup when clicked on current window.
|
||||
IMGUI_API bool BeginPopupContextVoid(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 0); // open+begin popup when clicked in void (where there are no windows).
|
||||
|
||||
// Popups: query functions
|
||||
// - IsPopupOpen(): return true if the popup is open at the current BeginPopup() level of the popup stack.
|
||||
@@ -905,7 +911,7 @@ namespace ImGui
|
||||
// - 5. Call EndTable()
|
||||
IMGUI_API bool BeginTable(const char* str_id, int columns, ImGuiTableFlags flags = 0, const ImVec2& outer_size = ImVec2(0.0f, 0.0f), float inner_width = 0.0f);
|
||||
IMGUI_API void EndTable(); // only call EndTable() if BeginTable() returns true!
|
||||
IMGUI_API void TableNextRow(ImGuiTableRowFlags row_flags = 0, float min_row_height = 0.0f); // append into the first cell of a new row.
|
||||
IMGUI_API void TableNextRow(ImGuiTableRowFlags row_flags = 0, float min_row_height = 0.0f); // append into the first cell of a new row. 'min_row_height' include the minimum top and bottom padding aka CellPadding.y * 2.0f.
|
||||
IMGUI_API bool TableNextColumn(); // append into the next column (or first column of next row if currently in last column). Return true when column is visible.
|
||||
IMGUI_API bool TableSetColumnIndex(int column_n); // append into the specified column. Return true when column is visible.
|
||||
|
||||
@@ -962,19 +968,21 @@ namespace ImGui
|
||||
// Docking
|
||||
// - Read https://github.com/ocornut/imgui/wiki/Docking for details.
|
||||
// - Enable with io.ConfigFlags |= ImGuiConfigFlags_DockingEnable.
|
||||
// - You can use most Docking facilities without calling any API. You don't necessarily need to call a DockSpaceXXX function to use Docking!
|
||||
// - You can use many Docking facilities without calling any API.
|
||||
// - Drag from window title bar or their tab to dock/undock. Hold SHIFT to disable docking.
|
||||
// - Drag from window menu button (upper-left button) to undock an entire node (all windows).
|
||||
// - When io.ConfigDockingWithShift == true, you instead need to hold SHIFT to enable docking.
|
||||
// - DockSpaceOverViewport:
|
||||
// - This is a helper to create an invisible window covering a viewport, then submit a DockSpace() into it.
|
||||
// - Most applications can simply call DockSpaceOverViewport() once to allow docking windows into e.g. the edge of your screen.
|
||||
// e.g. ImGui::NewFrame(); ImGui::DockSpaceOverViewport(); // Create a dockspace in main viewport.
|
||||
// or: ImGui::NewFrame(); ImGui::DockSpaceOverViewport(0, nullptr, ImGuiDockNodeFlags_PassthruCentralNode); // Create a dockspace in main viewport, central node is transparent.
|
||||
// - Dockspaces:
|
||||
// - If you want to dock windows into the edge of your screen, most application can simply call DockSpaceOverViewport():
|
||||
// e.g. ImGui::NewFrame(); then ImGui::DockSpaceOverViewport(); // Create a dockspace in main viewport.
|
||||
// or: ImGui::NewFrame(); then ImGui::DockSpaceOverViewport(0, nullptr, ImGuiDockNodeFlags_PassthruCentralNode); // Create a dockspace in main viewport, where central node is transparent.
|
||||
// - A dockspace is an explicit dock node within an existing window.
|
||||
// - DockSpaceOverViewport() basically creates an invisible window covering a viewport, and submit a DockSpace() into it.
|
||||
// - IMPORTANT: Dockspaces need to be submitted _before_ any window they can host. Submit them early in your frame!
|
||||
// - IMPORTANT: Dockspaces need to be kept alive if hidden, otherwise windows docked into it will be undocked.
|
||||
// If you have e.g. multiple tabs with a dockspace inside each tab: submit the non-visible dockspaces with ImGuiDockNodeFlags_KeepAliveOnly.
|
||||
// - See 'Demo->Examples->Dockspace' or 'Demo->Examples->Documents' for more detailed demos.
|
||||
// - Programmatic docking:
|
||||
// - There is no public API yet other than the very limited SetNextWindowDockID() function. Sorry for that!
|
||||
// - Read https://github.com/ocornut/imgui/wiki/Docking for examples of how to use current internal API.
|
||||
@@ -982,7 +990,7 @@ namespace ImGui
|
||||
IMGUI_API ImGuiID DockSpaceOverViewport(ImGuiID dockspace_id = 0, const ImGuiViewport* viewport = NULL, ImGuiDockNodeFlags flags = 0, const ImGuiWindowClass* window_class = NULL);
|
||||
IMGUI_API void SetNextWindowDockID(ImGuiID dock_id, ImGuiCond cond = 0); // set next window dock id
|
||||
IMGUI_API void SetNextWindowClass(const ImGuiWindowClass* window_class); // set next window class (control docking compatibility + provide hints to platform backend via custom viewport flags and platform parent/child relationship)
|
||||
IMGUI_API ImGuiID GetWindowDockID();
|
||||
IMGUI_API ImGuiID GetWindowDockID(); // get dock id of current window, or 0 if not associated to any docking node.
|
||||
IMGUI_API bool IsWindowDocked(); // is current window docked into another window?
|
||||
|
||||
// Logging/Capture
|
||||
@@ -1011,7 +1019,7 @@ namespace ImGui
|
||||
// Disabling [BETA API]
|
||||
// - Disable all user interactions and dim items visuals (applying style.DisabledAlpha over current colors)
|
||||
// - Those can be nested but it cannot be used to enable an already disabled section (a single BeginDisabled(true) in the stack is enough to keep everything disabled)
|
||||
// - Tooltips windows are automatically opted out of disabling. Note that IsItemHovered() by default returns false on disabled items, unless using ImGuiHoveredFlags_AllowWhenDisabled.
|
||||
// - Tooltips windows are automatically opted out of disabling. Note that IsItemHovered() by default returns false on disabled items, unless using ImGuiHoveredFlags_AllowWhenDisabled.
|
||||
// - BeginDisabled(false)/EndDisabled() essentially does nothing but is provided to facilitate use of boolean expressions (as a micro-optimization: if you have tens of thousands of BeginDisabled(false)/EndDisabled() pairs, you might want to reformulate your code to avoid making those calls)
|
||||
IMGUI_API void BeginDisabled(bool disabled = true);
|
||||
IMGUI_API void EndDisabled();
|
||||
@@ -1051,6 +1059,7 @@ namespace ImGui
|
||||
IMGUI_API ImVec2 GetItemRectMin(); // get upper-left bounding rectangle of the last item (screen space)
|
||||
IMGUI_API ImVec2 GetItemRectMax(); // get lower-right bounding rectangle of the last item (screen space)
|
||||
IMGUI_API ImVec2 GetItemRectSize(); // get size of last item
|
||||
IMGUI_API ImGuiItemFlags GetItemFlags(); // get generic flags of last item
|
||||
|
||||
// Viewports
|
||||
// - Currently represents the Platform Window created by the application which is hosting our Dear ImGui windows.
|
||||
@@ -1081,19 +1090,22 @@ namespace ImGui
|
||||
IMGUI_API void ColorConvertRGBtoHSV(float r, float g, float b, float& out_h, float& out_s, float& out_v);
|
||||
IMGUI_API void ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float& out_g, float& out_b);
|
||||
|
||||
// Inputs Utilities: Keyboard/Mouse/Gamepad
|
||||
// Inputs Utilities: Raw Keyboard/Mouse/Gamepad Access
|
||||
// - Consider using the Shortcut() function instead of IsKeyPressed()/IsKeyChordPressed()! Shortcut() is easier to use and better featured (can do focus routing check).
|
||||
// - the ImGuiKey enum contains all possible keyboard, mouse and gamepad inputs (e.g. ImGuiKey_A, ImGuiKey_MouseLeft, ImGuiKey_GamepadDpadUp...).
|
||||
// - (legacy: before v1.87, we used ImGuiKey to carry native/user indices as defined by each backends. This was obsoleted in 1.87 (2022-02) and completely removed in 1.91.5 (2024-11). See https://github.com/ocornut/imgui/issues/4921)
|
||||
// - (legacy: any use of ImGuiKey will assert when key < 512 to detect passing legacy native/user indices)
|
||||
// - (legacy: before v1.87 (2022-02), we used ImGuiKey < 512 values to carry native/user indices as defined by each backends. This was obsoleted in 1.87 (2022-02) and completely removed in 1.91.5 (2024-11). See https://github.com/ocornut/imgui/issues/4921)
|
||||
IMGUI_API bool IsKeyDown(ImGuiKey key); // is key being held.
|
||||
IMGUI_API bool IsKeyPressed(ImGuiKey key, bool repeat = true); // was key pressed (went from !Down to Down)? if repeat=true, uses io.KeyRepeatDelay / KeyRepeatRate
|
||||
IMGUI_API bool IsKeyPressed(ImGuiKey key, bool repeat = true); // was key pressed (went from !Down to Down)? Repeat rate uses io.KeyRepeatDelay / KeyRepeatRate.
|
||||
IMGUI_API bool IsKeyReleased(ImGuiKey key); // was key released (went from Down to !Down)?
|
||||
IMGUI_API bool IsKeyChordPressed(ImGuiKeyChord key_chord); // was key chord (mods + key) pressed, e.g. you can pass 'ImGuiMod_Ctrl | ImGuiKey_S' as a key-chord. This doesn't do any routing or focus check, please consider using Shortcut() function instead.
|
||||
IMGUI_API int GetKeyPressedAmount(ImGuiKey key, float repeat_delay, float rate); // uses provided repeat rate/delay. return a count, most often 0 or 1 but might be >1 if RepeatRate is small enough that DeltaTime > RepeatRate
|
||||
IMGUI_API const char* GetKeyName(ImGuiKey key); // [DEBUG] returns English name of the key. Those names are provided for debugging purpose and are not meant to be saved persistently nor compared.
|
||||
IMGUI_API void SetNextFrameWantCaptureKeyboard(bool want_capture_keyboard); // Override io.WantCaptureKeyboard flag next frame (said flag is left for your application to handle, typically when true it instructs your app to ignore inputs). e.g. force capture keyboard when your widget is being hovered. This is equivalent to setting "io.WantCaptureKeyboard = want_capture_keyboard"; after the next NewFrame() call.
|
||||
|
||||
// Inputs Utilities: Shortcut Testing & Routing [BETA]
|
||||
// Inputs Utilities: Shortcut Testing & Routing
|
||||
// - Typical use is e.g.: 'if (ImGui::Shortcut(ImGuiMod_Ctrl | ImGuiKey_S)) { ... }'.
|
||||
// - Flags: Default route use ImGuiInputFlags_RouteFocused, but see ImGuiInputFlags_RouteGlobal and other options in ImGuiInputFlags_!
|
||||
// - Flags: Use ImGuiInputFlags_Repeat to support repeat.
|
||||
// - ImGuiKeyChord = a ImGuiKey + optional ImGuiMod_Alt/ImGuiMod_Ctrl/ImGuiMod_Shift/ImGuiMod_Super.
|
||||
// ImGuiKey_C // Accepted by functions taking ImGuiKey or ImGuiKeyChord arguments
|
||||
// ImGuiMod_Ctrl | ImGuiKey_C // Accepted by functions taking ImGuiKeyChord arguments
|
||||
@@ -1105,8 +1117,10 @@ namespace ImGui
|
||||
// The whole system is order independent, so if Child1 makes its calls before Parent, results will be identical.
|
||||
// This is an important property as it facilitate working with foreign code or larger codebase.
|
||||
// - To understand the difference:
|
||||
// - IsKeyChordPressed() compares mods and call IsKeyPressed() -> function has no side-effect.
|
||||
// - Shortcut() submits a route, routes are resolved, if it currently can be routed it calls IsKeyChordPressed() -> function has (desirable) side-effects as it can prevents another call from getting the route.
|
||||
// - IsKeyChordPressed() compares mods and call IsKeyPressed()
|
||||
// -> the function has no side-effect.
|
||||
// - Shortcut() submits a route, routes are resolved, if it currently can be routed it calls IsKeyChordPressed()
|
||||
// -> the function has (desirable) side-effects as it can prevents another call from getting the route.
|
||||
// - Visualize registered routes in 'Metrics/Debugger->Inputs'.
|
||||
IMGUI_API bool Shortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags = 0);
|
||||
IMGUI_API void SetNextItemShortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags = 0);
|
||||
@@ -1156,7 +1170,9 @@ namespace ImGui
|
||||
IMGUI_API const char* SaveIniSettingsToMemory(size_t* out_ini_size = NULL); // return a zero-terminated string with the .ini data which you can save by your own mean. call when io.WantSaveIniSettings is set, then save data by your own mean and clear io.WantSaveIniSettings.
|
||||
|
||||
// Debug Utilities
|
||||
// - Your main debugging friend is the ShowMetricsWindow() function, which is also accessible from Demo->Tools->Metrics Debugger
|
||||
// - Your main debugging friend is the ShowMetricsWindow() function.
|
||||
// - Interactive tools are all accessible from the 'Dear ImGui Demo->Tools' menu.
|
||||
// - Read https://github.com/ocornut/imgui/wiki/Debug-Tools for a description of all available debug tools.
|
||||
IMGUI_API void DebugTextEncoding(const char* text);
|
||||
IMGUI_API void DebugFlashStyleColor(ImGuiCol idx);
|
||||
IMGUI_API void DebugStartItemPicker();
|
||||
@@ -1263,7 +1279,7 @@ enum ImGuiChildFlags_
|
||||
};
|
||||
|
||||
// Flags for ImGui::PushItemFlag()
|
||||
// (Those are shared by all items)
|
||||
// (Those are shared by all submitted items)
|
||||
enum ImGuiItemFlags_
|
||||
{
|
||||
ImGuiItemFlags_None = 0, // (Default)
|
||||
@@ -1273,6 +1289,7 @@ enum ImGuiItemFlags_
|
||||
ImGuiItemFlags_ButtonRepeat = 1 << 3, // false // Any button-like behavior will have repeat mode enabled (based on io.KeyRepeatDelay and io.KeyRepeatRate values). Note that you can also call IsItemActive() after any button to tell if it is being held.
|
||||
ImGuiItemFlags_AutoClosePopups = 1 << 4, // true // MenuItem()/Selectable() automatically close their parent popup window.
|
||||
ImGuiItemFlags_AllowDuplicateId = 1 << 5, // false // Allow submitting an item with the same identifier as an item already submitted this frame without triggering a warning tooltip if io.ConfigDebugHighlightIdConflicts is set.
|
||||
ImGuiItemFlags_Disabled = 1 << 6, // false // [Internal] Disable interactions. DOES NOT affect visuals. This is used by BeginDisabled()/EndDisabled() and only provided here so you can read back via GetItemFlags().
|
||||
};
|
||||
|
||||
// Flags for ImGui::InputText()
|
||||
@@ -1291,7 +1308,7 @@ enum ImGuiInputTextFlags_
|
||||
ImGuiInputTextFlags_AllowTabInput = 1 << 5, // Pressing TAB input a '\t' character into the text field
|
||||
ImGuiInputTextFlags_EnterReturnsTrue = 1 << 6, // Return 'true' when Enter is pressed (as opposed to every time the value was modified). Consider using IsItemDeactivatedAfterEdit() instead!
|
||||
ImGuiInputTextFlags_EscapeClearsAll = 1 << 7, // Escape key clears content if not empty, and deactivate otherwise (contrast to default behavior of Escape to revert)
|
||||
ImGuiInputTextFlags_CtrlEnterForNewLine = 1 << 8, // In multi-line mode, validate with Enter, add new line with Ctrl+Enter (default is opposite: validate with Ctrl+Enter, add line with Enter).
|
||||
ImGuiInputTextFlags_CtrlEnterForNewLine = 1 << 8, // In multi-line mode: validate with Enter, add new line with Ctrl+Enter (default is opposite: validate with Ctrl+Enter, add line with Enter). Note that Shift+Enter always enter a new line either way.
|
||||
|
||||
// Other options
|
||||
ImGuiInputTextFlags_ReadOnly = 1 << 9, // Read-only mode
|
||||
@@ -1339,7 +1356,7 @@ enum ImGuiTreeNodeFlags_
|
||||
ImGuiTreeNodeFlags_DefaultOpen = 1 << 5, // Default node to be open
|
||||
ImGuiTreeNodeFlags_OpenOnDoubleClick = 1 << 6, // Open on double-click instead of simple click (default for multi-select unless any _OpenOnXXX behavior is set explicitly). Both behaviors may be combined.
|
||||
ImGuiTreeNodeFlags_OpenOnArrow = 1 << 7, // Open when clicking on the arrow part (default for multi-select unless any _OpenOnXXX behavior is set explicitly). Both behaviors may be combined.
|
||||
ImGuiTreeNodeFlags_Leaf = 1 << 8, // No collapsing, no arrow (use as a convenience for leaf nodes).
|
||||
ImGuiTreeNodeFlags_Leaf = 1 << 8, // No collapsing, no arrow (use as a convenience for leaf nodes). Note: will always open a tree/id scope and return true. If you never use that scope, add ImGuiTreeNodeFlags_NoTreePushOnOpen.
|
||||
ImGuiTreeNodeFlags_Bullet = 1 << 9, // Display a bullet instead of arrow. IMPORTANT: node can still be marked open/close if you don't set the _Leaf flag!
|
||||
ImGuiTreeNodeFlags_FramePadding = 1 << 10, // Use FramePadding (even for an unframed text node) to vertically align text baseline to regular widget height. Equivalent to calling AlignTextToFramePadding() before the node.
|
||||
ImGuiTreeNodeFlags_SpanAvailWidth = 1 << 11, // Extend hit box to the right-most edge, even if not framed. This is not the default in order to allow adding other items on the same line without using AllowOverlap mode.
|
||||
@@ -1365,21 +1382,14 @@ enum ImGuiTreeNodeFlags_
|
||||
};
|
||||
|
||||
// Flags for OpenPopup*(), BeginPopupContext*(), IsPopupOpen() functions.
|
||||
// - To be backward compatible with older API which took an 'int mouse_button = 1' argument instead of 'ImGuiPopupFlags flags',
|
||||
// we need to treat small flags values as a mouse button index, so we encode the mouse button in the first few bits of the flags.
|
||||
// It is therefore guaranteed to be legal to pass a mouse button index in ImGuiPopupFlags.
|
||||
// - For the same reason, we exceptionally default the ImGuiPopupFlags argument of BeginPopupContextXXX functions to 1 instead of 0.
|
||||
// IMPORTANT: because the default parameter is 1 (==ImGuiPopupFlags_MouseButtonRight), if you rely on the default parameter
|
||||
// and want to use another flag, you need to pass in the ImGuiPopupFlags_MouseButtonRight flag explicitly.
|
||||
// - IMPORTANT: If you ever used the left mouse button with BeginPopupContextXXX() helpers before 1.92.6: Read "API BREAKING CHANGES" 2026/01/07 (1.92.6) entry in imgui.cpp or GitHub topic #9157.
|
||||
// - Multiple buttons currently cannot be combined/or-ed in those functions (we could allow it later).
|
||||
enum ImGuiPopupFlags_
|
||||
{
|
||||
ImGuiPopupFlags_None = 0,
|
||||
ImGuiPopupFlags_MouseButtonLeft = 0, // For BeginPopupContext*(): open on Left Mouse release. Guaranteed to always be == 0 (same as ImGuiMouseButton_Left)
|
||||
ImGuiPopupFlags_MouseButtonRight = 1, // For BeginPopupContext*(): open on Right Mouse release. Guaranteed to always be == 1 (same as ImGuiMouseButton_Right)
|
||||
ImGuiPopupFlags_MouseButtonMiddle = 2, // For BeginPopupContext*(): open on Middle Mouse release. Guaranteed to always be == 2 (same as ImGuiMouseButton_Middle)
|
||||
ImGuiPopupFlags_MouseButtonMask_ = 0x1F,
|
||||
ImGuiPopupFlags_MouseButtonDefault_ = 1,
|
||||
ImGuiPopupFlags_MouseButtonLeft = 1 << 2, // For BeginPopupContext*(): open on Left Mouse release. Only one button allowed!
|
||||
ImGuiPopupFlags_MouseButtonRight = 2 << 2, // For BeginPopupContext*(): open on Right Mouse release. Only one button allowed! (default)
|
||||
ImGuiPopupFlags_MouseButtonMiddle = 3 << 2, // For BeginPopupContext*(): open on Middle Mouse release. Only one button allowed!
|
||||
ImGuiPopupFlags_NoReopen = 1 << 5, // For OpenPopup*(), BeginPopupContext*(): don't reopen same popup if already open (won't reposition, won't reinitialize navigation)
|
||||
//ImGuiPopupFlags_NoReopenAlwaysNavInit = 1 << 6, // For OpenPopup*(), BeginPopupContext*(): focus and initialize navigation even when not reopening.
|
||||
ImGuiPopupFlags_NoOpenOverExistingPopup = 1 << 7, // For OpenPopup*(), BeginPopupContext*(): don't open if there's already a popup at the same level of the popup stack
|
||||
@@ -1387,6 +1397,9 @@ enum ImGuiPopupFlags_
|
||||
ImGuiPopupFlags_AnyPopupId = 1 << 10, // For IsPopupOpen(): ignore the ImGuiID parameter and test for any popup.
|
||||
ImGuiPopupFlags_AnyPopupLevel = 1 << 11, // For IsPopupOpen(): search/test at any level of the popup stack (default test in the current level)
|
||||
ImGuiPopupFlags_AnyPopup = ImGuiPopupFlags_AnyPopupId | ImGuiPopupFlags_AnyPopupLevel,
|
||||
ImGuiPopupFlags_MouseButtonShift_ = 2, // [Internal]
|
||||
ImGuiPopupFlags_MouseButtonMask_ = 0x0C, // [Internal]
|
||||
ImGuiPopupFlags_InvalidMask_ = 0x03, // [Internal] Reserve legacy bits 0-1 to detect incorrectly passing 1 or 2 to the function.
|
||||
};
|
||||
|
||||
// Flags for ImGui::Selectable()
|
||||
@@ -1604,7 +1617,7 @@ enum ImGuiSortDirection : ImU8
|
||||
// All our named keys are >= 512. Keys value 0 to 511 are left unused and were legacy native/opaque key values (< 1.87).
|
||||
// Support for legacy keys was completely removed in 1.91.5.
|
||||
// Read details about the 1.87+ transition : https://github.com/ocornut/imgui/issues/4921
|
||||
// Note that "Keys" related to physical keys and are not the same concept as input "Characters", the later are submitted via io.AddInputCharacter().
|
||||
// Note that "Keys" related to physical keys and are not the same concept as input "Characters", the latter are submitted via io.AddInputCharacter().
|
||||
// The keyboard key enum values are named after the keys on a standard US keyboard, and on other keyboard types the keys reported may not match the keycaps.
|
||||
enum ImGuiKey : int
|
||||
{
|
||||
@@ -1673,10 +1686,10 @@ enum ImGuiKey : int
|
||||
// // XBOX | SWITCH | PLAYSTA. | -> ACTION
|
||||
ImGuiKey_GamepadStart, // Menu | + | Options |
|
||||
ImGuiKey_GamepadBack, // View | - | Share |
|
||||
ImGuiKey_GamepadFaceLeft, // X | Y | Square | Tap: Toggle Menu. Hold: Windowing mode (Focus/Move/Resize windows)
|
||||
ImGuiKey_GamepadFaceLeft, // X | Y | Square | Toggle Menu. Hold for Windowing mode (Focus/Move/Resize windows)
|
||||
ImGuiKey_GamepadFaceRight, // B | A | Circle | Cancel / Close / Exit
|
||||
ImGuiKey_GamepadFaceUp, // Y | X | Triangle | Text Input / On-screen Keyboard
|
||||
ImGuiKey_GamepadFaceDown, // A | B | Cross | Activate / Open / Toggle / Tweak
|
||||
ImGuiKey_GamepadFaceUp, // Y | X | Triangle | Open Context Menu
|
||||
ImGuiKey_GamepadFaceDown, // A | B | Cross | Activate / Open / Toggle. Hold for 0.60f to Activate in Text Input mode (e.g. wired to an on-screen keyboard).
|
||||
ImGuiKey_GamepadDpadLeft, // D-pad Left | " | " | Move / Tweak / Resize Window (in Windowing mode)
|
||||
ImGuiKey_GamepadDpadRight, // D-pad Right | " | " | Move / Tweak / Resize Window (in Windowing mode)
|
||||
ImGuiKey_GamepadDpadUp, // D-pad Up | " | " | Move / Tweak / Resize Window (in Windowing mode)
|
||||
@@ -1761,7 +1774,7 @@ enum ImGuiInputFlags_
|
||||
enum ImGuiConfigFlags_
|
||||
{
|
||||
ImGuiConfigFlags_None = 0,
|
||||
ImGuiConfigFlags_NavEnableKeyboard = 1 << 0, // Master keyboard navigation enable flag. Enable full Tabbing + directional arrows + space/enter to activate.
|
||||
ImGuiConfigFlags_NavEnableKeyboard = 1 << 0, // Master keyboard navigation enable flag. Enable full Tabbing + directional arrows + Space/Enter to activate. Note: some features such as basic Tabbing and CtrL+Tab are enabled by regardless of this flag (and may be disabled via other means, see #4828, #9218).
|
||||
ImGuiConfigFlags_NavEnableGamepad = 1 << 1, // Master gamepad navigation enable flag. Backend also needs to set ImGuiBackendFlags_HasGamepad.
|
||||
ImGuiConfigFlags_NoMouse = 1 << 4, // Instruct dear imgui to disable mouse inputs and interactions.
|
||||
ImGuiConfigFlags_NoMouseCursorChange = 1 << 5, // Instruct backend to not alter mouse cursor shape and visibility. Use if the backend cursor changes are interfering with yours and you don't want to use SetMouseCursor() to change mouse cursor. You may want to honor requests from imgui by reading GetMouseCursor() yourself instead.
|
||||
@@ -1913,6 +1926,7 @@ enum ImGuiStyleVar_
|
||||
ImGuiStyleVar_ScrollbarPadding, // float ScrollbarPadding
|
||||
ImGuiStyleVar_GrabMinSize, // float GrabMinSize
|
||||
ImGuiStyleVar_GrabRounding, // float GrabRounding
|
||||
ImGuiStyleVar_ImageRounding, // float ImageRounding
|
||||
ImGuiStyleVar_ImageBorderSize, // float ImageBorderSize
|
||||
ImGuiStyleVar_TabRounding, // float TabRounding
|
||||
ImGuiStyleVar_TabBorderSize, // float TabBorderSize
|
||||
@@ -1926,6 +1940,7 @@ enum ImGuiStyleVar_
|
||||
ImGuiStyleVar_TreeLinesRounding, // float TreeLinesRounding
|
||||
ImGuiStyleVar_ButtonTextAlign, // ImVec2 ButtonTextAlign
|
||||
ImGuiStyleVar_SelectableTextAlign, // ImVec2 SelectableTextAlign
|
||||
ImGuiStyleVar_SeparatorSize, // float SeparatorSize
|
||||
ImGuiStyleVar_SeparatorTextBorderSize, // float SeparatorTextBorderSize
|
||||
ImGuiStyleVar_SeparatorTextAlign, // ImVec2 SeparatorTextAlign
|
||||
ImGuiStyleVar_SeparatorTextPadding, // ImVec2 SeparatorTextPadding
|
||||
@@ -1956,19 +1971,20 @@ enum ImGuiColorEditFlags_
|
||||
ImGuiColorEditFlags_NoTooltip = 1 << 6, // // ColorEdit, ColorPicker, ColorButton: disable tooltip when hovering the preview.
|
||||
ImGuiColorEditFlags_NoLabel = 1 << 7, // // ColorEdit, ColorPicker: disable display of inline text label (the label is still forwarded to the tooltip and picker).
|
||||
ImGuiColorEditFlags_NoSidePreview = 1 << 8, // // ColorPicker: disable bigger color preview on right side of the picker, use small color square preview instead.
|
||||
ImGuiColorEditFlags_NoDragDrop = 1 << 9, // // ColorEdit: disable drag and drop target. ColorButton: disable drag and drop source.
|
||||
ImGuiColorEditFlags_NoDragDrop = 1 << 9, // // ColorEdit: disable drag and drop target/source. ColorButton: disable drag and drop source.
|
||||
ImGuiColorEditFlags_NoBorder = 1 << 10, // // ColorButton: disable border (which is enforced by default)
|
||||
ImGuiColorEditFlags_NoColorMarkers = 1 << 11, // // ColorEdit: disable rendering R/G/B/A color marker. May also be disabled globally by setting style.ColorMarkerSize = 0.
|
||||
|
||||
// Alpha preview
|
||||
// - Prior to 1.91.8 (2025/01/21): alpha was made opaque in the preview by default using old name ImGuiColorEditFlags_AlphaPreview.
|
||||
// - We now display the preview as transparent by default. You can use ImGuiColorEditFlags_AlphaOpaque to use old behavior.
|
||||
// - The new flags may be combined better and allow finer controls.
|
||||
ImGuiColorEditFlags_AlphaOpaque = 1 << 11, // // ColorEdit, ColorPicker, ColorButton: disable alpha in the preview,. Contrary to _NoAlpha it may still be edited when calling ColorEdit4()/ColorPicker4(). For ColorButton() this does the same as _NoAlpha.
|
||||
ImGuiColorEditFlags_AlphaNoBg = 1 << 12, // // ColorEdit, ColorPicker, ColorButton: disable rendering a checkerboard background behind transparent color.
|
||||
ImGuiColorEditFlags_AlphaPreviewHalf= 1 << 13, // // ColorEdit, ColorPicker, ColorButton: display half opaque / half transparent preview.
|
||||
ImGuiColorEditFlags_AlphaOpaque = 1 << 12, // // ColorEdit, ColorPicker, ColorButton: disable alpha in the preview,. Contrary to _NoAlpha it may still be edited when calling ColorEdit4()/ColorPicker4(). For ColorButton() this does the same as _NoAlpha.
|
||||
ImGuiColorEditFlags_AlphaNoBg = 1 << 13, // // ColorEdit, ColorPicker, ColorButton: disable rendering a checkerboard background behind transparent color.
|
||||
ImGuiColorEditFlags_AlphaPreviewHalf= 1 << 14, // // ColorEdit, ColorPicker, ColorButton: display half opaque / half transparent preview.
|
||||
|
||||
// User Options (right-click on widget to change some of them).
|
||||
ImGuiColorEditFlags_AlphaBar = 1 << 16, // // ColorEdit, ColorPicker: show vertical alpha bar/gradient in picker.
|
||||
ImGuiColorEditFlags_AlphaBar = 1 << 18, // // ColorEdit, ColorPicker: show vertical alpha bar/gradient in picker.
|
||||
ImGuiColorEditFlags_HDR = 1 << 19, // // (WIP) ColorEdit: Currently only disable 0.0f..1.0f limits in RGBA edition (note: you probably want to use ImGuiColorEditFlags_Float flag as well).
|
||||
ImGuiColorEditFlags_DisplayRGB = 1 << 20, // [Display] // ColorEdit: override _display_ type among RGB/HSV/Hex. ColorPicker: select any combination using one or more of RGB/HSV/Hex.
|
||||
ImGuiColorEditFlags_DisplayHSV = 1 << 21, // [Display] // "
|
||||
@@ -2011,8 +2027,9 @@ enum ImGuiSliderFlags_
|
||||
ImGuiSliderFlags_ClampOnInput = 1 << 9, // Clamp value to min/max bounds when input manually with Ctrl+Click. By default Ctrl+Click allows going out of bounds.
|
||||
ImGuiSliderFlags_ClampZeroRange = 1 << 10, // Clamp even if min==max==0.0f. Otherwise due to legacy reason DragXXX functions don't clamp with those values. When your clamping limits are dynamic you almost always want to use it.
|
||||
ImGuiSliderFlags_NoSpeedTweaks = 1 << 11, // Disable keyboard modifiers altering tweak speed. Useful if you want to alter tweak speed yourself based on your own logic.
|
||||
ImGuiSliderFlags_ColorMarkers = 1 << 12, // DragScalarN(), SliderScalarN(): Draw R/G/B/A color markers on each component.
|
||||
ImGuiSliderFlags_AlwaysClamp = ImGuiSliderFlags_ClampOnInput | ImGuiSliderFlags_ClampZeroRange,
|
||||
ImGuiSliderFlags_InvalidMask_ = 0x7000000F, // [Internal] We treat using those bits as being potentially a 'float power' argument from the previous API that has got miscast to this enum, and will trigger an assert if needed.
|
||||
ImGuiSliderFlags_InvalidMask_ = 0x7000000F, // [Internal] We treat using those bits as being potentially a 'float power' argument from legacy API (obsoleted 2020-08) that has got miscast to this enum, and will trigger an assert if needed.
|
||||
};
|
||||
|
||||
// Identify a mouse button.
|
||||
@@ -2102,7 +2119,7 @@ enum ImGuiTableFlags_
|
||||
ImGuiTableFlags_Reorderable = 1 << 1, // Enable reordering columns in header row (need calling TableSetupColumn() + TableHeadersRow() to display headers)
|
||||
ImGuiTableFlags_Hideable = 1 << 2, // Enable hiding/disabling columns in context menu.
|
||||
ImGuiTableFlags_Sortable = 1 << 3, // Enable sorting. Call TableGetSortSpecs() to obtain sort specs. Also see ImGuiTableFlags_SortMulti and ImGuiTableFlags_SortTristate.
|
||||
ImGuiTableFlags_NoSavedSettings = 1 << 4, // Disable persisting columns order, width and sort settings in the .ini file.
|
||||
ImGuiTableFlags_NoSavedSettings = 1 << 4, // Disable persisting columns order, width, visibility and sort settings in the .ini file.
|
||||
ImGuiTableFlags_ContextMenuInBody = 1 << 5, // Right-click on columns body/contents will display table context menu. By default it is available in TableHeadersRow().
|
||||
// Decorations
|
||||
ImGuiTableFlags_RowBg = 1 << 6, // Set each RowBg color with ImGuiCol_TableRowBg or ImGuiCol_TableRowBgAlt (equivalent of calling TableSetBgColor with ImGuiTableBgFlags_RowBg0 on each row manually)
|
||||
@@ -2218,7 +2235,7 @@ struct ImGuiTableSortSpecs
|
||||
int SpecsCount; // Sort spec count. Most often 1. May be > 1 when ImGuiTableFlags_SortMulti is enabled. May be == 0 when ImGuiTableFlags_SortTristate is enabled.
|
||||
bool SpecsDirty; // Set to true when specs have changed since last time! Use this to sort again, then clear the flag.
|
||||
|
||||
ImGuiTableSortSpecs() { memset(this, 0, sizeof(*this)); }
|
||||
ImGuiTableSortSpecs() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
// Sorting specification for one column of a table (sizeof == 12 bytes)
|
||||
@@ -2229,7 +2246,7 @@ struct ImGuiTableColumnSortSpecs
|
||||
ImS16 SortOrder; // Index within parent ImGuiTableSortSpecs (always stored in order starting from 0, tables sorted on a single criteria will always have a 0 here)
|
||||
ImGuiSortDirection SortDirection; // ImGuiSortDirection_Ascending or ImGuiSortDirection_Descending
|
||||
|
||||
ImGuiTableColumnSortSpecs() { memset(this, 0, sizeof(*this)); }
|
||||
ImGuiTableColumnSortSpecs() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -2352,7 +2369,7 @@ struct ImGuiStyle
|
||||
// - recap: ImGui::GetFontSize() == FontSizeBase * (FontScaleMain * FontScaleDpi * other_scaling_factors)
|
||||
float FontSizeBase; // Current base font size before external global factors are applied. Use PushFont(NULL, size) to modify. Use ImGui::GetFontSize() to obtain scaled value.
|
||||
float FontScaleMain; // Main global scale factor. May be set by application once, or exposed to end-user.
|
||||
float FontScaleDpi; // Additional global scale factor from viewport/monitor contents scale. When io.ConfigDpiScaleFonts is enabled, this is automatically overwritten when changing monitor DPI.
|
||||
float FontScaleDpi; // Additional global scale factor from viewport/monitor contents scale. In docking branch: when io.ConfigDpiScaleFonts is enabled, this is automatically overwritten when changing monitor DPI.
|
||||
|
||||
float Alpha; // Global alpha applies to everything in Dear ImGui.
|
||||
float DisabledAlpha; // Additional alpha multiplier applied by BeginDisabled(). Multiply over current value of Alpha.
|
||||
@@ -2382,6 +2399,7 @@ struct ImGuiStyle
|
||||
float GrabMinSize; // Minimum width/height of a grab box for slider/scrollbar.
|
||||
float GrabRounding; // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs.
|
||||
float LogSliderDeadzone; // The size in pixels of the dead-zone around zero on logarithmic sliders that cross zero.
|
||||
float ImageRounding; // Rounding of Image() calls.
|
||||
float ImageBorderSize; // Thickness of border around Image() calls.
|
||||
float TabRounding; // Radius of upper corners of a tab. Set to 0.0f to have rectangular tabs.
|
||||
float TabBorderSize; // Thickness of border around tabs.
|
||||
@@ -2399,9 +2417,11 @@ struct ImGuiStyle
|
||||
float DragDropTargetRounding; // Radius of the drag and drop target frame.
|
||||
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 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.
|
||||
@@ -2432,7 +2452,7 @@ struct ImGuiStyle
|
||||
ImGuiHoveredFlags HoverFlagsForTooltipNav; // Default flags when using IsItemHovered(ImGuiHoveredFlags_ForTooltip) or BeginItemTooltip()/SetItemTooltip() while using keyboard/gamepad.
|
||||
|
||||
// [Internal]
|
||||
float _MainScale; // FIXME-WIP: Reference scale, as applied by ScaleAllSizes().
|
||||
float _MainScale; // FIXME-WIP: Reference scale, as applied by ScaleAllSizes(). PLEASE DO NOT USE THIS FOR NOW.
|
||||
float _NextFrameFontSizeBase; // FIXME: Temporary hack until we finish remaining work.
|
||||
|
||||
// Functions
|
||||
@@ -2522,7 +2542,7 @@ struct ImGuiIO
|
||||
bool ConfigMacOSXBehaviors; // = defined(__APPLE__) // Swap Cmd<>Ctrl keys + OS X style text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl.
|
||||
bool ConfigInputTrickleEventQueue; // = true // Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates.
|
||||
bool ConfigInputTextCursorBlink; // = true // Enable blinking cursor (optional as some users consider it to be distracting).
|
||||
bool ConfigInputTextEnterKeepActive; // = false // [BETA] Pressing Enter will keep item active and select contents (single-line only).
|
||||
bool ConfigInputTextEnterKeepActive; // = false // [BETA] Pressing Enter will reactivate item and select all text (single-line only).
|
||||
bool ConfigDragClickToInputText; // = false // [BETA] Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving). Not desirable on devices without a keyboard.
|
||||
bool ConfigWindowsResizeFromEdges; // = true // Enable resizing of windows from their edges and from the lower-left corner. This requires ImGuiBackendFlags_HasMouseCursors for better mouse cursor feedback. (This used to be a per-window ImGuiWindowFlags_ResizeFromAnySide flag)
|
||||
bool ConfigWindowsMoveFromTitleBarOnly; // = false // Enable allowing to move windows only when clicking on their title bar. Does not apply to windows without a title bar.
|
||||
@@ -2544,7 +2564,7 @@ struct ImGuiIO
|
||||
|
||||
// Options to configure Error Handling and how we handle recoverable errors [EXPERIMENTAL]
|
||||
// - Error recovery is provided as a way to facilitate:
|
||||
// - Recovery after a programming error (native code or scripting language - the later tends to facilitate iterating on code while running).
|
||||
// - Recovery after a programming error (native code or scripting language - the latter tends to facilitate iterating on code while running).
|
||||
// - Recovery after running an exception handler or any error processing which may skip code after an error has been detected.
|
||||
// - Error recovery is not perfect nor guaranteed! It is a feature to ease development.
|
||||
// You not are not supposed to rely on it in the course of a normal application run.
|
||||
@@ -2736,18 +2756,20 @@ 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
|
||||
|
||||
// Arguments for the different callback events
|
||||
// - During Resize callback, Buf will be same as your input buffer.
|
||||
// - However, during Completion/History/Always callback, Buf always points to our own internal data (it is not the same as your buffer)! Changes to it will be reflected into your own buffer shortly after the callback.
|
||||
// - To modify the text buffer in a callback, prefer using the InsertChars() / DeleteChars() function. InsertChars() will take care of calling the resize callback if necessary.
|
||||
// - If you know your edits are not going to resize the underlying buffer allocation, you may modify the contents of 'Buf[]' directly. You need to update 'BufTextLen' accordingly (0 <= BufTextLen < BufSize) and set 'BufDirty'' to true so InputText can update its internal state.
|
||||
ImWchar EventChar; // Character input // Read-write // [CharFilter] Replace character with another one, or set to zero to drop. return 1 is equivalent to setting EventChar=0;
|
||||
ImGuiKey EventKey; // Key pressed (Up/Down/TAB) // Read-only // [Completion,History]
|
||||
ImWchar EventChar; // Character input // Read-write // [CharFilter] Replace character with another one, or set to zero to drop. return 1 is equivalent to setting EventChar=0;
|
||||
bool EventActivated; // Input field just got activated // Read-only // [Always]
|
||||
bool BufDirty; // Set if you modify Buf/BufTextLen! // Write // [Completion,History,Always]
|
||||
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
|
||||
bool BufDirty; // Set if you modify Buf/BufTextLen! // Write // [Completion,History,Always]
|
||||
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]
|
||||
@@ -2757,9 +2779,10 @@ struct ImGuiInputTextCallbackData
|
||||
IMGUI_API ImGuiInputTextCallbackData();
|
||||
IMGUI_API void DeleteChars(int pos, int bytes_count);
|
||||
IMGUI_API void InsertChars(int pos, const char* text, const char* text_end = NULL);
|
||||
void SelectAll() { SelectionStart = 0; SelectionEnd = BufTextLen; }
|
||||
void ClearSelection() { SelectionStart = SelectionEnd = BufTextLen; }
|
||||
bool HasSelection() const { return SelectionStart != SelectionEnd; }
|
||||
void SelectAll() { SelectionStart = 0; CursorPos = SelectionEnd = BufTextLen; }
|
||||
void SetSelection(int s, int e) { IM_ASSERT(s >= 0 && s <= BufTextLen); IM_ASSERT(e >= 0 && e <= BufTextLen); SelectionStart = s; CursorPos = SelectionEnd = e; }
|
||||
void ClearSelection() { SelectionStart = SelectionEnd = BufTextLen; }
|
||||
bool HasSelection() const { return SelectionStart != SelectionEnd; }
|
||||
};
|
||||
|
||||
// Resizing callback data to apply custom constraint. As enabled by SetNextWindowSizeConstraints(). Callback is called during the next Begin().
|
||||
@@ -2791,7 +2814,7 @@ struct ImGuiWindowClass
|
||||
bool DockingAlwaysTabBar; // Set to true to enforce single floating windows of this class always having their own docking node (equivalent of setting the global io.ConfigDockingAlwaysTabBar)
|
||||
bool DockingAllowUnclassed; // Set to true to allow windows of this class to be docked/merged with an unclassed window. // FIXME-DOCK: Move to DockNodeFlags override?
|
||||
|
||||
ImGuiWindowClass() { memset(this, 0, sizeof(*this)); ParentViewportId = (ImGuiID)-1; DockingAllowUnclassed = true; }
|
||||
ImGuiWindowClass() { memset((void*)this, 0, sizeof(*this)); ParentViewportId = (ImGuiID)-1; DockingAllowUnclassed = true; }
|
||||
};
|
||||
|
||||
// Data payload for Drag and Drop operations: AcceptDragDropPayload(), GetDragDropPayload()
|
||||
@@ -2972,6 +2995,7 @@ struct ImGuiListClipper
|
||||
ImGuiContext* Ctx; // Parent UI context
|
||||
int DisplayStart; // First item to display, updated by each call to Step()
|
||||
int DisplayEnd; // End of items to display (exclusive)
|
||||
int UserIndex; // Helper storage for user convenience/code. Optional, and otherwise unused if you don't use it.
|
||||
int ItemsCount; // [Internal] Number of items
|
||||
float ItemsHeight; // [Internal] Height of item after a first step and item submission can calculate it
|
||||
double StartPosY; // [Internal] Cursor position at the time of Begin() or after table frozen rows are all processed
|
||||
@@ -3000,7 +3024,7 @@ struct ImGuiListClipper
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
//inline void IncludeRangeByIndices(int item_begin, int item_end) { IncludeItemsByIndex(item_begin, item_end); } // [renamed in 1.89.9]
|
||||
//inline void ForceDisplayRangeByIndices(int item_begin, int item_end) { IncludeItemsByIndex(item_begin, item_end); } // [renamed in 1.89.6]
|
||||
//inline ImGuiListClipper(int items_count, float items_height = -1.0f) { memset(this, 0, sizeof(*this)); ItemsCount = -1; Begin(items_count, items_height); } // [removed in 1.79]
|
||||
//inline ImGuiListClipper(int items_count, float items_height = -1.0f) { memset((void*)this, 0, sizeof(*this)); ItemsCount = -1; Begin(items_count, items_height); } // [removed in 1.79]
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -3285,7 +3309,7 @@ struct ImDrawCmd
|
||||
int UserCallbackDataSize; // 4 // Size of callback user data when using storage, otherwise 0.
|
||||
int UserCallbackDataOffset;// 4 // [Internal] Offset of callback user data when using storage, otherwise -1.
|
||||
|
||||
ImDrawCmd() { memset(this, 0, sizeof(*this)); } // Also ensure our padding fields are zeroed
|
||||
ImDrawCmd() { memset((void*)this, 0, sizeof(*this)); } // Also ensure our padding fields are zeroed
|
||||
|
||||
// Since 1.83: returns ImTextureID associated with this draw call. Warning: DO NOT assume this is always same as 'TextureId' (we will change this function for an upcoming feature)
|
||||
// Since 1.92: removed ImDrawCmd::TextureId field, the getter function must be used!
|
||||
@@ -3331,7 +3355,7 @@ struct ImDrawListSplitter
|
||||
int _Count; // Number of active channels (1+)
|
||||
ImVector<ImDrawChannel> _Channels; // Draw channels (not resized down so _Count might be < Channels.Size)
|
||||
|
||||
inline ImDrawListSplitter() { memset(this, 0, sizeof(*this)); }
|
||||
inline ImDrawListSplitter() { memset((void*)this, 0, sizeof(*this)); }
|
||||
inline ~ImDrawListSplitter() { ClearFreeMemory(); }
|
||||
inline void Clear() { _Current = 0; _Count = 1; } // Do not clear Channels[] so our allocations are reused next frame
|
||||
IMGUI_API void ClearFreeMemory();
|
||||
@@ -3642,7 +3666,7 @@ struct ImTextureData
|
||||
bool WantDestroyNextFrame; // rw - // [Internal] Queued to set ImTextureStatus_WantDestroy next frame. May still be used in the current frame.
|
||||
|
||||
// Functions
|
||||
ImTextureData() { memset(this, 0, sizeof(*this)); Status = ImTextureStatus_Destroyed; TexID = ImTextureID_Invalid; }
|
||||
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);
|
||||
IMGUI_API void DestroyPixels();
|
||||
@@ -3657,7 +3681,7 @@ struct ImTextureData
|
||||
// - Call SetTexID() and SetStatus() after honoring texture requests. Never modify TexID and Status directly!
|
||||
// - A backend may decide to destroy a texture that we did not request to destroy, which is fine (e.g. freeing resources), but we immediately set the texture back in _WantCreate mode.
|
||||
void SetTexID(ImTextureID tex_id) { TexID = tex_id; }
|
||||
void SetStatus(ImTextureStatus status) { Status = status; if (status == ImTextureStatus_Destroyed && !WantDestroyNextFrame) Status = ImTextureStatus_WantCreate; }
|
||||
void SetStatus(ImTextureStatus status) { Status = status; if (status == ImTextureStatus_Destroyed && !WantDestroyNextFrame && Pixels != nullptr) Status = ImTextureStatus_WantCreate; }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -3689,16 +3713,15 @@ struct ImFontConfig
|
||||
char Name[40]; // <auto> // Name (strictly to ease debugging, hence limited size buffer)
|
||||
void* FontData; // // TTF/OTF data
|
||||
int FontDataSize; // // TTF/OTF data size
|
||||
bool FontDataOwnedByAtlas; // true // TTF/OTF data ownership taken by the owner ImFontAtlas (will delete memory itself).
|
||||
bool FontDataOwnedByAtlas; // true // TTF/OTF data ownership taken by the owner ImFontAtlas (will delete memory itself). SINCE 1.92, THE DATA NEEDS TO PERSIST FOR WHOLE DURATION OF ATLAS.
|
||||
|
||||
// Options
|
||||
bool MergeMode; // false // Merge into previous ImFont, so you can combine multiple inputs font into one ImFont (e.g. ASCII font + icons + Japanese glyphs). You may want to use GlyphOffset.y when merge font of different heights.
|
||||
bool PixelSnapH; // false // Align every glyph AdvanceX to pixel boundaries. Useful e.g. if you are merging a non-pixel aligned font with the default font. If enabled, you can set OversampleH/V to 1.
|
||||
bool PixelSnapV; // true // Align Scaled GlyphOffset.y to pixel boundaries.
|
||||
bool PixelSnapH; // false // Align every glyph AdvanceX to pixel boundaries. Prevents fractional font size from working correctly! Useful e.g. if you are merging a non-pixel aligned font with the default font. If enabled, OversampleH/V will default to 1.
|
||||
ImS8 OversampleH; // 0 (2) // Rasterize at higher quality for sub-pixel positioning. 0 == auto == 1 or 2 depending on size. Note the difference between 2 and 3 is minimal. You can reduce this to 1 for large glyphs save memory. Read https://github.com/nothings/stb/blob/master/tests/oversample/README.md for details.
|
||||
ImS8 OversampleV; // 0 (1) // Rasterize at higher quality for sub-pixel positioning. 0 == auto == 1. This is not really useful as we don't use sub-pixel positions on the Y axis.
|
||||
ImWchar EllipsisChar; // 0 // Explicitly specify Unicode codepoint of ellipsis character. When fonts are being merged first specified ellipsis will be used.
|
||||
float SizePixels; // // Size in pixels for rasterizer (more or less maps to the resulting font height).
|
||||
float SizePixels; // // Output size in pixels for rasterizer (more or less maps to the resulting font height).
|
||||
const ImWchar* GlyphRanges; // NULL // *LEGACY* THE ARRAY DATA NEEDS TO PERSIST AS LONG AS THE FONT IS ALIVE. Pointer to a user-provided list of Unicode range (2 value per range, values are inclusive, zero-terminated list).
|
||||
const ImWchar* GlyphExcludeRanges; // NULL // Pointer to a small user-provided list of Unicode ranges (2 value per range, values are inclusive, zero-terminated list). This is very close to GlyphRanges[] but designed to exclude ranges from a font source, when merging fonts with overlapping glyphs. Use "Input Glyphs Overlap Detection Tool" to find about your overlapping ranges.
|
||||
//ImVec2 GlyphExtraSpacing; // 0, 0 // (REMOVED AT IT SEEMS LARGELY OBSOLETE. PLEASE REPORT IF YOU WERE USING THIS). Extra spacing (in pixels) between glyphs when rendered: essentially add to glyph->AdvanceX. Only X axis is supported for now.
|
||||
@@ -3708,9 +3731,10 @@ struct ImFontConfig
|
||||
float GlyphExtraAdvanceX; // 0 // Extra spacing (in pixels) between glyphs. Please contact us if you are using this. // FIXME-NEWATLAS: Intentionally unscaled
|
||||
ImU32 FontNo; // 0 // Index of font within TTF/OTF file
|
||||
unsigned int FontLoaderFlags; // 0 // Settings for custom font builder. THIS IS BUILDER IMPLEMENTATION DEPENDENT. Leave as zero if unsure.
|
||||
//unsigned int FontBuilderFlags; // -- // [Renamed in 1.92] Ue FontLoaderFlags.
|
||||
//unsigned int FontBuilderFlags; // -- // [Renamed in 1.92] Use FontLoaderFlags.
|
||||
float RasterizerMultiply; // 1.0f // Linearly brighten (>1.0f) or darken (<1.0f) font output. Brightening small fonts may be a good workaround to make them more readable. This is a silly thing we may remove in the future.
|
||||
float RasterizerDensity; // 1.0f // [LEGACY: this only makes sense when ImGuiBackendFlags_RendererHasTextures is not supported] DPI scale multiplier for rasterization. Not altering other font metrics: makes it easy to swap between e.g. a 100% and a 400% fonts for a zooming display, or handle Retina screen. IMPORTANT: If you change this it is expected that you increase/decrease font scale roughly to the inverse of this, otherwise quality may look lowered.
|
||||
float ExtraSizeScale; // 1.0f // Extra rasterizer scale over SizePixels.
|
||||
|
||||
// [Internal]
|
||||
ImFontFlags Flags; // Font flags (don't use just yet, will be exposed in upcoming 1.92.X updates)
|
||||
@@ -3718,6 +3742,9 @@ struct ImFontConfig
|
||||
const ImFontLoader* FontLoader; // Custom font backend for this source (default source is the one stored in ImFontAtlas)
|
||||
void* FontLoaderData; // Font loader opaque storage (per font config)
|
||||
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
bool PixelSnapV; // true // [Obsoleted in 1.91.6] Align Scaled GlyphOffset.y to pixel boundaries.
|
||||
#endif
|
||||
IMGUI_API ImFontConfig();
|
||||
};
|
||||
|
||||
@@ -3734,7 +3761,7 @@ struct ImFontGlyph
|
||||
float U0, V0, U1, V1; // Texture coordinates for the current value of ImFontAtlas->TexRef. Cached equivalent of calling GetCustomRect() with PackId.
|
||||
int PackId; // [Internal] ImFontAtlasRectId value (FIXME: Cold data, could be moved elsewhere?)
|
||||
|
||||
ImFontGlyph() { memset(this, 0, sizeof(*this)); PackId = -1; }
|
||||
ImFontGlyph() { memset((void*)this, 0, sizeof(*this)); PackId = -1; }
|
||||
};
|
||||
|
||||
// Helper to build glyph ranges from text/string data. Feed your application strings/characters to it then call BuildRanges().
|
||||
@@ -3767,7 +3794,7 @@ struct ImFontAtlasRect
|
||||
unsigned short w, h; // Size
|
||||
ImVec2 uv0, uv1; // UV coordinates (in current texture)
|
||||
|
||||
ImFontAtlasRect() { memset(this, 0, sizeof(*this)); }
|
||||
ImFontAtlasRect() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
// Flags for ImFontAtlas build
|
||||
@@ -3792,7 +3819,7 @@ enum ImFontAtlasFlags_
|
||||
// - Call Build() + GetTexDataAsAlpha8() or GetTexDataAsRGBA32() to build and retrieve pixels data.
|
||||
// - Call SetTexID(my_tex_id); and pass the pointer/identifier to your texture in a format natural to your graphics API.
|
||||
// Common pitfalls:
|
||||
// - If you pass a 'glyph_ranges' array to AddFont*** functions, you need to make sure that your array persist up until the
|
||||
// - If you pass a 'glyph_ranges' array to AddFont*** functions, you need to make sure that your array persists up until the
|
||||
// atlas is build (when calling GetTexData*** or Build()). We only copy the pointer, not the data.
|
||||
// - Important: By default, AddFontFromMemoryTTF() takes ownership of the data. Even though we are not writing to it, we will free the pointer on destruction.
|
||||
// You can set font_cfg->FontDataOwnedByAtlas=false to keep ownership of your data and it won't be freed,
|
||||
@@ -3803,7 +3830,9 @@ struct ImFontAtlas
|
||||
IMGUI_API ImFontAtlas();
|
||||
IMGUI_API ~ImFontAtlas();
|
||||
IMGUI_API ImFont* AddFont(const ImFontConfig* font_cfg);
|
||||
IMGUI_API ImFont* AddFontDefault(const ImFontConfig* font_cfg = NULL);
|
||||
IMGUI_API ImFont* AddFontDefault(const ImFontConfig* font_cfg = NULL); // Selects between AddFontDefaultVector() and AddFontDefaultBitmap().
|
||||
IMGUI_API ImFont* AddFontDefaultVector(const ImFontConfig* font_cfg = NULL); // Embedded scalable font. Recommended at any higher size.
|
||||
IMGUI_API ImFont* AddFontDefaultBitmap(const ImFontConfig* font_cfg = NULL); // Embedded classic pixel-clean font. Recommended at Size 13px with no scaling.
|
||||
IMGUI_API ImFont* AddFontFromFileTTF(const char* filename, float size_pixels = 0.0f, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL);
|
||||
IMGUI_API ImFont* AddFontFromMemoryTTF(void* font_data, int font_data_size, float size_pixels = 0.0f, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // Note: Transfer ownership of 'ttf_data' to ImFontAtlas! Will be deleted after destruction of the atlas. Set font_cfg->FontDataOwnedByAtlas=false to keep ownership of your data and it won't be freed.
|
||||
IMGUI_API ImFont* AddFontFromMemoryCompressedTTF(const void* compressed_font_data, int compressed_font_data_size, float size_pixels = 0.0f, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data' still owned by caller. Compress with binary_to_compressed_c.cpp.
|
||||
@@ -3970,7 +3999,7 @@ struct ImFontBaked
|
||||
unsigned int MetricsTotalSurface:26;// 3 // out // Total surface in pixels to get an idea of the font rasterization/texture cost (not exact, we approximate the cost of padding between glyphs)
|
||||
unsigned int WantDestroy:1; // 0 // // Queued for destroy
|
||||
unsigned int LoadNoFallback:1; // 0 // // Disable loading fallback in lower-level calls.
|
||||
unsigned int LoadNoRenderOnLayout:1;// 0 // // Enable a two-steps mode where CalcTextSize() calls will load AdvanceX *without* rendering/packing glyphs. Only advantagous if you know that the glyph is unlikely to actually be rendered, otherwise it is slower because we'd do one query on the first CalcTextSize and one query on the first Draw.
|
||||
unsigned int LoadNoRenderOnLayout:1;// 0 // // Enable a two-steps mode where CalcTextSize() calls will load AdvanceX *without* rendering/packing glyphs. Only advantageous if you know that the glyph is unlikely to actually be rendered, otherwise it is slower because we'd do one query on the first CalcTextSize and one query on the first Draw.
|
||||
int LastUsedFrame; // 4 // // Record of that time this was bounds
|
||||
ImGuiID BakedId; // 4 // // Unique ID for this baked storage
|
||||
ImFont* OwnerFont; // 4-8 // in // Parent font
|
||||
@@ -4013,10 +4042,10 @@ struct ImFont
|
||||
ImGuiID FontId; // Unique identifier for the font
|
||||
float LegacySize; // 4 // in // Font size passed to AddFont(). Use for old code calling PushFont() expecting to use that size. (use ImGui::GetFontBaked() to get font baked at current bound size).
|
||||
ImVector<ImFontConfig*> Sources; // 16 // in // List of sources. Pointers within OwnerAtlas->Sources[]
|
||||
ImWchar EllipsisChar; // 2-4 // out // Character used for ellipsis rendering ('...').
|
||||
ImWchar EllipsisChar; // 2-4 // out // Character used for ellipsis rendering ('...'). If you ever want to temporarily swap this for an alternative/dummy char, make sure to clear EllipsisAutoBake.
|
||||
ImWchar FallbackChar; // 2-4 // out // Character used if a glyph isn't found (U+FFFD, '?')
|
||||
ImU8 Used8kPagesMap[(IM_UNICODE_CODEPOINT_MAX+1)/8192/8]; // 1 bytes if ImWchar=ImWchar16, 16 bytes if ImWchar==ImWchar32. Store 1-bit for each block of 4K codepoints that has one active glyph. This is mainly used to facilitate iterations across all used codepoints.
|
||||
bool EllipsisAutoBake; // 1 // // Mark when the "..." glyph needs to be generated.
|
||||
ImU8 Used8kPagesMap[(IM_UNICODE_CODEPOINT_MAX+1)/8192/8]; // 1 bytes if ImWchar=ImWchar16, 17 bytes if ImWchar==ImWchar32. Store 1-bit for each block of 8K codepoints that has one active glyph. This is mainly used to facilitate iterations across all used codepoints.
|
||||
bool EllipsisAutoBake; // 1 // // Mark when the "..." glyph (== EllipsisChar) needs to be generated by combining multiple '.'.
|
||||
ImGuiStorage RemapPairs; // 16 // // Remapping pairs when using AddRemapChar(), otherwise empty.
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
float Scale; // 4 // in // Legacy base font scale (~1.0f), multiplied by the per-window font scale which you can adjust with SetWindowFontScale()
|
||||
@@ -4057,8 +4086,10 @@ inline ImTextureID ImTextureRef::GetTexID() const
|
||||
// Using an indirection to avoid patching ImDrawCmd after a SetTexID() call (but this could be an alternative solution too)
|
||||
inline ImTextureID ImDrawCmd::GetTexID() const
|
||||
{
|
||||
// If you are getting this assert: A renderer backend with support for ImGuiBackendFlags_RendererHasTextures (1.92)
|
||||
// must iterate and handle ImTextureData requests stored in ImDrawData::Textures[].
|
||||
// If you are getting this assert with ImTextureID_Invalid == 0 and your ImTextureID is used to store an index:
|
||||
// - You can add '#define ImTextureID_Invalid ((ImTextureID)-1)' in your imconfig file.
|
||||
// If you are getting this assert with a renderer backend with support for ImGuiBackendFlags_RendererHasTextures (1.92+):
|
||||
// - You must correctly iterate and handle ImTextureData requests stored in ImDrawData::Textures[]. See docs/BACKENDS.md.
|
||||
ImTextureID tex_id = TexRef._TexData ? TexRef._TexData->TexID : TexRef._TexID; // == TexRef.GetTexID() above.
|
||||
if (TexRef._TexData != NULL)
|
||||
IM_ASSERT(tex_id != ImTextureID_Invalid && "ImDrawCmd is referring to ImTextureData that wasn't uploaded to graphics system. Backend must call ImTextureData::SetTexID() after handling ImTextureStatus_WantCreate request!");
|
||||
@@ -4126,7 +4157,7 @@ struct ImGuiViewport
|
||||
bool PlatformRequestResize; // Platform window requested resize (e.g. window was resized by the OS / host window manager, authoritative size will be OS window size)
|
||||
bool PlatformRequestClose; // Platform window requested closure (e.g. window was moved by the OS / host window manager, e.g. pressing ALT-F4)
|
||||
|
||||
ImGuiViewport() { memset(this, 0, sizeof(*this)); }
|
||||
ImGuiViewport() { memset((void*)this, 0, sizeof(*this)); }
|
||||
~ImGuiViewport() { IM_ASSERT(PlatformUserData == NULL && RendererUserData == NULL); }
|
||||
|
||||
// Helpers
|
||||
@@ -4195,7 +4226,7 @@ struct ImGuiPlatformIO
|
||||
|
||||
// Optional: Access OS clipboard
|
||||
// (default to use native Win32 clipboard on Windows, otherwise uses a private clipboard. Override to access OS clipboard on other architectures)
|
||||
const char* (*Platform_GetClipboardTextFn)(ImGuiContext* ctx);
|
||||
const char* (*Platform_GetClipboardTextFn)(ImGuiContext* ctx); // Should return NULL on failure (e.g. clipboard data is not text).
|
||||
void (*Platform_SetClipboardTextFn)(ImGuiContext* ctx, const char* text);
|
||||
void* Platform_ClipboardUserData;
|
||||
|
||||
@@ -4315,7 +4346,7 @@ struct ImGuiPlatformImeData
|
||||
float InputLineHeight; // Line height (for IME).
|
||||
ImGuiID ViewportId; // ID of platform window/viewport.
|
||||
|
||||
ImGuiPlatformImeData() { memset(this, 0, sizeof(*this)); }
|
||||
ImGuiPlatformImeData() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -4337,19 +4368,20 @@ namespace ImGui
|
||||
inline void PopButtonRepeat() { PopItemFlag(); }
|
||||
inline void PushTabStop(bool tab_stop) { PushItemFlag(ImGuiItemFlags_NoTabStop, !tab_stop); }
|
||||
inline void PopTabStop() { PopItemFlag(); }
|
||||
// You do not need those functions! See #7838 on GitHub for more info.
|
||||
IMGUI_API ImVec2 GetContentRegionMax(); // Content boundaries max (e.g. window boundaries including scrolling, or current column boundaries). You should never need this. Always use GetCursorScreenPos() and GetContentRegionAvail()!
|
||||
IMGUI_API ImVec2 GetWindowContentRegionMin(); // Content boundaries min for the window (roughly (0,0)-Scroll), in window-local coordinates. You should never need this. Always use GetCursorScreenPos() and GetContentRegionAvail()!
|
||||
IMGUI_API ImVec2 GetWindowContentRegionMax(); // Content boundaries max for the window (roughly (0,0)+Size-Scroll), in window-local coordinates. You should never need this. Always use GetCursorScreenPos() and GetContentRegionAvail()!
|
||||
// OBSOLETED in 1.90.0 (from September 2023)
|
||||
inline bool BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags window_flags = 0) { return BeginChild(id, size, ImGuiChildFlags_FrameStyle, window_flags); }
|
||||
inline void EndChildFrame() { EndChild(); }
|
||||
//inline bool BeginChild(const char* str_id, const ImVec2& size_arg, bool borders, ImGuiWindowFlags window_flags){ return BeginChild(str_id, size_arg, borders ? ImGuiChildFlags_Borders : ImGuiChildFlags_None, window_flags); } // Unnecessary as true == ImGuiChildFlags_Borders
|
||||
//inline bool BeginChild(ImGuiID id, const ImVec2& size_arg, bool borders, ImGuiWindowFlags window_flags) { return BeginChild(id, size_arg, borders ? ImGuiChildFlags_Borders : ImGuiChildFlags_None, window_flags); } // Unnecessary as true == ImGuiChildFlags_Borders
|
||||
inline void ShowStackToolWindow(bool* p_open = NULL) { ShowIDStackToolWindow(p_open); }
|
||||
IMGUI_API bool Combo(const char* label, int* current_item, bool (*old_callback)(void* user_data, int idx, const char** out_text), void* user_data, int items_count, int popup_max_height_in_items = -1);
|
||||
IMGUI_API bool ListBox(const char* label, int* current_item, bool (*old_callback)(void* user_data, int idx, const char** out_text), void* user_data, int items_count, int height_in_items = -1);
|
||||
|
||||
// Some of the older obsolete names along with their replacement (commented out so they are not reported in IDE)
|
||||
// OBSOLETED in 1.90.0 (from September 2023)
|
||||
//IMGUI_API bool Combo(const char* label, int* current_item, bool (*old_callback)(void* user_data, int idx, const char** out_text), void* user_data, int items_count, int popup_max_height_in_items = -1); // Getter signature changed. See 2023/09/15 and 2026/02/27 commits.
|
||||
//IMGUI_API bool ListBox(const char* label, int* current_item, bool (*old_callback)(void* user_data, int idx, const char** out_text), void* user_data, int items_count, int height_in_items = -1); // Getter signature changed. See 2023/09/15 and 2026/02/27 commits.
|
||||
//inline bool BeginChild(const char* str_id, const ImVec2& size_arg, bool borders, ImGuiWindowFlags window_flags) { return BeginChild(str_id, size_arg, borders ? ImGuiChildFlags_Borders : ImGuiChildFlags_None, window_flags); } // Unnecessary as true == ImGuiChildFlags_Borders
|
||||
//inline bool BeginChild(ImGuiID id, const ImVec2& size_arg, bool borders, ImGuiWindowFlags window_flags) { return BeginChild(id, size_arg, borders ? ImGuiChildFlags_Borders : ImGuiChildFlags_None, window_flags); } // Unnecessary as true == ImGuiChildFlags_Borders
|
||||
//inline bool BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags flags = 0) { return BeginChild(id, size, ImGuiChildFlags_FrameStyle, flags); }
|
||||
//inline void EndChildFrame() { EndChild(); }
|
||||
//inline void ShowStackToolWindow(bool* p_open = NULL) { ShowIDStackToolWindow(p_open); }
|
||||
// OBSOLETED in 1.89.7 (from June 2023)
|
||||
//IMGUI_API void SetItemAllowOverlap(); // Use SetNextItemAllowOverlap() _before_ item.
|
||||
//-- OBSOLETED in 1.89.4 (from March 2023)
|
||||
@@ -4459,10 +4491,12 @@ typedef ImFontAtlasRect ImFontAtlasCustomRect;
|
||||
//typedef ImGuiKeyChord ImGuiKeyModFlags; // == int
|
||||
//enum ImGuiKeyModFlags_ { ImGuiKeyModFlags_None = 0, ImGuiKeyModFlags_Ctrl = ImGuiMod_Ctrl, ImGuiKeyModFlags_Shift = ImGuiMod_Shift, ImGuiKeyModFlags_Alt = ImGuiMod_Alt, ImGuiKeyModFlags_Super = ImGuiMod_Super };
|
||||
|
||||
#define IM_OFFSETOF(_TYPE,_MEMBER) offsetof(_TYPE, _MEMBER) // OBSOLETED IN 1.90 (now using C++11 standard version)
|
||||
//#define IM_OFFSETOF(_TYPE,_MEMBER) offsetof(_TYPE, _MEMBER) // OBSOLETED IN 1.90 (now using C++11 standard version)
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
|
||||
#define IM_ARRAYSIZE IM_COUNTOF // RENAMED IN 1.92.6: IM_ARRAYSIZE -> IM_COUNTOF
|
||||
|
||||
// RENAMED IMGUI_DISABLE_METRICS_WINDOW > IMGUI_DISABLE_DEBUG_TOOLS in 1.88 (from June 2022)
|
||||
#ifdef IMGUI_DISABLE_METRICS_WINDOW
|
||||
#error IMGUI_DISABLE_METRICS_WINDOW was renamed to IMGUI_DISABLE_DEBUG_TOOLS, please use new name.
|
||||
|
||||
222
lib/third_party/imgui/imgui/include/imgui_internal.h
vendored
222
lib/third_party/imgui/imgui/include/imgui_internal.h
vendored
@@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.92.5
|
||||
// dear imgui, v1.92.7 WIP
|
||||
// (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.
|
||||
@@ -60,7 +60,7 @@ Index of this file:
|
||||
#include <limits.h> // INT_MIN, INT_MAX
|
||||
|
||||
// Enable SSE intrinsics if available
|
||||
#if (defined __SSE__ || defined __x86_64__ || defined _M_X64 || (defined(_M_IX86_FP) && (_M_IX86_FP >= 1))) && !defined(IMGUI_DISABLE_SSE)
|
||||
#if (defined __SSE__ || defined __x86_64__ || defined _M_X64 || (defined(_M_IX86_FP) && (_M_IX86_FP >= 1))) && !defined(IMGUI_DISABLE_SSE) && !defined(_M_ARM64) && !defined(_M_ARM64EC)
|
||||
#define IMGUI_ENABLE_SSE
|
||||
#include <immintrin.h>
|
||||
#if (defined __AVX__ || defined __SSE4_2__)
|
||||
@@ -106,6 +106,7 @@ Index of this file:
|
||||
#pragma GCC diagnostic ignored "-Wfloat-equal" // warning: comparing floating-point with '==' or '!=' is unsafe
|
||||
#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 "-Wdeprecated-enum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated
|
||||
#pragma GCC diagnostic ignored "-Wsign-conversion" // warning: conversion to 'xxxx' from 'xxxx' may change the sign of the result
|
||||
#endif
|
||||
|
||||
// In 1.89.4, we moved the implementation of "courtesy maths operators" from imgui_internal.h in imgui.h
|
||||
@@ -288,11 +289,9 @@ extern IMGUI_API ImGuiContext* GImGui; // Current implicit context pointer
|
||||
#define IM_MEMALIGN(_OFF,_ALIGN) (((_OFF) + ((_ALIGN) - 1)) & ~((_ALIGN) - 1)) // Memory align e.g. IM_ALIGN(0,4)=0, IM_ALIGN(1,4)=4, IM_ALIGN(4,4)=4, IM_ALIGN(5,4)=8
|
||||
#define IM_F32_TO_INT8_UNBOUND(_VAL) ((int)((_VAL) * 255.0f + ((_VAL)>=0 ? 0.5f : -0.5f))) // Unsaturated, for display purpose
|
||||
#define IM_F32_TO_INT8_SAT(_VAL) ((int)(ImSaturate(_VAL) * 255.0f + 0.5f)) // Saturated, always output 0..255
|
||||
#define IM_TRUNC(_VAL) ((float)(int)(_VAL)) // ImTrunc() is not inlined in MSVC debug builds
|
||||
#define IM_ROUND(_VAL) ((float)(int)((_VAL) + 0.5f)) //
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
#define IM_FLOOR IM_TRUNC // [OBSOLETE] Renamed in 1.90.0 (Sept 2023)
|
||||
#endif
|
||||
#define IM_TRUNC(_VAL) ((float)(int)(_VAL)) // Positive values only! ImTrunc() is not inlined in MSVC debug builds
|
||||
#define IM_ROUND(_VAL) ((float)(int)((_VAL) + 0.5f)) // Positive values only!
|
||||
//#define IM_FLOOR IM_TRUNC // [OBSOLETE] Renamed in 1.90.0 (Sept 2023)
|
||||
|
||||
// Hint for branch prediction
|
||||
#if (defined(__cplusplus) && (__cplusplus >= 202002L)) || (defined(_MSVC_LANG) && (_MSVC_LANG >= 202002L))
|
||||
@@ -347,7 +346,6 @@ extern IMGUI_API ImGuiContext* GImGui; // Current implicit context pointer
|
||||
#define IM_PRIu64 "llu"
|
||||
#define IM_PRIX64 "llX"
|
||||
#endif
|
||||
#define IM_TEXTUREID_TO_U64(_TEXID) ((ImU64)(intptr_t)(_TEXID))
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Generic helpers
|
||||
@@ -454,6 +452,16 @@ IMGUI_API ImVec2 ImFontCalcTextSizeEx(ImFont* font, float size, float max
|
||||
IMGUI_API const char* ImFontCalcWordWrapPositionEx(ImFont* font, float size, const char* text, const char* text_end, float wrap_width, ImDrawTextFlags flags = 0);
|
||||
IMGUI_API const char* ImTextCalcWordWrapNextLineStart(const char* text, const char* text_end, ImDrawTextFlags flags = 0); // trim trailing space and find beginning of next line
|
||||
|
||||
// Character classification for word-wrapping logic
|
||||
enum ImWcharClass
|
||||
{
|
||||
ImWcharClass_Blank, ImWcharClass_Punct, ImWcharClass_Other
|
||||
};
|
||||
IMGUI_API void ImTextInitClassifiers();
|
||||
IMGUI_API void ImTextClassifierClear(ImU32* bits, unsigned int codepoint_min, unsigned int codepoint_end, ImWcharClass char_class);
|
||||
IMGUI_API void ImTextClassifierSetCharClass(ImU32* bits, unsigned int codepoint_min, unsigned int codepoint_end, ImWcharClass char_class, unsigned int c);
|
||||
IMGUI_API void ImTextClassifierSetCharClassFromStr(ImU32* bits, unsigned int codepoint_min, unsigned int codepoint_end, ImWcharClass char_class, const char* s);
|
||||
|
||||
// Helpers: File System
|
||||
#ifdef IMGUI_DISABLE_FILE_FUNCTIONS
|
||||
#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS
|
||||
@@ -531,7 +539,7 @@ inline ImVec2 ImTrunc(const ImVec2& v) { return
|
||||
inline float ImFloor(float f) { return (float)((f >= 0 || (float)(int)f == f) ? (int)f : (int)f - 1); } // Decent replacement for floorf()
|
||||
inline ImVec2 ImFloor(const ImVec2& v) { return ImVec2(ImFloor(v.x), ImFloor(v.y)); }
|
||||
inline float ImTrunc64(float f) { return (float)(ImS64)(f); }
|
||||
inline float ImRound64(float f) { return (float)(ImS64)(f + 0.5f); }
|
||||
inline float ImRound64(float f) { return (float)(ImS64)(f + 0.5f); } // FIXME: Positive values only.
|
||||
inline int ImModPositive(int a, int b) { return (a + b) % b; }
|
||||
inline float ImDot(const ImVec2& a, const ImVec2& b) { return a.x * b.x + a.y * b.y; }
|
||||
inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); }
|
||||
@@ -539,7 +547,7 @@ inline float ImLinearSweep(float current, float target, float speed) { if (cu
|
||||
inline float ImLinearRemapClamp(float s0, float s1, float d0, float d1, float x) { return ImSaturate((x - s0) / (s1 - s0)) * (d1 - d0) + d0; }
|
||||
inline ImVec2 ImMul(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); }
|
||||
inline bool ImIsFloatAboveGuaranteedIntegerPrecision(float f) { return f <= -16777216 || f >= 16777216; }
|
||||
inline float ImExponentialMovingAverage(float avg, float sample, int n){ avg -= avg / n; avg += sample / n; return avg; }
|
||||
inline float ImExponentialMovingAverage(float avg, float sample, int n){ avg -= avg / (float)n; avg += sample / (float)n; return avg; }
|
||||
IM_MSVC_RUNTIME_CHECKS_RESTORE
|
||||
|
||||
// Helpers: Geometry
|
||||
@@ -615,7 +623,6 @@ struct IMGUI_API ImRect
|
||||
void TranslateY(float dy) { Min.y += dy; Max.y += dy; }
|
||||
void ClipWith(const ImRect& r) { Min = ImMax(Min, r.Min); Max = ImMin(Max, r.Max); } // Simple version, may lead to an inverted rectangle, which is fine for Contains/Overlaps test but not for display.
|
||||
void ClipWithFull(const ImRect& r) { Min = ImClamp(Min, r.Min, r.Max); Max = ImClamp(Max, r.Min, r.Max); } // Full version, ensure both points are fully clipped.
|
||||
void Floor() { Min.x = IM_TRUNC(Min.x); Min.y = IM_TRUNC(Min.y); Max.x = IM_TRUNC(Max.x); Max.y = IM_TRUNC(Max.y); }
|
||||
bool IsInverted() const { return Min.x > Max.x || Min.y > Max.y; }
|
||||
ImVec4 ToVec4() const { return ImVec4(Min.x, Min.y, Max.x, Max.y); }
|
||||
const ImVec4& AsVec4() const { return *(const ImVec4*)&Min.x; }
|
||||
@@ -649,15 +656,15 @@ typedef ImU32* ImBitArrayPtr; // Name for use in structs
|
||||
template<int BITCOUNT, int OFFSET = 0>
|
||||
struct ImBitArray
|
||||
{
|
||||
ImU32 Storage[(BITCOUNT + 31) >> 5];
|
||||
ImU32 Data[(BITCOUNT + 31) >> 5];
|
||||
ImBitArray() { ClearAllBits(); }
|
||||
void ClearAllBits() { memset(Storage, 0, sizeof(Storage)); }
|
||||
void SetAllBits() { memset(Storage, 255, sizeof(Storage)); }
|
||||
bool TestBit(int n) const { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); return IM_BITARRAY_TESTBIT(Storage, n); }
|
||||
void SetBit(int n) { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); ImBitArraySetBit(Storage, n); }
|
||||
void ClearBit(int n) { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); ImBitArrayClearBit(Storage, n); }
|
||||
void SetBitRange(int n, int n2) { n += OFFSET; n2 += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT && n2 > n && n2 <= BITCOUNT); ImBitArraySetBitRange(Storage, n, n2); } // Works on range [n..n2)
|
||||
bool operator[](int n) const { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); return IM_BITARRAY_TESTBIT(Storage, n); }
|
||||
void ClearAllBits() { memset(Data, 0, sizeof(Data)); }
|
||||
void SetAllBits() { memset(Data, 255, sizeof(Data)); }
|
||||
bool TestBit(int n) const { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); return IM_BITARRAY_TESTBIT(Data, n); }
|
||||
void SetBit(int n) { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); ImBitArraySetBit(Data, n); }
|
||||
void ClearBit(int n) { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); ImBitArrayClearBit(Data, n); }
|
||||
void SetBitRange(int n, int n2) { n += OFFSET; n2 += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT && n2 > n && n2 <= BITCOUNT); ImBitArraySetBitRange(Data, n, n2); } // Works on range [n..n2)
|
||||
bool operator[](int n) const { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); return IM_BITARRAY_TESTBIT(Data, n); }
|
||||
};
|
||||
|
||||
// Helper: ImBitVector
|
||||
@@ -714,7 +721,7 @@ struct ImSpanAllocator
|
||||
int Offsets[CHUNKS];
|
||||
int Sizes[CHUNKS];
|
||||
|
||||
ImSpanAllocator() { memset(this, 0, sizeof(*this)); }
|
||||
ImSpanAllocator() { memset((void*)this, 0, sizeof(*this)); }
|
||||
inline void Reserve(int n, size_t sz, int a=4) { IM_ASSERT(n == CurrIdx && n < CHUNKS); CurrOff = IM_MEMALIGN(CurrOff, a); Offsets[n] = CurrOff; Sizes[n] = (int)sz; CurrIdx++; CurrOff += (int)sz; }
|
||||
inline int GetArenaSizeInBytes() { return CurrOff; }
|
||||
inline void SetArenaBasePtr(void* base_ptr) { BasePtr = (char*)base_ptr; }
|
||||
@@ -725,10 +732,10 @@ struct ImSpanAllocator
|
||||
};
|
||||
|
||||
// Helper: ImStableVector<>
|
||||
// Allocating chunks of BLOCK_SIZE items. Objects pointers are never invalidated when growing, only by clear().
|
||||
// Allocating chunks of BLOCKSIZE items. Objects pointers are never invalidated when growing, only by clear().
|
||||
// Important: does not destruct anything!
|
||||
// Implemented only the minimum set of functions we need for it.
|
||||
template<typename T, int BLOCK_SIZE>
|
||||
template<typename T, int BLOCKSIZE>
|
||||
struct ImStableVector
|
||||
{
|
||||
int Size = 0;
|
||||
@@ -742,19 +749,19 @@ struct ImStableVector
|
||||
inline void resize(int new_size) { if (new_size > Capacity) reserve(new_size); Size = new_size; }
|
||||
inline void reserve(int new_cap)
|
||||
{
|
||||
new_cap = IM_MEMALIGN(new_cap, BLOCK_SIZE);
|
||||
int old_count = Capacity / BLOCK_SIZE;
|
||||
int new_count = new_cap / BLOCK_SIZE;
|
||||
new_cap = IM_MEMALIGN(new_cap, BLOCKSIZE);
|
||||
int old_count = Capacity / BLOCKSIZE;
|
||||
int new_count = new_cap / BLOCKSIZE;
|
||||
if (new_count <= old_count)
|
||||
return;
|
||||
Blocks.resize(new_count);
|
||||
for (int n = old_count; n < new_count; n++)
|
||||
Blocks[n] = (T*)IM_ALLOC(sizeof(T) * BLOCK_SIZE);
|
||||
Blocks[n] = (T*)IM_ALLOC(sizeof(T) * BLOCKSIZE);
|
||||
Capacity = new_cap;
|
||||
}
|
||||
inline T& operator[](int i) { IM_ASSERT(i >= 0 && i < Size); return Blocks[i / BLOCK_SIZE][i % BLOCK_SIZE]; }
|
||||
inline const T& operator[](int i) const { IM_ASSERT(i >= 0 && i < Size); return Blocks[i / BLOCK_SIZE][i % BLOCK_SIZE]; }
|
||||
inline T* push_back(const T& v) { int i = Size; IM_ASSERT(i >= 0); if (Size == Capacity) reserve(Capacity + BLOCK_SIZE); void* ptr = &Blocks[i / BLOCK_SIZE][i % BLOCK_SIZE]; memcpy(ptr, &v, sizeof(v)); Size++; return (T*)ptr; }
|
||||
inline T& operator[](int i) { IM_ASSERT(i >= 0 && i < Size); return Blocks[i / BLOCKSIZE][i % BLOCKSIZE]; }
|
||||
inline const T& operator[](int i) const { IM_ASSERT(i >= 0 && i < Size); return Blocks[i / BLOCKSIZE][i % BLOCKSIZE]; }
|
||||
inline T* push_back(const T& v) { int i = Size; IM_ASSERT(i >= 0); if (Size == Capacity) reserve(Capacity + BLOCKSIZE); void* ptr = &Blocks[i / BLOCKSIZE][i % BLOCKSIZE]; memcpy(ptr, &v, sizeof(v)); Size++; return (T*)ptr; }
|
||||
};
|
||||
|
||||
// Helper: ImPool<>
|
||||
@@ -898,7 +905,7 @@ struct ImDrawDataBuilder
|
||||
ImVector<ImDrawList*>* Layers[2]; // Pointers to global layers for: regular, tooltip. LayersP[0] is owned by DrawData.
|
||||
ImVector<ImDrawList*> LayerData1;
|
||||
|
||||
ImDrawDataBuilder() { memset(this, 0, sizeof(*this)); }
|
||||
ImDrawDataBuilder() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
struct ImFontStackData
|
||||
@@ -972,7 +979,6 @@ enum ImGuiDataTypePrivate_
|
||||
enum ImGuiItemFlagsPrivate_
|
||||
{
|
||||
// Controlled by user
|
||||
ImGuiItemFlags_Disabled = 1 << 10, // false // Disable interactions (DOES NOT affect visuals. DO NOT mix direct use of this with BeginDisabled(). See BeginDisabled()/EndDisabled() for full disable feature, and github #211).
|
||||
ImGuiItemFlags_ReadOnly = 1 << 11, // false // [ALPHA] Allow hovering interactions but underlying value is not changed.
|
||||
ImGuiItemFlags_MixedValue = 1 << 12, // false // [BETA] Represent a mixed/indeterminate value, generally multi-selection where values differ. Currently only supported by Checkbox() (later should support all sorts of widgets)
|
||||
ImGuiItemFlags_NoWindowHoverableCheck = 1 << 13, // false // Disable hoverable check in ItemHoverable()
|
||||
@@ -1174,7 +1180,7 @@ struct IMGUI_API ImGuiComboPreviewData
|
||||
float BackupPrevLineTextBaseOffset;
|
||||
ImGuiLayoutType BackupLayout;
|
||||
|
||||
ImGuiComboPreviewData() { memset(this, 0, sizeof(*this)); }
|
||||
ImGuiComboPreviewData() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
// Stacked storage data for BeginGroup()/EndGroup()
|
||||
@@ -1208,7 +1214,7 @@ struct IMGUI_API ImGuiMenuColumns
|
||||
ImU16 OffsetMark;
|
||||
ImU16 Widths[4]; // Width of: Icon, Label, Shortcut, Mark (accumulators for current frame)
|
||||
|
||||
ImGuiMenuColumns() { memset(this, 0, sizeof(*this)); }
|
||||
ImGuiMenuColumns() { memset((void*)this, 0, sizeof(*this)); }
|
||||
void Update(float spacing, bool window_reappearing);
|
||||
float DeclColumns(float w_icon, float w_label, float w_shortcut, float w_mark);
|
||||
void CalcNextTotalWidth(bool update_offsets);
|
||||
@@ -1220,7 +1226,7 @@ struct IMGUI_API ImGuiInputTextDeactivatedState
|
||||
ImGuiID ID; // widget id owning the text state (which just got deactivated)
|
||||
ImVector<char> TextA; // text buffer
|
||||
|
||||
ImGuiInputTextDeactivatedState() { memset(this, 0, sizeof(*this)); }
|
||||
ImGuiInputTextDeactivatedState() { memset((void*)this, 0, sizeof(*this)); }
|
||||
void ClearFreeMemory() { ID = 0; TextA.clear(); }
|
||||
};
|
||||
|
||||
@@ -1244,7 +1250,7 @@ struct IMGUI_API ImGuiInputTextState
|
||||
ImGuiInputTextFlags Flags; // copy of InputText() flags. may be used to check if e.g. ImGuiInputTextFlags_Password is set.
|
||||
ImGuiID ID; // widget id owning the text state
|
||||
int TextLen; // UTF-8 length of the string in TextA (in bytes)
|
||||
const char* TextSrc; // == TextA.Data unless read-only, in which case == buf passed to InputText(). Field only set and valid _inside_ the call InputText() call.
|
||||
const char* TextSrc; // == TextA.Data unless read-only, in which case == buf passed to InputText(). For _ReadOnly fields, pointer will be null outside the InputText() call.
|
||||
ImVector<char> TextA; // main UTF8 buffer. TextA.Size is a buffer size! Should always be >= buf_size passed by user (and of course >= CurLenA + 1).
|
||||
ImVector<char> TextToRevertTo; // value to revert to when pressing Escape = backup of end-user buffer at the time of focus (in UTF-8, unaltered)
|
||||
ImVector<char> CallbackTextBackup; // temporary storage for callback to support automatic reconcile of undo-stack
|
||||
@@ -1278,6 +1284,7 @@ struct IMGUI_API ImGuiInputTextState
|
||||
int GetCursorPos() const;
|
||||
int GetSelectionStart() const;
|
||||
int GetSelectionEnd() const;
|
||||
void SetSelection(int start, int end);
|
||||
void SelectAll();
|
||||
|
||||
// Reload user buf (WIP #2890)
|
||||
@@ -1353,18 +1360,19 @@ struct ImGuiNextWindowData
|
||||
ImVec2 MenuBarOffsetMinVal; // (Always on) This is not exposed publicly, so we don't clear it and it doesn't have a corresponding flag (could we? for consistency?)
|
||||
ImGuiWindowRefreshFlags RefreshFlagsVal;
|
||||
|
||||
ImGuiNextWindowData() { memset(this, 0, sizeof(*this)); }
|
||||
ImGuiNextWindowData() { memset((void*)this, 0, sizeof(*this)); }
|
||||
inline void ClearFlags() { HasFlags = ImGuiNextWindowDataFlags_None; }
|
||||
};
|
||||
|
||||
enum ImGuiNextItemDataFlags_
|
||||
{
|
||||
ImGuiNextItemDataFlags_None = 0,
|
||||
ImGuiNextItemDataFlags_HasWidth = 1 << 0,
|
||||
ImGuiNextItemDataFlags_HasOpen = 1 << 1,
|
||||
ImGuiNextItemDataFlags_HasShortcut = 1 << 2,
|
||||
ImGuiNextItemDataFlags_HasRefVal = 1 << 3,
|
||||
ImGuiNextItemDataFlags_HasStorageID = 1 << 4,
|
||||
ImGuiNextItemDataFlags_None = 0,
|
||||
ImGuiNextItemDataFlags_HasWidth = 1 << 0,
|
||||
ImGuiNextItemDataFlags_HasOpen = 1 << 1,
|
||||
ImGuiNextItemDataFlags_HasShortcut = 1 << 2,
|
||||
ImGuiNextItemDataFlags_HasRefVal = 1 << 3,
|
||||
ImGuiNextItemDataFlags_HasStorageID = 1 << 4,
|
||||
ImGuiNextItemDataFlags_HasColorMarker = 1 << 5,
|
||||
};
|
||||
|
||||
struct ImGuiNextItemData
|
||||
@@ -1382,8 +1390,9 @@ struct ImGuiNextItemData
|
||||
ImU8 OpenCond; // Set by SetNextItemOpen()
|
||||
ImGuiDataTypeStorage RefVal; // Not exposed yet, for ImGuiInputTextFlags_ParseEmptyAsRefVal
|
||||
ImGuiID StorageId; // Set by SetNextItemStorageID()
|
||||
ImU32 ColorMarker; // Set by SetNextItemColorMarker(). Not exposed yet, supported by DragScalar,SliderScalar and for ImGuiSliderFlags_ColorMarkers.
|
||||
|
||||
ImGuiNextItemData() { memset(this, 0, sizeof(*this)); SelectionUserData = -1; }
|
||||
ImGuiNextItemData() { memset((void*)this, 0, sizeof(*this)); SelectionUserData = -1; }
|
||||
inline void ClearFlags() { HasFlags = ImGuiNextItemDataFlags_None; ItemFlags = ImGuiItemFlags_None; } // Also cleared manually by ItemAdd()!
|
||||
};
|
||||
|
||||
@@ -1400,7 +1409,7 @@ struct ImGuiLastItemData
|
||||
ImRect ClipRect; // Clip rectangle at the time of submitting item. ONLY VALID IF (StatusFlags & ImGuiItemStatusFlags_HasClipRect) is set..
|
||||
ImGuiKeyChord Shortcut; // Shortcut at the time of submitting item. ONLY VALID IF (StatusFlags & ImGuiItemStatusFlags_HasShortcut) is set..
|
||||
|
||||
ImGuiLastItemData() { memset(this, 0, sizeof(*this)); }
|
||||
ImGuiLastItemData() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
// Store data emitted by TreeNode() for usage by TreePop()
|
||||
@@ -1433,7 +1442,7 @@ struct IMGUI_API ImGuiErrorRecoveryState
|
||||
short SizeOfBeginPopupStack;
|
||||
short SizeOfDisabledStack;
|
||||
|
||||
ImGuiErrorRecoveryState() { memset(this, 0, sizeof(*this)); }
|
||||
ImGuiErrorRecoveryState() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
// Data saved for each window pushed into the stack
|
||||
@@ -1494,7 +1503,7 @@ struct ImGuiPopupData
|
||||
ImVec2 OpenPopupPos; // Set on OpenPopup(), preferred popup position (typically == OpenMousePos when using mouse)
|
||||
ImVec2 OpenMousePos; // Set on OpenPopup(), copy of mouse position at the time of opening popup
|
||||
|
||||
ImGuiPopupData() { memset(this, 0, sizeof(*this)); ParentNavLayer = OpenFrameCount = -1; }
|
||||
ImGuiPopupData() { memset((void*)this, 0, sizeof(*this)); ParentNavLayer = OpenFrameCount = -1; }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -1523,8 +1532,8 @@ typedef ImBitArray<ImGuiKey_NamedKey_COUNT, -ImGuiKey_NamedKey_BEGIN> ImBitAr
|
||||
#define ImGuiKey_NavGamepadTweakFast ImGuiKey_GamepadR1
|
||||
#define ImGuiKey_NavGamepadActivate (g.IO.ConfigNavSwapGamepadButtons ? ImGuiKey_GamepadFaceRight : ImGuiKey_GamepadFaceDown)
|
||||
#define ImGuiKey_NavGamepadCancel (g.IO.ConfigNavSwapGamepadButtons ? ImGuiKey_GamepadFaceDown : ImGuiKey_GamepadFaceRight)
|
||||
#define ImGuiKey_NavGamepadMenu ImGuiKey_GamepadFaceLeft
|
||||
#define ImGuiKey_NavGamepadInput ImGuiKey_GamepadFaceUp
|
||||
#define ImGuiKey_NavGamepadMenu ImGuiKey_GamepadFaceLeft // Toggle menu layer. Hold to enable Windowing.
|
||||
#define ImGuiKey_NavGamepadContextMenu ImGuiKey_GamepadFaceUp // Open context menu (same as Shift+F10)
|
||||
|
||||
enum ImGuiInputEventType
|
||||
{
|
||||
@@ -1575,7 +1584,7 @@ struct ImGuiInputEvent
|
||||
};
|
||||
bool AddedByTestEngine;
|
||||
|
||||
ImGuiInputEvent() { memset(this, 0, sizeof(*this)); }
|
||||
ImGuiInputEvent() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
// Input function taking an 'ImGuiID owner_id' argument defaults to (ImGuiKeyOwner_Any == 0) aka don't test ownership, which matches legacy behavior.
|
||||
@@ -1607,7 +1616,7 @@ struct ImGuiKeyRoutingTable
|
||||
ImVector<ImGuiKeyRoutingData> EntriesNext; // Double-buffer to avoid reallocation (could use a shared buffer)
|
||||
|
||||
ImGuiKeyRoutingTable() { Clear(); }
|
||||
void Clear() { for (int n = 0; n < IM_ARRAYSIZE(Index); n++) Index[n] = -1; Entries.clear(); EntriesNext.clear(); }
|
||||
void Clear() { for (int n = 0; n < IM_COUNTOF(Index); n++) Index[n] = -1; Entries.clear(); EntriesNext.clear(); }
|
||||
};
|
||||
|
||||
// This extends ImGuiKeyData but only for named keys (legacy keys don't support the new features)
|
||||
@@ -1690,7 +1699,7 @@ struct ImGuiListClipperData
|
||||
int ItemsFrozen;
|
||||
ImVector<ImGuiListClipperRange> Ranges;
|
||||
|
||||
ImGuiListClipperData() { memset(this, 0, sizeof(*this)); }
|
||||
ImGuiListClipperData() { memset((void*)this, 0, sizeof(*this)); }
|
||||
void Reset(ImGuiListClipper* clipper) { ListClipper = clipper; StepNo = ItemsFrozen = 0; Ranges.resize(0); }
|
||||
};
|
||||
|
||||
@@ -1825,7 +1834,7 @@ struct IMGUI_API ImGuiTypingSelectState
|
||||
float LastRequestTime = 0.0f;
|
||||
bool SingleCharModeLock = false; // After a certain single char repeat count we lock into SingleCharMode. Two benefits: 1) buffer never fill, 2) we can provide an immediate SingleChar mode without timer elapsing.
|
||||
|
||||
ImGuiTypingSelectState() { memset(this, 0, sizeof(*this)); }
|
||||
ImGuiTypingSelectState() { memset((void*)this, 0, sizeof(*this)); }
|
||||
void Clear() { SearchBuffer[0] = 0; SingleCharModeLock = false; } // We preserve remaining data for easier debugging
|
||||
};
|
||||
|
||||
@@ -1861,7 +1870,7 @@ struct ImGuiOldColumnData
|
||||
ImGuiOldColumnFlags Flags; // Not exposed
|
||||
ImRect ClipRect;
|
||||
|
||||
ImGuiOldColumnData() { memset(this, 0, sizeof(*this)); }
|
||||
ImGuiOldColumnData() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
struct ImGuiOldColumns
|
||||
@@ -1882,7 +1891,7 @@ struct ImGuiOldColumns
|
||||
ImVector<ImGuiOldColumnData> Columns;
|
||||
ImDrawListSplitter Splitter;
|
||||
|
||||
ImGuiOldColumns() { memset(this, 0, sizeof(*this)); }
|
||||
ImGuiOldColumns() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -1910,7 +1919,7 @@ struct ImGuiBoxSelectState
|
||||
ImRect BoxSelectRectPrev; // Selection rectangle in absolute coordinates (derived every frame from BoxSelectStartPosRel and MousePos)
|
||||
ImRect BoxSelectRectCurr;
|
||||
|
||||
ImGuiBoxSelectState() { memset(this, 0, sizeof(*this)); }
|
||||
ImGuiBoxSelectState() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -2111,7 +2120,7 @@ struct ImGuiDockContext
|
||||
ImVector<ImGuiDockRequest> Requests;
|
||||
ImVector<ImGuiDockNodeSettings> NodesSettings;
|
||||
bool WantFullRebuild;
|
||||
ImGuiDockContext() { memset(this, 0, sizeof(*this)); }
|
||||
ImGuiDockContext() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
#endif // #ifdef IMGUI_HAS_DOCK
|
||||
@@ -2189,7 +2198,7 @@ struct ImGuiWindowSettings
|
||||
bool WantApply; // Set when loaded from .ini data (to enable merging/loading .ini data into an already running context)
|
||||
bool WantDelete; // Set to invalidate/delete the settings entry
|
||||
|
||||
ImGuiWindowSettings() { memset(this, 0, sizeof(*this)); DockOrder = -1; }
|
||||
ImGuiWindowSettings() { memset((void*)this, 0, sizeof(*this)); DockOrder = -1; }
|
||||
char* GetName() { return (char*)(this + 1); }
|
||||
};
|
||||
|
||||
@@ -2205,7 +2214,7 @@ struct ImGuiSettingsHandler
|
||||
void (*WriteAllFn)(ImGuiContext* ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* out_buf); // Write: Output every entries into 'out_buf'
|
||||
void* UserData;
|
||||
|
||||
ImGuiSettingsHandler() { memset(this, 0, sizeof(*this)); }
|
||||
ImGuiSettingsHandler() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -2247,7 +2256,9 @@ struct ImGuiLocEntry
|
||||
// - See 'Demo->Configuration->Error Handling' and ImGuiIO definitions for details on error handling.
|
||||
// - Read https://github.com/ocornut/imgui/wiki/Error-Handling for details on error handling.
|
||||
#ifndef IM_ASSERT_USER_ERROR
|
||||
#define IM_ASSERT_USER_ERROR(_EXPR,_MSG) do { if (!(_EXPR) && ImGui::ErrorLog(_MSG)) { IM_ASSERT((_EXPR) && _MSG); } } while (0) // Recoverable User Error
|
||||
#define IM_ASSERT_USER_ERROR(_EXPR,_MSG) do { if (!(_EXPR)) { if (ImGui::ErrorLog(_MSG)) { IM_ASSERT((_EXPR) && _MSG); } } } while (0) // Recoverable User Error
|
||||
#define IM_ASSERT_USER_ERROR_RET(_EXPR,_MSG) do { if (!(_EXPR)) { if (ImGui::ErrorLog(_MSG)) { IM_ASSERT((_EXPR) && _MSG); } return; } } while (0) // Recoverable User Error
|
||||
#define IM_ASSERT_USER_ERROR_RETV(_EXPR,_RETV,_MSG) do { if (!(_EXPR)) { if (ImGui::ErrorLog(_MSG)) { IM_ASSERT((_EXPR) && _MSG); } return _RETV; } } while (0) // Recoverable User Error
|
||||
#endif
|
||||
|
||||
// The error callback is currently not public, as it is expected that only advanced users will rely on it.
|
||||
@@ -2277,7 +2288,8 @@ enum ImGuiDebugLogFlags_
|
||||
|
||||
ImGuiDebugLogFlags_EventMask_ = ImGuiDebugLogFlags_EventError | ImGuiDebugLogFlags_EventActiveId | ImGuiDebugLogFlags_EventFocus | ImGuiDebugLogFlags_EventPopup | ImGuiDebugLogFlags_EventNav | ImGuiDebugLogFlags_EventClipper | ImGuiDebugLogFlags_EventSelection | ImGuiDebugLogFlags_EventIO | ImGuiDebugLogFlags_EventFont | ImGuiDebugLogFlags_EventInputRouting | ImGuiDebugLogFlags_EventDocking | ImGuiDebugLogFlags_EventViewport,
|
||||
ImGuiDebugLogFlags_OutputToTTY = 1 << 20, // Also send output to TTY
|
||||
ImGuiDebugLogFlags_OutputToTestEngine = 1 << 21, // Also send output to Test Engine
|
||||
ImGuiDebugLogFlags_OutputToDebugger = 1 << 21, // Also send output to Debugger Console [Windows only]
|
||||
ImGuiDebugLogFlags_OutputToTestEngine = 1 << 22, // Also send output to Dear ImGui Test Engine
|
||||
};
|
||||
|
||||
struct ImGuiDebugAllocEntry
|
||||
@@ -2294,7 +2306,7 @@ struct ImGuiDebugAllocInfo
|
||||
ImS16 LastEntriesIdx; // Current index in buffer
|
||||
ImGuiDebugAllocEntry LastEntriesBuf[6]; // Track last 6 frames that had allocations
|
||||
|
||||
ImGuiDebugAllocInfo() { memset(this, 0, sizeof(*this)); }
|
||||
ImGuiDebugAllocInfo() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
struct ImGuiMetricsConfig
|
||||
@@ -2324,7 +2336,7 @@ struct ImGuiStackLevelInfo
|
||||
ImS8 DataType; // ImGuiDataType
|
||||
int DescOffset; // -1 or offset into parent's ResultsPathsBuf
|
||||
|
||||
ImGuiStackLevelInfo() { memset(this, 0, sizeof(*this)); DataType = -1; DescOffset = -1; }
|
||||
ImGuiStackLevelInfo() { memset((void*)this, 0, sizeof(*this)); DataType = -1; DescOffset = -1; }
|
||||
};
|
||||
|
||||
struct ImGuiDebugItemPathQuery
|
||||
@@ -2337,7 +2349,7 @@ struct ImGuiDebugItemPathQuery
|
||||
ImGuiTextBuffer ResultsDescBuf;
|
||||
ImGuiTextBuffer ResultPathBuf;
|
||||
|
||||
ImGuiDebugItemPathQuery() { memset(this, 0, sizeof(*this)); }
|
||||
ImGuiDebugItemPathQuery() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
// State for ID Stack tool queries
|
||||
@@ -2348,7 +2360,7 @@ struct ImGuiIDStackTool
|
||||
int LastActiveFrame;
|
||||
float CopyToClipboardLastTime;
|
||||
|
||||
ImGuiIDStackTool() { memset(this, 0, sizeof(*this)); LastActiveFrame = -1; OptHexEncodeNonAsciiChars = true; CopyToClipboardLastTime = -FLT_MAX; }
|
||||
ImGuiIDStackTool() { memset((void*)this, 0, sizeof(*this)); LastActiveFrame = -1; OptHexEncodeNonAsciiChars = true; CopyToClipboardLastTime = -FLT_MAX; }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -2366,9 +2378,11 @@ struct ImGuiContextHook
|
||||
ImGuiContextHookCallback Callback;
|
||||
void* UserData;
|
||||
|
||||
ImGuiContextHook() { memset(this, 0, sizeof(*this)); }
|
||||
ImGuiContextHook() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
typedef void (*ImGuiDemoMarkerCallback)(const char* file, int line, const char* section);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] ImGuiContext (main Dear ImGui context)
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -2522,6 +2536,7 @@ struct ImGuiContext
|
||||
ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusedWindow'
|
||||
ImGuiID NavFocusScopeId; // Focused focus scope (e.g. selection code often wants to "clear other items" when landing on an item of the same scope)
|
||||
ImGuiNavLayer NavLayer; // Focused layer (main scrolling layer, or menu/title bar layer)
|
||||
ImGuiItemFlags NavIdItemFlags;
|
||||
ImGuiID NavActivateId; // ~~ (g.ActiveId == 0) && (IsKeyPressed(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate)) ? NavId : 0, also set when calling ActivateItemByID()
|
||||
ImGuiID NavActivateDownId; // ~~ IsKeyDown(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyDown(ImGuiKey_NavGamepadActivate) ? NavId : 0
|
||||
ImGuiID NavActivatePressedId; // ~~ IsKeyPressed(ImGuiKey_Space) || IsKeyPressed(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate) ? NavId : 0 (no repeat)
|
||||
@@ -2529,6 +2544,8 @@ struct ImGuiContext
|
||||
ImVector<ImGuiFocusScopeData> NavFocusRoute; // Reversed copy focus scope stack for NavId (should contains NavFocusScopeId). This essentially follow the window->ParentWindowForFocusRoute chain.
|
||||
ImGuiID NavHighlightActivatedId;
|
||||
float NavHighlightActivatedTimer;
|
||||
ImGuiID NavOpenContextMenuItemId;
|
||||
ImGuiID NavOpenContextMenuWindowId;
|
||||
ImGuiID NavNextActivateId; // Set by ActivateItemByID(), queued until next frame.
|
||||
ImGuiActivateFlags NavNextActivateFlags;
|
||||
ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS CAN ONLY BE ImGuiInputSource_Keyboard or ImGuiInputSource_Gamepad
|
||||
@@ -2551,7 +2568,7 @@ struct ImGuiContext
|
||||
ImGuiDir NavMoveDirForDebug;
|
||||
ImGuiDir NavMoveClipDir; // FIXME-NAV: Describe the purpose of this better. Might want to rename?
|
||||
ImRect NavScoringRect; // Rectangle used for scoring, in screen space. Based of window->NavRectRel[], modified for directional navigation scoring.
|
||||
ImRect NavScoringNoClipRect; // Some nav operations (such as PageUp/PageDown) enforce a region which clipper will attempt to always keep submitted
|
||||
ImRect NavScoringNoClipRect; // Some nav operations (such as PageUp/PageDown) enforce a region which clipper will attempt to always keep submitted. Unset/invalid if inverted.
|
||||
int NavScoringDebugCount; // Metrics for debugging
|
||||
int NavTabbingDir; // Generally -1 or +1, 0 when tabbing without a nav id
|
||||
int NavTabbingCounter; // >0 when counting items for tabbing
|
||||
@@ -2568,10 +2585,15 @@ struct ImGuiContext
|
||||
bool NavJustMovedToIsTabbing; // Copy of ImGuiNavMoveFlags_IsTabbing. Maybe we should store whole flags.
|
||||
bool NavJustMovedToHasSelectionData; // Copy of move result's ItemFlags & ImGuiItemFlags_HasSelectionUserData). Maybe we should just store ImGuiNavItemData.
|
||||
|
||||
// Navigation: Windowing (Ctrl+Tab for list, or Menu button + keys or directional pads to move/resize)
|
||||
// Navigation: extra config options (will be made public eventually)
|
||||
// - Tabbing (Tab, Shift+Tab) and Windowing (Ctrl+Tab, Ctrl+Shift+Tab) are enabled REGARDLESS of ImGuiConfigFlags_NavEnableKeyboard being set.
|
||||
// - Ctrl+Tab is reconfigurable because it is the only shortcut that may be polled when no window are focused. It also doesn't work e.g. Web platforms.
|
||||
bool ConfigNavEnableTabbing; // = true. Enable tabbing (Tab, Shift+Tab). PLEASE LET ME KNOW IF YOU USE THIS.
|
||||
bool ConfigNavWindowingWithGamepad; // = true. Enable Ctrl+Tab by holding ImGuiKey_GamepadFaceLeft (== ImGuiKey_NavGamepadMenu). When false, the button may still be used to toggle Menu layer.
|
||||
ImGuiKeyChord ConfigNavWindowingKeyNext; // = ImGuiMod_Ctrl | ImGuiKey_Tab (or ImGuiMod_Super | ImGuiKey_Tab on OS X). For reconfiguration (see #4828)
|
||||
ImGuiKeyChord ConfigNavWindowingKeyNext; // = ImGuiMod_Ctrl | ImGuiKey_Tab (or ImGuiMod_Super | ImGuiKey_Tab on OS X). Set to 0 to disable. For reconfiguration (see #4828)
|
||||
ImGuiKeyChord ConfigNavWindowingKeyPrev; // = ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Tab (or ImGuiMod_Super | ImGuiMod_Shift | ImGuiKey_Tab on OS X)
|
||||
|
||||
// Navigation: Windowing (Ctrl+Tab for list, or Menu button + keys or directional pads to move/resize)
|
||||
ImGuiWindow* NavWindowingTarget; // Target window when doing Ctrl+Tab (or Pad Menu + FocusPrev/Next), this window is temporarily displayed top-most!
|
||||
ImGuiWindow* NavWindowingTargetAnim; // Record of last valid NavWindowingTarget until DimBgRatio and NavWindowingHighlightAlpha becomes 0.0f, so the fade-out can stay on it.
|
||||
ImGuiWindow* NavWindowingListWindow; // Internal window actually listing the Ctrl+Tab contents
|
||||
@@ -2653,6 +2675,7 @@ struct ImGuiContext
|
||||
ImGuiInputTextDeactivatedState InputTextDeactivatedState;
|
||||
ImFontBaked InputTextPasswordFontBackupBaked;
|
||||
ImFontFlags InputTextPasswordFontBackupFlags;
|
||||
ImGuiID InputTextReactivateId; // ID of InputText to reactivate on next frame (for io.ConfigInputTextEnterKeepActive behavior)
|
||||
ImGuiID TempInputId; // Temporary text input when using Ctrl+Click on a slider, etc.
|
||||
ImGuiDataTypeStorage DataTypeZeroValue; // 0 for all data types
|
||||
int BeginMenuDepth;
|
||||
@@ -2700,8 +2723,11 @@ struct ImGuiContext
|
||||
ImVector<ImGuiSettingsHandler> SettingsHandlers; // List of .ini settings handlers
|
||||
ImChunkStream<ImGuiWindowSettings> SettingsWindows; // ImGuiWindow .ini settings entries
|
||||
ImChunkStream<ImGuiTableSettings> SettingsTables; // ImGuiTable .ini settings entries
|
||||
|
||||
// Hooks
|
||||
ImVector<ImGuiContextHook> Hooks; // Hooks for extensions (e.g. test engine)
|
||||
ImGuiID HookIdNext; // Next available HookId
|
||||
ImGuiDemoMarkerCallback DemoMarkerCallback;
|
||||
|
||||
// Localization
|
||||
const char* LocalizationTable[ImGuiLocKey_COUNT];
|
||||
@@ -2776,6 +2802,8 @@ struct ImGuiContext
|
||||
// [SECTION] ImGuiWindowTempData, ImGuiWindow
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define IMGUI_WINDOW_HARD_MIN_SIZE 4.0f
|
||||
|
||||
// Transient per-window data, reset at the beginning of the frame. This used to be called ImGuiDrawContext, hence the DC variable name in ImGuiWindow.
|
||||
// (That's theory, in practice the delimitation between ImGuiWindow and ImGuiWindowTempData is quite tenuous and could be reconsidered..)
|
||||
// (This doesn't need a constructor because we zero-clear it as part of ImGuiWindow and all frame-temporary data are setup on Begin)
|
||||
@@ -2830,6 +2858,7 @@ struct IMGUI_API ImGuiWindowTempData
|
||||
// Local parameters stacks
|
||||
// We store the current settings outside of the vectors to increase memory locality (reduce cache misses). The vectors are rarely modified. Also it allows us to not heap allocate for short-lived windows which are not using those settings.
|
||||
float ItemWidth; // Current item width (>0.0: width in pixels, <0.0: align xx pixels to the right of window).
|
||||
float ItemWidthDefault;
|
||||
float TextWrapPos; // Current text wrap pos.
|
||||
ImVector<float> ItemWidthStack; // Store item widths to restore (attention: .back() is not == ItemWidth)
|
||||
ImVector<float> TextWrapPosStack; // Store text wrap pos to restore (attention: .back() is not == TextWrapPos)
|
||||
@@ -2928,7 +2957,6 @@ struct IMGUI_API ImGuiWindow
|
||||
int LastFrameActive; // Last frame number the window was Active.
|
||||
int LastFrameJustFocused; // Last frame number the window was made Focused.
|
||||
float LastTimeActive; // Last timestamp the window was Active (using float as we don't need high precision there)
|
||||
float ItemWidthDefault;
|
||||
ImGuiStorage StateStorage;
|
||||
ImVector<ImGuiOldColumns> ColumnsStorage;
|
||||
float FontWindowScale; // User scale multiplier per-window, via SetWindowFontScale()
|
||||
@@ -3017,7 +3045,7 @@ struct ImGuiTabItem
|
||||
ImGuiWindow* Window; // When TabItem is part of a DockNode's TabBar, we hold on to a window.
|
||||
int LastFrameVisible;
|
||||
int LastFrameSelected; // This allows us to infer an ordered list of the last activated tabs with little maintenance
|
||||
float Offset; // Position relative to beginning of tab
|
||||
float Offset; // Position relative to beginning of tab bar
|
||||
float Width; // Width currently displayed
|
||||
float ContentWidth; // Width of label + padding, stored during BeginTabItem() call (misnamed as "Content" would normally imply width of label only)
|
||||
float RequestedWidth; // Width optionally requested by caller, -1.0f is unused
|
||||
@@ -3026,7 +3054,7 @@ struct ImGuiTabItem
|
||||
ImS16 IndexDuringLayout; // Index only used during TabBarLayout(). Tabs gets reordered so 'Tabs[n].IndexDuringLayout == n' but may mismatch during additions.
|
||||
bool WantClose; // Marked as closed by SetTabItemClosed()
|
||||
|
||||
ImGuiTabItem() { memset(this, 0, sizeof(*this)); LastFrameVisible = LastFrameSelected = -1; RequestedWidth = -1.0f; NameOffset = -1; BeginOrder = IndexDuringLayout = -1; }
|
||||
ImGuiTabItem() { memset((void*)this, 0, sizeof(*this)); LastFrameVisible = LastFrameSelected = -1; RequestedWidth = -1.0f; NameOffset = -1; BeginOrder = IndexDuringLayout = -1; }
|
||||
};
|
||||
|
||||
// Storage for a tab bar (sizeof() 160 bytes)
|
||||
@@ -3038,6 +3066,7 @@ struct IMGUI_API ImGuiTabBar
|
||||
ImGuiID ID; // Zero for tab-bars used by docking
|
||||
ImGuiID SelectedTabId; // Selected tab/window
|
||||
ImGuiID NextSelectedTabId; // Next selected tab/window. Will also trigger a scrolling animation
|
||||
ImGuiID NextScrollToTabId;
|
||||
ImGuiID VisibleTabId; // Can occasionally be != SelectedTabId (e.g. when previewing contents for Ctrl+Tab preview)
|
||||
int CurrFrameVisible;
|
||||
int PrevFrameVisible;
|
||||
@@ -3130,7 +3159,7 @@ struct ImGuiTableColumn
|
||||
|
||||
ImGuiTableColumn()
|
||||
{
|
||||
memset(this, 0, sizeof(*this));
|
||||
memset((void*)this, 0, sizeof(*this));
|
||||
StretchWeight = WidthRequest = -1.0f;
|
||||
NameOffset = -1;
|
||||
DisplayOrder = IndexWithinEnabledSet = -1;
|
||||
@@ -3291,7 +3320,7 @@ struct IMGUI_API ImGuiTable
|
||||
bool MemoryCompacted;
|
||||
bool HostSkipItems; // Backup of InnerWindow->SkipItem at the end of BeginTable(), because we will overwrite InnerWindow->SkipItem on a per-column basis
|
||||
|
||||
ImGuiTable() { memset(this, 0, sizeof(*this)); LastFrameActive = -1; }
|
||||
ImGuiTable() { memset((void*)this, 0, sizeof(*this)); LastFrameActive = -1; }
|
||||
~ImGuiTable() { IM_FREE(RawData); }
|
||||
};
|
||||
|
||||
@@ -3320,7 +3349,7 @@ struct IMGUI_API ImGuiTableTempData
|
||||
float HostBackupItemWidth; // Backup of OuterWindow->DC.ItemWidth at the end of BeginTable()
|
||||
int HostBackupItemWidthStackSize;//Backup of OuterWindow->DC.ItemWidthStack.Size at the end of BeginTable()
|
||||
|
||||
ImGuiTableTempData() { memset(this, 0, sizeof(*this)); LastTimeActive = -1.0f; }
|
||||
ImGuiTableTempData() { memset((void*)this, 0, sizeof(*this)); LastTimeActive = -1.0f; }
|
||||
};
|
||||
|
||||
// sizeof() ~ 16
|
||||
@@ -3357,7 +3386,7 @@ struct ImGuiTableSettings
|
||||
ImGuiTableColumnIdx ColumnsCountMax; // Maximum number of columns this settings instance can store, we can recycle a settings instance with lower number of columns but not higher
|
||||
bool WantApply; // Set when loaded from .ini data (to enable merging/loading .ini data into an already running context)
|
||||
|
||||
ImGuiTableSettings() { memset(this, 0, sizeof(*this)); }
|
||||
ImGuiTableSettings() { memset((void*)this, 0, sizeof(*this)); }
|
||||
ImGuiTableColumnSettings* GetColumnSettings() { return (ImGuiTableColumnSettings*)(this + 1); }
|
||||
};
|
||||
|
||||
@@ -3375,6 +3404,7 @@ namespace ImGui
|
||||
// - You are calling ImGui functions after ImGui::EndFrame()/ImGui::Render() and before the next ImGui::NewFrame(), which is also illegal.
|
||||
IMGUI_API ImGuiIO& GetIO(ImGuiContext* ctx);
|
||||
IMGUI_API ImGuiPlatformIO& GetPlatformIO(ImGuiContext* ctx);
|
||||
inline float GetScale() { ImGuiContext& g = *GImGui; return g.Style._MainScale; } // FIXME-DPI: I don't want to formalize this just yet. Because reasons. Please don't use.
|
||||
inline ImGuiWindow* GetCurrentWindowRead() { ImGuiContext& g = *GImGui; return g.CurrentWindow; }
|
||||
inline ImGuiWindow* GetCurrentWindow() { ImGuiContext& g = *GImGui; g.CurrentWindow->WriteAccessed = true; return g.CurrentWindow; }
|
||||
IMGUI_API ImGuiWindow* FindWindowByID(ImGuiID id);
|
||||
@@ -3431,6 +3461,12 @@ namespace ImGui
|
||||
IMGUI_API void Initialize();
|
||||
IMGUI_API void Shutdown(); // Since 1.60 this is a _private_ function. You can call DestroyContext() to destroy the context created by CreateContext().
|
||||
|
||||
// Context name & generic context hooks
|
||||
IMGUI_API void SetContextName(ImGuiContext* ctx, const char* name);
|
||||
IMGUI_API ImGuiID AddContextHook(ImGuiContext* ctx, const ImGuiContextHook* hook);
|
||||
IMGUI_API void RemoveContextHook(ImGuiContext* ctx, ImGuiID hook_to_remove);
|
||||
IMGUI_API void CallContextHooks(ImGuiContext* ctx, ImGuiContextHookType type);
|
||||
|
||||
// NewFrame
|
||||
IMGUI_API void UpdateInputEvents(bool trickle_fast_inputs);
|
||||
IMGUI_API void UpdateHoveredWindowAndCaptureFlags(const ImVec2& mouse_pos);
|
||||
@@ -3441,11 +3477,6 @@ namespace ImGui
|
||||
IMGUI_API void UpdateMouseMovingWindowNewFrame();
|
||||
IMGUI_API void UpdateMouseMovingWindowEndFrame();
|
||||
|
||||
// Generic context hooks
|
||||
IMGUI_API ImGuiID AddContextHook(ImGuiContext* context, const ImGuiContextHook* hook);
|
||||
IMGUI_API void RemoveContextHook(ImGuiContext* context, ImGuiID hook_to_remove);
|
||||
IMGUI_API void CallContextHooks(ImGuiContext* context, ImGuiContextHookType type);
|
||||
|
||||
// Viewports
|
||||
IMGUI_API void TranslateWindowsInViewport(ImGuiViewportP* viewport, const ImVec2& old_pos, const ImVec2& new_pos, const ImVec2& old_size, const ImVec2& new_size);
|
||||
IMGUI_API void ScaleWindowsInViewport(ImGuiViewportP* viewport, float scale);
|
||||
@@ -3489,7 +3520,6 @@ namespace ImGui
|
||||
|
||||
// Basic Accessors
|
||||
inline ImGuiItemStatusFlags GetItemStatusFlags() { ImGuiContext& g = *GImGui; return g.LastItemData.StatusFlags; }
|
||||
inline ImGuiItemFlags GetItemFlags() { ImGuiContext& g = *GImGui; return g.LastItemData.ItemFlags; }
|
||||
inline ImGuiID GetActiveID() { ImGuiContext& g = *GImGui; return g.ActiveId; }
|
||||
inline ImGuiID GetFocusID() { ImGuiContext& g = *GImGui; return g.NavId; }
|
||||
IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window);
|
||||
@@ -3545,6 +3575,9 @@ namespace ImGui
|
||||
IMGUI_API ImGuiWindow* FindBlockingModal(ImGuiWindow* window);
|
||||
IMGUI_API ImVec2 FindBestWindowPosForPopup(ImGuiWindow* window);
|
||||
IMGUI_API ImVec2 FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy);
|
||||
IMGUI_API ImGuiMouseButton GetMouseButtonFromPopupFlags(ImGuiPopupFlags flags);
|
||||
IMGUI_API bool IsPopupOpenRequestForItem(ImGuiPopupFlags flags, ImGuiID id);
|
||||
IMGUI_API bool IsPopupOpenRequestForWindow(ImGuiPopupFlags flags);
|
||||
|
||||
// Tooltips
|
||||
IMGUI_API bool BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags extra_window_flags);
|
||||
@@ -3807,6 +3840,7 @@ namespace ImGui
|
||||
IMGUI_API void TableMergeDrawChannels(ImGuiTable* table);
|
||||
inline ImGuiTableInstanceData* TableGetInstanceData(ImGuiTable* table, int instance_no) { if (instance_no == 0) return &table->InstanceDataFirst; return &table->InstanceDataExtra[instance_no - 1]; }
|
||||
inline ImGuiID TableGetInstanceID(ImGuiTable* table, int instance_no) { return TableGetInstanceData(table, instance_no)->TableInstanceID; }
|
||||
IMGUI_API void TableFixDisplayOrder(ImGuiTable* table);
|
||||
IMGUI_API void TableSortSpecsSanitize(ImGuiTable* table);
|
||||
IMGUI_API void TableSortSpecsBuild(ImGuiTable* table);
|
||||
IMGUI_API ImGuiSortDirection TableGetColumnNextSortDirection(ImGuiTableColumn* column);
|
||||
@@ -3822,6 +3856,7 @@ namespace ImGui
|
||||
IMGUI_API float TableCalcMaxColumnWidth(const ImGuiTable* table, int column_n);
|
||||
IMGUI_API void TableSetColumnWidthAutoSingle(ImGuiTable* table, int column_n);
|
||||
IMGUI_API void TableSetColumnWidthAutoAll(ImGuiTable* table);
|
||||
IMGUI_API void TableSetColumnDisplayOrder(ImGuiTable* table, int column_n, int dst_order);
|
||||
IMGUI_API void TableRemove(ImGuiTable* table);
|
||||
IMGUI_API void TableGcCompactTransientBuffers(ImGuiTable* table);
|
||||
IMGUI_API void TableGcCompactTransientBuffers(ImGuiTableTempData* table);
|
||||
@@ -3872,6 +3907,7 @@ namespace ImGui
|
||||
IMGUI_API void RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float ellipsis_max_x, const char* text, const char* text_end, const ImVec2* text_size_if_known);
|
||||
IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool borders = true, float rounding = 0.0f);
|
||||
IMGUI_API void RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding = 0.0f);
|
||||
IMGUI_API void RenderColorComponentMarker(const ImRect& bb, ImU32 col, float rounding);
|
||||
IMGUI_API void RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, float grid_step, ImVec2 grid_off, float rounding = 0.0f, ImDrawFlags flags = 0);
|
||||
IMGUI_API void RenderNavCursor(const ImRect& bb, ImGuiID id, ImGuiNavRenderCursorFlags flags = ImGuiNavRenderCursorFlags_None); // Navigation highlight
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
@@ -3886,7 +3922,7 @@ namespace ImGui
|
||||
IMGUI_API void RenderCheckMark(ImDrawList* draw_list, ImVec2 pos, ImU32 col, float sz);
|
||||
IMGUI_API void RenderArrowPointingAt(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, ImGuiDir direction, ImU32 col);
|
||||
IMGUI_API void RenderArrowDockMenu(ImDrawList* draw_list, ImVec2 p_min, float sz, ImU32 col);
|
||||
IMGUI_API void RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, ImU32 col, float x_start_norm, float x_end_norm, float rounding);
|
||||
IMGUI_API void RenderRectFilledInRangeH(ImDrawList* draw_list, const ImRect& rect, ImU32 col, float fill_x0, float fill_x1, float rounding);
|
||||
IMGUI_API void RenderRectFilledWithHole(ImDrawList* draw_list, const ImRect& outer, const ImRect& inner, ImU32 col, float rounding);
|
||||
IMGUI_API ImDrawFlags CalcRoundingFlagsForRectInRect(const ImRect& r_in, const ImRect& r_outer, float threshold);
|
||||
|
||||
@@ -3913,6 +3949,7 @@ namespace ImGui
|
||||
IMGUI_API ImGuiID GetWindowScrollbarID(ImGuiWindow* window, ImGuiAxis axis);
|
||||
IMGUI_API ImGuiID GetWindowResizeCornerID(ImGuiWindow* window, int n); // 0..3: corners
|
||||
IMGUI_API ImGuiID GetWindowResizeBorderID(ImGuiWindow* window, ImGuiDir dir);
|
||||
IMGUI_API void ExtendHitBoxWhenNearViewportEdge(ImGuiWindow* window, ImRect* bb, float threshold, ImGuiAxis axis);
|
||||
|
||||
// Widgets low-level behaviors
|
||||
IMGUI_API bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags = 0);
|
||||
@@ -3925,15 +3962,14 @@ namespace ImGui
|
||||
IMGUI_API void TreeNodeDrawLineToChildNode(const ImVec2& target_pos);
|
||||
IMGUI_API void TreeNodeDrawLineToTreePop(const ImGuiTreeNodeStackData* data);
|
||||
IMGUI_API void TreePushOverrideID(ImGuiID id);
|
||||
IMGUI_API bool TreeNodeGetOpen(ImGuiID storage_id);
|
||||
IMGUI_API void TreeNodeSetOpen(ImGuiID storage_id, bool open);
|
||||
IMGUI_API bool TreeNodeUpdateNextOpen(ImGuiID storage_id, ImGuiTreeNodeFlags flags); // Return open state. Consume previous SetNextItemOpen() data, if any. May return true when logging.
|
||||
|
||||
// Template functions are instantiated in imgui_widgets.cpp for a finite number of types.
|
||||
// To use them externally (for custom widget) you may need an "extern template" statement in your code in order to link to existing instances and silence Clang warnings (see #2036).
|
||||
// e.g. " extern template IMGUI_API float RoundScalarWithFormatT<float, float>(const char* format, ImGuiDataType data_type, float v); "
|
||||
template<typename T, typename SIGNED_T, typename FLOAT_T> IMGUI_API float ScaleRatioFromValueT(ImGuiDataType data_type, T v, T v_min, T v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_size);
|
||||
template<typename T, typename SIGNED_T, typename FLOAT_T> IMGUI_API T ScaleValueFromRatioT(ImGuiDataType data_type, float t, T v_min, T v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_size);
|
||||
template<typename T, typename SIGNED_T, typename FLOAT_T> IMGUI_API float ScaleRatioFromValueT(ImGuiDataType data_type, T v, T v_min, T v_max, float logarithmic_zero_epsilon, float zero_deadzone_size);
|
||||
template<typename T, typename SIGNED_T, typename FLOAT_T> IMGUI_API T ScaleValueFromRatioT(ImGuiDataType data_type, float t, T v_min, T v_max, float logarithmic_zero_epsilon, float zero_deadzone_size);
|
||||
template<typename T, typename SIGNED_T, typename FLOAT_T> IMGUI_API bool DragBehaviorT(ImGuiDataType data_type, T* v, float v_speed, T v_min, T v_max, const char* format, ImGuiSliderFlags flags);
|
||||
template<typename T, typename SIGNED_T, typename FLOAT_T> IMGUI_API bool SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, T* v, T v_min, T v_max, const char* format, ImGuiSliderFlags flags, ImRect* out_grab_bb);
|
||||
template<typename T> IMGUI_API T RoundScalarWithFormatT(const char* format, ImGuiDataType data_type, T v);
|
||||
@@ -3953,7 +3989,7 @@ namespace ImGui
|
||||
IMGUI_API void InputTextDeactivateHook(ImGuiID id);
|
||||
IMGUI_API bool TempInputText(const ImRect& bb, ImGuiID id, const char* label, char* buf, int buf_size, ImGuiInputTextFlags flags);
|
||||
IMGUI_API bool TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format, const void* p_clamp_min = NULL, const void* p_clamp_max = NULL);
|
||||
inline bool TempInputIsActive(ImGuiID id) { ImGuiContext& g = *GImGui; return (g.ActiveId == id && g.TempInputId == id); }
|
||||
inline bool TempInputIsActive(ImGuiID id) { ImGuiContext& g = *GImGui; return g.ActiveId == id && g.TempInputId == id; }
|
||||
inline ImGuiInputTextState* GetInputTextState(ImGuiID id) { ImGuiContext& g = *GImGui; return (id != 0 && g.InputTextState.ID == id) ? &g.InputTextState : NULL; } // Get input text state if active
|
||||
IMGUI_API void SetNextItemRefVal(ImGuiDataType data_type, void* p_data);
|
||||
inline bool IsItemActiveAsInputText() { ImGuiContext& g = *GImGui; return g.ActiveId != 0 && g.ActiveId == g.LastItemData.ID && g.InputTextState.ID == g.LastItemData.ID; } // This may be useful to apply workaround that a based on distinguish whenever an item is active as a text input field.
|
||||
@@ -3962,6 +3998,7 @@ namespace ImGui
|
||||
IMGUI_API void ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags flags);
|
||||
IMGUI_API void ColorEditOptionsPopup(const float* col, ImGuiColorEditFlags flags);
|
||||
IMGUI_API void ColorPickerOptionsPopup(const float* ref_col, ImGuiColorEditFlags flags);
|
||||
inline void SetNextItemColorMarker(ImU32 col) { ImGuiContext& g = *GImGui; g.NextItemData.HasFlags |= ImGuiNextItemDataFlags_HasColorMarker; g.NextItemData.ColorMarker = col; }
|
||||
|
||||
// Plot
|
||||
IMGUI_API int 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);
|
||||
@@ -3986,6 +4023,9 @@ namespace ImGui
|
||||
IMGUI_API bool BeginErrorTooltip();
|
||||
IMGUI_API void EndErrorTooltip();
|
||||
|
||||
// Demo Doc Marker for e.g. imgui_explorer
|
||||
IMGUI_API void DemoMarker(const char* file, int line, const char* section);
|
||||
|
||||
// Debug Tools
|
||||
IMGUI_API void DebugAllocHook(ImGuiDebugAllocInfo* info, int frame_count, void* ptr, size_t size); // size >= 0 : alloc, size = -1 : free
|
||||
IMGUI_API void DebugDrawCursorPos(ImU32 col = IM_COL32(255, 0, 0, 255));
|
||||
@@ -3999,13 +4039,14 @@ namespace ImGui
|
||||
IMGUI_API bool DebugBreakButton(const char* label, const char* description_of_location);
|
||||
IMGUI_API void DebugBreakButtonTooltip(bool keyboard_only, const char* description_of_location);
|
||||
IMGUI_API void ShowFontAtlas(ImFontAtlas* atlas);
|
||||
IMGUI_API ImU64 DebugTextureIDToU64(ImTextureID tex_id);
|
||||
IMGUI_API void DebugHookIdInfo(ImGuiID id, ImGuiDataType data_type, const void* data_id, const void* data_id_end);
|
||||
IMGUI_API void DebugNodeColumns(ImGuiOldColumns* columns);
|
||||
IMGUI_API void DebugNodeDockNode(ImGuiDockNode* node, const char* label);
|
||||
IMGUI_API void DebugNodeDrawList(ImGuiWindow* window, ImGuiViewportP* viewport, const ImDrawList* draw_list, const char* label);
|
||||
IMGUI_API void DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list, const ImDrawList* draw_list, const ImDrawCmd* draw_cmd, bool show_mesh, bool show_aabb);
|
||||
IMGUI_API void DebugNodeFont(ImFont* font);
|
||||
IMGUI_API void DebugNodeFontGlyphesForSrcMask(ImFont* font, ImFontBaked* baked, int src_mask);
|
||||
IMGUI_API void DebugNodeFontGlyphsForSrcMask(ImFont* font, ImFontBaked* baked, int src_mask);
|
||||
IMGUI_API void DebugNodeFontGlyph(ImFont* font, const ImFontGlyph* glyph);
|
||||
IMGUI_API void DebugNodeTexture(ImTextureData* tex, int int_id, const ImFontAtlasRect* highlight_rect = NULL); // ID used to facilitate persisting the "current" texture.
|
||||
IMGUI_API void DebugNodeStorage(ImGuiStorage* storage, const char* label);
|
||||
@@ -4064,14 +4105,14 @@ struct ImFontLoader
|
||||
// FIXME: At this point the two other types of buffers may be managed by core to be consistent?
|
||||
size_t FontBakedSrcLoaderDataSize;
|
||||
|
||||
ImFontLoader() { memset(this, 0, sizeof(*this)); }
|
||||
ImFontLoader() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
#ifdef IMGUI_ENABLE_STB_TRUETYPE
|
||||
IMGUI_API const ImFontLoader* ImFontAtlasGetFontLoaderForStbTruetype();
|
||||
#endif
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
typedef ImFontLoader ImFontBuilderIO; // [renamed/changed in 1.92] The types are not actually compatible but we provide this as a compile-time error report helper.
|
||||
typedef ImFontLoader ImFontBuilderIO; // [renamed/changed in 1.92.0] The types are not actually compatible but we provide this as a compile-time error report helper.
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -4161,7 +4202,7 @@ struct ImFontAtlasBuilder
|
||||
ImFontAtlasRectId PackIdMouseCursors; // White pixel + mouse cursors. Also happen to be fallback in case of packing failure.
|
||||
ImFontAtlasRectId PackIdLinesTexData;
|
||||
|
||||
ImFontAtlasBuilder() { memset(this, 0, sizeof(*this)); FrameCount = -1; RectsIndexFreeListStart = -1; PackIdMouseCursors = PackIdLinesTexData = -1; }
|
||||
ImFontAtlasBuilder() { memset((void*)this, 0, sizeof(*this)); FrameCount = -1; RectsIndexFreeListStart = -1; PackIdMouseCursors = PackIdLinesTexData = -1; }
|
||||
};
|
||||
|
||||
IMGUI_API void ImFontAtlasBuildInit(ImFontAtlas* atlas);
|
||||
@@ -4190,6 +4231,7 @@ IMGUI_API void ImFontAtlasFontSourceAddToFont(ImFontAtlas* atlas, I
|
||||
IMGUI_API void ImFontAtlasFontDestroySourceData(ImFontAtlas* atlas, ImFontConfig* src);
|
||||
IMGUI_API bool ImFontAtlasFontInitOutput(ImFontAtlas* atlas, ImFont* font); // Using FontDestroyOutput/FontInitOutput sequence useful notably if font loader params have changed
|
||||
IMGUI_API void ImFontAtlasFontDestroyOutput(ImFontAtlas* atlas, ImFont* font);
|
||||
IMGUI_API void ImFontAtlasFontRebuildOutput(ImFontAtlas* atlas, ImFont* font);
|
||||
IMGUI_API void ImFontAtlasFontDiscardBakes(ImFontAtlas* atlas, ImFont* font, int unused_frames);
|
||||
|
||||
IMGUI_API ImGuiID ImFontAtlasBakedGetId(ImGuiID font_id, float baked_size, float rasterizer_density);
|
||||
|
||||
@@ -315,7 +315,7 @@ static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0
|
||||
if (node->y > min_y) {
|
||||
// raise min_y higher.
|
||||
// we've accounted for all waste up to min_y,
|
||||
// but we'll now add more waste for everything we've visted
|
||||
// but we'll now add more waste for everything we've visited
|
||||
waste_area += visited_width * (node->y - min_y);
|
||||
min_y = node->y;
|
||||
// the first time through, visited_width might be reduced
|
||||
@@ -470,7 +470,7 @@ static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, i
|
||||
|
||||
// insert the new node into the right starting point, and
|
||||
// let 'cur' point to the remaining nodes needing to be
|
||||
// stiched back in
|
||||
// stitched back in
|
||||
|
||||
cur = *res.prev_link;
|
||||
if (cur->x < res.x) {
|
||||
|
||||
@@ -886,7 +886,7 @@ STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, fl
|
||||
// xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap
|
||||
|
||||
STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff);
|
||||
// the same as stbtt_GetCodepoitnBitmap, but you can specify a subpixel
|
||||
// the same as stbtt_GetCodepointBitmap, but you can specify a subpixel
|
||||
// shift for the character
|
||||
|
||||
STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint);
|
||||
|
||||
894
lib/third_party/imgui/imgui/source/imgui.cpp
vendored
894
lib/third_party/imgui/imgui/source/imgui.cpp
vendored
File diff suppressed because it is too large
Load Diff
1066
lib/third_party/imgui/imgui/source/imgui_demo.cpp
vendored
1066
lib/third_party/imgui/imgui/source/imgui_demo.cpp
vendored
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user