mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-03-28 15:57:03 -05:00
Compare commits
272 Commits
v1.36.1
...
feature/ap
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d76e92933a | ||
|
|
403104dda1 | ||
|
|
8334fbb236 | ||
|
|
0a0323ce5d | ||
|
|
726d36ba3d | ||
|
|
8bb1521963 | ||
|
|
9457c1f2b9 | ||
|
|
2b24330f9f | ||
|
|
9329170e59 | ||
|
|
98f3de828a | ||
|
|
3f38f42259 | ||
|
|
058a8cdc15 | ||
|
|
d0c1213ea0 | ||
|
|
30967bac6d | ||
|
|
09c9bcb046 | ||
|
|
93f1f5d076 | ||
|
|
93e5d62782 | ||
|
|
4d7021ece1 | ||
|
|
f976988c75 | ||
|
|
1eee31fdbb | ||
|
|
048c483903 | ||
|
|
b646ece14b | ||
|
|
35e8acd69d | ||
|
|
de4135d1ad | ||
|
|
a44959ce1b | ||
|
|
f4bad0053a | ||
|
|
26af5987a5 | ||
|
|
9cf3250751 | ||
|
|
acc77205bb | ||
|
|
a6b4f62d75 | ||
|
|
69c5d553b5 | ||
|
|
637cdd7084 | ||
|
|
8978e193db | ||
|
|
242b100aa3 | ||
|
|
3a888d48df | ||
|
|
721de39dbb | ||
|
|
07e29f2030 | ||
|
|
c117d9b3e5 | ||
|
|
16eae89151 | ||
|
|
95cb6d8ee6 | ||
|
|
af27c09204 | ||
|
|
5e3532267c | ||
|
|
7c0331df65 | ||
|
|
04ab87cd8e | ||
|
|
91f5e84250 | ||
|
|
b1edd95ebc | ||
|
|
758738da5c | ||
|
|
41c8be275b | ||
|
|
117eb1e2a7 | ||
|
|
3129d6e8fd | ||
|
|
2ba7db184b | ||
|
|
2cb0df4080 | ||
|
|
3adc2c44e6 | ||
|
|
6d3ff64894 | ||
|
|
cf84ad6196 | ||
|
|
6259190ad9 | ||
|
|
181be1a58e | ||
|
|
771e191f28 | ||
|
|
d4d6893eb3 | ||
|
|
9e75562662 | ||
|
|
2b3168163b | ||
|
|
252c06eb12 | ||
|
|
2a51d8169a | ||
|
|
7405c4b411 | ||
|
|
309ae7b619 | ||
|
|
64ef56a0df | ||
|
|
fbfe7b0d25 | ||
|
|
8c7e1a3b2d | ||
|
|
bf249cdafe | ||
|
|
59ba6f50cc | ||
|
|
8d6e7c7d44 | ||
|
|
52934ae166 | ||
|
|
56c4f2aa47 | ||
|
|
a1d8cbd7ba | ||
|
|
63a219a32b | ||
|
|
14fb256a6a | ||
|
|
95df7a23c3 | ||
|
|
bb17690cf5 | ||
|
|
a943b02e43 | ||
|
|
199f78347f | ||
|
|
d3d9a42d57 | ||
|
|
1fa45a8c84 | ||
|
|
0b6316ea23 | ||
|
|
466a843263 | ||
|
|
b6ade8b101 | ||
|
|
ff66b97e90 | ||
|
|
c604ec8fb9 | ||
|
|
7564651dd5 | ||
|
|
cad17ddefd | ||
|
|
25d2f209e5 | ||
|
|
8d660c3ffe | ||
|
|
209055d0b0 | ||
|
|
599b55965a | ||
|
|
69a9af5322 | ||
|
|
0303cd0ad0 | ||
|
|
8eb7e9fb05 | ||
|
|
6a1de5fc4e | ||
|
|
a4af55cb66 | ||
|
|
1e17422f5e | ||
|
|
8abaafab79 | ||
|
|
71e1465524 | ||
|
|
3d2ea3753b | ||
|
|
88530eff8b | ||
|
|
df3decf71b | ||
|
|
565ee4cb2d | ||
|
|
40fc325ba9 | ||
|
|
6aca16102d | ||
|
|
cb11b57ab1 | ||
|
|
d504937d50 | ||
|
|
6bfdb7ca4e | ||
|
|
e1637824c6 | ||
|
|
e36f2f2bcb | ||
|
|
1a54e08f11 | ||
|
|
ecc86ee429 | ||
|
|
185a593bc2 | ||
|
|
4a916ebb89 | ||
|
|
1c305ca762 | ||
|
|
17fff56fa0 | ||
|
|
ec1b1c2b7d | ||
|
|
7bae22f56f | ||
|
|
21e5eeef16 | ||
|
|
bf5eea80f6 | ||
|
|
9f9a6d9827 | ||
|
|
ae622e6d75 | ||
|
|
68fbff631f | ||
|
|
6cdce75095 | ||
|
|
f699e76c56 | ||
|
|
a729329cd4 | ||
|
|
d5020ce9bb | ||
|
|
126868c251 | ||
|
|
b206e9fc95 | ||
|
|
4b6ff68464 | ||
|
|
b23a0febb5 | ||
|
|
05ad547341 | ||
|
|
f10af882a7 | ||
|
|
98f32ebcad | ||
|
|
e2c302836f | ||
|
|
f1d9642cf6 | ||
|
|
5c58e5b545 | ||
|
|
803cb335e1 | ||
|
|
ae4dde8255 | ||
|
|
cb34f68b1b | ||
|
|
96ef983cfb | ||
|
|
d8c3d67dfe | ||
|
|
5de5153663 | ||
|
|
1e747b6831 | ||
|
|
fbe9d16073 | ||
|
|
d02c0073a0 | ||
|
|
1090b9879c | ||
|
|
5a6af976cd | ||
|
|
55e39a5d30 | ||
|
|
c9b1ddfb59 | ||
|
|
f7dd696ffc | ||
|
|
70f210ac5d | ||
|
|
cad1c11f8b | ||
|
|
f7fa305e82 | ||
|
|
f96c51e854 | ||
|
|
c19705d3e5 | ||
|
|
1190511994 | ||
|
|
69ee7ef63c | ||
|
|
fc95e5a9a8 | ||
|
|
6ecc495d43 | ||
|
|
6e861001cf | ||
|
|
c56af08c7e | ||
|
|
e68abefe48 | ||
|
|
fd0635cb82 | ||
|
|
baa3cfb354 | ||
|
|
aea9bab853 | ||
|
|
48de609f53 | ||
|
|
71f4f87288 | ||
|
|
48b202c56b | ||
|
|
d975019a7b | ||
|
|
6009b5013b | ||
|
|
24979d7fbd | ||
|
|
b4bf42e377 | ||
|
|
f94819351a | ||
|
|
8da69c11d9 | ||
|
|
635a825095 | ||
|
|
bbffdbf56f | ||
|
|
1c30533d19 | ||
|
|
dcd80fe6ad | ||
|
|
525ab8d945 | ||
|
|
d8fb3f526a | ||
|
|
a55df1d111 | ||
|
|
2cf32ba38d | ||
|
|
c82907153e | ||
|
|
165403da67 | ||
|
|
0e4d94946e | ||
|
|
9f9c5abf35 | ||
|
|
6a3b10111f | ||
|
|
0a55f4bf83 | ||
|
|
493d66d991 | ||
|
|
268b495a29 | ||
|
|
180f4926f8 | ||
|
|
c853349b78 | ||
|
|
ee555e0da9 | ||
|
|
3dec4cc698 | ||
|
|
d7b2b94cec | ||
|
|
c9e88586aa | ||
|
|
1d641504b1 | ||
|
|
655e068b9b | ||
|
|
67a9f314cc | ||
|
|
ff2b58e8a3 | ||
|
|
a1482cb40e | ||
|
|
89111059f9 | ||
|
|
0ae823716a | ||
|
|
dab3f722e8 | ||
|
|
0dc1af0747 | ||
|
|
021206e052 | ||
|
|
cb09cf3734 | ||
|
|
f0525d6463 | ||
|
|
e22424ffa4 | ||
|
|
6e666c64e8 | ||
|
|
5f5f6ac539 | ||
|
|
3024c79f4f | ||
|
|
ba96d86dc2 | ||
|
|
40ec7195d1 | ||
|
|
f10dfa0c20 | ||
|
|
6a5473f6fe | ||
|
|
f79de6fbe8 | ||
|
|
ec4ee3132b | ||
|
|
1298f2b688 | ||
|
|
534a2f1d28 | ||
|
|
c8e95cf3c3 | ||
|
|
c4918a963c | ||
|
|
bf6f738d2e | ||
|
|
1605904eb1 | ||
|
|
138517f116 | ||
|
|
d4a4cb2e80 | ||
|
|
9a9dc328e3 | ||
|
|
50eea0a4f1 | ||
|
|
528a8b5b46 | ||
|
|
0db0bc53fa | ||
|
|
0297c267e9 | ||
|
|
5af85f24f6 | ||
|
|
5110a7578e | ||
|
|
5af28670f0 | ||
|
|
efa2b781dd | ||
|
|
979f151181 | ||
|
|
6f125f18c3 | ||
|
|
edba7051f0 | ||
|
|
fa1ae8d746 | ||
|
|
a476617432 | ||
|
|
ffac13bfef | ||
|
|
f877bf21ba | ||
|
|
4bc4882b1f | ||
|
|
084c17dc26 | ||
|
|
26c39d6822 | ||
|
|
aefc173227 | ||
|
|
bf44a1cce6 | ||
|
|
a76c6c653d | ||
|
|
f11205bba7 | ||
|
|
72d9c5019c | ||
|
|
58d66e3e97 | ||
|
|
43c88a2fab | ||
|
|
9ce64ec6e1 | ||
|
|
c749d6a7dc | ||
|
|
f3e6d35c98 | ||
|
|
0be539b8a5 | ||
|
|
0454a369e5 | ||
|
|
010025cbfa | ||
|
|
61cae0a9f8 | ||
|
|
9e83d9e68c | ||
|
|
248acd5e26 | ||
|
|
42c1f5601a | ||
|
|
9c1a673047 | ||
|
|
99b90f90ac | ||
|
|
6ead8d8b49 | ||
|
|
9b12232e9f | ||
|
|
c1ed1baaad | ||
|
|
ab34312089 | ||
|
|
a25d92fbb7 |
300
.github/workflows/build.yml
vendored
300
.github/workflows/build.yml
vendored
@@ -6,6 +6,7 @@ on:
|
||||
- 'master'
|
||||
- 'releases/**'
|
||||
- 'tests/**'
|
||||
- 'feature/**'
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
@@ -18,11 +19,18 @@ jobs:
|
||||
win:
|
||||
runs-on: windows-2022
|
||||
name: 🪟 Windows MINGW64
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
|
||||
env:
|
||||
CCACHE_DIR: "${{ github.workspace }}/.ccache"
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
attestations: write
|
||||
|
||||
steps:
|
||||
- name: 🧰 Checkout
|
||||
uses: actions/checkout@v4
|
||||
@@ -81,11 +89,64 @@ jobs:
|
||||
run: |
|
||||
cd build
|
||||
ninja install
|
||||
|
||||
- name: 🪲 Create PDBs for MSI
|
||||
run: |
|
||||
cd build
|
||||
|
||||
mkdir cv2pdb
|
||||
cd cv2pdb
|
||||
wget https://github.com/rainers/cv2pdb/releases/download/v0.52/cv2pdb-0.52.zip
|
||||
unzip cv2pdb-0.52.zip
|
||||
cd ..
|
||||
|
||||
cv2pdb/cv2pdb.exe imhex.exe
|
||||
cv2pdb/cv2pdb.exe imhex-gui.exe
|
||||
cv2pdb/cv2pdb.exe libimhex.dll
|
||||
cv2pdb/cv2pdb.exe libpl.dll
|
||||
|
||||
for plugin in plugins/*.hexplug; do
|
||||
cv2pdb/cv2pdb.exe $plugin
|
||||
done
|
||||
|
||||
rm -rf cv2pdb
|
||||
|
||||
- name: 📦 Bundle MSI
|
||||
run: |
|
||||
cd build
|
||||
cpack
|
||||
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
|
||||
|
||||
- name: 🪲 Create PDBs for ZIP
|
||||
run: |
|
||||
cd build/install
|
||||
|
||||
mkdir cv2pdb
|
||||
cd cv2pdb
|
||||
wget https://github.com/rainers/cv2pdb/releases/download/v0.52/cv2pdb-0.52.zip
|
||||
unzip cv2pdb-0.52.zip
|
||||
cd ..
|
||||
|
||||
cv2pdb/cv2pdb.exe imhex.exe
|
||||
cv2pdb/cv2pdb.exe imhex-gui.exe
|
||||
cv2pdb/cv2pdb.exe libimhex.dll
|
||||
cv2pdb/cv2pdb.exe libpl.dll
|
||||
|
||||
for plugin in plugins/*.hexplug; do
|
||||
cv2pdb/cv2pdb.exe $plugin
|
||||
done
|
||||
|
||||
rm -rf cv2pdb
|
||||
|
||||
- name: 🗝️ Generate build provenance attestations
|
||||
uses: actions/attest-build-provenance@v2
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
with:
|
||||
subject-path: |
|
||||
imhex-*.msi
|
||||
|
||||
- name: ⬆️ Upload Windows Installer
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
@@ -122,12 +183,16 @@ jobs:
|
||||
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
|
||||
@@ -173,9 +238,13 @@ jobs:
|
||||
ninja
|
||||
|
||||
# MacOS build
|
||||
macos:
|
||||
macos-x86:
|
||||
runs-on: macos-13
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
attestations: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -205,10 +274,13 @@ jobs:
|
||||
max-size: 1G
|
||||
|
||||
- name: ⬇️ Install dependencies
|
||||
env:
|
||||
# Make brew not display useless errors
|
||||
HOMEBREW_TESTS: 1
|
||||
run: |
|
||||
brew reinstall python --quiet || true
|
||||
brew link --overwrite --quiet python || true
|
||||
brew bundle --no-lock --quiet --file dist/Brewfile || true
|
||||
brew link --overwrite --quiet python 2>/dev/null || true
|
||||
brew bundle --no-lock --quiet --file dist/macOS/Brewfile || true
|
||||
rm -rf /usr/local/Cellar/capstone
|
||||
|
||||
- name: ⬇️ Install classic glfw
|
||||
@@ -299,19 +371,20 @@ jobs:
|
||||
|
||||
- name: 📦 Create DMG
|
||||
run: |
|
||||
set -x
|
||||
mkdir bundle
|
||||
mv build/install/ImHex.app bundle
|
||||
cd bundle
|
||||
ln -s /Applications Applications
|
||||
cd ..
|
||||
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
|
||||
brew install imagemagick
|
||||
git clone https://github.com/sindresorhus/create-dmg
|
||||
cd create-dmg
|
||||
npm i && npm -g i
|
||||
cd ../build/install
|
||||
create-dmg ImHex.app || true
|
||||
mv *.dmg ../../imhex-${{ env.IMHEX_VERSION }}-macOS${{ matrix.suffix }}-x86_64.dmg
|
||||
|
||||
- name: 🗝️ Generate build provenance attestations
|
||||
uses: actions/attest-build-provenance@v2
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
with:
|
||||
subject-path: |
|
||||
./*.dmg
|
||||
|
||||
- name: ⬆️ Upload DMG
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -320,11 +393,13 @@ jobs:
|
||||
name: macOS DMG${{ matrix.suffix }} x86_64
|
||||
path: ./*.dmg
|
||||
|
||||
macos-arm64-build:
|
||||
macos-arm64:
|
||||
runs-on: ubuntu-24.04
|
||||
name: 🍎 macOS 13 arm64
|
||||
|
||||
outputs:
|
||||
IMHEX_VERSION: ${{ steps.build.outputs.IMHEX_VERSION }}
|
||||
|
||||
steps:
|
||||
- name: 🧰 Checkout
|
||||
uses: actions/checkout@v4
|
||||
@@ -367,9 +442,15 @@ jobs:
|
||||
macos-arm64-package:
|
||||
runs-on: macos-13
|
||||
name: 🍎 macOS 13 arm64 Packaging
|
||||
needs: macos-arm64-build
|
||||
needs: macos-arm64
|
||||
|
||||
env:
|
||||
IMHEX_VERSION: ${{ needs.macos-arm64-build.outputs.IMHEX_VERSION }}
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
attestations: write
|
||||
|
||||
steps:
|
||||
- name: ⬇️ Download artifact
|
||||
uses: actions/download-artifact@v4
|
||||
@@ -404,19 +485,20 @@ jobs:
|
||||
|
||||
- name: 📦 Create DMG
|
||||
run: |
|
||||
set -x
|
||||
mkdir bundle
|
||||
mv out/ImHex.app bundle
|
||||
cd bundle
|
||||
ln -s /Applications Applications
|
||||
cd ..
|
||||
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
|
||||
brew install imagemagick
|
||||
git clone https://github.com/sindresorhus/create-dmg
|
||||
cd create-dmg
|
||||
npm i && npm -g i
|
||||
cd ../out
|
||||
create-dmg ImHex.app || true
|
||||
mv *.dmg ../imhex-${{ env.IMHEX_VERSION }}-macOS${{ matrix.suffix }}-arm64.dmg
|
||||
|
||||
- name: 🗝️ Generate build provenance attestations
|
||||
uses: actions/attest-build-provenance@v2
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
with:
|
||||
subject-path: |
|
||||
./*.dmg
|
||||
|
||||
- name: ⬆️ Upload DMG
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -441,6 +523,10 @@ jobs:
|
||||
image: "ubuntu:${{ matrix.release_num }}"
|
||||
options: --privileged
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
attestations: write
|
||||
|
||||
steps:
|
||||
- name: ⬇️ Install setup dependencies
|
||||
run: apt update && apt install -y git curl
|
||||
@@ -498,9 +584,16 @@ jobs:
|
||||
- name: 📦 Bundle DEB
|
||||
run: |
|
||||
cp -r build/DEBIAN build/DebDir
|
||||
dpkg-deb -Zgzip --build build/DebDir
|
||||
dpkg-deb -Zzstd --build build/DebDir
|
||||
mv build/DebDir.deb imhex-${{ env.IMHEX_VERSION }}-Ubuntu-${{ matrix.release_num }}-x86_64.deb
|
||||
|
||||
- name: 🗝️ Generate build provenance attestations
|
||||
uses: actions/attest-build-provenance@v2
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
with:
|
||||
subject-path: |
|
||||
./*.deb
|
||||
|
||||
- name: ⬆️ Upload DEB
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
@@ -510,8 +603,26 @@ jobs:
|
||||
|
||||
# AppImage build
|
||||
appimage:
|
||||
runs-on: ubuntu-24.04
|
||||
name: ⬇️ AppImage
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- architecture: "x86_64"
|
||||
architecture_package: "amd64"
|
||||
architecture_appimage_builder: "x86_64"
|
||||
image: ubuntu-24.04
|
||||
- architecture: "arm64"
|
||||
architecture_package: "arm64"
|
||||
architecture_appimage_builder: "aarch64"
|
||||
image: ubuntu-24.04-arm
|
||||
|
||||
runs-on: ${{ matrix.image }}
|
||||
name: ⬇️ AppImage ${{ matrix.architecture }}
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
attestations: write
|
||||
|
||||
steps:
|
||||
- name: 🧰 Checkout
|
||||
uses: actions/checkout@v4
|
||||
@@ -533,22 +644,31 @@ jobs:
|
||||
|
||||
- name: 🛠️ Build using docker
|
||||
run: |
|
||||
docker buildx build . -f dist/appimage/Dockerfile --progress=plain --build-arg "BUILD_TYPE=$BUILD_TYPE" \
|
||||
--build-arg "GIT_COMMIT_HASH=$GITHUB_SHA" --build-arg "GIT_BRANCH=${GITHUB_REF##*/}" --output out
|
||||
docker buildx build . -f dist/AppImage/Dockerfile --progress=plain --build-arg "BUILD_TYPE=$BUILD_TYPE" \
|
||||
--build-arg "GIT_COMMIT_HASH=$GITHUB_SHA" --build-arg "GIT_BRANCH=${GITHUB_REF##*/}" \
|
||||
--build-arg "ARCHITECTURE_PACKAGE=${{ matrix.architecture_package }}" --build-arg "ARCHITECTURE_FILE_NAME=${{ matrix.architecture }}" --build-arg "ARCHITECTURE_APPIMAGE_BUILDER=${{ matrix.architecture_appimage_builder }}" \
|
||||
--output out
|
||||
|
||||
- name: 🗝️ Generate build provenance attestations
|
||||
uses: actions/attest-build-provenance@v2
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
with:
|
||||
subject-path: |
|
||||
out/*.AppImage
|
||||
out/*.AppImage.zsync
|
||||
|
||||
- name: ⬆️ Upload AppImage
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
if-no-files-found: error
|
||||
name: Linux AppImage x86_64
|
||||
name: Linux AppImage ${{ matrix.architecture }}
|
||||
path: 'out/*.AppImage'
|
||||
|
||||
- name: ⬆️ Upload AppImage zsync
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
if-no-files-found: error
|
||||
name: Linux AppImage zsync x86_64
|
||||
name: Linux AppImage zsync ${{ matrix.architecture }}
|
||||
path: 'out/*.AppImage.zsync'
|
||||
|
||||
# ArchLinux build
|
||||
@@ -559,6 +679,10 @@ jobs:
|
||||
container:
|
||||
image: archlinux:base-devel
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
attestations: write
|
||||
|
||||
steps:
|
||||
- name: ⬇️ Update all packages
|
||||
run: |
|
||||
@@ -642,6 +766,13 @@ jobs:
|
||||
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
|
||||
|
||||
- name: 🗝️ Generate build provenance attestations
|
||||
uses: actions/attest-build-provenance@v2
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
with:
|
||||
subject-path: |
|
||||
build/imhex-${{ env.IMHEX_VERSION }}-ArchLinux-x86_64.pkg.tar.zst
|
||||
|
||||
- name: ⬆️ Upload imhex-archlinux.pkg.tar.zst
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
@@ -680,6 +811,10 @@ jobs:
|
||||
image: "almalinux:9"
|
||||
options: --privileged --pid=host --security-opt apparmor=unconfined
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
attestations: write
|
||||
|
||||
steps:
|
||||
# This, together with the `--pid=host --security-opt apparmor=unconfined` docker options is required to allow
|
||||
# fedpkg to work inside a Docker container running on Ubuntu again.
|
||||
@@ -775,6 +910,13 @@ jobs:
|
||||
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
|
||||
|
||||
- name: 🗝️ Generate build provenance attestations
|
||||
uses: actions/attest-build-provenance@v2
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
with:
|
||||
subject-path: |
|
||||
imhex-${{ env.IMHEX_VERSION }}-${{ matrix.name }}-${{ matrix.release_num }}-x86_64.rpm
|
||||
|
||||
- name: ⬆️ Upload RPM
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
@@ -782,3 +924,85 @@ jobs:
|
||||
name: ${{ matrix.name }} ${{ matrix.release_num }} RPM x86_64
|
||||
path: |
|
||||
imhex-${{ env.IMHEX_VERSION }}-${{ matrix.name }}-${{ matrix.release_num }}-x86_64.rpm
|
||||
|
||||
webassembly-build:
|
||||
runs-on: ubuntu-24.04
|
||||
name: 🌍 Web
|
||||
permissions:
|
||||
pages: write
|
||||
id-token: write
|
||||
actions: write
|
||||
steps:
|
||||
- name: 🧰 Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: 📁 Restore docker /cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: cache
|
||||
key: web-cache-${{ hashFiles('**/CMakeLists.txt') }}
|
||||
|
||||
- name: 🐳 Inject /cache into docker
|
||||
uses: reproducible-containers/buildkit-cache-dance@v2
|
||||
with:
|
||||
cache-source: cache
|
||||
cache-target: /cache
|
||||
|
||||
- name: 🛠️ Build using docker
|
||||
run: |
|
||||
docker buildx build . -f dist/web/Dockerfile --progress=plain --build-arg 'JOBS=4' --output out --target raw
|
||||
|
||||
- name: 🔨 Fix permissions
|
||||
run: |
|
||||
chmod -c -R +rX "out/"
|
||||
|
||||
- name: ⬆️ Upload artifacts
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
with:
|
||||
path: out/
|
||||
|
||||
- name: 🔨 Copy necessary files
|
||||
run: |
|
||||
cp dist/web/serve.py out/start_imhex_web.py
|
||||
|
||||
- name: ⬆️ Upload package
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
if-no-files-found: error
|
||||
name: ImHex Web
|
||||
path: out/*
|
||||
|
||||
# See https://github.com/actions/cache/issues/342#issuecomment-1711054115
|
||||
- name: 🗑️ Delete old cache
|
||||
continue-on-error: true
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
gh extension install actions/gh-actions-cache || true
|
||||
gh actions-cache delete "build-web-cache" --confirm || true
|
||||
|
||||
webassembly-deploy:
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
permissions:
|
||||
pages: write
|
||||
id-token: write
|
||||
actions: write
|
||||
name: 📃 Deploy to GitHub Pages
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
if: ${{ github.ref == 'refs/heads/master' && github.event.repository.fork == false }}
|
||||
needs: webassembly-build
|
||||
|
||||
steps:
|
||||
- name: 🌍 Deploy WebAssembly Build to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v4
|
||||
|
||||
- name: 🗑️ Delete artifact
|
||||
uses: geekyeggo/delete-artifact@v5
|
||||
with:
|
||||
name: github-pages
|
||||
|
||||
79
.github/workflows/build_web.yml
vendored
79
.github/workflows/build_web.yml
vendored
@@ -1,79 +0,0 @@
|
||||
name: Build for the web
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'releases/**'
|
||||
- 'tests/**'
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
BUILD_TYPE: Release
|
||||
|
||||
permissions:
|
||||
pages: write
|
||||
id-token: write
|
||||
actions: write
|
||||
|
||||
jobs:
|
||||
|
||||
build:
|
||||
runs-on: ubuntu-24.04
|
||||
name: 🌍 WebAssembly
|
||||
steps:
|
||||
- name: 🧰 Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: 📁 Restore docker /cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: cache
|
||||
key: web-cache-${{ hashFiles('**/CMakeLists.txt') }}
|
||||
|
||||
- name: 🐳 Inject /cache into docker
|
||||
uses: reproducible-containers/buildkit-cache-dance@v2
|
||||
with:
|
||||
cache-source: cache
|
||||
cache-target: /cache
|
||||
|
||||
- name: 🛠️ Build using docker
|
||||
run: |
|
||||
docker buildx build . -f dist/web/Dockerfile --progress=plain --build-arg 'JOBS=4' --output out --target raw
|
||||
|
||||
- name: 🔨 Fix permissions
|
||||
run: |
|
||||
chmod -c -R +rX "out/"
|
||||
|
||||
- name: ⬆️ Upload artifacts
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
with:
|
||||
path: out/
|
||||
|
||||
# See https://github.com/actions/cache/issues/342#issuecomment-1711054115
|
||||
- name: 🗑️ Delete old cache
|
||||
continue-on-error: true
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
gh extension install actions/gh-actions-cache || true
|
||||
gh actions-cache delete "build-web-cache" --confirm || true
|
||||
|
||||
deploy:
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
|
||||
name: 📃 Deploy to GitHub Pages
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
if: ${{ github.ref == 'refs/heads/master' && github.event.repository.fork == false }}
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- name: 🌍 Deploy
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v4
|
||||
3
.github/workflows/release.yml
vendored
3
.github/workflows/release.yml
vendored
@@ -63,7 +63,7 @@ jobs:
|
||||
token: ${{ secrets.RELEASE_TOKEN }}
|
||||
|
||||
release-upload-artifacts:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04
|
||||
name: Release Upload Artifacts
|
||||
|
||||
steps:
|
||||
@@ -117,6 +117,7 @@ jobs:
|
||||
run: |
|
||||
mv "Windows Portable x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-x86_64.zip
|
||||
mv "Windows Portable NoGPU x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-NoGPU-x86_64.zip
|
||||
mv "ImHex Web.zip" imhex-${{ env.IMHEX_VERSION }}-web.zip
|
||||
|
||||
- name: ⬆️ Upload everything to release
|
||||
uses: softprops/action-gh-release@4634c16e79c963813287e889244c50009e7f0981
|
||||
|
||||
2
.github/workflows/stale_issues.yml
vendored
2
.github/workflows/stale_issues.yml
vendored
@@ -6,7 +6,7 @@ on:
|
||||
|
||||
jobs:
|
||||
close-issues:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
1
.github/workflows/tests.yml
vendored
1
.github/workflows/tests.yml
vendored
@@ -6,6 +6,7 @@ on:
|
||||
- 'master'
|
||||
- 'releases/**'
|
||||
- 'tests/**'
|
||||
- 'feature/**'
|
||||
pull_request:
|
||||
branches:
|
||||
- 'master'
|
||||
|
||||
7
.gitmodules
vendored
7
.gitmodules
vendored
@@ -28,7 +28,7 @@
|
||||
ignore = dirty
|
||||
[submodule "lib/third_party/lunasvg"]
|
||||
path = lib/third_party/lunasvg
|
||||
url = https://github.com/sammycage/lunasvg
|
||||
url = https://github.com/WerWolv/lunasvg
|
||||
ignore = dirty
|
||||
|
||||
[submodule "lib/external/libromfs"]
|
||||
@@ -43,4 +43,7 @@
|
||||
|
||||
[submodule "lib/third_party/HashLibPlus"]
|
||||
path = lib/third_party/HashLibPlus
|
||||
url = https://github.com/WerWolv/HashLibPlus
|
||||
url = https://github.com/WerWolv/HashLibPlus
|
||||
[submodule "lib/external/disassembler"]
|
||||
path = lib/external/disassembler
|
||||
url = https://github.com/WerWolv/Disassembler
|
||||
|
||||
@@ -81,7 +81,6 @@ if (IMHEX_ENABLE_UNIT_TESTS)
|
||||
endif ()
|
||||
|
||||
# Configure more resources that will be added to the install package
|
||||
generatePDBs()
|
||||
generateSDKDirectory()
|
||||
|
||||
# Handle package generation
|
||||
|
||||
@@ -27,6 +27,11 @@ chmod +x imhex-*.AppImage
|
||||
./imhex-*.AppImage
|
||||
```
|
||||
|
||||
If you're experiencing glib / libgtk assertion failures, you might need to setup your `XDG_DATA_DIRS` env var correctly. In this case, run the following command before executing the AppImage. (See issue [ImHex/#2038](https://github.com/WerWolv/ImHex/issues/2038))
|
||||
```bash
|
||||
export XDG_DATA_DIRS="/usr/local/share:/usr/share"
|
||||
```
|
||||
|
||||
#### Flatpak
|
||||
To install the Flatpak, make sure you have the Flathub repository added to your system. Then simply run the following command:
|
||||
|
||||
|
||||
16
README.md
16
README.md
@@ -38,8 +38,8 @@ If you like my work, please consider supporting me on GitHub Sponsors, Patreon o
|
||||
</p>
|
||||
|
||||
## Screenshots
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
<details>
|
||||
<summary><strong>More Screenshots</strong></summary>
|
||||
@@ -328,12 +328,12 @@ To use ImHex, the following minimal system requirements need to be met.
|
||||
- RHEL/AlmaLinux
|
||||
- Arch Linux
|
||||
- Basically any other distro will work as well when compiling ImHex from sources.
|
||||
- **CPU**: x86_64 (64 Bit)
|
||||
- **CPU**: Officially supported are x86_64 and ARM64, though any Little Endian 64 bit CPU should work.
|
||||
- **GPU**: OpenGL 3.0 or higher
|
||||
- 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
|
||||
- **RAM**: 256MB, more may be required for more complicated analysis
|
||||
- **Storage**: 150MB
|
||||
- **RAM**: ~150MiB, more is required for more complex analysis
|
||||
- **Storage**: 150MiB
|
||||
|
||||
## Installing
|
||||
|
||||
@@ -342,8 +342,10 @@ Information on how to install ImHex can be found in the [Install](/INSTALL.md) g
|
||||
## Compiling
|
||||
|
||||
To compile ImHex on any platform, GCC (or Clang) is required with a version that supports C++23 or higher.
|
||||
On macOS, Clang is also required to compile some ObjC code.
|
||||
All releases are being built using latest available GCC.
|
||||
Windows and Linux releases are being built using latest available GCC.
|
||||
MacOS releases are being built using latest available LLVM Clang.
|
||||
|
||||
Important to note is, the MSVC and AppleClang compilers are both **NOT** supported since they're both generally severely outdated and lack features GCC and LLVM Clang have.
|
||||
|
||||
> [!NOTE]
|
||||
> Many dependencies are bundled into the repository using submodules so make sure to clone it using the `--recurse-submodules` option.
|
||||
|
||||
@@ -1,3 +1,17 @@
|
||||
# Some libraries we use set the BUILD_SHARED_LIBS variable to ON, which causes CMake to
|
||||
# display a warning about options being set using set() instead of option().
|
||||
# Explicitly set the policy to NEW to suppress the warning.
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
|
||||
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0063 NEW)
|
||||
|
||||
if (POLICY CMP0177)
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0177 OLD)
|
||||
cmake_policy(SET CMP0177 OLD)
|
||||
endif()
|
||||
|
||||
set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "Disable deprecated warnings" FORCE)
|
||||
|
||||
include(FetchContent)
|
||||
|
||||
if(IMHEX_STRIP_RELEASE)
|
||||
@@ -226,7 +240,7 @@ macro(createPackage)
|
||||
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.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.svg DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps RENAME imhex.svg)
|
||||
downloadImHexPatternsFiles("./share/imhex")
|
||||
|
||||
# install AppStream file
|
||||
@@ -370,15 +384,6 @@ macro(configureCMake)
|
||||
message(WARNING "LTO is not supported: ${output_error}")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# Some libraries we use set the BUILD_SHARED_LIBS variable to ON, which causes CMake to
|
||||
# display a warning about options being set using set() instead of option().
|
||||
# Explicitly set the policy to NEW to suppress the warning.
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
|
||||
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0063 NEW)
|
||||
|
||||
set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "Disable deprecated warnings" FORCE)
|
||||
endmacro()
|
||||
|
||||
function(configureProject)
|
||||
@@ -649,6 +654,7 @@ macro(addBundledLibraries)
|
||||
set(FPHSA_NAME_MISMATCHED ON CACHE BOOL "")
|
||||
|
||||
if(NOT USE_SYSTEM_FMT)
|
||||
set(FMT_INSTALL OFF CACHE BOOL "Disable install targets for libfmt" FORCE)
|
||||
add_subdirectory(${THIRD_PARTY_LIBS_FOLDER}/fmt EXCLUDE_FROM_ALL)
|
||||
set(FMT_LIBRARIES fmt::fmt-header-only)
|
||||
else()
|
||||
@@ -728,6 +734,7 @@ macro(addBundledLibraries)
|
||||
endif()
|
||||
|
||||
add_subdirectory(${EXTERNAL_LIBS_FOLDER}/pattern_language EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(${EXTERNAL_LIBS_FOLDER}/disassembler EXCLUDE_FROM_ALL)
|
||||
|
||||
if (LIBPL_SHARED_LIBRARY)
|
||||
install(
|
||||
@@ -784,59 +791,6 @@ function(enableUnityBuild TARGET)
|
||||
endif ()
|
||||
endfunction()
|
||||
|
||||
function(generatePDBs)
|
||||
if (NOT IMHEX_GENERATE_PDBS)
|
||||
return()
|
||||
endif ()
|
||||
|
||||
if (NOT WIN32 OR CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
return()
|
||||
endif ()
|
||||
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
cv2pdb
|
||||
URL "https://github.com/rainers/cv2pdb/releases/download/v0.52/cv2pdb-0.52.zip"
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP ON
|
||||
)
|
||||
FetchContent_Populate(cv2pdb)
|
||||
|
||||
set(PDBS_TO_GENERATE main main-forwarder libimhex ${PLUGINS})
|
||||
foreach (PDB ${PDBS_TO_GENERATE})
|
||||
if (PDB STREQUAL "main")
|
||||
set(GENERATED_PDB imhex)
|
||||
elseif (PDB STREQUAL "main-forwarder")
|
||||
set(GENERATED_PDB imhex-gui)
|
||||
elseif (PDB STREQUAL "libimhex")
|
||||
set(GENERATED_PDB libimhex)
|
||||
else ()
|
||||
set(GENERATED_PDB plugins/${PDB})
|
||||
endif ()
|
||||
|
||||
if (IMHEX_REPLACE_DWARF_WITH_PDB)
|
||||
set(PDB_OUTPUT_PATH ${CMAKE_BINARY_DIR}/${GENERATED_PDB})
|
||||
else ()
|
||||
set(PDB_OUTPUT_PATH)
|
||||
endif()
|
||||
|
||||
add_custom_target(${PDB}_pdb DEPENDS ${CMAKE_BINARY_DIR}/${GENERATED_PDB}.pdb)
|
||||
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/${GENERATED_PDB}.pdb
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
COMMAND
|
||||
(
|
||||
${CMAKE_COMMAND} -E remove -f ${CMAKE_BINARY_DIR}/${GENERATED_PDB}.pdb &&
|
||||
${cv2pdb_SOURCE_DIR}/cv2pdb64.exe $<TARGET_FILE:${PDB}> ${PDB_OUTPUT_PATH} &&
|
||||
${CMAKE_COMMAND} -E remove -f ${CMAKE_BINARY_DIR}/${GENERATED_PDB}
|
||||
) || (exit 0)
|
||||
COMMAND_EXPAND_LISTS)
|
||||
|
||||
install(FILES ${CMAKE_BINARY_DIR}/${GENERATED_PDB}.pdb DESTINATION ".")
|
||||
|
||||
add_dependencies(imhex_all ${PDB}_pdb)
|
||||
endforeach ()
|
||||
|
||||
endfunction()
|
||||
|
||||
function(generateSDKDirectory)
|
||||
if (WIN32)
|
||||
set(SDK_PATH "./sdk")
|
||||
@@ -865,6 +819,12 @@ function(generateSDKDirectory)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/cmake/build_helpers.cmake DESTINATION "${SDK_PATH}/cmake")
|
||||
install(DIRECTORY ${CMAKE_SOURCE_DIR}/cmake/sdk/ DESTINATION "${SDK_PATH}")
|
||||
install(TARGETS libimhex ARCHIVE DESTINATION "${SDK_PATH}/lib")
|
||||
|
||||
install(DIRECTORY ${CMAKE_SOURCE_DIR}/plugins/ui DESTINATION "${SDK_PATH}/lib" PATTERN "**/source/*" EXCLUDE)
|
||||
install(TARGETS ui ARCHIVE DESTINATION "${SDK_PATH}/lib")
|
||||
|
||||
install(DIRECTORY ${CMAKE_SOURCE_DIR}/plugins/fonts DESTINATION "${SDK_PATH}/lib" PATTERN "**/source/*" EXCLUDE)
|
||||
install(TARGETS fonts ARCHIVE DESTINATION "${SDK_PATH}/lib")
|
||||
endfunction()
|
||||
|
||||
function(addIncludesFromLibrary target library)
|
||||
|
||||
@@ -11,32 +11,23 @@ AppDir:
|
||||
exec_args: $@
|
||||
apt:
|
||||
arch:
|
||||
- amd64
|
||||
- "{{ARCHITECTURE_PACKAGE}}"
|
||||
allow_unauthenticated: true
|
||||
sources:
|
||||
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ oracular main restricted
|
||||
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ oracular-updates main restricted
|
||||
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ oracular universe
|
||||
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ oracular-updates universe
|
||||
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ oracular multiverse
|
||||
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ oracular-updates multiverse
|
||||
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ oracular-backports main restricted
|
||||
universe multiverse
|
||||
- sourceline: deb http://security.ubuntu.com/ubuntu oracular-security main restricted
|
||||
- sourceline: deb http://security.ubuntu.com/ubuntu oracular-security universe
|
||||
- sourceline: deb http://security.ubuntu.com/ubuntu oracular-security multiverse
|
||||
- sourceline: 'deb [arch=amd64] http://us.archive.ubuntu.com/ubuntu/ oracular main restricted universe multiverse'
|
||||
- sourceline: 'deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ oracular main restricted universe multiverse'
|
||||
include:
|
||||
- librsvg2-common
|
||||
- libbz2-1.0:amd64
|
||||
- libcap2:amd64
|
||||
- libdbus-1-3:amd64
|
||||
- libfontconfig1:amd64
|
||||
- libgpg-error0:amd64
|
||||
- liblzma5:amd64
|
||||
- libnss-mdns:amd64
|
||||
- libpcre3:amd64
|
||||
- libselinux1:amd64
|
||||
- libtinfo6:amd64
|
||||
- libbz2-1.0
|
||||
- libcap2
|
||||
- libdbus-1-3
|
||||
- libfontconfig1
|
||||
- libgpg-error0
|
||||
- liblzma5
|
||||
- libnss-mdns
|
||||
- libpcre3
|
||||
- libselinux1
|
||||
- libtinfo6
|
||||
files:
|
||||
include:
|
||||
- /lib/x86_64-linux-gnu/libLLVM-13.so.1
|
||||
@@ -133,6 +124,6 @@ AppDir:
|
||||
- usr/share/doc/*/NEWS.*
|
||||
- usr/share/doc/*/TODO.*
|
||||
AppImage:
|
||||
arch: x86_64
|
||||
update-information: gh-releases-zsync|WerWolv|ImHex|latest|imhex-*-x86_64.AppImage.zsync
|
||||
file_name: imhex-{{VERSION}}-x86_64.AppImage
|
||||
arch: "{{ARCHITECTURE_APPIMAGE_BUILDER}}"
|
||||
update-information: gh-releases-zsync|WerWolv|ImHex|latest|imhex-*-{{ARCHITECTURE_FILE_NAME}}.AppImage.zsync
|
||||
file_name: imhex-{{VERSION}}-{{ARCHITECTURE_FILE_NAME}}.AppImage
|
||||
@@ -30,8 +30,14 @@ ARG LTO=ON
|
||||
ARG BUILD_TYPE=RelWithDebInfo
|
||||
ARG GIT_COMMIT_HASH
|
||||
ARG GIT_BRANCH
|
||||
ARG ARCHITECTURE_PACKAGE
|
||||
ARG ARCHITECTURE_FILE_NAME
|
||||
ARG ARCHITECTURE_APPIMAGE_BUILDER
|
||||
WORKDIR /build
|
||||
SHELL ["bash", "-c"] # Ubuntu sh doesnt support string substitution
|
||||
|
||||
# Ubuntu sh doesnt support string substitution
|
||||
SHELL ["bash", "-c"]
|
||||
|
||||
RUN <<EOF
|
||||
# Prepare ImHex build
|
||||
set -xe
|
||||
@@ -73,7 +79,10 @@ pip3 install git+https://github.com/AppImageCrafters/appimage-builder@f38699e
|
||||
|
||||
# Package ImHex as AppImage
|
||||
export VERSION=$(cat /imhex/VERSION)
|
||||
appimage-builder --recipe /imhex/dist/AppImageBuilder.yml
|
||||
export ARCHITECTURE_PACKAGE=${ARCHITECTURE_PACKAGE}
|
||||
export ARCHITECTURE_FILE_NAME=${ARCHITECTURE_FILE_NAME}
|
||||
export ARCHITECTURE_APPIMAGE_BUILDER=${ARCHITECTURE_APPIMAGE_BUILDER}
|
||||
appimage-builder --recipe /imhex/dist/AppImage/AppImageBuilder.yml
|
||||
EOF
|
||||
|
||||
FROM scratch
|
||||
2
dist/get_deps_msys2.sh
vendored
2
dist/get_deps_msys2.sh
vendored
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
pacman -S --needed --noconfirm pactoys
|
||||
pacman -S --needed --noconfirm pactoys unzip
|
||||
pacboy -S --needed --noconfirm \
|
||||
gcc:p \
|
||||
lld:p \
|
||||
|
||||
6
dist/imhex.desktop
vendored
6
dist/imhex.desktop
vendored
@@ -1,4 +1,5 @@
|
||||
[Desktop Entry]
|
||||
Version=1.0
|
||||
Name=ImHex
|
||||
Comment=ImHex Hex Editor
|
||||
GenericName=Hex Editor
|
||||
@@ -10,3 +11,8 @@ Categories=Development;IDE;
|
||||
StartupWMClass=imhex
|
||||
Keywords=static-analysis;reverse-engineering;disassembler;disassembly;hacking;forensics;hex-editor;cybersecurity;security;binary-analysis;
|
||||
MimeType=application/vnd.imhex.proj;
|
||||
Actions=NewFile;
|
||||
|
||||
[Desktop Action NewFile]
|
||||
Exec=imhex --new
|
||||
Name=Create New File
|
||||
0
dist/Brewfile → dist/macOS/Brewfile
vendored
0
dist/Brewfile → dist/macOS/Brewfile
vendored
2
dist/macOS/arm64.Dockerfile
vendored
2
dist/macOS/arm64.Dockerfile
vendored
@@ -1,5 +1,5 @@
|
||||
# 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:clang19-nosdk as build
|
||||
|
||||
ENV MACOSX_DEPLOYMENT_TARGET 13.0
|
||||
|
||||
|
||||
2
dist/macOS/arm64.crosscompile.Dockerfile
vendored
2
dist/macOS/arm64.crosscompile.Dockerfile
vendored
@@ -1,4 +1,4 @@
|
||||
# This image is is provided for reference, but a (probably more up to date) image should be available at https://github.com/iTrooz/macos-crosscompile
|
||||
# This image is provided for reference, but a (probably more up to date) image should be available at https://github.com/iTrooz/macos-crosscompile
|
||||
FROM ubuntu:22.04
|
||||
|
||||
ENV PATH $PATH:/osxcross/target/bin
|
||||
|
||||
4
dist/rpm/imhex.spec
vendored
4
dist/rpm/imhex.spec
vendored
@@ -123,9 +123,11 @@ cp -a lib/third_party/xdgpp/LICENSE %{buildroot
|
||||
%doc README.md
|
||||
%{_bindir}/imhex
|
||||
%{_bindir}/imhex-updater
|
||||
%{_datadir}/pixmaps/%{name}.png
|
||||
%{_datadir}/pixmaps/%{name}.svg
|
||||
%{_datadir}/applications/%{name}.desktop
|
||||
%{_datadir}/mime/packages/%{name}.xml
|
||||
%{_libdir}/libimhex.so*
|
||||
%{_libdir}/%{name}/
|
||||
%{_libdir}/*.hexpluglib
|
||||
/usr/lib/debug/%{_libdir}/*.debug
|
||||
%{_metainfodir}/net.werwolv.%{name}.metainfo.xml
|
||||
11
dist/web/Dockerfile
vendored
11
dist/web/Dockerfile
vendored
@@ -1,4 +1,4 @@
|
||||
FROM emscripten/emsdk:3.1.51 as build
|
||||
FROM emscripten/emsdk:3.1.51 AS build
|
||||
|
||||
# Used to invalidate layer cache but not mount cache
|
||||
# See https://github.com/moby/moby/issues/41715#issuecomment-733976493
|
||||
@@ -27,7 +27,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
|
||||
' >> /emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake
|
||||
EOF
|
||||
|
||||
ENV VCPKG_DEFAULT_BINARY_CACHE /cache/vcpkg
|
||||
ENV VCPKG_DEFAULT_BINARY_CACHE=/cache/vcpkg
|
||||
RUN --mount=type=cache,target=/cache <<EOF
|
||||
# Install dependencies with vcpkg
|
||||
set -xe
|
||||
@@ -45,7 +45,7 @@ EOF
|
||||
|
||||
# Build ImHex
|
||||
ARG JOBS=4
|
||||
ENV CCACHE_DIR /cache/ccache
|
||||
ENV CCACHE_DIR=/cache/ccache
|
||||
|
||||
RUN mkdir /build
|
||||
WORKDIR /build
|
||||
@@ -67,6 +67,7 @@ cmake /imhex
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_TOOLCHAIN_FILE=/vcpkg/scripts/buildsystems/vcpkg.cmake \
|
||||
-DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake \
|
||||
-DLIBROMFS_COMPRESS_RESOURCES=OFF \
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
|
||||
ninja -j $JOBS
|
||||
@@ -79,7 +80,7 @@ EOF
|
||||
# See https://stackoverflow.com/questions/41701849/cannot-modify-accept-encoding-with-fetch https://github.com/AnthumChris/fetch-progress-indicators/issues/13
|
||||
RUN du -b /build/imhex.wasm | cut -f1 > imhex.wasm.size
|
||||
|
||||
FROM scratch as raw
|
||||
FROM scratch AS raw
|
||||
COPY --from=build [ \
|
||||
# ImHex \
|
||||
"/build/imhex.wasm", \
|
||||
@@ -93,7 +94,7 @@ COPY --from=build [ \
|
||||
"/build/wasm-config.js", \
|
||||
"/build/enable-threads.js", \
|
||||
"/build/favicon.ico", \
|
||||
"/build/icon.png", \
|
||||
"/build/icon.svg", \
|
||||
"/build/manifest.json", \
|
||||
"/build/robots.txt", \
|
||||
"/build/sitemap.xml", \
|
||||
|
||||
BIN
dist/web/source/favicon.ico
vendored
BIN
dist/web/source/favicon.ico
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 162 KiB |
BIN
dist/web/source/icon.png
vendored
BIN
dist/web/source/icon.png
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 157 KiB |
11
dist/web/source/icon.svg
vendored
Normal file
11
dist/web/source/icon.svg
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" version="1">
|
||||
<rect style="opacity:0.2" width="55" height="10" x="5" y="-60" rx="1.41" transform="rotate(90)"/>
|
||||
<rect style="fill:#2b50a1" width="55" height="10" x="4" y="-60" rx="1.41" transform="rotate(90)"/>
|
||||
<rect style="fill:#2b50a1" width="55" height="10" x="4" y="-14" rx="1.41" transform="rotate(90)"/>
|
||||
<rect style="fill:#2b50a1" width="55" height="10" x="4" y="-33" rx="1.41" transform="rotate(90)"/>
|
||||
<path style="opacity:0.2" d="M 5.3808594,5 C 4.6158118,5 4,5.6158118 4,6.3808594 V 13.619141 C 4,14.384188 4.6158118,15 5.3808594,15 H 31.619141 C 32.384188,15 33,14.384188 33,13.619141 V 6.3808594 C 33,5.6158118 32.384188,5 31.619141,5 Z M 40.400391,5 C 39.624791,5 39,5.6247906 39,6.4003906 V 13.599609 C 39,14.375209 39.624791,15 40.400391,15 H 58.599609 C 59.375209,15 60,14.375209 60,13.599609 V 6.4003906 C 60,5.6247906 59.375209,5 58.599609,5 Z M 5.3808594,50 C 4.6158118,50 4,50.615812 4,51.380859 v 7.238282 C 4,59.384188 4.6158118,60 5.3808594,60 H 31.619141 C 32.384188,60 33,59.384188 33,58.619141 V 51.380859 C 33,50.615812 32.384188,50 31.619141,50 Z"/>
|
||||
<rect style="fill:#3a6be0" width="29" height="10" x="4" y="4" rx="1.381"/>
|
||||
<rect style="fill:#3a6be0" width="21" height="10" x="39" y="4" rx="1.4"/>
|
||||
<rect style="fill:#3a6be0" width="29" height="10" x="4" y="49" rx="1.381"/>
|
||||
<path style="fill:#ffffff;opacity:0.1" d="M 5.3808594 4 C 4.6158118 4 4 4.6158118 4 5.3808594 L 4 6.3808594 C 4 5.6158118 4.6158118 5 5.3808594 5 L 31.619141 5 C 32.384188 5 33 5.6158118 33 6.3808594 L 33 5.3808594 C 33 4.6158118 32.384188 4 31.619141 4 L 5.3808594 4 z M 40.400391 4 C 39.624791 4 39 4.6247906 39 5.4003906 L 39 6.4003906 C 39 5.6247906 39.624791 5 40.400391 5 L 58.599609 5 C 59.375209 5 60 5.6247906 60 6.4003906 L 60 5.4003906 C 60 4.6247906 59.375209 4 58.599609 4 L 40.400391 4 z M 5.3808594 49 C 4.6158118 49 4 49.615812 4 50.380859 L 4 51.380859 C 4 50.615812 4.6158118 50 5.3808594 50 L 31.619141 50 C 32.384188 50 33 50.615812 33 51.380859 L 33 50.380859 C 33 49.615812 32.384188 49 31.619141 49 L 5.3808594 49 z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
4
dist/web/source/index.html
vendored
4
dist/web/source/index.html
vendored
@@ -11,7 +11,7 @@
|
||||
<meta name="title" content="ImHex">
|
||||
<meta name="description" content="Free and extremely powerful Online Hex Editor for your Web Browser. ImHex is a free and open source Hex Editor for Reverse Engineers and Developers and Data Analysts.">
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||
<link rel="apple-touch-icon" href="icon.png">
|
||||
<link rel="apple-touch-icon" href="icon.svg">
|
||||
|
||||
<!-- Open Graph / Facebook -->
|
||||
<meta property="og:type" content="website">
|
||||
@@ -38,7 +38,7 @@
|
||||
"founder": "WerWolv",
|
||||
"slogan": "A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.",
|
||||
"url": "https://imhex.werwolv.net",
|
||||
"logo": "https://imhex.werwolv.net/assets/logos/logo.png"
|
||||
"logo": "https://imhex.werwolv.net/assets/logos/logo.svg"
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
4
dist/web/source/manifest.json
vendored
4
dist/web/source/manifest.json
vendored
@@ -10,8 +10,8 @@
|
||||
],
|
||||
"icons": [
|
||||
{
|
||||
"src": "icon.png",
|
||||
"type": "image/png",
|
||||
"src": "icon.svg",
|
||||
"type": "image/svg",
|
||||
"sizes": "640x640"
|
||||
}
|
||||
],
|
||||
|
||||
9
dist/web/source/wasm-config.js
vendored
9
dist/web/source/wasm-config.js
vendored
@@ -261,4 +261,11 @@ function js_resizeCanvas() {
|
||||
canvas.left = document.documentElement.clientLeft;
|
||||
canvas.width = Math.min(document.documentElement.clientWidth, window.innerWidth || 0);
|
||||
canvas.height = Math.min(document.documentElement.clientHeight, window.innerHeight || 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent some default browser shortcuts from preventing ImHex ones to work
|
||||
document.addEventListener('keydown', e => {
|
||||
if (e.ctrlKey) {
|
||||
if (e.which == 83) e.preventDefault();
|
||||
}
|
||||
})
|
||||
1
lib/external/disassembler
vendored
Submodule
1
lib/external/disassembler
vendored
Submodule
Submodule lib/external/disassembler added at 172c61ec3f
2
lib/external/libromfs
vendored
2
lib/external/libromfs
vendored
Submodule lib/external/libromfs updated: 03adcfdde0...60ba28a53b
2
lib/external/libwolv
vendored
2
lib/external/libwolv
vendored
Submodule lib/external/libwolv updated: b9d7f4abaf...323ad9e4f0
2
lib/external/pattern_language
vendored
2
lib/external/pattern_language
vendored
Submodule lib/external/pattern_language updated: f45156a55c...947b99cbe7
@@ -38,6 +38,7 @@ set(LIBIMHEX_SOURCES
|
||||
source/helpers/debugging.cpp
|
||||
source/helpers/default_paths.cpp
|
||||
source/helpers/imgui_hooks.cpp
|
||||
source/helpers/semantic_version.cpp
|
||||
|
||||
source/test/tests.cpp
|
||||
|
||||
@@ -49,6 +50,7 @@ set(LIBIMHEX_SOURCES
|
||||
source/ui/view.cpp
|
||||
source/ui/popup.cpp
|
||||
source/ui/toast.cpp
|
||||
source/ui/banner.cpp
|
||||
|
||||
source/subcommands/subcommands.cpp
|
||||
)
|
||||
@@ -133,13 +135,14 @@ if (NOT IMHEX_EXTERNAL_PLUGIN_BUILD)
|
||||
if (WIN32)
|
||||
set_target_properties(libimhex PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
|
||||
target_link_options(libimhex PRIVATE -Wl,--export-all-symbols)
|
||||
target_link_libraries(libimhex PRIVATE Netapi32.lib)
|
||||
elseif (APPLE)
|
||||
find_library(FOUNDATION NAMES Foundation)
|
||||
target_link_libraries(libimhex PUBLIC ${FOUNDATION})
|
||||
endif ()
|
||||
|
||||
target_link_libraries(libimhex PRIVATE microtar libwolv ${NFD_LIBRARIES} magic dl ${JTHREAD_LIBRARIES})
|
||||
target_link_libraries(libimhex PUBLIC libpl ${IMGUI_LIBRARIES})
|
||||
target_link_libraries(libimhex PRIVATE microtar libwolv ${NFD_LIBRARIES} magic dl)
|
||||
target_link_libraries(libimhex PUBLIC libpl ${IMGUI_LIBRARIES} ${JTHREAD_LIBRARIES})
|
||||
|
||||
precompileHeaders(libimhex "${CMAKE_CURRENT_SOURCE_DIR}/include")
|
||||
endif()
|
||||
|
||||
@@ -20,6 +20,7 @@ using ImGuiDataType = int;
|
||||
using ImGuiInputTextFlags = int;
|
||||
struct ImColor;
|
||||
enum ImGuiCustomCol : int;
|
||||
typedef int ImGuiColorEditFlags;
|
||||
|
||||
namespace hex {
|
||||
|
||||
@@ -43,7 +44,6 @@ namespace hex {
|
||||
plugins when needed.
|
||||
*/
|
||||
namespace ContentRegistry {
|
||||
|
||||
/* Settings Registry. Allows adding of new entries into the ImHex preferences window. */
|
||||
namespace Settings {
|
||||
|
||||
@@ -177,7 +177,7 @@ namespace hex {
|
||||
|
||||
class SliderDataSize : public Widget {
|
||||
public:
|
||||
SliderDataSize(u64 defaultValue, u64 min, u64 max) : m_value(defaultValue), m_min(min), m_max(max) { }
|
||||
SliderDataSize(u64 defaultValue, u64 min, u64 max, u64 stepSize) : m_value(defaultValue), m_min(min), m_max(max), m_stepSize(stepSize) { }
|
||||
bool draw(const std::string &name) override;
|
||||
|
||||
void load(const nlohmann::json &data) override;
|
||||
@@ -188,11 +188,12 @@ namespace hex {
|
||||
protected:
|
||||
u64 m_value;
|
||||
u64 m_min, m_max;
|
||||
u64 m_stepSize;
|
||||
};
|
||||
|
||||
class ColorPicker : public Widget {
|
||||
public:
|
||||
explicit ColorPicker(ImColor defaultColor);
|
||||
explicit ColorPicker(ImColor defaultColor, ImGuiColorEditFlags flags = 0);
|
||||
|
||||
bool draw(const std::string &name) override;
|
||||
|
||||
@@ -202,12 +203,14 @@ namespace hex {
|
||||
[[nodiscard]] ImColor getColor() const;
|
||||
|
||||
protected:
|
||||
std::array<float, 4> m_value{};
|
||||
std::array<float, 4> m_value = {}, m_defaultValue = {};
|
||||
ImGuiColorEditFlags m_flags;
|
||||
};
|
||||
|
||||
class DropDown : public Widget {
|
||||
public:
|
||||
explicit DropDown(const std::vector<std::string> &items, const std::vector<nlohmann::json> &settingsValues, const nlohmann::json &defaultItem) : m_items(items), m_settingsValues(settingsValues), m_defaultItem(defaultItem) { }
|
||||
explicit DropDown(const std::vector<std::string> &items, const std::vector<nlohmann::json> &settingsValues, const nlohmann::json &defaultItem) : m_items(items.begin(), items.end()), m_settingsValues(settingsValues), m_defaultItem(defaultItem) { }
|
||||
explicit DropDown(const std::vector<UnlocalizedString> &items, const std::vector<nlohmann::json> &settingsValues, const nlohmann::json &defaultItem) : m_items(items), m_settingsValues(settingsValues), m_defaultItem(defaultItem) { }
|
||||
|
||||
bool draw(const std::string &name) override;
|
||||
|
||||
@@ -218,7 +221,7 @@ namespace hex {
|
||||
const nlohmann::json& getValue() const;
|
||||
|
||||
protected:
|
||||
std::vector<std::string> m_items;
|
||||
std::vector<UnlocalizedString> m_items;
|
||||
std::vector<nlohmann::json> m_settingsValues;
|
||||
nlohmann::json m_defaultItem;
|
||||
|
||||
@@ -623,8 +626,7 @@ namespace hex {
|
||||
/* Data Inspector Registry. Allows adding of new types to the data inspector */
|
||||
namespace DataInspector {
|
||||
|
||||
enum class NumberDisplayStyle
|
||||
{
|
||||
enum class NumberDisplayStyle : u8 {
|
||||
Decimal,
|
||||
Hexadecimal,
|
||||
Octal
|
||||
@@ -678,6 +680,13 @@ namespace hex {
|
||||
std::optional<impl::EditingFunction> editingFunction = std::nullopt
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Allows adding new menu items to data inspector row context menus. Call this function inside the
|
||||
* draw function of the data inspector row definition.
|
||||
* @param function Callback that will draw menu items
|
||||
*/
|
||||
void drawMenuItems(const std::function<void()> &function);
|
||||
|
||||
}
|
||||
|
||||
/* Data Processor Node Registry. Allows adding new processor nodes to be used in the data processor */
|
||||
@@ -1008,7 +1017,7 @@ namespace hex {
|
||||
|
||||
namespace impl {
|
||||
|
||||
using Callback = std::function<std::string(prv::Provider *provider, u64 address, size_t size)>;
|
||||
using Callback = std::function<std::string(prv::Provider *provider, u64 address, size_t size, bool preview)>;
|
||||
struct ExportMenuEntry {
|
||||
UnlocalizedString unlocalizedName;
|
||||
Callback callback;
|
||||
@@ -1016,7 +1025,7 @@ namespace hex {
|
||||
|
||||
struct FindOccurrence {
|
||||
Region region;
|
||||
enum class DecodeType { ASCII, Binary, UTF16, Unsigned, Signed, Float, Double } decodeType;
|
||||
enum class DecodeType { ASCII, UTF8, Binary, UTF16, Unsigned, Signed, Float, Double } decodeType;
|
||||
std::endian endian = std::endian::native;
|
||||
bool selected;
|
||||
};
|
||||
@@ -1354,6 +1363,7 @@ namespace hex {
|
||||
|
||||
}
|
||||
|
||||
/* Data Information Registry. Allows adding new analyzers to the data information view */
|
||||
namespace DataInformation {
|
||||
|
||||
class InformationSection {
|
||||
@@ -1420,6 +1430,54 @@ namespace hex {
|
||||
|
||||
}
|
||||
|
||||
/* Disassembler Registry. Allows adding new disassembler architectures */
|
||||
namespace Disassembler {
|
||||
|
||||
struct Instruction {
|
||||
u64 address;
|
||||
u64 offset;
|
||||
size_t size;
|
||||
std::string bytes;
|
||||
std::string mnemonic;
|
||||
std::string operators;
|
||||
};
|
||||
|
||||
class Architecture {
|
||||
public:
|
||||
explicit Architecture(std::string name) : m_name(std::move(name)) {}
|
||||
virtual ~Architecture() = default;
|
||||
|
||||
virtual bool start() = 0;
|
||||
virtual void end() = 0;
|
||||
|
||||
virtual std::optional<Instruction> disassemble(u64 imageBaseAddress, u64 instructionLoadAddress, u64 instructionDataAddress, std::span<const u8> code) = 0;
|
||||
virtual void drawSettings() = 0;
|
||||
|
||||
[[nodiscard]] const std::string& getName() const { return m_name; }
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
};
|
||||
|
||||
namespace impl {
|
||||
|
||||
using CreatorFunction = std::function<std::unique_ptr<Architecture>()>;
|
||||
|
||||
void addArchitectureCreator(CreatorFunction function);
|
||||
|
||||
const std::map<std::string, CreatorFunction>& getArchitectures();
|
||||
|
||||
}
|
||||
|
||||
template<std::derived_from<Architecture> T>
|
||||
void add(auto && ...args) {
|
||||
impl::addArchitectureCreator([...args = std::move(args)] {
|
||||
return std::make_unique<T>(args...);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
#include <hex/helpers/logger.hpp>
|
||||
#include <hex/helpers/patches.hpp>
|
||||
|
||||
#include <wolv/types/type_name.hpp>
|
||||
|
||||
@@ -32,15 +31,6 @@
|
||||
#define EVENT_DEF_NO_LOG(event_name, ...) EVENT_DEF_IMPL(event_name, #event_name, false, __VA_ARGS__)
|
||||
|
||||
|
||||
/* Forward declarations */
|
||||
struct GLFWwindow;
|
||||
namespace hex {
|
||||
class Achievement;
|
||||
class View;
|
||||
}
|
||||
|
||||
namespace pl::ptrn { class Pattern; }
|
||||
|
||||
namespace hex {
|
||||
|
||||
namespace impl {
|
||||
@@ -100,7 +90,8 @@ namespace hex {
|
||||
|
||||
/**
|
||||
* @brief The EventManager allows subscribing to and posting events to different parts of the program.
|
||||
* To create a new event, use the EVENT_DEF macro. This will create a new event type with the given name and parameters
|
||||
* To create a new event, use the EVENT_DEF macro. This will create a new event type with the given name and parameters.
|
||||
* Events should be created in an `events_*.hpp` category file under the `events` folder, and never directly here.
|
||||
*/
|
||||
class EventManager {
|
||||
public:
|
||||
@@ -200,122 +191,4 @@ namespace hex {
|
||||
static void unsubscribe(void *token, impl::EventId id);
|
||||
};
|
||||
|
||||
/* Default Events */
|
||||
|
||||
/**
|
||||
* @brief Called when Imhex finished startup, and will enter the main window rendering loop
|
||||
*/
|
||||
EVENT_DEF(EventImHexStartupFinished);
|
||||
|
||||
EVENT_DEF(EventFileLoaded, std::fs::path);
|
||||
EVENT_DEF(EventDataChanged, prv::Provider *);
|
||||
EVENT_DEF(EventHighlightingChanged);
|
||||
EVENT_DEF(EventWindowClosing, GLFWwindow *);
|
||||
EVENT_DEF(EventRegionSelected, ImHexApi::HexEditor::ProviderRegion);
|
||||
EVENT_DEF(EventAbnormalTermination, int);
|
||||
EVENT_DEF(EventThemeChanged);
|
||||
EVENT_DEF(EventOSThemeChanged);
|
||||
EVENT_DEF(EventDPIChanged, float, float);
|
||||
EVENT_DEF(EventWindowFocused, bool);
|
||||
|
||||
/**
|
||||
* @brief Called when the provider is created.
|
||||
* This event is responsible for (optionally) initializing the provider and calling EventProviderOpened
|
||||
* (although the event can also be called manually without problem)
|
||||
*/
|
||||
EVENT_DEF(EventProviderCreated, prv::Provider *);
|
||||
EVENT_DEF(EventProviderChanged, prv::Provider *, prv::Provider *);
|
||||
|
||||
/**
|
||||
* @brief Called as a continuation of EventProviderCreated
|
||||
* this event is normally called immediately after EventProviderCreated successfully initialized the provider.
|
||||
* If no initialization (Provider::skipLoadInterface() has been set), this event should be called manually
|
||||
* If skipLoadInterface failed, this event is not called
|
||||
*
|
||||
* @note this is not related to Provider::open()
|
||||
*/
|
||||
EVENT_DEF(EventProviderOpened, prv::Provider *);
|
||||
EVENT_DEF(EventProviderClosing, prv::Provider *, bool *);
|
||||
EVENT_DEF(EventProviderClosed, prv::Provider *);
|
||||
EVENT_DEF(EventProviderDeleted, prv::Provider *);
|
||||
EVENT_DEF(EventProviderSaved, prv::Provider *);
|
||||
EVENT_DEF(EventWindowInitialized);
|
||||
EVENT_DEF(EventWindowDeinitializing, GLFWwindow *);
|
||||
EVENT_DEF(EventBookmarkCreated, ImHexApi::Bookmarks::Entry&);
|
||||
|
||||
/**
|
||||
* @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(EventPatternExecuted, const std::string&);
|
||||
EVENT_DEF(EventPatternEditorChanged, const std::string&);
|
||||
EVENT_DEF(EventStoreContentDownloaded, const std::fs::path&);
|
||||
EVENT_DEF(EventStoreContentRemoved, const std::fs::path&);
|
||||
EVENT_DEF(EventImHexClosing);
|
||||
EVENT_DEF(EventAchievementUnlocked, const Achievement&);
|
||||
EVENT_DEF(EventSearchBoxClicked, u32);
|
||||
EVENT_DEF(EventViewOpened, View*);
|
||||
EVENT_DEF(EventFirstLaunch);
|
||||
|
||||
EVENT_DEF(EventFileDragged, bool);
|
||||
EVENT_DEF(EventFileDropped, std::fs::path);
|
||||
|
||||
EVENT_DEF(EventProviderDataModified, prv::Provider *, u64, u64, const u8*);
|
||||
EVENT_DEF(EventProviderDataInserted, prv::Provider *, u64, u64);
|
||||
EVENT_DEF(EventProviderDataRemoved, prv::Provider *, u64, u64);
|
||||
EVENT_DEF(EventProviderDirtied, prv::Provider *);
|
||||
|
||||
/**
|
||||
* @brief Called when a project has been loaded
|
||||
*/
|
||||
EVENT_DEF(EventProjectOpened);
|
||||
|
||||
EVENT_DEF_NO_LOG(EventFrameBegin);
|
||||
EVENT_DEF_NO_LOG(EventFrameEnd);
|
||||
EVENT_DEF_NO_LOG(EventSetTaskBarIconState, u32, u32, u32);
|
||||
EVENT_DEF_NO_LOG(EventImGuiElementRendered, ImGuiID, const std::array<float, 4>&);
|
||||
|
||||
EVENT_DEF(RequestAddInitTask, std::string, bool, std::function<bool()>);
|
||||
EVENT_DEF(RequestAddExitTask, std::string, std::function<bool()>);
|
||||
EVENT_DEF(RequestOpenWindow, std::string);
|
||||
EVENT_DEF(RequestHexEditorSelectionChange, Region);
|
||||
EVENT_DEF(RequestPatternEditorSelectionChange, u32, u32);
|
||||
EVENT_DEF(RequestJumpToPattern, const pl::ptrn::Pattern*);
|
||||
EVENT_DEF(RequestAddBookmark, Region, std::string, std::string, color_t, u64*);
|
||||
EVENT_DEF(RequestRemoveBookmark, u64);
|
||||
EVENT_DEF(RequestSetPatternLanguageCode, std::string);
|
||||
EVENT_DEF(RequestRunPatternCode);
|
||||
EVENT_DEF(RequestLoadPatternLanguageFile, std::fs::path);
|
||||
EVENT_DEF(RequestSavePatternLanguageFile, std::fs::path);
|
||||
EVENT_DEF(RequestUpdateWindowTitle);
|
||||
EVENT_DEF(RequestCloseImHex, bool);
|
||||
EVENT_DEF(RequestRestartImHex);
|
||||
EVENT_DEF(RequestOpenFile, std::fs::path);
|
||||
EVENT_DEF(RequestChangeTheme, std::string);
|
||||
EVENT_DEF(RequestOpenPopup, std::string);
|
||||
EVENT_DEF(RequestAddVirtualFile, std::fs::path, std::vector<u8>, Region);
|
||||
|
||||
/**
|
||||
* @brief Creates a provider from it's unlocalized name, and add it to the provider list
|
||||
*/
|
||||
EVENT_DEF(RequestCreateProvider, std::string, bool, bool, hex::prv::Provider **);
|
||||
EVENT_DEF(RequestInitThemeHandlers);
|
||||
|
||||
/**
|
||||
* @brief Send an event to the main Imhex instance
|
||||
*/
|
||||
EVENT_DEF(SendMessageToMainInstance, const std::string, const std::vector<u8>&);
|
||||
|
||||
/**
|
||||
* Move the data from all PerProvider instances from one provider to another.
|
||||
* The 'from' provider should not have any per provider data after this, and should be immediately deleted
|
||||
*/
|
||||
EVENT_DEF(MovePerProviderData, prv::Provider *, prv::Provider *);
|
||||
|
||||
/**
|
||||
* Called when ImHex managed to catch an error in a general try/catch to prevent/recover from a crash
|
||||
*/
|
||||
EVENT_DEF(EventCrashRecovered, const std::exception &);
|
||||
}
|
||||
120
lib/libimhex/include/hex/api/events/events_gui.hpp
Normal file
120
lib/libimhex/include/hex/api/events/events_gui.hpp
Normal file
@@ -0,0 +1,120 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/api/event_manager.hpp>
|
||||
|
||||
/* Forward declarations */
|
||||
struct GLFWwindow;
|
||||
namespace hex { class View; }
|
||||
|
||||
/* GUI events definitions */
|
||||
namespace hex {
|
||||
|
||||
/**
|
||||
* @brief Signals a newly opened window
|
||||
*
|
||||
* This event is sent when the window has just been opened and docked by the Window manager.
|
||||
*
|
||||
* FIXME: In the event that a newly created window is already docked, this will not be sent.
|
||||
*
|
||||
* FIXME: This is currently only used for the introduction tutorial.
|
||||
* If the event's only purpose is this, maybe rename it?
|
||||
*
|
||||
* @param view the new view reference
|
||||
*/
|
||||
EVENT_DEF(EventViewOpened, View*);
|
||||
|
||||
/**
|
||||
* @brief Signals a change in the DPI scale.
|
||||
*
|
||||
* This event is called once at startup to signal native scale definition (by passing the same value twice).
|
||||
* On Windows OS, this event can also be posted if the window DPI has been changed.
|
||||
*
|
||||
* @param oldScale the old scale
|
||||
* @param newScale the current scale that's now in use
|
||||
*/
|
||||
EVENT_DEF(EventDPIChanged, float, float);
|
||||
|
||||
/**
|
||||
* @brief Signals the focus of the ImHex main window.
|
||||
*
|
||||
* This is directly tied as a GLFW window focus callback, and will be called accordingly when GLFW detects
|
||||
* a change in focus.
|
||||
*
|
||||
* @param isFocused true if the window is focused
|
||||
*/
|
||||
EVENT_DEF(EventWindowFocused, bool);
|
||||
|
||||
/**
|
||||
* @brief Signals a window being closed.
|
||||
*
|
||||
* Allows reactive clean up of running tasks, and prevents ImHex from closing
|
||||
* by displaying an exit confirmation popup.
|
||||
*
|
||||
* @param window The window reference
|
||||
*/
|
||||
EVENT_DEF(EventWindowClosing, GLFWwindow*);
|
||||
|
||||
/**
|
||||
* @brief Informs that the main window is initialized
|
||||
*
|
||||
* On Windows OS, it is used to initialize system theme, if ImHex's theme is following it.
|
||||
*
|
||||
* FIXME: Change event name to reflect Theme detection, if it's only used for that purpose?
|
||||
*/
|
||||
EVENT_DEF(EventWindowInitialized);
|
||||
|
||||
/**
|
||||
* @brief Informs that the main window is deinitializing
|
||||
*
|
||||
* Allows for lifecycle cleanup before ImHex shutdown.
|
||||
*
|
||||
* @param window The window reference
|
||||
*/
|
||||
EVENT_DEF(EventWindowDeinitializing, GLFWwindow*);
|
||||
|
||||
/**
|
||||
* @brief Signals a theme change in the host OS
|
||||
*
|
||||
* Allows ImHex to react to OS theme changes dynamically during execution.
|
||||
*/
|
||||
EVENT_DEF(EventOSThemeChanged);
|
||||
|
||||
}
|
||||
|
||||
/* silent (no-logging) GUI events definitions */
|
||||
namespace hex {
|
||||
|
||||
/**
|
||||
* @brief Signals the start of a new ImGui frame
|
||||
*/
|
||||
EVENT_DEF_NO_LOG(EventFrameBegin);
|
||||
|
||||
/**
|
||||
* @brief Signals the end of an ImGui frame
|
||||
*/
|
||||
EVENT_DEF_NO_LOG(EventFrameEnd);
|
||||
|
||||
/**
|
||||
* @brief Windows OS: Sets the taskbar icon state
|
||||
*
|
||||
* This event is used on Windows OS to display progress through the taskbar icon (the famous "green loading bar"
|
||||
* in the taskbar).
|
||||
*
|
||||
* @param progressState the progress state (converted from the TaskProgressState enum)
|
||||
* @param progressType the type of progress (converted from the TaskProgressType enum)
|
||||
* @param percentage actual progress percentage (expected from 0 to 100)
|
||||
*
|
||||
* @see hex::ImHexApi::System::TaskProgressState
|
||||
* @see hex::ImHexApi::System::TaskProgressType
|
||||
*/
|
||||
EVENT_DEF_NO_LOG(EventSetTaskBarIconState, u32, u32, u32);
|
||||
|
||||
/**
|
||||
* @brief Informs of an ImGui element being rendered
|
||||
*
|
||||
* @param elementId the element's ID
|
||||
* @param boundingBox the bounding box (composed of 4 floats)
|
||||
*/
|
||||
EVENT_DEF_NO_LOG(EventImGuiElementRendered, ImGuiID, const std::array<float, 4>&);
|
||||
|
||||
}
|
||||
158
lib/libimhex/include/hex/api/events/events_interaction.hpp
Normal file
158
lib/libimhex/include/hex/api/events/events_interaction.hpp
Normal file
@@ -0,0 +1,158 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/api/event_manager.hpp>
|
||||
#include <hex/helpers/patches.hpp>
|
||||
|
||||
/* Forward declarations */
|
||||
namespace hex { class Achievement; }
|
||||
|
||||
/* Interaction events definitions */
|
||||
namespace hex {
|
||||
|
||||
/**
|
||||
* @brief Signals a file was loaded
|
||||
*
|
||||
* FIXME: this event is unused and should be scrapped.
|
||||
*
|
||||
* @param path the loaded file's path
|
||||
*/
|
||||
EVENT_DEF(EventFileLoaded, std::fs::path);
|
||||
|
||||
/**
|
||||
* @brief Signals a change in the current data
|
||||
*
|
||||
* Enables provider reaction to data change, especially the data inspector.
|
||||
*
|
||||
* This is caused by the following:
|
||||
* - an explicit provider reload, requested by the user (Ctrl+R)
|
||||
* - any user action that results in the creation of an "undo" stack action (generally a data modification)
|
||||
*
|
||||
* @param provider the Provider subject to the data change
|
||||
*/
|
||||
EVENT_DEF(EventDataChanged, prv::Provider *);
|
||||
|
||||
/**
|
||||
* @brief Signals a change in highlighting
|
||||
*
|
||||
* The event's only purpose is for the Hex editor to clear highlights when receiving this event.
|
||||
*/
|
||||
EVENT_DEF(EventHighlightingChanged);
|
||||
|
||||
/**
|
||||
* @brief Informs of a provider region being selected
|
||||
*
|
||||
* This is very generally used to signal user actions that select a specific region within the provider.
|
||||
* It is also used to pass on regions when the provider changes.
|
||||
*
|
||||
* @param providerRegion the provider-aware region being selected
|
||||
*/
|
||||
EVENT_DEF(EventRegionSelected, ImHexApi::HexEditor::ProviderRegion);
|
||||
|
||||
/**
|
||||
* @brief Signals a theme change
|
||||
*
|
||||
* On Windows OS, this is used to reflect the theme color onto the window frame.
|
||||
*/
|
||||
EVENT_DEF(EventThemeChanged);
|
||||
|
||||
/**
|
||||
* @brief Signals that a bookmark was created
|
||||
*
|
||||
* For now, this event's only purpose is to unlock an achievement.
|
||||
*
|
||||
* @param entry the new bookmark
|
||||
*/
|
||||
EVENT_DEF(EventBookmarkCreated, ImHexApi::Bookmarks::Entry&);
|
||||
|
||||
/**
|
||||
* @brief Called upon creation of an IPS patch.
|
||||
* As for now, the event only serves a purpose for the achievement unlock.
|
||||
*
|
||||
* @param data the pointer to the patch content's start
|
||||
* @param size the patch data size
|
||||
* @param kind the patch's kind
|
||||
*/
|
||||
EVENT_DEF(EventPatchCreated, const u8*, u64, const PatchKind);
|
||||
|
||||
/**
|
||||
* @brief Signals the beginning of evaluation of the current pattern
|
||||
*
|
||||
* This allows resetting the drawer view for the pattern data while we wait for the execution completion.
|
||||
*/
|
||||
EVENT_DEF(EventPatternEvaluating);
|
||||
|
||||
/**
|
||||
* @brief Signals the completion of the pattern evaluation
|
||||
*
|
||||
* This causes another reset in the drawer view, to refresh the table displayed to the user.
|
||||
*
|
||||
* @param code the execution's status code
|
||||
*/
|
||||
EVENT_DEF(EventPatternExecuted, const std::string&);
|
||||
|
||||
/**
|
||||
* @brief Denotes when pattern editor has changed
|
||||
*
|
||||
* FIXME: this event is unused and should be scrapped.
|
||||
*/
|
||||
EVENT_DEF(EventPatternEditorChanged, const std::string&);
|
||||
|
||||
/**
|
||||
* @brief Signals that a Content Store item was downloaded
|
||||
*
|
||||
* FIXME: this event is unused and should be scrapped.
|
||||
*
|
||||
* @param path the item's path on the filesystem
|
||||
*/
|
||||
EVENT_DEF(EventStoreContentDownloaded, const std::fs::path&);
|
||||
|
||||
/**
|
||||
* @brief Signals the removal of a Content Store item
|
||||
*
|
||||
* Note: at the time of the event firing, the item has already been removed from the filesystem.
|
||||
*
|
||||
* FIXME: this event is unused and should be scrapped.
|
||||
*
|
||||
* @param path the item's old file path where it used to be in the filesystem
|
||||
*/
|
||||
EVENT_DEF(EventStoreContentRemoved, const std::fs::path&);
|
||||
|
||||
/**
|
||||
* @brief Signals the unlocking of an achievement
|
||||
*
|
||||
* This is used by the achievement manager to refresh the achievement display, as well as store progress to
|
||||
* the appropriate storage file.
|
||||
*
|
||||
* @param achievement the achievement that was unlocked
|
||||
*/
|
||||
EVENT_DEF(EventAchievementUnlocked, const Achievement&);
|
||||
|
||||
/**
|
||||
* @brief Signals a click on the search box
|
||||
*
|
||||
* As there are different behaviours depending on the click (left or right) done by the user,
|
||||
* this allows the consequences of said click to be registered in their own components.
|
||||
*
|
||||
* @param button the ImGuiMouseButton's value
|
||||
*/
|
||||
EVENT_DEF(EventSearchBoxClicked, u32);
|
||||
|
||||
/**
|
||||
* @brief Updates on whether a file is being dragged into ImHex
|
||||
*
|
||||
* Allows ImGUi to display a file dragging information on screen when a file is being dragged.
|
||||
*
|
||||
* @param isFileDragged true if a file is being dragged
|
||||
*/
|
||||
EVENT_DEF(EventFileDragged, bool);
|
||||
|
||||
/**
|
||||
* @brief Triggers loading when a file is dropped
|
||||
*
|
||||
* The event fires when a file is dropped into ImHex, which passes it to file handlers to load it.
|
||||
*
|
||||
* @param path the dropped file's path
|
||||
*/
|
||||
EVENT_DEF(EventFileDropped, std::fs::path);
|
||||
|
||||
}
|
||||
72
lib/libimhex/include/hex/api/events/events_lifecycle.hpp
Normal file
72
lib/libimhex/include/hex/api/events/events_lifecycle.hpp
Normal file
@@ -0,0 +1,72 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/api/event_manager.hpp>
|
||||
|
||||
/* Lifecycle events definitions */
|
||||
namespace hex {
|
||||
|
||||
/**
|
||||
* @brief Called when Imhex finished startup, and will enter the main window rendering loop
|
||||
*/
|
||||
EVENT_DEF(EventImHexStartupFinished);
|
||||
|
||||
/**
|
||||
* @brief Called when ImHex is closing, to trigger the last shutdown hooks
|
||||
*
|
||||
* This is the last event to fire before complete graceful shutdown.
|
||||
*/
|
||||
EVENT_DEF(EventImHexClosing);
|
||||
|
||||
/**
|
||||
* @brief Signals that it's ImHex first launch ever
|
||||
*
|
||||
* This event allows for the launch of the ImHex tutorial (also called Out of Box experience).
|
||||
*/
|
||||
EVENT_DEF(EventFirstLaunch);
|
||||
|
||||
/**
|
||||
* FIXME: this event is unused and should be scrapped.
|
||||
*/
|
||||
EVENT_DEF(EventAnySettingChanged);
|
||||
|
||||
/**
|
||||
* @brief Ensures correct plugin cleanup on crash
|
||||
*
|
||||
* This event is fired when catching an unexpected error that cannot be recovered and
|
||||
* which forces Imhex to close immediately.
|
||||
*
|
||||
* Subscribing to this event ensures that the plugin can correctly clean up any mission-critical tasks
|
||||
* before forceful shutdown.
|
||||
*
|
||||
* @param signal the POSIX signal code
|
||||
*/
|
||||
EVENT_DEF(EventAbnormalTermination, int);
|
||||
|
||||
/**
|
||||
* @brief Informs of the ImHex versions (and difference, if any)
|
||||
*
|
||||
* Called on every startup to inform subscribers of the two versions picked up:
|
||||
* - the version of the previous launch, gathered from the settings file
|
||||
* - the current version, gathered directly from C++ code
|
||||
*
|
||||
* In most cases, and unless ImHex was updated, the two parameters will be the same.
|
||||
*
|
||||
* FIXME: Maybe rename the event to signal a startup information, instead of the misleading
|
||||
* title that the event could be fired when ImHex detects that it was updated since last launch?
|
||||
*
|
||||
* @param previousLaunchVersion ImHex's version during the previous launch
|
||||
* @param currentVersion ImHex's current version for this startup
|
||||
*/
|
||||
EVENT_DEF(EventImHexUpdated, SemanticVersion, SemanticVersion);
|
||||
|
||||
/**
|
||||
* @brief Called when ImHex managed to catch an error in a general try/catch to prevent/recover from a crash
|
||||
*/
|
||||
EVENT_DEF(EventCrashRecovered, const std::exception &);
|
||||
|
||||
/**
|
||||
* @brief Called when a project has been loaded
|
||||
*/
|
||||
EVENT_DEF(EventProjectOpened);
|
||||
|
||||
}
|
||||
113
lib/libimhex/include/hex/api/events/events_provider.hpp
Normal file
113
lib/libimhex/include/hex/api/events/events_provider.hpp
Normal file
@@ -0,0 +1,113 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
#include <hex/api/event_manager.hpp>
|
||||
|
||||
/* Provider events definitions */
|
||||
namespace hex {
|
||||
/**
|
||||
* @brief Called when the provider is created.
|
||||
* This event is responsible for (optionally) initializing the provider and calling EventProviderOpened
|
||||
* (although the event can also be called manually without problem)
|
||||
*/
|
||||
EVENT_DEF(EventProviderCreated, prv::Provider *);
|
||||
|
||||
/**
|
||||
* @brief Called as a continuation of EventProviderCreated
|
||||
* this event is normally called immediately after EventProviderCreated successfully initialized the provider.
|
||||
* If no initialization (Provider::skipLoadInterface() has been set), this event should be called manually
|
||||
* If skipLoadInterface failed, this event is not called
|
||||
*
|
||||
* @note this is not related to Provider::open()
|
||||
*/
|
||||
EVENT_DEF(EventProviderOpened, prv::Provider *);
|
||||
|
||||
/**
|
||||
* @brief Signals a change in provider (in-place)
|
||||
*
|
||||
* Note: if the provider was deleted, the new ("current") provider will be `nullptr`
|
||||
*
|
||||
* @param oldProvider the old provider
|
||||
* @param currentProvider the current provider
|
||||
*/
|
||||
EVENT_DEF(EventProviderChanged, prv::Provider *, prv::Provider *);
|
||||
|
||||
/**
|
||||
* @brief Signals that a provider was saved
|
||||
*
|
||||
* @param provider the saved provider
|
||||
*/
|
||||
EVENT_DEF(EventProviderSaved, prv::Provider *);
|
||||
|
||||
/**
|
||||
* @brief Signals a provider is closing
|
||||
*
|
||||
* FIXME: as for now, this behaves as a request more than an event. Also, the boolean is always set to true,
|
||||
* and serves no purpose. This should be moved into the Provider requests section and declared accordingly.
|
||||
*
|
||||
* @param provider the closing provider
|
||||
* @param shouldClose whether the provider should close
|
||||
*/
|
||||
EVENT_DEF(EventProviderClosing, prv::Provider *, bool *);
|
||||
|
||||
/**
|
||||
* @brief Signals that a provider was closed
|
||||
*
|
||||
* As this is a closure information broadcast, the provider should generally not be accessed, as it could
|
||||
* result in problems.
|
||||
*
|
||||
* @param provider the now-closed provider
|
||||
*/
|
||||
EVENT_DEF(EventProviderClosed, prv::Provider *);
|
||||
|
||||
/**
|
||||
* @brief Signals that a provider is being deleted
|
||||
*
|
||||
* Provider's data should not be accessed.
|
||||
*
|
||||
* @param provider the provider
|
||||
*/
|
||||
EVENT_DEF(EventProviderDeleted, prv::Provider *);
|
||||
|
||||
}
|
||||
|
||||
/* Provider data events definitions */
|
||||
namespace hex {
|
||||
|
||||
/**
|
||||
* @brief Signals the dirtying of a provider
|
||||
*
|
||||
* Any data modification that occurs in a provider dirties it, until its state is either saved or restored.
|
||||
* This event signals that fact to subscribers so additional code can be executed for certain cases.
|
||||
*/
|
||||
EVENT_DEF(EventProviderDirtied, prv::Provider *);
|
||||
|
||||
/**
|
||||
* @brief Signals an insertion of new data into a provider
|
||||
*
|
||||
* @param provider the provider
|
||||
* @param offset the start of the insertion
|
||||
* @param size the new data's size
|
||||
*/
|
||||
EVENT_DEF(EventProviderDataInserted, prv::Provider *, u64, u64);
|
||||
|
||||
/**
|
||||
* @brief Signals a modification in the provider's data
|
||||
*
|
||||
* @param provider the provider
|
||||
* @param offset the data modification's offset (start address)
|
||||
* @param size the buffer's size
|
||||
* @param buffer the modified data written at this address
|
||||
*/
|
||||
EVENT_DEF(EventProviderDataModified, prv::Provider *, u64, u64, const u8*);
|
||||
|
||||
/**
|
||||
* @brief Signals a removal of some of the provider's data
|
||||
*
|
||||
* @param provider the provider
|
||||
* @param offset the deletion offset (start address)
|
||||
* @param size the deleted data's size
|
||||
*/
|
||||
EVENT_DEF(EventProviderDataRemoved, prv::Provider *, u64, u64);
|
||||
|
||||
}
|
||||
37
lib/libimhex/include/hex/api/events/requests_gui.hpp
Normal file
37
lib/libimhex/include/hex/api/events/requests_gui.hpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/api/event_manager.hpp>
|
||||
|
||||
/* GUI requests definitions */
|
||||
namespace hex {
|
||||
|
||||
/**
|
||||
* @brief Requests the opening of a new window.
|
||||
*
|
||||
* @param name the window's name
|
||||
*/
|
||||
EVENT_DEF(RequestOpenWindow, std::string);
|
||||
|
||||
/**
|
||||
* @brief Centralized request to update ImHex's main window title
|
||||
*
|
||||
* This request can be called to make ImHex refresh its main window title, taking into account a new project
|
||||
* or file opened/closed.
|
||||
*/
|
||||
EVENT_DEF(RequestUpdateWindowTitle);
|
||||
|
||||
/**
|
||||
* @brief Requests a theme type (light or dark) change
|
||||
*
|
||||
* @param themeType either `Light` or `Dark`
|
||||
*/
|
||||
EVENT_DEF(RequestChangeTheme, std::string);
|
||||
|
||||
/**
|
||||
* @brief Requests the opening of a popup
|
||||
*
|
||||
* @param name the popup's name
|
||||
*/
|
||||
EVENT_DEF(RequestOpenPopup, std::string);
|
||||
|
||||
}
|
||||
116
lib/libimhex/include/hex/api/events/requests_interaction.hpp
Normal file
116
lib/libimhex/include/hex/api/events/requests_interaction.hpp
Normal file
@@ -0,0 +1,116 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
#include <hex/api/event_manager.hpp>
|
||||
|
||||
/* Forward declarations */
|
||||
namespace pl::ptrn { class Pattern; }
|
||||
|
||||
/* Interaction requests definitions */
|
||||
namespace hex {
|
||||
|
||||
/**
|
||||
* @brief Requests a selection change in the Hex editor
|
||||
*
|
||||
* This request is handled by the Hex editor, which proceeds to check if the selection is valid.
|
||||
* If it is invalid, the Hex editor fires the `EventRegionSelected` event with nullptr region info.
|
||||
*
|
||||
* @param region the region that should be selected
|
||||
*/
|
||||
EVENT_DEF(RequestHexEditorSelectionChange, Region);
|
||||
|
||||
/**
|
||||
* @brief Requests the Pattern editor to move selection
|
||||
*
|
||||
* Requests the Pattern editor to move the cursor's position to reflect the user's click or movement.
|
||||
*
|
||||
* @param line the target line
|
||||
* @param column the target column
|
||||
*/
|
||||
EVENT_DEF(RequestPatternEditorSelectionChange, u32, u32);
|
||||
|
||||
/**
|
||||
* @brief Requests a jump to a given pattern
|
||||
*
|
||||
* This request is fired by the Hex editor when the user asks to jump to the pattern.
|
||||
* It is then caught and reflected by the Pattern data component.
|
||||
*
|
||||
* @param pattern the pattern to jump to
|
||||
*/
|
||||
EVENT_DEF(RequestJumpToPattern, const pl::ptrn::Pattern*);
|
||||
|
||||
/**
|
||||
* @brief Requests to add a bookmark
|
||||
*
|
||||
* @param region the region to be bookmarked
|
||||
* @param name the bookmark's name
|
||||
* @param comment a comment
|
||||
* @param color the color
|
||||
* @param id the bookmark's unique ID
|
||||
*/
|
||||
EVENT_DEF(RequestAddBookmark, Region, std::string, std::string, color_t, u64*);
|
||||
|
||||
/**
|
||||
* @brief Requests a bookmark removal
|
||||
*
|
||||
* @param id the bookmark's unique ID
|
||||
*/
|
||||
EVENT_DEF(RequestRemoveBookmark, u64);
|
||||
|
||||
/**
|
||||
* @brief Request the Pattern editor to set its code
|
||||
*
|
||||
* This request allows the rest of ImHex to interface with the Pattern editor component, by setting its code.
|
||||
* This allows for `.hexpat` file loading, and more.
|
||||
*
|
||||
* @param code the code's string
|
||||
*/
|
||||
EVENT_DEF(RequestSetPatternLanguageCode, std::string);
|
||||
|
||||
/**
|
||||
* @brief Requests the Pattern editor to run the current code
|
||||
*
|
||||
* This is only ever used in the introduction tutorial.
|
||||
*
|
||||
* FIXME: the name is misleading, as for now this activates the pattern's auto-evaluation rather than a
|
||||
* one-off execution
|
||||
*/
|
||||
EVENT_DEF(RequestRunPatternCode);
|
||||
|
||||
/**
|
||||
* @brief Request to load a pattern language file
|
||||
*
|
||||
* FIXME: this request is unused, as now another component is responsible for pattern file loading.
|
||||
* This request should be scrapped.
|
||||
*
|
||||
* @param path the pattern file's path
|
||||
*/
|
||||
EVENT_DEF(RequestLoadPatternLanguageFile, std::fs::path);
|
||||
|
||||
/**
|
||||
* @brief Request to save a pattern language file
|
||||
*
|
||||
* FIXME: this request is unused, as now another component is responsible for pattern file saving.
|
||||
* This request should be scrapped.
|
||||
*
|
||||
* @param path the pattern file's path
|
||||
*/
|
||||
EVENT_DEF(RequestSavePatternLanguageFile, std::fs::path);
|
||||
|
||||
/**
|
||||
* @brief Requests ImHex to open and process a file
|
||||
*
|
||||
* @param path the file's path
|
||||
*/
|
||||
EVENT_DEF(RequestOpenFile, std::fs::path);
|
||||
|
||||
/**
|
||||
* @brief Adds a virtual file in the Pattern editor
|
||||
*
|
||||
* @param path the file's path
|
||||
* @param data the file's data
|
||||
* @param region the impacted region
|
||||
*/
|
||||
EVENT_DEF(RequestAddVirtualFile, std::fs::path, std::vector<u8>, Region);
|
||||
|
||||
}
|
||||
84
lib/libimhex/include/hex/api/events/requests_lifecycle.hpp
Normal file
84
lib/libimhex/include/hex/api/events/requests_lifecycle.hpp
Normal file
@@ -0,0 +1,84 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
#include <hex/api/event_manager.hpp>
|
||||
|
||||
/* Lifecycle requests definitions */
|
||||
namespace hex {
|
||||
|
||||
/**
|
||||
* @brief Emit a request to add an initialization task to the list
|
||||
*
|
||||
* These tasks will be executed at startup.
|
||||
*
|
||||
* @param name Name of the init task
|
||||
* @param isAsync Whether the task is asynchronous (true if yes)
|
||||
* @param callbackFunction The function to call to execute the task
|
||||
*/
|
||||
EVENT_DEF(RequestAddInitTask, std::string, bool, std::function<bool()>);
|
||||
|
||||
/**
|
||||
* @brief Emit a request to add an exit task to the list
|
||||
*
|
||||
* These tasks will be executed during the exit phase.
|
||||
*
|
||||
* FIXME: request is unused and should be scrapped.
|
||||
*
|
||||
* @param name Name of the exit task
|
||||
* @param callbackFunction The function to call to execute the task
|
||||
*/
|
||||
EVENT_DEF(RequestAddExitTask, std::string, std::function<bool()>);
|
||||
|
||||
/**
|
||||
* @brief Requests ImHex's graceful shutdown
|
||||
*
|
||||
* If there are no questions (bool set to true), ImHex closes immediately.
|
||||
* If set to false, there is a procedure run to prompt a confirmation to the user.
|
||||
*
|
||||
* @param noQuestions true if no questions
|
||||
*/
|
||||
EVENT_DEF(RequestCloseImHex, bool);
|
||||
|
||||
/**
|
||||
* @brief Requests ImHex's restart
|
||||
*
|
||||
* This event is necessary for ImHex to restart in the main loop for native and web platforms,
|
||||
* as ImHex cannot simply close and re-open.
|
||||
*
|
||||
* This event serves no purpose on Linux, Windows and macOS platforms.
|
||||
*/
|
||||
EVENT_DEF(RequestRestartImHex);
|
||||
|
||||
/**
|
||||
* @brief Requests the initialization of theme handlers
|
||||
*
|
||||
* This is called during ImGui bootstrapping, and should not be called at any other time.
|
||||
*/
|
||||
EVENT_DEF(RequestInitThemeHandlers);
|
||||
|
||||
/**
|
||||
* @brief Requests version and first-startup checks
|
||||
*
|
||||
* This request is called during ImHex's startup, and allows ImHex to check if it was updated since last launch.
|
||||
* It also ensures newcomers (that open ImHex for the first time) are greeted with the tutorial.
|
||||
*
|
||||
* FIXME: the name is misleading, as this request does not effectively start any migration. It only executes
|
||||
* checks about ImHex's version. The name should be changed to reflect this behaviour.
|
||||
*/
|
||||
EVENT_DEF(RequestStartMigration);
|
||||
|
||||
/**
|
||||
* @brief Send a subcommand to the main Imhex instance
|
||||
*
|
||||
* This request is called to send a subcommand to the main ImHex instance.
|
||||
* This subcommand will then be executed by a handler when ImHex finishing initializing
|
||||
* (`EventImHexStartupFinished`).
|
||||
*
|
||||
* FIXME: change the name so that it is prefixed with "Request" like every other request.
|
||||
*
|
||||
* @param name the subcommand's name
|
||||
* @param data the subcommand's data
|
||||
*/
|
||||
EVENT_DEF(SendMessageToMainInstance, const std::string, const std::vector<u8>&);
|
||||
|
||||
}
|
||||
22
lib/libimhex/include/hex/api/events/requests_provider.hpp
Normal file
22
lib/libimhex/include/hex/api/events/requests_provider.hpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/api/event_manager.hpp>
|
||||
|
||||
/* Provider requests definitions */
|
||||
namespace hex {
|
||||
|
||||
/**
|
||||
* @brief Creates a provider from its unlocalized name, and add it to the provider list
|
||||
*/
|
||||
EVENT_DEF(RequestCreateProvider, std::string, bool, bool, hex::prv::Provider **);
|
||||
|
||||
/**
|
||||
* @brief Move the data from all PerProvider instances from one provider to another
|
||||
*
|
||||
* The 'from' provider should not have any per provider data after this, and should be immediately deleted
|
||||
*
|
||||
* FIXME: rename with the "Request" prefix to apply standard naming convention.
|
||||
*/
|
||||
EVENT_DEF(MovePerProviderData, prv::Provider *, prv::Provider *);
|
||||
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <hex.hpp>
|
||||
#include <hex/api/localization_manager.hpp>
|
||||
#include <hex/helpers/semantic_version.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
@@ -492,6 +493,7 @@ namespace hex {
|
||||
*/
|
||||
float getNativeScale();
|
||||
|
||||
float getBackingScaleFactor();
|
||||
|
||||
/**
|
||||
* @brief Gets the current main window position
|
||||
@@ -580,6 +582,14 @@ namespace hex {
|
||||
*/
|
||||
const std::string& getGLRenderer();
|
||||
|
||||
/**
|
||||
* @brief Checks if ImHex is being run in a "Corporate Environment"
|
||||
* This function simply checks for common telltale signs such as if the machine is joined a
|
||||
* domain. It's not super accurate, but it's still useful for statistics
|
||||
* @return True if it is
|
||||
*/
|
||||
bool isCorporateEnvironment();
|
||||
|
||||
/**
|
||||
* @brief Checks if ImHex is running in portable mode
|
||||
* @return Whether ImHex is running in portable mode
|
||||
@@ -618,7 +628,7 @@ namespace hex {
|
||||
* @brief Gets the current ImHex version
|
||||
* @return ImHex version
|
||||
*/
|
||||
std::string getImHexVersion(bool withBuildType = true);
|
||||
SemanticVersion getImHexVersion();
|
||||
|
||||
/**
|
||||
* @brief Gets the current git commit hash
|
||||
@@ -695,6 +705,13 @@ namespace hex {
|
||||
*/
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -736,11 +753,8 @@ namespace hex {
|
||||
|
||||
const std::vector<Font>& getFonts();
|
||||
|
||||
void setCustomFontPath(const std::fs::path &path);
|
||||
void setFontSize(float size);
|
||||
void setFontAtlas(ImFontAtlas *fontAtlas);
|
||||
std::map<UnlocalizedString, ImFont*>& getFontDefinitions();
|
||||
|
||||
void setFonts(ImFont *bold, ImFont *italic);
|
||||
}
|
||||
|
||||
GlyphRange glyph(const char *glyph);
|
||||
@@ -753,26 +767,8 @@ namespace hex {
|
||||
|
||||
constexpr static float DefaultFontSize = 13.0;
|
||||
|
||||
ImFont* Bold();
|
||||
ImFont* Italic();
|
||||
|
||||
/**
|
||||
* @brief Gets the current custom font path
|
||||
* @return The current custom font path
|
||||
*/
|
||||
const std::filesystem::path& getCustomFontPath();
|
||||
|
||||
/**
|
||||
* @brief Gets the current font size
|
||||
* @return The current font size
|
||||
*/
|
||||
float getFontSize();
|
||||
|
||||
/**
|
||||
* @brief Gets the current font atlas
|
||||
* @return Current font atlas
|
||||
*/
|
||||
ImFontAtlas* getFontAtlas();
|
||||
void registerFont(const UnlocalizedString &fontName);
|
||||
ImFont* getFont(const UnlocalizedString &fontName);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace hex {
|
||||
|
||||
}
|
||||
|
||||
void loadLanguage(const std::string &language);
|
||||
void loadLanguage(std::string language);
|
||||
std::string getLocalizedString(const std::string &unlocalizedString, const std::string &language = "");
|
||||
|
||||
[[nodiscard]] const std::map<std::string, std::string> &getSupportedLanguages();
|
||||
|
||||
@@ -2,137 +2,25 @@
|
||||
|
||||
#include <hex.hpp>
|
||||
#include <hex/api/localization_manager.hpp>
|
||||
#include <hex/helpers/keys.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
struct ImGuiWindow;
|
||||
|
||||
struct KeyEquivalent {
|
||||
bool valid;
|
||||
bool ctrl, opt, cmd, shift;
|
||||
int key;
|
||||
};
|
||||
|
||||
namespace hex {
|
||||
|
||||
class View;
|
||||
|
||||
enum class Keys : u32 {
|
||||
Space = GLFW_KEY_SPACE,
|
||||
Apostrophe = GLFW_KEY_APOSTROPHE,
|
||||
Comma = GLFW_KEY_COMMA,
|
||||
Minus = GLFW_KEY_MINUS,
|
||||
Period = GLFW_KEY_PERIOD,
|
||||
Slash = GLFW_KEY_SLASH,
|
||||
Num0 = GLFW_KEY_0,
|
||||
Num1 = GLFW_KEY_1,
|
||||
Num2 = GLFW_KEY_2,
|
||||
Num3 = GLFW_KEY_3,
|
||||
Num4 = GLFW_KEY_4,
|
||||
Num5 = GLFW_KEY_5,
|
||||
Num6 = GLFW_KEY_6,
|
||||
Num7 = GLFW_KEY_7,
|
||||
Num8 = GLFW_KEY_8,
|
||||
Num9 = GLFW_KEY_9,
|
||||
Semicolon = GLFW_KEY_SEMICOLON,
|
||||
Equals = GLFW_KEY_EQUAL,
|
||||
A = GLFW_KEY_A,
|
||||
B = GLFW_KEY_B,
|
||||
C = GLFW_KEY_C,
|
||||
D = GLFW_KEY_D,
|
||||
E = GLFW_KEY_E,
|
||||
F = GLFW_KEY_F,
|
||||
G = GLFW_KEY_G,
|
||||
H = GLFW_KEY_H,
|
||||
I = GLFW_KEY_I,
|
||||
J = GLFW_KEY_J,
|
||||
K = GLFW_KEY_K,
|
||||
L = GLFW_KEY_L,
|
||||
M = GLFW_KEY_M,
|
||||
N = GLFW_KEY_N,
|
||||
O = GLFW_KEY_O,
|
||||
P = GLFW_KEY_P,
|
||||
Q = GLFW_KEY_Q,
|
||||
R = GLFW_KEY_R,
|
||||
S = GLFW_KEY_S,
|
||||
T = GLFW_KEY_T,
|
||||
U = GLFW_KEY_U,
|
||||
V = GLFW_KEY_V,
|
||||
W = GLFW_KEY_W,
|
||||
X = GLFW_KEY_X,
|
||||
Y = GLFW_KEY_Y,
|
||||
Z = GLFW_KEY_Z,
|
||||
LeftBracket = GLFW_KEY_LEFT_BRACKET,
|
||||
Backslash = GLFW_KEY_BACKSLASH,
|
||||
RightBracket = GLFW_KEY_RIGHT_BRACKET,
|
||||
GraveAccent = GLFW_KEY_GRAVE_ACCENT,
|
||||
World1 = GLFW_KEY_WORLD_1,
|
||||
World2 = GLFW_KEY_WORLD_2,
|
||||
Escape = GLFW_KEY_ESCAPE,
|
||||
Enter = GLFW_KEY_ENTER,
|
||||
Tab = GLFW_KEY_TAB,
|
||||
Backspace = GLFW_KEY_BACKSPACE,
|
||||
Insert = GLFW_KEY_INSERT,
|
||||
Delete = GLFW_KEY_DELETE,
|
||||
Right = GLFW_KEY_RIGHT,
|
||||
Left = GLFW_KEY_LEFT,
|
||||
Down = GLFW_KEY_DOWN,
|
||||
Up = GLFW_KEY_UP,
|
||||
PageUp = GLFW_KEY_PAGE_UP,
|
||||
PageDown = GLFW_KEY_PAGE_DOWN,
|
||||
Home = GLFW_KEY_HOME,
|
||||
End = GLFW_KEY_END,
|
||||
CapsLock = GLFW_KEY_CAPS_LOCK,
|
||||
ScrollLock = GLFW_KEY_SCROLL_LOCK,
|
||||
NumLock = GLFW_KEY_NUM_LOCK,
|
||||
PrintScreen = GLFW_KEY_PRINT_SCREEN,
|
||||
Pause = GLFW_KEY_PAUSE,
|
||||
F1 = GLFW_KEY_F1,
|
||||
F2 = GLFW_KEY_F2,
|
||||
F3 = GLFW_KEY_F3,
|
||||
F4 = GLFW_KEY_F4,
|
||||
F5 = GLFW_KEY_F5,
|
||||
F6 = GLFW_KEY_F6,
|
||||
F7 = GLFW_KEY_F7,
|
||||
F8 = GLFW_KEY_F8,
|
||||
F9 = GLFW_KEY_F9,
|
||||
F10 = GLFW_KEY_F10,
|
||||
F11 = GLFW_KEY_F11,
|
||||
F12 = GLFW_KEY_F12,
|
||||
F13 = GLFW_KEY_F13,
|
||||
F14 = GLFW_KEY_F14,
|
||||
F15 = GLFW_KEY_F15,
|
||||
F16 = GLFW_KEY_F16,
|
||||
F17 = GLFW_KEY_F17,
|
||||
F18 = GLFW_KEY_F18,
|
||||
F19 = GLFW_KEY_F19,
|
||||
F20 = GLFW_KEY_F20,
|
||||
F21 = GLFW_KEY_F21,
|
||||
F22 = GLFW_KEY_F22,
|
||||
F23 = GLFW_KEY_F23,
|
||||
F24 = GLFW_KEY_F24,
|
||||
F25 = GLFW_KEY_F25,
|
||||
KeyPad0 = GLFW_KEY_KP_0,
|
||||
KeyPad1 = GLFW_KEY_KP_1,
|
||||
KeyPad2 = GLFW_KEY_KP_2,
|
||||
KeyPad3 = GLFW_KEY_KP_3,
|
||||
KeyPad4 = GLFW_KEY_KP_4,
|
||||
KeyPad5 = GLFW_KEY_KP_5,
|
||||
KeyPad6 = GLFW_KEY_KP_6,
|
||||
KeyPad7 = GLFW_KEY_KP_7,
|
||||
KeyPad8 = GLFW_KEY_KP_8,
|
||||
KeyPad9 = GLFW_KEY_KP_9,
|
||||
KeyPadDecimal = GLFW_KEY_KP_DECIMAL,
|
||||
KeyPadDivide = GLFW_KEY_KP_DIVIDE,
|
||||
KeyPadMultiply = GLFW_KEY_KP_MULTIPLY,
|
||||
KeyPadSubtract = GLFW_KEY_KP_SUBTRACT,
|
||||
KeyPadAdd = GLFW_KEY_KP_ADD,
|
||||
KeyPadEnter = GLFW_KEY_KP_ENTER,
|
||||
KeyPadEqual = GLFW_KEY_KP_EQUAL,
|
||||
Menu = GLFW_KEY_MENU,
|
||||
};
|
||||
|
||||
|
||||
class Key {
|
||||
public:
|
||||
constexpr Key() = default;
|
||||
@@ -153,12 +41,7 @@ namespace hex {
|
||||
constexpr static auto SUPER = Key(static_cast<Keys>(0x0800'0000));
|
||||
constexpr static auto CurrentView = Key(static_cast<Keys>(0x1000'0000));
|
||||
constexpr static auto AllowWhileTyping = Key(static_cast<Keys>(0x2000'0000));
|
||||
|
||||
#if defined (OS_MACOS)
|
||||
constexpr static auto CTRLCMD = SUPER;
|
||||
#else
|
||||
constexpr static auto CTRLCMD = CTRL;
|
||||
#endif
|
||||
constexpr static auto CTRLCMD = Key(static_cast<Keys>(0x4000'0000));
|
||||
|
||||
class Shortcut {
|
||||
public:
|
||||
@@ -180,6 +63,7 @@ namespace hex {
|
||||
|
||||
bool isLocal() const;
|
||||
std::string toString() const;
|
||||
KeyEquivalent toKeyEquivalent() const;
|
||||
const std::set<Key>& getKeys() const;
|
||||
bool has(Key key) const;
|
||||
bool matches(const Shortcut &other) const;
|
||||
@@ -199,10 +83,12 @@ namespace hex {
|
||||
class ShortcutManager {
|
||||
public:
|
||||
using Callback = std::function<void()>;
|
||||
using EnabledCallback = std::function<bool()>;
|
||||
struct ShortcutEntry {
|
||||
Shortcut shortcut;
|
||||
std::vector<UnlocalizedString> unlocalizedName;
|
||||
Callback callback;
|
||||
EnabledCallback enabledCallback;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -210,9 +96,10 @@ namespace hex {
|
||||
* @param shortcut The shortcut to add.
|
||||
* @param unlocalizedName The unlocalized name of the shortcut
|
||||
* @param callback The callback to call when the shortcut is triggered.
|
||||
* @param enabledCallback Callback that's called to check if this shortcut is enabled
|
||||
*/
|
||||
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 std::vector<UnlocalizedString> &unlocalizedName, const Callback &callback, const EnabledCallback &enabledCallback = []{ return true; });
|
||||
static void addGlobalShortcut(const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const Callback &callback, const EnabledCallback &enabledCallback = []{ return true; });
|
||||
|
||||
/**
|
||||
* @brief Add a view-specific shortcut. View-specific shortcuts can only be triggered when the specified view is focused.
|
||||
@@ -220,9 +107,10 @@ namespace hex {
|
||||
* @param shortcut The shortcut to add.
|
||||
* @param unlocalizedName The unlocalized name of the shortcut
|
||||
* @param callback The callback to call when the shortcut is triggered.
|
||||
* @param enabledCallback Callback that's called to check if this shortcut is enabled
|
||||
*/
|
||||
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 std::vector<UnlocalizedString> &unlocalizedName, const Callback &callback, const EnabledCallback &enabledCallback = []{ return true; });
|
||||
static void addShortcut(View *view, const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const Callback &callback, const EnabledCallback &enabledCallback = []{ return true; });
|
||||
|
||||
|
||||
/**
|
||||
@@ -255,6 +143,11 @@ namespace hex {
|
||||
static void resumeShortcuts();
|
||||
static void pauseShortcuts();
|
||||
|
||||
static void enableMacOSMode();
|
||||
|
||||
[[nodiscard]] static std::optional<UnlocalizedString> getLastActivatedMenu();
|
||||
static void resetLastActivatedMenu();
|
||||
|
||||
[[nodiscard]] static std::optional<Shortcut> getPreviousShortcut();
|
||||
|
||||
[[nodiscard]] static std::vector<ShortcutEntry> getGlobalShortcuts();
|
||||
|
||||
@@ -67,6 +67,7 @@ namespace hex {
|
||||
|
||||
static void reset();
|
||||
|
||||
static void setAccentColor(const ImColor &color);
|
||||
|
||||
public:
|
||||
struct ThemeHandler {
|
||||
@@ -82,6 +83,7 @@ namespace hex {
|
||||
static const std::map<std::string, ThemeHandler>& getThemeHandlers();
|
||||
static const std::map<std::string, StyleHandler>& getStyleHandlers();
|
||||
|
||||
|
||||
private:
|
||||
ThemeManager() = default;
|
||||
};
|
||||
|
||||
@@ -151,6 +151,9 @@ namespace hex {
|
||||
static void addInteractiveHelpText(std::initializer_list<std::variant<Lang, std::string, int>> &&ids, UnlocalizedString unlocalizedString);
|
||||
static void addInteractiveHelpLink(std::initializer_list<std::variant<Lang, std::string, int>> &&ids, std::string link);
|
||||
|
||||
static void setLastItemInteractiveHelpPopup(std::function<void()> callback);
|
||||
static void setLastItemInteractiveHelpLink(std::string link);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Draws the tutorial
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/api/event_manager.hpp>
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
|
||||
namespace hex {
|
||||
|
||||
@@ -44,4 +44,7 @@ namespace hex::dbg {
|
||||
}
|
||||
}
|
||||
|
||||
bool debugModeEnabled();
|
||||
void setDebugModeEnabled(bool enabled);
|
||||
|
||||
}
|
||||
@@ -82,8 +82,9 @@ namespace hex::paths {
|
||||
const static inline impl::DataPath Nodes("scripts/nodes");
|
||||
const static inline impl::DataPath Layouts("layouts");
|
||||
const static inline impl::DataPath Workspaces("workspaces");
|
||||
const static inline impl::DataPath Disassemblers("disassemblers");
|
||||
|
||||
constexpr static inline std::array<const impl::DefaultPath*, 20> All = {
|
||||
constexpr static inline std::array<const impl::DefaultPath*, 21> All = {
|
||||
&Config,
|
||||
&Recent,
|
||||
|
||||
@@ -106,6 +107,7 @@ namespace hex::paths {
|
||||
&Nodes,
|
||||
&Layouts,
|
||||
&Workspaces,
|
||||
&Disassemblers
|
||||
};
|
||||
|
||||
}
|
||||
122
lib/libimhex/include/hex/helpers/keys.hpp
Normal file
122
lib/libimhex/include/hex/helpers/keys.hpp
Normal file
@@ -0,0 +1,122 @@
|
||||
#pragma once
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
enum class Keys {
|
||||
#else
|
||||
enum Keys {
|
||||
#endif
|
||||
Space = GLFW_KEY_SPACE,
|
||||
Apostrophe = GLFW_KEY_APOSTROPHE,
|
||||
Comma = GLFW_KEY_COMMA,
|
||||
Minus = GLFW_KEY_MINUS,
|
||||
Period = GLFW_KEY_PERIOD,
|
||||
Slash = GLFW_KEY_SLASH,
|
||||
Num0 = GLFW_KEY_0,
|
||||
Num1 = GLFW_KEY_1,
|
||||
Num2 = GLFW_KEY_2,
|
||||
Num3 = GLFW_KEY_3,
|
||||
Num4 = GLFW_KEY_4,
|
||||
Num5 = GLFW_KEY_5,
|
||||
Num6 = GLFW_KEY_6,
|
||||
Num7 = GLFW_KEY_7,
|
||||
Num8 = GLFW_KEY_8,
|
||||
Num9 = GLFW_KEY_9,
|
||||
Semicolon = GLFW_KEY_SEMICOLON,
|
||||
Equals = GLFW_KEY_EQUAL,
|
||||
A = GLFW_KEY_A,
|
||||
B = GLFW_KEY_B,
|
||||
C = GLFW_KEY_C,
|
||||
D = GLFW_KEY_D,
|
||||
E = GLFW_KEY_E,
|
||||
F = GLFW_KEY_F,
|
||||
G = GLFW_KEY_G,
|
||||
H = GLFW_KEY_H,
|
||||
I = GLFW_KEY_I,
|
||||
J = GLFW_KEY_J,
|
||||
K = GLFW_KEY_K,
|
||||
L = GLFW_KEY_L,
|
||||
M = GLFW_KEY_M,
|
||||
N = GLFW_KEY_N,
|
||||
O = GLFW_KEY_O,
|
||||
P = GLFW_KEY_P,
|
||||
Q = GLFW_KEY_Q,
|
||||
R = GLFW_KEY_R,
|
||||
S = GLFW_KEY_S,
|
||||
T = GLFW_KEY_T,
|
||||
U = GLFW_KEY_U,
|
||||
V = GLFW_KEY_V,
|
||||
W = GLFW_KEY_W,
|
||||
X = GLFW_KEY_X,
|
||||
Y = GLFW_KEY_Y,
|
||||
Z = GLFW_KEY_Z,
|
||||
LeftBracket = GLFW_KEY_LEFT_BRACKET,
|
||||
Backslash = GLFW_KEY_BACKSLASH,
|
||||
RightBracket = GLFW_KEY_RIGHT_BRACKET,
|
||||
GraveAccent = GLFW_KEY_GRAVE_ACCENT,
|
||||
World1 = GLFW_KEY_WORLD_1,
|
||||
World2 = GLFW_KEY_WORLD_2,
|
||||
Escape = GLFW_KEY_ESCAPE,
|
||||
Enter = GLFW_KEY_ENTER,
|
||||
Tab = GLFW_KEY_TAB,
|
||||
Backspace = GLFW_KEY_BACKSPACE,
|
||||
Insert = GLFW_KEY_INSERT,
|
||||
Delete = GLFW_KEY_DELETE,
|
||||
Right = GLFW_KEY_RIGHT,
|
||||
Left = GLFW_KEY_LEFT,
|
||||
Down = GLFW_KEY_DOWN,
|
||||
Up = GLFW_KEY_UP,
|
||||
PageUp = GLFW_KEY_PAGE_UP,
|
||||
PageDown = GLFW_KEY_PAGE_DOWN,
|
||||
Home = GLFW_KEY_HOME,
|
||||
End = GLFW_KEY_END,
|
||||
CapsLock = GLFW_KEY_CAPS_LOCK,
|
||||
ScrollLock = GLFW_KEY_SCROLL_LOCK,
|
||||
NumLock = GLFW_KEY_NUM_LOCK,
|
||||
PrintScreen = GLFW_KEY_PRINT_SCREEN,
|
||||
Pause = GLFW_KEY_PAUSE,
|
||||
F1 = GLFW_KEY_F1,
|
||||
F2 = GLFW_KEY_F2,
|
||||
F3 = GLFW_KEY_F3,
|
||||
F4 = GLFW_KEY_F4,
|
||||
F5 = GLFW_KEY_F5,
|
||||
F6 = GLFW_KEY_F6,
|
||||
F7 = GLFW_KEY_F7,
|
||||
F8 = GLFW_KEY_F8,
|
||||
F9 = GLFW_KEY_F9,
|
||||
F10 = GLFW_KEY_F10,
|
||||
F11 = GLFW_KEY_F11,
|
||||
F12 = GLFW_KEY_F12,
|
||||
F13 = GLFW_KEY_F13,
|
||||
F14 = GLFW_KEY_F14,
|
||||
F15 = GLFW_KEY_F15,
|
||||
F16 = GLFW_KEY_F16,
|
||||
F17 = GLFW_KEY_F17,
|
||||
F18 = GLFW_KEY_F18,
|
||||
F19 = GLFW_KEY_F19,
|
||||
F20 = GLFW_KEY_F20,
|
||||
F21 = GLFW_KEY_F21,
|
||||
F22 = GLFW_KEY_F22,
|
||||
F23 = GLFW_KEY_F23,
|
||||
F24 = GLFW_KEY_F24,
|
||||
F25 = GLFW_KEY_F25,
|
||||
KeyPad0 = GLFW_KEY_KP_0,
|
||||
KeyPad1 = GLFW_KEY_KP_1,
|
||||
KeyPad2 = GLFW_KEY_KP_2,
|
||||
KeyPad3 = GLFW_KEY_KP_3,
|
||||
KeyPad4 = GLFW_KEY_KP_4,
|
||||
KeyPad5 = GLFW_KEY_KP_5,
|
||||
KeyPad6 = GLFW_KEY_KP_6,
|
||||
KeyPad7 = GLFW_KEY_KP_7,
|
||||
KeyPad8 = GLFW_KEY_KP_8,
|
||||
KeyPad9 = GLFW_KEY_KP_9,
|
||||
KeyPadDecimal = GLFW_KEY_KP_DECIMAL,
|
||||
KeyPadDivide = GLFW_KEY_KP_DIVIDE,
|
||||
KeyPadMultiply = GLFW_KEY_KP_MULTIPLY,
|
||||
KeyPadSubtract = GLFW_KEY_KP_SUBTRACT,
|
||||
KeyPadAdd = GLFW_KEY_KP_ADD,
|
||||
KeyPadEnter = GLFW_KEY_KP_ENTER,
|
||||
KeyPadEqual = GLFW_KEY_KP_EQUAL,
|
||||
Menu = GLFW_KEY_MENU,
|
||||
};
|
||||
@@ -807,6 +807,8 @@ namespace hex::gl {
|
||||
void bind() const;
|
||||
void unbind() const;
|
||||
|
||||
bool isValid() const { return m_program != 0; }
|
||||
|
||||
void setUniform(std::string_view name, const int &value);
|
||||
void setUniform(std::string_view name, const float &value);
|
||||
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -26,7 +26,7 @@
|
||||
#include <hex/helpers/utils_linux.hpp>
|
||||
#endif
|
||||
|
||||
struct ImVec2;
|
||||
#include <imgui.h>
|
||||
|
||||
namespace hex {
|
||||
|
||||
@@ -340,4 +340,6 @@ namespace hex {
|
||||
*/
|
||||
[[nodiscard]] void* getContainingModule(void* symbol);
|
||||
|
||||
[[nodiscard]] std::optional<ImColor> blendColors(const std::optional<ImColor> &a, const std::optional<ImColor> &b);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/helpers/keys.hpp>
|
||||
|
||||
#if defined(OS_MACOS)
|
||||
|
||||
struct GLFWwindow;
|
||||
@@ -17,8 +19,11 @@
|
||||
void enumerateFontsMacos();
|
||||
|
||||
void macosHandleTitlebarDoubleClickGesture(GLFWwindow *window);
|
||||
void macosSetWindowMovable(GLFWwindow *window, bool movable);
|
||||
bool macosIsWindowBeingResizedByUser(GLFWwindow *window);
|
||||
void macosMarkContentEdited(GLFWwindow *window, bool edited = true);
|
||||
|
||||
void macosGetKey(Keys key, int *output);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace hex::prv {
|
||||
|
||||
[[nodiscard]] std::string getName() const override { return m_name; }
|
||||
|
||||
[[nodiscard]] std::string getTypeName() const override { return "MemoryProvider"; }
|
||||
[[nodiscard]] UnlocalizedString getTypeName() const override { return "MemoryProvider"; }
|
||||
private:
|
||||
void renameFile();
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ namespace hex::prv {
|
||||
|
||||
struct MenuEntry {
|
||||
std::string name;
|
||||
const char *icon;
|
||||
std::function<void()> callback;
|
||||
};
|
||||
|
||||
@@ -151,7 +152,7 @@ namespace hex::prv {
|
||||
* like "hex.builtin.provider.mem_file" or "hex.builtin.provider.file"
|
||||
* @return The provider's type name
|
||||
*/
|
||||
[[nodiscard]] virtual std::string getTypeName() const = 0;
|
||||
[[nodiscard]] virtual UnlocalizedString getTypeName() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Gets a human readable representation of the current provider
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
#include <hex/api/event_manager.hpp>
|
||||
#include <hex/api/events/events_provider.hpp>
|
||||
#include <hex/api/events/events_lifecycle.hpp>
|
||||
#include <hex/api/events/requests_provider.hpp>
|
||||
|
||||
|
||||
#include <map>
|
||||
#include <ranges>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <hex.hpp>
|
||||
#include <hex/api/localization_manager.hpp>
|
||||
#include <hex/api/event_manager.hpp>
|
||||
#include <hex/api/events/events_interaction.hpp>
|
||||
|
||||
#include <hex/providers/undo_redo/operations/operation.hpp>
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace hex::test {
|
||||
return m_data->size();
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string getTypeName() const override { return "hex.test.provider.test"; }
|
||||
[[nodiscard]] UnlocalizedString getTypeName() const override { return "hex.test.provider.test"; }
|
||||
|
||||
bool open() override { return true; }
|
||||
void close() override { }
|
||||
|
||||
57
lib/libimhex/include/hex/ui/banner.hpp
Normal file
57
lib/libimhex/include/hex/ui/banner.hpp
Normal file
@@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
#include <hex/helpers/utils.hpp>
|
||||
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include "hex/api/localization_manager.hpp"
|
||||
|
||||
namespace hex {
|
||||
|
||||
namespace impl {
|
||||
|
||||
class BannerBase {
|
||||
public:
|
||||
BannerBase(ImColor color) : m_color(color) {}
|
||||
virtual ~BannerBase() = default;
|
||||
|
||||
virtual void draw() { drawContent(); }
|
||||
virtual void drawContent() = 0;
|
||||
|
||||
[[nodiscard]] static std::list<std::unique_ptr<BannerBase>> &getOpenBanners();
|
||||
|
||||
[[nodiscard]] const ImColor& getColor() const {
|
||||
return m_color;
|
||||
}
|
||||
|
||||
void close() { m_shouldClose = true; }
|
||||
[[nodiscard]] bool shouldClose() const { return m_shouldClose; }
|
||||
|
||||
protected:
|
||||
static std::mutex& getMutex();
|
||||
|
||||
bool m_shouldClose = false;
|
||||
ImColor m_color;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
class Banner : public impl::BannerBase {
|
||||
public:
|
||||
using impl::BannerBase::BannerBase;
|
||||
|
||||
template<typename ...Args>
|
||||
static void open(Args && ... args) {
|
||||
std::lock_guard lock(getMutex());
|
||||
|
||||
auto toast = std::make_unique<T>(std::forward<Args>(args)...);
|
||||
getOpenBanners().emplace_back(std::move(toast));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -79,16 +79,16 @@ namespace ImGuiExt {
|
||||
Texture(const Texture&) = delete;
|
||||
Texture(Texture&& other) noexcept;
|
||||
|
||||
static Texture fromImage(const ImU8 *buffer, int size, Filter filter = Filter::Nearest);
|
||||
static Texture fromImage(std::span<const std::byte> buffer, Filter filter = Filter::Nearest);
|
||||
static Texture fromImage(const char *path, Filter filter = Filter::Nearest);
|
||||
static Texture fromImage(const std::fs::path &path, Filter filter = Filter::Nearest);
|
||||
static Texture fromGLTexture(unsigned int texture, int width, int height);
|
||||
static Texture fromBitmap(const ImU8 *buffer, int size, int width, int height, Filter filter = Filter::Nearest);
|
||||
static Texture fromBitmap(std::span<const std::byte> buffer, int width, int height, Filter filter = Filter::Nearest);
|
||||
static Texture fromSVG(const char *path, int width = 0, int height = 0, Filter filter = Filter::Nearest);
|
||||
static Texture fromSVG(const std::fs::path &path, int width = 0, int height = 0, Filter filter = Filter::Nearest);
|
||||
static Texture fromSVG(std::span<const std::byte> buffer, int width = 0, int height = 0, Filter filter = Filter::Nearest);
|
||||
[[nodiscard]] static Texture fromImage(const ImU8 *buffer, int size, Filter filter = Filter::Nearest);
|
||||
[[nodiscard]] static Texture fromImage(std::span<const std::byte> buffer, Filter filter = Filter::Nearest);
|
||||
[[nodiscard]] static Texture fromImage(const char *path, Filter filter = Filter::Nearest);
|
||||
[[nodiscard]] static Texture fromImage(const std::fs::path &path, Filter filter = Filter::Nearest);
|
||||
[[nodiscard]] static Texture fromGLTexture(unsigned int texture, int width, int height);
|
||||
[[nodiscard]] static Texture fromBitmap(const ImU8 *buffer, int size, int width, int height, Filter filter = Filter::Nearest);
|
||||
[[nodiscard]] static Texture fromBitmap(std::span<const std::byte> buffer, int width, int height, Filter filter = Filter::Nearest);
|
||||
[[nodiscard]] static Texture fromSVG(const char *path, int width = 0, int height = 0, Filter filter = Filter::Nearest);
|
||||
[[nodiscard]] static Texture fromSVG(const std::fs::path &path, int width = 0, int height = 0, Filter filter = Filter::Nearest);
|
||||
[[nodiscard]] static Texture fromSVG(std::span<const std::byte> buffer, int width = 0, int height = 0, Filter filter = Filter::Nearest);
|
||||
|
||||
|
||||
~Texture();
|
||||
@@ -144,13 +144,13 @@ namespace ImGuiExt {
|
||||
|
||||
bool TitleBarButton(const char *label, ImVec2 size_arg);
|
||||
bool ToolBarButton(const char *symbol, ImVec4 color);
|
||||
bool IconButton(const char *symbol, ImVec4 color, ImVec2 size_arg = ImVec2(0, 0));
|
||||
bool IconButton(const char *symbol, ImVec4 color, ImVec2 size_arg = ImVec2(0, 0), ImVec2 iconOffset = ImVec2(0, 0));
|
||||
|
||||
bool InputIntegerPrefix(const char* label, const char *prefix, void *value, ImGuiDataType type, const char *format, ImGuiInputTextFlags flags = ImGuiInputTextFlags_None);
|
||||
bool InputHexadecimal(const char* label, u32 *value, ImGuiInputTextFlags flags = ImGuiInputTextFlags_None);
|
||||
bool InputHexadecimal(const char* label, u64 *value, ImGuiInputTextFlags flags = ImGuiInputTextFlags_None);
|
||||
|
||||
bool SliderBytes(const char *label, u64 *value, u64 min, u64 max, ImGuiSliderFlags flags = ImGuiSliderFlags_None);
|
||||
bool SliderBytes(const char *label, u64 *value, u64 min, u64 max, u64 stepSize = 1, ImGuiSliderFlags flags = ImGuiSliderFlags_None);
|
||||
|
||||
inline bool HasSecondPassed() {
|
||||
return static_cast<ImU32>(ImGui::GetTime() * 100) % 100 <= static_cast<ImU32>(ImGui::GetIO().DeltaTime * 100);
|
||||
@@ -203,7 +203,7 @@ namespace ImGuiExt {
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4());
|
||||
|
||||
ImGui::PushItemWidth(ImGui::CalcTextSize(text.c_str()).x + ImGui::GetStyle().FramePadding.x * 2);
|
||||
ImGui::InputText("##", const_cast<char *>(text.c_str()), text.size(), ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_NoHorizontalScroll);
|
||||
ImGui::InputText("##", const_cast<char *>(text.c_str()), text.size() + 1, ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_NoHorizontalScroll);
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
ImGui::PopStyleColor();
|
||||
@@ -235,11 +235,13 @@ namespace ImGuiExt {
|
||||
|
||||
inline void TextFormattedWrappedSelectable(std::string_view fmt, auto &&...args) {
|
||||
// Manually wrap text, using the letter M (generally the widest character in non-monospaced fonts) to calculate the character width to use.
|
||||
auto text = wolv::util::wrapMonospacedString(
|
||||
auto text = wolv::util::trim(wolv::util::wrapMonospacedString(
|
||||
hex::format(fmt, std::forward<decltype(args)>(args)...),
|
||||
ImGui::CalcTextSize("M").x,
|
||||
ImGui::GetContentRegionAvail().x - ImGui::GetStyle().ScrollbarSize - ImGui::GetStyle().FrameBorderSize
|
||||
);
|
||||
));
|
||||
|
||||
auto textSize = ImGui::CalcTextSize(text.c_str());
|
||||
|
||||
ImGui::PushID(text.c_str());
|
||||
|
||||
@@ -250,8 +252,8 @@ namespace ImGuiExt {
|
||||
ImGui::InputTextMultiline(
|
||||
"##",
|
||||
const_cast<char *>(text.c_str()),
|
||||
text.size(),
|
||||
ImVec2(0, -FLT_MIN),
|
||||
text.size() + 1,
|
||||
ImVec2(0, textSize.y),
|
||||
ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_NoHorizontalScroll
|
||||
);
|
||||
ImGui::PopItemWidth();
|
||||
@@ -291,8 +293,8 @@ namespace ImGuiExt {
|
||||
bool BitCheckbox(const char* label, bool* v);
|
||||
|
||||
bool DimmedButton(const char* label, ImVec2 size = ImVec2(0, 0));
|
||||
bool DimmedIconButton(const char *symbol, ImVec4 color, ImVec2 size = ImVec2(0, 0));
|
||||
bool DimmedButtonToggle(const char *icon, bool *v, ImVec2 size);
|
||||
bool DimmedIconButton(const char *symbol, ImVec4 color, ImVec2 size = ImVec2(0, 0), ImVec2 iconOffset = ImVec2(0, 0));
|
||||
bool DimmedButtonToggle(const char *icon, bool *v, ImVec2 size = ImVec2(0, 0), ImVec2 iconOffset = ImVec2(0, 0));
|
||||
bool DimmedIconToggle(const char *icon, bool *v);
|
||||
bool DimmedIconToggle(const char *iconOn, const char *iconOff, bool *v);
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
#include <hex/api/shortcut_manager.hpp>
|
||||
#include <hex/api/event_manager.hpp>
|
||||
#include <hex/api/localization_manager.hpp>
|
||||
|
||||
#include <hex/providers/provider.hpp>
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
#include <hex/api/achievement_manager.hpp>
|
||||
#include <hex/api/event_manager.hpp>
|
||||
#include <hex/api/events/events_interaction.hpp>
|
||||
|
||||
#include <hex/helpers/auto_reset.hpp>
|
||||
#include <hex/helpers/default_paths.hpp>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#if defined(OS_WEB)
|
||||
#include <emscripten.h>
|
||||
#endif
|
||||
|
||||
namespace hex {
|
||||
|
||||
static AutoReset<std::unordered_map<std::string, std::unordered_map<std::string, std::unique_ptr<Achievement>>>> s_achievements;
|
||||
@@ -215,7 +219,16 @@ namespace hex {
|
||||
}
|
||||
|
||||
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 &[achievementName, achievement] : achievements) {
|
||||
@@ -254,16 +267,23 @@ namespace hex {
|
||||
if (json.empty())
|
||||
return;
|
||||
|
||||
for (const auto &directory : paths::Config.write()) {
|
||||
auto path = directory / AchievementsFile;
|
||||
#if defined(OS_WEB)
|
||||
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);
|
||||
if (!file.isValid())
|
||||
continue;
|
||||
wolv::io::File file(path, wolv::io::File::Mode::Create);
|
||||
if (!file.isValid())
|
||||
continue;
|
||||
|
||||
file.writeString(json.dump(4));
|
||||
break;
|
||||
}
|
||||
file.writeString(json.dump(4));
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <hex/api/content_registry.hpp>
|
||||
#include <hex/api/shortcut_manager.hpp>
|
||||
#include <hex/api/events/requests_provider.hpp>
|
||||
|
||||
#include <hex/helpers/fs.hpp>
|
||||
#include <hex/helpers/logger.hpp>
|
||||
@@ -38,6 +39,34 @@ namespace hex {
|
||||
|
||||
static AutoReset<std::map<std::string, std::map<std::string, std::vector<OnChange>>>> s_onChangeCallbacks;
|
||||
|
||||
static void runAllOnChangeCallbacks() {
|
||||
for (const auto &[category, rest] : *impl::s_onChangeCallbacks) {
|
||||
for (const auto &[name, callbacks] : rest) {
|
||||
for (const auto &[id, callback] : callbacks) {
|
||||
try {
|
||||
callback(getSetting(category, name, {}));
|
||||
} catch (const std::exception &e) {
|
||||
log::error("Failed to load setting [{}/{}]: {}", category, name, e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void runOnChangeHandlers(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, const nlohmann::json &value) {
|
||||
if (auto categoryIt = s_onChangeCallbacks->find(unlocalizedCategory); categoryIt != s_onChangeCallbacks->end()) {
|
||||
if (auto nameIt = categoryIt->second.find(unlocalizedName); nameIt != categoryIt->second.end()) {
|
||||
for (const auto &[id, callback] : nameIt->second) {
|
||||
try {
|
||||
callback(value);
|
||||
} catch (const nlohmann::json::exception &e) {
|
||||
log::error("Failed to run onChange handler for setting {}/{}: {}", unlocalizedCategory.get(), unlocalizedName.get(), e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static AutoReset<nlohmann::json> s_settings;
|
||||
const nlohmann::json& getSettingsData() {
|
||||
return s_settings;
|
||||
@@ -72,24 +101,28 @@ namespace hex {
|
||||
s_settings = nlohmann::json::parse(data);
|
||||
}
|
||||
|
||||
for (const auto &[category, rest] : *impl::s_onChangeCallbacks) {
|
||||
for (const auto &[name, callbacks] : rest) {
|
||||
for (const auto &[id, callback] : callbacks) {
|
||||
try {
|
||||
callback(getSetting(category, name, {}));
|
||||
} catch (const std::exception &e) {
|
||||
log::error("Failed to load setting [{}/{}]: {}", category, name, e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
runAllOnChangeCallbacks();
|
||||
}
|
||||
|
||||
void store() {
|
||||
auto data = s_settings->dump();
|
||||
if (!s_settings.isValid())
|
||||
return;
|
||||
|
||||
const auto &settingsData = *s_settings;
|
||||
|
||||
// During a crash settings can be empty, causing them to be overwritten.
|
||||
if (settingsData.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto result = settingsData.dump(4);
|
||||
if (result.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
MAIN_THREAD_EM_ASM({
|
||||
localStorage.setItem("config", UTF8ToString($0));
|
||||
}, data.c_str());
|
||||
}, result.c_str());
|
||||
}
|
||||
|
||||
void clear() {
|
||||
@@ -115,17 +148,7 @@ namespace hex {
|
||||
if (!loaded)
|
||||
store();
|
||||
|
||||
for (const auto &[category, rest] : *impl::s_onChangeCallbacks) {
|
||||
for (const auto &[name, callbacks] : rest) {
|
||||
for (const auto &[id, callback] : callbacks) {
|
||||
try {
|
||||
callback(getSetting(category, name, {}));
|
||||
} catch (const std::exception &e) {
|
||||
log::error("Failed to load setting [{}/{}]: {}", category, name, e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
runAllOnChangeCallbacks();
|
||||
}
|
||||
|
||||
void store() {
|
||||
@@ -135,7 +158,7 @@ namespace hex {
|
||||
const auto &settingsData = *s_settings;
|
||||
|
||||
// During a crash settings can be empty, causing them to be overwritten.
|
||||
if (settingsData.empty()) {
|
||||
if (s_settings->empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -201,6 +224,8 @@ namespace hex {
|
||||
log::error("Failed to load setting [{} / {}]: {}", unlocalizedCategory.get(), unlocalizedName.get(), e.what());
|
||||
}
|
||||
});
|
||||
|
||||
runOnChangeHandlers(unlocalizedCategory, unlocalizedName, getSetting(unlocalizedCategory, unlocalizedName, entry->widget->store()));
|
||||
}
|
||||
|
||||
return entry->widget.get();
|
||||
@@ -210,20 +235,6 @@ namespace hex {
|
||||
hex::log::error("Failed to read setting {}/{}: {}", unlocalizedCategory.get(), unlocalizedName.get(), e.what());
|
||||
}
|
||||
|
||||
void runOnChangeHandlers(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedName, const nlohmann::json &value) {
|
||||
if (auto categoryIt = s_onChangeCallbacks->find(unlocalizedCategory); categoryIt != s_onChangeCallbacks->end()) {
|
||||
if (auto nameIt = categoryIt->second.find(unlocalizedName); nameIt != categoryIt->second.end()) {
|
||||
for (const auto &[id, callback] : nameIt->second) {
|
||||
try {
|
||||
callback(value);
|
||||
} catch (const nlohmann::json::exception &e) {
|
||||
log::error("Failed to run onChange handler for setting {}/{}: {}", unlocalizedCategory.get(), unlocalizedName.get(), e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void setCategoryDescription(const UnlocalizedString &unlocalizedCategory, const UnlocalizedString &unlocalizedDescription) {
|
||||
@@ -325,7 +336,7 @@ namespace hex {
|
||||
|
||||
|
||||
bool SliderDataSize::draw(const std::string &name) {
|
||||
return ImGuiExt::SliderBytes(name.c_str(), &m_value, m_min, m_max);
|
||||
return ImGuiExt::SliderBytes(name.c_str(), &m_value, m_min, m_max, m_stepSize);
|
||||
}
|
||||
|
||||
void SliderDataSize::load(const nlohmann::json &data) {
|
||||
@@ -341,17 +352,34 @@ namespace hex {
|
||||
}
|
||||
|
||||
|
||||
ColorPicker::ColorPicker(ImColor defaultColor) {
|
||||
m_value = {
|
||||
defaultColor.Value.x,
|
||||
defaultColor.Value.y,
|
||||
defaultColor.Value.z,
|
||||
defaultColor.Value.w
|
||||
ColorPicker::ColorPicker(ImColor defaultColor, ImGuiColorEditFlags flags) {
|
||||
m_defaultValue = m_value = {
|
||||
defaultColor.Value.x,
|
||||
defaultColor.Value.y,
|
||||
defaultColor.Value.z,
|
||||
defaultColor.Value.w
|
||||
};
|
||||
m_flags = flags;
|
||||
}
|
||||
|
||||
bool ColorPicker::draw(const std::string &name) {
|
||||
return ImGui::ColorEdit4(name.c_str(), m_value.data(), ImGuiColorEditFlags_NoInputs);
|
||||
ImGui::PushID(name.c_str());
|
||||
auto result = ImGui::ColorEdit4("##color_picker", m_value.data(), ImGuiColorEditFlags_NoInputs | m_flags);
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button("X", ImGui::GetStyle().FramePadding * 2 + ImVec2(ImGui::GetTextLineHeight(), ImGui::GetTextLineHeight()))) {
|
||||
m_value = m_defaultValue;
|
||||
result = true;
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::TextUnformatted(name.c_str());
|
||||
|
||||
ImGui::PopID();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void ColorPicker::load(const nlohmann::json &data) {
|
||||
@@ -377,7 +405,7 @@ namespace hex {
|
||||
bool DropDown::draw(const std::string &name) {
|
||||
auto preview = "";
|
||||
if (static_cast<size_t>(m_value) < m_items.size())
|
||||
preview = m_items[m_value].c_str();
|
||||
preview = m_items[m_value].get().c_str();
|
||||
|
||||
bool changed = false;
|
||||
if (ImGui::BeginCombo(name.c_str(), Lang(preview))) {
|
||||
@@ -630,7 +658,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -752,6 +780,14 @@ namespace hex {
|
||||
impl::s_entries->push_back({ unlocalizedName, requiredSize, maxSize, std::move(displayGeneratorFunction), std::move(editingFunction) });
|
||||
}
|
||||
|
||||
void drawMenuItems(const std::function<void()> &function) {
|
||||
if (ImGui::BeginPopup("##DataInspectorRowContextMenu")) {
|
||||
function();
|
||||
ImGui::Separator();
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace ContentRegistry::DataProcessorNode {
|
||||
@@ -917,17 +953,10 @@ namespace hex {
|
||||
});
|
||||
|
||||
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)
|
||||
ShortcutManager::addShortcut(view, shortcut, unlocalizedShortcutName, callbackIfEnabled);
|
||||
ShortcutManager::addShortcut(view, shortcut, unlocalizedMainMenuNames, function, enabledCallback);
|
||||
else
|
||||
ShortcutManager::addGlobalShortcut(shortcut, unlocalizedShortcutName, callbackIfEnabled);
|
||||
ShortcutManager::addGlobalShortcut(shortcut, unlocalizedMainMenuNames, function, enabledCallback);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1391,4 +1420,23 @@ namespace hex {
|
||||
|
||||
}
|
||||
|
||||
namespace ContentRegistry::Disassembler {
|
||||
|
||||
namespace impl {
|
||||
|
||||
static AutoReset<std::map<std::string, impl::CreatorFunction>> s_architectures;
|
||||
|
||||
void addArchitectureCreator(impl::CreatorFunction function) {
|
||||
const auto arch = function();
|
||||
(*s_architectures)[arch->getName()] = std::move(function);
|
||||
}
|
||||
|
||||
const std::map<std::string, impl::CreatorFunction>& getArchitectures() {
|
||||
return *s_architectures;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
|
||||
#include <hex/api/event_manager.hpp>
|
||||
#include <hex/api/events/events_provider.hpp>
|
||||
#include <hex/api/events/events_lifecycle.hpp>
|
||||
#include <hex/api/events/events_gui.hpp>
|
||||
#include <hex/api/events/requests_interaction.hpp>
|
||||
#include <hex/api/events/requests_lifecycle.hpp>
|
||||
#include <hex/api/events/requests_provider.hpp>
|
||||
#include <hex/api/events/requests_gui.hpp>
|
||||
|
||||
#include <hex/api/task_manager.hpp>
|
||||
#include <hex/helpers/fmt.hpp>
|
||||
#include <hex/helpers/utils.hpp>
|
||||
@@ -11,6 +18,7 @@
|
||||
#include <wolv/utils/string.hpp>
|
||||
|
||||
#include <utility>
|
||||
#include <numeric>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
@@ -18,13 +26,20 @@
|
||||
#include <algorithm>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include <hex/helpers/utils_macos.hpp>
|
||||
|
||||
#if defined(OS_WINDOWS)
|
||||
#include <windows.h>
|
||||
#include <DSRole.h>
|
||||
#else
|
||||
#include <sys/utsname.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined(OS_WEB)
|
||||
#include <emscripten.h>
|
||||
#endif
|
||||
|
||||
namespace hex {
|
||||
|
||||
|
||||
@@ -608,6 +623,27 @@ namespace hex {
|
||||
return impl::s_nativeScale;
|
||||
}
|
||||
|
||||
float getBackingScaleFactor() {
|
||||
#if defined(OS_WINDOWS)
|
||||
return 1.0F;
|
||||
#elif defined(OS_MACOS)
|
||||
return ::getBackingScaleFactor();
|
||||
#elif defined(OS_LINUX)
|
||||
if (std::string_view(::getenv("XDG_SESSION_TYPE")) == "x11")
|
||||
return 1.0F;
|
||||
else {
|
||||
float xScale = 0, yScale = 0;
|
||||
glfwGetMonitorContentScale(glfwGetPrimaryMonitor(), &xScale, &yScale);
|
||||
|
||||
return std::midpoint(xScale, yScale);
|
||||
}
|
||||
#elif defined(OS_WEB)
|
||||
return 1.0F;
|
||||
#else
|
||||
return 1.0F;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
ImVec2 getMainWindowPosition() {
|
||||
if ((ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable) != ImGuiConfigFlags_None)
|
||||
@@ -645,6 +681,14 @@ namespace hex {
|
||||
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() {
|
||||
return *impl::s_initArguments;
|
||||
@@ -689,6 +733,27 @@ namespace hex {
|
||||
return impl::s_glRenderer;
|
||||
}
|
||||
|
||||
bool isCorporateEnvironment() {
|
||||
#if defined(OS_WINDOWS)
|
||||
{
|
||||
DSROLE_PRIMARY_DOMAIN_INFO_BASIC * info;
|
||||
if ((DsRoleGetPrimaryDomainInformation(NULL, DsRolePrimaryDomainInfoBasic, (PBYTE *)&info) == ERROR_SUCCESS) && (info != nullptr))
|
||||
{
|
||||
bool result = std::wstring(info->DomainNameFlat).empty();
|
||||
DsRoleFreeMemory(info);
|
||||
|
||||
return result;
|
||||
} else {
|
||||
DWORD size = 1024;
|
||||
::GetComputerNameExA(ComputerNameDnsDomain, nullptr, &size);
|
||||
return size > 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool isPortableVersion() {
|
||||
static std::optional<bool> portable;
|
||||
if (portable.has_value())
|
||||
@@ -794,16 +859,11 @@ namespace hex {
|
||||
return { { name, version } };
|
||||
}
|
||||
|
||||
std::string getImHexVersion(bool withBuildType) {
|
||||
SemanticVersion getImHexVersion() {
|
||||
#if defined IMHEX_VERSION
|
||||
if (withBuildType) {
|
||||
return IMHEX_VERSION;
|
||||
} else {
|
||||
auto version = std::string(IMHEX_VERSION);
|
||||
return version.substr(0, version.find('-'));
|
||||
}
|
||||
return SemanticVersion(IMHEX_VERSION);
|
||||
#else
|
||||
return "Unknown";
|
||||
return {};
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -837,7 +897,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
bool isNightlyBuild() {
|
||||
return getImHexVersion(false).ends_with("WIP");
|
||||
return getImHexVersion().nightly();
|
||||
}
|
||||
|
||||
bool updateImHex(UpdateType updateType) {
|
||||
@@ -935,11 +995,6 @@ namespace hex {
|
||||
return *s_fonts;
|
||||
}
|
||||
|
||||
static AutoReset<std::fs::path> s_customFontPath;
|
||||
void setCustomFontPath(const std::fs::path &path) {
|
||||
s_customFontPath = path;
|
||||
}
|
||||
|
||||
static float s_fontSize = DefaultFontSize;
|
||||
void setFontSize(float size) {
|
||||
s_fontSize = size;
|
||||
@@ -957,6 +1012,10 @@ namespace hex {
|
||||
s_italicFont = italic;
|
||||
}
|
||||
|
||||
static AutoReset<std::map<UnlocalizedString, ImFont*>> s_fontDefinitions;
|
||||
std::map<UnlocalizedString, ImFont*>& getFontDefinitions() {
|
||||
return *s_fontDefinitions;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1021,10 +1080,6 @@ namespace hex {
|
||||
});
|
||||
}
|
||||
|
||||
const std::fs::path& getCustomFontPath() {
|
||||
return impl::s_customFontPath;
|
||||
}
|
||||
|
||||
float getFontSize() {
|
||||
return impl::s_fontSize;
|
||||
}
|
||||
@@ -1033,6 +1088,14 @@ namespace hex {
|
||||
return impl::s_fontAtlas;
|
||||
}
|
||||
|
||||
void registerFont(const UnlocalizedString &fontName) {
|
||||
(*impl::s_fontDefinitions)[fontName] = nullptr;
|
||||
}
|
||||
|
||||
ImFont* getFont(const UnlocalizedString &fontName) {
|
||||
return (*impl::s_fontDefinitions)[fontName];
|
||||
}
|
||||
|
||||
ImFont* Bold() {
|
||||
return impl::s_boldFont;
|
||||
}
|
||||
|
||||
@@ -56,18 +56,19 @@ namespace hex {
|
||||
}
|
||||
}
|
||||
|
||||
void loadLanguage(const std::string &language) {
|
||||
void loadLanguage(std::string language) {
|
||||
auto &definitions = ContentRegistry::Language::impl::getLanguageDefinitions();
|
||||
|
||||
const auto& fallbackLanguage = getFallbackLanguage();
|
||||
if (!definitions.contains(language))
|
||||
return;
|
||||
language = fallbackLanguage;
|
||||
|
||||
s_currStrings->clear();
|
||||
|
||||
loadLanguageDefinitions(definitions.at(language));
|
||||
|
||||
const auto& fallbackLanguage = getFallbackLanguage();
|
||||
loadLanguageDefinitions(definitions.at(fallbackLanguage));
|
||||
if (language != fallbackLanguage)
|
||||
loadLanguageDefinitions(definitions.at(fallbackLanguage));
|
||||
|
||||
s_selectedLanguage = language;
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ namespace hex {
|
||||
|
||||
|
||||
const auto requestedVersion = getCompatibleVersion();
|
||||
const auto imhexVersion = ImHexApi::System::getImHexVersion();
|
||||
const auto imhexVersion = ImHexApi::System::getImHexVersion().get();
|
||||
if (!imhexVersion.starts_with(requestedVersion)) {
|
||||
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()));
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <hex/api/shortcut_manager.hpp>
|
||||
#include <imgui.h>
|
||||
#include <hex/api/content_registry.hpp>
|
||||
#include <hex/api/task_manager.hpp>
|
||||
#include <hex/helpers/auto_reset.hpp>
|
||||
|
||||
#include <hex/ui/view.hpp>
|
||||
@@ -12,6 +13,8 @@ namespace hex {
|
||||
AutoReset<std::map<Shortcut, ShortcutManager::ShortcutEntry>> s_globalShortcuts;
|
||||
std::atomic<bool> s_paused;
|
||||
std::optional<Shortcut> s_prevShortcut;
|
||||
bool s_macOSMode = false;
|
||||
AutoReset<std::optional<UnlocalizedString>> s_lastShortcutMainMenu;
|
||||
|
||||
}
|
||||
|
||||
@@ -78,22 +81,14 @@ namespace hex {
|
||||
std::string Shortcut::toString() const {
|
||||
std::string result;
|
||||
|
||||
#if defined(OS_MACOS)
|
||||
constexpr static auto CTRL_NAME = "⌃";
|
||||
constexpr static auto ALT_NAME = "⌥";
|
||||
constexpr static auto SHIFT_NAME = "⇧";
|
||||
constexpr static auto SUPER_NAME = "⌘";
|
||||
constexpr static auto Concatination = " ";
|
||||
#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";
|
||||
constexpr static auto Concatination = " + ";
|
||||
#endif
|
||||
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) {
|
||||
if (keys.erase(CTRL) > 0 || (!s_macOSMode && keys.erase(CTRLCMD) > 0)) {
|
||||
result += CTRL_NAME;
|
||||
result += Concatination;
|
||||
}
|
||||
@@ -105,7 +100,7 @@ namespace hex {
|
||||
result += SHIFT_NAME;
|
||||
result += Concatination;
|
||||
}
|
||||
if (keys.erase(SUPER) > 0) {
|
||||
if (keys.erase(SUPER) > 0 || (s_macOSMode && keys.erase(CTRLCMD) > 0)) {
|
||||
result += SUPER_NAME;
|
||||
result += Concatination;
|
||||
}
|
||||
@@ -238,28 +233,66 @@ namespace hex {
|
||||
return result;
|
||||
}
|
||||
|
||||
KeyEquivalent Shortcut::toKeyEquivalent() const {
|
||||
#if defined(OS_MACOS)
|
||||
if (*this == None)
|
||||
return { };
|
||||
|
||||
void ShortcutManager::addGlobalShortcut(const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const std::function<void()> &callback) {
|
||||
KeyEquivalent result = {};
|
||||
result.valid = true;
|
||||
|
||||
for (const auto &key : m_keys) {
|
||||
switch (key.getKeyCode()) {
|
||||
case CTRL.getKeyCode():
|
||||
result.ctrl = true;
|
||||
break;
|
||||
case SHIFT.getKeyCode():
|
||||
result.shift = true;
|
||||
break;
|
||||
case ALT.getKeyCode():
|
||||
result.opt = true;
|
||||
break;
|
||||
case SUPER.getKeyCode():
|
||||
case CTRLCMD.getKeyCode():
|
||||
result.cmd = true;
|
||||
break;
|
||||
case CurrentView.getKeyCode(): break;
|
||||
case AllowWhileTyping.getKeyCode(): break;
|
||||
default:
|
||||
macosGetKey(Keys(key.getKeyCode()), &result.key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
#else
|
||||
return { };
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ShortcutManager::addGlobalShortcut(const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const std::function<void()> &callback, const EnabledCallback &enabledCallback) {
|
||||
log::debug("Adding global shortcut {} for {}", shortcut.toString(), unlocalizedName.back().get());
|
||||
auto [it, inserted] = s_globalShortcuts->insert({ shortcut, { shortcut, unlocalizedName, callback } });
|
||||
auto [it, inserted] = s_globalShortcuts->insert({ shortcut, { shortcut, unlocalizedName, callback, enabledCallback } });
|
||||
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, const EnabledCallback &enabledCallback) {
|
||||
log::debug("Adding global shortcut {} for {}", shortcut.toString(), unlocalizedName.get());
|
||||
auto [it, inserted] = s_globalShortcuts->insert({ shortcut, { shortcut, { unlocalizedName }, callback } });
|
||||
auto [it, inserted] = s_globalShortcuts->insert({ shortcut, { shortcut, { unlocalizedName }, callback, enabledCallback } });
|
||||
if (!inserted) log::error("Failed to add shortcut!");
|
||||
}
|
||||
|
||||
void ShortcutManager::addShortcut(View *view, const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const std::function<void()> &callback) {
|
||||
void ShortcutManager::addShortcut(View *view, const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const std::function<void()> &callback, const EnabledCallback &enabledCallback) {
|
||||
log::debug("Adding shortcut {} for {}", shortcut.toString(), unlocalizedName.back().get());
|
||||
auto [it, inserted] = view->m_shortcuts.insert({ shortcut + CurrentView, { shortcut, unlocalizedName, callback } });
|
||||
auto [it, inserted] = view->m_shortcuts.insert({ shortcut + CurrentView, { shortcut, unlocalizedName, callback, enabledCallback } });
|
||||
if (!inserted) log::error("Failed to add shortcut!");
|
||||
}
|
||||
|
||||
void ShortcutManager::addShortcut(View *view, const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const std::function<void()> &callback) {
|
||||
void ShortcutManager::addShortcut(View *view, const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const std::function<void()> &callback, const EnabledCallback &enabledCallback) {
|
||||
log::debug("Adding shortcut {} for {}", shortcut.toString(), unlocalizedName.get());
|
||||
auto [it, inserted] = view->m_shortcuts.insert({ shortcut + CurrentView, { shortcut, { unlocalizedName }, callback } });
|
||||
auto [it, inserted] = view->m_shortcuts.insert({ shortcut + CurrentView, { shortcut, { unlocalizedName }, callback, enabledCallback } });
|
||||
if (!inserted) log::error("Failed to add shortcut!");
|
||||
}
|
||||
|
||||
@@ -267,32 +300,45 @@ namespace hex {
|
||||
Shortcut pressedShortcut;
|
||||
|
||||
if (ctrl)
|
||||
pressedShortcut += CTRL;
|
||||
pressedShortcut += s_macOSMode ? CTRL : CTRLCMD;
|
||||
if (alt)
|
||||
pressedShortcut += ALT;
|
||||
if (shift)
|
||||
pressedShortcut += SHIFT;
|
||||
if (super)
|
||||
pressedShortcut += SUPER;
|
||||
pressedShortcut += s_macOSMode ? CTRLCMD : SUPER;
|
||||
if (focused)
|
||||
pressedShortcut += CurrentView;
|
||||
if (ImGui::GetIO().WantTextInput)
|
||||
pressedShortcut += AllowWhileTyping;
|
||||
|
||||
pressedShortcut += static_cast<Keys>(keyCode);
|
||||
|
||||
return pressedShortcut;
|
||||
}
|
||||
|
||||
static void processShortcut(const Shortcut &shortcut, const std::map<Shortcut, ShortcutManager::ShortcutEntry> &shortcuts) {
|
||||
static void processShortcut(Shortcut shortcut, const std::map<Shortcut, ShortcutManager::ShortcutEntry> &shortcuts) {
|
||||
if (s_paused) return;
|
||||
|
||||
if (ImGui::IsPopupOpen(ImGuiID(0), ImGuiPopupFlags_AnyPopupId))
|
||||
return;
|
||||
|
||||
if (auto it = shortcuts.find(shortcut); it != shortcuts.end()) {
|
||||
const bool currentlyTyping = ImGui::GetIO().WantTextInput;
|
||||
|
||||
auto it = shortcuts.find(shortcut + AllowWhileTyping);
|
||||
if (!currentlyTyping && it == shortcuts.end()) {
|
||||
if (it == shortcuts.end())
|
||||
it = shortcuts.find(shortcut);
|
||||
}
|
||||
|
||||
if (it != shortcuts.end()) {
|
||||
const auto &[foundShortcut, entry] = *it;
|
||||
entry.callback();
|
||||
|
||||
if (entry.enabledCallback()) {
|
||||
entry.callback();
|
||||
|
||||
if (!entry.unlocalizedName.empty()) {
|
||||
s_lastShortcutMainMenu = entry.unlocalizedName.front();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -312,6 +358,15 @@ namespace hex {
|
||||
processShortcut(pressedShortcut, s_globalShortcuts);
|
||||
}
|
||||
|
||||
std::optional<UnlocalizedString> ShortcutManager::getLastActivatedMenu() {
|
||||
return *s_lastShortcutMainMenu;
|
||||
}
|
||||
|
||||
void ShortcutManager::resetLastActivatedMenu() {
|
||||
s_lastShortcutMainMenu->reset();
|
||||
}
|
||||
|
||||
|
||||
void ShortcutManager::clearShortcuts() {
|
||||
s_globalShortcuts->clear();
|
||||
}
|
||||
@@ -387,4 +442,9 @@ namespace hex {
|
||||
return result;
|
||||
}
|
||||
|
||||
void ShortcutManager::enableMacOSMode() {
|
||||
s_macOSMode = true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
#include <hex/api/theme_manager.hpp>
|
||||
#include <hex/api/event_manager.hpp>
|
||||
#include <hex/api/events/events_interaction.hpp>
|
||||
|
||||
#include <hex/helpers/logger.hpp>
|
||||
#include <hex/helpers/utils.hpp>
|
||||
@@ -16,6 +16,7 @@ namespace hex {
|
||||
AutoReset<std::map<std::string, ThemeManager::StyleHandler>> s_styleHandlers;
|
||||
AutoReset<std::string> s_imageTheme;
|
||||
AutoReset<std::string> s_currTheme;
|
||||
AutoReset<std::optional<float>> s_accentColor;
|
||||
|
||||
std::recursive_mutex s_themeMutex;
|
||||
}
|
||||
@@ -155,12 +156,28 @@ namespace hex {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto color = parseColorString(value.get<std::string>());
|
||||
auto colorString = value.get<std::string>();
|
||||
bool accentableColor = false;
|
||||
if (colorString.starts_with("*")) {
|
||||
colorString = colorString.substr(1);
|
||||
accentableColor = true;
|
||||
}
|
||||
auto color = parseColorString(colorString);
|
||||
|
||||
if (!color.has_value()) {
|
||||
log::warn("Invalid color '{}' for '{}.{}'", value.get<std::string>(), type, key);
|
||||
log::warn("Invalid color '{}' for '{}.{}'", colorString, type, key);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (accentableColor && s_accentColor->has_value()) {
|
||||
float h, s, v;
|
||||
ImGui::ColorConvertRGBtoHSV(color->Value.x, color->Value.y, color->Value.z, h, s, v);
|
||||
|
||||
h = s_accentColor->value();
|
||||
|
||||
ImGui::ColorConvertHSVtoRGB(h, s, v, color->Value.x, color->Value.y, color->Value.z);
|
||||
}
|
||||
|
||||
(*s_themeHandlers)[type].setFunction((*s_themeHandlers)[type].colorMap.at(key), color.value());
|
||||
}
|
||||
}
|
||||
@@ -236,6 +253,14 @@ namespace hex {
|
||||
s_currTheme->clear();
|
||||
}
|
||||
|
||||
void ThemeManager::setAccentColor(const ImColor &color) {
|
||||
float h, s, v;
|
||||
ImGui::ColorConvertRGBtoHSV(color.Value.x, color.Value.y, color.Value.z, h, s, v);
|
||||
|
||||
s_accentColor = h;
|
||||
reapplyCurrentTheme();
|
||||
}
|
||||
|
||||
|
||||
const std::map<std::string, ThemeManager::ThemeHandler> &ThemeManager::getThemeHandlers() {
|
||||
return s_themeHandlers;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
#include <hex/api/localization_manager.hpp>
|
||||
#include <hex/api/task_manager.hpp>
|
||||
#include <hex/api/events/events_gui.hpp>
|
||||
|
||||
#include <hex/helpers/auto_reset.hpp>
|
||||
|
||||
@@ -11,6 +12,8 @@
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
namespace hex {
|
||||
|
||||
namespace {
|
||||
@@ -20,10 +23,12 @@ namespace hex {
|
||||
|
||||
AutoReset<std::map<ImGuiID, std::string>> s_highlights;
|
||||
AutoReset<std::vector<std::pair<ImRect, std::string>>> s_highlightDisplays;
|
||||
AutoReset<std::map<ImGuiID, ImRect>> s_interactiveHelpDisplays;
|
||||
|
||||
AutoReset<std::map<ImGuiID, std::function<void()>>> s_interactiveHelpItems;
|
||||
ImRect s_hoveredRect;
|
||||
ImGuiID s_hoveredId;
|
||||
ImGuiID s_activeHelpId;
|
||||
bool s_helpHoverActive = false;
|
||||
|
||||
|
||||
@@ -33,6 +38,13 @@ namespace hex {
|
||||
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) {
|
||||
const ImGuiID seed = idStack.back();
|
||||
const ImGuiID id = ImHashStr(string.c_str(), string.length(), seed);
|
||||
@@ -84,9 +96,23 @@ namespace hex {
|
||||
EventImGuiElementRendered::subscribe([](ImGuiID id, const std::array<float, 4> bb){
|
||||
const auto boundingBox = ImRect(bb[0], bb[1], bb[2], bb[3]);
|
||||
|
||||
const auto element = hex::s_highlights->find(id);
|
||||
if (element != hex::s_highlights->end()) {
|
||||
hex::s_highlightDisplays->emplace_back(boundingBox, element->second);
|
||||
{
|
||||
const auto element = hex::s_highlights->find(id);
|
||||
if (element != hex::s_highlights->end()) {
|
||||
hex::s_highlightDisplays->emplace_back(boundingBox, element->second);
|
||||
|
||||
const auto window = ImGui::GetCurrentWindow();
|
||||
if (window != nullptr && window->DockNode != nullptr && window->DockNode->TabBar != nullptr)
|
||||
window->DockNode->TabBar->NextSelectedTabId = window->TabId;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const auto element = s_interactiveHelpItems->find(id);
|
||||
if (element != s_interactiveHelpItems->end()) {
|
||||
(*s_interactiveHelpDisplays)[id] = boundingBox;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (id != 0 && boundingBox.Contains(ImGui::GetMousePos())) {
|
||||
@@ -117,10 +143,10 @@ namespace hex {
|
||||
});
|
||||
}
|
||||
|
||||
void TutorialManager::addInteractiveHelpText(std::initializer_list<std::variant<Lang, std::string, int>> &&ids, UnlocalizedString text) {
|
||||
void TutorialManager::addInteractiveHelpText(std::initializer_list<std::variant<Lang, std::string, int>> &&ids, UnlocalizedString unlocalizedString) {
|
||||
auto id = calculateId(ids);
|
||||
|
||||
s_interactiveHelpItems->emplace(id, [text = std::move(text)]{
|
||||
s_interactiveHelpItems->emplace(id, [text = std::move(unlocalizedString)]{
|
||||
log::info("{}", Lang(text).get());
|
||||
});
|
||||
}
|
||||
@@ -133,6 +159,39 @@ namespace hex {
|
||||
});
|
||||
}
|
||||
|
||||
void TutorialManager::setLastItemInteractiveHelpPopup(std::function<void()> callback) {
|
||||
auto id = ImGui::GetItemID();
|
||||
|
||||
if (!s_interactiveHelpItems->contains(id)) {
|
||||
s_interactiveHelpItems->emplace(id, [id]{
|
||||
s_activeHelpId = id;
|
||||
});
|
||||
}
|
||||
|
||||
if (id == s_activeHelpId) {
|
||||
ImGui::SetNextWindowSize(scaled({ 400, 0 }));
|
||||
if (ImGui::BeginTooltip()) {
|
||||
callback();
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
|
||||
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) || ImGui::IsKeyPressed(ImGuiKey_Escape))
|
||||
s_activeHelpId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void TutorialManager::setLastItemInteractiveHelpLink(std::string link) {
|
||||
auto id = ImGui::GetItemID();
|
||||
|
||||
if (s_interactiveHelpItems->contains(id))
|
||||
return;
|
||||
|
||||
s_interactiveHelpItems->emplace(id, [link = std::move(link)]{
|
||||
hex::openWebpage(link);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void TutorialManager::startTutorial(const UnlocalizedString &unlocalizedName) {
|
||||
s_currentTutorial = s_tutorials->find(unlocalizedName);
|
||||
if (s_currentTutorial == s_tutorials->end())
|
||||
@@ -146,6 +205,19 @@ namespace hex {
|
||||
const auto &drawList = ImGui::GetForegroundDrawList();
|
||||
drawList->AddText(ImGui::GetMousePos() + scaled({ 10, -5, }), ImGui::GetColorU32(ImGuiCol_Text), "?");
|
||||
|
||||
for (const auto &[id, boundingBox] : *s_interactiveHelpDisplays) {
|
||||
drawList->AddRect(
|
||||
boundingBox.Min - ImVec2(5, 5),
|
||||
boundingBox.Max + ImVec2(5, 5),
|
||||
ImGui::GetColorU32(ImGuiCol_PlotHistogram),
|
||||
5.0F,
|
||||
ImDrawFlags_None,
|
||||
2.0F
|
||||
);
|
||||
}
|
||||
|
||||
s_interactiveHelpDisplays->clear();
|
||||
|
||||
const bool mouseClicked = ImGui::IsMouseClicked(ImGuiMouseButton_Left);
|
||||
if (s_hoveredId != 0) {
|
||||
drawList->AddRectFilled(s_hoveredRect.Min, s_hoveredRect.Max, 0x30FFFFFF);
|
||||
@@ -164,6 +236,11 @@ namespace hex {
|
||||
if (mouseClicked || ImGui::IsKeyPressed(ImGuiKey_Escape)) {
|
||||
s_helpHoverActive = false;
|
||||
}
|
||||
|
||||
// Discard mouse click so it doesn't activate clicked item
|
||||
ImGui::GetIO().MouseDown[ImGuiMouseButton_Left] = false;
|
||||
ImGui::GetIO().MouseReleased[ImGuiMouseButton_Left] = false;
|
||||
ImGui::GetIO().MouseClicked[ImGuiMouseButton_Left] = false;
|
||||
}
|
||||
|
||||
for (const auto &[rect, unlocalizedText] : *s_highlightDisplays) {
|
||||
|
||||
@@ -12,4 +12,13 @@ namespace hex::dbg {
|
||||
|
||||
}
|
||||
|
||||
static bool s_debugMode = false;
|
||||
bool debugModeEnabled() {
|
||||
return s_debugMode;
|
||||
}
|
||||
|
||||
void setDebugModeEnabled(bool enabled) {
|
||||
s_debugMode = enabled;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -123,7 +123,13 @@ namespace hex::fs {
|
||||
// Call callback that will write the file
|
||||
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(), {
|
||||
onload: () => {
|
||||
@@ -191,6 +197,7 @@ namespace hex::fs {
|
||||
else if (!validExtensions.empty())
|
||||
path = "file." + validExtensions[0].spec;
|
||||
|
||||
std::fs::create_directory("/savedFiles");
|
||||
callJs_saveFile(path.filename().string().c_str());
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include <hex/api/event_manager.hpp>
|
||||
#include <hex/api/events/events_gui.hpp>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include <hex/helpers/logger.hpp>
|
||||
|
||||
#include <hex/api/task_manager.hpp>
|
||||
#include <hex/api/event_manager.hpp>
|
||||
|
||||
#include <hex/helpers/fs.hpp>
|
||||
#include <hex/helpers/fmt.hpp>
|
||||
|
||||
@@ -81,6 +81,9 @@ namespace hex::gl {
|
||||
std::vector<char> log(512);
|
||||
glGetShaderInfoLog(m_program, log.size(), nullptr, log.data());
|
||||
log::error("Failed to link shader: {}", log.data());
|
||||
|
||||
glDeleteProgram(m_program);
|
||||
m_program = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ namespace hex {
|
||||
return "";
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string getTypeName() const override { return ""; }
|
||||
[[nodiscard]] UnlocalizedString getTypeName() const override { return ""; }
|
||||
|
||||
const std::map<u64, u8>& getPatches() const {
|
||||
return m_patches;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -8,6 +8,9 @@
|
||||
#include <hex/providers/buffered_reader.hpp>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#if defined(OS_WINDOWS)
|
||||
#include <windows.h>
|
||||
@@ -685,7 +688,7 @@ namespace hex {
|
||||
return string;
|
||||
|
||||
// If the string is longer than the max length, find the last space before the max length
|
||||
auto it = string.begin() + maxLength;
|
||||
auto it = string.begin() + maxLength / 2;
|
||||
while (it != string.begin() && !std::isspace(*it)) --it;
|
||||
|
||||
// If there's no space before the max length, just cut the string
|
||||
@@ -844,4 +847,22 @@ namespace hex {
|
||||
#endif
|
||||
}
|
||||
|
||||
std::optional<ImColor> blendColors(const std::optional<ImColor> &a, const std::optional<ImColor> &b) {
|
||||
if (!a.has_value() && !b.has_value())
|
||||
return std::nullopt;
|
||||
else if (a.has_value() && !b.has_value())
|
||||
return a;
|
||||
else if (!a.has_value() && b.has_value())
|
||||
return b;
|
||||
else
|
||||
return ImAlphaBlendColors(a.value(), b.value());
|
||||
}
|
||||
|
||||
extern "C" void macOSCloseButtonPressed() {
|
||||
auto windowHandle = ImHexApi::System::getMainWindowHandle();
|
||||
|
||||
glfwHideWindow(windowHandle);
|
||||
glfwIconifyWindow(windowHandle);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,6 +18,8 @@
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#include <hex/helpers/keys.hpp>
|
||||
|
||||
void errorMessageMacos(const char *cMessage) {
|
||||
CFStringRef strMessage = CFStringCreateWithCString(NULL, cMessage, kCFStringEncodingUTF8);
|
||||
CFUserNotificationDisplayAlert(0, kCFUserNotificationStopAlertLevel, NULL, NULL, NULL, strMessage, NULL, NULL, NULL, NULL, NULL);
|
||||
@@ -46,6 +48,33 @@
|
||||
return [[NSScreen mainScreen] backingScaleFactor];
|
||||
}
|
||||
|
||||
void macOSCloseButtonPressed(void);
|
||||
|
||||
@interface CloseButtonHandler : NSObject
|
||||
@end
|
||||
|
||||
@implementation CloseButtonHandler
|
||||
- (void)pressed:(id)sender {
|
||||
macOSCloseButtonPressed();
|
||||
}
|
||||
@end
|
||||
|
||||
@interface ImHexAppDelegate : NSObject<NSApplicationDelegate>
|
||||
@end
|
||||
|
||||
@implementation ImHexAppDelegate
|
||||
- (void) application:(NSApplication*)sender openFiles:(NSArray*)filenames
|
||||
{
|
||||
NSLog(@"A");
|
||||
|
||||
[NSApp replyToOpenOrPrint:NSApplicationDelegateReplySuccess];
|
||||
}
|
||||
|
||||
- (IBAction) clickAction:(id)sender {
|
||||
NSLog(@"B");
|
||||
}
|
||||
@end
|
||||
|
||||
void setupMacosWindowStyle(GLFWwindow *window, bool borderlessWindowMode) {
|
||||
NSWindow* cocoaWindow = glfwGetCocoaWindow(window);
|
||||
|
||||
@@ -59,6 +88,13 @@
|
||||
[cocoaWindow setHasShadow:YES];
|
||||
[cocoaWindow setBackgroundColor:[NSColor colorWithWhite: 0 alpha: 0.001f]];
|
||||
}
|
||||
|
||||
NSButton *closeButton = [cocoaWindow standardWindowButton:NSWindowCloseButton];
|
||||
[closeButton setAction:@selector(pressed:)];
|
||||
[closeButton setTarget:[CloseButtonHandler alloc]];
|
||||
|
||||
NSApplication *app = [NSApplication sharedApplication];
|
||||
[app setDelegate:[ImHexAppDelegate alloc]];
|
||||
}
|
||||
|
||||
bool isMacosFullScreenModeEnabled(GLFWwindow *window) {
|
||||
@@ -112,6 +148,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
void macosSetWindowMovable(GLFWwindow *window, bool movable) {
|
||||
NSWindow* cocoaWindow = glfwGetCocoaWindow(window);
|
||||
|
||||
[cocoaWindow setMovable:movable];
|
||||
}
|
||||
|
||||
bool macosIsWindowBeingResizedByUser(GLFWwindow *window) {
|
||||
NSWindow* cocoaWindow = glfwGetCocoaWindow(window);
|
||||
|
||||
@@ -145,4 +187,123 @@
|
||||
|
||||
@end
|
||||
|
||||
void macosGetKey(enum Keys key, int *output) {
|
||||
*output = 0x00;
|
||||
switch (key) {
|
||||
case Space: *output = ' '; break;
|
||||
case Apostrophe: *output = '\''; break;
|
||||
case Comma: *output = ','; break;
|
||||
case Minus: *output = '-'; break;
|
||||
case Period: *output = '.'; break;
|
||||
case Slash: *output = '/'; break;
|
||||
case Num0: *output = '0'; break;
|
||||
case Num1: *output = '1'; break;
|
||||
case Num2: *output = '2'; break;
|
||||
case Num3: *output = '3'; break;
|
||||
case Num4: *output = '4'; break;
|
||||
case Num5: *output = '5'; break;
|
||||
case Num6: *output = '6'; break;
|
||||
case Num7: *output = '7'; break;
|
||||
case Num8: *output = '8'; break;
|
||||
case Num9: *output = '9'; break;
|
||||
case Semicolon: *output = ';'; break;
|
||||
case Equals: *output = '='; break;
|
||||
case A: *output = 'a'; break;
|
||||
case B: *output = 'b'; break;
|
||||
case C: *output = 'c'; break;
|
||||
case D: *output = 'd'; break;
|
||||
case E: *output = 'e'; break;
|
||||
case F: *output = 'f'; break;
|
||||
case G: *output = 'g'; break;
|
||||
case H: *output = 'h'; break;
|
||||
case I: *output = 'i'; break;
|
||||
case J: *output = 'j'; break;
|
||||
case K: *output = 'k'; break;
|
||||
case L: *output = 'l'; break;
|
||||
case M: *output = 'm'; break;
|
||||
case N: *output = 'n'; break;
|
||||
case O: *output = 'o'; break;
|
||||
case P: *output = 'p'; break;
|
||||
case Q: *output = 'q'; break;
|
||||
case R: *output = 'r'; break;
|
||||
case S: *output = 's'; break;
|
||||
case T: *output = 't'; break;
|
||||
case U: *output = 'u'; break;
|
||||
case V: *output = 'v'; break;
|
||||
case W: *output = 'w'; break;
|
||||
case X: *output = 'x'; break;
|
||||
case Y: *output = 'y'; break;
|
||||
case Z: *output = 'z'; break;
|
||||
case LeftBracket: *output = '/'; break;
|
||||
case Backslash: *output = '\\'; break;
|
||||
case RightBracket: *output = ']'; break;
|
||||
case GraveAccent: *output = '`'; break;
|
||||
case World1: break;
|
||||
case World2: break;
|
||||
case Escape: break;
|
||||
case Enter: *output = NSEnterCharacter; break;
|
||||
case Tab: *output = NSTabCharacter; break;
|
||||
case Backspace: *output = NSBackspaceCharacter; break;
|
||||
case Insert: *output = NSInsertFunctionKey; break;
|
||||
case Delete: *output = NSDeleteCharacter; break;
|
||||
case Right: *output = NSRightArrowFunctionKey; break;
|
||||
case Left: *output = NSLeftArrowFunctionKey; break;
|
||||
case Down: *output = NSDownArrowFunctionKey; break;
|
||||
case Up: *output = NSUpArrowFunctionKey; break;
|
||||
case PageUp: *output = NSPageUpFunctionKey; break;
|
||||
case PageDown: *output = NSPageDownFunctionKey; break;
|
||||
case Home: *output = NSHomeFunctionKey; break;
|
||||
case End: *output = NSEndFunctionKey; break;
|
||||
case CapsLock: break;
|
||||
case ScrollLock: *output = NSScrollLockFunctionKey; break;
|
||||
case NumLock: break;
|
||||
case PrintScreen: *output = NSPrintScreenFunctionKey; break;
|
||||
case Pause: *output = NSPauseFunctionKey; break;
|
||||
case F1: *output = NSF1FunctionKey; break;
|
||||
case F2: *output = NSF2FunctionKey; break;
|
||||
case F3: *output = NSF3FunctionKey; break;
|
||||
case F4: *output = NSF4FunctionKey; break;
|
||||
case F5: *output = NSF5FunctionKey; break;
|
||||
case F6: *output = NSF6FunctionKey; break;
|
||||
case F7: *output = NSF7FunctionKey; break;
|
||||
case F8: *output = NSF8FunctionKey; break;
|
||||
case F9: *output = NSF9FunctionKey; break;
|
||||
case F10: *output = NSF10FunctionKey; break;
|
||||
case F11: *output = NSF11FunctionKey; break;
|
||||
case F12: *output = NSF12FunctionKey; break;
|
||||
case F13: *output = NSF13FunctionKey; break;
|
||||
case F14: *output = NSF14FunctionKey; break;
|
||||
case F15: *output = NSF15FunctionKey; break;
|
||||
case F16: *output = NSF16FunctionKey; break;
|
||||
case F17: *output = NSF17FunctionKey; break;
|
||||
case F18: *output = NSF18FunctionKey; break;
|
||||
case F19: *output = NSF19FunctionKey; break;
|
||||
case F20: *output = NSF20FunctionKey; break;
|
||||
case F21: *output = NSF21FunctionKey; break;
|
||||
case F22: *output = NSF22FunctionKey; break;
|
||||
case F23: *output = NSF23FunctionKey; break;
|
||||
case F24: *output = NSF24FunctionKey; break;
|
||||
case F25: *output = NSF25FunctionKey; break;
|
||||
case KeyPad0: *output = '0'; break;
|
||||
case KeyPad1: *output = '1'; break;
|
||||
case KeyPad2: *output = '2'; break;
|
||||
case KeyPad3: *output = '3'; break;
|
||||
case KeyPad4: *output = '4'; break;
|
||||
case KeyPad5: *output = '5'; break;
|
||||
case KeyPad6: *output = '6'; break;
|
||||
case KeyPad7: *output = '7'; break;
|
||||
case KeyPad8: *output = '8'; break;
|
||||
case KeyPad9: *output = '9'; break;
|
||||
case KeyPadDecimal: *output = '.'; break;
|
||||
case KeyPadDivide: *output = '/'; break;
|
||||
case KeyPadMultiply: *output = '*'; break;
|
||||
case KeyPadSubtract: *output = '-'; break;
|
||||
case KeyPadAdd: *output = '+'; break;
|
||||
case KeyPadEnter: *output = NSEnterCharacter; break;
|
||||
case KeyPadEqual: *output = '='; break;
|
||||
case Menu: *output = NSMenuFunctionKey; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include <hex/providers/provider.hpp>
|
||||
|
||||
#include <hex.hpp>
|
||||
#include <hex/api/event_manager.hpp>
|
||||
#include <hex/api/events/events_provider.hpp>
|
||||
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#include "hex/subcommands/subcommands.hpp"
|
||||
|
||||
#include <hex/api/event_manager.hpp>
|
||||
#include <hex/api/events/requests_lifecycle.hpp>
|
||||
#include <hex/api/plugin_manager.hpp>
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
#include <hex/helpers/logger.hpp>
|
||||
|
||||
18
lib/libimhex/source/ui/banner.cpp
Normal file
18
lib/libimhex/source/ui/banner.cpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#include <hex/ui/banner.hpp>
|
||||
#include <hex/helpers/auto_reset.hpp>
|
||||
|
||||
namespace hex::impl {
|
||||
|
||||
[[nodiscard]] std::list<std::unique_ptr<BannerBase>> &BannerBase::getOpenBanners() {
|
||||
static AutoReset<std::list<std::unique_ptr<BannerBase>>> openBanners;
|
||||
|
||||
return openBanners;
|
||||
}
|
||||
|
||||
std::mutex& BannerBase::getMutex() {
|
||||
static std::mutex mutex;
|
||||
|
||||
return mutex;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <hex/api/task_manager.hpp>
|
||||
#include <hex/api/theme_manager.hpp>
|
||||
#include <hex/helpers/logger.hpp>
|
||||
#include <hex/helpers/utils_macos.hpp>
|
||||
|
||||
|
||||
namespace ImGuiExt {
|
||||
@@ -222,14 +223,16 @@ namespace ImGuiExt {
|
||||
}
|
||||
|
||||
Texture Texture::fromSVG(const char *path, int width, int height, Filter filter) {
|
||||
const auto scaleFactor = hex::ImHexApi::System::getBackingScaleFactor();
|
||||
|
||||
auto document = lunasvg::Document::loadFromFile(path);
|
||||
auto bitmap = document->renderToBitmap(width, height);
|
||||
auto bitmap = document->renderToBitmap(width * scaleFactor, height * scaleFactor);
|
||||
|
||||
auto texture = createMultisampleTextureFromRGBA8Array(bitmap.data(), bitmap.width(), bitmap.height(), filter);
|
||||
|
||||
Texture result;
|
||||
result.m_width = bitmap.width();
|
||||
result.m_height = bitmap.height();
|
||||
result.m_width = bitmap.width() / scaleFactor;
|
||||
result.m_height = bitmap.height() / scaleFactor;
|
||||
result.m_textureId = texture;
|
||||
|
||||
return result;
|
||||
@@ -240,15 +243,17 @@ namespace ImGuiExt {
|
||||
}
|
||||
|
||||
Texture Texture::fromSVG(std::span<const std::byte> buffer, int width, int height, Filter filter) {
|
||||
const auto scaleFactor = hex::ImHexApi::System::getBackingScaleFactor();
|
||||
|
||||
auto document = lunasvg::Document::loadFromData(reinterpret_cast<const char*>(buffer.data()), buffer.size());
|
||||
auto bitmap = document->renderToBitmap(width, height);
|
||||
auto bitmap = document->renderToBitmap(width * scaleFactor, height * scaleFactor);
|
||||
bitmap.convertToRGBA();
|
||||
|
||||
auto texture = createMultisampleTextureFromRGBA8Array(bitmap.data(), bitmap.width(), bitmap.height(), filter);
|
||||
|
||||
Texture result;
|
||||
result.m_width = bitmap.width();
|
||||
result.m_height = bitmap.height();
|
||||
result.m_width = bitmap.width() / scaleFactor;
|
||||
result.m_height = bitmap.height() / scaleFactor;
|
||||
result.m_textureId = texture;
|
||||
|
||||
return result;
|
||||
@@ -819,7 +824,7 @@ namespace ImGuiExt {
|
||||
return pressed;
|
||||
}
|
||||
|
||||
bool IconButton(const char *symbol, ImVec4 color, ImVec2 size_arg) {
|
||||
bool IconButton(const char *symbol, ImVec4 color, ImVec2 size_arg, ImVec2 iconOffset) {
|
||||
ImGuiWindow *window = GetCurrentWindow();
|
||||
if (window->SkipItems)
|
||||
return false;
|
||||
@@ -850,7 +855,7 @@ namespace ImGuiExt {
|
||||
: ImGuiCol_Button);
|
||||
RenderNavCursor(bb, id);
|
||||
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) + iconOffset, bb.Max - style.FramePadding, symbol, nullptr, &label_size, style.ButtonTextAlign, &bb);
|
||||
|
||||
PopStyleColor();
|
||||
|
||||
@@ -908,8 +913,9 @@ namespace ImGuiExt {
|
||||
return InputIntegerPrefix(label, "0x", value, ImGuiDataType_U64, "%llX", flags | ImGuiInputTextFlags_CharsHexadecimal);
|
||||
}
|
||||
|
||||
bool SliderBytes(const char *label, u64 *value, u64 min, u64 max, ImGuiSliderFlags flags) {
|
||||
bool SliderBytes(const char *label, u64 *value, u64 min, u64 max, u64 stepSize, ImGuiSliderFlags flags) {
|
||||
std::string format;
|
||||
|
||||
if (*value < 1024) {
|
||||
format = hex::format("{} Bytes", *value);
|
||||
} else if (*value < 1024 * 1024) {
|
||||
@@ -920,7 +926,15 @@ namespace ImGuiExt {
|
||||
format = hex::format("{:.2f} GB", *value / (1024.0 * 1024.0 * 1024.0));
|
||||
}
|
||||
|
||||
return ImGui::SliderScalar(label, ImGuiDataType_U64, value, &min, &max, format.c_str(), flags | ImGuiSliderFlags_Logarithmic);
|
||||
*value /= stepSize;
|
||||
min /= stepSize;
|
||||
max /= stepSize;
|
||||
|
||||
auto result = ImGui::SliderScalar(label, ImGuiDataType_U64, value, &min, &max, format.c_str(), flags | ImGuiSliderFlags_Logarithmic);
|
||||
|
||||
*value *= stepSize;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void SmallProgressBar(float fraction, float yOffset) {
|
||||
@@ -1096,14 +1110,14 @@ namespace ImGuiExt {
|
||||
return res;
|
||||
}
|
||||
|
||||
bool DimmedIconButton(const char *symbol, ImVec4 color, ImVec2 size){
|
||||
bool DimmedIconButton(const char *symbol, ImVec4 color, ImVec2 size, ImVec2 iconOffset) {
|
||||
PushStyleColor(ImGuiCol_ButtonHovered, GetCustomColorU32(ImGuiCustomCol_DescButtonHovered));
|
||||
PushStyleColor(ImGuiCol_Button, GetCustomColorU32(ImGuiCustomCol_DescButton));
|
||||
PushStyleColor(ImGuiCol_Text, GetColorU32(ImGuiCol_ButtonActive));
|
||||
PushStyleColor(ImGuiCol_ButtonActive, GetCustomColorU32(ImGuiCustomCol_DescButtonActive));
|
||||
PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1);
|
||||
|
||||
bool res = IconButton(symbol, color, size);
|
||||
bool res = IconButton(symbol, color, size, iconOffset);
|
||||
|
||||
PopStyleColor(4);
|
||||
PopStyleVar(1);
|
||||
@@ -1111,7 +1125,7 @@ namespace ImGuiExt {
|
||||
return res;
|
||||
}
|
||||
|
||||
bool DimmedButtonToggle(const char *icon, bool *v, ImVec2 size) {
|
||||
bool DimmedButtonToggle(const char *icon, bool *v, ImVec2 size, ImVec2 iconOffset) {
|
||||
bool pushed = false;
|
||||
bool toggled = false;
|
||||
|
||||
@@ -1120,7 +1134,7 @@ namespace ImGuiExt {
|
||||
pushed = true;
|
||||
}
|
||||
|
||||
if (DimmedIconButton(icon, GetStyleColorVec4(ImGuiCol_Text), size)) {
|
||||
if (DimmedIconButton(icon, GetStyleColorVec4(ImGuiCol_Text), size, iconOffset)) {
|
||||
*v = !*v;
|
||||
toggled = true;
|
||||
}
|
||||
|
||||
2
lib/third_party/edlib
vendored
2
lib/third_party/edlib
vendored
Submodule lib/third_party/edlib updated: 931be2b090...42aa8fa705
2
lib/third_party/fmt
vendored
2
lib/third_party/fmt
vendored
Submodule lib/third_party/fmt updated: 0c9fce2ffe...8303d140a1
4
lib/third_party/imgui/CMakeLists.txt
vendored
4
lib/third_party/imgui/CMakeLists.txt
vendored
@@ -10,7 +10,7 @@ add_subdirectory(cimgui)
|
||||
add_subdirectory(implot)
|
||||
add_subdirectory(implot3d)
|
||||
add_subdirectory(imnodes)
|
||||
add_subdirectory(custom)
|
||||
add_subdirectory(backend)
|
||||
add_subdirectory(ColorTextEditor)
|
||||
|
||||
set(IMGUI_LIBRARIES imgui_imgui imgui_cimgui imgui_implot imgui_implot3d imgui_imnodes imgui_custom imgui_color_text_editor PARENT_SCOPE)
|
||||
set(IMGUI_LIBRARIES imgui_imgui imgui_cimgui imgui_implot imgui_implot3d imgui_imnodes imgui_backend imgui_color_text_editor PARENT_SCOPE)
|
||||
@@ -307,6 +307,7 @@ public:
|
||||
return text.empty() || text == "\n";
|
||||
}
|
||||
void SetTopLine();
|
||||
void SetScrollY();
|
||||
void SetTextLines(const std::vector<std::string>& aLines);
|
||||
std::vector<std::string> GetTextLines() const;
|
||||
|
||||
@@ -406,7 +407,7 @@ public:
|
||||
void Cut();
|
||||
void Paste();
|
||||
void Delete();
|
||||
int32_t GetPageSize() const;
|
||||
float GetPageSize() const;
|
||||
|
||||
ImVec2 &GetCharAdvance() { return mCharAdvance; }
|
||||
|
||||
@@ -600,8 +601,8 @@ private:
|
||||
float mLineNumberFieldWidth = 0.0F;
|
||||
float mLongest = 0.0F;
|
||||
float mTextStart = 20.0F; // position (in pixels) where a code line starts relative to the left of the TextEditor.
|
||||
int mLeftMargin = 10;
|
||||
int mTopLine = 0;
|
||||
float mLeftMargin = 10.0;
|
||||
float mTopLine = 0.0F;
|
||||
bool mSetTopLine = false;
|
||||
bool mCursorPositionChanged = false;
|
||||
bool mBreakPointsChanged = false;
|
||||
@@ -628,10 +629,11 @@ private:
|
||||
uint64_t mStartTime = 0;
|
||||
std::vector<std::string> mDefines;
|
||||
TextEditor *mSourceCodeEditor = nullptr;
|
||||
float mSavedScrollY = 0;
|
||||
float mShiftedScrollY = 0;
|
||||
float mScrollY = 0;
|
||||
int mNumberOfLinesDisplayed = 0;
|
||||
float mScrollYIncrement = 0.0F;
|
||||
bool mSetScrollY = false;
|
||||
float mNumberOfLinesDisplayed = 0;
|
||||
float mLastClick = -1.0F;
|
||||
bool mShowCursor = true;
|
||||
bool mShowLineNumbers = true;
|
||||
|
||||
@@ -311,6 +311,9 @@ TextEditor::Coordinates TextEditor::ScreenPosToCoordinates(const ImVec2 &aPositi
|
||||
ImVec2 local(aPosition.x - origin.x, aPosition.y - origin.y);
|
||||
|
||||
int lineNo = std::max(0, (int)floor(local.y / mCharAdvance.y));
|
||||
if (local.x < mCharAdvance.x)
|
||||
return Coordinates(lineNo, 0);
|
||||
local.x -= mCharAdvance.x;
|
||||
|
||||
int columnCoord = 0;
|
||||
|
||||
@@ -349,7 +352,7 @@ TextEditor::Coordinates TextEditor::ScreenPosToCoordinates(const ImVec2 &aPositi
|
||||
}
|
||||
}
|
||||
|
||||
return SanitizeCoordinates(Coordinates(lineNo, columnCoord - (columnCoord != 0)));
|
||||
return SanitizeCoordinates(Coordinates(lineNo, columnCoord));
|
||||
}
|
||||
|
||||
void TextEditor::DeleteWordLeft() {
|
||||
@@ -891,14 +894,16 @@ void TextEditor::RenderText(const char *aTitle, const ImVec2 &lineNumbersStartPo
|
||||
ImVec2 cursorScreenPos = ImGui::GetCursorScreenPos();
|
||||
ImVec2 position = lineNumbersStartPos;
|
||||
auto scrollX = ImGui::GetScrollX();
|
||||
if (mSetScrollY)
|
||||
SetScrollY();
|
||||
auto scrollY = ImGui::GetScrollY();
|
||||
if (mSetTopLine)
|
||||
SetTopLine();
|
||||
else
|
||||
mTopLine = std::max<int>(0, std::floor((scrollY-mTopMargin) / mCharAdvance.y));
|
||||
mTopLine = std::max<float>(0.0F, (scrollY-mTopMargin) / mCharAdvance.y);
|
||||
auto lineNo = mTopLine;
|
||||
int globalLineMax = mLines.size();
|
||||
auto lineMax = std::clamp(lineNo + mNumberOfLinesDisplayed, 0, globalLineMax - 1);
|
||||
float globalLineMax = mLines.size();
|
||||
auto lineMax = std::clamp(lineNo + mNumberOfLinesDisplayed, 0.0F, globalLineMax-1.0F);
|
||||
int totalDigitCount = std::floor(std::log10(globalLineMax)) + 1;
|
||||
mLongest = GetLongestLineLength() * mCharAdvance.x;
|
||||
|
||||
@@ -906,7 +911,7 @@ void TextEditor::RenderText(const char *aTitle, const ImVec2 &lineNumbersStartPo
|
||||
char buf[16];
|
||||
|
||||
if (mShowLineNumbers)
|
||||
snprintf(buf, 16, " %d ", globalLineMax);
|
||||
snprintf(buf, 16, " %d ", int(globalLineMax));
|
||||
else
|
||||
buf[0] = '\0';
|
||||
mTextStart = ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, buf, nullptr, nullptr).x + mLeftMargin;
|
||||
@@ -915,7 +920,7 @@ void TextEditor::RenderText(const char *aTitle, const ImVec2 &lineNumbersStartPo
|
||||
float spaceSize = ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, " ", nullptr, nullptr).x;
|
||||
|
||||
while (lineNo <= lineMax) {
|
||||
ImVec2 lineStartScreenPos = ImVec2(cursorScreenPos.x + mLeftMargin, cursorScreenPos.y + lineNo * mCharAdvance.y);
|
||||
ImVec2 lineStartScreenPos = ImVec2(cursorScreenPos.x + mLeftMargin, mTopMargin + cursorScreenPos.y + std::floor(lineNo) * mCharAdvance.y);
|
||||
ImVec2 textScreenPos = lineStartScreenPos;
|
||||
|
||||
auto &line = mLines[lineNo];
|
||||
@@ -941,11 +946,8 @@ void TextEditor::RenderText(const char *aTitle, const ImVec2 &lineNumbersStartPo
|
||||
ImVec2 vend(lineStartScreenPos.x + ssend, lineStartScreenPos.y + mCharAdvance.y);
|
||||
drawList->AddRectFilled(vstart, vend, mPalette[(int)PaletteIndex::Selection]);
|
||||
}
|
||||
float startPos = 0;
|
||||
if (scrollY < mTopMargin)
|
||||
startPos = mTopMargin - scrollY;
|
||||
ImVec2 lineNoStartScreenPos = ImVec2(position.x, startPos + position.y + (lineNo - mTopLine) * mCharAdvance.y);
|
||||
auto start = ImVec2(lineNoStartScreenPos.x + mLineNumberFieldWidth, lineNoStartScreenPos.y);
|
||||
ImVec2 lineNoStartScreenPos = ImVec2(position.x, mTopMargin + cursorScreenPos.y + std::floor(lineNo) * mCharAdvance.y);
|
||||
auto start = ImVec2(lineNoStartScreenPos.x + mLineNumberFieldWidth, lineStartScreenPos.y);
|
||||
bool focused = ImGui::IsWindowFocused();
|
||||
if (!mIgnoreImGuiChild)
|
||||
ImGui::EndChild();
|
||||
@@ -960,14 +962,14 @@ void TextEditor::RenderText(const char *aTitle, const ImVec2 &lineNumbersStartPo
|
||||
while (padding-- > 0) {
|
||||
space += " ";
|
||||
}
|
||||
std::string lineNoStr = space + std::to_string(lineNo + 1);
|
||||
TextUnformattedColoredAt(ImVec2(mLeftMargin + lineNoStartScreenPos.x, lineNoStartScreenPos.y), mPalette[(int) PaletteIndex::LineNumber], lineNoStr.c_str());
|
||||
std::string lineNoStr = space + std::to_string((int)(lineNo + 1));
|
||||
TextUnformattedColoredAt(ImVec2(mLeftMargin + lineNoStartScreenPos.x, lineStartScreenPos.y), mPalette[(int) PaletteIndex::LineNumber], lineNoStr.c_str());
|
||||
}
|
||||
|
||||
// Draw breakpoints
|
||||
if (mBreakpoints.count(lineNo + 1) != 0) {
|
||||
auto end = ImVec2(lineNoStartScreenPos.x + contentSize.x + mLineNumberFieldWidth, lineNoStartScreenPos.y + mCharAdvance.y);
|
||||
drawList->AddRectFilled(ImVec2(lineNumbersStartPos.x, lineNoStartScreenPos.y), end, mPalette[(int)PaletteIndex::Breakpoint]);
|
||||
auto end = ImVec2(lineNoStartScreenPos.x + contentSize.x + mLineNumberFieldWidth, lineStartScreenPos.y + mCharAdvance.y);
|
||||
drawList->AddRectFilled(ImVec2(lineNumbersStartPos.x, lineStartScreenPos.y), end, mPalette[(int)PaletteIndex::Breakpoint]);
|
||||
|
||||
drawList->AddCircleFilled(start + ImVec2(0, mCharAdvance.y) / 2, mCharAdvance.y / 3, mPalette[(int)PaletteIndex::Breakpoint]);
|
||||
drawList->AddCircle(start + ImVec2(0, mCharAdvance.y) / 2, mCharAdvance.y / 3, mPalette[(int)PaletteIndex::Default]);
|
||||
@@ -977,9 +979,9 @@ void TextEditor::RenderText(const char *aTitle, const ImVec2 &lineNumbersStartPo
|
||||
|
||||
// Highlight the current line (where the cursor is)
|
||||
if (!HasSelection()) {
|
||||
auto end = ImVec2(lineNoStartScreenPos.x + contentSize.x + mLineNumberFieldWidth, lineNoStartScreenPos.y + mCharAdvance.y);
|
||||
drawList->AddRectFilled(ImVec2(lineNumbersStartPos.x, lineNoStartScreenPos.y), end, mPalette[(int)(focused ? PaletteIndex::CurrentLineFill : PaletteIndex::CurrentLineFillInactive)]);
|
||||
drawList->AddRect(ImVec2(lineNumbersStartPos.x, lineNoStartScreenPos.y), end, mPalette[(int)PaletteIndex::CurrentLineEdge], 1.0f);
|
||||
auto end = ImVec2(lineNoStartScreenPos.x + contentSize.x + mLineNumberFieldWidth, lineStartScreenPos.y + mCharAdvance.y);
|
||||
drawList->AddRectFilled(ImVec2(lineNumbersStartPos.x, lineStartScreenPos.y), end, mPalette[(int)(focused ? PaletteIndex::CurrentLineFill : PaletteIndex::CurrentLineFillInactive)]);
|
||||
drawList->AddRect(ImVec2(lineNumbersStartPos.x, lineStartScreenPos.y), end, mPalette[(int)PaletteIndex::CurrentLineEdge], 1.0f);
|
||||
}
|
||||
}
|
||||
if (mShowLineNumbers && !mIgnoreImGuiChild)
|
||||
@@ -1152,7 +1154,7 @@ void TextEditor::RenderText(const char *aTitle, const ImVec2 &lineNumbersStartPo
|
||||
mLineBuffer.clear();
|
||||
}
|
||||
|
||||
++lineNo;
|
||||
lineNo = std::floor(lineNo + 1.0F);
|
||||
}
|
||||
}
|
||||
if (!mIgnoreImGuiChild)
|
||||
@@ -1167,9 +1169,9 @@ void TextEditor::RenderText(const char *aTitle, const ImVec2 &lineNumbersStartPo
|
||||
ImGui::BeginChild(aTitle);
|
||||
|
||||
if (mShowLineNumbers)
|
||||
ImGui::Dummy(ImVec2(mLongest, (globalLineMax - lineMax - 2) * mCharAdvance.y + ImGui::GetCurrentWindow()->InnerClipRect.GetHeight()));
|
||||
ImGui::Dummy(ImVec2(mLongest, (globalLineMax - lineMax - 2.0F) * mCharAdvance.y + ImGui::GetCurrentWindow()->InnerClipRect.GetHeight()));
|
||||
else
|
||||
ImGui::Dummy(ImVec2(mLongest, (globalLineMax - 1 - lineMax + GetPageSize() - 1) * mCharAdvance.y));
|
||||
ImGui::Dummy(ImVec2(mLongest, (globalLineMax - 1.0f - lineMax + GetPageSize() - 1.0f ) * mCharAdvance.y - 2 * ImGuiStyle().WindowPadding.y));
|
||||
|
||||
if (mScrollToCursor)
|
||||
EnsureCursorVisible();
|
||||
@@ -1177,8 +1179,6 @@ void TextEditor::RenderText(const char *aTitle, const ImVec2 &lineNumbersStartPo
|
||||
|
||||
if (mTopMarginChanged) {
|
||||
mTopMarginChanged = false;
|
||||
if (mTopMargin == 0)
|
||||
mSavedScrollY = ImGui::GetScrollY();
|
||||
auto window = ImGui::GetCurrentWindow();
|
||||
auto maxScroll = window->ScrollMax.y;
|
||||
if (maxScroll > 0) {
|
||||
@@ -1194,10 +1194,8 @@ void TextEditor::RenderText(const char *aTitle, const ImVec2 &lineNumbersStartPo
|
||||
|
||||
if (mNewTopMargin > mTopMargin)
|
||||
mShiftedScrollY = oldScrollY + pixelCount;
|
||||
else if (mNewTopMargin > 0)
|
||||
mShiftedScrollY = oldScrollY - pixelCount;
|
||||
else
|
||||
mShiftedScrollY = mSavedScrollY;
|
||||
mShiftedScrollY = oldScrollY - pixelCount;
|
||||
ImGui::SetScrollY(mShiftedScrollY);
|
||||
mTopMargin = mNewTopMargin;
|
||||
}
|
||||
@@ -1222,6 +1220,7 @@ void TextEditor::Render(const char *aTitle, const ImVec2 &aSize, bool aBorder) {
|
||||
if (mShowLineNumbers ) {
|
||||
std::string lineNumber = " " + std::to_string(mLines.size()) + " ";
|
||||
mLineNumberFieldWidth = ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, lineNumber.c_str(), nullptr, nullptr).x + mLeftMargin;
|
||||
ImGui::SetNextWindowPos(position);
|
||||
ImGui::SetCursorScreenPos(position);
|
||||
auto lineNoSize = ImVec2(mLineNumberFieldWidth, aSize.y);
|
||||
if (!mIgnoreImGuiChild) {
|
||||
@@ -1648,6 +1647,11 @@ void TextEditor::JumpToCoords(const Coordinates &aNewPos) {
|
||||
void TextEditor::MoveUp(int aAmount, bool aSelect) {
|
||||
ResetCursorBlinkTime();
|
||||
auto oldPos = mState.mCursorPosition;
|
||||
if (aAmount < 0) {
|
||||
mScrollYIncrement = -1.0;
|
||||
SetScrollY();
|
||||
return;
|
||||
}
|
||||
mState.mCursorPosition.mLine = std::max(0, mState.mCursorPosition.mLine - aAmount);
|
||||
if (oldPos != mState.mCursorPosition) {
|
||||
if (aSelect) {
|
||||
@@ -1671,10 +1675,16 @@ void TextEditor::MoveDown(int aAmount, bool aSelect) {
|
||||
IM_ASSERT(mState.mCursorPosition.mColumn >= 0);
|
||||
ResetCursorBlinkTime();
|
||||
auto oldPos = mState.mCursorPosition;
|
||||
if (aAmount < 0) {
|
||||
mScrollYIncrement = 1.0;
|
||||
SetScrollY();
|
||||
return;
|
||||
}
|
||||
|
||||
mState.mCursorPosition.mLine = std::clamp(mState.mCursorPosition.mLine + aAmount, 0, (int)mLines.size() - 1);
|
||||
if (oldPos.mLine == (mLines.size() - 1)) {
|
||||
mTopLine += aAmount;
|
||||
mTopLine = std::clamp(mTopLine, 0, (int)mLines.size() - 1);
|
||||
mTopLine = std::clamp(mTopLine, 0.0F, mLines.size() - 1.0F);
|
||||
SetTopLine();
|
||||
EnsureCursorVisible();
|
||||
return;
|
||||
@@ -2508,7 +2518,6 @@ bool TextEditor::FindReplaceHandler::Replace(TextEditor *editor, bool next) {
|
||||
u.mAfter = editor->mState;
|
||||
editor->AddUndo(u);
|
||||
editor->mTextChanged = true;
|
||||
mMatches.erase(mMatches.begin() + matchIndex - 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -3002,6 +3011,17 @@ float TextEditor::TextDistanceToLineStart(const Coordinates &aFrom) const {
|
||||
return distance;
|
||||
}
|
||||
|
||||
void TextEditor::SetScrollY() {
|
||||
if (!mWithinRender) {
|
||||
mSetScrollY = true;
|
||||
return;
|
||||
} else {
|
||||
mSetScrollY = false;
|
||||
auto scrollY = ImGui::GetScrollY();
|
||||
ImGui::SetScrollY(std::clamp(scrollY+mScrollYIncrement,0.0f,ImGui::GetScrollMaxY()));
|
||||
}
|
||||
}
|
||||
|
||||
void TextEditor::SetTopLine() {
|
||||
if (!mWithinRender) {
|
||||
mSetTopLine = true;
|
||||
@@ -3065,9 +3085,9 @@ void TextEditor::EnsureCursorVisible() {
|
||||
mOldTopMargin = mTopMargin;
|
||||
}
|
||||
|
||||
int TextEditor::GetPageSize() const {
|
||||
auto height = ImGui::GetCurrentWindow()->InnerClipRect.GetHeight() - mTopMargin - ImGui::GetStyle().FramePadding.y;
|
||||
return (int)floor(height / mCharAdvance.y);
|
||||
float TextEditor::GetPageSize() const {
|
||||
auto height = ImGui::GetCurrentWindow()->InnerClipRect.GetHeight();
|
||||
return height / mCharAdvance.y;
|
||||
}
|
||||
|
||||
void TextEditor::ResetCursorBlinkTime() {
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
# https://github.com/ocornut/imgui with custom modifications made to the OpenGL 3 and GLFW backends
|
||||
project(imgui_custom)
|
||||
# https://github.com/ocornut/imgui backends with custom modifications made to the OpenGL 3 and GLFW backends
|
||||
project(imgui_backend)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
if (NOT IMHEX_EXTERNAL_PLUGIN_BUILD)
|
||||
add_library(imgui_custom OBJECT
|
||||
add_library(imgui_backend OBJECT
|
||||
source/imgui_impl_opengl3.cpp
|
||||
source/imgui_impl_glfw.cpp
|
||||
)
|
||||
|
||||
target_include_directories(imgui_custom PUBLIC
|
||||
target_include_directories(imgui_backend PUBLIC
|
||||
include
|
||||
)
|
||||
|
||||
target_link_libraries(imgui_custom PRIVATE imgui_includes)
|
||||
target_link_libraries(imgui_backend PRIVATE imgui_includes)
|
||||
|
||||
find_package(OpenGL REQUIRED)
|
||||
find_package(Freetype REQUIRED)
|
||||
@@ -35,9 +35,9 @@ if (NOT IMHEX_EXTERNAL_PLUGIN_BUILD)
|
||||
set(GLFW_LIBRARIES "glfw3")
|
||||
endif ()
|
||||
|
||||
target_include_directories(imgui_custom PUBLIC ${FREETYPE_INCLUDE_DIRS} ${OpenGL_INCLUDE_DIRS})
|
||||
target_link_directories(imgui_custom PUBLIC ${FREETYPE_LIBRARY_DIRS} ${OpenGL_LIBRARY_DIRS})
|
||||
target_link_libraries(imgui_custom PUBLIC ${GLFW_LIBRARIES} ${OPENGL_LIBRARIES})
|
||||
target_include_directories(imgui_backend PUBLIC ${FREETYPE_INCLUDE_DIRS} ${OpenGL_INCLUDE_DIRS})
|
||||
target_link_directories(imgui_backend PUBLIC ${FREETYPE_LIBRARY_DIRS} ${OpenGL_LIBRARY_DIRS})
|
||||
target_link_libraries(imgui_backend PUBLIC ${GLFW_LIBRARIES} ${OPENGL_LIBRARIES})
|
||||
endif()
|
||||
|
||||
target_include_directories(imgui_all_includes INTERFACE include)
|
||||
@@ -6,7 +6,7 @@
|
||||
// Implemented features:
|
||||
// [X] Platform: Clipboard support.
|
||||
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only).
|
||||
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values 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: 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'.
|
||||
@@ -28,15 +28,17 @@
|
||||
struct GLFWwindow;
|
||||
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_InitForVulkan(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_NewFrame();
|
||||
|
||||
// Emscripten related initialization phase methods
|
||||
// Emscripten related initialization phase methods (call after ImGui_ImplGlfw_InitForOpenGL)
|
||||
#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
|
||||
|
||||
// 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_MonitorCallback(GLFWmonitor* monitor, int event);
|
||||
|
||||
// GLFW helpers
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_Sleep(int milliseconds);
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
@@ -6,7 +6,7 @@
|
||||
// Implemented features:
|
||||
// [X] Platform: Clipboard support.
|
||||
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only).
|
||||
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values 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: 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'.
|
||||
@@ -21,9 +21,23 @@
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - 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
|
||||
// (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-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-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)
|
||||
@@ -104,15 +118,30 @@
|
||||
//#include <GLFW/glfw3native.h> // for glfwGetCocoaWindow()
|
||||
// #endif
|
||||
// IMHEX PATCH END
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h> // for usleep()
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
#include <string_view>
|
||||
#include <cstdlib>
|
||||
#endif
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#include <emscripten.h>
|
||||
#include <emscripten/html5.h>
|
||||
|
||||
// IMHEX PATCH BEGIN
|
||||
#include <emscripten_browser_clipboard.h>
|
||||
|
||||
static std::string clipboardContent;
|
||||
// IMHEX PATCH END
|
||||
|
||||
#ifdef EMSCRIPTEN_USE_PORT_CONTRIB_GLFW3
|
||||
#include <GLFW/emscripten_glfw3.h>
|
||||
#else
|
||||
#define EMSCRIPTEN_USE_EMBEDDED_GLFW3
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// We gather version tests as define in order to easily see which features are version-dependent.
|
||||
@@ -159,12 +188,14 @@ struct ImGui_ImplGlfw_Data
|
||||
double Time;
|
||||
GLFWwindow* MouseWindow;
|
||||
GLFWcursor* MouseCursors[ImGuiMouseCursor_COUNT];
|
||||
bool MouseIgnoreButtonUpWaitForFocusLoss;
|
||||
bool MouseIgnoreButtonUp;
|
||||
ImVec2 LastValidMousePos;
|
||||
GLFWwindow* KeyOwnerWindows[GLFW_KEY_LAST];
|
||||
bool InstalledCallbacks;
|
||||
bool CallbacksChainForAllWindows;
|
||||
bool WantUpdateMonitors;
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3
|
||||
const char* CanvasSelector;
|
||||
#endif
|
||||
|
||||
@@ -198,8 +229,8 @@ static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_GetBackendData()
|
||||
|
||||
// Forward Declarations
|
||||
static void ImGui_ImplGlfw_UpdateMonitors();
|
||||
static void ImGui_ImplGlfw_InitPlatformInterface();
|
||||
static void ImGui_ImplGlfw_ShutdownPlatformInterface();
|
||||
static void ImGui_ImplGlfw_InitMultiViewportSupport();
|
||||
static void ImGui_ImplGlfw_ShutdownMultiViewportSupport();
|
||||
|
||||
// Functions
|
||||
static const char* ImGui_ImplGlfw_GetClipboardText(void* user_data)
|
||||
@@ -224,9 +255,12 @@ static void ImGui_ImplGlfw_SetClipboardText(void* user_data, const char* text)
|
||||
// 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_LEFT: return ImGuiKey_LeftArrow;
|
||||
@@ -351,13 +385,34 @@ static ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int key)
|
||||
|
||||
// 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
|
||||
static void ImGui_ImplGlfw_UpdateKeyModifiers(GLFWwindow* window)
|
||||
static void ImGui_ImplGlfw_UpdateKeyModifiers(GLFWwindow* window, int mods)
|
||||
{
|
||||
// IMHEX PATCH BEGIN
|
||||
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));
|
||||
io.AddKeyEvent(ImGuiMod_Alt, (glfwGetKey(window, GLFW_KEY_LEFT_ALT) == GLFW_PRESS) || (glfwGetKey(window, GLFW_KEY_RIGHT_ALT) == GLFW_PRESS));
|
||||
io.AddKeyEvent(ImGuiMod_Super, (glfwGetKey(window, GLFW_KEY_LEFT_SUPER) == GLFW_PRESS) || (glfwGetKey(window, GLFW_KEY_RIGHT_SUPER) == GLFW_PRESS));
|
||||
|
||||
#ifdef __linux__
|
||||
static bool isX11 = [] {
|
||||
const auto sessionType = std::getenv("XDG_SESSION_TYPE");
|
||||
if (sessionType == nullptr)
|
||||
return false;
|
||||
|
||||
return std::string_view(sessionType) == "x11";
|
||||
}();
|
||||
|
||||
if (isX11) {
|
||||
io.AddKeyEvent(ImGuiMod_Ctrl, (glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS) || (glfwGetKey(window, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS));
|
||||
io.AddKeyEvent(ImGuiMod_Shift, (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) || (glfwGetKey(window, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS));
|
||||
io.AddKeyEvent(ImGuiMod_Alt, (glfwGetKey(window, GLFW_KEY_LEFT_ALT) == GLFW_PRESS) || (glfwGetKey(window, GLFW_KEY_RIGHT_ALT) == GLFW_PRESS));
|
||||
io.AddKeyEvent(ImGuiMod_Super, (glfwGetKey(window, GLFW_KEY_LEFT_SUPER) == GLFW_PRESS) || (glfwGetKey(window, GLFW_KEY_RIGHT_SUPER) == GLFW_PRESS));
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
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)
|
||||
@@ -372,7 +427,11 @@ void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int acti
|
||||
if (bd->PrevUserCallbackMousebutton != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window))
|
||||
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(window, mods);
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
if (button >= 0 && button < ImGuiMouseButton_COUNT)
|
||||
@@ -385,7 +444,7 @@ void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yo
|
||||
if (bd->PrevUserCallbackScroll != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window))
|
||||
bd->PrevUserCallbackScroll(window, xoffset, yoffset);
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3
|
||||
// Ignore GLFW events: will be processed in ImGui_ImplEmscripten_WheelCallback().
|
||||
return;
|
||||
#endif
|
||||
@@ -394,9 +453,10 @@ void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yo
|
||||
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)
|
||||
{
|
||||
#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.
|
||||
// (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.
|
||||
@@ -407,7 +467,7 @@ static int ImGui_ImplGlfw_TranslateUntranslatedKey(int key, int scancode)
|
||||
GLFWerrorfun prev_error_callback = glfwSetErrorCallback(nullptr);
|
||||
const char* key_name = glfwGetKeyName(key, scancode);
|
||||
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);
|
||||
#endif
|
||||
if (key_name && key_name[0] != 0 && key_name[1] == 0)
|
||||
@@ -436,7 +496,7 @@ void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int keycode, int scancode, i
|
||||
if (action != GLFW_PRESS && action != GLFW_RELEASE)
|
||||
return;
|
||||
|
||||
ImGui_ImplGlfw_UpdateKeyModifiers(window);
|
||||
ImGui_ImplGlfw_UpdateKeyModifiers(window, mods);
|
||||
|
||||
if (keycode >= 0 && keycode < IM_ARRAYSIZE(bd->KeyOwnerWindows))
|
||||
bd->KeyOwnerWindows[keycode] = (action == GLFW_PRESS) ? window : nullptr;
|
||||
@@ -444,7 +504,7 @@ void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int keycode, int scancode, i
|
||||
keycode = ImGui_ImplGlfw_TranslateUntranslatedKey(keycode, scancode);
|
||||
|
||||
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.SetKeyEventNativeData(imgui_key, keycode, scancode); // To support legacy indexing (<1.87 user code)
|
||||
}
|
||||
@@ -455,6 +515,10 @@ void ImGui_ImplGlfw_WindowFocusCallback(GLFWwindow* window, int focused)
|
||||
if (bd->PrevUserCallbackWindowFocus != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window))
|
||||
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();
|
||||
io.AddFocusEvent(focused != 0);
|
||||
}
|
||||
@@ -515,7 +579,7 @@ void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor*, int)
|
||||
bd->WantUpdateMonitors = true;
|
||||
}
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3
|
||||
static EM_BOOL ImGui_ImplEmscripten_WheelCallback(int, const EmscriptenWheelEvent* ev, void*)
|
||||
{
|
||||
// Mimic Emscripten_HandleWheel() in SDL.
|
||||
@@ -600,6 +664,7 @@ EM_JS(void, ImGui_ImplGlfw_EmscriptenOpenURL, (const char* url), { url = url ? U
|
||||
static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, GlfwClientApi client_api)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IMGUI_CHECKVERSION();
|
||||
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);
|
||||
|
||||
@@ -665,14 +730,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.
|
||||
if (install_callbacks)
|
||||
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();
|
||||
glfwSetMonitorCallback(ImGui_ImplGlfw_MonitorCallback);
|
||||
|
||||
@@ -689,8 +749,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
|
||||
#else
|
||||
IM_UNUSED(main_viewport);
|
||||
#endif
|
||||
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
|
||||
ImGui_ImplGlfw_InitPlatformInterface();
|
||||
ImGui_ImplGlfw_InitMultiViewportSupport();
|
||||
|
||||
// Windows: register a WndProc hook so we can intercept some messages.
|
||||
#ifdef _WIN32
|
||||
@@ -699,6 +758,23 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
|
||||
::SetWindowLongPtrW((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC, (LONG_PTR)ImGui_ImplGlfw_WndProc);
|
||||
#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;
|
||||
return true;
|
||||
}
|
||||
@@ -724,12 +800,13 @@ void ImGui_ImplGlfw_Shutdown()
|
||||
IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
ImGui_ImplGlfw_ShutdownPlatformInterface();
|
||||
ImGui_ImplGlfw_ShutdownMultiViewportSupport();
|
||||
|
||||
if (bd->InstalledCallbacks)
|
||||
ImGui_ImplGlfw_RestoreCallbacks(bd->Window);
|
||||
#ifdef __EMSCRIPTEN__
|
||||
emscripten_set_wheel_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, nullptr, false, nullptr);
|
||||
#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3
|
||||
if (bd->CanvasSelector)
|
||||
emscripten_set_wheel_callback(bd->CanvasSelector, nullptr, false, nullptr);
|
||||
#endif
|
||||
|
||||
for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)
|
||||
@@ -761,14 +838,14 @@ static void ImGui_ImplGlfw_UpdateMouseData()
|
||||
ImGuiViewport* viewport = platform_io.Viewports[n];
|
||||
GLFWwindow* window = (GLFWwindow*)viewport->PlatformHandle;
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3
|
||||
const bool is_window_focused = true;
|
||||
#else
|
||||
const bool is_window_focused = glfwGetWindowAttrib(window, GLFW_FOCUSED) != 0;
|
||||
#endif
|
||||
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.
|
||||
if (io.WantSetMousePos)
|
||||
glfwSetCursorPos(window, (double)(mouse_pos_prev.x - viewport->Pos.x), (double)(mouse_pos_prev.y - viewport->Pos.y));
|
||||
@@ -840,7 +917,6 @@ static void ImGui_ImplGlfw_UpdateMouseCursor()
|
||||
{
|
||||
// Show OS mouse cursor
|
||||
// FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here.
|
||||
|
||||
// IMHEX PATCH BEGIN
|
||||
#if !defined(_WIN32)
|
||||
glfwSetCursor(window, bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow]);
|
||||
@@ -861,7 +937,7 @@ static void ImGui_ImplGlfw_UpdateGamepads()
|
||||
return;
|
||||
|
||||
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
|
||||
#if GLFW_HAS_GAMEPAD_API && !defined(__EMSCRIPTEN__)
|
||||
#if GLFW_HAS_GAMEPAD_API && !defined(EMSCRIPTEN_USE_EMBEDDED_GLFW3)
|
||||
GLFWgamepadstate gamepad;
|
||||
if (!glfwGetGamepadState(GLFW_JOYSTICK_1, &gamepad))
|
||||
return;
|
||||
@@ -940,13 +1016,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.
|
||||
float 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;
|
||||
|
||||
// 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
|
||||
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);
|
||||
@@ -978,6 +1050,7 @@ void ImGui_ImplGlfw_NewFrame()
|
||||
io.DeltaTime = bd->Time > 0.0 ? (float)(current_time - bd->Time) : (float)(1.0f / 60.0f);
|
||||
bd->Time = current_time;
|
||||
|
||||
bd->MouseIgnoreButtonUp = false;
|
||||
ImGui_ImplGlfw_UpdateMouseData();
|
||||
ImGui_ImplGlfw_UpdateMouseCursor();
|
||||
|
||||
@@ -985,7 +1058,17 @@ void ImGui_ImplGlfw_NewFrame()
|
||||
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)
|
||||
{
|
||||
ImGui_ImplGlfw_Data* bd = (ImGui_ImplGlfw_Data*)user_data;
|
||||
@@ -1006,7 +1089,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.
|
||||
// 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);
|
||||
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
|
||||
@@ -1018,8 +1101,24 @@ void ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback(const char* canvas_sel
|
||||
|
||||
// Change the size of the GLFW window according to the size of the canvas
|
||||
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
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
@@ -1091,6 +1190,11 @@ static void ImGui_ImplGlfw_CreateWindow(ImGuiViewport* viewport)
|
||||
ImGui_ImplGlfw_ViewportData* vd = IM_NEW(ImGui_ImplGlfw_ViewportData)();
|
||||
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
|
||||
// With GLFW 3.3, the hint GLFW_FOCUS_ON_SHOW fixes this problem
|
||||
glfwWindowHint(GLFW_VISIBLE, false);
|
||||
@@ -1152,6 +1256,7 @@ static void ImGui_ImplGlfw_DestroyWindow(ImGuiViewport* viewport)
|
||||
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.
|
||||
}
|
||||
|
||||
glfwDestroyWindow(vd->Window);
|
||||
}
|
||||
vd->Window = nullptr;
|
||||
@@ -1324,7 +1429,7 @@ static int ImGui_ImplGlfw_CreateVkSurface(ImGuiViewport* viewport, ImU64 vk_inst
|
||||
}
|
||||
#endif // GLFW_HAS_VULKAN
|
||||
|
||||
static void ImGui_ImplGlfw_InitPlatformInterface()
|
||||
static void ImGui_ImplGlfw_InitMultiViewportSupport()
|
||||
{
|
||||
// Register platform interface (will be coupled with a renderer interface)
|
||||
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
|
||||
@@ -1359,7 +1464,7 @@ static void ImGui_ImplGlfw_InitPlatformInterface()
|
||||
main_viewport->PlatformHandle = (void*)bd->Window;
|
||||
}
|
||||
|
||||
static void ImGui_ImplGlfw_ShutdownPlatformInterface()
|
||||
static void ImGui_ImplGlfw_ShutdownMultiViewportSupport()
|
||||
{
|
||||
ImGui::DestroyPlatformWindows();
|
||||
}
|
||||
29
lib/third_party/imgui/imgui/include/imgui.h
vendored
29
lib/third_party/imgui/imgui/include/imgui.h
vendored
@@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.91.6
|
||||
// dear imgui, v1.91.7
|
||||
// (headers)
|
||||
|
||||
// Help:
|
||||
@@ -28,8 +28,8 @@
|
||||
|
||||
// Library Version
|
||||
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
|
||||
#define IMGUI_VERSION "1.91.6"
|
||||
#define IMGUI_VERSION_NUM 19160
|
||||
#define IMGUI_VERSION "1.91.7"
|
||||
#define IMGUI_VERSION_NUM 19170
|
||||
#define IMGUI_HAS_TABLE
|
||||
#define IMGUI_HAS_VIEWPORT // Viewport WIP branch
|
||||
#define IMGUI_HAS_DOCK // Docking WIP branch
|
||||
@@ -141,6 +141,7 @@ Index of this file:
|
||||
#elif defined(__GNUC__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
|
||||
#pragma GCC diagnostic ignored "-Wfloat-equal" // warning: comparing floating-point with '==' or '!=' is unsafe
|
||||
#pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
|
||||
#endif
|
||||
|
||||
@@ -700,6 +701,7 @@ namespace ImGui
|
||||
|
||||
// Widgets: List Boxes
|
||||
// - This is essentially a thin wrapper to using BeginChild/EndChild with the ImGuiChildFlags_FrameStyle flag for stylistic changes + displaying a label.
|
||||
// - If you don't need a label you can probably simply use BeginChild() with the ImGuiChildFlags_FrameStyle flag for the same result.
|
||||
// - You can submit contents and manage your selection state however you want it, by creating e.g. Selectable() or any other items.
|
||||
// - The simplified/old ListBox() api are helpers over BeginListBox()/EndListBox() which are kept available for convenience purpose. This is analoguous to how Combos are created.
|
||||
// - Choose frame width: size.x > 0.0f: custom / size.x < 0.0f or -FLT_MIN: right-align / size.x = 0.0f (default): use current ItemWidth
|
||||
@@ -1136,8 +1138,8 @@ enum ImGuiWindowFlags_
|
||||
|
||||
// Obsolete names
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
ImGuiWindowFlags_NavFlattened = 1 << 29, // Obsoleted in 1.90.9: Use ImGuiChildFlags_NavFlattened in BeginChild() call.
|
||||
ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 30, // Obsoleted in 1.90.0: Use ImGuiChildFlags_AlwaysUseWindowPadding in BeginChild() call.
|
||||
ImGuiWindowFlags_NavFlattened = 1 << 31, // Obsoleted in 1.90.9: Use ImGuiChildFlags_NavFlattened in BeginChild() call.
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -1219,7 +1221,7 @@ enum ImGuiInputTextFlags_
|
||||
ImGuiInputTextFlags_CallbackAlways = 1 << 20, // Callback on each iteration. User code may query cursor position, modify text buffer.
|
||||
ImGuiInputTextFlags_CallbackCharFilter = 1 << 21, // Callback on character inputs to replace or discard them. Modify 'EventChar' to replace or discard, or return 1 in callback to discard.
|
||||
ImGuiInputTextFlags_CallbackResize = 1 << 22, // Callback on buffer capacity changes request (beyond 'buf_size' parameter value), allowing the string to grow. Notify when the string wants to be resized (for string types which hold a cache of their Size). You will be provided a new BufSize in the callback and NEED to honor it. (see misc/cpp/imgui_stdlib.h for an example of using this)
|
||||
ImGuiInputTextFlags_CallbackEdit = 1 << 23, // Callback on any edit (note that InputText() already returns true on edit, the callback is useful mainly to manipulate the underlying buffer while focus is active)
|
||||
ImGuiInputTextFlags_CallbackEdit = 1 << 23, // Callback on any edit. Note that InputText() already returns true on edit + you can always use IsItemEdited(). The callback is useful to manipulate the underlying buffer while focus is active.
|
||||
|
||||
// Obsolete names
|
||||
//ImGuiInputTextFlags_AlwaysInsertMode = ImGuiInputTextFlags_AlwaysOverwrite // [renamed in 1.82] name was not matching behavior
|
||||
@@ -1242,14 +1244,16 @@ enum ImGuiTreeNodeFlags_
|
||||
ImGuiTreeNodeFlags_FramePadding = 1 << 10, // Use FramePadding (even for an unframed text node) to vertically align text baseline to regular widget height. Equivalent to calling AlignTextToFramePadding() before the node.
|
||||
ImGuiTreeNodeFlags_SpanAvailWidth = 1 << 11, // Extend hit box to the right-most edge, even if not framed. This is not the default in order to allow adding other items on the same line without using AllowOverlap mode.
|
||||
ImGuiTreeNodeFlags_SpanFullWidth = 1 << 12, // Extend hit box to the left-most and right-most edges (cover the indent area).
|
||||
ImGuiTreeNodeFlags_SpanTextWidth = 1 << 13, // Narrow hit box + narrow hovering highlight, will only cover the label text.
|
||||
ImGuiTreeNodeFlags_SpanAllColumns = 1 << 14, // Frame will span all columns of its container table (text will still fit in current column)
|
||||
ImGuiTreeNodeFlags_NavLeftJumpsBackHere = 1 << 15, // (WIP) Nav: left direction may move to this TreeNode() from any of its child (items submitted between TreeNode and TreePop)
|
||||
ImGuiTreeNodeFlags_SpanLabelWidth = 1 << 13, // Narrow hit box + narrow hovering highlight, will only cover the label text.
|
||||
ImGuiTreeNodeFlags_SpanAllColumns = 1 << 14, // Frame will span all columns of its container table (label will still fit in current column)
|
||||
ImGuiTreeNodeFlags_LabelSpanAllColumns = 1 << 15, // Label will span all columns of its container table
|
||||
//ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 16, // FIXME: TODO: Disable automatic scroll on TreePop() if node got just open and contents is not visible
|
||||
ImGuiTreeNodeFlags_NavLeftJumpsBackHere = 1 << 17, // (WIP) Nav: left direction may move to this TreeNode() from any of its child (items submitted between TreeNode and TreePop)
|
||||
ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_NoAutoOpenOnLog,
|
||||
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
ImGuiTreeNodeFlags_AllowItemOverlap = ImGuiTreeNodeFlags_AllowOverlap, // Renamed in 1.89.7
|
||||
ImGuiTreeNodeFlags_SpanTextWidth = ImGuiTreeNodeFlags_SpanLabelWidth,// Renamed in 1.90.7
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -1457,6 +1461,7 @@ enum ImGuiDataType_
|
||||
ImGuiDataType_Float, // float
|
||||
ImGuiDataType_Double, // double
|
||||
ImGuiDataType_Bool, // bool (provided for user convenience, not supported by scalar widgets)
|
||||
ImGuiDataType_String, // char* (provided for user convenience, not supported by scalar widgets)
|
||||
ImGuiDataType_COUNT
|
||||
};
|
||||
|
||||
@@ -1865,6 +1870,7 @@ enum ImGuiSliderFlags_
|
||||
ImGuiSliderFlags_WrapAround = 1 << 8, // Enable wrapping around from max to min and from min to max. Only supported by DragXXX() functions for now.
|
||||
ImGuiSliderFlags_ClampOnInput = 1 << 9, // Clamp value to min/max bounds when input manually with CTRL+Click. By default CTRL+Click allows going out of bounds.
|
||||
ImGuiSliderFlags_ClampZeroRange = 1 << 10, // Clamp even if min==max==0.0f. Otherwise due to legacy reason DragXXX functions don't clamp with those values. When your clamping limits are dynamic you almost always want to use it.
|
||||
ImGuiSliderFlags_NoSpeedTweaks = 1 << 11, // Disable keyboard modifiers altering tweak speed. Useful if you want to alter tweak speed yourself based on your own logic.
|
||||
ImGuiSliderFlags_AlwaysClamp = ImGuiSliderFlags_ClampOnInput | ImGuiSliderFlags_ClampZeroRange,
|
||||
ImGuiSliderFlags_InvalidMask_ = 0x7000000F, // [Internal] We treat using those bits as being potentially a 'float power' argument from the previous API that has got miscast to this enum, and will trigger an assert if needed.
|
||||
};
|
||||
@@ -2535,7 +2541,7 @@ struct ImGuiIO
|
||||
// Shared state of InputText(), passed as an argument to your callback when a ImGuiInputTextFlags_Callback* flag is used.
|
||||
// The callback function should return 0 by default.
|
||||
// Callbacks (follow a flag name and see comments in ImGuiInputTextFlags_ declarations for more details)
|
||||
// - ImGuiInputTextFlags_CallbackEdit: Callback on buffer edit (note that InputText() already returns true on edit, the callback is useful mainly to manipulate the underlying buffer while focus is active)
|
||||
// - ImGuiInputTextFlags_CallbackEdit: Callback on buffer edit. Note that InputText() already returns true on edit + you can always use IsItemEdited(). The callback is useful to manipulate the underlying buffer while focus is active.
|
||||
// - ImGuiInputTextFlags_CallbackAlways: Callback on each iteration
|
||||
// - ImGuiInputTextFlags_CallbackCompletion: Callback on pressing TAB
|
||||
// - ImGuiInputTextFlags_CallbackHistory: Callback on pressing Up/Down arrows
|
||||
@@ -2810,6 +2816,7 @@ struct ImGuiListClipper
|
||||
// - It is important that we are keeping those disabled by default so they don't leak in user space.
|
||||
// - This is in order to allow user enabling implicit cast operators between ImVec2/ImVec4 and their own types (using IM_VEC2_CLASS_EXTRA in imconfig.h)
|
||||
// - Add '#define IMGUI_DEFINE_MATH_OPERATORS' before including this file (or in imconfig.h) to access courtesy maths operators for ImVec2 and ImVec4.
|
||||
// - We intentionally provide ImVec2*float but not float*ImVec2: this is rare enough and we want to reduce the surface for possible user mistake.
|
||||
#ifdef IMGUI_DEFINE_MATH_OPERATORS
|
||||
#define IMGUI_DEFINE_MATH_OPERATORS_IMPLEMENTED
|
||||
IM_MSVC_RUNTIME_CHECKS_OFF
|
||||
@@ -3011,7 +3018,7 @@ struct ImGuiSelectionBasicStorage
|
||||
IMGUI_API void Clear(); // Clear selection
|
||||
IMGUI_API void Swap(ImGuiSelectionBasicStorage& r); // Swap two selections
|
||||
IMGUI_API void SetItemSelected(ImGuiID id, bool selected); // Add/remove an item from selection (generally done by ApplyRequests() function)
|
||||
IMGUI_API bool GetNextSelectedItem(void** opaque_it, ImGuiID* out_id); // Iterate selection with 'void* it = NULL; ImGuiId id; while (selection.GetNextSelectedItem(&it, &id)) { ... }'
|
||||
IMGUI_API bool GetNextSelectedItem(void** opaque_it, ImGuiID* out_id); // Iterate selection with 'void* it = NULL; ImGuiID id; while (selection.GetNextSelectedItem(&it, &id)) { ... }'
|
||||
inline ImGuiID GetStorageIdFromIndex(int idx) { return AdapterIndexToStorageId(this, idx); } // Convert index to item id based on provided adapter.
|
||||
};
|
||||
|
||||
@@ -3399,7 +3406,7 @@ struct ImFontConfig
|
||||
unsigned int FontBuilderFlags; // 0 // Settings for custom font builder. THIS IS BUILDER IMPLEMENTATION DEPENDENT. Leave as zero if unsure.
|
||||
float RasterizerMultiply; // 1.0f // Linearly brighten (>1.0f) or darken (<1.0f) font output. Brightening small fonts may be a good workaround to make them more readable. This is a silly thing we may remove in the future.
|
||||
float RasterizerDensity; // 1.0f // DPI scale for rasterization, not altering other font metrics: make it easy to swap between e.g. a 100% and a 400% fonts for a zooming display. IMPORTANT: If you increase this it is expected that you increase font scale accordingly, otherwise quality may look lowered.
|
||||
ImWchar EllipsisChar; // -1 // Explicitly specify unicode codepoint of ellipsis character. When fonts are being merged first specified ellipsis will be used.
|
||||
ImWchar EllipsisChar; // 0 // Explicitly specify unicode codepoint of ellipsis character. When fonts are being merged first specified ellipsis will be used.
|
||||
|
||||
// [Internal]
|
||||
char Name[40]; // Name (strictly to ease debugging)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.91.6
|
||||
// dear imgui, v1.91.7
|
||||
// (internal structures/api)
|
||||
|
||||
// You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility.
|
||||
@@ -101,6 +101,7 @@ Index of this file:
|
||||
#elif defined(__GNUC__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
|
||||
#pragma GCC diagnostic ignored "-Wfloat-equal" // warning: comparing floating-point with '==' or '!=' is unsafe
|
||||
#pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-enum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated
|
||||
#endif
|
||||
@@ -139,6 +140,7 @@ struct ImGuiContext; // Main Dear ImGui context
|
||||
struct ImGuiContextHook; // Hook for extensions like ImGuiTestEngine
|
||||
struct ImGuiDataVarInfo; // Variable information (e.g. to access style variables from an enum)
|
||||
struct ImGuiDataTypeInfo; // Type information associated to a ImGuiDataType enum
|
||||
struct ImGuiDeactivatedItemData; // Data for IsItemDeactivated()/IsItemDeactivatedAfterEdit() function.
|
||||
struct ImGuiDockContext; // Docking system context
|
||||
struct ImGuiDockRequest; // Docking system dock/undock queued request
|
||||
struct ImGuiDockNode; // Docking system node (hold a list of Windows OR two child dock nodes)
|
||||
@@ -472,7 +474,7 @@ static inline double ImRsqrt(double x) { return 1.0 / sqrt(x); }
|
||||
template<typename T> static inline T ImMin(T lhs, T rhs) { return lhs < rhs ? lhs : rhs; }
|
||||
template<typename T> static inline T ImMax(T lhs, T rhs) { return lhs >= rhs ? lhs : rhs; }
|
||||
template<typename T> static inline T ImClamp(T v, T mn, T mx) { return (v < mn) ? mn : (v > mx) ? mx : v; }
|
||||
template<typename T> static inline T ImLerp(T a, T b, float t) { return (T)(a + (b - a) * t); }
|
||||
template<typename T> static inline T ImLerp(T a, T b, float t) { return (T)(a + (b - a) * (T)t); }
|
||||
template<typename T> static inline void ImSwap(T& a, T& b) { T tmp = a; a = b; b = tmp; }
|
||||
template<typename T> static inline T ImAddClampOverflow(T a, T b, T mn, T mx) { if (b < 0 && (a < mn - b)) return mn; if (b > 0 && (a > mx - b)) return mx; return a + b; }
|
||||
template<typename T> static inline T ImSubClampOverflow(T a, T b, T mn, T mx) { if (b > 0 && (a < mn + b)) return mn; if (b < 0 && (a > mx + b)) return mx; return a - b; }
|
||||
@@ -842,8 +844,7 @@ struct ImGuiDataTypeInfo
|
||||
// Extend ImGuiDataType_
|
||||
enum ImGuiDataTypePrivate_
|
||||
{
|
||||
ImGuiDataType_String = ImGuiDataType_COUNT + 1,
|
||||
ImGuiDataType_Pointer,
|
||||
ImGuiDataType_Pointer = ImGuiDataType_COUNT + 1,
|
||||
ImGuiDataType_ID,
|
||||
};
|
||||
|
||||
@@ -929,7 +930,7 @@ enum ImGuiButtonFlagsPrivate_
|
||||
ImGuiButtonFlags_PressedOnRelease = 1 << 7, // return true on release (default requires click+release)
|
||||
ImGuiButtonFlags_PressedOnDoubleClick = 1 << 8, // return true on double-click (default requires click+release)
|
||||
ImGuiButtonFlags_PressedOnDragDropHold = 1 << 9, // return true when held into while we are drag and dropping another item (used by e.g. tree nodes, collapsing headers)
|
||||
//ImGuiButtonFlags_Repeat = 1 << 10, // hold to repeat
|
||||
//ImGuiButtonFlags_Repeat = 1 << 10, // hold to repeat -> use ImGuiItemFlags_ButtonRepeat instead.
|
||||
ImGuiButtonFlags_FlattenChildren = 1 << 11, // allow interactions even if a child window is overlapping
|
||||
ImGuiButtonFlags_AllowOverlap = 1 << 12, // require previous frame HoveredId to either match id or be null before being usable.
|
||||
//ImGuiButtonFlags_DontClosePopups = 1 << 13, // disable automatically closing parent popup on press
|
||||
@@ -1086,7 +1087,7 @@ struct IMGUI_API ImGuiGroupData
|
||||
ImVec2 BackupCurrLineSize;
|
||||
float BackupCurrLineTextBaseOffset;
|
||||
ImGuiID BackupActiveIdIsAlive;
|
||||
bool BackupActiveIdPreviousFrameIsAlive;
|
||||
bool BackupDeactivatedIdIsAlive;
|
||||
bool BackupHoveredIdIsAlive;
|
||||
bool BackupIsSameLine;
|
||||
bool EmitItem;
|
||||
@@ -1137,8 +1138,10 @@ struct IMGUI_API ImGuiInputTextState
|
||||
{
|
||||
ImGuiContext* Ctx; // parent UI context (needs to be set explicitly by parent).
|
||||
ImStbTexteditState* Stb; // State for stb_textedit.h
|
||||
ImGuiInputTextFlags Flags; // copy of InputText() flags. may be used to check if e.g. ImGuiInputTextFlags_Password is set.
|
||||
ImGuiID ID; // widget id owning the text state
|
||||
int TextLen; // UTF-8 length of the string in TextA (in bytes)
|
||||
const char* TextSrc; // == TextA.Data unless read-only, in which case == buf passed to InputText(). Field only set and valid _inside_ the call InputText() call.
|
||||
ImVector<char> TextA; // main UTF8 buffer. TextA.Size is a buffer size! Should always be >= buf_size passed by user (and of course >= CurLenA + 1).
|
||||
ImVector<char> TextToRevertTo; // value to revert to when pressing Escape = backup of end-user buffer at the time of focus (in UTF-8, unaltered)
|
||||
ImVector<char> CallbackTextBackup; // temporary storage for callback to support automatic reconcile of undo-stack
|
||||
@@ -1148,9 +1151,8 @@ struct IMGUI_API ImGuiInputTextState
|
||||
bool CursorFollow; // set when we want scrolling to follow the current cursor position (not always!)
|
||||
bool SelectedAllMouseLock; // after a double-click to select all, we ignore further mouse drags to update selection
|
||||
bool Edited; // edited this frame
|
||||
ImGuiInputTextFlags Flags; // copy of InputText() flags. may be used to check if e.g. ImGuiInputTextFlags_Password is set.
|
||||
bool ReloadUserBuf; // force a reload of user buf so it may be modified externally. may be automatic in future version.
|
||||
int ReloadSelectionStart; // POSITIONS ARE IN IMWCHAR units *NOT* UTF-8 this is why this is not exposed yet.
|
||||
bool WantReloadUserBuf; // force a reload of user buf so it may be modified externally. may be automatic in future version.
|
||||
int ReloadSelectionStart;
|
||||
int ReloadSelectionEnd;
|
||||
|
||||
ImGuiInputTextState();
|
||||
@@ -1270,11 +1272,11 @@ struct ImGuiNextItemData
|
||||
struct ImGuiLastItemData
|
||||
{
|
||||
ImGuiID ID;
|
||||
ImGuiItemFlags ItemFlags; // See ImGuiItemFlags_
|
||||
ImGuiItemFlags ItemFlags; // See ImGuiItemFlags_ (called 'InFlags' before v1.91.4).
|
||||
ImGuiItemStatusFlags StatusFlags; // See ImGuiItemStatusFlags_
|
||||
ImRect Rect; // Full rectangle
|
||||
ImRect NavRect; // Navigation scoring rectangle (not displayed)
|
||||
// Rarely used fields are not explicitly cleared, only valid when the corresponding ImGuiItemStatusFlags ar set.
|
||||
// Rarely used fields are not explicitly cleared, only valid when the corresponding ImGuiItemStatusFlags are set.
|
||||
ImRect DisplayRect; // Display rectangle. ONLY VALID IF (StatusFlags & ImGuiItemStatusFlags_HasDisplayRect) is set.
|
||||
ImRect ClipRect; // Clip rectangle at the time of submitting item. ONLY VALID IF (StatusFlags & ImGuiItemStatusFlags_HasClipRect) is set..
|
||||
ImGuiKeyChord Shortcut; // Shortcut at the time of submitting item. ONLY VALID IF (StatusFlags & ImGuiItemStatusFlags_HasShortcut) is set..
|
||||
@@ -1337,6 +1339,15 @@ struct ImGuiPtrOrIndex
|
||||
ImGuiPtrOrIndex(int index) { Ptr = NULL; Index = index; }
|
||||
};
|
||||
|
||||
// Data used by IsItemDeactivated()/IsItemDeactivatedAfterEdit() functions
|
||||
struct ImGuiDeactivatedItemData
|
||||
{
|
||||
ImGuiID ID;
|
||||
int ElapseFrame;
|
||||
bool HasBeenEditedBefore;
|
||||
bool IsAlive;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Popup support
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -2244,9 +2255,9 @@ struct ImGuiContext
|
||||
int FrameCountEnded;
|
||||
int FrameCountPlatformEnded;
|
||||
int FrameCountRendered;
|
||||
ImGuiID WithinEndChildID; // Set within EndChild()
|
||||
bool WithinFrameScope; // Set by NewFrame(), cleared by EndFrame()
|
||||
bool WithinFrameScopeWithImplicitWindow; // Set by NewFrame(), cleared by EndFrame() when the implicit debug window has been pushed
|
||||
bool WithinEndChild; // Set within EndChild()
|
||||
bool GcCompactAll; // Request full GC
|
||||
bool TestEngineHookItems; // Will call test engine hooks: ImGuiTestEngineHook_ItemAdd(), ImGuiTestEngineHook_ItemInfo(), ImGuiTestEngineHook_Log()
|
||||
void* TestEngine; // Test engine user data
|
||||
@@ -2306,9 +2317,8 @@ struct ImGuiContext
|
||||
ImGuiWindow* ActiveIdWindow;
|
||||
ImGuiInputSource ActiveIdSource; // Activating source: ImGuiInputSource_Mouse OR ImGuiInputSource_Keyboard OR ImGuiInputSource_Gamepad
|
||||
ImGuiID ActiveIdPreviousFrame;
|
||||
bool ActiveIdPreviousFrameIsAlive;
|
||||
bool ActiveIdPreviousFrameHasBeenEditedBefore;
|
||||
ImGuiWindow* ActiveIdPreviousFrameWindow;
|
||||
ImGuiDeactivatedItemData DeactivatedItemData;
|
||||
ImGuiDataTypeStorage ActiveIdValueOnActivation; // Backup of initial value at the time of activation. ONLY SET BY SPECIFIC WIDGETS: DragXXX and SliderXXX.
|
||||
ImGuiID LastActiveId; // Store the last non-zero ActiveId, useful for animation.
|
||||
float LastActiveIdTimer; // Store the last non-zero ActiveId timer since the beginning of activation, useful for animation.
|
||||
|
||||
|
||||
774
lib/third_party/imgui/imgui/source/imgui.cpp
vendored
774
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