mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-04-01 21:17:44 -05:00
Compare commits
344 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
77c1ee3e7a | ||
|
|
4be2c33985 | ||
|
|
3034d79373 | ||
|
|
e7daa586ba | ||
|
|
3f4bdfdf61 | ||
|
|
ab5860dc9a | ||
|
|
53b2347358 | ||
|
|
a195179101 | ||
|
|
fdccc55805 | ||
|
|
55dce338b2 | ||
|
|
03c217addb | ||
|
|
a3a3f52b48 | ||
|
|
477b284041 | ||
|
|
b52495bc33 | ||
|
|
46ed451712 | ||
|
|
963afdce96 | ||
|
|
3f18a9a536 | ||
|
|
64b226e12d | ||
|
|
b74dc3d8b9 | ||
|
|
9668a885e8 | ||
|
|
b7afbf4a74 | ||
|
|
4784a82d51 | ||
|
|
a1ff1af754 | ||
|
|
5c6b20c0ec | ||
|
|
79af360822 | ||
|
|
fb23708220 | ||
|
|
93f6ab25e6 | ||
|
|
6faefed4f4 | ||
|
|
6a159be861 | ||
|
|
d7b43b54f9 | ||
|
|
1a92425995 | ||
|
|
347bdd9508 | ||
|
|
b80e8b63c9 | ||
|
|
621d529682 | ||
|
|
6005af1595 | ||
|
|
9a4329807a | ||
|
|
8e01da4c12 | ||
|
|
eb8ea520c7 | ||
|
|
512fcd361b | ||
|
|
aad6f6bcbe | ||
|
|
0af21505d7 | ||
|
|
2ae69e8e72 | ||
|
|
9274fac8e1 | ||
|
|
e2f82c60e6 | ||
|
|
bfddf24204 | ||
|
|
382599dcf6 | ||
|
|
5f2c07f2d8 | ||
|
|
914024c0b5 | ||
|
|
c5d3387962 | ||
|
|
7cc99c6fc9 | ||
|
|
a29b502a33 | ||
|
|
20cb74364f | ||
|
|
1c5a50c8d8 | ||
|
|
470523cc86 | ||
|
|
f6bc3d4650 | ||
|
|
41b1228d31 | ||
|
|
2cb4462274 | ||
|
|
810cd40ccd | ||
|
|
f931beb49a | ||
|
|
1c3dfc9b2f | ||
|
|
a1d4545e29 | ||
|
|
8865db2007 | ||
|
|
d2056d9409 | ||
|
|
74e74ddc38 | ||
|
|
5fcb737559 | ||
|
|
9303025427 | ||
|
|
680985fc13 | ||
|
|
5a360eb614 | ||
|
|
4a74bd78fd | ||
|
|
0f53656952 | ||
|
|
9ca40d3651 | ||
|
|
ab12503f62 | ||
|
|
b446d7fd4a | ||
|
|
fd46d85762 | ||
|
|
fa421afb00 | ||
|
|
a79d3e28ca | ||
|
|
fbb4f65735 | ||
|
|
00c62c90f6 | ||
|
|
384aa6e6a9 | ||
|
|
1c755249ec | ||
|
|
2c303b5bf2 | ||
|
|
415e3b4a93 | ||
|
|
8d9b056c8c | ||
|
|
a527a7f0b0 | ||
|
|
d78d955d11 | ||
|
|
9375a60cd9 | ||
|
|
bb99b9a0ef | ||
|
|
313e59d7f9 | ||
|
|
e34e0e62f2 | ||
|
|
212f75f1cb | ||
|
|
a07c79efcb | ||
|
|
89090b25e3 | ||
|
|
721164e562 | ||
|
|
b8ba980a20 | ||
|
|
79ded38434 | ||
|
|
f52db884a9 | ||
|
|
ee4bb33b0a | ||
|
|
caf8fa8e25 | ||
|
|
c46dea4c9e | ||
|
|
002b7b4f87 | ||
|
|
0a6a8c671f | ||
|
|
36014b706d | ||
|
|
df5e01d4eb | ||
|
|
c6f1525f55 | ||
|
|
5511259f2d | ||
|
|
f2ea7ca5d1 | ||
|
|
6184bbeae2 | ||
|
|
21506578f5 | ||
|
|
f39f395393 | ||
|
|
ed0a94659e | ||
|
|
7f75706584 | ||
|
|
3f316e42f2 | ||
|
|
4a331c0331 | ||
|
|
6a28de100c | ||
|
|
992f18b94b | ||
|
|
040a606b39 | ||
|
|
13e079d1b8 | ||
|
|
d9a7f40eb4 | ||
|
|
8d123da847 | ||
|
|
093310a9e5 | ||
|
|
21b315b97e | ||
|
|
c70cc3a6f1 | ||
|
|
1e71d8afc0 | ||
|
|
cb6b74b269 | ||
|
|
a1e399aa1a | ||
|
|
e1dfdd9400 | ||
|
|
6ab2e81f1c | ||
|
|
cf09029847 | ||
|
|
d02e170dac | ||
|
|
2b715bb0de | ||
|
|
2dcaf2c77b | ||
|
|
1b9f4f33de | ||
|
|
3c73f88a52 | ||
|
|
8acdc19be4 | ||
|
|
22252d9044 | ||
|
|
5948a74ad1 | ||
|
|
e46d9d7650 | ||
|
|
813276c907 | ||
|
|
7032473ecf | ||
|
|
807f1fb561 | ||
|
|
296f80ffe5 | ||
|
|
d45e0d1cac | ||
|
|
4b8f9984d5 | ||
|
|
7623610704 | ||
|
|
a7fe384a31 | ||
|
|
485ce887ea | ||
|
|
2a0bb79513 | ||
|
|
21ae88702f | ||
|
|
0ff1bb392c | ||
|
|
01af2f364c | ||
|
|
a639dddd19 | ||
|
|
71ec6c5061 | ||
|
|
8c4c4f5e8b | ||
|
|
2c2d3b2de3 | ||
|
|
caae5c9711 | ||
|
|
72822d03aa | ||
|
|
9de3dd89c5 | ||
|
|
bcb69b9855 | ||
|
|
6d2761f141 | ||
|
|
05c25b6aff | ||
|
|
9be9eb90f6 | ||
|
|
71f2f3a5fc | ||
|
|
862b1d407c | ||
|
|
5da0da48c8 | ||
|
|
3f1a51e350 | ||
|
|
d167e43252 | ||
|
|
fe9eecd031 | ||
|
|
ded8cff415 | ||
|
|
3497716a00 | ||
|
|
c78b4a3343 | ||
|
|
17359be58a | ||
|
|
382a62343d | ||
|
|
7e0f60615b | ||
|
|
e1a49b38a7 | ||
|
|
4333b8c351 | ||
|
|
6464377a89 | ||
|
|
4fcf732814 | ||
|
|
0d4f3e5735 | ||
|
|
1f2e453e20 | ||
|
|
5236c7b468 | ||
|
|
1738e8883f | ||
|
|
cc4563afb0 | ||
|
|
4b3bf2f358 | ||
|
|
80084f5c5a | ||
|
|
6d14b3f6bd | ||
|
|
592f613a61 | ||
|
|
3739bcc40c | ||
|
|
101c7a36fb | ||
|
|
21be959cba | ||
|
|
b3a0ebe7b6 | ||
|
|
96a588bd86 | ||
|
|
866b956680 | ||
|
|
d88252c6fd | ||
|
|
414e7d36a0 | ||
|
|
e0b4931a54 | ||
|
|
a587c5ff74 | ||
|
|
0b2eca3066 | ||
|
|
fa28052958 | ||
|
|
54f5bd1d80 | ||
|
|
4b3bbb4a97 | ||
|
|
187d90e8f2 | ||
|
|
2f60f61c15 | ||
|
|
057543da15 | ||
|
|
3c060cc57a | ||
|
|
928b4c6c4c | ||
|
|
871a0d535c | ||
|
|
87db9def32 | ||
|
|
04763eaeea | ||
|
|
b6c08a1a11 | ||
|
|
811c995047 | ||
|
|
7011df2ced | ||
|
|
a24692b4be | ||
|
|
0e7a32470b | ||
|
|
212d2f9db4 | ||
|
|
0263d3538e | ||
|
|
63c6028522 | ||
|
|
075ece2da7 | ||
|
|
e9fb02285e | ||
|
|
5dfd8c89a3 | ||
|
|
e9f7908afb | ||
|
|
fafce72c01 | ||
|
|
c3d15157ad | ||
|
|
e0712f73c2 | ||
|
|
3dd5b2365a | ||
|
|
b523f55984 | ||
|
|
79b8b77b25 | ||
|
|
c6065808a7 | ||
|
|
d69ae39b6f | ||
|
|
35739d6d0d | ||
|
|
e726fce360 | ||
|
|
0a038fecff | ||
|
|
0184bf9a7d | ||
|
|
60663babc8 | ||
|
|
a7115d4300 | ||
|
|
29558c9910 | ||
|
|
7c1d643f97 | ||
|
|
b2fc80f970 | ||
|
|
efee128c1c | ||
|
|
c3ddd68866 | ||
|
|
3cde4472c8 | ||
|
|
4c38fe261d | ||
|
|
33f7191c0d | ||
|
|
cda9ad3b30 | ||
|
|
1a7bd49361 | ||
|
|
cf2e189049 | ||
|
|
d5f5ba941a | ||
|
|
9a973be7ba | ||
|
|
d8e1284946 | ||
|
|
ce26fe1db7 | ||
|
|
a8ad045248 | ||
|
|
d097f6ada0 | ||
|
|
1b26db40f7 | ||
|
|
602b946fc9 | ||
|
|
48fc1a7a1e | ||
|
|
416889f49d | ||
|
|
5ca3222e5b | ||
|
|
d49d82e982 | ||
|
|
a4d5679219 | ||
|
|
bead103f3d | ||
|
|
e50b6733c4 | ||
|
|
75e5dbaaa4 | ||
|
|
965113c2b4 | ||
|
|
3bddaf509d | ||
|
|
c1c51e0baf | ||
|
|
09b6c2ab5b | ||
|
|
13fd956039 | ||
|
|
b6f0ee90af | ||
|
|
90e11e1c5d | ||
|
|
fc40e8ba70 | ||
|
|
7652b4a5b8 | ||
|
|
fb249767f1 | ||
|
|
d7ed311bcf | ||
|
|
8422965d0b | ||
|
|
7975edade4 | ||
|
|
1e18935513 | ||
|
|
c311b5315f | ||
|
|
26a73e0fba | ||
|
|
07c259c9c1 | ||
|
|
9e1c2d5a2c | ||
|
|
d7fb1b737f | ||
|
|
84c9c69fa3 | ||
|
|
12ca4e29cf | ||
|
|
27b1a5dc98 | ||
|
|
de36cc8445 | ||
|
|
03d344c0a2 | ||
|
|
39f01538c7 | ||
|
|
28c57cf666 | ||
|
|
59d120537d | ||
|
|
66d18e9475 | ||
|
|
1f5e4ceb0c | ||
|
|
0cbc65a52f | ||
|
|
2b0367cca6 | ||
|
|
1f01f480e0 | ||
|
|
7a167962d6 | ||
|
|
dae028d25d | ||
|
|
88e2fa04e7 | ||
|
|
bb0a8047ea | ||
|
|
b652565b57 | ||
|
|
9aaf6f3105 | ||
|
|
c26eccfe28 | ||
|
|
9fd547112d | ||
|
|
14bfc8af72 | ||
|
|
20f3458e37 | ||
|
|
6326e2d141 | ||
|
|
23ca3c1d2d | ||
|
|
0656ab4b88 | ||
|
|
90bb5d187c | ||
|
|
75a62e2bde | ||
|
|
7cd36b80eb | ||
|
|
dd607621d7 | ||
|
|
2595febf14 | ||
|
|
dc058c4cf3 | ||
|
|
25824e1821 | ||
|
|
381c2d52ee | ||
|
|
4020ac9843 | ||
|
|
b3b7a19df4 | ||
|
|
313e3e748f | ||
|
|
09b9f26e6f | ||
|
|
01b9cc64d6 | ||
|
|
97bf1dc850 | ||
|
|
f94794fe3e | ||
|
|
68e528dd3a | ||
|
|
06ab1d34aa | ||
|
|
2f2717e9aa | ||
|
|
88d24c2a03 | ||
|
|
ec2a2a6fbb | ||
|
|
60b81e714b | ||
|
|
2cd8b13c1d | ||
|
|
4afedb5131 | ||
|
|
71880ad2ad | ||
|
|
a30cce4cbc | ||
|
|
08b4f60ead | ||
|
|
11498bd09b | ||
|
|
7384c88ad6 | ||
|
|
6f22d70d59 | ||
|
|
adc279d681 | ||
|
|
f90dc5d619 | ||
|
|
6fd594c1f4 | ||
|
|
b94a4288bf | ||
|
|
cbf415256b | ||
|
|
4b1884944d | ||
|
|
5ff752c9af | ||
|
|
0e331a7cd1 | ||
|
|
10970d170c |
7
.github/workflows/analysis.yml
vendored
7
.github/workflows/analysis.yml
vendored
@@ -8,7 +8,7 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
codeql:
|
codeql:
|
||||||
name: 🐛 CodeQL
|
name: 🐛 CodeQL
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-24.04
|
||||||
permissions:
|
permissions:
|
||||||
actions: read
|
actions: read
|
||||||
contents: read
|
contents: read
|
||||||
@@ -49,7 +49,7 @@ jobs:
|
|||||||
set -x
|
set -x
|
||||||
mkdir -p build
|
mkdir -p build
|
||||||
cd build
|
cd build
|
||||||
CC=gcc-12 CXX=g++-12 cmake \
|
CC=gcc-14 CXX=g++-14 cmake \
|
||||||
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
|
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
|
||||||
-DCMAKE_INSTALL_PREFIX="$PWD/install" \
|
-DCMAKE_INSTALL_PREFIX="$PWD/install" \
|
||||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||||
@@ -57,8 +57,9 @@ jobs:
|
|||||||
-DCMAKE_C_FLAGS="-fuse-ld=lld" \
|
-DCMAKE_C_FLAGS="-fuse-ld=lld" \
|
||||||
-DCMAKE_CXX_FLAGS="-fuse-ld=lld" \
|
-DCMAKE_CXX_FLAGS="-fuse-ld=lld" \
|
||||||
-DIMHEX_PATTERNS_PULL_MASTER=ON \
|
-DIMHEX_PATTERNS_PULL_MASTER=ON \
|
||||||
|
-G Ninja \
|
||||||
..
|
..
|
||||||
make -j 4 install
|
ninja install
|
||||||
|
|
||||||
- name: 🗯️ Perform CodeQL Analysis
|
- name: 🗯️ Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@v2
|
uses: github/codeql-action/analyze@v2
|
||||||
208
.github/workflows/build.yml
vendored
208
.github/workflows/build.yml
vendored
@@ -64,7 +64,7 @@ jobs:
|
|||||||
cd build
|
cd build
|
||||||
|
|
||||||
cmake -G "Ninja" \
|
cmake -G "Ninja" \
|
||||||
-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \
|
-DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \
|
||||||
-DCMAKE_INSTALL_PREFIX="$PWD/install" \
|
-DCMAKE_INSTALL_PREFIX="$PWD/install" \
|
||||||
-DIMHEX_GENERATE_PACKAGE=ON \
|
-DIMHEX_GENERATE_PACKAGE=ON \
|
||||||
-DIMHEX_USE_DEFAULT_BUILD_SETTINGS=ON \
|
-DIMHEX_USE_DEFAULT_BUILD_SETTINGS=ON \
|
||||||
@@ -82,7 +82,7 @@ jobs:
|
|||||||
cd build
|
cd build
|
||||||
ninja install
|
ninja install
|
||||||
cpack
|
cpack
|
||||||
mv ImHex-*.msi ../imhex-${{env.IMHEX_VERSION}}-Windows-x86_64.msi
|
mv ImHex-*.msi ../imhex-${{ env.IMHEX_VERSION }}-Windows-x86_64.msi
|
||||||
|
|
||||||
echo "ImHex checks for the existence of this file to determine if it is running in portable mode. You should not delete this file" > $PWD/install/PORTABLE
|
echo "ImHex checks for the existence of this file to determine if it is running in portable mode. You should not delete this file" > $PWD/install/PORTABLE
|
||||||
|
|
||||||
@@ -107,7 +107,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
set -x
|
set -x
|
||||||
echo "NoGPU version Powered by Mesa 3D : https://fdossena.com/?p=mesa%2Findex.frag" > build/install/MESA.md
|
echo "NoGPU version Powered by Mesa 3D : https://fdossena.com/?p=mesa%2Findex.frag" > build/install/MESA.md
|
||||||
curl https://werwolv.net/downloads/mesa/MesaForWindows-x64-latest.7z -L -o mesa.7z
|
curl https://downloads.fdossena.com/geth.php?r=mesa64-latest -L -o mesa.7z
|
||||||
7z e mesa.7z
|
7z e mesa.7z
|
||||||
mv opengl32.dll build/install
|
mv opengl32.dll build/install
|
||||||
|
|
||||||
@@ -119,9 +119,62 @@ jobs:
|
|||||||
path: |
|
path: |
|
||||||
build/install/*
|
build/install/*
|
||||||
|
|
||||||
|
win-plugin-template-test:
|
||||||
|
runs-on: windows-2022
|
||||||
|
name: 🧪 Plugin Template Test
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: msys2 {0}
|
||||||
|
needs: win
|
||||||
|
env:
|
||||||
|
IMHEX_SDK_PATH: "${{ github.workspace }}/out/sdk"
|
||||||
|
steps:
|
||||||
|
- name: 🧰 Checkout ImHex
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
path: imhex
|
||||||
|
|
||||||
|
- name: 🟦 Install msys2
|
||||||
|
uses: msys2/setup-msys2@v2
|
||||||
|
with:
|
||||||
|
msystem: mingw64
|
||||||
|
|
||||||
|
- name: ⬇️ Install dependencies
|
||||||
|
run: |
|
||||||
|
set -x
|
||||||
|
imhex/dist/get_deps_msys2.sh
|
||||||
|
|
||||||
|
- name: 🧰 Checkout ImHex-Plugin-Template
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
repository: WerWolv/ImHex-Plugin-Template
|
||||||
|
submodules: recursive
|
||||||
|
path: template
|
||||||
|
|
||||||
|
- name: ⬇️ Download artifact
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: Windows Portable x86_64
|
||||||
|
path: out
|
||||||
|
|
||||||
|
- name: 🛠️ Build
|
||||||
|
run: |
|
||||||
|
set -x
|
||||||
|
cd template
|
||||||
|
mkdir -p build
|
||||||
|
cd build
|
||||||
|
|
||||||
|
cmake -G "Ninja" \
|
||||||
|
-DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \
|
||||||
|
-DIMHEX_USE_DEFAULT_BUILD_SETTINGS=ON \
|
||||||
|
-DUSE_SYSTEM_CAPSTONE=ON \
|
||||||
|
..
|
||||||
|
|
||||||
|
ninja
|
||||||
|
|
||||||
# MacOS build
|
# MacOS build
|
||||||
macos:
|
macos:
|
||||||
runs-on: macos-12
|
runs-on: macos-13
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
@@ -132,7 +185,7 @@ jobs:
|
|||||||
- suffix: ""
|
- suffix: ""
|
||||||
custom_glfw: false
|
custom_glfw: false
|
||||||
|
|
||||||
name: 🍎 macOS 12.0${{matrix.suffix}}
|
name: 🍎 macOS 13${{ matrix.suffix }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: 🧰 Checkout
|
- name: 🧰 Checkout
|
||||||
@@ -153,14 +206,15 @@ jobs:
|
|||||||
|
|
||||||
- name: ⬇️ Install dependencies
|
- name: ⬇️ Install dependencies
|
||||||
run: |
|
run: |
|
||||||
brew reinstall python || brew link --overwrite python || true
|
brew reinstall python --quiet || true
|
||||||
brew bundle --no-lock --file dist/Brewfile
|
brew link --overwrite --quiet python || true
|
||||||
|
brew bundle --no-lock --quiet --file dist/Brewfile || true
|
||||||
rm -rf /usr/local/Cellar/capstone
|
rm -rf /usr/local/Cellar/capstone
|
||||||
|
|
||||||
- name: ⬇️ Install classic glfw
|
- name: ⬇️ Install classic glfw
|
||||||
if: ${{! matrix.custom_glfw}}
|
if: ${{! matrix.custom_glfw }}
|
||||||
run: |
|
run: |
|
||||||
brew install glfw || true
|
brew install --quiet glfw || true
|
||||||
|
|
||||||
- name: ⬇️ Install .NET
|
- name: ⬇️ Install .NET
|
||||||
uses: actions/setup-dotnet@v4
|
uses: actions/setup-dotnet@v4
|
||||||
@@ -168,7 +222,7 @@ jobs:
|
|||||||
dotnet-version: '8.0.100'
|
dotnet-version: '8.0.100'
|
||||||
|
|
||||||
- name: 🧰 Checkout glfw
|
- name: 🧰 Checkout glfw
|
||||||
if: ${{matrix.custom_glfw}}
|
if: ${{ matrix.custom_glfw }}
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
repository: glfw/glfw
|
repository: glfw/glfw
|
||||||
@@ -176,7 +230,7 @@ jobs:
|
|||||||
|
|
||||||
# GLFW custom build (to allow software rendering)
|
# GLFW custom build (to allow software rendering)
|
||||||
- name: ⬇️ Patch and install custom glfw
|
- name: ⬇️ Patch and install custom glfw
|
||||||
if: ${{matrix.custom_glfw}}
|
if: ${{ matrix.custom_glfw }}
|
||||||
run: |
|
run: |
|
||||||
set -x
|
set -x
|
||||||
cd glfw
|
cd glfw
|
||||||
@@ -186,7 +240,7 @@ jobs:
|
|||||||
cd build
|
cd build
|
||||||
|
|
||||||
cmake -G "Ninja" \
|
cmake -G "Ninja" \
|
||||||
-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \
|
-DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \
|
||||||
-DBUILD_SHARED_LIBS=ON \
|
-DBUILD_SHARED_LIBS=ON \
|
||||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||||
@@ -201,14 +255,15 @@ jobs:
|
|||||||
set -x
|
set -x
|
||||||
mkdir -p build
|
mkdir -p build
|
||||||
cd build
|
cd build
|
||||||
CC=$(brew --prefix gcc@12)/bin/gcc-12 \
|
CC=$(brew --prefix llvm)/bin/clang \
|
||||||
CXX=$(brew --prefix gcc@12)/bin/g++-12 \
|
CXX=$(brew --prefix llvm)/bin/clang++ \
|
||||||
OBJC=$(brew --prefix llvm)/bin/clang \
|
OBJC=$(brew --prefix llvm)/bin/clang \
|
||||||
OBJCXX=$(brew --prefix llvm)/bin/clang++ \
|
OBJCXX=$(brew --prefix llvm)/bin/clang++ \
|
||||||
PKG_CONFIG_PATH="$(brew --prefix openssl)/lib/pkgconfig":"$(brew --prefix)/lib/pkgconfig" \
|
PKG_CONFIG_PATH="$(brew --prefix openssl)/lib/pkgconfig":"$(brew --prefix)/lib/pkgconfig" \
|
||||||
cmake -G "Ninja" \
|
cmake -G "Ninja" \
|
||||||
-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \
|
-DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \
|
||||||
-DIMHEX_GENERATE_PACKAGE=ON \
|
-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" \
|
||||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||||
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
|
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
|
||||||
@@ -236,6 +291,12 @@ jobs:
|
|||||||
cd build/install
|
cd build/install
|
||||||
chmod -R 755 ImHex.app/
|
chmod -R 755 ImHex.app/
|
||||||
|
|
||||||
|
- name: 🔫 Kill XProtect
|
||||||
|
run: |
|
||||||
|
# See https://github.com/actions/runner-images/issues/7522
|
||||||
|
echo Killing XProtect...; sudo pkill -9 XProtect >/dev/null || true;
|
||||||
|
echo Waiting for XProtect process...; while pgrep XProtect; do sleep 3; done;
|
||||||
|
|
||||||
- name: 📦 Create DMG
|
- name: 📦 Create DMG
|
||||||
run: |
|
run: |
|
||||||
set -x
|
set -x
|
||||||
@@ -244,18 +305,24 @@ jobs:
|
|||||||
cd bundle
|
cd bundle
|
||||||
ln -s /Applications Applications
|
ln -s /Applications Applications
|
||||||
cd ..
|
cd ..
|
||||||
hdiutil create -volname "ImHex" -srcfolder bundle -ov -format UDZO imhex-${{env.IMHEX_VERSION}}-macOS${{matrix.suffix}}-x86_64.dmg
|
for i in $(seq 1 10); do
|
||||||
|
if hdiutil create -volname "ImHex" -srcfolder bundle -ov -format UDZO imhex-${{ env.IMHEX_VERSION }}-macOS${{ matrix.suffix }}-x86_64.dmg; then
|
||||||
|
echo "Created dmg after ${i} attempts"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
sleep 10
|
||||||
|
done
|
||||||
|
|
||||||
- name: ⬆️ Upload DMG
|
- name: ⬆️ Upload DMG
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
name: macOS DMG${{matrix.suffix}} x86_64
|
name: macOS DMG${{ matrix.suffix }} x86_64
|
||||||
path: ./*.dmg
|
path: ./*.dmg
|
||||||
|
|
||||||
macos-arm64-build:
|
macos-arm64-build:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-24.04
|
||||||
name: 🍎 macOS 12.1 arm64
|
name: 🍎 macOS 13 arm64
|
||||||
outputs:
|
outputs:
|
||||||
IMHEX_VERSION: ${{ steps.build.outputs.IMHEX_VERSION }}
|
IMHEX_VERSION: ${{ steps.build.outputs.IMHEX_VERSION }}
|
||||||
steps:
|
steps:
|
||||||
@@ -298,8 +365,8 @@ jobs:
|
|||||||
gh actions-cache delete "build-macos-arm64-cache" --confirm || true
|
gh actions-cache delete "build-macos-arm64-cache" --confirm || true
|
||||||
|
|
||||||
macos-arm64-package:
|
macos-arm64-package:
|
||||||
runs-on: macos-12
|
runs-on: macos-13
|
||||||
name: 🍎 macOS 12.1 arm64 Packaging
|
name: 🍎 macOS 13 arm64 Packaging
|
||||||
needs: macos-arm64-build
|
needs: macos-arm64-build
|
||||||
env:
|
env:
|
||||||
IMHEX_VERSION: ${{ needs.macos-arm64-build.outputs.IMHEX_VERSION }}
|
IMHEX_VERSION: ${{ needs.macos-arm64-build.outputs.IMHEX_VERSION }}
|
||||||
@@ -329,6 +396,12 @@ jobs:
|
|||||||
cd out
|
cd out
|
||||||
chmod -R 755 ImHex.app/
|
chmod -R 755 ImHex.app/
|
||||||
|
|
||||||
|
- name: 🔫 Kill XProtect
|
||||||
|
run: |
|
||||||
|
# See https://github.com/actions/runner-images/issues/7522
|
||||||
|
echo Killing XProtect...; sudo pkill -9 XProtect >/dev/null || true;
|
||||||
|
echo Waiting for XProtect process...; while pgrep XProtect; do sleep 3; done;
|
||||||
|
|
||||||
- name: 📦 Create DMG
|
- name: 📦 Create DMG
|
||||||
run: |
|
run: |
|
||||||
set -x
|
set -x
|
||||||
@@ -337,7 +410,13 @@ jobs:
|
|||||||
cd bundle
|
cd bundle
|
||||||
ln -s /Applications Applications
|
ln -s /Applications Applications
|
||||||
cd ..
|
cd ..
|
||||||
hdiutil create -volname "ImHex" -srcfolder bundle -ov -format UDZO imhex-${{env.IMHEX_VERSION}}-macOS-arm64.dmg
|
for i in $(seq 1 10); do
|
||||||
|
if hdiutil create -volname "ImHex" -srcfolder bundle -ov -format UDZO imhex-${{ env.IMHEX_VERSION }}-macOS-arm64.dmg; then
|
||||||
|
echo "Created dmg after ${i} attempts"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
sleep 10
|
||||||
|
done
|
||||||
|
|
||||||
- name: ⬆️ Upload DMG
|
- name: ⬆️ Upload DMG
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
@@ -352,11 +431,11 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- release_num: 22.04
|
- release_num: "24.04"
|
||||||
- release_num: 24.04
|
- release_num: "24.10"
|
||||||
|
|
||||||
name: 🐧 Ubuntu ${{ matrix.release_num }}
|
name: 🐧 Ubuntu ${{ matrix.release_num }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-24.04
|
||||||
|
|
||||||
container:
|
container:
|
||||||
image: "ubuntu:${{ matrix.release_num }}"
|
image: "ubuntu:${{ matrix.release_num }}"
|
||||||
@@ -374,8 +453,8 @@ jobs:
|
|||||||
- name: 📜 Setup ccache
|
- name: 📜 Setup ccache
|
||||||
uses: hendrikmuhs/ccache-action@v1
|
uses: hendrikmuhs/ccache-action@v1
|
||||||
with:
|
with:
|
||||||
key: Ubuntu-${{matrix.release_num}}-ccache-${{ github.run_id }}
|
key: Ubuntu-${{ matrix.release_num }}-ccache-${{ github.run_id }}
|
||||||
restore-keys: Ubuntu-${{matrix.release_num}}-ccache
|
restore-keys: Ubuntu-${{ matrix.release_num }}-ccache
|
||||||
max-size: 1G
|
max-size: 1G
|
||||||
|
|
||||||
- name: ⬇️ Install dependencies
|
- name: ⬇️ Install dependencies
|
||||||
@@ -396,8 +475,8 @@ jobs:
|
|||||||
git config --global --add safe.directory '*'
|
git config --global --add safe.directory '*'
|
||||||
mkdir -p build
|
mkdir -p build
|
||||||
cd build
|
cd build
|
||||||
CC=gcc-12 CXX=g++-12 cmake -G "Ninja" \
|
CC=gcc-14 CXX=g++-14 cmake -G "Ninja" \
|
||||||
-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \
|
-DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \
|
||||||
-DCMAKE_INSTALL_PREFIX="/usr" \
|
-DCMAKE_INSTALL_PREFIX="/usr" \
|
||||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||||
@@ -420,7 +499,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
cp -r build/DEBIAN build/DebDir
|
cp -r build/DEBIAN build/DebDir
|
||||||
dpkg-deb -Zgzip --build build/DebDir
|
dpkg-deb -Zgzip --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 }}-Ubuntu-${{ matrix.release_num }}-x86_64.deb
|
||||||
|
|
||||||
- name: ⬆️ Upload DEB
|
- name: ⬆️ Upload DEB
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
@@ -431,7 +510,7 @@ jobs:
|
|||||||
|
|
||||||
# AppImage build
|
# AppImage build
|
||||||
appimage:
|
appimage:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-24.04
|
||||||
name: ⬇️ AppImage
|
name: ⬇️ AppImage
|
||||||
steps:
|
steps:
|
||||||
- name: 🧰 Checkout
|
- name: 🧰 Checkout
|
||||||
@@ -475,7 +554,7 @@ jobs:
|
|||||||
# ArchLinux build
|
# ArchLinux build
|
||||||
archlinux-build:
|
archlinux-build:
|
||||||
name: 🐧 ArchLinux
|
name: 🐧 ArchLinux
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-24.04
|
||||||
|
|
||||||
container:
|
container:
|
||||||
image: archlinux:base-devel
|
image: archlinux:base-devel
|
||||||
@@ -517,7 +596,7 @@ jobs:
|
|||||||
mkdir -p build
|
mkdir -p build
|
||||||
cd build
|
cd build
|
||||||
CC=gcc CXX=g++ cmake -G "Ninja" \
|
CC=gcc CXX=g++ cmake -G "Ninja" \
|
||||||
-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \
|
-DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \
|
||||||
-DCMAKE_INSTALL_PREFIX="/usr" \
|
-DCMAKE_INSTALL_PREFIX="/usr" \
|
||||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||||
@@ -542,7 +621,7 @@ jobs:
|
|||||||
- name: ✒️ Prepare PKGBUILD
|
- name: ✒️ Prepare PKGBUILD
|
||||||
run: |
|
run: |
|
||||||
cp dist/Arch/PKGBUILD build
|
cp dist/Arch/PKGBUILD build
|
||||||
sed -i 's/%version%/${{env.IMHEX_VERSION}}/g' build/PKGBUILD
|
sed -i 's/%version%/${{ env.IMHEX_VERSION }}/g' build/PKGBUILD
|
||||||
|
|
||||||
# makepkg doesn't want to run as root, so I had to chmod 777 all over
|
# makepkg doesn't want to run as root, so I had to chmod 777 all over
|
||||||
- name: 📦 Package ArchLinux .pkg.tar.zst
|
- name: 📦 Package ArchLinux .pkg.tar.zst
|
||||||
@@ -552,16 +631,16 @@ jobs:
|
|||||||
|
|
||||||
# the name is a small trick to make makepkg recognize it as the source
|
# the name is a small trick to make makepkg recognize it as the source
|
||||||
# else, it would try to download the file from the release
|
# else, it would try to download the file from the release
|
||||||
tar -cvf imhex-${{env.IMHEX_VERSION}}-ArchLinux-x86_64.pkg.tar.zst -C installDir .
|
tar -cvf imhex-${{ env.IMHEX_VERSION }}-ArchLinux-x86_64.pkg.tar.zst -C installDir .
|
||||||
|
|
||||||
chmod -R 777 .
|
chmod -R 777 .
|
||||||
|
|
||||||
sudo -u nobody makepkg
|
sudo -u nobody makepkg
|
||||||
|
|
||||||
# Replace the old file
|
# Replace the old file
|
||||||
rm imhex-${{env.IMHEX_VERSION}}-ArchLinux-x86_64.pkg.tar.zst
|
rm imhex-${{ env.IMHEX_VERSION }}-ArchLinux-x86_64.pkg.tar.zst
|
||||||
rm *imhex-bin-debug* # rm debug package which is created for some reason
|
rm *imhex-bin-debug* # rm debug package which is created for some reason
|
||||||
mv *.pkg.tar.zst imhex-${{env.IMHEX_VERSION}}-ArchLinux-x86_64.pkg.tar.zst
|
mv *.pkg.tar.zst imhex-${{ env.IMHEX_VERSION }}-ArchLinux-x86_64.pkg.tar.zst
|
||||||
|
|
||||||
- name: ⬆️ Upload imhex-archlinux.pkg.tar.zst
|
- name: ⬆️ Upload imhex-archlinux.pkg.tar.zst
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
@@ -569,7 +648,7 @@ jobs:
|
|||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
name: ArchLinux .pkg.tar.zst x86_64
|
name: ArchLinux .pkg.tar.zst x86_64
|
||||||
path: |
|
path: |
|
||||||
build/imhex-${{env.IMHEX_VERSION}}-ArchLinux-x86_64.pkg.tar.zst
|
build/imhex-${{ env.IMHEX_VERSION }}-ArchLinux-x86_64.pkg.tar.zst
|
||||||
|
|
||||||
# RPM distro builds
|
# RPM distro builds
|
||||||
rpm-build:
|
rpm-build:
|
||||||
@@ -581,29 +660,42 @@ jobs:
|
|||||||
mock_release: rawhide
|
mock_release: rawhide
|
||||||
release_num: rawhide
|
release_num: rawhide
|
||||||
mock_config: fedora-rawhide
|
mock_config: fedora-rawhide
|
||||||
|
- name: Fedora
|
||||||
|
mock_release: f41
|
||||||
|
release_num: 41
|
||||||
|
mock_config: fedora-41
|
||||||
- name: Fedora
|
- name: Fedora
|
||||||
mock_release: f40
|
mock_release: f40
|
||||||
release_num: 40
|
release_num: 40
|
||||||
mock_config: fedora-40
|
mock_config: fedora-40
|
||||||
- name: Fedora
|
|
||||||
mock_release: f39
|
|
||||||
release_num: 39
|
|
||||||
mock_config: fedora-39
|
|
||||||
- name: RHEL-AlmaLinux
|
- name: RHEL-AlmaLinux
|
||||||
mock_release: epel9
|
mock_release: epel9
|
||||||
release_num: 9
|
release_num: 9
|
||||||
mock_config: "alma+epel-9"
|
mock_config: "alma+epel-9"
|
||||||
|
|
||||||
name: 🐧 ${{ matrix.name }} ${{ matrix.release_num }}
|
name: 🐧 ${{ matrix.name }} ${{ matrix.release_num }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-24.04
|
||||||
|
|
||||||
container:
|
container:
|
||||||
image: "fedora:latest"
|
image: "almalinux:9"
|
||||||
options: --privileged
|
options: --privileged --pid=host --security-opt apparmor=unconfined
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: ⬇️ Install git-core
|
# This, together with the `--pid=host --security-opt apparmor=unconfined` docker options is required to allow
|
||||||
run: dnf install --disablerepo="*" --enablerepo="fedora" git-core -y
|
# fedpkg to work inside a Docker container running on Ubuntu again.
|
||||||
|
# GitHub seems to have enabled AppArmor on their Ubuntu CI runners which limits Docker in ways that cause
|
||||||
|
# programs inside it to fail.
|
||||||
|
# Without this, fedpkg will throw the unhelpful error message 'Insufficient Rights'
|
||||||
|
# This step uses nsenter to execute commands on the host that disable AppArmor entirely.
|
||||||
|
- name: 🛡️ Disable AppArmor on Host
|
||||||
|
run: |
|
||||||
|
nsenter -t 1 -m -u -n -i sudo systemctl disable --now apparmor.service
|
||||||
|
nsenter -t 1 -m -u -n -i sudo aa-teardown || true
|
||||||
|
nsenter -t 1 -m -u -n -i sudo sysctl --write kernel.apparmor_restrict_unprivileged_unconfined=0
|
||||||
|
nsenter -t 1 -m -u -n -i sudo sysctl --write kernel.apparmor_restrict_unprivileged_userns=0
|
||||||
|
|
||||||
|
- name: ⬇️ Install git-core and EPEL repo
|
||||||
|
run: dnf install git-core epel-release -y
|
||||||
|
|
||||||
- name: 🧰 Checkout
|
- name: 🧰 Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@@ -622,8 +714,8 @@ jobs:
|
|||||||
- name: ⬇️ Update all packages and install dependencies
|
- name: ⬇️ Update all packages and install dependencies
|
||||||
run: |
|
run: |
|
||||||
set -x
|
set -x
|
||||||
dnf upgrade --disablerepo="*" --enablerepo="fedora,updates" -y
|
dnf upgrade -y
|
||||||
dnf install --disablerepo="*" --enablerepo="fedora,updates" -y \
|
dnf install -y \
|
||||||
fedpkg \
|
fedpkg \
|
||||||
ccache
|
ccache
|
||||||
|
|
||||||
@@ -649,16 +741,16 @@ jobs:
|
|||||||
- name: ✒️ Modify spec file
|
- name: ✒️ Modify spec file
|
||||||
run: |
|
run: |
|
||||||
sed -i \
|
sed -i \
|
||||||
-e 's/Version: VERSION$/Version: ${{env.IMHEX_VERSION}}/g' \
|
-e 's/Version: VERSION$/Version: ${{ env.IMHEX_VERSION }}/g' \
|
||||||
-e 's/IMHEX_OFFLINE_BUILD=ON/IMHEX_OFFLINE_BUILD=OFF/g' \
|
-e 's/IMHEX_OFFLINE_BUILD=ON/IMHEX_OFFLINE_BUILD=OFF/g' \
|
||||||
-e '/IMHEX_OFFLINE_BUILD=OFF/a -D IMHEX_PATTERNS_PULL_MASTER=ON \\' \
|
-e '/IMHEX_OFFLINE_BUILD=OFF/a -D IMHEX_PATTERNS_PULL_MASTER=ON \\' \
|
||||||
-e '/BuildRequires: cmake/a BuildRequires: git-core' \
|
-e '/BuildRequires: cmake/a BuildRequires: git-core' \
|
||||||
-e '/%files/a %{_datadir}/%{name}/' \
|
-e '/%files/a %{_datadir}/%{name}/' \
|
||||||
$GITHUB_WORKSPACE/ImHex/dist/rpm/imhex.spec
|
$GITHUB_WORKSPACE/ImHex/dist/rpm/imhex.spec
|
||||||
|
|
||||||
- name: 📜 Fix ccache on EL9
|
- name: 📜 Fix ccache on EL9
|
||||||
if: matrix.mock_release == 'epel9'
|
if: matrix.mock_release == 'epel9'
|
||||||
run: sed -i '/\. \/opt\/rh\/gcc-toolset-12\/enable/a PATH=/usr/lib64/ccache:$PATH' $GITHUB_WORKSPACE/ImHex/dist/rpm/imhex.spec
|
run: sed -i '/\. \/opt\/rh\/gcc-toolset-14\/enable/a PATH=/usr/lib64/ccache:$PATH' $GITHUB_WORKSPACE/ImHex/dist/rpm/imhex.spec
|
||||||
|
|
||||||
- name: 🟩 Copy spec file to build root
|
- name: 🟩 Copy spec file to build root
|
||||||
run: mv $GITHUB_WORKSPACE/ImHex/dist/rpm/imhex.spec $GITHUB_WORKSPACE/imhex.spec
|
run: mv $GITHUB_WORKSPACE/ImHex/dist/rpm/imhex.spec $GITHUB_WORKSPACE/imhex.spec
|
||||||
@@ -680,8 +772,8 @@ jobs:
|
|||||||
|
|
||||||
- name: 🟩 Move and rename finished RPM
|
- name: 🟩 Move and rename finished RPM
|
||||||
run: |
|
run: |
|
||||||
mv $GITHUB_WORKSPACE/results_imhex/${{env.IMHEX_VERSION}}/*/imhex-${{env.IMHEX_VERSION}}-0.*.x86_64.rpm \
|
mv $GITHUB_WORKSPACE/results_imhex/${{ env.IMHEX_VERSION }}/*/imhex-${{ env.IMHEX_VERSION }}-0.*.x86_64.rpm \
|
||||||
$GITHUB_WORKSPACE/imhex-${{env.IMHEX_VERSION}}-${{matrix.name}}-${{matrix.release_num}}-x86_64.rpm
|
$GITHUB_WORKSPACE/imhex-${{ env.IMHEX_VERSION }}-${{ matrix.name }}-${{ matrix.release_num }}-x86_64.rpm
|
||||||
|
|
||||||
- name: ⬆️ Upload RPM
|
- name: ⬆️ Upload RPM
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
@@ -689,4 +781,4 @@ jobs:
|
|||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
name: ${{ matrix.name }} ${{ matrix.release_num }} RPM x86_64
|
name: ${{ matrix.name }} ${{ matrix.release_num }} RPM x86_64
|
||||||
path: |
|
path: |
|
||||||
imhex-${{env.IMHEX_VERSION}}-${{matrix.name}}-${{matrix.release_num}}-x86_64.rpm
|
imhex-${{ env.IMHEX_VERSION }}-${{ matrix.name }}-${{ matrix.release_num }}-x86_64.rpm
|
||||||
|
|||||||
13
.github/workflows/build_web.yml
vendored
13
.github/workflows/build_web.yml
vendored
@@ -20,7 +20,7 @@ permissions:
|
|||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-24.04
|
||||||
name: 🌍 WebAssembly
|
name: 🌍 WebAssembly
|
||||||
steps:
|
steps:
|
||||||
- name: 🧰 Checkout
|
- name: 🧰 Checkout
|
||||||
@@ -49,7 +49,7 @@ jobs:
|
|||||||
chmod -c -R +rX "out/"
|
chmod -c -R +rX "out/"
|
||||||
|
|
||||||
- name: ⬆️ Upload artifacts
|
- name: ⬆️ Upload artifacts
|
||||||
uses: actions/upload-pages-artifact@v2
|
uses: actions/upload-pages-artifact@v3
|
||||||
with:
|
with:
|
||||||
path: out/
|
path: out/
|
||||||
|
|
||||||
@@ -59,9 +59,8 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ github.token }}
|
GH_TOKEN: ${{ github.token }}
|
||||||
run: |
|
run: |
|
||||||
gh extension install actions/gh-actions-cache
|
gh extension install actions/gh-actions-cache || true
|
||||||
gh actions-cache delete "build-web-cache" --confirm
|
gh actions-cache delete "build-web-cache" --confirm || true
|
||||||
|
|
||||||
|
|
||||||
deploy:
|
deploy:
|
||||||
environment:
|
environment:
|
||||||
@@ -69,7 +68,7 @@ jobs:
|
|||||||
url: ${{ steps.deployment.outputs.page_url }}
|
url: ${{ steps.deployment.outputs.page_url }}
|
||||||
|
|
||||||
name: 📃 Deploy to GitHub Pages
|
name: 📃 Deploy to GitHub Pages
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-24.04
|
||||||
|
|
||||||
if: ${{ github.ref == 'refs/heads/master' && github.event.repository.fork == false }}
|
if: ${{ github.ref == 'refs/heads/master' && github.event.repository.fork == false }}
|
||||||
needs: build
|
needs: build
|
||||||
@@ -77,4 +76,4 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: 🌍 Deploy
|
- name: 🌍 Deploy
|
||||||
id: deployment
|
id: deployment
|
||||||
uses: actions/deploy-pages@v2
|
uses: actions/deploy-pages@v4
|
||||||
6
.github/workflows/release.yml
vendored
6
.github/workflows/release.yml
vendored
@@ -10,7 +10,7 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release-update-repos:
|
release-update-repos:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-24.04
|
||||||
name: Release Update Repos
|
name: Release Update Repos
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
@@ -90,7 +90,7 @@ jobs:
|
|||||||
run: tar --exclude-vcs -czvf Full.Sources.tar.gz ImHex
|
run: tar --exclude-vcs -czvf Full.Sources.tar.gz ImHex
|
||||||
|
|
||||||
- name: ⬇️ Download artifacts from latest workflow
|
- name: ⬇️ Download artifacts from latest workflow
|
||||||
uses: dawidd6/action-download-artifact@v3
|
uses: dawidd6/action-download-artifact@v6
|
||||||
with:
|
with:
|
||||||
github_token: ${{secrets.GITHUB_TOKEN}}
|
github_token: ${{secrets.GITHUB_TOKEN}}
|
||||||
workflow: build.yml
|
workflow: build.yml
|
||||||
@@ -147,7 +147,7 @@ jobs:
|
|||||||
commit_email: itrooz@protonmail.com
|
commit_email: itrooz@protonmail.com
|
||||||
ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
|
ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
|
||||||
commit_message: Bump to version ${{ env.IMHEX_VERSION }}
|
commit_message: Bump to version ${{ env.IMHEX_VERSION }}
|
||||||
ssh_keyscan_types: rsa,dsa,ecdsa,ed25519
|
ssh_keyscan_types: rsa,ecdsa,ed25519
|
||||||
|
|
||||||
release-update-winget:
|
release-update-winget:
|
||||||
name: Release update winget package
|
name: Release update winget package
|
||||||
|
|||||||
30
.github/workflows/stale_issues.yml
vendored
Normal file
30
.github/workflows/stale_issues.yml
vendored
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
name: Close inactive issues
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: "30 1 * * 0"
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
close-issues:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
issues: write
|
||||||
|
pull-requests: write
|
||||||
|
steps:
|
||||||
|
- uses: actions/stale@v5
|
||||||
|
with:
|
||||||
|
operations-per-run: '200'
|
||||||
|
ascending: true
|
||||||
|
days-before-issue-stale: 334
|
||||||
|
days-before-issue-close: 30
|
||||||
|
stale-issue-label: "stale"
|
||||||
|
stale-issue-message: |
|
||||||
|
This issue is marked stale as it has been open for 11 months without activity.
|
||||||
|
Please try the latest ImHex version. (Avaiable here: https://imhex.download/ for release and https://imhex.download/#nightly for development version)
|
||||||
|
If the issue persists on the latest version, please make a comment on this issue again
|
||||||
|
|
||||||
|
Without response, this issue will be closed in one month.
|
||||||
|
close-issue-message: ""
|
||||||
|
days-before-pr-stale: -1
|
||||||
|
days-before-pr-close: -1
|
||||||
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
37
.github/workflows/tests.yml
vendored
37
.github/workflows/tests.yml
vendored
@@ -15,7 +15,7 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
tests:
|
tests:
|
||||||
name: 🧪 Unit Tests
|
name: 🧪 Unit Tests
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-24.04
|
||||||
permissions:
|
permissions:
|
||||||
actions: read
|
actions: read
|
||||||
contents: read
|
contents: read
|
||||||
@@ -38,14 +38,13 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
sudo apt update
|
sudo apt update
|
||||||
sudo bash dist/get_deps_debian.sh
|
sudo bash dist/get_deps_debian.sh
|
||||||
sudo apt install gcovr -y
|
|
||||||
|
|
||||||
- name: 🛠️ Build
|
- name: 🛠️ Build
|
||||||
run: |
|
run: |
|
||||||
set -x
|
set -x
|
||||||
mkdir -p build
|
mkdir -p build
|
||||||
cd build
|
cd build
|
||||||
CC=gcc-12 CXX=g++-12 cmake \
|
CC=gcc-14 CXX=g++-14 cmake \
|
||||||
-DCMAKE_BUILD_TYPE=Debug \
|
-DCMAKE_BUILD_TYPE=Debug \
|
||||||
-DIMHEX_ENABLE_UNIT_TESTS=ON \
|
-DIMHEX_ENABLE_UNIT_TESTS=ON \
|
||||||
-DIMHEX_ENABLE_PLUGIN_TESTS=ON \
|
-DIMHEX_ENABLE_PLUGIN_TESTS=ON \
|
||||||
@@ -54,8 +53,10 @@ jobs:
|
|||||||
-DCMAKE_C_FLAGS="-fuse-ld=lld -fsanitize=address,leak,undefined -fno-sanitize-recover=all --coverage" \
|
-DCMAKE_C_FLAGS="-fuse-ld=lld -fsanitize=address,leak,undefined -fno-sanitize-recover=all --coverage" \
|
||||||
-DCMAKE_CXX_FLAGS="-fuse-ld=lld -fsanitize=address,leak,undefined -fno-sanitize-recover=all --coverage" \
|
-DCMAKE_CXX_FLAGS="-fuse-ld=lld -fsanitize=address,leak,undefined -fno-sanitize-recover=all --coverage" \
|
||||||
-DIMHEX_OFFLINE_BUILD=ON \
|
-DIMHEX_OFFLINE_BUILD=ON \
|
||||||
|
-G Ninja \
|
||||||
..
|
..
|
||||||
make -j4 unit_tests
|
ninja unit_tests
|
||||||
|
ninja imhex_all
|
||||||
|
|
||||||
- name: 🧪 Perform plcli Integration Tests
|
- name: 🧪 Perform plcli Integration Tests
|
||||||
run: |
|
run: |
|
||||||
@@ -68,16 +69,24 @@ jobs:
|
|||||||
ctest --output-on-failure
|
ctest --output-on-failure
|
||||||
|
|
||||||
# Generate report from all gcov .gcda files
|
# Generate report from all gcov .gcda files
|
||||||
- name: 🧪 Generate coverage report
|
#- name: 🧪 Generate coverage report
|
||||||
run: |
|
# run: |
|
||||||
gcovr --gcov-executable /usr/bin/gcov-12 -r . build --xml coverage_report.xml --verbose
|
# sudo apt install python3-pip python3-venv
|
||||||
|
# python3 -m venv venv
|
||||||
- name: Upload coverage reports to Codecov
|
# . venv/bin/activate
|
||||||
uses: codecov/codecov-action@v4
|
# pip3 install gcovr
|
||||||
with:
|
# cd build
|
||||||
fail_ci_if_error: true
|
# gcovr --gcov-executable /usr/bin/gcov-14 --exclude '.*/yara_rules/' --exclude '.*/third_party/' --exclude '.*/external/' --root .. --xml coverage_report.xml --verbose --gcov-ignore-errors all
|
||||||
token: ${{ secrets.CODECOV_TOKEN }}
|
#
|
||||||
file: coverage_report.xml
|
#- name: Upload coverage reports to Codecov
|
||||||
|
# env:
|
||||||
|
# CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||||
|
# if: ${{ env.CODECOV_TOKEN }}
|
||||||
|
# uses: codecov/codecov-action@v4
|
||||||
|
# with:
|
||||||
|
# fail_ci_if_error: true
|
||||||
|
# token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
|
# file: build/coverage_report.xml
|
||||||
|
|
||||||
langs:
|
langs:
|
||||||
name: 🧪 Langs
|
name: 🧪 Langs
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -6,6 +6,7 @@ cmake-build-*/
|
|||||||
build*/
|
build*/
|
||||||
local/
|
local/
|
||||||
venv/
|
venv/
|
||||||
|
.cache/
|
||||||
|
|
||||||
*.mgc
|
*.mgc
|
||||||
*.kdev4
|
*.kdev4
|
||||||
|
|||||||
2
.gitmodules
vendored
2
.gitmodules
vendored
@@ -28,7 +28,7 @@
|
|||||||
ignore = dirty
|
ignore = dirty
|
||||||
[submodule "lib/third_party/lunasvg"]
|
[submodule "lib/third_party/lunasvg"]
|
||||||
path = lib/third_party/lunasvg
|
path = lib/third_party/lunasvg
|
||||||
url = https://github.com/sammycage/lunasvg
|
url = https://github.com/WerWolv/lunasvg
|
||||||
ignore = dirty
|
ignore = dirty
|
||||||
|
|
||||||
[submodule "lib/external/libromfs"]
|
[submodule "lib/external/libromfs"]
|
||||||
|
|||||||
@@ -32,13 +32,14 @@ include("${IMHEX_BASE_FOLDER}/cmake/ide_helpers.cmake")
|
|||||||
# Basic compiler and cmake configurations
|
# Basic compiler and cmake configurations
|
||||||
set(CMAKE_CXX_STANDARD 23)
|
set(CMAKE_CXX_STANDARD 23)
|
||||||
set(CMAKE_INCLUDE_DIRECTORIES_BEFORE ON)
|
set(CMAKE_INCLUDE_DIRECTORIES_BEFORE ON)
|
||||||
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
include("${IMHEX_BASE_FOLDER}/cmake/build_helpers.cmake")
|
include("${IMHEX_BASE_FOLDER}/cmake/build_helpers.cmake")
|
||||||
|
|
||||||
# Setup project
|
# Setup project
|
||||||
loadVersion(IMHEX_VERSION IMHEX_VERSION_PLAIN)
|
loadVersion(IMHEX_VERSION IMHEX_VERSION_PLAIN)
|
||||||
setVariableInParent(IMHEX_VERSION ${IMHEX_VERSION})
|
setVariableInParent(IMHEX_VERSION ${IMHEX_VERSION})
|
||||||
configureCMake()
|
|
||||||
|
|
||||||
|
configureCMake()
|
||||||
project(imhex
|
project(imhex
|
||||||
LANGUAGES C CXX
|
LANGUAGES C CXX
|
||||||
VERSION ${IMHEX_VERSION_PLAIN}
|
VERSION ${IMHEX_VERSION_PLAIN}
|
||||||
@@ -72,8 +73,11 @@ addPluginDirectories()
|
|||||||
|
|
||||||
# Add unit tests
|
# Add unit tests
|
||||||
if (IMHEX_ENABLE_UNIT_TESTS)
|
if (IMHEX_ENABLE_UNIT_TESTS)
|
||||||
enable_testing()
|
if (NOT TARGET unit_tests)
|
||||||
add_subdirectory(tests EXCLUDE_FROM_ALL)
|
enable_testing()
|
||||||
|
add_custom_target(unit_tests)
|
||||||
|
add_subdirectory(tests EXCLUDE_FROM_ALL)
|
||||||
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
# Configure more resources that will be added to the install package
|
# Configure more resources that will be added to the install package
|
||||||
@@ -83,5 +87,5 @@ generateSDKDirectory()
|
|||||||
# Handle package generation
|
# Handle package generation
|
||||||
createPackage()
|
createPackage()
|
||||||
|
|
||||||
# Accomodate IDEs with FOLDER support
|
# Accommodate IDEs with FOLDER support
|
||||||
tweakTargetsForIDESupport()
|
tweakTargetsForIDESupport()
|
||||||
|
|||||||
19
README.md
19
README.md
@@ -314,23 +314,26 @@ To use ImHex, the following minimal system requirements need to be met.
|
|||||||
> ImHex requires a GPU with OpenGL 3.0 support in general.
|
> ImHex requires a GPU with OpenGL 3.0 support in general.
|
||||||
> There are releases available (with the `-NoGPU` suffix) that are software rendered and don't require a GPU, however these can be a lot slower than the GPU accelerated versions.
|
> There are releases available (with the `-NoGPU` suffix) that are software rendered and don't require a GPU, however these can be a lot slower than the GPU accelerated versions.
|
||||||
>
|
>
|
||||||
> If possible at all, make ImHex use the dedicated GPU on your system instead of the integrated one (especially Intel HD GPUs are known to cause issues).
|
> If possible at all, make ImHex use the dedicated GPU on your system instead of the integrated one.
|
||||||
|
> ImHex will usually run fine with integrated GPUs as well but certain Intel HD GPU drivers on Windows are known to cause graphical artifacts.
|
||||||
|
|
||||||
- **OS**:
|
- **OS**:
|
||||||
- **Windows**: Windows 7 or higher (Windows 10/11 recommended)
|
- **Windows**: Windows 7 or higher (Windows 10/11 recommended)
|
||||||
- **macOS**: macOS 12.1 (Monterey) or higher,
|
- **macOS**: macOS 13 (Ventura) or higher,
|
||||||
- Lower versions are supported, but you'll need to compile ImHex yourself
|
- Lower versions should still work too, but you'll need to compile ImHex yourself. The release binaries will NOT work.
|
||||||
|
- The macOS build is not signed and will require you to manually allow them in the Security & Privacy settings.
|
||||||
- **Linux**: "Modern" Linux. The following distributions have official releases available. Other distros are supported through the AppImage and Flatpak releases.
|
- **Linux**: "Modern" Linux. The following distributions have official releases available. Other distros are supported through the AppImage and Flatpak releases.
|
||||||
- Ubuntu 22.04/23.04
|
- Ubuntu and Debian
|
||||||
- Fedora 36/37
|
- Fedora
|
||||||
- RHEL/AlmaLinux 9
|
- RHEL/AlmaLinux
|
||||||
- Arch Linux
|
- Arch Linux
|
||||||
|
- Basically any other distro will work as well when compiling ImHex from sources.
|
||||||
- **CPU**: x86_64 (64 Bit)
|
- **CPU**: x86_64 (64 Bit)
|
||||||
- **GPU**: OpenGL 3.0 or higher
|
- **GPU**: OpenGL 3.0 or higher
|
||||||
- Intel HD drivers are really buggy and often cause graphic artifacts
|
- Integrated Intel HD iGPUs are supported, however certain drivers are known to cause various graphical artifacts, especially on Windows. Use at your own risk.
|
||||||
- In case you don't have a GPU available, there are software rendered releases available for Windows and macOS
|
- In case you don't have a GPU available, there are software rendered releases available for Windows and macOS
|
||||||
- **RAM**: 256MB, more may be required for more complicated analysis
|
- **RAM**: 256MB, more may be required for more complicated analysis
|
||||||
- **Storage**: 100MB
|
- **Storage**: 150MB
|
||||||
|
|
||||||
## Installing
|
## Installing
|
||||||
|
|
||||||
|
|||||||
@@ -225,6 +225,7 @@ macro(createPackage)
|
|||||||
|
|
||||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE DESTINATION ${CMAKE_INSTALL_PREFIX}/share/licenses/imhex)
|
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE DESTINATION ${CMAKE_INSTALL_PREFIX}/share/licenses/imhex)
|
||||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/dist/imhex.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications)
|
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/dist/imhex.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications)
|
||||||
|
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/dist/imhex.mime.xml DESTINATION ${CMAKE_INSTALL_PREFIX}/share/mime/packages RENAME imhex.xml)
|
||||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/icon.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps RENAME imhex.png)
|
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/icon.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps RENAME imhex.png)
|
||||||
downloadImHexPatternsFiles("./share/imhex")
|
downloadImHexPatternsFiles("./share/imhex")
|
||||||
|
|
||||||
@@ -239,6 +240,7 @@ macro(createPackage)
|
|||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
if (IMHEX_GENERATE_PACKAGE)
|
if (IMHEX_GENERATE_PACKAGE)
|
||||||
|
set(EXTRA_BUNDLE_LIBRARY_PATHS ${EXTRA_BUNDLE_LIBRARY_PATHS} "${IMHEX_SYSTEM_LIBRARY_PATH}")
|
||||||
include(PostprocessBundle)
|
include(PostprocessBundle)
|
||||||
|
|
||||||
set_target_properties(libimhex PROPERTIES SOVERSION ${IMHEX_VERSION})
|
set_target_properties(libimhex PROPERTIES SOVERSION ${IMHEX_VERSION})
|
||||||
@@ -307,9 +309,6 @@ endfunction()
|
|||||||
macro(configureCMake)
|
macro(configureCMake)
|
||||||
message(STATUS "Configuring ImHex v${IMHEX_VERSION}")
|
message(STATUS "Configuring ImHex v${IMHEX_VERSION}")
|
||||||
|
|
||||||
# Enable C and C++ languages
|
|
||||||
enable_language(C CXX)
|
|
||||||
|
|
||||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON CACHE BOOL "Enable position independent code for all targets" FORCE)
|
set(CMAKE_POSITION_INDEPENDENT_CODE ON CACHE BOOL "Enable position independent code for all targets" FORCE)
|
||||||
|
|
||||||
# Configure use of recommended build tools
|
# Configure use of recommended build tools
|
||||||
@@ -383,6 +382,9 @@ macro(configureCMake)
|
|||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
function(configureProject)
|
function(configureProject)
|
||||||
|
# Enable C and C++ languages
|
||||||
|
enable_language(C CXX)
|
||||||
|
|
||||||
if (XCODE)
|
if (XCODE)
|
||||||
# Support Xcode's multi configuration paradigm by placing built artifacts into separate directories
|
# Support Xcode's multi configuration paradigm by placing built artifacts into separate directories
|
||||||
set(IMHEX_MAIN_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/Configs/$<CONFIG>" PARENT_SCOPE)
|
set(IMHEX_MAIN_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/Configs/$<CONFIG>" PARENT_SCOPE)
|
||||||
@@ -573,7 +575,7 @@ macro(setupCompilerFlags target)
|
|||||||
set(IMHEX_CXX_FLAGS "-fexceptions -frtti")
|
set(IMHEX_CXX_FLAGS "-fexceptions -frtti")
|
||||||
|
|
||||||
# Disable some warnings
|
# Disable some warnings
|
||||||
set(IMHEX_C_CXX_FLAGS "-Wno-unknown-warning-option -Wno-array-bounds -Wno-deprecated-declarations -Wno-unknown-pragmas")
|
set(IMHEX_C_CXX_FLAGS "-Wno-array-bounds -Wno-deprecated-declarations -Wno-unknown-pragmas")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||||
@@ -582,6 +584,13 @@ macro(setupCompilerFlags target)
|
|||||||
endif ()
|
endif ()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND APPLE)
|
||||||
|
execute_process(COMMAND brew --prefix llvm OUTPUT_VARIABLE LLVM_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${LLVM_PREFIX}/lib/c++")
|
||||||
|
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${LLVM_PREFIX}/lib/c++")
|
||||||
|
set(IMHEX_C_CXX_FLAGS "-Wno-unknown-warning-option")
|
||||||
|
endif()
|
||||||
|
|
||||||
# Disable some warnings for gcc
|
# Disable some warnings for gcc
|
||||||
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||||
set(IMHEX_C_CXX_FLAGS "${IMHEX_C_CXX_FLAGS} -Wno-restrict -Wno-stringop-overread -Wno-stringop-overflow -Wno-dangling-reference")
|
set(IMHEX_C_CXX_FLAGS "${IMHEX_C_CXX_FLAGS} -Wno-restrict -Wno-stringop-overread -Wno-stringop-overflow -Wno-dangling-reference")
|
||||||
@@ -702,9 +711,11 @@ macro(addBundledLibraries)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (USE_SYSTEM_BOOST)
|
if (USE_SYSTEM_BOOST)
|
||||||
find_package(boost REQUIRED)
|
find_package(Boost REQUIRED)
|
||||||
|
set(BOOST_LIBRARIES Boost::regex)
|
||||||
else()
|
else()
|
||||||
add_subdirectory(${THIRD_PARTY_LIBS_FOLDER}/boost ${CMAKE_CURRENT_BINARY_DIR}/boost EXCLUDE_FROM_ALL)
|
add_subdirectory(${THIRD_PARTY_LIBS_FOLDER}/boost ${CMAKE_CURRENT_BINARY_DIR}/boost EXCLUDE_FROM_ALL)
|
||||||
|
set(BOOST_LIBRARIES boost::regex)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(LIBPL_BUILD_CLI_AS_EXECUTABLE OFF CACHE BOOL "" FORCE)
|
set(LIBPL_BUILD_CLI_AS_EXECUTABLE OFF CACHE BOOL "" FORCE)
|
||||||
@@ -846,6 +857,9 @@ function(generateSDKDirectory)
|
|||||||
if (NOT USE_SYSTEM_NLOHMANN_JSON)
|
if (NOT USE_SYSTEM_NLOHMANN_JSON)
|
||||||
install(DIRECTORY ${CMAKE_SOURCE_DIR}/lib/third_party/nlohmann_json DESTINATION "${SDK_PATH}/lib/third_party")
|
install(DIRECTORY ${CMAKE_SOURCE_DIR}/lib/third_party/nlohmann_json DESTINATION "${SDK_PATH}/lib/third_party")
|
||||||
endif()
|
endif()
|
||||||
|
if (NOT USE_SYSTEM_BOOST)
|
||||||
|
install(DIRECTORY ${CMAKE_SOURCE_DIR}/lib/third_party/boost DESTINATION "${SDK_PATH}/lib/third_party")
|
||||||
|
endif()
|
||||||
|
|
||||||
install(DIRECTORY ${CMAKE_SOURCE_DIR}/cmake/modules DESTINATION "${SDK_PATH}/cmake")
|
install(DIRECTORY ${CMAKE_SOURCE_DIR}/cmake/modules DESTINATION "${SDK_PATH}/cmake")
|
||||||
install(FILES ${CMAKE_SOURCE_DIR}/cmake/build_helpers.cmake DESTINATION "${SDK_PATH}/cmake")
|
install(FILES ${CMAKE_SOURCE_DIR}/cmake/build_helpers.cmake DESTINATION "${SDK_PATH}/cmake")
|
||||||
|
|||||||
@@ -89,4 +89,5 @@ if (CoreClrEmbed_INCLUDE_DIR AND CoreClrEmbed_LIBRARY)
|
|||||||
set(CoreClrEmbed_LIBRARIES "${CoreClrEmbed_LIBRARY}" CACHE STRING "CoreClrEmbed libraries" FORCE)
|
set(CoreClrEmbed_LIBRARIES "${CoreClrEmbed_LIBRARY}" CACHE STRING "CoreClrEmbed libraries" FORCE)
|
||||||
set(CoreClrEmbed_SHARED_LIBRARIES "${CoreClrEmbed_SHARED_LIBRARY}" CACHE STRING "CoreClrEmbed shared libraries" FORCE)
|
set(CoreClrEmbed_SHARED_LIBRARIES "${CoreClrEmbed_SHARED_LIBRARY}" CACHE STRING "CoreClrEmbed shared libraries" FORCE)
|
||||||
set(CoreClrEmbed_INCLUDE_DIRS "${CoreClrEmbed_INCLUDE_DIR}" CACHE STRING "CoreClrEmbed include directories" FORCE)
|
set(CoreClrEmbed_INCLUDE_DIRS "${CoreClrEmbed_INCLUDE_DIR}" CACHE STRING "CoreClrEmbed include directories" FORCE)
|
||||||
|
set(CoreClrEmbed_VERSION "${CORECLR_RUNTIME_VERSION_FULL}" CACHE STRING "CoreClrEmbed version" FORCE)
|
||||||
endif()
|
endif()
|
||||||
60
cmake/modules/FindLZ4.cmake
Normal file
60
cmake/modules/FindLZ4.cmake
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
find_path(LZ4_INCLUDE_DIR
|
||||||
|
NAMES lz4.h
|
||||||
|
HINTS "${LZ4_INCLUDEDIR}" "${LZ4_HINTS}/include"
|
||||||
|
PATHS
|
||||||
|
/usr/local/include
|
||||||
|
/usr/include
|
||||||
|
)
|
||||||
|
|
||||||
|
find_library(LZ4_LIBRARY
|
||||||
|
NAMES lz4 liblz4
|
||||||
|
HINTS "${LZ4_LIBDIR}" "${LZ4_HINTS}/lib"
|
||||||
|
PATHS
|
||||||
|
/usr/local/lib
|
||||||
|
/usr/lib
|
||||||
|
)
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
find_package_handle_standard_args( LZ4 DEFAULT_MSG LZ4_LIBRARY LZ4_INCLUDE_DIR )
|
||||||
|
|
||||||
|
if( LZ4_FOUND )
|
||||||
|
include( CheckIncludeFile )
|
||||||
|
include( CMakePushCheckState )
|
||||||
|
|
||||||
|
set( LZ4_INCLUDE_DIRS ${LZ4_INCLUDE_DIR} )
|
||||||
|
set( LZ4_LIBRARIES ${LZ4_LIBRARY} )
|
||||||
|
|
||||||
|
cmake_push_check_state()
|
||||||
|
set( CMAKE_REQUIRED_INCLUDES ${LZ4_INCLUDE_DIRS} )
|
||||||
|
check_include_file( lz4frame.h HAVE_LZ4FRAME_H )
|
||||||
|
cmake_pop_check_state()
|
||||||
|
|
||||||
|
if (WIN32)
|
||||||
|
set ( LZ4_DLL_DIR "${LZ4_HINTS}/bin"
|
||||||
|
CACHE PATH "Path to LZ4 DLL"
|
||||||
|
)
|
||||||
|
file( GLOB _lz4_dll RELATIVE "${LZ4_DLL_DIR}"
|
||||||
|
"${LZ4_DLL_DIR}/lz4*.dll"
|
||||||
|
)
|
||||||
|
set ( LZ4_DLL ${_lz4_dll}
|
||||||
|
# We're storing filenames only. Should we use STRING instead?
|
||||||
|
CACHE FILEPATH "LZ4 DLL file name"
|
||||||
|
)
|
||||||
|
file( GLOB _lz4_pdb RELATIVE "${LZ4_DLL_DIR}"
|
||||||
|
"${LZ4_DLL_DIR}/lz4*.pdb"
|
||||||
|
)
|
||||||
|
set ( LZ4_PDB ${_lz4_pdb}
|
||||||
|
CACHE FILEPATH "LZ4 PDB file name"
|
||||||
|
)
|
||||||
|
mark_as_advanced( LZ4_DLL_DIR LZ4_DLL LZ4_PDB )
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
set( LZ4_INCLUDE_DIRS )
|
||||||
|
set( LZ4_LIBRARIES )
|
||||||
|
endif()
|
||||||
|
|
||||||
|
mark_as_advanced( LZ4_LIBRARIES LZ4_INCLUDE_DIRS )
|
||||||
|
|
||||||
|
add_library( LZ4::lz4 INTERFACE IMPORTED )
|
||||||
|
set_property( TARGET LZ4::lz4 PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${LZ4_INCLUDE_DIRS} )
|
||||||
|
set_property( TARGET LZ4::lz4 PROPERTY INTERFACE_LINK_LIBRARIES ${LZ4_LIBRARIES} )
|
||||||
@@ -39,3 +39,7 @@ if (ZSTD_FOUND)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
mark_as_advanced(ZSTD_INCLUDE_DIR ZSTD_LIBRARY)
|
mark_as_advanced(ZSTD_INCLUDE_DIR ZSTD_LIBRARY)
|
||||||
|
|
||||||
|
add_library(ZSTD::zstd INTERFACE IMPORTED)
|
||||||
|
set_property(TARGET ZSTD::zstd PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${ZSTD_INCLUDE_DIR})
|
||||||
|
set_property(TARGET ZSTD::zstd PROPERTY INTERFACE_LINK_LIBRARIES ${ZSTD_LIBRARY})
|
||||||
@@ -55,9 +55,9 @@ IF(MBEDTLS_FOUND)
|
|||||||
MESSAGE(STATUS " Crypto: ${MBEDCRYPTO_LIBRARY}")
|
MESSAGE(STATUS " Crypto: ${MBEDCRYPTO_LIBRARY}")
|
||||||
ENDIF(NOT MBEDTLS_FIND_QUIETLY)
|
ENDIF(NOT MBEDTLS_FIND_QUIETLY)
|
||||||
ELSE(MBEDTLS_FOUND)
|
ELSE(MBEDTLS_FOUND)
|
||||||
IF(MBEDTLS_FIND_REQUIRED)
|
IF(mbedTLS_FIND_REQUIRED)
|
||||||
MESSAGE(FATAL_ERROR "Could not find mbedTLS")
|
MESSAGE(FATAL_ERROR "Could not find mbedTLS")
|
||||||
ENDIF(MBEDTLS_FIND_REQUIRED)
|
ENDIF(mbedTLS_FIND_REQUIRED)
|
||||||
ENDIF(MBEDTLS_FOUND)
|
ENDIF(MBEDTLS_FOUND)
|
||||||
|
|
||||||
MARK_AS_ADVANCED(
|
MARK_AS_ADVANCED(
|
||||||
|
|||||||
@@ -72,10 +72,23 @@ macro(add_imhex_plugin)
|
|||||||
add_subdirectory(${IMHEX_BASE_FOLDER}/lib/external/libromfs ${CMAKE_CURRENT_BINARY_DIR}/libromfs)
|
add_subdirectory(${IMHEX_BASE_FOLDER}/lib/external/libromfs ${CMAKE_CURRENT_BINARY_DIR}/libromfs)
|
||||||
target_link_libraries(${IMHEX_PLUGIN_NAME} PRIVATE ${LIBROMFS_LIBRARY})
|
target_link_libraries(${IMHEX_PLUGIN_NAME} PRIVATE ${LIBROMFS_LIBRARY})
|
||||||
|
|
||||||
foreach(feature ${IMHEX_PLUGIN_FEATURES})
|
set(FEATURE_DEFINE_CONTENT)
|
||||||
string(TOUPPER ${feature} feature)
|
|
||||||
add_definitions(-DIMHEX_PLUGIN_${IMHEX_PLUGIN_NAME}_FEATURE_${feature}=0)
|
if (IMHEX_PLUGIN_FEATURES)
|
||||||
endforeach()
|
list(LENGTH IMHEX_PLUGIN_FEATURES IMHEX_FEATURE_COUNT)
|
||||||
|
math(EXPR IMHEX_FEATURE_COUNT "${IMHEX_FEATURE_COUNT} - 1" OUTPUT_FORMAT DECIMAL)
|
||||||
|
foreach(index RANGE 0 ${IMHEX_FEATURE_COUNT} 2)
|
||||||
|
list(SUBLIST IMHEX_PLUGIN_FEATURES ${index} 2 IMHEX_PLUGIN_FEATURE)
|
||||||
|
list(GET IMHEX_PLUGIN_FEATURE 0 feature_define)
|
||||||
|
list(GET IMHEX_PLUGIN_FEATURE 1 feature_description)
|
||||||
|
|
||||||
|
string(TOUPPER ${feature_define} feature_define)
|
||||||
|
add_definitions(-DIMHEX_PLUGIN_${IMHEX_PLUGIN_NAME}_FEATURE_${feature_define}=0)
|
||||||
|
set(FEATURE_DEFINE_CONTENT "${FEATURE_DEFINE_CONTENT}{ \"${feature_description}\", IMHEX_FEATURE_ENABLED(${feature_define}) },")
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_compile_options(${IMHEX_PLUGIN_NAME} PRIVATE -DIMHEX_PLUGIN_FEATURES_CONTENT=${FEATURE_DEFINE_CONTENT})
|
||||||
|
|
||||||
# Add the new plugin to the main dependency list so it gets built by default
|
# Add the new plugin to the main dependency list so it gets built by default
|
||||||
if (TARGET imhex_all)
|
if (TARGET imhex_all)
|
||||||
@@ -117,6 +130,10 @@ macro(add_imhex_plugin)
|
|||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
macro(add_romfs_resource input output)
|
macro(add_romfs_resource input output)
|
||||||
|
if (NOT EXISTS ${input})
|
||||||
|
message(WARNING "Resource file ${input} does not exist")
|
||||||
|
endif()
|
||||||
|
|
||||||
configure_file(${input} ${CMAKE_CURRENT_BINARY_DIR}/romfs/${output} COPYONLY)
|
configure_file(${input} ${CMAKE_CURRENT_BINARY_DIR}/romfs/${output} COPYONLY)
|
||||||
|
|
||||||
list(APPEND LIBROMFS_RESOURCE_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/romfs)
|
list(APPEND LIBROMFS_RESOURCE_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/romfs)
|
||||||
|
|||||||
@@ -29,6 +29,10 @@ add_subdirectory_if_exists(lib/third_party/nlohmann_json)
|
|||||||
set(NLOHMANN_JSON_LIBRARIES nlohmann_json PARENT_SCOPE)
|
set(NLOHMANN_JSON_LIBRARIES nlohmann_json PARENT_SCOPE)
|
||||||
set(NLOHMANN_JSON_LIBRARIES nlohmann_json)
|
set(NLOHMANN_JSON_LIBRARIES nlohmann_json)
|
||||||
|
|
||||||
|
add_subdirectory_if_exists(lib/third_party/boost)
|
||||||
|
set(BOOST_LIBRARIES boost::regex PARENT_SCOPE)
|
||||||
|
set(BOOST_LIBRARIES boost::regex)
|
||||||
|
|
||||||
add_subdirectory(lib/external/libwolv EXCLUDE_FROM_ALL)
|
add_subdirectory(lib/external/libwolv EXCLUDE_FROM_ALL)
|
||||||
|
|
||||||
set(LIBPL_ENABLE_CLI OFF CACHE BOOL "" FORCE)
|
set(LIBPL_ENABLE_CLI OFF CACHE BOOL "" FORCE)
|
||||||
@@ -44,7 +48,7 @@ add_subdirectory(lib/libimhex)
|
|||||||
if (WIN32)
|
if (WIN32)
|
||||||
set_target_properties(libimhex PROPERTIES
|
set_target_properties(libimhex PROPERTIES
|
||||||
IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/../libimhex.dll"
|
IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/../libimhex.dll"
|
||||||
IMPORTED_IMPLIB "${CMAKE_CURRENT_SOURCE_DIR}/lib/libimhex.dll.a"
|
IMPORTED_IMPLIB "${CMAKE_CURRENT_SOURCE_DIR}/lib/liblibimhex.dll.a"
|
||||||
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/lib/libimhex/include")
|
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/lib/libimhex/include")
|
||||||
elseif (APPLE)
|
elseif (APPLE)
|
||||||
file(GLOB LIBIMHEX_DYLIB "${CMAKE_CURRENT_SOURCE_DIR}/../../Frameworks/libimhex.*.dylib")
|
file(GLOB LIBIMHEX_DYLIB "${CMAKE_CURRENT_SOURCE_DIR}/../../Frameworks/libimhex.*.dylib")
|
||||||
|
|||||||
21
dist/AppImageBuilder.yml
vendored
21
dist/AppImageBuilder.yml
vendored
@@ -14,22 +14,23 @@ AppDir:
|
|||||||
- amd64
|
- amd64
|
||||||
allow_unauthenticated: true
|
allow_unauthenticated: true
|
||||||
sources:
|
sources:
|
||||||
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ jammy main restricted
|
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ oracular main restricted
|
||||||
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ jammy-updates main restricted
|
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ oracular-updates main restricted
|
||||||
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ jammy universe
|
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ oracular universe
|
||||||
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ jammy-updates universe
|
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ oracular-updates universe
|
||||||
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ jammy multiverse
|
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ oracular multiverse
|
||||||
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ jammy-updates multiverse
|
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ oracular-updates multiverse
|
||||||
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ jammy-backports main restricted
|
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ oracular-backports main restricted
|
||||||
universe multiverse
|
universe multiverse
|
||||||
- sourceline: deb http://security.ubuntu.com/ubuntu jammy-security main restricted
|
- sourceline: deb http://security.ubuntu.com/ubuntu oracular-security main restricted
|
||||||
- sourceline: deb http://security.ubuntu.com/ubuntu jammy-security universe
|
- sourceline: deb http://security.ubuntu.com/ubuntu oracular-security universe
|
||||||
- sourceline: deb http://security.ubuntu.com/ubuntu jammy-security multiverse
|
- sourceline: deb http://security.ubuntu.com/ubuntu oracular-security multiverse
|
||||||
include:
|
include:
|
||||||
- librsvg2-common
|
- librsvg2-common
|
||||||
- libbz2-1.0:amd64
|
- libbz2-1.0:amd64
|
||||||
- libcap2:amd64
|
- libcap2:amd64
|
||||||
- libdbus-1-3:amd64
|
- libdbus-1-3:amd64
|
||||||
|
- libfontconfig1:amd64
|
||||||
- libgpg-error0:amd64
|
- libgpg-error0:amd64
|
||||||
- liblzma5:amd64
|
- liblzma5:amd64
|
||||||
- libnss-mdns:amd64
|
- libnss-mdns:amd64
|
||||||
|
|||||||
1
dist/Arch/Dockerfile
vendored
1
dist/Arch/Dockerfile
vendored
@@ -13,6 +13,7 @@ RUN pacman -S --needed --noconfirm \
|
|||||||
glfw-x11 \
|
glfw-x11 \
|
||||||
file \
|
file \
|
||||||
mbedtls \
|
mbedtls \
|
||||||
|
fontconfig \
|
||||||
freetype2 \
|
freetype2 \
|
||||||
curl \
|
curl \
|
||||||
dbus \
|
dbus \
|
||||||
|
|||||||
4
dist/Arch/PKGBUILD
vendored
4
dist/Arch/PKGBUILD
vendored
@@ -8,7 +8,7 @@ pkgdesc="A Hex Editor for Reverse Engineers, Programmers and people who value th
|
|||||||
arch=("x86_64")
|
arch=("x86_64")
|
||||||
url="https://github.com/WerWolv/ImHex"
|
url="https://github.com/WerWolv/ImHex"
|
||||||
license=('GPL2')
|
license=('GPL2')
|
||||||
depends=(glfw mbedtls freetype2 libglvnd dbus gtk3 curl fmt yara nlohmann-json zlib bzip2 xz zstd)
|
depends=(glfw mbedtls fontconfig freetype2 libglvnd dbus gtk3 curl fmt yara nlohmann-json zlib bzip2 xz zstd)
|
||||||
makedepends=(git)
|
makedepends=(git)
|
||||||
provides=(imhex)
|
provides=(imhex)
|
||||||
conflicts=(imhex)
|
conflicts=(imhex)
|
||||||
@@ -26,5 +26,5 @@ package() {
|
|||||||
|
|
||||||
install -d "$pkgdir/usr/share/imhex"
|
install -d "$pkgdir/usr/share/imhex"
|
||||||
cp -r "$srcdir/usr/share/imhex/"{constants,encodings,includes,magic,patterns} "$pkgdir/usr/share/imhex"
|
cp -r "$srcdir/usr/share/imhex/"{constants,encodings,includes,magic,patterns} "$pkgdir/usr/share/imhex"
|
||||||
cp -r "$srcdir/usr/share/"{applications,licenses,pixmaps} "$pkgdir/usr/share"
|
cp -r "$srcdir/usr/share/"{applications,licenses,pixmaps,mime} "$pkgdir/usr/share"
|
||||||
}
|
}
|
||||||
|
|||||||
1
dist/Brewfile
vendored
1
dist/Brewfile
vendored
@@ -6,7 +6,6 @@ brew "freetype2"
|
|||||||
brew "libmagic"
|
brew "libmagic"
|
||||||
brew "pkg-config"
|
brew "pkg-config"
|
||||||
brew "curl"
|
brew "curl"
|
||||||
brew "gcc@12"
|
|
||||||
brew "llvm"
|
brew "llvm"
|
||||||
brew "glfw"
|
brew "glfw"
|
||||||
brew "ninja"
|
brew "ninja"
|
||||||
|
|||||||
2
dist/DEBIAN/control.in
vendored
2
dist/DEBIAN/control.in
vendored
@@ -4,7 +4,7 @@ Section: editors
|
|||||||
Priority: optional
|
Priority: optional
|
||||||
Architecture: amd64
|
Architecture: amd64
|
||||||
License: GNU GPL-2
|
License: GNU GPL-2
|
||||||
Depends: libglfw3 | libglfw3-wayland, libmagic1, libmbedtls14, libfreetype6, libopengl0, libdbus-1-3, xdg-desktop-portal
|
Depends: libfontconfig1, libglfw3 | libglfw3-wayland, libmagic1, libmbedtls14, libfreetype6, libopengl0, libdbus-1-3, xdg-desktop-portal
|
||||||
Maintainer: WerWolv <hey@werwolv.net>
|
Maintainer: WerWolv <hey@werwolv.net>
|
||||||
Description: ImHex Hex Editor
|
Description: ImHex Hex Editor
|
||||||
A Hex Editor for Reverse Engineers, Programmers and
|
A Hex Editor for Reverse Engineers, Programmers and
|
||||||
|
|||||||
13
dist/ImHex-9999.ebuild
vendored
13
dist/ImHex-9999.ebuild
vendored
@@ -20,13 +20,14 @@ DEPEND=""
|
|||||||
RDEPEND="${DEPEND}
|
RDEPEND="${DEPEND}
|
||||||
media-libs/glfw
|
media-libs/glfw
|
||||||
sys-apps/file
|
sys-apps/file
|
||||||
dev-libs/mbedtls
|
net-libs/mbedtls
|
||||||
dev-cpp/nlohmann_json
|
dev-cpp/nlohmann_json
|
||||||
dbus
|
sys-apps/dbus
|
||||||
xdg-desktop-portal
|
sys-apps/xdg-desktop-portal
|
||||||
sys-libs/zlib
|
sys-libs/zlib
|
||||||
app-arch/bzip2
|
app-arch/bzip2
|
||||||
app-arch/lzma
|
app-arch/lzma
|
||||||
app-arch/zstd
|
app-arch/zstd
|
||||||
|
app-arch/lz4
|
||||||
"
|
"
|
||||||
BDEPEND="${DEPEND}"
|
BDEPEND="${DEPEND}"
|
||||||
|
|||||||
28
dist/appimage/Dockerfile
vendored
28
dist/appimage/Dockerfile
vendored
@@ -1,4 +1,4 @@
|
|||||||
FROM ubuntu:22.04 as build
|
FROM ubuntu:24.10 as build
|
||||||
|
|
||||||
# Used to invalidate layer cache but not mount cache
|
# Used to invalidate layer cache but not mount cache
|
||||||
# See https://github.com/moby/moby/issues/41715#issuecomment-733976493
|
# See https://github.com/moby/moby/issues/41715#issuecomment-733976493
|
||||||
@@ -14,24 +14,13 @@ apt update
|
|||||||
# general deps
|
# general deps
|
||||||
apt install -y ccache git wget
|
apt install -y ccache git wget
|
||||||
# appimage tools deps
|
# appimage tools deps
|
||||||
apt install -y python3-pip python3-setuptools desktop-file-utils libgdk-pixbuf2.0-dev fuse ninja-build
|
apt install -y python3-pip python3-venv python3-setuptools desktop-file-utils libgdk-pixbuf2.0-dev fuse ninja-build
|
||||||
apt install -y squashfs-tools zsync
|
apt install -y squashfs-tools zsync
|
||||||
|
|
||||||
# imhex deps
|
# imhex deps
|
||||||
/tmp/get_deps_debian.sh
|
/tmp/get_deps_debian.sh
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
RUN --mount=type=cache,target=/cache <<EOF
|
|
||||||
# Download appimage-builder
|
|
||||||
set -xe
|
|
||||||
|
|
||||||
mkdir -p /cache/bin
|
|
||||||
wget -nc https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage -O /cache/bin/appimagetool || true
|
|
||||||
chmod +x /cache/bin/appimagetool
|
|
||||||
|
|
||||||
pip3 install git+https://github.com/AppImageCrafters/appimage-builder@f38699e
|
|
||||||
EOF
|
|
||||||
|
|
||||||
ENV PATH="/cache/bin/:${PATH}"
|
ENV PATH="/cache/bin/:${PATH}"
|
||||||
|
|
||||||
# Copy Imhex source
|
# Copy Imhex source
|
||||||
@@ -47,7 +36,7 @@ RUN <<EOF
|
|||||||
# Prepare ImHex build
|
# Prepare ImHex build
|
||||||
set -xe
|
set -xe
|
||||||
|
|
||||||
CC=gcc-12 CXX=g++-12 cmake -G "Ninja" \
|
CC=gcc-14 CXX=g++-14 cmake -G "Ninja" \
|
||||||
-DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
|
-DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
|
||||||
-DCMAKE_INSTALL_PREFIX="/usr" \
|
-DCMAKE_INSTALL_PREFIX="/usr" \
|
||||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||||
@@ -71,9 +60,18 @@ ccache -s
|
|||||||
EOF
|
EOF
|
||||||
|
|
||||||
RUN <<EOF
|
RUN <<EOF
|
||||||
# Package ImHex as AppImage
|
# Download appimage-builder
|
||||||
set -xe
|
set -xe
|
||||||
|
|
||||||
|
mkdir -p /cache/bin
|
||||||
|
wget -nc https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage -O /cache/bin/appimagetool || true
|
||||||
|
chmod +x /cache/bin/appimagetool
|
||||||
|
|
||||||
|
python3 -m venv venv
|
||||||
|
. venv/bin/activate
|
||||||
|
pip3 install git+https://github.com/AppImageCrafters/appimage-builder@f38699e
|
||||||
|
|
||||||
|
# Package ImHex as AppImage
|
||||||
export VERSION=$(cat /imhex/VERSION)
|
export VERSION=$(cat /imhex/VERSION)
|
||||||
appimage-builder --recipe /imhex/dist/AppImageBuilder.yml
|
appimage-builder --recipe /imhex/dist/AppImageBuilder.yml
|
||||||
EOF
|
EOF
|
||||||
|
|||||||
4
dist/get_deps_archlinux.sh
vendored
4
dist/get_deps_archlinux.sh
vendored
@@ -5,6 +5,7 @@ pacman -S $@ --needed \
|
|||||||
gcc \
|
gcc \
|
||||||
lld \
|
lld \
|
||||||
glfw \
|
glfw \
|
||||||
|
fontconfig \
|
||||||
file \
|
file \
|
||||||
mbedtls \
|
mbedtls \
|
||||||
freetype2 \
|
freetype2 \
|
||||||
@@ -18,4 +19,5 @@ pacman -S $@ --needed \
|
|||||||
zlib \
|
zlib \
|
||||||
bzip2 \
|
bzip2 \
|
||||||
xz \
|
xz \
|
||||||
zstd
|
zstd \
|
||||||
|
lz4
|
||||||
|
|||||||
8
dist/get_deps_debian.sh
vendored
8
dist/get_deps_debian.sh
vendored
@@ -8,8 +8,8 @@ fi
|
|||||||
|
|
||||||
apt install -y \
|
apt install -y \
|
||||||
build-essential \
|
build-essential \
|
||||||
gcc-12 \
|
gcc-14 \
|
||||||
g++-12 \
|
g++-14 \
|
||||||
lld \
|
lld \
|
||||||
${PKGCONF:-} \
|
${PKGCONF:-} \
|
||||||
cmake \
|
cmake \
|
||||||
@@ -18,6 +18,7 @@ apt install -y \
|
|||||||
libglm-dev \
|
libglm-dev \
|
||||||
libmagic-dev \
|
libmagic-dev \
|
||||||
libmbedtls-dev \
|
libmbedtls-dev \
|
||||||
|
libfontconfig-dev \
|
||||||
libfreetype-dev \
|
libfreetype-dev \
|
||||||
libdbus-1-dev \
|
libdbus-1-dev \
|
||||||
libcurl4-gnutls-dev \
|
libcurl4-gnutls-dev \
|
||||||
@@ -26,4 +27,5 @@ apt install -y \
|
|||||||
zlib1g-dev \
|
zlib1g-dev \
|
||||||
libbz2-dev \
|
libbz2-dev \
|
||||||
liblzma-dev \
|
liblzma-dev \
|
||||||
libzstd-dev
|
libzstd-dev \
|
||||||
|
liblz4-dev
|
||||||
|
|||||||
4
dist/get_deps_fedora.sh
vendored
4
dist/get_deps_fedora.sh
vendored
@@ -4,6 +4,7 @@ dnf install -y \
|
|||||||
cmake \
|
cmake \
|
||||||
dbus-devel \
|
dbus-devel \
|
||||||
file-devel \
|
file-devel \
|
||||||
|
fontconfig-devel \
|
||||||
freetype-devel \
|
freetype-devel \
|
||||||
libcurl-devel \
|
libcurl-devel \
|
||||||
gcc-c++ \
|
gcc-c++ \
|
||||||
@@ -16,4 +17,5 @@ dnf install -y \
|
|||||||
libzstd-devel \
|
libzstd-devel \
|
||||||
zlib-devel \
|
zlib-devel \
|
||||||
bzip2-devel \
|
bzip2-devel \
|
||||||
xz-devel
|
xz-devel \
|
||||||
|
lz4-devel
|
||||||
3
dist/get_deps_msys2.sh
vendored
3
dist/get_deps_msys2.sh
vendored
@@ -17,4 +17,5 @@ pacboy -S --needed --noconfirm \
|
|||||||
zlib:p \
|
zlib:p \
|
||||||
bzip2:p \
|
bzip2:p \
|
||||||
xz:p \
|
xz:p \
|
||||||
zstd:p
|
zstd:p \
|
||||||
|
lz4:p
|
||||||
|
|||||||
8
dist/get_deps_tumbleweed.sh
vendored
8
dist/get_deps_tumbleweed.sh
vendored
@@ -3,8 +3,9 @@
|
|||||||
zypper install \
|
zypper install \
|
||||||
cmake \
|
cmake \
|
||||||
ninja \
|
ninja \
|
||||||
gcc12 \
|
gcc14 \
|
||||||
gcc12-c++ \
|
gcc14-c++ \
|
||||||
|
fontconfig-devel \
|
||||||
freetype2-devel \
|
freetype2-devel \
|
||||||
libcurl-devel \
|
libcurl-devel \
|
||||||
dbus-1-devel \
|
dbus-1-devel \
|
||||||
@@ -16,4 +17,5 @@ zypper install \
|
|||||||
libzstd-devel \
|
libzstd-devel \
|
||||||
zlib-devel \
|
zlib-devel \
|
||||||
bzip3-devel \
|
bzip3-devel \
|
||||||
xz-devel
|
xz-devel \
|
||||||
|
lz4-dev
|
||||||
|
|||||||
1
dist/imhex.desktop
vendored
1
dist/imhex.desktop
vendored
@@ -9,3 +9,4 @@ StartupNotify=true
|
|||||||
Categories=Development;IDE;
|
Categories=Development;IDE;
|
||||||
StartupWMClass=imhex
|
StartupWMClass=imhex
|
||||||
Keywords=static-analysis;reverse-engineering;disassembler;disassembly;hacking;forensics;hex-editor;cybersecurity;security;binary-analysis;
|
Keywords=static-analysis;reverse-engineering;disassembler;disassembly;hacking;forensics;hex-editor;cybersecurity;security;binary-analysis;
|
||||||
|
MimeType=application/vnd.imhex.proj;
|
||||||
|
|||||||
8
dist/imhex.mime.xml
vendored
Normal file
8
dist/imhex.mime.xml
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
|
||||||
|
<mime-type type="application/vnd.imhex.proj">
|
||||||
|
<comment>ImHex Project</comment>
|
||||||
|
<glob pattern="*.hexproj"/>
|
||||||
|
</mime-type>
|
||||||
|
</mime-info>
|
||||||
16
dist/langtool.py
vendored
16
dist/langtool.py
vendored
@@ -129,16 +129,19 @@ def main():
|
|||||||
key in lang_data["translations"]
|
key in lang_data["translations"]
|
||||||
and lang_data["translations"][key] != INVALID_TRANSLATION
|
and lang_data["translations"][key] != INVALID_TRANSLATION
|
||||||
)
|
)
|
||||||
if not has_translation and not (
|
if (
|
||||||
(command == "retranslate" or command == "untranslate")
|
has_translation
|
||||||
and re.compile(args.keys).fullmatch(key)
|
and not (
|
||||||
|
(command == "retranslate" or command == "untranslate")
|
||||||
|
and re.compile(args.keys).fullmatch(key)
|
||||||
|
)
|
||||||
|
and not command == "fmtzh"
|
||||||
):
|
):
|
||||||
continue
|
continue
|
||||||
if command == "check":
|
if command == "check":
|
||||||
print(
|
print(
|
||||||
f"Error: Translation {lang_data['code']} is missing translation for key '{key}'"
|
f"Error: Translation {lang_data['code']} is missing translation for key '{key}'"
|
||||||
)
|
)
|
||||||
exit(2)
|
|
||||||
elif (
|
elif (
|
||||||
command == "translate"
|
command == "translate"
|
||||||
or command == "retranslate"
|
or command == "retranslate"
|
||||||
@@ -148,7 +151,10 @@ def main():
|
|||||||
continue
|
continue
|
||||||
reference_tranlsation = (
|
reference_tranlsation = (
|
||||||
" '%s'" % reference_lang_data["translations"][key]
|
" '%s'" % reference_lang_data["translations"][key]
|
||||||
if reference_lang_data
|
if (
|
||||||
|
reference_lang_data
|
||||||
|
and key in reference_lang_data["translations"]
|
||||||
|
)
|
||||||
else ""
|
else ""
|
||||||
)
|
)
|
||||||
print(
|
print(
|
||||||
|
|||||||
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
|
# This base image is also known as "crosscompile". See arm64.crosscompile.Dockerfile
|
||||||
FROM ghcr.io/itrooz/macos-crosscompile:clang17-nosdk as build
|
FROM ghcr.io/itrooz/macos-crosscompile:clang17-nosdk as build
|
||||||
|
|
||||||
ENV MACOSX_DEPLOYMENT_TARGET 12.1
|
ENV MACOSX_DEPLOYMENT_TARGET 13.0
|
||||||
|
|
||||||
# -- DOWNLOADING STUFF
|
# -- DOWNLOADING STUFF
|
||||||
|
|
||||||
@@ -118,7 +118,7 @@ if [ "$CUSTOM_GLFW" ]; then
|
|||||||
cd /mnt/glfw
|
cd /mnt/glfw
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
CC=o64-gcc CXX=o64-g++ cmake -G "Ninja" \
|
CC=o64-clang CXX=o64-clang++ cmake -G "Ninja" \
|
||||||
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
|
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
|
||||||
-DBUILD_SHARED_LIBS=ON \
|
-DBUILD_SHARED_LIBS=ON \
|
||||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||||
@@ -126,7 +126,7 @@ if [ "$CUSTOM_GLFW" ]; then
|
|||||||
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
|
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
|
||||||
-DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
|
-DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
|
||||||
-DCMAKE_INSTALL_PREFIX=/vcpkg/installed/arm-osx-mytriplet \
|
-DCMAKE_INSTALL_PREFIX=/vcpkg/installed/arm-osx-mytriplet \
|
||||||
-DVCPKG_TARGET_TRIPLET=arm-osx-mytriplet -DCMAKE_TOOLCHAIN_FILE=/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/osxcross/target/toolchain.cmake -DCMAKE_OSX_SYSROOT=/osxcross/target/SDK/MacOSX14.0.sdk -DCMAKE_OSX_DEPLOYMENT_TARGET=12.1 \
|
-DVCPKG_TARGET_TRIPLET=arm-osx-mytriplet -DCMAKE_TOOLCHAIN_FILE=/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/osxcross/target/toolchain.cmake -DCMAKE_OSX_SYSROOT=/osxcross/target/SDK/MacOSX14.0.sdk -DCMAKE_OSX_DEPLOYMENT_TARGET=13.0 \
|
||||||
..
|
..
|
||||||
ninja -j $JOBS install
|
ninja -j $JOBS install
|
||||||
|
|
||||||
@@ -148,7 +148,7 @@ RUN --mount=type=cache,target=/cache --mount=type=cache,target=/mnt/ImHex/build/
|
|||||||
`# ccache flags` \
|
`# ccache flags` \
|
||||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_OBJC_COMPILER_LAUNCHER=ccache -DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
|
-DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_OBJC_COMPILER_LAUNCHER=ccache -DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
|
||||||
`# MacOS cross-compiling flags` \
|
`# MacOS cross-compiling flags` \
|
||||||
-DVCPKG_TARGET_TRIPLET=arm-osx-mytriplet -DCMAKE_TOOLCHAIN_FILE=/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/osxcross/target/toolchain.cmake -DCMAKE_OSX_SYSROOT=/osxcross/target/SDK/MacOSX14.0.sdk -DCMAKE_OSX_DEPLOYMENT_TARGET=12.1 \
|
-DVCPKG_TARGET_TRIPLET=arm-osx-mytriplet -DCMAKE_TOOLCHAIN_FILE=/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/osxcross/target/toolchain.cmake -DCMAKE_OSX_SYSROOT=/osxcross/target/SDK/MacOSX14.0.sdk -DCMAKE_OSX_DEPLOYMENT_TARGET=13.0 \
|
||||||
`# Override compilers for code generators` \
|
`# Override compilers for code generators` \
|
||||||
-DNATIVE_CMAKE_C_COMPILER=/usr/bin/clang -DNATIVE_CMAKE_CXX_COMPILER=/usr/bin/clang++ \
|
-DNATIVE_CMAKE_C_COMPILER=/usr/bin/clang -DNATIVE_CMAKE_CXX_COMPILER=/usr/bin/clang++ \
|
||||||
`# Normal ImHex flags` \
|
`# Normal ImHex flags` \
|
||||||
|
|||||||
13
dist/macOS/arm64.crosscompile.Dockerfile
vendored
13
dist/macOS/arm64.crosscompile.Dockerfile
vendored
@@ -68,19 +68,6 @@ RUN --mount=type=cache,target=/cache <<EOF
|
|||||||
|
|
||||||
ccache -s
|
ccache -s
|
||||||
EOF
|
EOF
|
||||||
# Not needed, because we don't use gcc for cross-compiling anymore
|
|
||||||
# ## Install dependencies for gcc-13
|
|
||||||
# RUN apt install -y gcc g++ zlib1g-dev libmpc-dev libmpfr-dev libgmp-dev
|
|
||||||
# ## Build cross-compiler gcc-13
|
|
||||||
# RUN --mount=type=cache,target=/cache <<EOF
|
|
||||||
# set -xe
|
|
||||||
# ccache -zs
|
|
||||||
|
|
||||||
# cd /osxcross
|
|
||||||
# UNATTENDED=1 CC=/usr/lib/ccache/gcc CXX=/usr/lib/ccache/g++ GCC_VERSION=13.2.0 ./build_gcc.sh
|
|
||||||
|
|
||||||
# ccache -s
|
|
||||||
# EOF
|
|
||||||
|
|
||||||
ARG DELETE_SDK=1
|
ARG DELETE_SDK=1
|
||||||
RUN <<EOF
|
RUN <<EOF
|
||||||
|
|||||||
12
dist/rpm/imhex.spec
vendored
12
dist/rpm/imhex.spec
vendored
@@ -16,6 +16,7 @@ BuildRequires: cmake
|
|||||||
BuildRequires: desktop-file-utils
|
BuildRequires: desktop-file-utils
|
||||||
BuildRequires: dbus-devel
|
BuildRequires: dbus-devel
|
||||||
BuildRequires: file-devel
|
BuildRequires: file-devel
|
||||||
|
BuildRequires: fontconfig-devel
|
||||||
BuildRequires: freetype-devel
|
BuildRequires: freetype-devel
|
||||||
BuildRequires: fmt-devel
|
BuildRequires: fmt-devel
|
||||||
BuildRequires: gcc-c++
|
BuildRequires: gcc-c++
|
||||||
@@ -34,7 +35,7 @@ BuildRequires: zlib-devel
|
|||||||
BuildRequires: bzip2-devel
|
BuildRequires: bzip2-devel
|
||||||
BuildRequires: xz-devel
|
BuildRequires: xz-devel
|
||||||
%if 0%{?rhel}
|
%if 0%{?rhel}
|
||||||
BuildRequires: gcc-toolset-12
|
BuildRequires: gcc-toolset-14
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
Provides: bundled(gnulib)
|
Provides: bundled(gnulib)
|
||||||
@@ -70,9 +71,9 @@ rm -rf lib/third_party/{fmt,nlohmann_json,yara}
|
|||||||
|
|
||||||
%build
|
%build
|
||||||
%if 0%{?rhel}
|
%if 0%{?rhel}
|
||||||
. /opt/rh/gcc-toolset-12/enable
|
. /opt/rh/gcc-toolset-14/enable
|
||||||
%set_build_flags
|
%set_build_flags
|
||||||
CXXFLAGS+=" -std=gnu++2b"
|
CXXFLAGS+=" -std=gnu++23"
|
||||||
%endif
|
%endif
|
||||||
%cmake \
|
%cmake \
|
||||||
-D CMAKE_BUILD_TYPE=Release \
|
-D CMAKE_BUILD_TYPE=Release \
|
||||||
@@ -93,9 +94,9 @@ CXXFLAGS+=" -std=gnu++2b"
|
|||||||
|
|
||||||
%check
|
%check
|
||||||
%if 0%{?rhel}
|
%if 0%{?rhel}
|
||||||
. /opt/rh/gcc-toolset-12/enable
|
. /opt/rh/gcc-toolset-14/enable
|
||||||
%set_build_flags
|
%set_build_flags
|
||||||
CXXFLAGS+=" -std=gnu++2b"
|
CXXFLAGS+=" -std=gnu++23"
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
|
|
||||||
@@ -124,6 +125,7 @@ cp -a lib/third_party/xdgpp/LICENSE %{buildroot
|
|||||||
%{_bindir}/imhex-updater
|
%{_bindir}/imhex-updater
|
||||||
%{_datadir}/pixmaps/%{name}.png
|
%{_datadir}/pixmaps/%{name}.png
|
||||||
%{_datadir}/applications/%{name}.desktop
|
%{_datadir}/applications/%{name}.desktop
|
||||||
|
%{_datadir}/mime/packages/%{name}.xml
|
||||||
%{_libdir}/libimhex.so*
|
%{_libdir}/libimhex.so*
|
||||||
%{_libdir}/%{name}/
|
%{_libdir}/%{name}/
|
||||||
%{_metainfodir}/net.werwolv.%{name}.metainfo.xml
|
%{_metainfodir}/net.werwolv.%{name}.metainfo.xml
|
||||||
5
dist/web/Dockerfile
vendored
5
dist/web/Dockerfile
vendored
@@ -5,7 +5,7 @@ FROM emscripten/emsdk:3.1.51 as build
|
|||||||
ARG UNIQUEKEY 1
|
ARG UNIQUEKEY 1
|
||||||
|
|
||||||
RUN apt update
|
RUN apt update
|
||||||
RUN apt install -y git ccache autoconf automake libtool cmake pkg-config
|
RUN apt install -y git ccache autoconf automake libtool cmake pkg-config ninja-build
|
||||||
|
|
||||||
RUN <<EOF
|
RUN <<EOF
|
||||||
# Install vcpkg
|
# Install vcpkg
|
||||||
@@ -56,6 +56,7 @@ set -xe
|
|||||||
ccache -zs
|
ccache -zs
|
||||||
|
|
||||||
cmake /imhex \
|
cmake /imhex \
|
||||||
|
-G "Ninja" \
|
||||||
-DIMHEX_OFFLINE_BUILD=ON \
|
-DIMHEX_OFFLINE_BUILD=ON \
|
||||||
-DIMHEX_STATIC_LINK_PLUGINS=ON \
|
-DIMHEX_STATIC_LINK_PLUGINS=ON \
|
||||||
-DIMHEX_EXCLUDE_PLUGINS="script_loader" \
|
-DIMHEX_EXCLUDE_PLUGINS="script_loader" \
|
||||||
@@ -68,7 +69,7 @@ cmake /imhex
|
|||||||
-DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake \
|
-DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake \
|
||||||
-DCMAKE_BUILD_TYPE=Release
|
-DCMAKE_BUILD_TYPE=Release
|
||||||
|
|
||||||
make -j $JOBS
|
ninja -j $JOBS
|
||||||
|
|
||||||
cp /imhex/dist/web/source/* /build
|
cp /imhex/dist/web/source/* /build
|
||||||
ccache -s
|
ccache -s
|
||||||
|
|||||||
2
dist/web/source/index.html
vendored
2
dist/web/source/index.html
vendored
@@ -62,7 +62,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="loading" class="centered">
|
<div id="loading" class="centered">
|
||||||
<img src="https://raw.githubusercontent.com/WerWolv/ImHex/master/plugins/builtin/romfs/assets/dark/banner.png" id="logo" alt="ImHex Logo">
|
<img src="https://raw.githubusercontent.com/WerWolv/ImHex/master/plugins/builtin/romfs/assets/dark/banner.svg" id="logo" alt="ImHex Logo">
|
||||||
<h1>A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.</h1>
|
<h1>A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.</h1>
|
||||||
<h2>Available both natively and on the web</h2>
|
<h2>Available both natively and on the web</h2>
|
||||||
<h5>ImHex runs directly in your web browser with the help of Emscripten and WebAssembly.</h5>
|
<h5>ImHex runs directly in your web browser with the help of Emscripten and WebAssembly.</h5>
|
||||||
|
|||||||
13
dist/web/source/style.css
vendored
13
dist/web/source/style.css
vendored
@@ -137,7 +137,7 @@ a:hover {
|
|||||||
|
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--progress: 25%;
|
--progress: 0%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress-bar-container {
|
.progress-bar-container {
|
||||||
@@ -175,3 +175,14 @@ a:hover {
|
|||||||
width: var(--progress);
|
width: var(--progress);
|
||||||
background-color: #3864cb;
|
background-color: #3864cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#logo {
|
||||||
|
height: 25%;
|
||||||
|
margin-top: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.canvas-fixed {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
144
dist/web/source/wasm-config.js
vendored
144
dist/web/source/wasm-config.js
vendored
@@ -100,7 +100,77 @@ var notWorkingTimer = setTimeout(() => {
|
|||||||
|
|
||||||
var Module = {
|
var Module = {
|
||||||
preRun: [],
|
preRun: [],
|
||||||
postRun: [],
|
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() {
|
onRuntimeInitialized: function() {
|
||||||
// Triggered when the wasm module is loaded and ready to use.
|
// Triggered when the wasm module is loaded and ready to use.
|
||||||
document.getElementById("loading").style.display = "none"
|
document.getElementById("loading").style.display = "none"
|
||||||
@@ -111,13 +181,55 @@ var Module = {
|
|||||||
print: (function() { })(),
|
print: (function() { })(),
|
||||||
printErr: function(text) { },
|
printErr: function(text) { },
|
||||||
canvas: (function() {
|
canvas: (function() {
|
||||||
let canvas = document.getElementById('canvas');
|
const canvas = document.getElementById('canvas');
|
||||||
// As a default initial behavior, pop up an alert when webgl context is lost. To make your
|
canvas.addEventListener("webglcontextlost", function(e) {
|
||||||
// application robust, you may want to override this behavior before shipping!
|
alert('WebGL context lost, please reload the page');
|
||||||
// See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2
|
e.preventDefault();
|
||||||
canvas.addEventListener("webglcontextlost", function(e) { alert('WebGL context lost. You will need to reload the page.'); e.preventDefault(); }, false);
|
}, false);
|
||||||
|
|
||||||
return canvas;
|
// Turn long touches into right-clicks
|
||||||
|
let timer = null;
|
||||||
|
canvas.addEventListener('touchstart', event => {
|
||||||
|
timer = setTimeout(() => {
|
||||||
|
let eventArgs = {
|
||||||
|
bubbles: true,
|
||||||
|
cancelable: true,
|
||||||
|
view: window,
|
||||||
|
screenX: event.touches[0].screenX,
|
||||||
|
screenY: event.touches[0].screenY,
|
||||||
|
clientX: event.touches[0].clientX,
|
||||||
|
clientY: event.touches[0].clientY,
|
||||||
|
button: 2,
|
||||||
|
buttons: 2,
|
||||||
|
relatedTarget: event.target,
|
||||||
|
region: event.region
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.dispatchEvent(new MouseEvent('mousedown', eventArgs));
|
||||||
|
canvas.dispatchEvent(new MouseEvent('mouseup', eventArgs));
|
||||||
|
}, 400);
|
||||||
|
});
|
||||||
|
|
||||||
|
canvas.addEventListener('touchend', event => {
|
||||||
|
if (timer) {
|
||||||
|
clearTimeout(timer);
|
||||||
|
timer = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (typeof WebGL2RenderingContext !== 'undefined') {
|
||||||
|
let gl = canvas.getContext('webgl2', { stencil: true });
|
||||||
|
if (!gl) {
|
||||||
|
console.error('WebGL 2 not available, falling back to WebGL');
|
||||||
|
gl = canvas.getContext('webgl', { stencil: true });
|
||||||
|
}
|
||||||
|
if (!gl) {
|
||||||
|
alert('WebGL not available with stencil buffer');
|
||||||
|
}
|
||||||
|
return canvas;
|
||||||
|
} else {
|
||||||
|
alert('WebGL 2 not supported by this browser');
|
||||||
|
}
|
||||||
})(),
|
})(),
|
||||||
setStatus: function(text) { },
|
setStatus: function(text) { },
|
||||||
totalDependencies: 0,
|
totalDependencies: 0,
|
||||||
@@ -144,14 +256,16 @@ if (urlParams.has("lang")) {
|
|||||||
window.addEventListener('resize', js_resizeCanvas, false);
|
window.addEventListener('resize', js_resizeCanvas, false);
|
||||||
function js_resizeCanvas() {
|
function js_resizeCanvas() {
|
||||||
let canvas = document.getElementById('canvas');
|
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.width = Math.min(document.documentElement.clientWidth, window.innerWidth || 0);
|
||||||
canvas.height = Math.min(document.documentElement.clientHeight, window.innerHeight || 0);
|
canvas.height = Math.min(document.documentElement.clientHeight, window.innerHeight || 0);
|
||||||
|
|
||||||
canvas.classList.add("canvas_full_screen")
|
|
||||||
|
|
||||||
if (GLFW.active && GLFW.active.windowPosFunc) {
|
|
||||||
getWasmTableEntry(GLFW.active.windowPosFunc)(GLFW.active.id, GLFW.active.x, GLFW.active.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFW.onWindowSizeChanged();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prevent some default browser shortcuts from preventing ImHex ones to work
|
||||||
|
document.addEventListener('keydown', e => {
|
||||||
|
if (e.ctrlKey) {
|
||||||
|
if (e.which == 83) e.preventDefault();
|
||||||
|
}
|
||||||
|
})
|
||||||
2
lib/external/libwolv
vendored
2
lib/external/libwolv
vendored
Submodule lib/external/libwolv updated: 0e3ba3aa6f...b9d7f4abaf
2
lib/external/pattern_language
vendored
2
lib/external/pattern_language
vendored
Submodule lib/external/pattern_language updated: c09d987099...f45156a55c
@@ -38,6 +38,7 @@ set(LIBIMHEX_SOURCES
|
|||||||
source/helpers/debugging.cpp
|
source/helpers/debugging.cpp
|
||||||
source/helpers/default_paths.cpp
|
source/helpers/default_paths.cpp
|
||||||
source/helpers/imgui_hooks.cpp
|
source/helpers/imgui_hooks.cpp
|
||||||
|
source/helpers/semantic_version.cpp
|
||||||
|
|
||||||
source/test/tests.cpp
|
source/test/tests.cpp
|
||||||
|
|
||||||
@@ -144,7 +145,7 @@ if (NOT IMHEX_EXTERNAL_PLUGIN_BUILD)
|
|||||||
precompileHeaders(libimhex "${CMAKE_CURRENT_SOURCE_DIR}/include")
|
precompileHeaders(libimhex "${CMAKE_CURRENT_SOURCE_DIR}/include")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_link_libraries(libimhex ${LIBIMHEX_LIBRARY_TYPE} ${NLOHMANN_JSON_LIBRARIES} imgui_all_includes ${MBEDTLS_LIBRARIES} ${FMT_LIBRARIES} ${LUNASVG_LIBRARIES} boost::regex)
|
target_link_libraries(libimhex ${LIBIMHEX_LIBRARY_TYPE} ${NLOHMANN_JSON_LIBRARIES} imgui_all_includes ${MBEDTLS_LIBRARIES} ${FMT_LIBRARIES} ${LUNASVG_LIBRARIES} ${BOOST_LIBRARIES})
|
||||||
|
|
||||||
set_property(TARGET libimhex PROPERTY INTERPROCEDURAL_OPTIMIZATION FALSE)
|
set_property(TARGET libimhex PROPERTY INTERPROCEDURAL_OPTIMIZATION FALSE)
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <hex/helpers/types.hpp>
|
#include <hex/helpers/types.hpp>
|
||||||
#include <hex/helpers/intrinsics.hpp>
|
|
||||||
@@ -295,6 +295,7 @@ namespace hex {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class AchievementManager {
|
class AchievementManager {
|
||||||
|
static bool s_initialized;
|
||||||
public:
|
public:
|
||||||
AchievementManager() = delete;
|
AchievementManager() = delete;
|
||||||
|
|
||||||
|
|||||||
@@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
#include <hex.hpp>
|
#include <hex.hpp>
|
||||||
#include <hex/api/localization_manager.hpp>
|
#include <hex/api/localization_manager.hpp>
|
||||||
|
#include <hex/api/shortcut_manager.hpp>
|
||||||
#include <hex/helpers/concepts.hpp>
|
#include <hex/helpers/concepts.hpp>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <map>
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <span>
|
#include <span>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -24,7 +24,6 @@ enum ImGuiCustomCol : int;
|
|||||||
namespace hex {
|
namespace hex {
|
||||||
|
|
||||||
class View;
|
class View;
|
||||||
class Shortcut;
|
|
||||||
class Task;
|
class Task;
|
||||||
|
|
||||||
namespace dp {
|
namespace dp {
|
||||||
@@ -381,7 +380,7 @@ namespace hex {
|
|||||||
};
|
};
|
||||||
|
|
||||||
using DisplayCallback = std::function<std::string(std::string)>;
|
using DisplayCallback = std::function<std::string(std::string)>;
|
||||||
using ExecuteCallback = std::function<void(std::string)>;
|
using ExecuteCallback = std::function<std::optional<std::string>(std::string)>;
|
||||||
using QueryCallback = std::function<std::vector<QueryResult>(std::string)>;
|
using QueryCallback = std::function<std::vector<QueryResult>(std::string)>;
|
||||||
|
|
||||||
struct Entry {
|
struct Entry {
|
||||||
@@ -417,7 +416,7 @@ namespace hex {
|
|||||||
const std::string &command,
|
const std::string &command,
|
||||||
const UnlocalizedString &unlocalizedDescription,
|
const UnlocalizedString &unlocalizedDescription,
|
||||||
const impl::DisplayCallback &displayCallback,
|
const impl::DisplayCallback &displayCallback,
|
||||||
const impl::ExecuteCallback &executeCallback = [](auto) {});
|
const impl::ExecuteCallback &executeCallback = [](auto) { return std::nullopt; });
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Adds a new command handler to the command palette
|
* @brief Adds a new command handler to the command palette
|
||||||
@@ -438,7 +437,7 @@ namespace hex {
|
|||||||
|
|
||||||
namespace impl {
|
namespace impl {
|
||||||
|
|
||||||
using VisualizerFunctionCallback = std::function<void(pl::ptrn::Pattern&, pl::ptrn::IIterable&, bool, std::span<const pl::core::Token::Literal>)>;
|
using VisualizerFunctionCallback = std::function<void(pl::ptrn::Pattern&, bool, std::span<const pl::core::Token::Literal>)>;
|
||||||
|
|
||||||
struct FunctionDefinition {
|
struct FunctionDefinition {
|
||||||
pl::api::Namespace ns;
|
pl::api::Namespace ns;
|
||||||
@@ -450,6 +449,14 @@ namespace hex {
|
|||||||
bool dangerous;
|
bool dangerous;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct TypeDefinition {
|
||||||
|
pl::api::Namespace ns;
|
||||||
|
std::string name;
|
||||||
|
|
||||||
|
pl::api::FunctionParameterCount parameterCount;
|
||||||
|
pl::api::TypeCallback callback;
|
||||||
|
};
|
||||||
|
|
||||||
struct Visualizer {
|
struct Visualizer {
|
||||||
pl::api::FunctionParameterCount parameterCount;
|
pl::api::FunctionParameterCount parameterCount;
|
||||||
VisualizerFunctionCallback callback;
|
VisualizerFunctionCallback callback;
|
||||||
@@ -459,6 +466,7 @@ namespace hex {
|
|||||||
const std::map<std::string, Visualizer>& getInlineVisualizers();
|
const std::map<std::string, Visualizer>& getInlineVisualizers();
|
||||||
const std::map<std::string, pl::api::PragmaHandler>& getPragmas();
|
const std::map<std::string, pl::api::PragmaHandler>& getPragmas();
|
||||||
const std::vector<FunctionDefinition>& getFunctions();
|
const std::vector<FunctionDefinition>& getFunctions();
|
||||||
|
const std::vector<TypeDefinition>& getTypes();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -517,6 +525,20 @@ namespace hex {
|
|||||||
const pl::api::FunctionCallback &func
|
const pl::api::FunctionCallback &func
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Adds a new type to the pattern language
|
||||||
|
* @param ns The namespace of the type
|
||||||
|
* @param name The name of the type
|
||||||
|
* @param parameterCount The amount of non-type template parameters the type takes
|
||||||
|
* @param func The type callback
|
||||||
|
*/
|
||||||
|
void addType(
|
||||||
|
const pl::api::Namespace &ns,
|
||||||
|
const std::string &name,
|
||||||
|
pl::api::FunctionParameterCount parameterCount,
|
||||||
|
const pl::api::TypeCallback &func
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Adds a new visualizer to the pattern language
|
* @brief Adds a new visualizer to the pattern language
|
||||||
* @note Visualizers are extensions to the [[hex::visualize]] attribute, used to visualize data
|
* @note Visualizers are extensions to the [[hex::visualize]] attribute, used to visualize data
|
||||||
@@ -748,7 +770,7 @@ namespace hex {
|
|||||||
struct MenuItem {
|
struct MenuItem {
|
||||||
std::vector<UnlocalizedString> unlocalizedNames;
|
std::vector<UnlocalizedString> unlocalizedNames;
|
||||||
Icon icon;
|
Icon icon;
|
||||||
std::unique_ptr<Shortcut> shortcut;
|
Shortcut shortcut;
|
||||||
View *view;
|
View *view;
|
||||||
MenuCallback callback;
|
MenuCallback callback;
|
||||||
EnabledCallback enabledCallback;
|
EnabledCallback enabledCallback;
|
||||||
@@ -1273,7 +1295,7 @@ namespace hex {
|
|||||||
void stopServices();
|
void stopServices();
|
||||||
}
|
}
|
||||||
|
|
||||||
void registerService(const UnlocalizedString &unlocalizedName, const impl::Callback &callback);
|
void registerService(const UnlocalizedString &unlocalizedString, const impl::Callback &callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Network Communication Interface Registry. Allows adding new communication interface endpoints */
|
/* Network Communication Interface Registry. Allows adding new communication interface endpoints */
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include <hex/api/imhex_api.hpp>
|
#include <hex/api/imhex_api.hpp>
|
||||||
#include <hex/helpers/logger.hpp>
|
#include <hex/helpers/logger.hpp>
|
||||||
|
#include <hex/helpers/patches.hpp>
|
||||||
|
|
||||||
#include <wolv/types/type_name.hpp>
|
#include <wolv/types/type_name.hpp>
|
||||||
|
|
||||||
@@ -129,15 +130,9 @@ namespace hex {
|
|||||||
static void subscribe(void *token, typename E::Callback function) {
|
static void subscribe(void *token, typename E::Callback function) {
|
||||||
std::scoped_lock lock(getEventMutex());
|
std::scoped_lock lock(getEventMutex());
|
||||||
|
|
||||||
if (getTokenStore().contains(token)) {
|
if (isAlreadyRegistered(token, E::Id)) {
|
||||||
auto&& [begin, end] = getTokenStore().equal_range(token);
|
log::fatal("The token '{}' has already registered the same event ('{}')", token, wolv::type::getTypeName<E>());
|
||||||
const auto eventRegistered = std::any_of(begin, end, [&](auto &item) {
|
return;
|
||||||
return item.second->first == E::Id;
|
|
||||||
});
|
|
||||||
if (eventRegistered) {
|
|
||||||
log::fatal("The token '{}' has already registered the same event ('{}')", token, wolv::type::getTypeName<E>());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getTokenStore().insert({ token, subscribe<E>(function) });
|
getTokenStore().insert({ token, subscribe<E>(function) });
|
||||||
@@ -162,16 +157,7 @@ namespace hex {
|
|||||||
static void unsubscribe(void *token) noexcept {
|
static void unsubscribe(void *token) noexcept {
|
||||||
std::scoped_lock lock(getEventMutex());
|
std::scoped_lock lock(getEventMutex());
|
||||||
|
|
||||||
auto &tokenStore = getTokenStore();
|
unsubscribe(token, E::Id);
|
||||||
auto iter = std::find_if(tokenStore.begin(), tokenStore.end(), [&](auto &item) {
|
|
||||||
return item.first == token && item.second->first == E::Id;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (iter != tokenStore.end()) {
|
|
||||||
getEvents().erase(iter->second);
|
|
||||||
tokenStore.erase(iter);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -209,6 +195,9 @@ namespace hex {
|
|||||||
static std::multimap<void *, EventList::iterator>& getTokenStore();
|
static std::multimap<void *, EventList::iterator>& getTokenStore();
|
||||||
static EventList& getEvents();
|
static EventList& getEvents();
|
||||||
static std::recursive_mutex& getEventMutex();
|
static std::recursive_mutex& getEventMutex();
|
||||||
|
|
||||||
|
static bool isAlreadyRegistered(void *token, impl::EventId id);
|
||||||
|
static void unsubscribe(void *token, impl::EventId id);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Default Events */
|
/* Default Events */
|
||||||
@@ -226,7 +215,9 @@ namespace hex {
|
|||||||
EVENT_DEF(EventAbnormalTermination, int);
|
EVENT_DEF(EventAbnormalTermination, int);
|
||||||
EVENT_DEF(EventThemeChanged);
|
EVENT_DEF(EventThemeChanged);
|
||||||
EVENT_DEF(EventOSThemeChanged);
|
EVENT_DEF(EventOSThemeChanged);
|
||||||
|
EVENT_DEF(EventDPIChanged, float, float);
|
||||||
EVENT_DEF(EventWindowFocused, bool);
|
EVENT_DEF(EventWindowFocused, bool);
|
||||||
|
EVENT_DEF(EventImHexUpdated, SemanticVersion, SemanticVersion);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Called when the provider is created.
|
* @brief Called when the provider is created.
|
||||||
@@ -252,7 +243,12 @@ namespace hex {
|
|||||||
EVENT_DEF(EventWindowInitialized);
|
EVENT_DEF(EventWindowInitialized);
|
||||||
EVENT_DEF(EventWindowDeinitializing, GLFWwindow *);
|
EVENT_DEF(EventWindowDeinitializing, GLFWwindow *);
|
||||||
EVENT_DEF(EventBookmarkCreated, ImHexApi::Bookmarks::Entry&);
|
EVENT_DEF(EventBookmarkCreated, ImHexApi::Bookmarks::Entry&);
|
||||||
EVENT_DEF(EventPatchCreated, u64, u8, u8);
|
|
||||||
|
/**
|
||||||
|
* @brief Called upon creation of an IPS patch.
|
||||||
|
* As for now, the event only serves a purpose for the achievement unlock.
|
||||||
|
*/
|
||||||
|
EVENT_DEF(EventPatchCreated, const u8*, u64, const PatchKind);
|
||||||
EVENT_DEF(EventPatternEvaluating);
|
EVENT_DEF(EventPatternEvaluating);
|
||||||
EVENT_DEF(EventPatternExecuted, const std::string&);
|
EVENT_DEF(EventPatternExecuted, const std::string&);
|
||||||
EVENT_DEF(EventPatternEditorChanged, const std::string&);
|
EVENT_DEF(EventPatternEditorChanged, const std::string&);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <hex.hpp>
|
#include <hex.hpp>
|
||||||
#include <hex/api/localization_manager.hpp>
|
#include <hex/api/localization_manager.hpp>
|
||||||
|
#include <hex/helpers/semantic_version.hpp>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
@@ -75,7 +76,7 @@ namespace hex {
|
|||||||
namespace impl {
|
namespace impl {
|
||||||
|
|
||||||
using HighlightingFunction = std::function<std::optional<color_t>(u64, const u8*, size_t, bool)>;
|
using HighlightingFunction = std::function<std::optional<color_t>(u64, const u8*, size_t, bool)>;
|
||||||
using HoveringFunction = std::function<bool(const prv::Provider *, u64, const u8*, size_t)>;
|
using HoveringFunction = std::function<std::set<Region>(const prv::Provider *, u64, size_t)>;
|
||||||
|
|
||||||
const std::map<u32, Highlighting>& getBackgroundHighlights();
|
const std::map<u32, Highlighting>& getBackgroundHighlights();
|
||||||
const std::map<u32, HighlightingFunction>& getBackgroundHighlightingFunctions();
|
const std::map<u32, HighlightingFunction>& getBackgroundHighlightingFunctions();
|
||||||
@@ -618,7 +619,7 @@ namespace hex {
|
|||||||
* @brief Gets the current ImHex version
|
* @brief Gets the current ImHex version
|
||||||
* @return ImHex version
|
* @return ImHex version
|
||||||
*/
|
*/
|
||||||
std::string getImHexVersion(bool withBuildType = true);
|
SemanticVersion getImHexVersion();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets the current git commit hash
|
* @brief Gets the current git commit hash
|
||||||
@@ -695,6 +696,13 @@ namespace hex {
|
|||||||
*/
|
*/
|
||||||
void* getLibImHexModuleHandle();
|
void* getLibImHexModuleHandle();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new migration routine that will be executed when upgrading from a lower version than specified in migrationVersion
|
||||||
|
* @param migrationVersion Upgrade point version
|
||||||
|
* @param function Function to run
|
||||||
|
*/
|
||||||
|
void addMigrationRoutine(SemanticVersion migrationVersion, std::function<void()> function);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <hex.hpp>
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/core.h>
|
||||||
|
#include <wolv/types/static_string.hpp>
|
||||||
|
|
||||||
namespace hex {
|
namespace hex {
|
||||||
|
|
||||||
@@ -22,8 +25,10 @@ namespace hex {
|
|||||||
};
|
};
|
||||||
|
|
||||||
namespace impl {
|
namespace impl {
|
||||||
|
|
||||||
void setFallbackLanguage(const std::string &language);
|
void setFallbackLanguage(const std::string &language);
|
||||||
void resetLanguageStrings();
|
void resetLanguageStrings();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadLanguage(const std::string &language);
|
void loadLanguage(const std::string &language);
|
||||||
@@ -32,14 +37,18 @@ namespace hex {
|
|||||||
[[nodiscard]] const std::map<std::string, std::string> &getSupportedLanguages();
|
[[nodiscard]] const std::map<std::string, std::string> &getSupportedLanguages();
|
||||||
[[nodiscard]] const std::string &getFallbackLanguage();
|
[[nodiscard]] const std::string &getFallbackLanguage();
|
||||||
[[nodiscard]] const std::string &getSelectedLanguage();
|
[[nodiscard]] const std::string &getSelectedLanguage();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct UnlocalizedString;
|
struct UnlocalizedString;
|
||||||
|
|
||||||
|
class LangConst;
|
||||||
|
|
||||||
class Lang {
|
class Lang {
|
||||||
public:
|
public:
|
||||||
explicit Lang(const char *unlocalizedString);
|
explicit Lang(const char *unlocalizedString);
|
||||||
explicit Lang(const std::string &unlocalizedString);
|
explicit Lang(const std::string &unlocalizedString);
|
||||||
|
explicit(false) Lang(const LangConst &localizedString);
|
||||||
explicit Lang(const UnlocalizedString &unlocalizedString);
|
explicit Lang(const UnlocalizedString &unlocalizedString);
|
||||||
explicit Lang(std::string_view unlocalizedString);
|
explicit Lang(std::string_view unlocalizedString);
|
||||||
|
|
||||||
@@ -47,30 +56,54 @@ namespace hex {
|
|||||||
[[nodiscard]] operator std::string_view() const;
|
[[nodiscard]] operator std::string_view() const;
|
||||||
[[nodiscard]] operator const char *() const;
|
[[nodiscard]] operator const char *() const;
|
||||||
|
|
||||||
[[nodiscard]] const std::string &get() const;
|
const char* get() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
std::size_t m_entryHash;
|
||||||
std::string m_unlocalizedString;
|
std::string m_unlocalizedString;
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] std::string operator+(const std::string &&left, const Lang &&right);
|
class LangConst {
|
||||||
[[nodiscard]] std::string operator+(const Lang &&left, const std::string &&right);
|
public:
|
||||||
[[nodiscard]] std::string operator+(const std::string_view &&left, const Lang &&right);
|
[[nodiscard]] operator std::string() const;
|
||||||
[[nodiscard]] std::string operator+(const Lang &&left, const std::string_view &&right);
|
[[nodiscard]] operator std::string_view() const;
|
||||||
[[nodiscard]] std::string operator+(const char *left, const Lang &&right);
|
[[nodiscard]] operator const char *() const;
|
||||||
[[nodiscard]] std::string operator+(const Lang &&left, const char *right);
|
|
||||||
[[nodiscard]] std::string operator+(const Lang &&left, const Lang &&right);
|
|
||||||
|
|
||||||
[[nodiscard]] inline Lang operator""_lang(const char *string, size_t) {
|
const char* get() const;
|
||||||
return Lang(string);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
constexpr static size_t hash(std::string_view string) {
|
||||||
|
constexpr u64 p = 131;
|
||||||
|
constexpr u64 m = std::numeric_limits<std::uint32_t>::max() - 4;
|
||||||
|
u64 total = 0;
|
||||||
|
u64 currentMultiplier = 1;
|
||||||
|
|
||||||
|
for (char c : string) {
|
||||||
|
total = (total + currentMultiplier * c) % m;
|
||||||
|
currentMultiplier = (currentMultiplier * p) % m;
|
||||||
|
}
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
constexpr explicit LangConst(std::size_t hash, const char *unlocalizedString) : m_entryHash(hash), m_unlocalizedString(unlocalizedString) {}
|
||||||
|
|
||||||
|
template<wolv::type::StaticString>
|
||||||
|
friend consteval LangConst operator""_lang();
|
||||||
|
friend class Lang;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::size_t m_entryHash;
|
||||||
|
const char *m_unlocalizedString = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
struct UnlocalizedString {
|
struct UnlocalizedString {
|
||||||
public:
|
public:
|
||||||
UnlocalizedString() = default;
|
UnlocalizedString() = default;
|
||||||
UnlocalizedString(auto && arg) : m_unlocalizedString(std::forward<decltype(arg)>(arg)) {
|
|
||||||
static_assert(!std::same_as<std::remove_cvref_t<decltype(arg)>, Lang>, "Expected a unlocalized name, got a localized one!");
|
template<typename T>
|
||||||
|
UnlocalizedString(T &&arg) : m_unlocalizedString(std::forward<T>(arg)) {
|
||||||
|
static_assert(!std::same_as<std::remove_cvref_t<T>, Lang>, "Expected a unlocalized name, got a localized one!");
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] operator std::string() const {
|
[[nodiscard]] operator std::string() const {
|
||||||
@@ -102,12 +135,17 @@ namespace hex {
|
|||||||
std::string m_unlocalizedString;
|
std::string m_unlocalizedString;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
template<wolv::type::StaticString String>
|
||||||
|
[[nodiscard]] consteval LangConst operator""_lang() {
|
||||||
template<>
|
return LangConst(LangConst::hash(String.value.data()), String.value.data());
|
||||||
struct fmt::formatter<hex::Lang> : fmt::formatter<std::string_view> {
|
|
||||||
template<typename FormatContext>
|
|
||||||
auto format(const hex::Lang &entry, FormatContext &ctx) {
|
|
||||||
return fmt::formatter<std::string_view>::format(entry.get(), ctx);
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
// {fmt} formatter for hex::Lang and hex::LangConst
|
||||||
|
inline auto format_as(const hex::Lang &entry) {
|
||||||
|
return entry.get();
|
||||||
|
}
|
||||||
|
inline auto format_as(const hex::LangConst &entry) {
|
||||||
|
return entry.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ namespace hex {
|
|||||||
|
|
||||||
class View;
|
class View;
|
||||||
|
|
||||||
enum class Keys {
|
enum class Keys : u32 {
|
||||||
Space = GLFW_KEY_SPACE,
|
Space = GLFW_KEY_SPACE,
|
||||||
Apostrophe = GLFW_KEY_APOSTROPHE,
|
Apostrophe = GLFW_KEY_APOSTROPHE,
|
||||||
Comma = GLFW_KEY_COMMA,
|
Comma = GLFW_KEY_COMMA,
|
||||||
@@ -138,6 +138,7 @@ namespace hex {
|
|||||||
constexpr Key() = default;
|
constexpr Key() = default;
|
||||||
constexpr Key(Keys key) : m_key(static_cast<u32>(key)) { }
|
constexpr Key(Keys key) : m_key(static_cast<u32>(key)) { }
|
||||||
|
|
||||||
|
bool operator==(const Key &) const = default;
|
||||||
auto operator<=>(const Key &) const = default;
|
auto operator<=>(const Key &) const = default;
|
||||||
|
|
||||||
[[nodiscard]] constexpr u32 getKeyCode() const { return m_key; }
|
[[nodiscard]] constexpr u32 getKeyCode() const { return m_key; }
|
||||||
@@ -152,224 +153,31 @@ namespace hex {
|
|||||||
constexpr static auto SUPER = Key(static_cast<Keys>(0x0800'0000));
|
constexpr static auto SUPER = Key(static_cast<Keys>(0x0800'0000));
|
||||||
constexpr static auto CurrentView = Key(static_cast<Keys>(0x1000'0000));
|
constexpr static auto CurrentView = Key(static_cast<Keys>(0x1000'0000));
|
||||||
constexpr static auto AllowWhileTyping = Key(static_cast<Keys>(0x2000'0000));
|
constexpr static auto AllowWhileTyping = Key(static_cast<Keys>(0x2000'0000));
|
||||||
|
constexpr static auto CTRLCMD = Key(static_cast<Keys>(0x4000'0000));
|
||||||
#if defined (OS_MACOS)
|
|
||||||
constexpr static auto CTRLCMD = SUPER;
|
|
||||||
#else
|
|
||||||
constexpr static auto CTRLCMD = CTRL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class Shortcut {
|
class Shortcut {
|
||||||
public:
|
public:
|
||||||
Shortcut() = default;
|
Shortcut() = default;
|
||||||
Shortcut(Keys key) : m_keys({ key }) { }
|
Shortcut(Keys key);
|
||||||
explicit Shortcut(std::set<Key> keys) : m_keys(std::move(keys)) { }
|
explicit Shortcut(std::set<Key> keys);
|
||||||
Shortcut(const Shortcut &other) = default;
|
Shortcut(const Shortcut &other) = default;
|
||||||
Shortcut(Shortcut &&) noexcept = default;
|
Shortcut(Shortcut &&) noexcept = default;
|
||||||
|
|
||||||
Shortcut& operator=(const Shortcut &other) = default;
|
constexpr static auto None = Keys(0);
|
||||||
|
|
||||||
|
Shortcut& operator=(const Shortcut &other) = default;
|
||||||
Shortcut& operator=(Shortcut &&) noexcept = default;
|
Shortcut& operator=(Shortcut &&) noexcept = default;
|
||||||
|
|
||||||
constexpr static inline auto None = Keys(0);
|
Shortcut operator+(const Key &other) const;
|
||||||
|
Shortcut &operator+=(const Key &other);
|
||||||
|
bool operator<(const Shortcut &other) const;
|
||||||
|
bool operator==(const Shortcut &other) const;
|
||||||
|
|
||||||
Shortcut operator+(const Key &other) const {
|
bool isLocal() const;
|
||||||
Shortcut result = *this;
|
std::string toString() const;
|
||||||
result.m_keys.insert(other);
|
const std::set<Key>& getKeys() const;
|
||||||
|
bool has(Key key) const;
|
||||||
return result;
|
bool matches(const Shortcut &other) const;
|
||||||
}
|
|
||||||
|
|
||||||
Shortcut &operator+=(const Key &other) {
|
|
||||||
m_keys.insert(other);
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator<(const Shortcut &other) const {
|
|
||||||
return m_keys < other.m_keys;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const Shortcut &other) const {
|
|
||||||
auto thisKeys = m_keys;
|
|
||||||
auto otherKeys = other.m_keys;
|
|
||||||
|
|
||||||
thisKeys.erase(CurrentView);
|
|
||||||
thisKeys.erase(AllowWhileTyping);
|
|
||||||
otherKeys.erase(CurrentView);
|
|
||||||
otherKeys.erase(AllowWhileTyping);
|
|
||||||
|
|
||||||
return thisKeys == otherKeys;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isLocal() const {
|
|
||||||
return m_keys.contains(CurrentView);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string toString() const {
|
|
||||||
std::string result;
|
|
||||||
|
|
||||||
#if defined(OS_MACOS)
|
|
||||||
constexpr static auto CTRL_NAME = "CTRL";
|
|
||||||
constexpr static auto ALT_NAME = "OPT";
|
|
||||||
constexpr static auto SHIFT_NAME = "SHIFT";
|
|
||||||
constexpr static auto SUPER_NAME = "CMD";
|
|
||||||
#else
|
|
||||||
constexpr static auto CTRL_NAME = "CTRL";
|
|
||||||
constexpr static auto ALT_NAME = "ALT";
|
|
||||||
constexpr static auto SHIFT_NAME = "SHIFT";
|
|
||||||
constexpr static auto SUPER_NAME = "SUPER";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
constexpr static auto Concatination = " + ";
|
|
||||||
|
|
||||||
auto keys = m_keys;
|
|
||||||
if (keys.erase(CTRL) > 0) {
|
|
||||||
result += CTRL_NAME;
|
|
||||||
result += Concatination;
|
|
||||||
}
|
|
||||||
if (keys.erase(ALT) > 0) {
|
|
||||||
result += ALT_NAME;
|
|
||||||
result += Concatination;
|
|
||||||
}
|
|
||||||
if (keys.erase(SHIFT) > 0) {
|
|
||||||
result += SHIFT_NAME;
|
|
||||||
result += Concatination;
|
|
||||||
}
|
|
||||||
if (keys.erase(SUPER) > 0) {
|
|
||||||
result += SUPER_NAME;
|
|
||||||
result += Concatination;
|
|
||||||
}
|
|
||||||
keys.erase(CurrentView);
|
|
||||||
|
|
||||||
for (const auto &key : keys) {
|
|
||||||
switch (Keys(key.getKeyCode())) {
|
|
||||||
case Keys::Space: result += "SPACE"; break;
|
|
||||||
case Keys::Apostrophe: result += "'"; break;
|
|
||||||
case Keys::Comma: result += ","; break;
|
|
||||||
case Keys::Minus: result += "-"; break;
|
|
||||||
case Keys::Period: result += "."; break;
|
|
||||||
case Keys::Slash: result += "/"; break;
|
|
||||||
case Keys::Num0: result += "0"; break;
|
|
||||||
case Keys::Num1: result += "1"; break;
|
|
||||||
case Keys::Num2: result += "2"; break;
|
|
||||||
case Keys::Num3: result += "3"; break;
|
|
||||||
case Keys::Num4: result += "4"; break;
|
|
||||||
case Keys::Num5: result += "5"; break;
|
|
||||||
case Keys::Num6: result += "6"; break;
|
|
||||||
case Keys::Num7: result += "7"; break;
|
|
||||||
case Keys::Num8: result += "8"; break;
|
|
||||||
case Keys::Num9: result += "9"; break;
|
|
||||||
case Keys::Semicolon: result += ";"; break;
|
|
||||||
case Keys::Equals: result += "="; break;
|
|
||||||
case Keys::A: result += "A"; break;
|
|
||||||
case Keys::B: result += "B"; break;
|
|
||||||
case Keys::C: result += "C"; break;
|
|
||||||
case Keys::D: result += "D"; break;
|
|
||||||
case Keys::E: result += "E"; break;
|
|
||||||
case Keys::F: result += "F"; break;
|
|
||||||
case Keys::G: result += "G"; break;
|
|
||||||
case Keys::H: result += "H"; break;
|
|
||||||
case Keys::I: result += "I"; break;
|
|
||||||
case Keys::J: result += "J"; break;
|
|
||||||
case Keys::K: result += "K"; break;
|
|
||||||
case Keys::L: result += "L"; break;
|
|
||||||
case Keys::M: result += "M"; break;
|
|
||||||
case Keys::N: result += "N"; break;
|
|
||||||
case Keys::O: result += "O"; break;
|
|
||||||
case Keys::P: result += "P"; break;
|
|
||||||
case Keys::Q: result += "Q"; break;
|
|
||||||
case Keys::R: result += "R"; break;
|
|
||||||
case Keys::S: result += "S"; break;
|
|
||||||
case Keys::T: result += "T"; break;
|
|
||||||
case Keys::U: result += "U"; break;
|
|
||||||
case Keys::V: result += "V"; break;
|
|
||||||
case Keys::W: result += "W"; break;
|
|
||||||
case Keys::X: result += "X"; break;
|
|
||||||
case Keys::Y: result += "Y"; break;
|
|
||||||
case Keys::Z: result += "Z"; break;
|
|
||||||
case Keys::LeftBracket: result += "["; break;
|
|
||||||
case Keys::Backslash: result += "\\"; break;
|
|
||||||
case Keys::RightBracket: result += "]"; break;
|
|
||||||
case Keys::GraveAccent: result += "`"; break;
|
|
||||||
case Keys::World1: result += "WORLD1"; break;
|
|
||||||
case Keys::World2: result += "WORLD2"; break;
|
|
||||||
case Keys::Escape: result += "ESC"; break;
|
|
||||||
case Keys::Enter: result += "ENTER"; break;
|
|
||||||
case Keys::Tab: result += "TAB"; break;
|
|
||||||
case Keys::Backspace: result += "BACKSPACE"; break;
|
|
||||||
case Keys::Insert: result += "INSERT"; break;
|
|
||||||
case Keys::Delete: result += "DELETE"; break;
|
|
||||||
case Keys::Right: result += "RIGHT"; break;
|
|
||||||
case Keys::Left: result += "LEFT"; break;
|
|
||||||
case Keys::Down: result += "DOWN"; break;
|
|
||||||
case Keys::Up: result += "UP"; break;
|
|
||||||
case Keys::PageUp: result += "PAGEUP"; break;
|
|
||||||
case Keys::PageDown: result += "PAGEDOWN"; break;
|
|
||||||
case Keys::Home: result += "HOME"; break;
|
|
||||||
case Keys::End: result += "END"; break;
|
|
||||||
case Keys::CapsLock: result += "CAPSLOCK"; break;
|
|
||||||
case Keys::ScrollLock: result += "SCROLLLOCK"; break;
|
|
||||||
case Keys::NumLock: result += "NUMLOCK"; break;
|
|
||||||
case Keys::PrintScreen: result += "PRINTSCREEN"; break;
|
|
||||||
case Keys::Pause: result += "PAUSE"; break;
|
|
||||||
case Keys::F1: result += "F1"; break;
|
|
||||||
case Keys::F2: result += "F2"; break;
|
|
||||||
case Keys::F3: result += "F3"; break;
|
|
||||||
case Keys::F4: result += "F4"; break;
|
|
||||||
case Keys::F5: result += "F5"; break;
|
|
||||||
case Keys::F6: result += "F6"; break;
|
|
||||||
case Keys::F7: result += "F7"; break;
|
|
||||||
case Keys::F8: result += "F8"; break;
|
|
||||||
case Keys::F9: result += "F9"; break;
|
|
||||||
case Keys::F10: result += "F10"; break;
|
|
||||||
case Keys::F11: result += "F11"; break;
|
|
||||||
case Keys::F12: result += "F12"; break;
|
|
||||||
case Keys::F13: result += "F13"; break;
|
|
||||||
case Keys::F14: result += "F14"; break;
|
|
||||||
case Keys::F15: result += "F15"; break;
|
|
||||||
case Keys::F16: result += "F16"; break;
|
|
||||||
case Keys::F17: result += "F17"; break;
|
|
||||||
case Keys::F18: result += "F18"; break;
|
|
||||||
case Keys::F19: result += "F19"; break;
|
|
||||||
case Keys::F20: result += "F20"; break;
|
|
||||||
case Keys::F21: result += "F21"; break;
|
|
||||||
case Keys::F22: result += "F22"; break;
|
|
||||||
case Keys::F23: result += "F23"; break;
|
|
||||||
case Keys::F24: result += "F24"; break;
|
|
||||||
case Keys::F25: result += "F25"; break;
|
|
||||||
case Keys::KeyPad0: result += "KP0"; break;
|
|
||||||
case Keys::KeyPad1: result += "KP1"; break;
|
|
||||||
case Keys::KeyPad2: result += "KP2"; break;
|
|
||||||
case Keys::KeyPad3: result += "KP3"; break;
|
|
||||||
case Keys::KeyPad4: result += "KP4"; break;
|
|
||||||
case Keys::KeyPad5: result += "KP5"; break;
|
|
||||||
case Keys::KeyPad6: result += "KP6"; break;
|
|
||||||
case Keys::KeyPad7: result += "KP7"; break;
|
|
||||||
case Keys::KeyPad8: result += "KP8"; break;
|
|
||||||
case Keys::KeyPad9: result += "KP9"; break;
|
|
||||||
case Keys::KeyPadDecimal: result += "KPDECIMAL"; break;
|
|
||||||
case Keys::KeyPadDivide: result += "KPDIVIDE"; break;
|
|
||||||
case Keys::KeyPadMultiply: result += "KPMULTIPLY"; break;
|
|
||||||
case Keys::KeyPadSubtract: result += "KPSUBTRACT"; break;
|
|
||||||
case Keys::KeyPadAdd: result += "KPADD"; break;
|
|
||||||
case Keys::KeyPadEnter: result += "KPENTER"; break;
|
|
||||||
case Keys::KeyPadEqual: result += "KPEQUAL"; break;
|
|
||||||
case Keys::Menu: result += "MENU"; break;
|
|
||||||
default:
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
result += " + ";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result.ends_with(" + "))
|
|
||||||
result = result.substr(0, result.size() - 3);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::set<Key>& getKeys() const { return m_keys; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend Shortcut operator+(const Key &lhs, const Key &rhs);
|
friend Shortcut operator+(const Key &lhs, const Key &rhs);
|
||||||
@@ -377,12 +185,7 @@ namespace hex {
|
|||||||
std::set<Key> m_keys;
|
std::set<Key> m_keys;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline Shortcut operator+(const Key &lhs, const Key &rhs) {
|
Shortcut operator+(const Key &lhs, const Key &rhs);
|
||||||
Shortcut result;
|
|
||||||
result.m_keys = { lhs, rhs };
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The ShortcutManager handles global and view-specific shortcuts.
|
* @brief The ShortcutManager handles global and view-specific shortcuts.
|
||||||
@@ -393,7 +196,7 @@ namespace hex {
|
|||||||
using Callback = std::function<void()>;
|
using Callback = std::function<void()>;
|
||||||
struct ShortcutEntry {
|
struct ShortcutEntry {
|
||||||
Shortcut shortcut;
|
Shortcut shortcut;
|
||||||
UnlocalizedString unlocalizedName;
|
std::vector<UnlocalizedString> unlocalizedName;
|
||||||
Callback callback;
|
Callback callback;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -403,6 +206,7 @@ namespace hex {
|
|||||||
* @param unlocalizedName The unlocalized name of the shortcut
|
* @param unlocalizedName The unlocalized name of the shortcut
|
||||||
* @param callback The callback to call when the shortcut is triggered.
|
* @param callback The callback to call when the shortcut is triggered.
|
||||||
*/
|
*/
|
||||||
|
static void addGlobalShortcut(const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const Callback &callback);
|
||||||
static void addGlobalShortcut(const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const Callback &callback);
|
static void addGlobalShortcut(const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const Callback &callback);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -412,6 +216,7 @@ namespace hex {
|
|||||||
* @param unlocalizedName The unlocalized name of the shortcut
|
* @param unlocalizedName The unlocalized name of the shortcut
|
||||||
* @param callback The callback to call when the shortcut is triggered.
|
* @param callback The callback to call when the shortcut is triggered.
|
||||||
*/
|
*/
|
||||||
|
static void addShortcut(View *view, const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const Callback &callback);
|
||||||
static void addShortcut(View *view, const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const Callback &callback);
|
static void addShortcut(View *view, const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const Callback &callback);
|
||||||
|
|
||||||
|
|
||||||
@@ -445,12 +250,14 @@ namespace hex {
|
|||||||
static void resumeShortcuts();
|
static void resumeShortcuts();
|
||||||
static void pauseShortcuts();
|
static void pauseShortcuts();
|
||||||
|
|
||||||
|
static void enableMacOSMode();
|
||||||
|
|
||||||
[[nodiscard]] static std::optional<Shortcut> getPreviousShortcut();
|
[[nodiscard]] static std::optional<Shortcut> getPreviousShortcut();
|
||||||
|
|
||||||
[[nodiscard]] static std::vector<ShortcutEntry> getGlobalShortcuts();
|
[[nodiscard]] static std::vector<ShortcutEntry> getGlobalShortcuts();
|
||||||
[[nodiscard]] static std::vector<ShortcutEntry> getViewShortcuts(const View *view);
|
[[nodiscard]] static std::vector<ShortcutEntry> getViewShortcuts(const View *view);
|
||||||
|
|
||||||
[[nodiscard]] static bool updateShortcut(const Shortcut &oldShortcut, const Shortcut &newShortcut, View *view = nullptr);
|
[[nodiscard]] static bool updateShortcut(const Shortcut &oldShortcut, Shortcut newShortcut, View *view = nullptr);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -22,7 +22,7 @@ namespace hex {
|
|||||||
class Task {
|
class Task {
|
||||||
public:
|
public:
|
||||||
Task() = default;
|
Task() = default;
|
||||||
Task(UnlocalizedString unlocalizedName, u64 maxValue, bool background, std::function<void(Task &)> function);
|
Task(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, std::function<void(Task &)> function);
|
||||||
|
|
||||||
Task(const Task&) = delete;
|
Task(const Task&) = delete;
|
||||||
Task(Task &&other) noexcept;
|
Task(Task &&other) noexcept;
|
||||||
@@ -130,20 +130,37 @@ namespace hex {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates a new asynchronous task that gets displayed in the Task Manager in the footer
|
* @brief Creates a new asynchronous task that gets displayed in the Task Manager in the footer
|
||||||
* @param name Name of the task
|
* @param unlocalizedName Name of the task
|
||||||
* @param maxValue Maximum value of the task
|
* @param maxValue Maximum value of the task
|
||||||
* @param function Function to be executed
|
* @param function Function to be executed
|
||||||
* @return A TaskHolder holding a weak reference to the task
|
* @return A TaskHolder holding a weak reference to the task
|
||||||
*/
|
*/
|
||||||
static TaskHolder createTask(std::string name, u64 maxValue, std::function<void(Task &)> function);
|
static TaskHolder createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, std::function<void(Task &)> function);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Creates a new asynchronous task that gets displayed in the Task Manager in the footer
|
||||||
|
* @param unlocalizedName Name of the task
|
||||||
|
* @param maxValue Maximum value of the task
|
||||||
|
* @param function Function to be executed
|
||||||
|
* @return A TaskHolder holding a weak reference to the task
|
||||||
|
*/
|
||||||
|
static TaskHolder createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, std::function<void()> function);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates a new asynchronous task that does not get displayed in the Task Manager
|
* @brief Creates a new asynchronous task that does not get displayed in the Task Manager
|
||||||
* @param name Name of the task
|
* @param unlocalizedName Name of the task
|
||||||
* @param function Function to be executed
|
* @param function Function to be executed
|
||||||
* @return A TaskHolder holding a weak reference to the task
|
* @return A TaskHolder holding a weak reference to the task
|
||||||
*/
|
*/
|
||||||
static TaskHolder createBackgroundTask(std::string name, std::function<void(Task &)> function);
|
static TaskHolder createBackgroundTask(const UnlocalizedString &unlocalizedName, std::function<void(Task &)> function);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Creates a new asynchronous task that does not get displayed in the Task Manager
|
||||||
|
* @param unlocalizedName Name of the task
|
||||||
|
* @param function Function to be executed
|
||||||
|
* @return A TaskHolder holding a weak reference to the task
|
||||||
|
*/
|
||||||
|
static TaskHolder createBackgroundTask(const UnlocalizedString &unlocalizedName, std::function<void()> function);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates a new synchronous task that will execute the given function at the start of the next frame
|
* @brief Creates a new synchronous task that will execute the given function at the start of the next frame
|
||||||
@@ -190,7 +207,7 @@ namespace hex {
|
|||||||
static void runDeferredCalls();
|
static void runDeferredCalls();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static TaskHolder createTask(std::string name, u64 maxValue, bool background, std::function<void(Task &)> function);
|
static TaskHolder createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, std::function<void(Task &)> function);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -56,6 +56,7 @@ namespace hex {
|
|||||||
*/
|
*/
|
||||||
static void addStyleHandler(const std::string &name, const StyleMap &styleMap);
|
static void addStyleHandler(const std::string &name, const StyleMap &styleMap);
|
||||||
|
|
||||||
|
static void reapplyCurrentTheme();
|
||||||
|
|
||||||
static std::vector<std::string> getThemeNames();
|
static std::vector<std::string> getThemeNames();
|
||||||
static const std::string &getImageTheme();
|
static const std::string &getImageTheme();
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
#include <hex.hpp>
|
#include <hex.hpp>
|
||||||
#include <hex/api/localization_manager.hpp>
|
#include <hex/api/localization_manager.hpp>
|
||||||
|
|
||||||
#include <hex/helpers/intrinsics.hpp>
|
|
||||||
#include <hex/data_processor/attribute.hpp>
|
#include <hex/data_processor/attribute.hpp>
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
@@ -12,6 +11,7 @@
|
|||||||
|
|
||||||
#include <nlohmann/json_fwd.hpp>
|
#include <nlohmann/json_fwd.hpp>
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
#include <hex/providers/provider_data.hpp>
|
||||||
|
|
||||||
namespace hex::prv {
|
namespace hex::prv {
|
||||||
class Provider;
|
class Provider;
|
||||||
@@ -42,11 +42,12 @@ namespace hex::dp {
|
|||||||
m_overlay = overlay;
|
m_overlay = overlay;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void drawNode() { }
|
void draw();
|
||||||
virtual void process() = 0;
|
virtual void process() = 0;
|
||||||
|
virtual void reset() { }
|
||||||
|
|
||||||
virtual void store(nlohmann::json &j) const { hex::unused(j); }
|
virtual void store(nlohmann::json &j) const { std::ignore = j; }
|
||||||
virtual void load(const nlohmann::json &j) { hex::unused(j); }
|
virtual void load(const nlohmann::json &j) { std::ignore = j; }
|
||||||
|
|
||||||
struct NodeError {
|
struct NodeError {
|
||||||
Node *node;
|
Node *node;
|
||||||
@@ -80,6 +81,11 @@ namespace hex::dp {
|
|||||||
void setIntegerOnOutput(u32 index, i128 integer);
|
void setIntegerOnOutput(u32 index, i128 integer);
|
||||||
void setFloatOnOutput(u32 index, double floatingPoint);
|
void setFloatOnOutput(u32 index, double floatingPoint);
|
||||||
|
|
||||||
|
static void interrupt();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void drawNode() { }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int m_id;
|
int m_id;
|
||||||
UnlocalizedString m_unlocalizedTitle, m_unlocalizedName;
|
UnlocalizedString m_unlocalizedTitle, m_unlocalizedName;
|
||||||
@@ -90,45 +96,16 @@ namespace hex::dp {
|
|||||||
|
|
||||||
static int s_idCounter;
|
static int s_idCounter;
|
||||||
|
|
||||||
Attribute& getAttribute(u32 index) {
|
Attribute& getAttribute(u32 index);
|
||||||
if (index >= this->getAttributes().size())
|
Attribute *getConnectedInputAttribute(u32 index);
|
||||||
throw std::runtime_error("Attribute index out of bounds!");
|
void markInputProcessed(u32 index);
|
||||||
|
void unmarkInputProcessed(u32 index);
|
||||||
return this->getAttributes()[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
Attribute *getConnectedInputAttribute(u32 index) {
|
|
||||||
const auto &connectedAttribute = this->getAttribute(index).getConnectedAttributes();
|
|
||||||
|
|
||||||
if (connectedAttribute.empty())
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
return connectedAttribute.begin()->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
void markInputProcessed(u32 index) {
|
|
||||||
const auto &[iter, inserted] = m_processedInputs.insert(index);
|
|
||||||
if (!inserted)
|
|
||||||
throwNodeError("Recursion detected!");
|
|
||||||
}
|
|
||||||
|
|
||||||
void unmarkInputProcessed(u32 index) {
|
|
||||||
m_processedInputs.erase(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
[[noreturn]] void throwNodeError(const std::string &message) {
|
[[noreturn]] void throwNodeError(const std::string &message);
|
||||||
throw NodeError { this, message };
|
|
||||||
}
|
|
||||||
|
|
||||||
void setOverlayData(u64 address, const std::vector<u8> &data);
|
void setOverlayData(u64 address, const std::vector<u8> &data);
|
||||||
|
void setAttributes(std::vector<Attribute> attributes);
|
||||||
void setAttributes(std::vector<Attribute> attributes) {
|
|
||||||
m_attributes = std::move(attributes);
|
|
||||||
|
|
||||||
for (auto &attr : m_attributes)
|
|
||||||
attr.setParentNode(this);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2,10 +2,15 @@
|
|||||||
|
|
||||||
#include <hex.hpp>
|
#include <hex.hpp>
|
||||||
|
|
||||||
|
#include <wolv/utils/expected.hpp>
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#define CRYPTO_ERROR_INVALID_KEY_LENGTH (-1)
|
||||||
|
#define CRYPTO_ERROR_INVALID_MODE (-2)
|
||||||
|
|
||||||
namespace hex::prv {
|
namespace hex::prv {
|
||||||
class Provider;
|
class Provider;
|
||||||
}
|
}
|
||||||
@@ -60,5 +65,5 @@ namespace hex::crypt {
|
|||||||
Key256Bits = 2
|
Key256Bits = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<u8> aesDecrypt(AESMode mode, KeyLength keyLength, const std::vector<u8> &key, std::array<u8, 8> nonce, std::array<u8, 8> iv, const std::vector<u8> &input);
|
wolv::util::Expected<std::vector<u8>, int> aesDecrypt(AESMode mode, KeyLength keyLength, const std::vector<u8> &key, std::array<u8, 8> nonce, std::array<u8, 8> iv, const std::vector<u8> &input);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <fmt/format.h>
|
#include <fmt/core.h>
|
||||||
|
#include <fmt/ranges.h>
|
||||||
|
|
||||||
namespace hex {
|
namespace hex {
|
||||||
|
|
||||||
|
|||||||
@@ -25,13 +25,16 @@
|
|||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
std::future<HttpRequest::Result<T>> HttpRequest::uploadFile(const std::fs::path &path, const std::string &mimeName) {
|
std::future<HttpRequest::Result<T>> HttpRequest::uploadFile(const std::fs::path &path, const std::string &mimeName) {
|
||||||
hex::unused(path, mimeName);
|
std::ignore = path;
|
||||||
|
std::ignore = mimeName;
|
||||||
throw std::logic_error("Not implemented");
|
throw std::logic_error("Not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
std::future<HttpRequest::Result<T>> HttpRequest::uploadFile(std::vector<u8> data, const std::string &mimeName, const std::fs::path &fileName) {
|
std::future<HttpRequest::Result<T>> HttpRequest::uploadFile(std::vector<u8> data, const std::string &mimeName, const std::fs::path &fileName) {
|
||||||
hex::unused(data, mimeName, fileName);
|
std::ignore = data;
|
||||||
|
std::ignore = mimeName;
|
||||||
|
std::ignore = fileName;
|
||||||
throw std::logic_error("Not implemented");
|
throw std::logic_error("Not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
namespace hex {
|
|
||||||
|
|
||||||
void unused(auto && ... x) {
|
|
||||||
((void)x, ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -21,6 +21,11 @@ namespace hex {
|
|||||||
MissingEOF
|
MissingEOF
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class PatchKind {
|
||||||
|
IPS,
|
||||||
|
IPS32
|
||||||
|
};
|
||||||
|
|
||||||
class Patches {
|
class Patches {
|
||||||
public:
|
public:
|
||||||
Patches() = default;
|
Patches() = default;
|
||||||
|
|||||||
36
lib/libimhex/include/hex/helpers/semantic_version.hpp
Normal file
36
lib/libimhex/include/hex/helpers/semantic_version.hpp
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <hex.hpp>
|
||||||
|
|
||||||
|
#include <compare>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace hex {
|
||||||
|
|
||||||
|
class SemanticVersion {
|
||||||
|
public:
|
||||||
|
SemanticVersion() = default;
|
||||||
|
SemanticVersion(std::string version);
|
||||||
|
SemanticVersion(std::string_view version);
|
||||||
|
SemanticVersion(const char *version);
|
||||||
|
|
||||||
|
std::strong_ordering operator<=>(const SemanticVersion &) const;
|
||||||
|
bool operator==(const SemanticVersion &other) const;
|
||||||
|
|
||||||
|
u32 major() const;
|
||||||
|
u32 minor() const;
|
||||||
|
u32 patch() const;
|
||||||
|
bool nightly() const;
|
||||||
|
const std::string& buildType() const;
|
||||||
|
|
||||||
|
bool isValid() const;
|
||||||
|
|
||||||
|
std::string get(bool withBuildType = true) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::string> m_parts;
|
||||||
|
std::string m_buildType;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -29,7 +29,7 @@ namespace hex {
|
|||||||
void close();
|
void close();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief get the error string explaining the error that occured when opening the file.
|
* @brief get the error string explaining the error that occurred when opening the file.
|
||||||
* This error is a combination of the tar error and the native file open error
|
* This error is a combination of the tar error and the native file open error
|
||||||
*/
|
*/
|
||||||
std::string getOpenErrorString() const;
|
std::string getOpenErrorString() const;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#include <concepts>
|
#include <concepts>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
using u8 = std::uint8_t;
|
using u8 = std::uint8_t;
|
||||||
using u16 = std::uint16_t;
|
using u16 = std::uint16_t;
|
||||||
@@ -61,6 +62,10 @@ namespace hex {
|
|||||||
constexpr static Region Invalid() {
|
constexpr static Region Invalid() {
|
||||||
return { 0, 0 };
|
return { 0, 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr bool operator<(const Region &other) const {
|
||||||
|
return this->address < other.address;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,29 @@ namespace hex {
|
|||||||
class Provider;
|
class Provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
[[nodiscard]] std::vector<std::vector<T>> sampleChannels(const std::vector<T> &data, size_t count, size_t channels) {
|
||||||
|
if (channels == 0) return {};
|
||||||
|
size_t signalLength = std::max(1.0, double(data.size()) / channels);
|
||||||
|
|
||||||
|
size_t stride = std::max(1.0, double(signalLength) / count);
|
||||||
|
|
||||||
|
std::vector<std::vector<T>> result;
|
||||||
|
result.resize(channels);
|
||||||
|
for (size_t i = 0; i < channels; i++) {
|
||||||
|
result[i].reserve(count);
|
||||||
|
}
|
||||||
|
result.reserve(count);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < data.size(); i += stride) {
|
||||||
|
for (size_t j = 0; j < channels; j++) {
|
||||||
|
result[j].push_back(data[i + j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
[[nodiscard]] std::vector<T> sampleData(const std::vector<T> &data, size_t count) {
|
[[nodiscard]] std::vector<T> sampleData(const std::vector<T> &data, size_t count) {
|
||||||
size_t stride = std::max(1.0, double(data.size()) / count);
|
size_t stride = std::max(1.0, double(data.size()) / count);
|
||||||
@@ -262,13 +285,13 @@ namespace hex {
|
|||||||
|
|
||||||
[[nodiscard]] float float16ToFloat32(u16 float16);
|
[[nodiscard]] float float16ToFloat32(u16 float16);
|
||||||
|
|
||||||
[[nodiscard]] inline bool equalsIgnoreCase(const std::string &left, const std::string &right) {
|
[[nodiscard]] inline bool equalsIgnoreCase(std::string_view left, std::string_view right) {
|
||||||
return std::equal(left.begin(), left.end(), right.begin(), right.end(), [](char a, char b) {
|
return std::equal(left.begin(), left.end(), right.begin(), right.end(), [](char a, char b) {
|
||||||
return tolower(a) == tolower(b);
|
return tolower(a) == tolower(b);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline bool containsIgnoreCase(const std::string &a, const std::string &b) {
|
[[nodiscard]] inline bool containsIgnoreCase(std::string_view a, std::string_view b) {
|
||||||
auto iter = std::search(a.begin(), a.end(), b.begin(), b.end(), [](char ch1, char ch2) {
|
auto iter = std::search(a.begin(), a.end(), b.begin(), b.end(), [](char ch1, char ch2) {
|
||||||
return std::toupper(ch1) == std::toupper(ch2);
|
return std::toupper(ch1) == std::toupper(ch2);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -37,21 +37,40 @@ void* PluginSubCommandsFunctionHelper<T>::getSubCommands() {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] static auto& getFeaturesImpl() {
|
||||||
|
static std::vector<hex::Feature> features;
|
||||||
|
return features;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined (IMHEX_STATIC_LINK_PLUGINS)
|
#if defined (IMHEX_STATIC_LINK_PLUGINS)
|
||||||
#define IMHEX_PLUGIN_VISIBILITY_PREFIX static
|
#define IMHEX_PLUGIN_VISIBILITY_PREFIX static
|
||||||
#else
|
#else
|
||||||
#define IMHEX_PLUGIN_VISIBILITY_PREFIX extern "C" [[gnu::visibility("default")]]
|
#define IMHEX_PLUGIN_VISIBILITY_PREFIX extern "C" [[gnu::visibility("default")]]
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define IMHEX_FEATURE_ENABLED(feature) WOLV_TOKEN_CONCAT(WOLV_TOKEN_CONCAT(WOLV_TOKEN_CONCAT(IMHEX_PLUGIN_, IMHEX_PLUGIN_NAME), _FEATURE_), feature)
|
||||||
|
#define IMHEX_DEFINE_PLUGIN_FEATURES() IMHEX_DEFINE_PLUGIN_FEATURES_IMPL()
|
||||||
|
#define IMHEX_DEFINE_PLUGIN_FEATURES_IMPL() \
|
||||||
|
template<> \
|
||||||
|
struct PluginFeatureFunctionHelper<PluginFunctionHelperInstantiation> { \
|
||||||
|
static void* getFeatures(); \
|
||||||
|
}; \
|
||||||
|
void* PluginFeatureFunctionHelper<PluginFunctionHelperInstantiation>::getFeatures() { \
|
||||||
|
return &getFeaturesImpl(); \
|
||||||
|
} \
|
||||||
|
static auto initFeatures = [] { getFeaturesImpl() = std::vector<hex::Feature>({ IMHEX_PLUGIN_FEATURES_CONTENT }); return 0; }()
|
||||||
|
|
||||||
|
#define IMHEX_PLUGIN_FEATURES ::getFeaturesImpl()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This macro is used to define all the required entry points for a plugin.
|
* This macro is used to define all the required entry points for a plugin.
|
||||||
* Name, Author and Description will be displayed in the in the plugin list on the Welcome screen.
|
* Name, Author and Description will be displayed in the plugin list on the Welcome screen.
|
||||||
*/
|
*/
|
||||||
#define IMHEX_PLUGIN_SETUP(name, author, description) IMHEX_PLUGIN_SETUP_IMPL(name, author, description)
|
#define IMHEX_PLUGIN_SETUP(name, author, description) IMHEX_PLUGIN_SETUP_IMPL(name, author, description)
|
||||||
#define IMHEX_LIBRARY_SETUP(name) IMHEX_LIBRARY_SETUP_IMPL(name)
|
#define IMHEX_LIBRARY_SETUP(name) IMHEX_LIBRARY_SETUP_IMPL(name)
|
||||||
|
|
||||||
#define IMHEX_LIBRARY_SETUP_IMPL(name) \
|
#define IMHEX_LIBRARY_SETUP_IMPL(name) \
|
||||||
namespace { static struct EXIT_HANDLER { ~EXIT_HANDLER() { hex::log::debug("Unloaded library '{}'", name); } } HANDLER; } \
|
namespace { static struct EXIT_HANDLER { ~EXIT_HANDLER() { hex::log::info("Unloaded library '{}'", name); } } HANDLER; } \
|
||||||
IMHEX_PLUGIN_VISIBILITY_PREFIX void WOLV_TOKEN_CONCAT(initializeLibrary_, IMHEX_PLUGIN_NAME)(); \
|
IMHEX_PLUGIN_VISIBILITY_PREFIX void WOLV_TOKEN_CONCAT(initializeLibrary_, IMHEX_PLUGIN_NAME)(); \
|
||||||
IMHEX_PLUGIN_VISIBILITY_PREFIX const char *WOLV_TOKEN_CONCAT(getLibraryName_, IMHEX_PLUGIN_NAME)() { return name; } \
|
IMHEX_PLUGIN_VISIBILITY_PREFIX const char *WOLV_TOKEN_CONCAT(getLibraryName_, IMHEX_PLUGIN_NAME)() { return name; } \
|
||||||
IMHEX_PLUGIN_VISIBILITY_PREFIX void WOLV_TOKEN_CONCAT(setImGuiContext_, IMHEX_PLUGIN_NAME)(ImGuiContext *ctx) { \
|
IMHEX_PLUGIN_VISIBILITY_PREFIX void WOLV_TOKEN_CONCAT(setImGuiContext_, IMHEX_PLUGIN_NAME)(ImGuiContext *ctx) { \
|
||||||
@@ -85,6 +104,7 @@ void* PluginSubCommandsFunctionHelper<T>::getSubCommands() {
|
|||||||
ImGui::SetCurrentContext(ctx); \
|
ImGui::SetCurrentContext(ctx); \
|
||||||
GImGui = ctx; \
|
GImGui = ctx; \
|
||||||
} \
|
} \
|
||||||
|
IMHEX_DEFINE_PLUGIN_FEATURES(); \
|
||||||
IMHEX_PLUGIN_VISIBILITY_PREFIX void* getFeatures() { \
|
IMHEX_PLUGIN_VISIBILITY_PREFIX void* getFeatures() { \
|
||||||
return PluginFeatureFunctionHelper<PluginFunctionHelperInstantiation>::getFeatures(); \
|
return PluginFeatureFunctionHelper<PluginFunctionHelperInstantiation>::getFeatures(); \
|
||||||
} \
|
} \
|
||||||
@@ -129,18 +149,3 @@ void* PluginSubCommandsFunctionHelper<T>::getSubCommands() {
|
|||||||
return &g_subCommands; \
|
return &g_subCommands; \
|
||||||
} \
|
} \
|
||||||
std::vector<hex::SubCommand> g_subCommands
|
std::vector<hex::SubCommand> g_subCommands
|
||||||
|
|
||||||
#define IMHEX_FEATURE_ENABLED(feature) WOLV_TOKEN_CONCAT(WOLV_TOKEN_CONCAT(WOLV_TOKEN_CONCAT(IMHEX_PLUGIN_, IMHEX_PLUGIN_NAME), _FEATURE_), feature)
|
|
||||||
#define IMHEX_DEFINE_PLUGIN_FEATURES() IMHEX_DEFINE_PLUGIN_FEATURES_IMPL()
|
|
||||||
#define IMHEX_DEFINE_PLUGIN_FEATURES_IMPL() \
|
|
||||||
extern std::vector<hex::Feature> g_features; \
|
|
||||||
template<> \
|
|
||||||
struct PluginFeatureFunctionHelper<PluginFunctionHelperInstantiation> { \
|
|
||||||
static void* getFeatures(); \
|
|
||||||
}; \
|
|
||||||
void* PluginFeatureFunctionHelper<PluginFunctionHelperInstantiation>::getFeatures() { \
|
|
||||||
return &g_features; \
|
|
||||||
} \
|
|
||||||
std::vector<hex::Feature> g_features
|
|
||||||
|
|
||||||
#define IMHEX_PLUGIN_FEATURES g_features
|
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ namespace hex::prv {
|
|||||||
void insert(u64 offset, u64 size);
|
void insert(u64 offset, u64 size);
|
||||||
void remove(u64 offset, u64 size);
|
void remove(u64 offset, u64 size);
|
||||||
|
|
||||||
virtual void resizeRaw(u64 newSize) { hex::unused(newSize); }
|
virtual void resizeRaw(u64 newSize) { std::ignore = newSize; }
|
||||||
virtual void insertRaw(u64 offset, u64 size);
|
virtual void insertRaw(u64 offset, u64 size);
|
||||||
virtual void removeRaw(u64 offset, u64 size);
|
virtual void removeRaw(u64 offset, u64 size);
|
||||||
|
|
||||||
|
|||||||
@@ -97,29 +97,25 @@ namespace ImGuiExt {
|
|||||||
Texture& operator=(Texture&& other) noexcept;
|
Texture& operator=(Texture&& other) noexcept;
|
||||||
|
|
||||||
[[nodiscard]] constexpr bool isValid() const noexcept {
|
[[nodiscard]] constexpr bool isValid() const noexcept {
|
||||||
return m_textureId != nullptr;
|
return m_textureId != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] operator ImTextureID() const noexcept {
|
[[nodiscard]] operator ImTextureID() const noexcept {
|
||||||
return m_textureId;
|
return m_textureId;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] operator intptr_t() const noexcept {
|
[[nodiscard]] ImVec2 getSize() const noexcept {
|
||||||
return reinterpret_cast<intptr_t>(m_textureId);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto getSize() const noexcept {
|
|
||||||
return ImVec2(m_width, m_height);
|
return ImVec2(m_width, m_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] constexpr auto getAspectRatio() const noexcept {
|
[[nodiscard]] constexpr float getAspectRatio() const noexcept {
|
||||||
if (m_height == 0) return 1.0F;
|
if (m_height == 0) return 1.0F;
|
||||||
|
|
||||||
return float(m_width) / float(m_height);
|
return float(m_width) / float(m_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ImTextureID m_textureId = nullptr;
|
ImTextureID m_textureId = 0;
|
||||||
int m_width = 0, m_height = 0;
|
int m_width = 0, m_height = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -137,6 +133,8 @@ namespace ImGuiExt {
|
|||||||
|
|
||||||
void UnderlinedText(const char *label, ImColor color = ImGui::GetStyleColorVec4(ImGuiCol_Text), const ImVec2 &size_arg = ImVec2(0, 0));
|
void UnderlinedText(const char *label, ImColor color = ImGui::GetStyleColorVec4(ImGuiCol_Text), const ImVec2 &size_arg = ImVec2(0, 0));
|
||||||
|
|
||||||
|
void UnderwavedText(const char *label, ImColor textColor = ImGui::GetStyleColorVec4(ImGuiCol_Text), ImColor lineColor = ImGui::GetStyleColorVec4(ImGuiCol_Text), const ImVec2 &size_arg = ImVec2(0, 0));
|
||||||
|
|
||||||
void TextSpinner(const char *label);
|
void TextSpinner(const char *label);
|
||||||
|
|
||||||
void Header(const char *label, bool firstEntry = false);
|
void Header(const char *label, bool firstEntry = false);
|
||||||
@@ -284,6 +282,7 @@ namespace ImGuiExt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool InputTextIcon(const char* label, const char *icon, std::string &buffer, ImGuiInputTextFlags flags = ImGuiInputTextFlags_None);
|
bool InputTextIcon(const char* label, const char *icon, std::string &buffer, ImGuiInputTextFlags flags = ImGuiInputTextFlags_None);
|
||||||
|
bool InputTextIconHint(const char* label, const char *icon, const char *hint, std::string &buffer, ImGuiInputTextFlags flags = ImGuiInputTextFlags_None);
|
||||||
|
|
||||||
bool InputScalarCallback(const char* label, ImGuiDataType data_type, void* p_data, const char* format, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data);
|
bool InputScalarCallback(const char* label, ImGuiDataType data_type, void* p_data, const char* format, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data);
|
||||||
|
|
||||||
@@ -297,7 +296,7 @@ namespace ImGuiExt {
|
|||||||
bool DimmedIconToggle(const char *icon, bool *v);
|
bool DimmedIconToggle(const char *icon, bool *v);
|
||||||
bool DimmedIconToggle(const char *iconOn, const char *iconOff, bool *v);
|
bool DimmedIconToggle(const char *iconOn, const char *iconOff, bool *v);
|
||||||
|
|
||||||
void TextOverlay(const char *text, ImVec2 pos);
|
void TextOverlay(const char *text, ImVec2 pos, float maxWidth = -1);
|
||||||
|
|
||||||
bool BeginBox();
|
bool BeginBox();
|
||||||
void EndBox();
|
void EndBox();
|
||||||
|
|||||||
@@ -6,6 +6,10 @@
|
|||||||
|
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
#if defined(OS_WEB)
|
||||||
|
#include <emscripten.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace hex {
|
namespace hex {
|
||||||
|
|
||||||
static AutoReset<std::unordered_map<std::string, std::unordered_map<std::string, std::unique_ptr<Achievement>>>> s_achievements;
|
static AutoReset<std::unordered_map<std::string, std::unordered_map<std::string, std::unique_ptr<Achievement>>>> s_achievements;
|
||||||
@@ -196,8 +200,11 @@ namespace hex {
|
|||||||
|
|
||||||
|
|
||||||
constexpr static auto AchievementsFile = "achievements.json";
|
constexpr static auto AchievementsFile = "achievements.json";
|
||||||
|
bool AchievementManager::s_initialized = false;
|
||||||
|
|
||||||
void AchievementManager::loadProgress() {
|
void AchievementManager::loadProgress() {
|
||||||
|
if (s_initialized)
|
||||||
|
return;
|
||||||
for (const auto &directory : paths::Config.read()) {
|
for (const auto &directory : paths::Config.read()) {
|
||||||
auto path = directory / AchievementsFile;
|
auto path = directory / AchievementsFile;
|
||||||
|
|
||||||
@@ -212,7 +219,16 @@ namespace hex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
auto json = nlohmann::json::parse(file.readString());
|
#if defined(OS_WEB)
|
||||||
|
auto data = (char *) MAIN_THREAD_EM_ASM_INT({
|
||||||
|
let data = localStorage.getItem("achievements");
|
||||||
|
return data ? stringToNewUTF8(data) : null;
|
||||||
|
});
|
||||||
|
#else
|
||||||
|
auto data = file.readString();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
auto json = nlohmann::json::parse(data);
|
||||||
|
|
||||||
for (const auto &[categoryName, achievements] : getAchievements()) {
|
for (const auto &[categoryName, achievements] : getAchievements()) {
|
||||||
for (const auto &[achievementName, achievement] : achievements) {
|
for (const auto &[achievementName, achievement] : achievements) {
|
||||||
@@ -227,6 +243,8 @@ namespace hex {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s_initialized = true;
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
log::error("Failed to load achievements: {}", e.what());
|
log::error("Failed to load achievements: {}", e.what());
|
||||||
}
|
}
|
||||||
@@ -235,6 +253,8 @@ namespace hex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AchievementManager::storeProgress() {
|
void AchievementManager::storeProgress() {
|
||||||
|
if (!s_initialized)
|
||||||
|
loadProgress();
|
||||||
nlohmann::json json;
|
nlohmann::json json;
|
||||||
for (const auto &[categoryName, achievements] : getAchievements()) {
|
for (const auto &[categoryName, achievements] : getAchievements()) {
|
||||||
json[categoryName] = nlohmann::json::object();
|
json[categoryName] = nlohmann::json::object();
|
||||||
@@ -247,16 +267,23 @@ namespace hex {
|
|||||||
if (json.empty())
|
if (json.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (const auto &directory : paths::Config.write()) {
|
#if defined(OS_WEB)
|
||||||
auto path = directory / AchievementsFile;
|
auto data = json.dump();
|
||||||
|
MAIN_THREAD_EM_ASM({
|
||||||
|
localStorage.setItem("achievements", UTF8ToString($0));
|
||||||
|
}, data.c_str());
|
||||||
|
#else
|
||||||
|
for (const auto &directory : paths::Config.write()) {
|
||||||
|
auto path = directory / AchievementsFile;
|
||||||
|
|
||||||
wolv::io::File file(path, wolv::io::File::Mode::Create);
|
wolv::io::File file(path, wolv::io::File::Mode::Create);
|
||||||
if (!file.isValid())
|
if (!file.isValid())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
file.writeString(json.dump(4));
|
file.writeString(json.dump(4));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -191,6 +191,17 @@ namespace hex {
|
|||||||
const auto entry = insertOrGetEntry(subCategory->entries, unlocalizedName);
|
const auto entry = insertOrGetEntry(subCategory->entries, unlocalizedName);
|
||||||
|
|
||||||
entry->widget = std::move(widget);
|
entry->widget = std::move(widget);
|
||||||
|
if (entry->widget != nullptr) {
|
||||||
|
onChange(unlocalizedCategory, unlocalizedName, [widget = entry->widget.get(), unlocalizedCategory, unlocalizedName](const SettingsValue &) {
|
||||||
|
try {
|
||||||
|
auto defaultValue = widget->store();
|
||||||
|
widget->load(ContentRegistry::Settings::impl::getSetting(unlocalizedCategory, unlocalizedName, defaultValue));
|
||||||
|
widget->onChanged();
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
log::error("Failed to load setting [{} / {}]: {}", unlocalizedCategory.get(), unlocalizedName.get(), e.what());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return entry->widget.get();
|
return entry->widget.get();
|
||||||
}
|
}
|
||||||
@@ -552,6 +563,11 @@ namespace hex {
|
|||||||
return *s_functions;
|
return *s_functions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static AutoReset<std::vector<TypeDefinition>> s_types;
|
||||||
|
const std::vector<TypeDefinition>& getTypes() {
|
||||||
|
return *s_types;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string getFunctionName(const pl::api::Namespace &ns, const std::string &name) {
|
static std::string getFunctionName(const pl::api::Namespace &ns, const std::string &name) {
|
||||||
@@ -605,12 +621,16 @@ namespace hex {
|
|||||||
runtime.addFunction(ns, name, paramCount, callback);
|
runtime.addFunction(ns, name, paramCount, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const auto &[ns, name, paramCount, callback] : impl::getTypes()) {
|
||||||
|
runtime.addType(ns, name, paramCount, callback);
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto &[name, callback] : impl::getPragmas()) {
|
for (const auto &[name, callback] : impl::getPragmas()) {
|
||||||
runtime.addPragma(name, callback);
|
runtime.addPragma(name, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
runtime.addDefine("__IMHEX__");
|
runtime.addDefine("__IMHEX__");
|
||||||
runtime.addDefine("__IMHEX_VERSION__", ImHexApi::System::getImHexVersion());
|
runtime.addDefine("__IMHEX_VERSION__", ImHexApi::System::getImHexVersion().get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void addPragma(const std::string &name, const pl::api::PragmaHandler &handler) {
|
void addPragma(const std::string &name, const pl::api::PragmaHandler &handler) {
|
||||||
@@ -639,6 +659,15 @@ namespace hex {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addType(const pl::api::Namespace &ns, const std::string &name, pl::api::FunctionParameterCount parameterCount, const pl::api::TypeCallback &func) {
|
||||||
|
log::debug("Registered new pattern language type: {}", getFunctionName(ns, name));
|
||||||
|
|
||||||
|
impl::s_types->push_back({
|
||||||
|
ns, name,
|
||||||
|
parameterCount, func
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void addVisualizer(const std::string &name, const impl::VisualizerFunctionCallback &function, pl::api::FunctionParameterCount parameterCount) {
|
void addVisualizer(const std::string &name, const impl::VisualizerFunctionCallback &function, pl::api::FunctionParameterCount parameterCount) {
|
||||||
log::debug("Registered new pattern visualizer function: {}", name);
|
log::debug("Registered new pattern visualizer function: {}", name);
|
||||||
@@ -884,14 +913,21 @@ namespace hex {
|
|||||||
coloredIcon.color = ImGuiCustomCol_ToolbarGray;
|
coloredIcon.color = ImGuiCustomCol_ToolbarGray;
|
||||||
|
|
||||||
impl::s_menuItems->insert({
|
impl::s_menuItems->insert({
|
||||||
priority, impl::MenuItem { unlocalizedMainMenuNames, coloredIcon, std::make_unique<Shortcut>(shortcut), view, function, enabledCallback, selectedCallback, -1 }
|
priority, impl::MenuItem { unlocalizedMainMenuNames, coloredIcon, shortcut, view, function, enabledCallback, selectedCallback, -1 }
|
||||||
});
|
});
|
||||||
|
|
||||||
if (shortcut != Shortcut::None) {
|
if (shortcut != Shortcut::None) {
|
||||||
|
auto callbackIfEnabled = [enabledCallback, function]{ if (enabledCallback()) { function(); } };
|
||||||
|
|
||||||
|
const auto unlocalizedShortcutName =
|
||||||
|
unlocalizedMainMenuNames.size() == 1 ?
|
||||||
|
std::vector { unlocalizedMainMenuNames.back() } :
|
||||||
|
std::vector(unlocalizedMainMenuNames.begin() + 1, unlocalizedMainMenuNames.end());
|
||||||
|
|
||||||
if (shortcut.isLocal() && view != nullptr)
|
if (shortcut.isLocal() && view != nullptr)
|
||||||
ShortcutManager::addShortcut(view, shortcut, unlocalizedMainMenuNames.back(), function);
|
ShortcutManager::addShortcut(view, shortcut, unlocalizedShortcutName, callbackIfEnabled);
|
||||||
else
|
else
|
||||||
ShortcutManager::addGlobalShortcut(shortcut, unlocalizedMainMenuNames.back(), function);
|
ShortcutManager::addGlobalShortcut(shortcut, unlocalizedShortcutName, callbackIfEnabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -904,14 +940,14 @@ namespace hex {
|
|||||||
|
|
||||||
unlocalizedMainMenuNames.emplace_back(impl::SubMenuValue);
|
unlocalizedMainMenuNames.emplace_back(impl::SubMenuValue);
|
||||||
impl::s_menuItems->insert({
|
impl::s_menuItems->insert({
|
||||||
priority, impl::MenuItem { unlocalizedMainMenuNames, icon, std::make_unique<Shortcut>(), nullptr, function, enabledCallback, []{ return false; }, -1 }
|
priority, impl::MenuItem { unlocalizedMainMenuNames, icon, Shortcut::None, nullptr, function, enabledCallback, []{ return false; }, -1 }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void addMenuItemSeparator(std::vector<UnlocalizedString> unlocalizedMainMenuNames, u32 priority) {
|
void addMenuItemSeparator(std::vector<UnlocalizedString> unlocalizedMainMenuNames, u32 priority) {
|
||||||
unlocalizedMainMenuNames.emplace_back(impl::SeparatorValue);
|
unlocalizedMainMenuNames.emplace_back(impl::SeparatorValue);
|
||||||
impl::s_menuItems->insert({
|
impl::s_menuItems->insert({
|
||||||
priority, impl::MenuItem { unlocalizedMainMenuNames, "", std::make_unique<Shortcut>(), nullptr, []{}, []{ return true; }, []{ return false; }, -1 }
|
priority, impl::MenuItem { unlocalizedMainMenuNames, "", Shortcut::None, nullptr, []{}, []{ return true; }, []{ return false; }, -1 }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1199,7 +1235,7 @@ namespace hex {
|
|||||||
|
|
||||||
class Service {
|
class Service {
|
||||||
public:
|
public:
|
||||||
Service(std::string name, std::jthread thread) : m_name(std::move(name)), m_thread(std::move(thread)) { }
|
Service(const UnlocalizedString &unlocalizedName, std::jthread thread) : m_unlocalizedName(std::move(unlocalizedName)), m_thread(std::move(thread)) { }
|
||||||
Service(const Service&) = delete;
|
Service(const Service&) = delete;
|
||||||
Service(Service &&) = default;
|
Service(Service &&) = default;
|
||||||
~Service() {
|
~Service() {
|
||||||
@@ -1211,8 +1247,8 @@ namespace hex {
|
|||||||
Service& operator=(const Service&) = delete;
|
Service& operator=(const Service&) = delete;
|
||||||
Service& operator=(Service &&) = default;
|
Service& operator=(Service &&) = default;
|
||||||
|
|
||||||
[[nodiscard]] const std::string& getName() const {
|
[[nodiscard]] const UnlocalizedString& getUnlocalizedName() const {
|
||||||
return m_name;
|
return m_unlocalizedName;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] const std::jthread& getThread() const {
|
[[nodiscard]] const std::jthread& getThread() const {
|
||||||
@@ -1220,7 +1256,7 @@ namespace hex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_name;
|
UnlocalizedString m_unlocalizedName;
|
||||||
std::jthread m_thread;
|
std::jthread m_thread;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -21,4 +21,30 @@ namespace hex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool EventManager::isAlreadyRegistered(void *token, impl::EventId id) {
|
||||||
|
if (getTokenStore().contains(token)) {
|
||||||
|
auto&& [begin, end] = getTokenStore().equal_range(token);
|
||||||
|
|
||||||
|
return std::any_of(begin, end, [&](auto &item) {
|
||||||
|
return item.second->first == id;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventManager::unsubscribe(void *token, impl::EventId id) {
|
||||||
|
auto &tokenStore = getTokenStore();
|
||||||
|
auto iter = std::find_if(tokenStore.begin(), tokenStore.end(), [&](auto &item) {
|
||||||
|
return item.first == token && item.second->first == id;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (iter != tokenStore.end()) {
|
||||||
|
getEvents().erase(iter->second);
|
||||||
|
tokenStore.erase(iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -268,7 +268,7 @@ namespace hex {
|
|||||||
|
|
||||||
static i64 s_currentProvider = -1;
|
static i64 s_currentProvider = -1;
|
||||||
static AutoReset<std::vector<std::unique_ptr<prv::Provider>>> s_providers;
|
static AutoReset<std::vector<std::unique_ptr<prv::Provider>>> s_providers;
|
||||||
static AutoReset<std::list<std::unique_ptr<prv::Provider>>> s_providersToRemove;
|
static AutoReset<std::map<prv::Provider*, std::unique_ptr<prv::Provider>>> s_providersToRemove;
|
||||||
|
|
||||||
namespace impl {
|
namespace impl {
|
||||||
|
|
||||||
@@ -337,8 +337,11 @@ namespace hex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void markDirty() {
|
void markDirty() {
|
||||||
get()->markDirty();
|
const auto provider = get();
|
||||||
EventProviderDirtied::post(get());
|
if (!provider->isDirty()) {
|
||||||
|
provider->markDirty();
|
||||||
|
EventProviderDirtied::post(provider);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void resetDirty() {
|
void resetDirty() {
|
||||||
@@ -430,7 +433,8 @@ namespace hex {
|
|||||||
|
|
||||||
// Move provider over to a list of providers to delete
|
// Move provider over to a list of providers to delete
|
||||||
eraseMutex.lock();
|
eraseMutex.lock();
|
||||||
auto removeIt = s_providersToRemove->emplace(s_providersToRemove->end(), std::move(*it));
|
auto providerToRemove = it->get();
|
||||||
|
(*s_providersToRemove)[providerToRemove] = std::move(*it);
|
||||||
eraseMutex.unlock();
|
eraseMutex.unlock();
|
||||||
|
|
||||||
// Remove left over references from the main provider list
|
// Remove left over references from the main provider list
|
||||||
@@ -443,16 +447,16 @@ namespace hex {
|
|||||||
if (s_providers->empty())
|
if (s_providers->empty())
|
||||||
EventProviderChanged::post(provider, nullptr);
|
EventProviderChanged::post(provider, nullptr);
|
||||||
|
|
||||||
EventProviderClosed::post(removeIt->get());
|
EventProviderClosed::post(it->get());
|
||||||
RequestUpdateWindowTitle::post();
|
RequestUpdateWindowTitle::post();
|
||||||
|
|
||||||
// Do the destruction of the provider in the background once all tasks have finished
|
// Do the destruction of the provider in the background once all tasks have finished
|
||||||
TaskManager::runWhenTasksFinished([removeIt] {
|
TaskManager::runWhenTasksFinished([providerToRemove] {
|
||||||
EventProviderDeleted::post(removeIt->get());
|
EventProviderDeleted::post(providerToRemove);
|
||||||
TaskManager::createBackgroundTask("Closing Provider", [removeIt](Task &) {
|
TaskManager::createBackgroundTask("Closing Provider", [providerToRemove](Task &) {
|
||||||
eraseMutex.lock();
|
eraseMutex.lock();
|
||||||
auto provider = std::move(*removeIt);
|
auto provider = std::move((*s_providersToRemove)[providerToRemove]);
|
||||||
s_providersToRemove->erase(removeIt);
|
s_providersToRemove->erase(providerToRemove);
|
||||||
eraseMutex.unlock();
|
eraseMutex.unlock();
|
||||||
|
|
||||||
provider->close();
|
provider->close();
|
||||||
@@ -641,6 +645,14 @@ namespace hex {
|
|||||||
return hex::getContainingModule(reinterpret_cast<void*>(&getLibImHexModuleHandle));
|
return hex::getContainingModule(reinterpret_cast<void*>(&getLibImHexModuleHandle));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addMigrationRoutine(SemanticVersion migrationVersion, std::function<void()> function) {
|
||||||
|
EventImHexUpdated::subscribe([migrationVersion, function](const SemanticVersion &oldVersion, const SemanticVersion &newVersion) {
|
||||||
|
if (oldVersion < migrationVersion && newVersion >= migrationVersion) {
|
||||||
|
function();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const std::map<std::string, std::string>& getInitArguments() {
|
const std::map<std::string, std::string>& getInitArguments() {
|
||||||
return *impl::s_initArguments;
|
return *impl::s_initArguments;
|
||||||
@@ -790,16 +802,11 @@ namespace hex {
|
|||||||
return { { name, version } };
|
return { { name, version } };
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getImHexVersion(bool withBuildType) {
|
SemanticVersion getImHexVersion() {
|
||||||
#if defined IMHEX_VERSION
|
#if defined IMHEX_VERSION
|
||||||
if (withBuildType) {
|
return SemanticVersion(IMHEX_VERSION);
|
||||||
return IMHEX_VERSION;
|
|
||||||
} else {
|
|
||||||
auto version = std::string(IMHEX_VERSION);
|
|
||||||
return version.substr(0, version.find('-'));
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
return "Unknown";
|
return {};
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -811,7 +818,7 @@ namespace hex {
|
|||||||
return std::string(GIT_COMMIT_HASH_LONG).substr(0, 7);
|
return std::string(GIT_COMMIT_HASH_LONG).substr(0, 7);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
hex::unused(longHash);
|
std::ignore = longHash;
|
||||||
return "Unknown";
|
return "Unknown";
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -833,7 +840,7 @@ namespace hex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool isNightlyBuild() {
|
bool isNightlyBuild() {
|
||||||
return getImHexVersion(false).ends_with("WIP");
|
return getImHexVersion().nightly();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool updateImHex(UpdateType updateType) {
|
bool updateImHex(UpdateType updateType) {
|
||||||
@@ -862,7 +869,7 @@ namespace hex {
|
|||||||
|
|
||||||
EventImHexClosing::subscribe([executablePath, updateTypeString] {
|
EventImHexClosing::subscribe([executablePath, updateTypeString] {
|
||||||
hex::executeCommand(
|
hex::executeCommand(
|
||||||
hex::format("{} {}",
|
hex::format("\"{}\" \"{}\"",
|
||||||
wolv::util::toUTF8String(executablePath),
|
wolv::util::toUTF8String(executablePath),
|
||||||
updateTypeString
|
updateTypeString
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ namespace hex {
|
|||||||
|
|
||||||
AutoReset<std::string> s_fallbackLanguage;
|
AutoReset<std::string> s_fallbackLanguage;
|
||||||
AutoReset<std::string> s_selectedLanguage;
|
AutoReset<std::string> s_selectedLanguage;
|
||||||
AutoReset<std::map<std::string, std::string>> s_currStrings;
|
AutoReset<std::map<size_t, std::string>> s_currStrings;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,6 +41,21 @@ namespace hex {
|
|||||||
return m_entries;
|
return m_entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void loadLanguageDefinitions(const std::vector<LanguageDefinition> &definitions) {
|
||||||
|
for (const auto &definition : definitions) {
|
||||||
|
const auto &entries = definition.getEntries();
|
||||||
|
if (entries.empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (const auto &[key, value] : entries) {
|
||||||
|
if (value.empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
s_currStrings->emplace(LangConst::hash(key), value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void loadLanguage(const std::string &language) {
|
void loadLanguage(const std::string &language) {
|
||||||
auto &definitions = ContentRegistry::Language::impl::getLanguageDefinitions();
|
auto &definitions = ContentRegistry::Language::impl::getLanguageDefinitions();
|
||||||
|
|
||||||
@@ -49,14 +64,10 @@ namespace hex {
|
|||||||
|
|
||||||
s_currStrings->clear();
|
s_currStrings->clear();
|
||||||
|
|
||||||
for (const auto &definition : definitions.at(language))
|
loadLanguageDefinitions(definitions.at(language));
|
||||||
s_currStrings->insert(definition.getEntries().begin(), definition.getEntries().end());
|
|
||||||
|
|
||||||
const auto& fallbackLanguage = getFallbackLanguage();
|
const auto& fallbackLanguage = getFallbackLanguage();
|
||||||
if (language != fallbackLanguage && definitions.contains(fallbackLanguage)) {
|
loadLanguageDefinitions(definitions.at(fallbackLanguage));
|
||||||
for (const auto &definition : definitions.at(fallbackLanguage))
|
|
||||||
s_currStrings->insert(definition.getEntries().begin(), definition.getEntries().end());
|
|
||||||
}
|
|
||||||
|
|
||||||
s_selectedLanguage = language;
|
s_selectedLanguage = language;
|
||||||
}
|
}
|
||||||
@@ -98,11 +109,11 @@ namespace hex {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Lang::Lang(const char *unlocalizedString) : m_unlocalizedString(unlocalizedString) { }
|
Lang::Lang(const char *unlocalizedString) : m_entryHash(LangConst::hash(unlocalizedString)), m_unlocalizedString(unlocalizedString) { }
|
||||||
Lang::Lang(const std::string &unlocalizedString) : m_unlocalizedString(unlocalizedString) { }
|
Lang::Lang(const std::string &unlocalizedString) : m_entryHash(LangConst::hash(unlocalizedString)), m_unlocalizedString(unlocalizedString) { }
|
||||||
Lang::Lang(const UnlocalizedString &unlocalizedString) : m_unlocalizedString(unlocalizedString.get()) { }
|
Lang::Lang(const LangConst &localizedString) : m_entryHash(localizedString.m_entryHash), m_unlocalizedString(localizedString.m_unlocalizedString) { }
|
||||||
Lang::Lang(std::string_view unlocalizedString) : m_unlocalizedString(unlocalizedString) { }
|
Lang::Lang(const UnlocalizedString &unlocalizedString) : m_entryHash(LangConst::hash(unlocalizedString.get())), m_unlocalizedString(unlocalizedString.get()) { }
|
||||||
|
Lang::Lang(std::string_view unlocalizedString) : m_entryHash(LangConst::hash(unlocalizedString)), m_unlocalizedString(unlocalizedString) { }
|
||||||
|
|
||||||
Lang::operator std::string() const {
|
Lang::operator std::string() const {
|
||||||
return get();
|
return get();
|
||||||
@@ -113,43 +124,41 @@ namespace hex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Lang::operator const char *() const {
|
Lang::operator const char *() const {
|
||||||
return get().c_str();
|
return get();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string operator+(const std::string &&left, const Lang &&right) {
|
const char *Lang::get() const {
|
||||||
return left + static_cast<std::string>(right);
|
const auto &lang = *LocalizationManager::s_currStrings;
|
||||||
|
|
||||||
|
const auto it = lang.find(m_entryHash);
|
||||||
|
if (it == lang.end()) {
|
||||||
|
return m_unlocalizedString.c_str();
|
||||||
|
} else {
|
||||||
|
return it->second.c_str();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string operator+(const Lang &&left, const std::string &&right) {
|
LangConst::operator std::string() const {
|
||||||
return static_cast<std::string>(left) + right;
|
return get();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string operator+(const Lang &&left, const Lang &&right) {
|
LangConst::operator std::string_view() const {
|
||||||
return static_cast<std::string>(left) + static_cast<std::string>(right);
|
return get();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string operator+(const std::string_view &&left, const Lang &&right) {
|
LangConst::operator const char *() const {
|
||||||
return std::string(left) + static_cast<std::string>(right);
|
return get();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string operator+(const Lang &&left, const std::string_view &&right) {
|
const char *LangConst::get() const {
|
||||||
return static_cast<std::string>(left) + std::string(right);
|
const auto &lang = *LocalizationManager::s_currStrings;
|
||||||
}
|
|
||||||
|
|
||||||
std::string operator+(const char *left, const Lang &&right) {
|
const auto it = lang.find(m_entryHash);
|
||||||
return left + static_cast<std::string>(right);
|
if (it == lang.end()) {
|
||||||
}
|
|
||||||
|
|
||||||
std::string operator+(const Lang &&left, const char *right) {
|
|
||||||
return static_cast<std::string>(left) + right;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string &Lang::get() const {
|
|
||||||
auto &lang = LocalizationManager::s_currStrings;
|
|
||||||
if (lang->contains(m_unlocalizedString))
|
|
||||||
return lang->at(m_unlocalizedString);
|
|
||||||
else
|
|
||||||
return m_unlocalizedString;
|
return m_unlocalizedString;
|
||||||
|
} else {
|
||||||
|
return it->second.c_str();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -112,10 +112,6 @@ namespace hex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Plugin::~Plugin() {
|
Plugin::~Plugin() {
|
||||||
if (isLoaded()) {
|
|
||||||
log::info("Trying to unload plugin '{}'", getPluginName());
|
|
||||||
}
|
|
||||||
|
|
||||||
unloadLibrary(m_handle, m_path);
|
unloadLibrary(m_handle, m_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,7 +129,7 @@ namespace hex {
|
|||||||
|
|
||||||
|
|
||||||
const auto requestedVersion = getCompatibleVersion();
|
const auto requestedVersion = getCompatibleVersion();
|
||||||
const auto imhexVersion = ImHexApi::System::getImHexVersion();
|
const auto imhexVersion = ImHexApi::System::getImHexVersion().get();
|
||||||
if (!imhexVersion.starts_with(requestedVersion)) {
|
if (!imhexVersion.starts_with(requestedVersion)) {
|
||||||
if (requestedVersion.empty()) {
|
if (requestedVersion.empty()) {
|
||||||
log::warn("Plugin '{}' did not specify a compatible version, assuming it is compatible with the current version of ImHex.", wolv::util::toUTF8String(m_path.filename()));
|
log::warn("Plugin '{}' did not specify a compatible version, assuming it is compatible with the current version of ImHex.", wolv::util::toUTF8String(m_path.filename()));
|
||||||
@@ -335,7 +331,7 @@ namespace hex {
|
|||||||
void PluginManager::initializeNewPlugins() {
|
void PluginManager::initializeNewPlugins() {
|
||||||
for (const auto &plugin : getPlugins()) {
|
for (const auto &plugin : getPlugins()) {
|
||||||
if (!plugin.isLoaded())
|
if (!plugin.isLoaded())
|
||||||
hex::unused(plugin.initializePlugin());
|
std::ignore = plugin.initializePlugin();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,31 +12,265 @@ namespace hex {
|
|||||||
AutoReset<std::map<Shortcut, ShortcutManager::ShortcutEntry>> s_globalShortcuts;
|
AutoReset<std::map<Shortcut, ShortcutManager::ShortcutEntry>> s_globalShortcuts;
|
||||||
std::atomic<bool> s_paused;
|
std::atomic<bool> s_paused;
|
||||||
std::optional<Shortcut> s_prevShortcut;
|
std::optional<Shortcut> s_prevShortcut;
|
||||||
|
bool s_macOSMode = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Shortcut operator+(const Key &lhs, const Key &rhs) {
|
||||||
|
Shortcut result;
|
||||||
|
result.m_keys = { lhs, rhs };
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Shortcut::Shortcut(Keys key) : m_keys({ key }) {
|
||||||
|
|
||||||
|
}
|
||||||
|
Shortcut::Shortcut(std::set<Key> keys) : m_keys(std::move(keys)) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Shortcut Shortcut::operator+(const Key &other) const {
|
||||||
|
Shortcut result = *this;
|
||||||
|
result.m_keys.insert(other);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Shortcut& Shortcut::operator+=(const Key &other) {
|
||||||
|
m_keys.insert(other);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Shortcut::operator<(const Shortcut &other) const {
|
||||||
|
return m_keys < other.m_keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Shortcut::operator==(const Shortcut &other) const {
|
||||||
|
return m_keys == other.m_keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Shortcut::isLocal() const {
|
||||||
|
return m_keys.contains(CurrentView);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::set<Key>& Shortcut::getKeys() const {
|
||||||
|
return m_keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Shortcut::has(Key key) const {
|
||||||
|
return m_keys.contains(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Shortcut::matches(const Shortcut& other) const {
|
||||||
|
auto left = this->m_keys;
|
||||||
|
auto right = other.m_keys;
|
||||||
|
|
||||||
|
left.erase(CurrentView);
|
||||||
|
left.erase(AllowWhileTyping);
|
||||||
|
right.erase(CurrentView);
|
||||||
|
right.erase(AllowWhileTyping);
|
||||||
|
|
||||||
|
return left == right;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string Shortcut::toString() const {
|
||||||
|
std::string result;
|
||||||
|
|
||||||
|
const auto CTRL_NAME = s_macOSMode ? "⌃" : "CTRL";
|
||||||
|
const auto ALT_NAME = s_macOSMode ? "⌥" : "ALT";
|
||||||
|
const auto SHIFT_NAME = s_macOSMode ? "⇧" : "SHIFT";
|
||||||
|
const auto SUPER_NAME = s_macOSMode ? "⌘" : "SUPER";
|
||||||
|
const auto Concatination = s_macOSMode ? " " : " + ";
|
||||||
|
|
||||||
|
auto keys = m_keys;
|
||||||
|
if (keys.erase(CTRL) > 0 || (!s_macOSMode && keys.erase(CTRLCMD) > 0)) {
|
||||||
|
result += CTRL_NAME;
|
||||||
|
result += Concatination;
|
||||||
|
}
|
||||||
|
if (keys.erase(ALT) > 0) {
|
||||||
|
result += ALT_NAME;
|
||||||
|
result += Concatination;
|
||||||
|
}
|
||||||
|
if (keys.erase(SHIFT) > 0) {
|
||||||
|
result += SHIFT_NAME;
|
||||||
|
result += Concatination;
|
||||||
|
}
|
||||||
|
if (keys.erase(SUPER) > 0 || (s_macOSMode && keys.erase(CTRLCMD) > 0)) {
|
||||||
|
result += SUPER_NAME;
|
||||||
|
result += Concatination;
|
||||||
|
}
|
||||||
|
keys.erase(CurrentView);
|
||||||
|
|
||||||
|
for (const auto &key : keys) {
|
||||||
|
switch (Keys(key.getKeyCode())) {
|
||||||
|
case Keys::Space: result += "⎵"; break;
|
||||||
|
case Keys::Apostrophe: result += "'"; break;
|
||||||
|
case Keys::Comma: result += ","; break;
|
||||||
|
case Keys::Minus: result += "-"; break;
|
||||||
|
case Keys::Period: result += "."; break;
|
||||||
|
case Keys::Slash: result += "/"; break;
|
||||||
|
case Keys::Num0: result += "0"; break;
|
||||||
|
case Keys::Num1: result += "1"; break;
|
||||||
|
case Keys::Num2: result += "2"; break;
|
||||||
|
case Keys::Num3: result += "3"; break;
|
||||||
|
case Keys::Num4: result += "4"; break;
|
||||||
|
case Keys::Num5: result += "5"; break;
|
||||||
|
case Keys::Num6: result += "6"; break;
|
||||||
|
case Keys::Num7: result += "7"; break;
|
||||||
|
case Keys::Num8: result += "8"; break;
|
||||||
|
case Keys::Num9: result += "9"; break;
|
||||||
|
case Keys::Semicolon: result += ";"; break;
|
||||||
|
case Keys::Equals: result += "="; break;
|
||||||
|
case Keys::A: result += "A"; break;
|
||||||
|
case Keys::B: result += "B"; break;
|
||||||
|
case Keys::C: result += "C"; break;
|
||||||
|
case Keys::D: result += "D"; break;
|
||||||
|
case Keys::E: result += "E"; break;
|
||||||
|
case Keys::F: result += "F"; break;
|
||||||
|
case Keys::G: result += "G"; break;
|
||||||
|
case Keys::H: result += "H"; break;
|
||||||
|
case Keys::I: result += "I"; break;
|
||||||
|
case Keys::J: result += "J"; break;
|
||||||
|
case Keys::K: result += "K"; break;
|
||||||
|
case Keys::L: result += "L"; break;
|
||||||
|
case Keys::M: result += "M"; break;
|
||||||
|
case Keys::N: result += "N"; break;
|
||||||
|
case Keys::O: result += "O"; break;
|
||||||
|
case Keys::P: result += "P"; break;
|
||||||
|
case Keys::Q: result += "Q"; break;
|
||||||
|
case Keys::R: result += "R"; break;
|
||||||
|
case Keys::S: result += "S"; break;
|
||||||
|
case Keys::T: result += "T"; break;
|
||||||
|
case Keys::U: result += "U"; break;
|
||||||
|
case Keys::V: result += "V"; break;
|
||||||
|
case Keys::W: result += "W"; break;
|
||||||
|
case Keys::X: result += "X"; break;
|
||||||
|
case Keys::Y: result += "Y"; break;
|
||||||
|
case Keys::Z: result += "Z"; break;
|
||||||
|
case Keys::LeftBracket: result += "["; break;
|
||||||
|
case Keys::Backslash: result += "\\"; break;
|
||||||
|
case Keys::RightBracket: result += "]"; break;
|
||||||
|
case Keys::GraveAccent: result += "`"; break;
|
||||||
|
case Keys::World1: result += "WORLD1"; break;
|
||||||
|
case Keys::World2: result += "WORLD2"; break;
|
||||||
|
case Keys::Escape: result += "ESC"; break;
|
||||||
|
case Keys::Enter: result += "⏎"; break;
|
||||||
|
case Keys::Tab: result += "⇥"; break;
|
||||||
|
case Keys::Backspace: result += "⌫"; break;
|
||||||
|
case Keys::Insert: result += "INSERT"; break;
|
||||||
|
case Keys::Delete: result += "DELETE"; break;
|
||||||
|
case Keys::Right: result += "RIGHT"; break;
|
||||||
|
case Keys::Left: result += "LEFT"; break;
|
||||||
|
case Keys::Down: result += "DOWN"; break;
|
||||||
|
case Keys::Up: result += "UP"; break;
|
||||||
|
case Keys::PageUp: result += "PAGEUP"; break;
|
||||||
|
case Keys::PageDown: result += "PAGEDOWN"; break;
|
||||||
|
case Keys::Home: result += "HOME"; break;
|
||||||
|
case Keys::End: result += "END"; break;
|
||||||
|
case Keys::CapsLock: result += "⇪"; break;
|
||||||
|
case Keys::ScrollLock: result += "SCROLLLOCK"; break;
|
||||||
|
case Keys::NumLock: result += "NUMLOCK"; break;
|
||||||
|
case Keys::PrintScreen: result += "PRINTSCREEN"; break;
|
||||||
|
case Keys::Pause: result += "PAUSE"; break;
|
||||||
|
case Keys::F1: result += "F1"; break;
|
||||||
|
case Keys::F2: result += "F2"; break;
|
||||||
|
case Keys::F3: result += "F3"; break;
|
||||||
|
case Keys::F4: result += "F4"; break;
|
||||||
|
case Keys::F5: result += "F5"; break;
|
||||||
|
case Keys::F6: result += "F6"; break;
|
||||||
|
case Keys::F7: result += "F7"; break;
|
||||||
|
case Keys::F8: result += "F8"; break;
|
||||||
|
case Keys::F9: result += "F9"; break;
|
||||||
|
case Keys::F10: result += "F10"; break;
|
||||||
|
case Keys::F11: result += "F11"; break;
|
||||||
|
case Keys::F12: result += "F12"; break;
|
||||||
|
case Keys::F13: result += "F13"; break;
|
||||||
|
case Keys::F14: result += "F14"; break;
|
||||||
|
case Keys::F15: result += "F15"; break;
|
||||||
|
case Keys::F16: result += "F16"; break;
|
||||||
|
case Keys::F17: result += "F17"; break;
|
||||||
|
case Keys::F18: result += "F18"; break;
|
||||||
|
case Keys::F19: result += "F19"; break;
|
||||||
|
case Keys::F20: result += "F20"; break;
|
||||||
|
case Keys::F21: result += "F21"; break;
|
||||||
|
case Keys::F22: result += "F22"; break;
|
||||||
|
case Keys::F23: result += "F23"; break;
|
||||||
|
case Keys::F24: result += "F24"; break;
|
||||||
|
case Keys::F25: result += "F25"; break;
|
||||||
|
case Keys::KeyPad0: result += "KP0"; break;
|
||||||
|
case Keys::KeyPad1: result += "KP1"; break;
|
||||||
|
case Keys::KeyPad2: result += "KP2"; break;
|
||||||
|
case Keys::KeyPad3: result += "KP3"; break;
|
||||||
|
case Keys::KeyPad4: result += "KP4"; break;
|
||||||
|
case Keys::KeyPad5: result += "KP5"; break;
|
||||||
|
case Keys::KeyPad6: result += "KP6"; break;
|
||||||
|
case Keys::KeyPad7: result += "KP7"; break;
|
||||||
|
case Keys::KeyPad8: result += "KP8"; break;
|
||||||
|
case Keys::KeyPad9: result += "KP9"; break;
|
||||||
|
case Keys::KeyPadDecimal: result += "KPDECIMAL"; break;
|
||||||
|
case Keys::KeyPadDivide: result += "KPDIVIDE"; break;
|
||||||
|
case Keys::KeyPadMultiply: result += "KPMULTIPLY"; break;
|
||||||
|
case Keys::KeyPadSubtract: result += "KPSUBTRACT"; break;
|
||||||
|
case Keys::KeyPadAdd: result += "KPADD"; break;
|
||||||
|
case Keys::KeyPadEnter: result += "KPENTER"; break;
|
||||||
|
case Keys::KeyPadEqual: result += "KPEQUAL"; break;
|
||||||
|
case Keys::Menu: result += "MENU"; break;
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
result += Concatination;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.ends_with(Concatination))
|
||||||
|
result = result.substr(0, result.size() - strlen(Concatination));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ShortcutManager::addGlobalShortcut(const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const std::function<void()> &callback) {
|
||||||
|
log::debug("Adding global shortcut {} for {}", shortcut.toString(), unlocalizedName.back().get());
|
||||||
|
auto [it, inserted] = s_globalShortcuts->insert({ shortcut, { shortcut, unlocalizedName, callback } });
|
||||||
|
if (!inserted) log::error("Failed to add shortcut!");
|
||||||
|
}
|
||||||
|
|
||||||
void ShortcutManager::addGlobalShortcut(const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const std::function<void()> &callback) {
|
void ShortcutManager::addGlobalShortcut(const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const std::function<void()> &callback) {
|
||||||
s_globalShortcuts->insert({ shortcut, { shortcut, unlocalizedName, callback } });
|
log::debug("Adding global shortcut {} for {}", shortcut.toString(), unlocalizedName.get());
|
||||||
|
auto [it, inserted] = s_globalShortcuts->insert({ shortcut, { shortcut, { unlocalizedName }, callback } });
|
||||||
|
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) {
|
||||||
|
log::debug("Adding shortcut {} for {}", shortcut.toString(), unlocalizedName.back().get());
|
||||||
|
auto [it, inserted] = view->m_shortcuts.insert({ shortcut + CurrentView, { shortcut, unlocalizedName, callback } });
|
||||||
|
if (!inserted) log::error("Failed to add shortcut!");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShortcutManager::addShortcut(View *view, const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const std::function<void()> &callback) {
|
void ShortcutManager::addShortcut(View *view, const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const std::function<void()> &callback) {
|
||||||
view->m_shortcuts.insert({ shortcut + CurrentView, { shortcut, unlocalizedName, callback } });
|
log::debug("Adding shortcut {} for {}", shortcut.toString(), unlocalizedName.get());
|
||||||
|
auto [it, inserted] = view->m_shortcuts.insert({ shortcut + CurrentView, { shortcut, { unlocalizedName }, callback } });
|
||||||
|
if (!inserted) log::error("Failed to add shortcut!");
|
||||||
}
|
}
|
||||||
|
|
||||||
static Shortcut getShortcut(bool ctrl, bool alt, bool shift, bool super, bool focused, u32 keyCode) {
|
static Shortcut getShortcut(bool ctrl, bool alt, bool shift, bool super, bool focused, u32 keyCode) {
|
||||||
Shortcut pressedShortcut;
|
Shortcut pressedShortcut;
|
||||||
|
|
||||||
if (ctrl)
|
if (ctrl)
|
||||||
pressedShortcut += CTRL;
|
pressedShortcut += s_macOSMode ? CTRL : CTRLCMD;
|
||||||
if (alt)
|
if (alt)
|
||||||
pressedShortcut += ALT;
|
pressedShortcut += ALT;
|
||||||
if (shift)
|
if (shift)
|
||||||
pressedShortcut += SHIFT;
|
pressedShortcut += SHIFT;
|
||||||
if (super)
|
if (super)
|
||||||
pressedShortcut += SUPER;
|
pressedShortcut += s_macOSMode ? CTRLCMD : SUPER;
|
||||||
if (focused)
|
if (focused)
|
||||||
pressedShortcut += CurrentView;
|
pressedShortcut += CurrentView;
|
||||||
|
if (ImGui::GetIO().WantTextInput)
|
||||||
|
pressedShortcut += AllowWhileTyping;
|
||||||
|
|
||||||
pressedShortcut += static_cast<Keys>(keyCode);
|
pressedShortcut += static_cast<Keys>(keyCode);
|
||||||
|
|
||||||
@@ -49,11 +283,9 @@ namespace hex {
|
|||||||
if (ImGui::IsPopupOpen(ImGuiID(0), ImGuiPopupFlags_AnyPopupId))
|
if (ImGui::IsPopupOpen(ImGuiID(0), ImGuiPopupFlags_AnyPopupId))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (shortcuts.contains(shortcut + AllowWhileTyping)) {
|
if (auto it = shortcuts.find(shortcut); it != shortcuts.end()) {
|
||||||
shortcuts.at(shortcut + AllowWhileTyping).callback();
|
const auto &[foundShortcut, entry] = *it;
|
||||||
} else if (shortcuts.contains(shortcut)) {
|
entry.callback();
|
||||||
if (!ImGui::GetIO().WantTextInput)
|
|
||||||
shortcuts.at(shortcut).callback();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,10 +354,13 @@ namespace hex {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ShortcutManager::updateShortcut(const Shortcut &oldShortcut, const Shortcut &newShortcut, View *view) {
|
bool ShortcutManager::updateShortcut(const Shortcut &oldShortcut, Shortcut newShortcut, View *view) {
|
||||||
if (oldShortcut == newShortcut)
|
if (oldShortcut.matches(newShortcut))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
if (oldShortcut.has(AllowWhileTyping))
|
||||||
|
newShortcut += AllowWhileTyping;
|
||||||
|
|
||||||
bool result;
|
bool result;
|
||||||
if (view != nullptr) {
|
if (view != nullptr) {
|
||||||
result = updateShortcutImpl(oldShortcut + CurrentView, newShortcut + CurrentView , view->m_shortcuts);
|
result = updateShortcutImpl(oldShortcut + CurrentView, newShortcut + CurrentView , view->m_shortcuts);
|
||||||
@@ -134,9 +369,9 @@ namespace hex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
for (auto &[priority, menuItem] : ContentRegistry::Interface::impl::getMenuItems()) {
|
for (auto &[priority, menuItem] : ContentRegistry::Interface::impl::getMenuItemsMutable()) {
|
||||||
if (menuItem.view == view && *menuItem.shortcut == oldShortcut) {
|
if (menuItem.view == view && menuItem.shortcut == oldShortcut) {
|
||||||
*menuItem.shortcut = newShortcut;
|
menuItem.shortcut = newShortcut;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -145,4 +380,9 @@ namespace hex {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ShortcutManager::enableMacOSMode() {
|
||||||
|
s_macOSMode = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -63,7 +63,7 @@ namespace hex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Task::Task(UnlocalizedString unlocalizedName, u64 maxValue, bool background, std::function<void(Task &)> function)
|
Task::Task(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, std::function<void(Task &)> function)
|
||||||
: m_unlocalizedName(std::move(unlocalizedName)), m_maxValue(maxValue), m_function(std::move(function)), m_background(background) { }
|
: m_unlocalizedName(std::move(unlocalizedName)), m_maxValue(maxValue), m_function(std::move(function)), m_background(background) { }
|
||||||
|
|
||||||
Task::Task(hex::Task &&other) noexcept {
|
Task::Task(hex::Task &&other) noexcept {
|
||||||
@@ -327,11 +327,11 @@ namespace hex {
|
|||||||
s_tasksFinishedCallbacks.clear();
|
s_tasksFinishedCallbacks.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
TaskHolder TaskManager::createTask(std::string name, u64 maxValue, bool background, std::function<void(Task&)> function) {
|
TaskHolder TaskManager::createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, std::function<void(Task&)> function) {
|
||||||
std::scoped_lock lock(s_queueMutex);
|
std::scoped_lock lock(s_queueMutex);
|
||||||
|
|
||||||
// Construct new task
|
// Construct new task
|
||||||
auto task = std::make_shared<Task>(std::move(name), maxValue, background, std::move(function));
|
auto task = std::make_shared<Task>(std::move(unlocalizedName), maxValue, background, std::move(function));
|
||||||
|
|
||||||
s_tasks.emplace_back(task);
|
s_tasks.emplace_back(task);
|
||||||
|
|
||||||
@@ -344,14 +344,32 @@ namespace hex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TaskHolder TaskManager::createTask(std::string name, u64 maxValue, std::function<void(Task &)> function) {
|
TaskHolder TaskManager::createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, std::function<void(Task &)> function) {
|
||||||
log::debug("Creating task {}", name);
|
log::debug("Creating task {}", unlocalizedName.get());
|
||||||
return createTask(std::move(name), maxValue, false, std::move(function));
|
return createTask(std::move(unlocalizedName), maxValue, false, std::move(function));
|
||||||
}
|
}
|
||||||
|
|
||||||
TaskHolder TaskManager::createBackgroundTask(std::string name, std::function<void(Task &)> function) {
|
TaskHolder TaskManager::createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, std::function<void()> function) {
|
||||||
log::debug("Creating background task {}", name);
|
log::debug("Creating task {}", unlocalizedName.get());
|
||||||
return createTask(std::move(name), 0, true, std::move(function));
|
return createTask(std::move(unlocalizedName), maxValue, false,
|
||||||
|
[function = std::move(function)](Task&) {
|
||||||
|
function();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
TaskHolder TaskManager::createBackgroundTask(const UnlocalizedString &unlocalizedName, std::function<void(Task &)> function) {
|
||||||
|
log::debug("Creating background task {}", unlocalizedName.get());
|
||||||
|
return createTask(std::move(unlocalizedName), 0, true, std::move(function));
|
||||||
|
}
|
||||||
|
|
||||||
|
TaskHolder TaskManager::createBackgroundTask(const UnlocalizedString &unlocalizedName, std::function<void()> function) {
|
||||||
|
log::debug("Creating background task {}", unlocalizedName.get());
|
||||||
|
return createTask(std::move(unlocalizedName), 0, true,
|
||||||
|
[function = std::move(function)](Task&) {
|
||||||
|
function();
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TaskManager::collectGarbage() {
|
void TaskManager::collectGarbage() {
|
||||||
@@ -472,7 +490,7 @@ namespace hex {
|
|||||||
#elif defined(OS_LINUX)
|
#elif defined(OS_LINUX)
|
||||||
pthread_setname_np(pthread_self(), name.c_str());
|
pthread_setname_np(pthread_self(), name.c_str());
|
||||||
#elif defined(OS_WEB)
|
#elif defined(OS_WEB)
|
||||||
hex::unused(name);
|
std::ignore = name;
|
||||||
#elif defined(OS_MACOS)
|
#elif defined(OS_MACOS)
|
||||||
pthread_setname_np(name.c_str());
|
pthread_setname_np(name.c_str());
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -21,6 +21,11 @@ namespace hex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ThemeManager::reapplyCurrentTheme() {
|
||||||
|
ThemeManager::changeTheme(s_currTheme);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void ThemeManager::addThemeHandler(const std::string &name, const ColorMap &colorMap, const std::function<ImColor(u32)> &getFunction, const std::function<void(u32, ImColor)> &setFunction) {
|
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);
|
std::unique_lock lock(s_themeMutex);
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,13 @@ namespace hex {
|
|||||||
idStack.push_back(0);
|
idStack.push_back(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void add(const char *string) {
|
||||||
|
const ImGuiID seed = idStack.back();
|
||||||
|
const ImGuiID id = ImHashStr(string, 0, seed);
|
||||||
|
|
||||||
|
idStack.push_back(id);
|
||||||
|
}
|
||||||
|
|
||||||
void add(const std::string &string) {
|
void add(const std::string &string) {
|
||||||
const ImGuiID seed = idStack.back();
|
const ImGuiID seed = idStack.back();
|
||||||
const ImGuiID id = ImHashStr(string.c_str(), string.length(), seed);
|
const ImGuiID id = ImHashStr(string.c_str(), string.length(), seed);
|
||||||
@@ -87,6 +94,10 @@ namespace hex {
|
|||||||
const auto element = hex::s_highlights->find(id);
|
const auto element = hex::s_highlights->find(id);
|
||||||
if (element != hex::s_highlights->end()) {
|
if (element != hex::s_highlights->end()) {
|
||||||
hex::s_highlightDisplays->emplace_back(boundingBox, element->second);
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (id != 0 && boundingBox.Contains(ImGui::GetMousePos())) {
|
if (id != 0 && boundingBox.Contains(ImGui::GetMousePos())) {
|
||||||
|
|||||||
@@ -8,12 +8,18 @@
|
|||||||
namespace hex::dp {
|
namespace hex::dp {
|
||||||
|
|
||||||
int Node::s_idCounter = 1;
|
int Node::s_idCounter = 1;
|
||||||
|
static std::atomic_bool s_interrupted;
|
||||||
|
|
||||||
Node::Node(UnlocalizedString unlocalizedTitle, std::vector<Attribute> attributes) : m_id(s_idCounter++), m_unlocalizedTitle(std::move(unlocalizedTitle)), m_attributes(std::move(attributes)) {
|
Node::Node(UnlocalizedString unlocalizedTitle, std::vector<Attribute> attributes) : m_id(s_idCounter++), m_unlocalizedTitle(std::move(unlocalizedTitle)), m_attributes(std::move(attributes)) {
|
||||||
for (auto &attr : m_attributes)
|
for (auto &attr : m_attributes)
|
||||||
attr.setParentNode(this);
|
attr.setParentNode(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Node::draw() {
|
||||||
|
this->drawNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const std::vector<u8>& Node::getBufferOnInput(u32 index) {
|
const std::vector<u8>& Node::getBufferOnInput(u32 index) {
|
||||||
auto attribute = this->getConnectedInputAttribute(index);
|
auto attribute = this->getConnectedInputAttribute(index);
|
||||||
|
|
||||||
@@ -29,9 +35,6 @@ namespace hex::dp {
|
|||||||
|
|
||||||
auto &outputData = attribute->getOutputData();
|
auto &outputData = attribute->getOutputData();
|
||||||
|
|
||||||
if (outputData.empty())
|
|
||||||
throwNodeError("No data available at connected attribute");
|
|
||||||
|
|
||||||
return outputData;
|
return outputData;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,9 +151,56 @@ namespace hex::dp {
|
|||||||
m_overlay->getData() = data;
|
m_overlay->getData() = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[noreturn]] void Node::throwNodeError(const std::string &message) {
|
||||||
|
throw NodeError { this, message };
|
||||||
|
}
|
||||||
|
|
||||||
|
void Node::setAttributes(std::vector<Attribute> attributes) {
|
||||||
|
m_attributes = std::move(attributes);
|
||||||
|
|
||||||
|
for (auto &attr : m_attributes)
|
||||||
|
attr.setParentNode(this);
|
||||||
|
}
|
||||||
|
|
||||||
void Node::setIdCounter(int id) {
|
void Node::setIdCounter(int id) {
|
||||||
if (id > s_idCounter)
|
if (id > s_idCounter)
|
||||||
s_idCounter = id;
|
s_idCounter = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Attribute& Node::getAttribute(u32 index) {
|
||||||
|
if (index >= this->getAttributes().size())
|
||||||
|
throw std::runtime_error("Attribute index out of bounds!");
|
||||||
|
|
||||||
|
return this->getAttributes()[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
Attribute *Node::getConnectedInputAttribute(u32 index) {
|
||||||
|
const auto &connectedAttribute = this->getAttribute(index).getConnectedAttributes();
|
||||||
|
|
||||||
|
if (connectedAttribute.empty())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return connectedAttribute.begin()->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Node::markInputProcessed(u32 index) {
|
||||||
|
const auto &[iter, inserted] = m_processedInputs.insert(index);
|
||||||
|
if (!inserted)
|
||||||
|
throwNodeError("Recursion detected!");
|
||||||
|
|
||||||
|
if (s_interrupted) {
|
||||||
|
s_interrupted = false;
|
||||||
|
throwNodeError("Execution interrupted!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Node::unmarkInputProcessed(u32 index) {
|
||||||
|
m_processedInputs.erase(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Node::interrupt() {
|
||||||
|
s_interrupted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
|
#include <algorithm>
|
||||||
#include <hex/helpers/crypto.hpp>
|
#include <hex/helpers/crypto.hpp>
|
||||||
|
|
||||||
#include <hex/providers/provider.hpp>
|
#include <hex/providers/provider.hpp>
|
||||||
|
|
||||||
#include <wolv/utils/guards.hpp>
|
#include <wolv/utils/guards.hpp>
|
||||||
|
#include <wolv/utils/expected.hpp>
|
||||||
|
|
||||||
#include <mbedtls/version.h>
|
#include <mbedtls/version.h>
|
||||||
#include <mbedtls/base64.h>
|
#include <mbedtls/base64.h>
|
||||||
@@ -496,8 +498,8 @@ namespace hex::crypt {
|
|||||||
return encodeLeb128<i128>(value);
|
return encodeLeb128<i128>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<u8> aes(mbedtls_cipher_type_t type, mbedtls_operation_t operation, const std::vector<u8> &key, std::array<u8, 8> nonce, std::array<u8, 8> iv, const std::vector<u8> &input) {
|
static wolv::util::Expected<std::vector<u8>, int> aes(mbedtls_cipher_type_t type, mbedtls_operation_t operation, const std::vector<u8> &key,
|
||||||
std::vector<u8> output;
|
std::array<u8, 8> nonce, std::array<u8, 8> iv, const std::span<const u8> &input) {
|
||||||
|
|
||||||
if (input.empty())
|
if (input.empty())
|
||||||
return {};
|
return {};
|
||||||
@@ -507,38 +509,65 @@ namespace hex::crypt {
|
|||||||
mbedtls_cipher_context_t ctx;
|
mbedtls_cipher_context_t ctx;
|
||||||
auto cipherInfo = mbedtls_cipher_info_from_type(type);
|
auto cipherInfo = mbedtls_cipher_info_from_type(type);
|
||||||
|
|
||||||
|
if (cipherInfo == nullptr)
|
||||||
|
return {};
|
||||||
|
|
||||||
mbedtls_cipher_setup(&ctx, cipherInfo);
|
int setupResult = mbedtls_cipher_setup(&ctx, cipherInfo);
|
||||||
mbedtls_cipher_setkey(&ctx, key.data(), key.size() * 8, operation);
|
if (setupResult != 0)
|
||||||
|
return wolv::util::Unexpected(setupResult);
|
||||||
|
|
||||||
|
int setKeyResult = mbedtls_cipher_setkey(&ctx, key.data(), key.size() * 8, operation);
|
||||||
|
if (setKeyResult != 0)
|
||||||
|
return wolv::util::Unexpected(setKeyResult);
|
||||||
|
|
||||||
std::array<u8, 16> nonceCounter = { 0 };
|
std::array<u8, 16> nonceCounter = { 0 };
|
||||||
std::copy(nonce.begin(), nonce.end(), nonceCounter.begin());
|
|
||||||
std::copy(iv.begin(), iv.end(), nonceCounter.begin() + 8);
|
auto mode = mbedtls_cipher_get_cipher_mode(&ctx);
|
||||||
|
|
||||||
|
// if we are in ECB mode, we don't need to set the nonce
|
||||||
|
if (mode != MBEDTLS_MODE_ECB) {
|
||||||
|
std::ranges::copy(nonce, nonceCounter.begin());
|
||||||
|
std::ranges::copy(iv, nonceCounter.begin() + 8);
|
||||||
|
}
|
||||||
|
|
||||||
size_t outputSize = input.size() + mbedtls_cipher_get_block_size(&ctx);
|
size_t outputSize = input.size() + mbedtls_cipher_get_block_size(&ctx);
|
||||||
output.resize(outputSize, 0x00);
|
std::vector<u8> output(outputSize, 0x00);
|
||||||
mbedtls_cipher_crypt(&ctx, nonceCounter.data(), nonceCounter.size(), input.data(), input.size(), output.data(), &outputSize);
|
|
||||||
|
|
||||||
|
int cryptResult = 0;
|
||||||
|
if (mode == MBEDTLS_MODE_ECB) {
|
||||||
|
cryptResult = mbedtls_cipher_crypt(&ctx, nullptr, 0, input.data(), input.size(), output.data(), &outputSize);
|
||||||
|
} else {
|
||||||
|
cryptResult = mbedtls_cipher_crypt(&ctx, nonceCounter.data(), nonceCounter.size(), input.data(), input.size(), output.data(), &outputSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// free regardless of the result
|
||||||
mbedtls_cipher_free(&ctx);
|
mbedtls_cipher_free(&ctx);
|
||||||
|
|
||||||
|
if (cryptResult != 0) {
|
||||||
|
return wolv::util::Unexpected(cryptResult);
|
||||||
|
}
|
||||||
|
|
||||||
output.resize(input.size());
|
output.resize(input.size());
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<u8> aesDecrypt(AESMode mode, KeyLength keyLength, const std::vector<u8> &key, std::array<u8, 8> nonce, std::array<u8, 8> iv, const std::vector<u8> &input) {
|
wolv::util::Expected<std::vector<u8>, int> aesDecrypt(AESMode mode, KeyLength keyLength, const std::vector<u8> &key, std::array<u8, 8> nonce, std::array<u8, 8> iv, const std::vector<u8> &input) {
|
||||||
switch (keyLength) {
|
switch (keyLength) {
|
||||||
case KeyLength::Key128Bits:
|
case KeyLength::Key128Bits:
|
||||||
if (key.size() != 128 / 8) return {};
|
if (key.size() != 128 / 8)
|
||||||
|
return wolv::util::Unexpected(CRYPTO_ERROR_INVALID_KEY_LENGTH);
|
||||||
break;
|
break;
|
||||||
case KeyLength::Key192Bits:
|
case KeyLength::Key192Bits:
|
||||||
if (key.size() != 192 / 8) return {};
|
if (key.size() != 192 / 8)
|
||||||
|
return wolv::util::Unexpected(CRYPTO_ERROR_INVALID_KEY_LENGTH);
|
||||||
break;
|
break;
|
||||||
case KeyLength::Key256Bits:
|
case KeyLength::Key256Bits:
|
||||||
if (key.size() != 256 / 8) return {};
|
if (key.size() != 256 / 8)
|
||||||
|
return wolv::util::Unexpected(CRYPTO_ERROR_INVALID_KEY_LENGTH);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return {};
|
return wolv::util::Unexpected(CRYPTO_ERROR_INVALID_KEY_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
mbedtls_cipher_type_t type;
|
mbedtls_cipher_type_t type;
|
||||||
@@ -568,7 +597,7 @@ namespace hex::crypt {
|
|||||||
type = MBEDTLS_CIPHER_AES_128_XTS;
|
type = MBEDTLS_CIPHER_AES_128_XTS;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return {};
|
return wolv::util::Unexpected(CRYPTO_ERROR_INVALID_MODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
type = mbedtls_cipher_type_t(type + u8(keyLength));
|
type = mbedtls_cipher_type_t(type + u8(keyLength));
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ namespace hex::paths {
|
|||||||
|
|
||||||
#elif defined(OS_MACOS)
|
#elif defined(OS_MACOS)
|
||||||
|
|
||||||
paths.push_back(wolv::io::fs::getApplicationSupportDirectoryPath());
|
paths.push_back(wolv::io::fs::getApplicationSupportDirectoryPath() / "imhex");
|
||||||
|
|
||||||
#elif defined(OS_LINUX) || defined(OS_WEB)
|
#elif defined(OS_LINUX) || defined(OS_WEB)
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ namespace hex::paths {
|
|||||||
#elif defined(OS_MACOS)
|
#elif defined(OS_MACOS)
|
||||||
return getDataPaths(includeSystemFolders);
|
return getDataPaths(includeSystemFolders);
|
||||||
#elif defined(OS_LINUX) || defined(OS_WEB)
|
#elif defined(OS_LINUX) || defined(OS_WEB)
|
||||||
hex::unused(includeSystemFolders);
|
std::ignore = includeSystemFolders;
|
||||||
return {xdg::ConfigHomeDir() / "imhex"};
|
return {xdg::ConfigHomeDir() / "imhex"};
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#if defined(OS_WEB)
|
#if defined(OS_WEB)
|
||||||
#include <emscripten.h>
|
#include <emscripten.h>
|
||||||
#else
|
#else
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
#include <nfd.hpp>
|
#include <nfd.hpp>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -50,13 +51,11 @@ namespace hex::fs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(OS_WINDOWS)
|
#if defined(OS_WINDOWS)
|
||||||
hex::unused(
|
std::ignore = ShellExecuteW(nullptr, L"open", filePath.c_str(), nullptr, nullptr, SW_SHOWNORMAL);
|
||||||
ShellExecuteW(nullptr, L"open", filePath.c_str(), nullptr, nullptr, SW_SHOWNORMAL)
|
|
||||||
);
|
|
||||||
#elif defined(OS_MACOS)
|
#elif defined(OS_MACOS)
|
||||||
hex::unused(system(
|
std::ignore = system(
|
||||||
hex::format("open {}", wolv::util::toUTF8String(filePath)).c_str()
|
hex::format("open {}", wolv::util::toUTF8String(filePath)).c_str()
|
||||||
));
|
);
|
||||||
#elif defined(OS_LINUX)
|
#elif defined(OS_LINUX)
|
||||||
executeCmd({"xdg-open", wolv::util::toUTF8String(filePath)});
|
executeCmd({"xdg-open", wolv::util::toUTF8String(filePath)});
|
||||||
#endif
|
#endif
|
||||||
@@ -72,9 +71,9 @@ namespace hex::fs {
|
|||||||
auto args = fmt::format(L"\"{}\"", dirPath.c_str());
|
auto args = fmt::format(L"\"{}\"", dirPath.c_str());
|
||||||
ShellExecuteW(nullptr, L"open", L"explorer.exe", args.c_str(), nullptr, SW_SHOWNORMAL);
|
ShellExecuteW(nullptr, L"open", L"explorer.exe", args.c_str(), nullptr, SW_SHOWNORMAL);
|
||||||
#elif defined(OS_MACOS)
|
#elif defined(OS_MACOS)
|
||||||
hex::unused(system(
|
std::ignore = system(
|
||||||
hex::format("open {}", wolv::util::toUTF8String(dirPath)).c_str()
|
hex::format("open {}", wolv::util::toUTF8String(dirPath)).c_str()
|
||||||
));
|
);
|
||||||
#elif defined(OS_LINUX)
|
#elif defined(OS_LINUX)
|
||||||
executeCmd({"xdg-open", wolv::util::toUTF8String(dirPath)});
|
executeCmd({"xdg-open", wolv::util::toUTF8String(dirPath)});
|
||||||
#endif
|
#endif
|
||||||
@@ -90,12 +89,12 @@ namespace hex::fs {
|
|||||||
auto args = fmt::format(L"/select,\"{}\"", selectedFilePath.c_str());
|
auto args = fmt::format(L"/select,\"{}\"", selectedFilePath.c_str());
|
||||||
ShellExecuteW(nullptr, L"open", L"explorer.exe", args.c_str(), nullptr, SW_SHOWNORMAL);
|
ShellExecuteW(nullptr, L"open", L"explorer.exe", args.c_str(), nullptr, SW_SHOWNORMAL);
|
||||||
#elif defined(OS_MACOS)
|
#elif defined(OS_MACOS)
|
||||||
hex::unused(system(
|
std::ignore = system(
|
||||||
hex::format(
|
hex::format(
|
||||||
R"(osascript -e 'tell application "Finder" to reveal POSIX file "{}"')",
|
R"(osascript -e 'tell application "Finder" to reveal POSIX file "{}"')",
|
||||||
wolv::util::toUTF8String(selectedFilePath)
|
wolv::util::toUTF8String(selectedFilePath)
|
||||||
).c_str()
|
).c_str()
|
||||||
));
|
);
|
||||||
system(R"(osascript -e 'tell application "Finder" to activate')");
|
system(R"(osascript -e 'tell application "Finder" to activate')");
|
||||||
#elif defined(OS_LINUX)
|
#elif defined(OS_LINUX)
|
||||||
// Fallback to only opening the folder for now
|
// Fallback to only opening the folder for now
|
||||||
@@ -124,7 +123,13 @@ namespace hex::fs {
|
|||||||
// Call callback that will write the file
|
// Call callback that will write the file
|
||||||
Module._fileBrowserCallback(stringToNewUTF8("/savedFiles/" + filename));
|
Module._fileBrowserCallback(stringToNewUTF8("/savedFiles/" + filename));
|
||||||
|
|
||||||
let data = FS.readFile("/savedFiles/" + filename);
|
let data;
|
||||||
|
try {
|
||||||
|
data = FS.readFile("/savedFiles/" + filename);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const reader = Object.assign(new FileReader(), {
|
const reader = Object.assign(new FileReader(), {
|
||||||
onload: () => {
|
onload: () => {
|
||||||
@@ -192,6 +197,7 @@ namespace hex::fs {
|
|||||||
else if (!validExtensions.empty())
|
else if (!validExtensions.empty())
|
||||||
path = "file." + validExtensions[0].spec;
|
path = "file." + validExtensions[0].spec;
|
||||||
|
|
||||||
|
std::fs::create_directory("/savedFiles");
|
||||||
callJs_saveFile(path.filename().string().c_str());
|
callJs_saveFile(path.filename().string().c_str());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,17 +41,21 @@ namespace hex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void HttpRequest::setProxyUrl(std::string proxy) {
|
void HttpRequest::setProxyUrl(std::string proxy) {
|
||||||
hex::unused(proxy);
|
std::ignore = proxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpRequest::setProxyState(bool state) {
|
void HttpRequest::setProxyState(bool state) {
|
||||||
hex::unused(state);
|
std::ignore = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpRequest::checkProxyErrors() { }
|
void HttpRequest::checkProxyErrors() { }
|
||||||
|
|
||||||
int HttpRequest::progressCallback(void *contents, curl_off_t dlTotal, curl_off_t dlNow, curl_off_t ulTotal, curl_off_t ulNow) {
|
int HttpRequest::progressCallback(void *contents, curl_off_t dlTotal, curl_off_t dlNow, curl_off_t ulTotal, curl_off_t ulNow) {
|
||||||
hex::unused(contents, dlTotal, dlNow, ulTotal, ulNow);
|
std::ignore = contents;
|
||||||
|
std::ignore = dlTotal;
|
||||||
|
std::ignore = dlNow;
|
||||||
|
std::ignore = ulTotal;
|
||||||
|
std::ignore = ulNow;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,9 @@ namespace hex {
|
|||||||
void close() override { }
|
void close() override { }
|
||||||
|
|
||||||
void readRaw(u64 offset, void *buffer, size_t size) override {
|
void readRaw(u64 offset, void *buffer, size_t size) override {
|
||||||
hex::unused(offset, buffer, size);
|
std::ignore = offset;
|
||||||
|
std::ignore = buffer;
|
||||||
|
std::ignore = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeRaw(u64 offset, const void *buffer, size_t size) override {
|
void writeRaw(u64 offset, const void *buffer, size_t size) override {
|
||||||
@@ -44,7 +46,7 @@ namespace hex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void resizeRaw(u64 newSize) override {
|
void resizeRaw(u64 newSize) override {
|
||||||
hex::unused(newSize);
|
std::ignore = newSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void insertRaw(u64 offset, u64 size) override {
|
void insertRaw(u64 offset, u64 size) override {
|
||||||
|
|||||||
118
lib/libimhex/source/helpers/semantic_version.cpp
Normal file
118
lib/libimhex/source/helpers/semantic_version.cpp
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
#include <hex/helpers/fmt.hpp>
|
||||||
|
#include <hex/helpers/semantic_version.hpp>
|
||||||
|
#include <wolv/utils/string.hpp>
|
||||||
|
|
||||||
|
namespace hex {
|
||||||
|
|
||||||
|
SemanticVersion::SemanticVersion(const char *version) : SemanticVersion(std::string(version)) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SemanticVersion::SemanticVersion(std::string_view version) : SemanticVersion(std::string(version.begin(), version.end())) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SemanticVersion::SemanticVersion(std::string version) {
|
||||||
|
if (version.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (version.starts_with("v"))
|
||||||
|
version = version.substr(1);
|
||||||
|
|
||||||
|
m_parts = wolv::util::splitString(version, ".");
|
||||||
|
|
||||||
|
if (m_parts.size() != 3 && m_parts.size() != 4) {
|
||||||
|
m_parts.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_parts.back().contains("-")) {
|
||||||
|
auto buildTypeParts = wolv::util::splitString(m_parts.back(), "-");
|
||||||
|
if (buildTypeParts.size() != 2) {
|
||||||
|
m_parts.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_parts.back() = buildTypeParts[0];
|
||||||
|
m_buildType = buildTypeParts[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 SemanticVersion::major() const {
|
||||||
|
if (!isValid()) return 0;
|
||||||
|
|
||||||
|
try {
|
||||||
|
return std::stoul(m_parts[0]);
|
||||||
|
} catch (...) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 SemanticVersion::minor() const {
|
||||||
|
if (!isValid()) return 0;
|
||||||
|
|
||||||
|
try {
|
||||||
|
return std::stoul(m_parts[1]);
|
||||||
|
} catch (...) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 SemanticVersion::patch() const {
|
||||||
|
if (!isValid()) return 0;
|
||||||
|
|
||||||
|
try {
|
||||||
|
return std::stoul(m_parts[2]);
|
||||||
|
} catch (...) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SemanticVersion::nightly() const {
|
||||||
|
if (!isValid()) return false;
|
||||||
|
|
||||||
|
return m_parts.size() == 4 && m_parts[3] == "WIP";
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& SemanticVersion::buildType() const {
|
||||||
|
return m_buildType;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SemanticVersion::isValid() const {
|
||||||
|
return !m_parts.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SemanticVersion::operator==(const SemanticVersion& other) const {
|
||||||
|
return this->m_parts == other.m_parts;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::strong_ordering SemanticVersion::operator<=>(const SemanticVersion &other) const {
|
||||||
|
if (*this == other)
|
||||||
|
return std::strong_ordering::equivalent;
|
||||||
|
|
||||||
|
if (this->major() > other.major())
|
||||||
|
return std::strong_ordering::greater;
|
||||||
|
if (this->minor() > other.minor())
|
||||||
|
return std::strong_ordering::greater;
|
||||||
|
if (this->patch() > other.patch())
|
||||||
|
return std::strong_ordering::greater;
|
||||||
|
if (!this->nightly() && other.nightly())
|
||||||
|
return std::strong_ordering::greater;
|
||||||
|
|
||||||
|
return std::strong_ordering::less;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string SemanticVersion::get(bool withBuildType) const {
|
||||||
|
if (!isValid()) return "";
|
||||||
|
|
||||||
|
auto result = wolv::util::combineStrings(m_parts, ".");
|
||||||
|
|
||||||
|
if (withBuildType && !m_buildType.empty())
|
||||||
|
result += hex::format("-{}", m_buildType);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -336,13 +336,13 @@ namespace hex {
|
|||||||
void startProgram(const std::string &command) {
|
void startProgram(const std::string &command) {
|
||||||
|
|
||||||
#if defined(OS_WINDOWS)
|
#if defined(OS_WINDOWS)
|
||||||
hex::unused(system(hex::format("start {0}", command).c_str()));
|
std::ignore = system(hex::format("start {0}", command).c_str());
|
||||||
#elif defined(OS_MACOS)
|
#elif defined(OS_MACOS)
|
||||||
hex::unused(system(hex::format("open {0}", command).c_str()));
|
std::ignore = system(hex::format("open {0}", command).c_str());
|
||||||
#elif defined(OS_LINUX)
|
#elif defined(OS_LINUX)
|
||||||
executeCmd({"xdg-open", command});
|
executeCmd({"xdg-open", command});
|
||||||
#elif defined(OS_WEB)
|
#elif defined(OS_WEB)
|
||||||
hex::unused(command);
|
std::ignore = command;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -685,7 +685,7 @@ namespace hex {
|
|||||||
return string;
|
return string;
|
||||||
|
|
||||||
// If the string is longer than the max length, find the last space before the max length
|
// If the string is longer than the max length, find the last space before the max length
|
||||||
auto it = string.begin() + maxLength / 2;
|
auto it = string.begin() + maxLength;
|
||||||
while (it != string.begin() && !std::isspace(*it)) --it;
|
while (it != string.begin() && !std::isspace(*it)) --it;
|
||||||
|
|
||||||
// If there's no space before the max length, just cut the string
|
// If there's no space before the max length, just cut the string
|
||||||
@@ -839,7 +839,7 @@ namespace hex {
|
|||||||
|
|
||||||
return dlopen(info.dli_fname, RTLD_LAZY);
|
return dlopen(info.dli_fname, RTLD_LAZY);
|
||||||
#else
|
#else
|
||||||
hex::unused(symbol);
|
std::ignore = symbol;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,7 +104,8 @@ namespace hex::prv {
|
|||||||
|
|
||||||
void Provider::insertRaw(u64 offset, u64 size) {
|
void Provider::insertRaw(u64 offset, u64 size) {
|
||||||
auto oldSize = this->getActualSize();
|
auto oldSize = this->getActualSize();
|
||||||
this->resizeRaw(oldSize + size);
|
auto newSize = oldSize + size;
|
||||||
|
this->resizeRaw(newSize);
|
||||||
|
|
||||||
std::vector<u8> buffer(0x1000);
|
std::vector<u8> buffer(0x1000);
|
||||||
const std::vector<u8> zeroBuffer(0x1000);
|
const std::vector<u8> zeroBuffer(0x1000);
|
||||||
@@ -116,7 +117,7 @@ namespace hex::prv {
|
|||||||
position -= readSize;
|
position -= readSize;
|
||||||
|
|
||||||
this->readRaw(position, buffer.data(), readSize);
|
this->readRaw(position, buffer.data(), readSize);
|
||||||
this->writeRaw(position, zeroBuffer.data(), readSize);
|
this->writeRaw(position, zeroBuffer.data(), newSize - oldSize);
|
||||||
this->writeRaw(position + size, buffer.data(), readSize);
|
this->writeRaw(position + size, buffer.data(), readSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ namespace ImGuiExt {
|
|||||||
|
|
||||||
STBI_FREE(imageData);
|
STBI_FREE(imageData);
|
||||||
|
|
||||||
result.m_textureId = reinterpret_cast<ImTextureID>(static_cast<intptr_t>(texture));
|
result.m_textureId = texture;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -189,14 +189,14 @@ namespace ImGuiExt {
|
|||||||
|
|
||||||
STBI_FREE(imageData);
|
STBI_FREE(imageData);
|
||||||
|
|
||||||
result.m_textureId = reinterpret_cast<ImTextureID>(static_cast<intptr_t>(texture));
|
result.m_textureId = texture;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture Texture::fromGLTexture(unsigned int glTexture, int width, int height) {
|
Texture Texture::fromGLTexture(unsigned int glTexture, int width, int height) {
|
||||||
Texture texture;
|
Texture texture;
|
||||||
texture.m_textureId = reinterpret_cast<ImTextureID>(static_cast<intptr_t>(glTexture));
|
texture.m_textureId = glTexture;
|
||||||
texture.m_width = width;
|
texture.m_width = width;
|
||||||
texture.m_height = height;
|
texture.m_height = height;
|
||||||
|
|
||||||
@@ -216,7 +216,7 @@ namespace ImGuiExt {
|
|||||||
Texture result;
|
Texture result;
|
||||||
result.m_width = width;
|
result.m_width = width;
|
||||||
result.m_height = height;
|
result.m_height = height;
|
||||||
result.m_textureId = reinterpret_cast<ImTextureID>(static_cast<intptr_t>(texture));
|
result.m_textureId = texture;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -230,7 +230,7 @@ namespace ImGuiExt {
|
|||||||
Texture result;
|
Texture result;
|
||||||
result.m_width = bitmap.width();
|
result.m_width = bitmap.width();
|
||||||
result.m_height = bitmap.height();
|
result.m_height = bitmap.height();
|
||||||
result.m_textureId = reinterpret_cast<ImTextureID>(static_cast<intptr_t>(texture));
|
result.m_textureId = texture;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -249,37 +249,37 @@ namespace ImGuiExt {
|
|||||||
Texture result;
|
Texture result;
|
||||||
result.m_width = bitmap.width();
|
result.m_width = bitmap.width();
|
||||||
result.m_height = bitmap.height();
|
result.m_height = bitmap.height();
|
||||||
result.m_textureId = reinterpret_cast<ImTextureID>(static_cast<intptr_t>(texture));
|
result.m_textureId = texture;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture::Texture(Texture&& other) noexcept {
|
Texture::Texture(Texture&& other) noexcept {
|
||||||
if (m_textureId != nullptr)
|
if (m_textureId != 0)
|
||||||
glDeleteTextures(1, reinterpret_cast<GLuint*>(&m_textureId));
|
glDeleteTextures(1, reinterpret_cast<GLuint*>(&m_textureId));
|
||||||
|
|
||||||
m_textureId = other.m_textureId;
|
m_textureId = other.m_textureId;
|
||||||
m_width = other.m_width;
|
m_width = other.m_width;
|
||||||
m_height = other.m_height;
|
m_height = other.m_height;
|
||||||
|
|
||||||
other.m_textureId = nullptr;
|
other.m_textureId = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture& Texture::operator=(Texture&& other) noexcept {
|
Texture& Texture::operator=(Texture&& other) noexcept {
|
||||||
if (m_textureId != nullptr)
|
if (m_textureId != 0)
|
||||||
glDeleteTextures(1, reinterpret_cast<GLuint*>(&m_textureId));
|
glDeleteTextures(1, reinterpret_cast<GLuint*>(&m_textureId));
|
||||||
|
|
||||||
m_textureId = other.m_textureId;
|
m_textureId = other.m_textureId;
|
||||||
m_width = other.m_width;
|
m_width = other.m_width;
|
||||||
m_height = other.m_height;
|
m_height = other.m_height;
|
||||||
|
|
||||||
other.m_textureId = nullptr;
|
other.m_textureId = 0;
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture::~Texture() {
|
Texture::~Texture() {
|
||||||
if (m_textureId == nullptr)
|
if (m_textureId == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
glDeleteTextures(1, reinterpret_cast<GLuint*>(&m_textureId));
|
glDeleteTextures(1, reinterpret_cast<GLuint*>(&m_textureId));
|
||||||
@@ -317,8 +317,6 @@ namespace ImGuiExt {
|
|||||||
if (!ItemAdd(bb, id))
|
if (!ItemAdd(bb, id))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (g.LastItemData.InFlags & ImGuiItemFlags_ButtonRepeat)
|
|
||||||
flags |= ImGuiButtonFlags_Repeat;
|
|
||||||
bool hovered, held;
|
bool hovered, held;
|
||||||
bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
|
bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
|
||||||
|
|
||||||
@@ -350,8 +348,6 @@ namespace ImGuiExt {
|
|||||||
const ImRect bb(pos, pos + size);
|
const ImRect bb(pos, pos + size);
|
||||||
ItemAdd(bb, id);
|
ItemAdd(bb, id);
|
||||||
|
|
||||||
if (g.LastItemData.InFlags & ImGuiItemFlags_ButtonRepeat)
|
|
||||||
flags |= ImGuiButtonFlags_Repeat;
|
|
||||||
bool hovered, held;
|
bool hovered, held;
|
||||||
bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
|
bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
|
||||||
|
|
||||||
@@ -387,8 +383,6 @@ namespace ImGuiExt {
|
|||||||
if (!ItemAdd(bb, id))
|
if (!ItemAdd(bb, id))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (g.LastItemData.InFlags & ImGuiItemFlags_ButtonRepeat)
|
|
||||||
flags |= ImGuiButtonFlags_Repeat;
|
|
||||||
bool hovered, held;
|
bool hovered, held;
|
||||||
bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
|
bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
|
||||||
|
|
||||||
@@ -425,8 +419,6 @@ namespace ImGuiExt {
|
|||||||
if (!ItemAdd(bb, id))
|
if (!ItemAdd(bb, id))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (g.LastItemData.InFlags & ImGuiItemFlags_ButtonRepeat)
|
|
||||||
flags |= ImGuiButtonFlags_Repeat;
|
|
||||||
bool hovered, held;
|
bool hovered, held;
|
||||||
bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
|
bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
|
||||||
|
|
||||||
@@ -436,7 +428,7 @@ namespace ImGuiExt {
|
|||||||
// Render
|
// Render
|
||||||
const ImU32 col = GetCustomColorU32((held && hovered) ? ImGuiCustomCol_DescButtonActive : hovered ? ImGuiCustomCol_DescButtonHovered
|
const ImU32 col = GetCustomColorU32((held && hovered) ? ImGuiCustomCol_DescButtonActive : hovered ? ImGuiCustomCol_DescButtonHovered
|
||||||
: ImGuiCustomCol_DescButton);
|
: ImGuiCustomCol_DescButton);
|
||||||
RenderNavHighlight(bb, id);
|
RenderNavCursor(bb, id);
|
||||||
RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding);
|
RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding);
|
||||||
PushStyleColor(ImGuiCol_Text, GetColorU32(ImGuiCol_ButtonActive));
|
PushStyleColor(ImGuiCol_Text, GetColorU32(ImGuiCol_ButtonActive));
|
||||||
RenderTextClipped(bb.Min + style.FramePadding * 2, bb.Max - style.FramePadding, label, nullptr, nullptr);
|
RenderTextClipped(bb.Min + style.FramePadding * 2, bb.Max - style.FramePadding, label, nullptr, nullptr);
|
||||||
@@ -478,8 +470,6 @@ namespace ImGuiExt {
|
|||||||
if (!ItemAdd(bb, id))
|
if (!ItemAdd(bb, id))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (g.LastItemData.InFlags & ImGuiItemFlags_ButtonRepeat)
|
|
||||||
flags |= ImGuiButtonFlags_Repeat;
|
|
||||||
bool hovered, held;
|
bool hovered, held;
|
||||||
bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
|
bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
|
||||||
|
|
||||||
@@ -489,7 +479,7 @@ namespace ImGuiExt {
|
|||||||
// Render
|
// Render
|
||||||
const ImU32 col = GetCustomColorU32((held && hovered) ? ImGuiCustomCol_DescButtonActive : hovered ? ImGuiCustomCol_DescButtonHovered
|
const ImU32 col = GetCustomColorU32((held && hovered) ? ImGuiCustomCol_DescButtonActive : hovered ? ImGuiCustomCol_DescButtonHovered
|
||||||
: ImGuiCustomCol_DescButton);
|
: ImGuiCustomCol_DescButton);
|
||||||
RenderNavHighlight(bb, id);
|
RenderNavCursor(bb, id);
|
||||||
RenderFrame(bb.Min, bb.Max, col, false, style.FrameRounding);
|
RenderFrame(bb.Min, bb.Max, col, false, style.FrameRounding);
|
||||||
PushStyleColor(ImGuiCol_Text, GetColorU32(ImGuiCol_ButtonActive));
|
PushStyleColor(ImGuiCol_Text, GetColorU32(ImGuiCol_ButtonActive));
|
||||||
RenderTextClipped(bb.Min + style.FramePadding * 2, bb.Max - style.FramePadding, label, nullptr, nullptr);
|
RenderTextClipped(bb.Min + style.FramePadding * 2, bb.Max - style.FramePadding, label, nullptr, nullptr);
|
||||||
@@ -522,7 +512,9 @@ namespace ImGuiExt {
|
|||||||
PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0F);
|
PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0F);
|
||||||
|
|
||||||
PushStyleColor(ImGuiCol_Text, iconColor);
|
PushStyleColor(ImGuiCol_Text, iconColor);
|
||||||
|
ImGui::PushID(text);
|
||||||
Button(icon);
|
Button(icon);
|
||||||
|
ImGui::PopID();
|
||||||
PopStyleColor();
|
PopStyleColor();
|
||||||
|
|
||||||
if (IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) {
|
if (IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) {
|
||||||
@@ -550,6 +542,34 @@ namespace ImGuiExt {
|
|||||||
PopStyleColor();
|
PopStyleColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UnderwavedText(const char *label, ImColor textColor, ImColor lineColor, const ImVec2 &size_arg) {
|
||||||
|
ImGuiWindow *window = GetCurrentWindow();
|
||||||
|
std::string labelStr(label);
|
||||||
|
for (char letter : labelStr) {
|
||||||
|
std::string letterStr(1, letter);
|
||||||
|
const ImVec2 label_size = CalcTextSize(letterStr.c_str(), nullptr, true);
|
||||||
|
ImVec2 size = CalcItemSize(size_arg, label_size.x, label_size.y);
|
||||||
|
ImVec2 pos = window->DC.CursorPos;
|
||||||
|
float lineWidth = size.x / 3.0f;
|
||||||
|
float halfLineW = lineWidth / 2.0f;
|
||||||
|
float lineY = pos.y + size.y;
|
||||||
|
ImVec2 initial = ImVec2(pos.x, lineY);
|
||||||
|
ImVec2 pos1 = ImVec2(pos.x + lineWidth, lineY - 2.0f);
|
||||||
|
ImVec2 pos2 = ImVec2(pos.x + lineWidth + halfLineW, lineY);
|
||||||
|
ImVec2 pos3 = ImVec2(pos.x + lineWidth * 2 + halfLineW, lineY - 2.0f);
|
||||||
|
ImVec2 pos4 = ImVec2(pos.x + lineWidth * 3, lineY - 1.0f);
|
||||||
|
|
||||||
|
PushStyleColor(ImGuiCol_Text, ImU32(textColor));
|
||||||
|
TextEx(letterStr.c_str(), nullptr, ImGuiTextFlags_NoWidthForLargeClippedText); // Skip formatting
|
||||||
|
GetWindowDrawList()->AddLine(initial, pos1, ImU32(lineColor),0.4f);
|
||||||
|
GetWindowDrawList()->AddLine(pos1, pos2, ImU32(lineColor),0.3f);
|
||||||
|
GetWindowDrawList()->AddLine(pos2, pos3, ImU32(lineColor),0.4f);
|
||||||
|
GetWindowDrawList()->AddLine(pos3, pos4, ImU32(lineColor),0.3f);
|
||||||
|
PopStyleColor();
|
||||||
|
window->DC.CursorPos = ImVec2(pos.x + size.x, pos.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TextSpinner(const char *label) {
|
void TextSpinner(const char *label) {
|
||||||
Text("[%c] %s", "|/-\\"[ImU32(GetTime() * 20) % 4], label);
|
Text("[%c] %s", "|/-\\"[ImU32(GetTime() * 20) % 4], label);
|
||||||
}
|
}
|
||||||
@@ -742,7 +762,7 @@ namespace ImGuiExt {
|
|||||||
// Render
|
// Render
|
||||||
const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered
|
const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered
|
||||||
: ImGuiCol_Button);
|
: ImGuiCol_Button);
|
||||||
RenderNavHighlight(bb, id);
|
RenderNavCursor(bb, id);
|
||||||
RenderFrame(bb.Min, bb.Max, col, false, style.FrameRounding);
|
RenderFrame(bb.Min, bb.Max, col, false, style.FrameRounding);
|
||||||
RenderTextClipped(bb.Min + style.FramePadding, bb.Max - style.FramePadding, label, nullptr, &label_size, style.ButtonTextAlign, &bb);
|
RenderTextClipped(bb.Min + style.FramePadding, bb.Max - style.FramePadding, label, nullptr, &label_size, style.ButtonTextAlign, &bb);
|
||||||
|
|
||||||
@@ -785,7 +805,7 @@ namespace ImGuiExt {
|
|||||||
// Render
|
// Render
|
||||||
const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ScrollbarGrabActive : hovered ? ImGuiCol_ScrollbarGrabHovered
|
const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ScrollbarGrabActive : hovered ? ImGuiCol_ScrollbarGrabHovered
|
||||||
: ImGuiCol_MenuBarBg);
|
: ImGuiCol_MenuBarBg);
|
||||||
RenderNavHighlight(bb, id);
|
RenderNavCursor(bb, id);
|
||||||
RenderFrame(bb.Min, bb.Max, col, false, style.FrameRounding);
|
RenderFrame(bb.Min, bb.Max, col, false, style.FrameRounding);
|
||||||
RenderTextClipped(bb.Min + padding, bb.Max - padding, symbol, nullptr, &size, style.ButtonTextAlign, &bb);
|
RenderTextClipped(bb.Min + padding, bb.Max - padding, symbol, nullptr, &size, style.ButtonTextAlign, &bb);
|
||||||
|
|
||||||
@@ -828,7 +848,7 @@ namespace ImGuiExt {
|
|||||||
// Render
|
// Render
|
||||||
const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered
|
const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered
|
||||||
: ImGuiCol_Button);
|
: ImGuiCol_Button);
|
||||||
RenderNavHighlight(bb, id);
|
RenderNavCursor(bb, id);
|
||||||
RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding);
|
RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding);
|
||||||
RenderTextClipped(bb.Min + style.FramePadding * ImVec2(1.3, 1), bb.Max - style.FramePadding, symbol, nullptr, &label_size, style.ButtonTextAlign, &bb);
|
RenderTextClipped(bb.Min + style.FramePadding * ImVec2(1.3, 1), bb.Max - style.FramePadding, symbol, nullptr, &label_size, style.ButtonTextAlign, &bb);
|
||||||
|
|
||||||
@@ -857,7 +877,7 @@ namespace ImGuiExt {
|
|||||||
char buf[64];
|
char buf[64];
|
||||||
DataTypeFormatString(buf, IM_ARRAYSIZE(buf), type, value, format);
|
DataTypeFormatString(buf, IM_ARRAYSIZE(buf), type, value, format);
|
||||||
|
|
||||||
RenderNavHighlight(frame_bb, id);
|
RenderNavCursor(frame_bb, id);
|
||||||
RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding);
|
RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding);
|
||||||
|
|
||||||
PushStyleVar(ImGuiStyleVar_Alpha, 0.6F);
|
PushStyleVar(ImGuiStyleVar_Alpha, 0.6F);
|
||||||
@@ -881,7 +901,7 @@ namespace ImGuiExt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool InputHexadecimal(const char *label, u32 *value, ImGuiInputTextFlags flags) {
|
bool InputHexadecimal(const char *label, u32 *value, ImGuiInputTextFlags flags) {
|
||||||
return InputIntegerPrefix(label, "0x", value, ImGuiDataType_U32, "%lX", flags | ImGuiInputTextFlags_CharsHexadecimal);
|
return InputIntegerPrefix(label, "0x", value, ImGuiDataType_U32, "%X", flags | ImGuiInputTextFlags_CharsHexadecimal);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InputHexadecimal(const char *label, u64 *value, ImGuiInputTextFlags flags) {
|
bool InputHexadecimal(const char *label, u64 *value, ImGuiInputTextFlags flags) {
|
||||||
@@ -951,11 +971,14 @@ namespace ImGuiExt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool InputTextIcon(const char *label, const char *icon, std::string &buffer, ImGuiInputTextFlags flags) {
|
bool InputTextIcon(const char *label, const char *icon, std::string &buffer, ImGuiInputTextFlags flags) {
|
||||||
|
return InputTextIconHint(label, icon, nullptr, buffer, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InputTextIconHint(const char* label, const char *icon, const char *hint, std::string &buffer, ImGuiInputTextFlags flags) {
|
||||||
auto window = GetCurrentWindow();
|
auto window = GetCurrentWindow();
|
||||||
const ImGuiID id = window->GetID(label);
|
const ImGuiID id = window->GetID(label);
|
||||||
const ImGuiStyle &style = GImGui->Style;
|
const ImGuiStyle &style = GImGui->Style;
|
||||||
|
|
||||||
|
|
||||||
const ImVec2 label_size = CalcTextSize(label, nullptr, true);
|
const ImVec2 label_size = CalcTextSize(label, nullptr, true);
|
||||||
const ImVec2 icon_frame_size = CalcTextSize(icon) + style.FramePadding * 2.0F;
|
const ImVec2 icon_frame_size = CalcTextSize(icon) + style.FramePadding * 2.0F;
|
||||||
const ImVec2 frame_size = CalcItemSize(ImVec2(0, 0), icon_frame_size.x, label_size.y + style.FramePadding.y * 2.0F);
|
const ImVec2 frame_size = CalcItemSize(ImVec2(0, 0), icon_frame_size.x, label_size.y + style.FramePadding.y * 2.0F);
|
||||||
@@ -963,12 +986,14 @@ namespace ImGuiExt {
|
|||||||
|
|
||||||
SetCursorPosX(GetCursorPosX() + frame_size.x);
|
SetCursorPosX(GetCursorPosX() + frame_size.x);
|
||||||
|
|
||||||
bool value_changed = InputTextEx(label, nullptr, buffer.data(), buffer.size() + 1, ImVec2(CalcItemWidth(), label_size.y + style.FramePadding.y * 2.0F), ImGuiInputTextFlags_CallbackResize | flags, UpdateStringSizeCallback, &buffer);
|
float width_adjustment = window->DC.ItemWidth < 0 ? 0 : icon_frame_size.x;
|
||||||
|
|
||||||
|
bool value_changed = InputTextEx(label, hint, buffer.data(), buffer.size() + 1, ImVec2(CalcItemWidth() - width_adjustment, label_size.y + style.FramePadding.y * 2.0F), ImGuiInputTextFlags_CallbackResize | flags, UpdateStringSizeCallback, &buffer);
|
||||||
|
|
||||||
if (value_changed)
|
if (value_changed)
|
||||||
MarkItemEdited(GImGui->LastItemData.ID);
|
MarkItemEdited(GImGui->LastItemData.ID);
|
||||||
|
|
||||||
RenderNavHighlight(frame_bb, id);
|
RenderNavCursor(frame_bb, id);
|
||||||
RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding);
|
RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding);
|
||||||
|
|
||||||
RenderFrame(frame_bb.Min, frame_bb.Min + icon_frame_size, GetColorU32(ImGuiCol_TableBorderStrong), true, style.FrameRounding);
|
RenderFrame(frame_bb.Min, frame_bb.Min + icon_frame_size, GetColorU32(ImGuiCol_TableBorderStrong), true, style.FrameRounding);
|
||||||
@@ -994,7 +1019,6 @@ namespace ImGuiExt {
|
|||||||
if ((flags & (ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsScientific)) == 0)
|
if ((flags & (ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsScientific)) == 0)
|
||||||
flags |= ImGuiInputTextFlags_CharsDecimal;
|
flags |= ImGuiInputTextFlags_CharsDecimal;
|
||||||
flags |= ImGuiInputTextFlags_AutoSelectAll;
|
flags |= ImGuiInputTextFlags_AutoSelectAll;
|
||||||
flags |= ImGuiInputTextFlags_NoMarkEdited; // We call MarkItemEdited() ourselves by comparing the actual data rather than the string.
|
|
||||||
|
|
||||||
if (ImGui::InputText(label, buf, IM_ARRAYSIZE(buf), flags, callback, user_data))
|
if (ImGui::InputText(label, buf, IM_ARRAYSIZE(buf), flags, callback, user_data))
|
||||||
value_changed = DataTypeApplyFromText(buf, data_type, p_data, format);
|
value_changed = DataTypeApplyFromText(buf, data_type, p_data, format);
|
||||||
@@ -1044,7 +1068,7 @@ namespace ImGuiExt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ImRect check_bb(pos, pos + size);
|
const ImRect check_bb(pos, pos + size);
|
||||||
RenderNavHighlight(total_bb, id);
|
RenderNavCursor(total_bb, id);
|
||||||
RenderFrame(check_bb.Min, check_bb.Max, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding);
|
RenderFrame(check_bb.Min, check_bb.Max, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding);
|
||||||
|
|
||||||
RenderText(check_bb.Min + style.FramePadding, *v ? "1" : "0");
|
RenderText(check_bb.Min + style.FramePadding, *v ? "1" : "0");
|
||||||
@@ -1147,17 +1171,19 @@ namespace ImGuiExt {
|
|||||||
return toggled;
|
return toggled;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextOverlay(const char *text, ImVec2 pos) {
|
void TextOverlay(const char *text, ImVec2 pos, float maxWidth) {
|
||||||
const auto textSize = CalcTextSize(text);
|
const auto textSize = CalcTextSize(text, nullptr, false, maxWidth);
|
||||||
const auto textPos = pos - textSize / 2;
|
const auto textPos = pos - textSize / 2;
|
||||||
const auto margin = GetStyle().FramePadding * 2;
|
const auto margin = GetStyle().FramePadding * 2;
|
||||||
const auto textRect = ImRect(textPos - margin, textPos + textSize + margin);
|
const auto textRect = ImRect(textPos - margin, textPos + textSize + margin);
|
||||||
|
|
||||||
auto drawList = GetForegroundDrawList();
|
auto drawList = GetWindowDrawList();
|
||||||
|
|
||||||
|
drawList->AddDrawCmd();
|
||||||
drawList->AddRectFilled(textRect.Min, textRect.Max, GetColorU32(ImGuiCol_WindowBg) | 0xFF000000);
|
drawList->AddRectFilled(textRect.Min, textRect.Max, GetColorU32(ImGuiCol_WindowBg) | 0xFF000000);
|
||||||
drawList->AddRect(textRect.Min, textRect.Max, GetColorU32(ImGuiCol_Border));
|
drawList->AddRect(textRect.Min, textRect.Max, GetColorU32(ImGuiCol_Border));
|
||||||
drawList->AddText(textPos, GetColorU32(ImGuiCol_Text), text);
|
drawList->AddDrawCmd();
|
||||||
|
drawList->AddText(nullptr, 0.0F, textPos, GetColorU32(ImGuiCol_Text), text, nullptr, maxWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BeginBox() {
|
bool BeginBox() {
|
||||||
@@ -1179,7 +1205,7 @@ namespace ImGuiExt {
|
|||||||
|
|
||||||
bool result = false;
|
bool result = false;
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 5.0F);
|
ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 5.0F);
|
||||||
if (ImGui::BeginChild(hex::format("{}##SubWindow", label).c_str(), size, ImGuiChildFlags_Border | ImGuiChildFlags_AutoResizeY | flags, hasMenuBar ? ImGuiWindowFlags_MenuBar : ImGuiWindowFlags_None)) {
|
if (ImGui::BeginChild(hex::format("{}##SubWindow", label).c_str(), size, ImGuiChildFlags_Borders | ImGuiChildFlags_AutoResizeY | flags, hasMenuBar ? ImGuiWindowFlags_MenuBar : ImGuiWindowFlags_None)) {
|
||||||
result = true;
|
result = true;
|
||||||
|
|
||||||
if (hasMenuBar && ImGui::BeginMenuBar()) {
|
if (hasMenuBar && ImGui::BeginMenuBar()) {
|
||||||
|
|||||||
2
lib/third_party/capstone
vendored
2
lib/third_party/capstone
vendored
Submodule lib/third_party/capstone updated: 097c04d941...5cca00533d
2
lib/third_party/fmt
vendored
2
lib/third_party/fmt
vendored
Submodule lib/third_party/fmt updated: 67c0c0c09c...0e8aad961d
3
lib/third_party/imgui/CMakeLists.txt
vendored
3
lib/third_party/imgui/CMakeLists.txt
vendored
@@ -8,8 +8,9 @@ add_library(imgui_all_includes INTERFACE)
|
|||||||
add_subdirectory(imgui)
|
add_subdirectory(imgui)
|
||||||
add_subdirectory(cimgui)
|
add_subdirectory(cimgui)
|
||||||
add_subdirectory(implot)
|
add_subdirectory(implot)
|
||||||
|
add_subdirectory(implot3d)
|
||||||
add_subdirectory(imnodes)
|
add_subdirectory(imnodes)
|
||||||
add_subdirectory(custom)
|
add_subdirectory(custom)
|
||||||
add_subdirectory(ColorTextEditor)
|
add_subdirectory(ColorTextEditor)
|
||||||
|
|
||||||
set(IMGUI_LIBRARIES imgui_imgui imgui_cimgui imgui_implot imgui_imnodes imgui_custom imgui_color_text_editor PARENT_SCOPE)
|
set(IMGUI_LIBRARIES imgui_imgui imgui_cimgui imgui_implot imgui_implot3d imgui_imnodes imgui_custom imgui_color_text_editor PARENT_SCOPE)
|
||||||
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16)
|
|||||||
# https://github.com/BalazsJako/ImGuiColorTextEdit
|
# https://github.com/BalazsJako/ImGuiColorTextEdit
|
||||||
project(imgui_color_text_editor)
|
project(imgui_color_text_editor)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
|
|
||||||
if (NOT IMHEX_EXTERNAL_PLUGIN_BUILD)
|
if (NOT IMHEX_EXTERNAL_PLUGIN_BUILD)
|
||||||
add_library(imgui_color_text_editor OBJECT
|
add_library(imgui_color_text_editor OBJECT
|
||||||
|
|||||||
@@ -4,11 +4,13 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <functional>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
|
#include "imgui_internal.h"
|
||||||
|
|
||||||
class TextEditor
|
class TextEditor
|
||||||
{
|
{
|
||||||
@@ -74,8 +76,8 @@ public:
|
|||||||
Coordinates() : mLine(0), mColumn(0) {}
|
Coordinates() : mLine(0), mColumn(0) {}
|
||||||
Coordinates(int aLine, int aColumn) : mLine(aLine), mColumn(aColumn)
|
Coordinates(int aLine, int aColumn) : mLine(aLine), mColumn(aColumn)
|
||||||
{
|
{
|
||||||
assert(aLine >= 0);
|
IM_ASSERT(aLine >= 0);
|
||||||
assert(aColumn >= 0);
|
IM_ASSERT(aColumn >= 0);
|
||||||
}
|
}
|
||||||
static Coordinates Invalid() { static Coordinates invalid(-1, -1); return invalid; }
|
static Coordinates Invalid() { static Coordinates invalid(-1, -1); return invalid; }
|
||||||
|
|
||||||
@@ -128,15 +130,86 @@ public:
|
|||||||
std::string mDeclaration;
|
std::string mDeclaration;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::string String;
|
using String = std::string;
|
||||||
typedef std::unordered_map<std::string, Identifier> Identifiers;
|
using Identifiers = std::unordered_map<std::string, Identifier>;
|
||||||
typedef std::unordered_set<std::string> Keywords;
|
using Keywords = std::unordered_set<std::string> ;
|
||||||
typedef std::map<int, std::string> ErrorMarkers;
|
using ErrorMarkers = std::map<Coordinates, std::pair<uint32_t ,std::string>>;
|
||||||
typedef std::unordered_set<int> Breakpoints;
|
using Breakpoints = std::unordered_set<uint32_t>;
|
||||||
typedef std::array<ImU32, (unsigned)PaletteIndex::Max> Palette;
|
using Palette = std::array<ImU32, (uint32_t)PaletteIndex::Max>;
|
||||||
typedef uint8_t Char;
|
using Char = uint8_t ;
|
||||||
|
|
||||||
struct Glyph
|
class ActionableBox {
|
||||||
|
|
||||||
|
ImRect mBox;
|
||||||
|
public:
|
||||||
|
ActionableBox()=default;
|
||||||
|
explicit ActionableBox(const ImRect &box) : mBox(box) {}
|
||||||
|
virtual bool trigger() {
|
||||||
|
return ImGui::IsMouseHoveringRect(mBox.Min,mBox.Max);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void callback() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CursorChangeBox : public ActionableBox {
|
||||||
|
public:
|
||||||
|
CursorChangeBox()=default;
|
||||||
|
explicit CursorChangeBox(const ImRect &box) : ActionableBox(box) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void callback() override {
|
||||||
|
ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ErrorGotoBox : public ActionableBox {
|
||||||
|
Coordinates mPos;
|
||||||
|
public:
|
||||||
|
ErrorGotoBox()=default;
|
||||||
|
ErrorGotoBox(const ImRect &box, const Coordinates &pos, TextEditor *editor) : ActionableBox(box), mPos(pos), mEditor(editor) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool trigger() override {
|
||||||
|
return ActionableBox::trigger() && ImGui::IsMouseClicked(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void callback() override {
|
||||||
|
mEditor->JumpToCoords(mPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
TextEditor *mEditor;
|
||||||
|
};
|
||||||
|
|
||||||
|
using ErrorGotoBoxes = std::map<Coordinates, ErrorGotoBox>;
|
||||||
|
using CursorBoxes = std::map<Coordinates, CursorChangeBox>;
|
||||||
|
|
||||||
|
class ErrorHoverBox : public ActionableBox {
|
||||||
|
Coordinates mPos;
|
||||||
|
std::string mErrorText;
|
||||||
|
public:
|
||||||
|
ErrorHoverBox()=default;
|
||||||
|
ErrorHoverBox(const ImRect &box, const Coordinates &pos,const char *errorText) : ActionableBox(box), mPos(pos), mErrorText(errorText) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void callback() override {
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.2f, 0.2f, 1.0f));
|
||||||
|
ImGui::Text("Error at line %d:", mPos.mLine);
|
||||||
|
ImGui::PopStyleColor();
|
||||||
|
ImGui::Separator();
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.5f, 0.5f, 0.2f, 1.0f));
|
||||||
|
ImGui::TextUnformatted(mErrorText.c_str());
|
||||||
|
ImGui::PopStyleColor();
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
using ErrorHoverBoxes = std::map<Coordinates, ErrorHoverBox>;
|
||||||
|
|
||||||
|
struct Glyph
|
||||||
{
|
{
|
||||||
Char mChar;
|
Char mChar;
|
||||||
PaletteIndex mColorIndex = PaletteIndex::Default;
|
PaletteIndex mColorIndex = PaletteIndex::Default;
|
||||||
@@ -187,6 +260,28 @@ public:
|
|||||||
static const LanguageDefinition& AngelScript();
|
static const LanguageDefinition& AngelScript();
|
||||||
static const LanguageDefinition& Lua();
|
static const LanguageDefinition& Lua();
|
||||||
};
|
};
|
||||||
|
void ClearErrorMarkers() {
|
||||||
|
mErrorMarkers.clear();
|
||||||
|
mErrorHoverBoxes.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearGotoBoxes() {
|
||||||
|
mErrorGotoBoxes.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearCursorBoxes() {
|
||||||
|
mCursorBoxes.clear();
|
||||||
|
}
|
||||||
|
void ClearActionables() {
|
||||||
|
ClearErrorMarkers();
|
||||||
|
ClearGotoBoxes();
|
||||||
|
ClearCursorBoxes();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Selection {
|
||||||
|
Coordinates mStart;
|
||||||
|
Coordinates mEnd;
|
||||||
|
};
|
||||||
|
|
||||||
TextEditor();
|
TextEditor();
|
||||||
~TextEditor();
|
~TextEditor();
|
||||||
@@ -198,28 +293,68 @@ public:
|
|||||||
static void SetPalette(const Palette& aValue);
|
static void SetPalette(const Palette& aValue);
|
||||||
|
|
||||||
void SetErrorMarkers(const ErrorMarkers& aMarkers) { mErrorMarkers = aMarkers; }
|
void SetErrorMarkers(const ErrorMarkers& aMarkers) { mErrorMarkers = aMarkers; }
|
||||||
|
Breakpoints &GetBreakpoints() { return mBreakpoints; }
|
||||||
void SetBreakpoints(const Breakpoints& aMarkers) { mBreakpoints = aMarkers; }
|
void SetBreakpoints(const Breakpoints& aMarkers) { mBreakpoints = aMarkers; }
|
||||||
|
ImVec2 Underwaves( ImVec2 pos, uint32_t nChars, ImColor color= ImGui::GetStyleColorVec4(ImGuiCol_Text), const ImVec2 &size_arg= ImVec2(0, 0));
|
||||||
|
|
||||||
void Render(const char* aTitle, const ImVec2& aSize = ImVec2(), bool aBorder = false);
|
void Render(const char* aTitle, const ImVec2& aSize = ImVec2(), bool aBorder = false);
|
||||||
void SetText(const std::string& aText);
|
void SetText(const std::string& aText);
|
||||||
|
void JumpToLine(int line);
|
||||||
|
void JumpToCoords(const Coordinates &coords);
|
||||||
std::string GetText() const;
|
std::string GetText() const;
|
||||||
|
bool isEmpty() const {
|
||||||
|
auto text = GetText();
|
||||||
|
return text.empty() || text == "\n";
|
||||||
|
}
|
||||||
|
void SetTopLine();
|
||||||
|
void SetScrollY();
|
||||||
void SetTextLines(const std::vector<std::string>& aLines);
|
void SetTextLines(const std::vector<std::string>& aLines);
|
||||||
std::vector<std::string> GetTextLines() const;
|
std::vector<std::string> GetTextLines() const;
|
||||||
|
|
||||||
std::string GetSelectedText() const;
|
std::string GetSelectedText() const;
|
||||||
std::string GetCurrentLineText()const;
|
std::string GetCurrentLineText()const;
|
||||||
|
|
||||||
|
std::string GetLineText(int line)const;
|
||||||
|
void SetSourceCodeEditor(TextEditor *editor) { mSourceCodeEditor = editor; }
|
||||||
|
TextEditor *GetSourceCodeEditor() {
|
||||||
|
if(mSourceCodeEditor!=nullptr)
|
||||||
|
return mSourceCodeEditor;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
class FindReplaceHandler;
|
class FindReplaceHandler;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
void AddClickableText(std::string text) {
|
||||||
|
mClickableText.push_back(text);
|
||||||
|
}
|
||||||
|
void ClearClickableText() {
|
||||||
|
mClickableText.clear();
|
||||||
|
}
|
||||||
FindReplaceHandler *GetFindReplaceHandler() { return &mFindReplaceHandler; }
|
FindReplaceHandler *GetFindReplaceHandler() { return &mFindReplaceHandler; }
|
||||||
int GetTotalLines() const { return (int)mLines.size(); }
|
int GetTotalLines() const { return (int)mLines.size(); }
|
||||||
bool IsOverwrite() const { return mOverwrite; }
|
bool IsOverwrite() const { return mOverwrite; }
|
||||||
|
void SetTopMarginChanged(int newMargin) {
|
||||||
|
mNewTopMargin = newMargin;
|
||||||
|
mTopMarginChanged = true;
|
||||||
|
}
|
||||||
|
void setFocusAtCoords(const Coordinates &coords) {
|
||||||
|
mFocusAtCoords = coords;
|
||||||
|
mUpdateFocus = true;
|
||||||
|
}
|
||||||
|
void SetOverwrite(bool aValue) { mOverwrite = aValue; }
|
||||||
|
|
||||||
|
std::string ReplaceStrings(std::string string, const std::string &search, const std::string &replace);
|
||||||
|
std::vector<std::string> SplitString(const std::string &string, const std::string &delimiter, bool removeEmpty);
|
||||||
|
std::string ReplaceTabsWithSpaces(const std::string& string, uint32_t tabSize);
|
||||||
|
std::string PreprocessText(const std::string &code);
|
||||||
|
|
||||||
void SetReadOnly(bool aValue);
|
void SetReadOnly(bool aValue);
|
||||||
bool IsReadOnly() const { return mReadOnly; }
|
bool IsReadOnly() const { return mReadOnly; }
|
||||||
bool IsTextChanged() const { return mTextChanged; }
|
bool IsTextChanged() const { return mTextChanged; }
|
||||||
bool IsCursorPositionChanged() const { return mCursorPositionChanged; }
|
bool IsCursorPositionChanged() const { return mCursorPositionChanged; }
|
||||||
|
bool IsBreakpointsChanged() const { return mBreakPointsChanged; }
|
||||||
|
void ClearBreakpointsChanged() { mBreakPointsChanged = false; }
|
||||||
|
|
||||||
void SetShowCursor(bool aValue) { mShowCursor = aValue; }
|
void SetShowCursor(bool aValue) { mShowCursor = aValue; }
|
||||||
void SetShowLineNumbers(bool aValue) { mShowLineNumbers = aValue; }
|
void SetShowLineNumbers(bool aValue) { mShowLineNumbers = aValue; }
|
||||||
@@ -230,6 +365,9 @@ public:
|
|||||||
Coordinates GetCursorPosition() const { return GetActualCursorCoordinates(); }
|
Coordinates GetCursorPosition() const { return GetActualCursorCoordinates(); }
|
||||||
void SetCursorPosition(const Coordinates& aPosition);
|
void SetCursorPosition(const Coordinates& aPosition);
|
||||||
|
|
||||||
|
bool RaiseContextMenu() { return mRaiseContextMenu; }
|
||||||
|
void ClearRaiseContextMenu() { mRaiseContextMenu = false; }
|
||||||
|
|
||||||
inline void SetHandleMouseInputs (bool aValue){ mHandleMouseInputs = aValue;}
|
inline void SetHandleMouseInputs (bool aValue){ mHandleMouseInputs = aValue;}
|
||||||
inline bool IsHandleMouseInputsEnabled() const { return mHandleKeyboardInputs; }
|
inline bool IsHandleMouseInputsEnabled() const { return mHandleKeyboardInputs; }
|
||||||
|
|
||||||
@@ -260,6 +398,7 @@ public:
|
|||||||
void SetSelectionStart(const Coordinates& aPosition);
|
void SetSelectionStart(const Coordinates& aPosition);
|
||||||
void SetSelectionEnd(const Coordinates& aPosition);
|
void SetSelectionEnd(const Coordinates& aPosition);
|
||||||
void SetSelection(const Coordinates& aStart, const Coordinates& aEnd, SelectionMode aMode = SelectionMode::Normal);
|
void SetSelection(const Coordinates& aStart, const Coordinates& aEnd, SelectionMode aMode = SelectionMode::Normal);
|
||||||
|
Selection GetSelection() const;
|
||||||
void SelectWordUnderCursor();
|
void SelectWordUnderCursor();
|
||||||
void SelectAll();
|
void SelectAll();
|
||||||
bool HasSelection() const;
|
bool HasSelection() const;
|
||||||
@@ -268,14 +407,19 @@ public:
|
|||||||
void Cut();
|
void Cut();
|
||||||
void Paste();
|
void Paste();
|
||||||
void Delete();
|
void Delete();
|
||||||
|
float GetPageSize() const;
|
||||||
|
|
||||||
ImVec2 &GetCharAdvance() { return mCharAdvance; }
|
ImVec2 &GetCharAdvance() { return mCharAdvance; }
|
||||||
|
|
||||||
bool CanUndo() const;
|
bool CanUndo();
|
||||||
bool CanRedo() const;
|
bool CanRedo() const;
|
||||||
void Undo(int aSteps = 1);
|
void Undo(int aSteps = 1);
|
||||||
void Redo(int aSteps = 1);
|
void Redo(int aSteps = 1);
|
||||||
|
|
||||||
|
void DeleteWordLeft();
|
||||||
|
void DeleteWordRight();
|
||||||
|
void Backspace();
|
||||||
|
|
||||||
static const Palette& GetDarkPalette();
|
static const Palette& GetDarkPalette();
|
||||||
static const Palette& GetLightPalette();
|
static const Palette& GetLightPalette();
|
||||||
static const Palette& GetRetroBluePalette();
|
static const Palette& GetRetroBluePalette();
|
||||||
@@ -297,7 +441,7 @@ public:
|
|||||||
FindReplaceHandler();
|
FindReplaceHandler();
|
||||||
typedef std::vector<EditorState> Matches;
|
typedef std::vector<EditorState> Matches;
|
||||||
Matches &GetMatches() { return mMatches; }
|
Matches &GetMatches() { return mMatches; }
|
||||||
bool FindNext(TextEditor *editor,bool wrapAround);
|
bool FindNext(TextEditor *editor);
|
||||||
unsigned FindMatch(TextEditor *editor,bool isNex);
|
unsigned FindMatch(TextEditor *editor,bool isNex);
|
||||||
bool Replace(TextEditor *editor,bool right);
|
bool Replace(TextEditor *editor,bool right);
|
||||||
bool ReplaceAll(TextEditor *editor);
|
bool ReplaceAll(TextEditor *editor);
|
||||||
@@ -400,7 +544,6 @@ private:
|
|||||||
void ColorizeInternal();
|
void ColorizeInternal();
|
||||||
float TextDistanceToLineStart(const Coordinates& aFrom) const;
|
float TextDistanceToLineStart(const Coordinates& aFrom) const;
|
||||||
void EnsureCursorVisible();
|
void EnsureCursorVisible();
|
||||||
int GetPageSize() const;
|
|
||||||
std::string GetText(const Coordinates& aStart, const Coordinates& aEnd) const;
|
std::string GetText(const Coordinates& aStart, const Coordinates& aEnd) const;
|
||||||
Coordinates GetActualCursorCoordinates() const;
|
Coordinates GetActualCursorCoordinates() const;
|
||||||
Coordinates SanitizeCoordinates(const Coordinates& aValue) const;
|
Coordinates SanitizeCoordinates(const Coordinates& aValue) const;
|
||||||
@@ -412,10 +555,13 @@ private:
|
|||||||
Coordinates FindWordStart(const Coordinates& aFrom) const;
|
Coordinates FindWordStart(const Coordinates& aFrom) const;
|
||||||
Coordinates FindWordEnd(const Coordinates& aFrom) const;
|
Coordinates FindWordEnd(const Coordinates& aFrom) const;
|
||||||
Coordinates FindNextWord(const Coordinates& aFrom) const;
|
Coordinates FindNextWord(const Coordinates& aFrom) const;
|
||||||
|
Coordinates StringIndexToCoordinates(int aIndex, const std::string &str) const;
|
||||||
int GetCharacterIndex(const Coordinates& aCoordinates) const;
|
int GetCharacterIndex(const Coordinates& aCoordinates) const;
|
||||||
int GetCharacterColumn(int aLine, int aIndex) const;
|
int GetCharacterColumn(int aLine, int aIndex) const;
|
||||||
int GetLineCharacterCount(int aLine) const;
|
int GetLineCharacterCount(int aLine) const;
|
||||||
unsigned long long GetLineByteCount(int aLine) const;
|
int Utf8CharsToBytes(const Coordinates &aCoordinates) const;
|
||||||
|
int GetLongestLineLength() const;
|
||||||
|
unsigned long long GetLineByteCount(int aLine) const;
|
||||||
int GetStringCharacterCount(std::string str) const;
|
int GetStringCharacterCount(std::string str) const;
|
||||||
int GetLineMaxColumn(int aLine) const;
|
int GetLineMaxColumn(int aLine) const;
|
||||||
bool IsOnWordBoundary(const Coordinates& aAt) const;
|
bool IsOnWordBoundary(const Coordinates& aAt) const;
|
||||||
@@ -423,7 +569,6 @@ private:
|
|||||||
void RemoveLine(int aIndex);
|
void RemoveLine(int aIndex);
|
||||||
Line& InsertLine(int aIndex);
|
Line& InsertLine(int aIndex);
|
||||||
void EnterCharacter(ImWchar aChar, bool aShift);
|
void EnterCharacter(ImWchar aChar, bool aShift);
|
||||||
void Backspace();
|
|
||||||
void DeleteSelection();
|
void DeleteSelection();
|
||||||
std::string GetWordUnderCursor() const;
|
std::string GetWordUnderCursor() const;
|
||||||
std::string GetWordAt(const Coordinates& aCoords) const;
|
std::string GetWordAt(const Coordinates& aCoords) const;
|
||||||
@@ -432,50 +577,72 @@ private:
|
|||||||
|
|
||||||
void HandleKeyboardInputs();
|
void HandleKeyboardInputs();
|
||||||
void HandleMouseInputs();
|
void HandleMouseInputs();
|
||||||
void Render();
|
void RenderText(const char *aTitle, const ImVec2 &lineNumbersStartPos, const ImVec2 &textEditorSize);
|
||||||
|
|
||||||
float mLineSpacing;
|
float mLineSpacing = 1.0F;
|
||||||
Lines mLines;
|
Lines mLines;
|
||||||
EditorState mState;
|
EditorState mState = {};
|
||||||
UndoBuffer mUndoBuffer;
|
UndoBuffer mUndoBuffer;
|
||||||
int mUndoIndex;
|
int mUndoIndex = 0;
|
||||||
bool mScrollToBottom;
|
bool mScrollToBottom = false;
|
||||||
float mTopMargin;
|
float mTopMargin = 0.0F;
|
||||||
|
float mNewTopMargin = 0.0F;
|
||||||
|
float mOldTopMargin = 0.0F;
|
||||||
|
bool mTopMarginChanged = false;
|
||||||
|
|
||||||
int mTabSize;
|
int mTabSize = 4;
|
||||||
bool mOverwrite;
|
bool mOverwrite = false;
|
||||||
bool mReadOnly;
|
bool mReadOnly = false;
|
||||||
bool mWithinRender;
|
bool mWithinRender = false;
|
||||||
bool mScrollToCursor;
|
bool mScrollToCursor = false;
|
||||||
bool mScrollToTop;
|
bool mScrollToTop = false;
|
||||||
bool mTextChanged;
|
bool mTextChanged = false;
|
||||||
bool mColorizerEnabled;
|
bool mColorizerEnabled = true;
|
||||||
float mTextStart; // position (in pixels) where a code line starts relative to the left of the TextEditor.
|
float mLineNumberFieldWidth = 0.0F;
|
||||||
int mLeftMargin;
|
float mLongest = 0.0F;
|
||||||
bool mCursorPositionChanged;
|
float mTextStart = 20.0F; // position (in pixels) where a code line starts relative to the left of the TextEditor.
|
||||||
int mColorRangeMin, mColorRangeMax;
|
float mLeftMargin = 10.0;
|
||||||
SelectionMode mSelectionMode;
|
float mTopLine = 0.0F;
|
||||||
bool mHandleKeyboardInputs;
|
bool mSetTopLine = false;
|
||||||
bool mHandleMouseInputs;
|
bool mCursorPositionChanged = false;
|
||||||
bool mIgnoreImGuiChild;
|
bool mBreakPointsChanged = false;
|
||||||
bool mShowWhitespaces;
|
int mColorRangeMin = 0, mColorRangeMax = 0;
|
||||||
|
SelectionMode mSelectionMode = SelectionMode::Normal;
|
||||||
|
bool mHandleKeyboardInputs = true;
|
||||||
|
bool mHandleMouseInputs = true;
|
||||||
|
bool mIgnoreImGuiChild = false;
|
||||||
|
bool mShowWhitespaces = true;
|
||||||
|
|
||||||
static Palette sPaletteBase;
|
static Palette sPaletteBase;
|
||||||
Palette mPalette;
|
Palette mPalette = {};
|
||||||
LanguageDefinition mLanguageDefinition;
|
LanguageDefinition mLanguageDefinition = {};
|
||||||
RegexList mRegexList;
|
RegexList mRegexList;
|
||||||
bool mCheckComments;
|
bool mCheckComments = true;
|
||||||
Breakpoints mBreakpoints;
|
Breakpoints mBreakpoints = {};
|
||||||
ErrorMarkers mErrorMarkers;
|
ErrorMarkers mErrorMarkers = {};
|
||||||
ImVec2 mCharAdvance;
|
ErrorHoverBoxes mErrorHoverBoxes = {};
|
||||||
Coordinates mInteractiveStart, mInteractiveEnd;
|
ErrorGotoBoxes mErrorGotoBoxes = {};
|
||||||
|
CursorBoxes mCursorBoxes = {};
|
||||||
|
ImVec2 mCharAdvance = {};
|
||||||
|
Coordinates mInteractiveStart = {}, mInteractiveEnd = {};
|
||||||
std::string mLineBuffer;
|
std::string mLineBuffer;
|
||||||
uint64_t mStartTime;
|
uint64_t mStartTime = 0;
|
||||||
std::vector<std::string> mDefines;
|
std::vector<std::string> mDefines;
|
||||||
|
TextEditor *mSourceCodeEditor = nullptr;
|
||||||
|
float mSavedScrollY = 0;
|
||||||
|
float mShiftedScrollY = 0;
|
||||||
|
float mScrollY = 0;
|
||||||
|
float mScrollYIncrement = 0.0F;
|
||||||
|
bool mSetScrollY = false;
|
||||||
|
float mNumberOfLinesDisplayed = 0;
|
||||||
|
float mLastClick = -1.0F;
|
||||||
|
bool mShowCursor = true;
|
||||||
|
bool mShowLineNumbers = true;
|
||||||
|
bool mRaiseContextMenu = false;
|
||||||
|
Coordinates mFocusAtCoords = {};
|
||||||
|
bool mUpdateFocus = false;
|
||||||
|
|
||||||
float mLastClick;
|
std::vector<std::string> mClickableText;
|
||||||
bool mShowCursor;
|
|
||||||
bool mShowLineNumbers;
|
|
||||||
|
|
||||||
static const int sCursorBlinkInterval;
|
static const int sCursorBlinkInterval;
|
||||||
static const int sCursorBlinkOnTime;
|
static const int sCursorBlinkOnTime;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
751
lib/third_party/imgui/cimgui/include/cimgui.h
vendored
751
lib/third_party/imgui/cimgui/include/cimgui.h
vendored
File diff suppressed because it is too large
Load Diff
589
lib/third_party/imgui/cimgui/source/cimgui.cpp
vendored
589
lib/third_party/imgui/cimgui/source/cimgui.cpp
vendored
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,7 @@
|
|||||||
// Implemented features:
|
// Implemented features:
|
||||||
// [X] Platform: Clipboard support.
|
// [X] Platform: Clipboard support.
|
||||||
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only).
|
// [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 will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
|
// [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: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
|
||||||
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+).
|
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+).
|
||||||
// [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
|
// [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
|
||||||
@@ -28,15 +28,17 @@
|
|||||||
struct GLFWwindow;
|
struct GLFWwindow;
|
||||||
struct GLFWmonitor;
|
struct GLFWmonitor;
|
||||||
|
|
||||||
|
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||||
IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window, bool install_callbacks);
|
IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window, bool install_callbacks);
|
||||||
IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks);
|
IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks);
|
||||||
IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOther(GLFWwindow* window, bool install_callbacks);
|
IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOther(GLFWwindow* window, bool install_callbacks);
|
||||||
IMGUI_IMPL_API void ImGui_ImplGlfw_Shutdown();
|
IMGUI_IMPL_API void ImGui_ImplGlfw_Shutdown();
|
||||||
IMGUI_IMPL_API void ImGui_ImplGlfw_NewFrame();
|
IMGUI_IMPL_API void ImGui_ImplGlfw_NewFrame();
|
||||||
|
|
||||||
// Emscripten related initialization phase methods
|
// Emscripten related initialization phase methods (call after ImGui_ImplGlfw_InitForOpenGL)
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
IMGUI_IMPL_API void ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback(const char* canvas_selector);
|
IMGUI_IMPL_API void ImGui_ImplGlfw_InstallEmscriptenCallbacks(GLFWwindow* window, const char* canvas_selector);
|
||||||
|
//static inline void ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback(const char* canvas_selector) { ImGui_ImplGlfw_InstallEmscriptenCallbacks(nullptr, canvas_selector); } } // Renamed in 1.91.0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// GLFW callbacks install
|
// GLFW callbacks install
|
||||||
@@ -59,4 +61,7 @@ IMGUI_IMPL_API void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key,
|
|||||||
IMGUI_IMPL_API void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c);
|
IMGUI_IMPL_API void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c);
|
||||||
IMGUI_IMPL_API void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor* monitor, int event);
|
IMGUI_IMPL_API void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor* monitor, int event);
|
||||||
|
|
||||||
|
// GLFW helpers
|
||||||
|
IMGUI_IMPL_API void ImGui_ImplGlfw_Sleep(int milliseconds);
|
||||||
|
|
||||||
#endif // #ifndef IMGUI_DISABLE
|
#endif // #ifndef IMGUI_DISABLE
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
// Implemented features:
|
// Implemented features:
|
||||||
// [X] Platform: Clipboard support.
|
// [X] Platform: Clipboard support.
|
||||||
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only).
|
// [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 will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
|
// [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: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
|
||||||
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+).
|
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+).
|
||||||
// [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
|
// [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
|
||||||
@@ -21,9 +21,23 @@
|
|||||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||||
// - Introduction, links and more at the top of imgui.cpp
|
// - Introduction, links and more at the top of imgui.cpp
|
||||||
|
|
||||||
|
// About Emscripten support:
|
||||||
|
// - Emscripten provides its own GLFW (3.2.1) implementation (syntax: "-sUSE_GLFW=3"), but Joystick is broken and several features are not supported (multiple windows, clipboard, timer, etc.)
|
||||||
|
// - A third-party Emscripten GLFW (3.4.0) implementation (syntax: "--use-port=contrib.glfw3") fixes the Joystick issue and implements all relevant features for the browser.
|
||||||
|
// See https://github.com/pongasoft/emscripten-glfw/blob/master/docs/Comparison.md for details.
|
||||||
|
|
||||||
// CHANGELOG
|
// CHANGELOG
|
||||||
// (minor and older changes stripped away, please see git history for details)
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
// 2024-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
// 2024-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
||||||
|
// 2024-11-05: [Docking] Added Linux workaround for spurious mouse up events emitted while dragging and creating new viewport. (#3158, #7733, #7922)
|
||||||
|
// 2024-08-22: moved some OS/backend related function pointers from ImGuiIO to ImGuiPlatformIO:
|
||||||
|
// - io.GetClipboardTextFn -> platform_io.Platform_GetClipboardTextFn
|
||||||
|
// - io.SetClipboardTextFn -> platform_io.Platform_SetClipboardTextFn
|
||||||
|
// - io.PlatformOpenInShellFn -> platform_io.Platform_OpenInShellFn
|
||||||
|
// 2024-07-31: Added ImGui_ImplGlfw_Sleep() helper function for usage by our examples app, since GLFW doesn't provide one.
|
||||||
|
// 2024-07-08: *BREAKING* Renamed ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback to ImGui_ImplGlfw_InstallEmscriptenCallbacks(), added GLFWWindow* parameter.
|
||||||
|
// 2024-07-08: Emscripten: Added support for GLFW3 contrib port (GLFW 3.4.0 features + bug fixes): to enable, replace -sUSE_GLFW=3 with --use-port=contrib.glfw3 (requires emscripten 3.1.59+) (https://github.com/pongasoft/emscripten-glfw)
|
||||||
|
// 2024-07-02: Emscripten: Added io.PlatformOpenInShellFn() handler for Emscripten versions.
|
||||||
// 2023-12-19: Emscripten: Added ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback() to register canvas selector and auto-resize GLFW window.
|
// 2023-12-19: Emscripten: Added ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback() to register canvas selector and auto-resize GLFW window.
|
||||||
// 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F24 function keys.
|
// 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F24 function keys.
|
||||||
// 2023-07-18: Inputs: Revert ignoring mouse data on GLFW_CURSOR_DISABLED as it can be used differently. User may set ImGuiConfigFLags_NoMouse if desired. (#5625, #6609)
|
// 2023-07-18: Inputs: Revert ignoring mouse data on GLFW_CURSOR_DISABLED as it can be used differently. User may set ImGuiConfigFLags_NoMouse if desired. (#5625, #6609)
|
||||||
@@ -104,15 +118,25 @@
|
|||||||
//#include <GLFW/glfw3native.h> // for glfwGetCocoaWindow()
|
//#include <GLFW/glfw3native.h> // for glfwGetCocoaWindow()
|
||||||
// #endif
|
// #endif
|
||||||
// IMHEX PATCH END
|
// IMHEX PATCH END
|
||||||
|
#ifndef _WIN32
|
||||||
|
#include <unistd.h> // for usleep()
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
#include <emscripten.h>
|
#include <emscripten.h>
|
||||||
#include <emscripten/html5.h>
|
#include <emscripten/html5.h>
|
||||||
|
|
||||||
// IMHEX PATCH BEGIN
|
// IMHEX PATCH BEGIN
|
||||||
#include <emscripten_browser_clipboard.h>
|
#include <emscripten_browser_clipboard.h>
|
||||||
|
|
||||||
static std::string clipboardContent;
|
static std::string clipboardContent;
|
||||||
// IMHEX PATCH END
|
// IMHEX PATCH END
|
||||||
|
|
||||||
|
#ifdef EMSCRIPTEN_USE_PORT_CONTRIB_GLFW3
|
||||||
|
#include <GLFW/emscripten_glfw3.h>
|
||||||
|
#else
|
||||||
|
#define EMSCRIPTEN_USE_EMBEDDED_GLFW3
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// We gather version tests as define in order to easily see which features are version-dependent.
|
// We gather version tests as define in order to easily see which features are version-dependent.
|
||||||
@@ -159,12 +183,14 @@ struct ImGui_ImplGlfw_Data
|
|||||||
double Time;
|
double Time;
|
||||||
GLFWwindow* MouseWindow;
|
GLFWwindow* MouseWindow;
|
||||||
GLFWcursor* MouseCursors[ImGuiMouseCursor_COUNT];
|
GLFWcursor* MouseCursors[ImGuiMouseCursor_COUNT];
|
||||||
|
bool MouseIgnoreButtonUpWaitForFocusLoss;
|
||||||
|
bool MouseIgnoreButtonUp;
|
||||||
ImVec2 LastValidMousePos;
|
ImVec2 LastValidMousePos;
|
||||||
GLFWwindow* KeyOwnerWindows[GLFW_KEY_LAST];
|
GLFWwindow* KeyOwnerWindows[GLFW_KEY_LAST];
|
||||||
bool InstalledCallbacks;
|
bool InstalledCallbacks;
|
||||||
bool CallbacksChainForAllWindows;
|
bool CallbacksChainForAllWindows;
|
||||||
bool WantUpdateMonitors;
|
bool WantUpdateMonitors;
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3
|
||||||
const char* CanvasSelector;
|
const char* CanvasSelector;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -198,8 +224,8 @@ static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_GetBackendData()
|
|||||||
|
|
||||||
// Forward Declarations
|
// Forward Declarations
|
||||||
static void ImGui_ImplGlfw_UpdateMonitors();
|
static void ImGui_ImplGlfw_UpdateMonitors();
|
||||||
static void ImGui_ImplGlfw_InitPlatformInterface();
|
static void ImGui_ImplGlfw_InitMultiViewportSupport();
|
||||||
static void ImGui_ImplGlfw_ShutdownPlatformInterface();
|
static void ImGui_ImplGlfw_ShutdownMultiViewportSupport();
|
||||||
|
|
||||||
// Functions
|
// Functions
|
||||||
static const char* ImGui_ImplGlfw_GetClipboardText(void* user_data)
|
static const char* ImGui_ImplGlfw_GetClipboardText(void* user_data)
|
||||||
@@ -224,9 +250,12 @@ static void ImGui_ImplGlfw_SetClipboardText(void* user_data, const char* text)
|
|||||||
// IMHEX PATCH END
|
// IMHEX PATCH END
|
||||||
}
|
}
|
||||||
|
|
||||||
static ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int key)
|
// 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)
|
||||||
{
|
{
|
||||||
switch (key)
|
IM_UNUSED(scancode);
|
||||||
|
switch (keycode)
|
||||||
{
|
{
|
||||||
case GLFW_KEY_TAB: return ImGuiKey_Tab;
|
case GLFW_KEY_TAB: return ImGuiKey_Tab;
|
||||||
case GLFW_KEY_LEFT: return ImGuiKey_LeftArrow;
|
case GLFW_KEY_LEFT: return ImGuiKey_LeftArrow;
|
||||||
@@ -351,13 +380,18 @@ static ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int key)
|
|||||||
|
|
||||||
// X11 does not include current pressed/released modifier key in 'mods' flags submitted by GLFW
|
// X11 does not include current pressed/released modifier key in 'mods' flags submitted by GLFW
|
||||||
// See https://github.com/ocornut/imgui/issues/6034 and https://github.com/glfw/glfw/issues/1630
|
// See https://github.com/ocornut/imgui/issues/6034 and https://github.com/glfw/glfw/issues/1630
|
||||||
static void ImGui_ImplGlfw_UpdateKeyModifiers(GLFWwindow* window)
|
static void ImGui_ImplGlfw_UpdateKeyModifiers(int mods)
|
||||||
{
|
{
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
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));
|
// IMHEX PATCH BEGIN
|
||||||
io.AddKeyEvent(ImGuiMod_Alt, (glfwGetKey(window, GLFW_KEY_LEFT_ALT) == GLFW_PRESS) || (glfwGetKey(window, GLFW_KEY_RIGHT_ALT) == GLFW_PRESS));
|
// The original version of this caused the CTRL key to sometimes get stuck when pressing ALT GR, SHIFT and Enter
|
||||||
io.AddKeyEvent(ImGuiMod_Super, (glfwGetKey(window, GLFW_KEY_LEFT_SUPER) == GLFW_PRESS) || (glfwGetKey(window, GLFW_KEY_RIGHT_SUPER) == GLFW_PRESS));
|
// together in some ways
|
||||||
|
io.AddKeyEvent(ImGuiMod_Ctrl, (mods & GLFW_MOD_CONTROL) != 0);
|
||||||
|
io.AddKeyEvent(ImGuiMod_Shift, (mods & GLFW_MOD_SHIFT) != 0);
|
||||||
|
io.AddKeyEvent(ImGuiMod_Alt, (mods & GLFW_MOD_ALT) != 0);
|
||||||
|
io.AddKeyEvent(ImGuiMod_Super, (mods & GLFW_MOD_SUPER) != 0);
|
||||||
|
// IMHEX PATCH END
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ImGui_ImplGlfw_ShouldChainCallback(GLFWwindow* window)
|
static bool ImGui_ImplGlfw_ShouldChainCallback(GLFWwindow* window)
|
||||||
@@ -372,7 +406,11 @@ void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int acti
|
|||||||
if (bd->PrevUserCallbackMousebutton != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window))
|
if (bd->PrevUserCallbackMousebutton != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window))
|
||||||
bd->PrevUserCallbackMousebutton(window, button, action, mods);
|
bd->PrevUserCallbackMousebutton(window, button, action, mods);
|
||||||
|
|
||||||
ImGui_ImplGlfw_UpdateKeyModifiers(window);
|
// Workaround for Linux: ignore mouse up events which are following an focus loss following a viewport creation
|
||||||
|
if (bd->MouseIgnoreButtonUp && action == GLFW_RELEASE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ImGui_ImplGlfw_UpdateKeyModifiers(mods);
|
||||||
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
if (button >= 0 && button < ImGuiMouseButton_COUNT)
|
if (button >= 0 && button < ImGuiMouseButton_COUNT)
|
||||||
@@ -385,7 +423,7 @@ void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yo
|
|||||||
if (bd->PrevUserCallbackScroll != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window))
|
if (bd->PrevUserCallbackScroll != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window))
|
||||||
bd->PrevUserCallbackScroll(window, xoffset, yoffset);
|
bd->PrevUserCallbackScroll(window, xoffset, yoffset);
|
||||||
|
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3
|
||||||
// Ignore GLFW events: will be processed in ImGui_ImplEmscripten_WheelCallback().
|
// Ignore GLFW events: will be processed in ImGui_ImplEmscripten_WheelCallback().
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
@@ -394,9 +432,10 @@ void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yo
|
|||||||
io.AddMouseWheelEvent((float)xoffset, (float)yoffset);
|
io.AddMouseWheelEvent((float)xoffset, (float)yoffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: should this be baked into ImGui_ImplGlfw_KeyToImGuiKey()? then what about the values passed to io.SetKeyEventNativeData()?
|
||||||
static int ImGui_ImplGlfw_TranslateUntranslatedKey(int key, int scancode)
|
static int ImGui_ImplGlfw_TranslateUntranslatedKey(int key, int scancode)
|
||||||
{
|
{
|
||||||
#if GLFW_HAS_GETKEYNAME && !defined(__EMSCRIPTEN__)
|
#if GLFW_HAS_GETKEYNAME && !defined(EMSCRIPTEN_USE_EMBEDDED_GLFW3)
|
||||||
// GLFW 3.1+ attempts to "untranslate" keys, which goes the opposite of what every other framework does, making using lettered shortcuts difficult.
|
// GLFW 3.1+ attempts to "untranslate" keys, which goes the opposite of what every other framework does, making using lettered shortcuts difficult.
|
||||||
// (It had reasons to do so: namely GLFW is/was more likely to be used for WASD-type game controls rather than lettered shortcuts, but IHMO the 3.1 change could have been done differently)
|
// (It had reasons to do so: namely GLFW is/was more likely to be used for WASD-type game controls rather than lettered shortcuts, but IHMO the 3.1 change could have been done differently)
|
||||||
// See https://github.com/glfw/glfw/issues/1502 for details.
|
// See https://github.com/glfw/glfw/issues/1502 for details.
|
||||||
@@ -407,7 +446,7 @@ static int ImGui_ImplGlfw_TranslateUntranslatedKey(int key, int scancode)
|
|||||||
GLFWerrorfun prev_error_callback = glfwSetErrorCallback(nullptr);
|
GLFWerrorfun prev_error_callback = glfwSetErrorCallback(nullptr);
|
||||||
const char* key_name = glfwGetKeyName(key, scancode);
|
const char* key_name = glfwGetKeyName(key, scancode);
|
||||||
glfwSetErrorCallback(prev_error_callback);
|
glfwSetErrorCallback(prev_error_callback);
|
||||||
#if GLFW_HAS_GETERROR && !defined(__EMSCRIPTEN__) // Eat errors (see #5908)
|
#if GLFW_HAS_GETERROR && !defined(EMSCRIPTEN_USE_EMBEDDED_GLFW3) // Eat errors (see #5908)
|
||||||
(void)glfwGetError(nullptr);
|
(void)glfwGetError(nullptr);
|
||||||
#endif
|
#endif
|
||||||
if (key_name && key_name[0] != 0 && key_name[1] == 0)
|
if (key_name && key_name[0] != 0 && key_name[1] == 0)
|
||||||
@@ -436,7 +475,7 @@ void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int keycode, int scancode, i
|
|||||||
if (action != GLFW_PRESS && action != GLFW_RELEASE)
|
if (action != GLFW_PRESS && action != GLFW_RELEASE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ImGui_ImplGlfw_UpdateKeyModifiers(window);
|
ImGui_ImplGlfw_UpdateKeyModifiers(mods);
|
||||||
|
|
||||||
if (keycode >= 0 && keycode < IM_ARRAYSIZE(bd->KeyOwnerWindows))
|
if (keycode >= 0 && keycode < IM_ARRAYSIZE(bd->KeyOwnerWindows))
|
||||||
bd->KeyOwnerWindows[keycode] = (action == GLFW_PRESS) ? window : nullptr;
|
bd->KeyOwnerWindows[keycode] = (action == GLFW_PRESS) ? window : nullptr;
|
||||||
@@ -444,7 +483,7 @@ void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int keycode, int scancode, i
|
|||||||
keycode = ImGui_ImplGlfw_TranslateUntranslatedKey(keycode, scancode);
|
keycode = ImGui_ImplGlfw_TranslateUntranslatedKey(keycode, scancode);
|
||||||
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
ImGuiKey imgui_key = ImGui_ImplGlfw_KeyToImGuiKey(keycode);
|
ImGuiKey imgui_key = ImGui_ImplGlfw_KeyToImGuiKey(keycode, scancode);
|
||||||
io.AddKeyEvent(imgui_key, (action == GLFW_PRESS));
|
io.AddKeyEvent(imgui_key, (action == GLFW_PRESS));
|
||||||
io.SetKeyEventNativeData(imgui_key, keycode, scancode); // To support legacy indexing (<1.87 user code)
|
io.SetKeyEventNativeData(imgui_key, keycode, scancode); // To support legacy indexing (<1.87 user code)
|
||||||
}
|
}
|
||||||
@@ -455,6 +494,10 @@ void ImGui_ImplGlfw_WindowFocusCallback(GLFWwindow* window, int focused)
|
|||||||
if (bd->PrevUserCallbackWindowFocus != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window))
|
if (bd->PrevUserCallbackWindowFocus != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window))
|
||||||
bd->PrevUserCallbackWindowFocus(window, focused);
|
bd->PrevUserCallbackWindowFocus(window, focused);
|
||||||
|
|
||||||
|
// Workaround for Linux: when losing focus with MouseIgnoreButtonUpWaitForFocusLoss set, we will temporarily ignore subsequent Mouse Up events
|
||||||
|
bd->MouseIgnoreButtonUp = (bd->MouseIgnoreButtonUpWaitForFocusLoss && focused == 0);
|
||||||
|
bd->MouseIgnoreButtonUpWaitForFocusLoss = false;
|
||||||
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
io.AddFocusEvent(focused != 0);
|
io.AddFocusEvent(focused != 0);
|
||||||
}
|
}
|
||||||
@@ -515,7 +558,7 @@ void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor*, int)
|
|||||||
bd->WantUpdateMonitors = true;
|
bd->WantUpdateMonitors = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3
|
||||||
static EM_BOOL ImGui_ImplEmscripten_WheelCallback(int, const EmscriptenWheelEvent* ev, void*)
|
static EM_BOOL ImGui_ImplEmscripten_WheelCallback(int, const EmscriptenWheelEvent* ev, void*)
|
||||||
{
|
{
|
||||||
// Mimic Emscripten_HandleWheel() in SDL.
|
// Mimic Emscripten_HandleWheel() in SDL.
|
||||||
@@ -589,9 +632,18 @@ void ImGui_ImplGlfw_SetCallbacksChainForAllWindows(bool chain_for_all_windows)
|
|||||||
bd->CallbacksChainForAllWindows = chain_for_all_windows;
|
bd->CallbacksChainForAllWindows = chain_for_all_windows;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
#if EMSCRIPTEN_USE_PORT_CONTRIB_GLFW3 >= 34020240817
|
||||||
|
void ImGui_ImplGlfw_EmscriptenOpenURL(const char* url) { if (url) emscripten::glfw3::OpenURL(url); }
|
||||||
|
#else
|
||||||
|
EM_JS(void, ImGui_ImplGlfw_EmscriptenOpenURL, (const char* url), { url = url ? UTF8ToString(url) : null; if (url) window.open(url, '_blank'); });
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, GlfwClientApi client_api)
|
static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, GlfwClientApi client_api)
|
||||||
{
|
{
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
IMGUI_CHECKVERSION();
|
||||||
IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!");
|
IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!");
|
||||||
//printf("GLFW_VERSION: %d.%d.%d (%d)", GLFW_VERSION_MAJOR, GLFW_VERSION_MINOR, GLFW_VERSION_REVISION, GLFW_VERSION_COMBINED);
|
//printf("GLFW_VERSION: %d.%d.%d (%d)", GLFW_VERSION_MAJOR, GLFW_VERSION_MINOR, GLFW_VERSION_REVISION, GLFW_VERSION_COMBINED);
|
||||||
|
|
||||||
@@ -612,6 +664,13 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
|
|||||||
bd->Time = 0.0;
|
bd->Time = 0.0;
|
||||||
bd->WantUpdateMonitors = true;
|
bd->WantUpdateMonitors = true;
|
||||||
|
|
||||||
|
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||||
|
platform_io.Platform_SetClipboardTextFn = [](ImGuiContext*, const char* text) { glfwSetClipboardString(NULL, text); };
|
||||||
|
platform_io.Platform_GetClipboardTextFn = [](ImGuiContext*) { return glfwGetClipboardString(NULL); };
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
platform_io.Platform_OpenInShellFn = [](ImGuiContext*, const char* url) { ImGui_ImplGlfw_EmscriptenOpenURL(url); return true; };
|
||||||
|
#endif
|
||||||
|
|
||||||
// IMHEX PATCH BEGIN
|
// IMHEX PATCH BEGIN
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
// Callback to handle clipboard paste from browser
|
// Callback to handle clipboard paste from browser
|
||||||
@@ -621,10 +680,6 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
|
|||||||
#endif
|
#endif
|
||||||
// IMHEX PATCH END
|
// IMHEX PATCH END
|
||||||
|
|
||||||
io.SetClipboardTextFn = ImGui_ImplGlfw_SetClipboardText;
|
|
||||||
io.GetClipboardTextFn = ImGui_ImplGlfw_GetClipboardText;
|
|
||||||
io.ClipboardUserData = bd->Window;
|
|
||||||
|
|
||||||
// Create mouse cursors
|
// Create mouse cursors
|
||||||
// (By design, on X11 cursors are user configurable and some cursors may be missing. When a cursor doesn't exist,
|
// (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.
|
// GLFW will emit an error which will often be printed by the app, so we temporarily disable error reporting.
|
||||||
@@ -654,14 +709,9 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
|
|||||||
// Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any.
|
// Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any.
|
||||||
if (install_callbacks)
|
if (install_callbacks)
|
||||||
ImGui_ImplGlfw_InstallCallbacks(window);
|
ImGui_ImplGlfw_InstallCallbacks(window);
|
||||||
// Register Emscripten Wheel callback to workaround issue in Emscripten GLFW Emulation (#6096)
|
|
||||||
// We intentionally do not check 'if (install_callbacks)' here, as some users may set it to false and call GLFW callback themselves.
|
|
||||||
// FIXME: May break chaining in case user registered their own Emscripten callback?
|
|
||||||
#ifdef __EMSCRIPTEN__
|
|
||||||
emscripten_set_wheel_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, nullptr, false, ImGui_ImplEmscripten_WheelCallback);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Update monitors the first time (note: monitor callback are broken in GLFW 3.2 and earlier, see github.com/glfw/glfw/issues/784)
|
// Update monitor a first time during init
|
||||||
|
// (note: monitor callback are broken in GLFW 3.2 and earlier, see github.com/glfw/glfw/issues/784)
|
||||||
ImGui_ImplGlfw_UpdateMonitors();
|
ImGui_ImplGlfw_UpdateMonitors();
|
||||||
glfwSetMonitorCallback(ImGui_ImplGlfw_MonitorCallback);
|
glfwSetMonitorCallback(ImGui_ImplGlfw_MonitorCallback);
|
||||||
|
|
||||||
@@ -678,8 +728,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
|
|||||||
#else
|
#else
|
||||||
IM_UNUSED(main_viewport);
|
IM_UNUSED(main_viewport);
|
||||||
#endif
|
#endif
|
||||||
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
|
ImGui_ImplGlfw_InitMultiViewportSupport();
|
||||||
ImGui_ImplGlfw_InitPlatformInterface();
|
|
||||||
|
|
||||||
// Windows: register a WndProc hook so we can intercept some messages.
|
// Windows: register a WndProc hook so we can intercept some messages.
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@@ -688,6 +737,23 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
|
|||||||
::SetWindowLongPtrW((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC, (LONG_PTR)ImGui_ImplGlfw_WndProc);
|
::SetWindowLongPtrW((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC, (LONG_PTR)ImGui_ImplGlfw_WndProc);
|
||||||
#endif
|
#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__
|
||||||
|
#if EMSCRIPTEN_USE_PORT_CONTRIB_GLFW3 >= 34020240817
|
||||||
|
if (emscripten::glfw3::IsRuntimePlatformApple())
|
||||||
|
{
|
||||||
|
ImGui::GetIO().ConfigMacOSXBehaviors = true;
|
||||||
|
|
||||||
|
// Due to how the browser (poorly) handles the Meta Key, this line essentially disables repeats when used.
|
||||||
|
// This means that Meta + V only registers a single key-press, even if the keys are held.
|
||||||
|
// This is a compromise for dealing with this issue in ImGui since ImGui implements key repeat itself.
|
||||||
|
// See https://github.com/pongasoft/emscripten-glfw/blob/v3.4.0.20240817/docs/Usage.md#the-problem-of-the-super-key
|
||||||
|
emscripten::glfw3::SetSuperPlusKeyTimeouts(10, 10);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
bd->ClientApi = client_api;
|
bd->ClientApi = client_api;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -713,12 +779,13 @@ void ImGui_ImplGlfw_Shutdown()
|
|||||||
IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?");
|
IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?");
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
|
||||||
ImGui_ImplGlfw_ShutdownPlatformInterface();
|
ImGui_ImplGlfw_ShutdownMultiViewportSupport();
|
||||||
|
|
||||||
if (bd->InstalledCallbacks)
|
if (bd->InstalledCallbacks)
|
||||||
ImGui_ImplGlfw_RestoreCallbacks(bd->Window);
|
ImGui_ImplGlfw_RestoreCallbacks(bd->Window);
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3
|
||||||
emscripten_set_wheel_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, nullptr, false, nullptr);
|
if (bd->CanvasSelector)
|
||||||
|
emscripten_set_wheel_callback(bd->CanvasSelector, nullptr, false, nullptr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)
|
for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)
|
||||||
@@ -750,14 +817,14 @@ static void ImGui_ImplGlfw_UpdateMouseData()
|
|||||||
ImGuiViewport* viewport = platform_io.Viewports[n];
|
ImGuiViewport* viewport = platform_io.Viewports[n];
|
||||||
GLFWwindow* window = (GLFWwindow*)viewport->PlatformHandle;
|
GLFWwindow* window = (GLFWwindow*)viewport->PlatformHandle;
|
||||||
|
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3
|
||||||
const bool is_window_focused = true;
|
const bool is_window_focused = true;
|
||||||
#else
|
#else
|
||||||
const bool is_window_focused = glfwGetWindowAttrib(window, GLFW_FOCUSED) != 0;
|
const bool is_window_focused = glfwGetWindowAttrib(window, GLFW_FOCUSED) != 0;
|
||||||
#endif
|
#endif
|
||||||
if (is_window_focused)
|
if (is_window_focused)
|
||||||
{
|
{
|
||||||
// (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
|
// (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when io.ConfigNavMoveSetMousePos is enabled by user)
|
||||||
// When multi-viewports are enabled, all Dear ImGui positions are same as OS positions.
|
// When multi-viewports are enabled, all Dear ImGui positions are same as OS positions.
|
||||||
if (io.WantSetMousePos)
|
if (io.WantSetMousePos)
|
||||||
glfwSetCursorPos(window, (double)(mouse_pos_prev.x - viewport->Pos.x), (double)(mouse_pos_prev.y - viewport->Pos.y));
|
glfwSetCursorPos(window, (double)(mouse_pos_prev.x - viewport->Pos.x), (double)(mouse_pos_prev.y - viewport->Pos.y));
|
||||||
@@ -829,7 +896,6 @@ static void ImGui_ImplGlfw_UpdateMouseCursor()
|
|||||||
{
|
{
|
||||||
// Show OS mouse cursor
|
// Show OS mouse cursor
|
||||||
// FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here.
|
// FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here.
|
||||||
|
|
||||||
// IMHEX PATCH BEGIN
|
// IMHEX PATCH BEGIN
|
||||||
#if !defined(_WIN32)
|
#if !defined(_WIN32)
|
||||||
glfwSetCursor(window, bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow]);
|
glfwSetCursor(window, bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow]);
|
||||||
@@ -850,7 +916,7 @@ static void ImGui_ImplGlfw_UpdateGamepads()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
|
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
|
||||||
#if GLFW_HAS_GAMEPAD_API && !defined(__EMSCRIPTEN__)
|
#if GLFW_HAS_GAMEPAD_API && !defined(EMSCRIPTEN_USE_EMBEDDED_GLFW3)
|
||||||
GLFWgamepadstate gamepad;
|
GLFWgamepadstate gamepad;
|
||||||
if (!glfwGetGamepadState(GLFW_JOYSTICK_1, &gamepad))
|
if (!glfwGetGamepadState(GLFW_JOYSTICK_1, &gamepad))
|
||||||
return;
|
return;
|
||||||
@@ -929,13 +995,9 @@ static void ImGui_ImplGlfw_UpdateMonitors()
|
|||||||
// Warning: the validity of monitor DPI information on Windows depends on the application DPI awareness settings, which generally needs to be set in the manifest or at runtime.
|
// Warning: the validity of monitor DPI information on Windows depends on the application DPI awareness settings, which generally needs to be set in the manifest or at runtime.
|
||||||
float x_scale, y_scale;
|
float x_scale, y_scale;
|
||||||
glfwGetMonitorContentScale(glfw_monitors[n], &x_scale, &y_scale);
|
glfwGetMonitorContentScale(glfw_monitors[n], &x_scale, &y_scale);
|
||||||
|
if (x_scale == 0.0f)
|
||||||
|
continue; // Some accessibility applications are declaring virtual monitors with a DPI of 0, see #7902.
|
||||||
monitor.DpiScale = x_scale;
|
monitor.DpiScale = x_scale;
|
||||||
|
|
||||||
// IMHEX PATCH BEGIN
|
|
||||||
// REASON: Prevent occasional crash when a monitor connection status is changed
|
|
||||||
if (x_scale > 0)
|
|
||||||
monitor.DpiScale = x_scale;
|
|
||||||
// IMHEX PATCH END
|
|
||||||
#endif
|
#endif
|
||||||
monitor.PlatformHandle = (void*)glfw_monitors[n]; // [...] GLFW doc states: "guaranteed to be valid only until the monitor configuration changes"
|
monitor.PlatformHandle = (void*)glfw_monitors[n]; // [...] GLFW doc states: "guaranteed to be valid only until the monitor configuration changes"
|
||||||
platform_io.Monitors.push_back(monitor);
|
platform_io.Monitors.push_back(monitor);
|
||||||
@@ -967,6 +1029,7 @@ void ImGui_ImplGlfw_NewFrame()
|
|||||||
io.DeltaTime = bd->Time > 0.0 ? (float)(current_time - bd->Time) : (float)(1.0f / 60.0f);
|
io.DeltaTime = bd->Time > 0.0 ? (float)(current_time - bd->Time) : (float)(1.0f / 60.0f);
|
||||||
bd->Time = current_time;
|
bd->Time = current_time;
|
||||||
|
|
||||||
|
bd->MouseIgnoreButtonUp = false;
|
||||||
ImGui_ImplGlfw_UpdateMouseData();
|
ImGui_ImplGlfw_UpdateMouseData();
|
||||||
ImGui_ImplGlfw_UpdateMouseCursor();
|
ImGui_ImplGlfw_UpdateMouseCursor();
|
||||||
|
|
||||||
@@ -974,7 +1037,17 @@ void ImGui_ImplGlfw_NewFrame()
|
|||||||
ImGui_ImplGlfw_UpdateGamepads();
|
ImGui_ImplGlfw_UpdateGamepads();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __EMSCRIPTEN__
|
// GLFW doesn't provide a portable sleep function
|
||||||
|
void ImGui_ImplGlfw_Sleep(int milliseconds)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
::Sleep(milliseconds);
|
||||||
|
#else
|
||||||
|
usleep(milliseconds * 1000);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3
|
||||||
static EM_BOOL ImGui_ImplGlfw_OnCanvasSizeChange(int event_type, const EmscriptenUiEvent* event, void* user_data)
|
static EM_BOOL ImGui_ImplGlfw_OnCanvasSizeChange(int event_type, const EmscriptenUiEvent* event, void* user_data)
|
||||||
{
|
{
|
||||||
ImGui_ImplGlfw_Data* bd = (ImGui_ImplGlfw_Data*)user_data;
|
ImGui_ImplGlfw_Data* bd = (ImGui_ImplGlfw_Data*)user_data;
|
||||||
@@ -995,7 +1068,7 @@ static EM_BOOL ImGui_ImplEmscripten_FullscreenChangeCallback(int event_type, con
|
|||||||
|
|
||||||
// 'canvas_selector' is a CSS selector. The event listener is applied to the first element that matches the query.
|
// 'canvas_selector' is a CSS selector. The event listener is applied to the first element that matches the query.
|
||||||
// STRING MUST PERSIST FOR THE APPLICATION DURATION. PLEASE USE A STRING LITERAL OR ENSURE POINTER WILL STAY VALID.
|
// STRING MUST PERSIST FOR THE APPLICATION DURATION. PLEASE USE A STRING LITERAL OR ENSURE POINTER WILL STAY VALID.
|
||||||
void ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback(const char* canvas_selector)
|
void ImGui_ImplGlfw_InstallEmscriptenCallbacks(GLFWwindow*, const char* canvas_selector)
|
||||||
{
|
{
|
||||||
IM_ASSERT(canvas_selector != nullptr);
|
IM_ASSERT(canvas_selector != nullptr);
|
||||||
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
|
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
|
||||||
@@ -1007,8 +1080,24 @@ void ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback(const char* canvas_sel
|
|||||||
|
|
||||||
// Change the size of the GLFW window according to the size of the canvas
|
// Change the size of the GLFW window according to the size of the canvas
|
||||||
ImGui_ImplGlfw_OnCanvasSizeChange(EMSCRIPTEN_EVENT_RESIZE, {}, bd);
|
ImGui_ImplGlfw_OnCanvasSizeChange(EMSCRIPTEN_EVENT_RESIZE, {}, bd);
|
||||||
|
|
||||||
|
// Register Emscripten Wheel callback to workaround issue in Emscripten GLFW Emulation (#6096)
|
||||||
|
// We intentionally do not check 'if (install_callbacks)' here, as some users may set it to false and call GLFW callback themselves.
|
||||||
|
// FIXME: May break chaining in case user registered their own Emscripten callback?
|
||||||
|
emscripten_set_wheel_callback(bd->CanvasSelector, nullptr, false, ImGui_ImplEmscripten_WheelCallback);
|
||||||
}
|
}
|
||||||
#endif
|
#elif defined(EMSCRIPTEN_USE_PORT_CONTRIB_GLFW3)
|
||||||
|
// When using --use-port=contrib.glfw3 for the GLFW implementation, you can override the behavior of this call
|
||||||
|
// by invoking emscripten_glfw_make_canvas_resizable afterward.
|
||||||
|
// See https://github.com/pongasoft/emscripten-glfw/blob/master/docs/Usage.md#how-to-make-the-canvas-resizable-by-the-user for an explanation
|
||||||
|
void ImGui_ImplGlfw_InstallEmscriptenCallbacks(GLFWwindow* window, const char* canvas_selector)
|
||||||
|
{
|
||||||
|
GLFWwindow* w = (GLFWwindow*)(EM_ASM_INT({ return Module.glfwGetWindow(UTF8ToString($0)); }, canvas_selector));
|
||||||
|
IM_ASSERT(window == w); // Sanity check
|
||||||
|
IM_UNUSED(w);
|
||||||
|
emscripten_glfw_make_canvas_resizable(window, "window", nullptr);
|
||||||
|
}
|
||||||
|
#endif // #ifdef EMSCRIPTEN_USE_PORT_CONTRIB_GLFW3
|
||||||
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------
|
||||||
@@ -1080,6 +1169,11 @@ static void ImGui_ImplGlfw_CreateWindow(ImGuiViewport* viewport)
|
|||||||
ImGui_ImplGlfw_ViewportData* vd = IM_NEW(ImGui_ImplGlfw_ViewportData)();
|
ImGui_ImplGlfw_ViewportData* vd = IM_NEW(ImGui_ImplGlfw_ViewportData)();
|
||||||
viewport->PlatformUserData = vd;
|
viewport->PlatformUserData = vd;
|
||||||
|
|
||||||
|
// Workaround for Linux: ignore mouse up events corresponding to losing focus of the previously focused window (#7733, #3158, #7922)
|
||||||
|
#ifdef __linux__
|
||||||
|
bd->MouseIgnoreButtonUpWaitForFocusLoss = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
// GLFW 3.2 unfortunately always set focus on glfwCreateWindow() if GLFW_VISIBLE is set, regardless of GLFW_FOCUSED
|
// GLFW 3.2 unfortunately always set focus on glfwCreateWindow() if GLFW_VISIBLE is set, regardless of GLFW_FOCUSED
|
||||||
// With GLFW 3.3, the hint GLFW_FOCUS_ON_SHOW fixes this problem
|
// With GLFW 3.3, the hint GLFW_FOCUS_ON_SHOW fixes this problem
|
||||||
glfwWindowHint(GLFW_VISIBLE, false);
|
glfwWindowHint(GLFW_VISIBLE, false);
|
||||||
@@ -1137,9 +1231,10 @@ static void ImGui_ImplGlfw_DestroyWindow(ImGuiViewport* viewport)
|
|||||||
|
|
||||||
// Release any keys that were pressed in the window being destroyed and are still held down,
|
// 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.
|
// 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_ARRAYSIZE(bd->KeyOwnerWindows); i++) {
|
||||||
if (bd->KeyOwnerWindows[i] == vd->Window)
|
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.
|
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.
|
||||||
|
}
|
||||||
|
|
||||||
glfwDestroyWindow(vd->Window);
|
glfwDestroyWindow(vd->Window);
|
||||||
}
|
}
|
||||||
@@ -1313,7 +1408,7 @@ static int ImGui_ImplGlfw_CreateVkSurface(ImGuiViewport* viewport, ImU64 vk_inst
|
|||||||
}
|
}
|
||||||
#endif // GLFW_HAS_VULKAN
|
#endif // GLFW_HAS_VULKAN
|
||||||
|
|
||||||
static void ImGui_ImplGlfw_InitPlatformInterface()
|
static void ImGui_ImplGlfw_InitMultiViewportSupport()
|
||||||
{
|
{
|
||||||
// Register platform interface (will be coupled with a renderer interface)
|
// Register platform interface (will be coupled with a renderer interface)
|
||||||
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
|
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
|
||||||
@@ -1348,7 +1443,7 @@ static void ImGui_ImplGlfw_InitPlatformInterface()
|
|||||||
main_viewport->PlatformHandle = (void*)bd->Window;
|
main_viewport->PlatformHandle = (void*)bd->Window;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ImGui_ImplGlfw_ShutdownPlatformInterface()
|
static void ImGui_ImplGlfw_ShutdownMultiViewportSupport()
|
||||||
{
|
{
|
||||||
ImGui::DestroyPlatformWindows();
|
ImGui::DestroyPlatformWindows();
|
||||||
}
|
}
|
||||||
|
|||||||
6
lib/third_party/imgui/imgui/CMakeLists.txt
vendored
6
lib/third_party/imgui/imgui/CMakeLists.txt
vendored
@@ -20,13 +20,17 @@ if (NOT IMHEX_EXTERNAL_PLUGIN_BUILD)
|
|||||||
include/misc/freetype
|
include/misc/freetype
|
||||||
)
|
)
|
||||||
|
|
||||||
target_compile_options(imgui_imgui PRIVATE -Wno-unknown-warning-option)
|
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||||
|
target_compile_options(imgui_imgui PRIVATE -Wno-unknown-warning-option)
|
||||||
|
endif()
|
||||||
|
|
||||||
find_package(Freetype REQUIRED)
|
find_package(Freetype REQUIRED)
|
||||||
|
|
||||||
target_include_directories(imgui_imgui PUBLIC ${FREETYPE_INCLUDE_DIRS})
|
target_include_directories(imgui_imgui PUBLIC ${FREETYPE_INCLUDE_DIRS})
|
||||||
target_link_directories(imgui_imgui PUBLIC ${FREETYPE_LIBRARY_DIRS})
|
target_link_directories(imgui_imgui PUBLIC ${FREETYPE_LIBRARY_DIRS})
|
||||||
target_link_libraries(imgui_imgui PUBLIC ${FREETYPE_LIBRARIES})
|
target_link_libraries(imgui_imgui PUBLIC ${FREETYPE_LIBRARIES})
|
||||||
|
|
||||||
|
target_compile_definitions(imgui_imgui PUBLIC IMGUI_USE_LEGACY_CRC32_ADLER=1)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_library(imgui_includes INTERFACE)
|
add_library(imgui_includes INTERFACE)
|
||||||
|
|||||||
832
lib/third_party/imgui/imgui/include/imgui.h
vendored
832
lib/third_party/imgui/imgui/include/imgui.h
vendored
File diff suppressed because it is too large
Load Diff
849
lib/third_party/imgui/imgui/include/imgui_internal.h
vendored
849
lib/third_party/imgui/imgui/include/imgui_internal.h
vendored
File diff suppressed because it is too large
Load Diff
@@ -3,6 +3,8 @@
|
|||||||
// Those changes would need to be pushed into nothings/stb:
|
// Those changes would need to be pushed into nothings/stb:
|
||||||
// - Fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321)
|
// - Fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321)
|
||||||
// - Fix in stb_textedit_find_charpos to handle last line (see https://github.com/ocornut/imgui/issues/6000 + #6783)
|
// - Fix in stb_textedit_find_charpos to handle last line (see https://github.com/ocornut/imgui/issues/6000 + #6783)
|
||||||
|
// - Added name to struct or it may be forward declared in our code.
|
||||||
|
// - Added UTF-8 support (see https://github.com/nothings/stb/issues/188 + https://github.com/ocornut/imgui/pull/7925)
|
||||||
// Grep for [DEAR IMGUI] to find the changes.
|
// Grep for [DEAR IMGUI] to find the changes.
|
||||||
// - Also renamed macros used or defined outside of IMSTB_TEXTEDIT_IMPLEMENTATION block from STB_TEXTEDIT_* to IMSTB_TEXTEDIT_*
|
// - Also renamed macros used or defined outside of IMSTB_TEXTEDIT_IMPLEMENTATION block from STB_TEXTEDIT_* to IMSTB_TEXTEDIT_*
|
||||||
|
|
||||||
@@ -209,6 +211,7 @@
|
|||||||
// int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
// int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||||
// int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len)
|
// int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len)
|
||||||
// void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXEDIT_KEYTYPE key)
|
// void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXEDIT_KEYTYPE key)
|
||||||
|
// void stb_textedit_text(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int text_len)
|
||||||
//
|
//
|
||||||
// Each of these functions potentially updates the string and updates the
|
// Each of these functions potentially updates the string and updates the
|
||||||
// state.
|
// state.
|
||||||
@@ -243,7 +246,12 @@
|
|||||||
// various definitions like STB_TEXTEDIT_K_LEFT have the is-key-event bit
|
// various definitions like STB_TEXTEDIT_K_LEFT have the is-key-event bit
|
||||||
// set, and make STB_TEXTEDIT_KEYTOCHAR check that the is-key-event bit is
|
// set, and make STB_TEXTEDIT_KEYTOCHAR check that the is-key-event bit is
|
||||||
// clear. STB_TEXTEDIT_KEYTYPE defaults to int, but you can #define it to
|
// clear. STB_TEXTEDIT_KEYTYPE defaults to int, but you can #define it to
|
||||||
// anything other type you wante before including.
|
// anything other type you want before including.
|
||||||
|
// if the STB_TEXTEDIT_KEYTOTEXT function is defined, selected keys are
|
||||||
|
// transformed into text and stb_textedit_text() is automatically called.
|
||||||
|
//
|
||||||
|
// text: [DEAR IMGUI] added 2024-09
|
||||||
|
// call this to text inputs sent to the textfield.
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// When rendering, you can read the cursor position and selection state from
|
// When rendering, you can read the cursor position and selection state from
|
||||||
@@ -318,7 +326,7 @@ typedef struct
|
|||||||
int undo_char_point, redo_char_point;
|
int undo_char_point, redo_char_point;
|
||||||
} StbUndoState;
|
} StbUndoState;
|
||||||
|
|
||||||
typedef struct
|
typedef struct STB_TexteditState
|
||||||
{
|
{
|
||||||
/////////////////////
|
/////////////////////
|
||||||
//
|
//
|
||||||
@@ -438,13 +446,13 @@ static int stb_text_locate_coord(IMSTB_TEXTEDIT_STRING *str, float x, float y)
|
|||||||
if (x < r.x1) {
|
if (x < r.x1) {
|
||||||
// search characters in row for one that straddles 'x'
|
// search characters in row for one that straddles 'x'
|
||||||
prev_x = r.x0;
|
prev_x = r.x0;
|
||||||
for (k=0; k < r.num_chars; ++k) {
|
for (k=0; k < r.num_chars; k = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, i + k) - i) {
|
||||||
float w = STB_TEXTEDIT_GETWIDTH(str, i, k);
|
float w = STB_TEXTEDIT_GETWIDTH(str, i, k);
|
||||||
if (x < prev_x+w) {
|
if (x < prev_x+w) {
|
||||||
if (x < prev_x+w/2)
|
if (x < prev_x+w/2)
|
||||||
return k+i;
|
return k+i;
|
||||||
else
|
else
|
||||||
return k+i+1;
|
return IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, i + k);
|
||||||
}
|
}
|
||||||
prev_x += w;
|
prev_x += w;
|
||||||
}
|
}
|
||||||
@@ -563,7 +571,7 @@ static void stb_textedit_find_charpos(StbFindState *find, IMSTB_TEXTEDIT_STRING
|
|||||||
|
|
||||||
// now scan to find xpos
|
// now scan to find xpos
|
||||||
find->x = r.x0;
|
find->x = r.x0;
|
||||||
for (i=0; first+i < n; ++i)
|
for (i=0; first+i < n; i = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, first + i) - first)
|
||||||
find->x += STB_TEXTEDIT_GETWIDTH(str, first, i);
|
find->x += STB_TEXTEDIT_GETWIDTH(str, first, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -640,6 +648,17 @@ static void stb_textedit_move_to_last(IMSTB_TEXTEDIT_STRING *str, STB_TexteditSt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// [DEAR IMGUI]
|
||||||
|
// Functions must be implemented for UTF8 support
|
||||||
|
// Code in this file that uses those functions is modified for [DEAR IMGUI] and deviates from the original stb_textedit.
|
||||||
|
// There is not necessarily a '[DEAR IMGUI]' at the usage sites.
|
||||||
|
#ifndef IMSTB_TEXTEDIT_GETPREVCHARINDEX
|
||||||
|
#define IMSTB_TEXTEDIT_GETPREVCHARINDEX(obj, idx) (idx - 1)
|
||||||
|
#endif
|
||||||
|
#ifndef IMSTB_TEXTEDIT_GETNEXTCHARINDEX
|
||||||
|
#define IMSTB_TEXTEDIT_GETNEXTCHARINDEX(obj, idx) (idx + 1)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef STB_TEXTEDIT_IS_SPACE
|
#ifdef STB_TEXTEDIT_IS_SPACE
|
||||||
static int is_word_boundary( IMSTB_TEXTEDIT_STRING *str, int idx )
|
static int is_word_boundary( IMSTB_TEXTEDIT_STRING *str, int idx )
|
||||||
{
|
{
|
||||||
@@ -720,36 +739,44 @@ static int stb_textedit_paste_internal(IMSTB_TEXTEDIT_STRING *str, STB_TexteditS
|
|||||||
#define STB_TEXTEDIT_KEYTYPE int
|
#define STB_TEXTEDIT_KEYTYPE int
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// [DEAR IMGUI] Added stb_textedit_text(), extracted out and called by stb_textedit_key() for backward compatibility.
|
||||||
|
static void stb_textedit_text(IMSTB_TEXTEDIT_STRING* str, STB_TexteditState* state, const IMSTB_TEXTEDIT_CHARTYPE* text, int text_len)
|
||||||
|
{
|
||||||
|
// can't add newline in single-line mode
|
||||||
|
if (text[0] == '\n' && state->single_line)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (state->insert_mode && !STB_TEXT_HAS_SELECTION(state) && state->cursor < STB_TEXTEDIT_STRINGLEN(str)) {
|
||||||
|
stb_text_makeundo_replace(str, state, state->cursor, 1, 1);
|
||||||
|
STB_TEXTEDIT_DELETECHARS(str, state->cursor, 1);
|
||||||
|
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, text_len)) {
|
||||||
|
state->cursor += text_len;
|
||||||
|
state->has_preferred_x = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
stb_textedit_delete_selection(str, state); // implicitly clamps
|
||||||
|
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, text_len)) {
|
||||||
|
stb_text_makeundo_insert(state, state->cursor, text_len);
|
||||||
|
state->cursor += text_len;
|
||||||
|
state->has_preferred_x = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// API key: process a keyboard input
|
// API key: process a keyboard input
|
||||||
static void stb_textedit_key(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_KEYTYPE key)
|
static void stb_textedit_key(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_KEYTYPE key)
|
||||||
{
|
{
|
||||||
retry:
|
retry:
|
||||||
switch (key) {
|
switch (key) {
|
||||||
default: {
|
default: {
|
||||||
|
#ifdef STB_TEXTEDIT_KEYTOTEXT
|
||||||
int c = STB_TEXTEDIT_KEYTOTEXT(key);
|
int c = STB_TEXTEDIT_KEYTOTEXT(key);
|
||||||
if (c > 0) {
|
if (c > 0) {
|
||||||
IMSTB_TEXTEDIT_CHARTYPE ch = (IMSTB_TEXTEDIT_CHARTYPE) c;
|
IMSTB_TEXTEDIT_CHARTYPE ch = (IMSTB_TEXTEDIT_CHARTYPE)c;
|
||||||
|
stb_textedit_text(str, state, &ch, 1);
|
||||||
// can't add newline in single-line mode
|
|
||||||
if (c == '\n' && state->single_line)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (state->insert_mode && !STB_TEXT_HAS_SELECTION(state) && state->cursor < STB_TEXTEDIT_STRINGLEN(str)) {
|
|
||||||
stb_text_makeundo_replace(str, state, state->cursor, 1, 1);
|
|
||||||
STB_TEXTEDIT_DELETECHARS(str, state->cursor, 1);
|
|
||||||
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) {
|
|
||||||
++state->cursor;
|
|
||||||
state->has_preferred_x = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
stb_textedit_delete_selection(str,state); // implicitly clamps
|
|
||||||
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) {
|
|
||||||
stb_text_makeundo_insert(state, state->cursor, 1);
|
|
||||||
++state->cursor;
|
|
||||||
state->has_preferred_x = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -775,7 +802,7 @@ retry:
|
|||||||
stb_textedit_move_to_first(state);
|
stb_textedit_move_to_first(state);
|
||||||
else
|
else
|
||||||
if (state->cursor > 0)
|
if (state->cursor > 0)
|
||||||
--state->cursor;
|
state->cursor = IMSTB_TEXTEDIT_GETPREVCHARINDEX(str, state->cursor);
|
||||||
state->has_preferred_x = 0;
|
state->has_preferred_x = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -784,7 +811,7 @@ retry:
|
|||||||
if (STB_TEXT_HAS_SELECTION(state))
|
if (STB_TEXT_HAS_SELECTION(state))
|
||||||
stb_textedit_move_to_last(str, state);
|
stb_textedit_move_to_last(str, state);
|
||||||
else
|
else
|
||||||
++state->cursor;
|
state->cursor = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor);
|
||||||
stb_textedit_clamp(str, state);
|
stb_textedit_clamp(str, state);
|
||||||
state->has_preferred_x = 0;
|
state->has_preferred_x = 0;
|
||||||
break;
|
break;
|
||||||
@@ -794,7 +821,7 @@ retry:
|
|||||||
stb_textedit_prep_selection_at_cursor(state);
|
stb_textedit_prep_selection_at_cursor(state);
|
||||||
// move selection left
|
// move selection left
|
||||||
if (state->select_end > 0)
|
if (state->select_end > 0)
|
||||||
--state->select_end;
|
state->select_end = IMSTB_TEXTEDIT_GETPREVCHARINDEX(str, state->select_end);
|
||||||
state->cursor = state->select_end;
|
state->cursor = state->select_end;
|
||||||
state->has_preferred_x = 0;
|
state->has_preferred_x = 0;
|
||||||
break;
|
break;
|
||||||
@@ -844,7 +871,7 @@ retry:
|
|||||||
case STB_TEXTEDIT_K_RIGHT | STB_TEXTEDIT_K_SHIFT:
|
case STB_TEXTEDIT_K_RIGHT | STB_TEXTEDIT_K_SHIFT:
|
||||||
stb_textedit_prep_selection_at_cursor(state);
|
stb_textedit_prep_selection_at_cursor(state);
|
||||||
// move selection right
|
// move selection right
|
||||||
++state->select_end;
|
state->select_end = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->select_end);
|
||||||
stb_textedit_clamp(str, state);
|
stb_textedit_clamp(str, state);
|
||||||
state->cursor = state->select_end;
|
state->cursor = state->select_end;
|
||||||
state->has_preferred_x = 0;
|
state->has_preferred_x = 0;
|
||||||
@@ -900,7 +927,7 @@ retry:
|
|||||||
x += dx;
|
x += dx;
|
||||||
if (x > goal_x)
|
if (x > goal_x)
|
||||||
break;
|
break;
|
||||||
++state->cursor;
|
state->cursor = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor);
|
||||||
}
|
}
|
||||||
stb_textedit_clamp(str, state);
|
stb_textedit_clamp(str, state);
|
||||||
|
|
||||||
@@ -962,7 +989,7 @@ retry:
|
|||||||
x += dx;
|
x += dx;
|
||||||
if (x > goal_x)
|
if (x > goal_x)
|
||||||
break;
|
break;
|
||||||
++state->cursor;
|
state->cursor = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor);
|
||||||
}
|
}
|
||||||
stb_textedit_clamp(str, state);
|
stb_textedit_clamp(str, state);
|
||||||
|
|
||||||
@@ -990,7 +1017,7 @@ retry:
|
|||||||
else {
|
else {
|
||||||
int n = STB_TEXTEDIT_STRINGLEN(str);
|
int n = STB_TEXTEDIT_STRINGLEN(str);
|
||||||
if (state->cursor < n)
|
if (state->cursor < n)
|
||||||
stb_textedit_delete(str, state, state->cursor, 1);
|
stb_textedit_delete(str, state, state->cursor, IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor) - state->cursor);
|
||||||
}
|
}
|
||||||
state->has_preferred_x = 0;
|
state->has_preferred_x = 0;
|
||||||
break;
|
break;
|
||||||
@@ -1002,8 +1029,9 @@ retry:
|
|||||||
else {
|
else {
|
||||||
stb_textedit_clamp(str, state);
|
stb_textedit_clamp(str, state);
|
||||||
if (state->cursor > 0) {
|
if (state->cursor > 0) {
|
||||||
stb_textedit_delete(str, state, state->cursor-1, 1);
|
int prev = IMSTB_TEXTEDIT_GETPREVCHARINDEX(str, state->cursor);
|
||||||
--state->cursor;
|
stb_textedit_delete(str, state, prev, state->cursor - prev);
|
||||||
|
state->cursor = prev;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state->has_preferred_x = 0;
|
state->has_preferred_x = 0;
|
||||||
|
|||||||
2451
lib/third_party/imgui/imgui/source/imgui.cpp
vendored
2451
lib/third_party/imgui/imgui/source/imgui.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