Compare commits

..

20 Commits

Author SHA1 Message Date
WerWolv
a6cc4ca210 Set native compiler to gcc 2023-11-04 15:02:39 +01:00
WerWolv
b4f6c8d773 Try to get libromfs to build again 2023-11-04 14:57:26 +01:00
WerWolv
effe93ddd8 Try fix sysroot settings 2023-11-04 14:27:40 +01:00
WerWolv
84b4c14d35 Don't cancel workflows if one fails in matrix 2023-11-04 13:55:23 +01:00
WerWolv
911164b513 Try force setting OSX Arch 2023-11-04 13:50:05 +01:00
WerWolv
411214797b Add cross compiling message 2023-11-03 16:16:45 +01:00
WerWolv
5206a712fe Use toolchain file to cross compile 2023-11-03 16:15:16 +01:00
WerWolv
641949ecda Set native compiler 2023-11-03 16:01:54 +01:00
WerWolv
eadf9c1c2e Don't use -target anymore 2023-11-03 15:41:26 +01:00
WerWolv
ed37d56625 Remove minor version number from build target 2023-11-03 14:18:28 +01:00
WerWolv
64185a0d2f Fixed target again 2023-11-03 14:06:08 +01:00
WerWolv
aa72cd4d24 Only update brew packages on ARM 2023-11-03 14:00:01 +01:00
WerWolv
7dbf84f73a Fixed build target tripple 2023-11-03 13:23:43 +01:00
WerWolv
f077515a46 Upgrade to macOS 12 builds 2023-11-03 13:16:33 +01:00
WerWolv
bb43af3fc9 Back to standard llvm 2023-11-03 12:55:40 +01:00
WerWolv
94c0b663f6 Try to use pre-built version 2023-11-03 12:47:00 +01:00
WerWolv
cac656710e Try using llvm17 directly 2023-11-03 08:10:32 +01:00
WerWolv
df807896ea Try install latest llvm
.
2023-11-02 22:25:24 +01:00
WerWolv
31b63a11ce Try fixing build 2023-11-02 21:33:29 +01:00
WerWolv
211f775b9f git: Try cross-compiling 2023-11-02 20:49:11 +01:00
732 changed files with 150490 additions and 96331 deletions

View File

@@ -65,5 +65,4 @@ readability-*,
-readability-redundant-access-specifiers, -readability-redundant-access-specifiers,
-readability-function-cognitive-complexity, -readability-function-cognitive-complexity,
-readability-identifier-naming, -readability-identifier-naming,
*-include-cleaner,
-readability-qualified-auto' -readability-qualified-auto'

View File

@@ -1,5 +0,0 @@
cmake-build-*/
build*/
local/
**/Dockerfile

View File

@@ -7,10 +7,3 @@ skip -rfu ^ImGui::
# Trigger breakpoint when execution reaches triggerSafeShutdown() # Trigger breakpoint when execution reaches triggerSafeShutdown()
break triggerSafeShutdown break triggerSafeShutdown
# Print backtrace after execution jumped to an invalid address
define fixbt
set $pc = *(void **)$rsp
set $rsp = $rsp + 8
bt
end

3
.gitattributes vendored
View File

@@ -1,4 +1 @@
lib/external/** linguist-vendored lib/external/** linguist-vendored
dist/*.sh eol=lf
dist/**/*Dockerfile eol=lf

View File

@@ -16,7 +16,7 @@ jobs:
steps: steps:
- name: 🧰 Checkout - name: 🧰 Checkout
uses: actions/checkout@v4 uses: actions/checkout@v3
with: with:
submodules: recursive submodules: recursive
@@ -26,14 +26,14 @@ jobs:
languages: 'cpp' languages: 'cpp'
- name: 📜 Setup ccache - name: 📜 Setup ccache
uses: hendrikmuhs/ccache-action@v1 uses: hendrikmuhs/ccache-action@v1.2
with: with:
key: ${{ runner.os }}-analysis-build-${{ github.run_id }} key: ${{ runner.os }}-analysis-build-${{ github.run_id }}
restore-keys: ${{ runner.os }}-analysis-build restore-keys: ${{ runner.os }}-analysis-build
max-size: 50M max-size: 50M
- name: 📜 Restore CMakeCache - name: 📜 Restore CMakeCache
uses: actions/cache@v4 uses: actions/cache@v3
with: with:
path: | path: |
build/CMakeCache.txt build/CMakeCache.txt
@@ -46,7 +46,6 @@ jobs:
- name: 🛠️ Build - name: 🛠️ Build
run: | run: |
set -x
mkdir -p build mkdir -p build
cd build cd build
CC=gcc-12 CXX=g++-12 cmake \ CC=gcc-12 CXX=g++-12 cmake \

View File

@@ -2,9 +2,7 @@ name: Build
on: on:
push: push:
branches: branches: ["*"]
- 'master'
- 'releases/**'
pull_request: pull_request:
workflow_dispatch: workflow_dispatch:
@@ -24,61 +22,71 @@ jobs:
CCACHE_DIR: "${{ github.workspace }}/.ccache" CCACHE_DIR: "${{ github.workspace }}/.ccache"
steps: steps:
- name: 🧰 Checkout - name: 🧰 Checkout
uses: actions/checkout@v4 uses: actions/checkout@v3
with: with:
submodules: recursive submodules: recursive
- name: 📜 Setup ccache - name: 📜 Setup ccache
uses: hendrikmuhs/ccache-action@v1 uses: hendrikmuhs/ccache-action@v1.2
id: cache-ccache id: cache-ccache
with: with:
key: ${{ runner.os }}-ccache-${{ github.run_id }} key: ${{ runner.os }}-ccache-${{ github.run_id }}
restore-keys: ${{ runner.os }}-ccache restore-keys: ${{ runner.os }}-ccache
max-size: 1G max-size: 1G
- name: 📜 Restore CMakeCache
uses: actions/cache@v3
with:
path: |
build/CMakeCache.txt
key: ${{ runner.os }}-cmakecache-${{ hashFiles('**/CMakeLists.txt') }}
- name: 🟦 Install msys2 - name: 🟦 Install msys2
uses: msys2/setup-msys2@v2 uses: msys2/setup-msys2@v2
with: with:
msystem: mingw64 msystem: mingw64
pacboy: >-
- name: ⬇️ Install dependencies gcc:p
run: | lld:p
set -x cmake:p
dist/get_deps_msys2.sh ccache:p
glfw:p
file:p
mbedtls:p
freetype:p
dlfcn:p
libbacktrace:p
ninja:p
curl-winssl:p
capstone:p
- name: ⬇️ Install .NET - name: ⬇️ Install .NET
uses: actions/setup-dotnet@v4 uses: actions/setup-dotnet@v3
with: with:
dotnet-version: '8.0.100' dotnet-version: '7.0.x'
- name: 📜 Set version variable - name: 📜 Set version variable
run: | run: |
echo "IMHEX_VERSION=`cat VERSION`" >> $GITHUB_ENV echo "IMHEX_VERSION=`cat VERSION`" >> $GITHUB_ENV
# Windows cmake build # Windows cmake build
- name: 🛠️ Configure CMake - name: 🛠️ Build
run: | run: |
set -x
mkdir -p build mkdir -p build
cd build cd build
cmake -G "Ninja" \ cmake -G "Ninja" \
-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \ -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \
-DCMAKE_INSTALL_PREFIX="$PWD/install" \ -DCMAKE_INSTALL_PREFIX="$PWD/install" \
-DIMHEX_GENERATE_PACKAGE=ON \ -DCREATE_PACKAGE=ON \
-DIMHEX_USE_DEFAULT_BUILD_SETTINGS=ON \ -DIMHEX_USE_DEFAULT_BUILD_SETTINGS=ON \
-DIMHEX_PATTERNS_PULL_MASTER=ON \ -DIMHEX_PATTERNS_PULL_MASTER=ON \
-DIMHEX_COMMIT_HASH_LONG="${GITHUB_SHA}" \ -DIMHEX_COMMIT_HASH_SHORT="${GITHUB_SHA::7}" \
-DIMHEX_COMMIT_BRANCH="${GITHUB_REF##*/}" \ -DIMHEX_COMMIT_HASH_LONG="${GITHUB_SHA}" \
-DUSE_SYSTEM_CAPSTONE=ON \ -DIMHEX_COMMIT_BRANCH="${GITHUB_REF##*/}" \
-DIMHEX_GENERATE_PDBS=ON \ -DUSE_SYSTEM_CAPSTONE=ON \
-DIMHEX_REPLACE_DWARF_WITH_PDB=ON \
-DDOTNET_EXECUTABLE="C:/Program Files/dotnet/dotnet.exe" \ -DDOTNET_EXECUTABLE="C:/Program Files/dotnet/dotnet.exe" \
.. ..
- name: 🛠️ Build
run: |
cd build
ninja install ninja install
cpack cpack
mv ImHex-*.msi ../imhex-${{env.IMHEX_VERSION}}-Windows-x86_64.msi mv ImHex-*.msi ../imhex-${{env.IMHEX_VERSION}}-Windows-x86_64.msi
@@ -86,17 +94,15 @@ jobs:
echo "ImHex checks for the existence of this file to determine if it is running in portable mode. You should not delete this file" > $PWD/install/PORTABLE echo "ImHex checks for the existence of this file to determine if it is running in portable mode. You should not delete this file" > $PWD/install/PORTABLE
- name: ⬆️ Upload Windows Installer - name: ⬆️ Upload Windows Installer
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
if-no-files-found: error
name: Windows Installer x86_64 name: Windows Installer x86_64
path: | path: |
imhex-*.msi imhex-*.msi
- name: ⬆️ Upload Portable ZIP - name: ⬆️ Upload Portable ZIP
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
if-no-files-found: error
name: Windows Portable x86_64 name: Windows Portable x86_64
path: | path: |
build/install/* build/install/*
@@ -104,16 +110,14 @@ jobs:
- name: ⬇️ Download Mesa3D for NoGPU version - name: ⬇️ Download Mesa3D for NoGPU version
shell: bash shell: bash
run: | run: |
set -x
echo "NoGPU version Powered by Mesa 3D : https://fdossena.com/?p=mesa%2Findex.frag" > build/install/MESA.md echo "NoGPU version Powered by Mesa 3D : https://fdossena.com/?p=mesa%2Findex.frag" > build/install/MESA.md
curl https://werwolv.net/downloads/mesa/MesaForWindows-x64-latest.7z -L -o mesa.7z curl https://werwolv.net/downloads/mesa/MesaForWindows-x64-latest.7z -L -o mesa.7z
7z e mesa.7z 7z e mesa.7z
mv opengl32.dll build/install mv opengl32.dll build/install
- name: ⬆️ Upload NoGPU Portable ZIP - name: ⬆️ Upload NoGPU Portable ZIP
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
if-no-files-found: error
name: Windows Portable NoGPU x86_64 name: Windows Portable NoGPU x86_64
path: | path: |
build/install/* build/install/*
@@ -128,14 +132,22 @@ jobs:
include: include:
- suffix: "-NoGPU" - suffix: "-NoGPU"
custom_glfw: true custom_glfw: true
toolchain_file: ""
needs_update: true
- suffix: "" - suffix: ""
custom_glfw: false custom_glfw: false
toolchain_file: ""
needs_update: true
- suffix: "-ARM"
custom_glfw: false
toolchain_file: "dist/macOS/macos_arm_toolchain.cmake"
needs_update: true
name: 🍎 macOS 12.0${{matrix.suffix}} name: 🍎 macOS 11.0${{matrix.suffix}}
steps: steps:
- name: 🧰 Checkout - name: 🧰 Checkout
uses: actions/checkout@v4 uses: actions/checkout@v3
with: with:
submodules: recursive submodules: recursive
@@ -144,16 +156,26 @@ jobs:
echo "IMHEX_VERSION=`cat VERSION`" >> $GITHUB_ENV echo "IMHEX_VERSION=`cat VERSION`" >> $GITHUB_ENV
- name: 📜 Setup ccache - name: 📜 Setup ccache
uses: hendrikmuhs/ccache-action@v1 uses: hendrikmuhs/ccache-action@v1.2
with: with:
key: ${{ runner.os }}${{ matrix.suffix }}-ccache-${{ github.run_id }} key: ${{ runner.os }}${{ matrix.suffix }}-ccache-${{ github.run_id }}
restore-keys: ${{ runner.os }}${{ matrix.suffix }}-ccache restore-keys: ${{ runner.os }}${{ matrix.suffix }}-ccache
max-size: 1G max-size: 1G
- name: 📜 Restore CMakeCache
uses: actions/cache@v3
with:
path: |
build/CMakeCache.txt
key: ${{ runner.os }}-${{ matrix.suffix }}-cmakecache-${{ hashFiles('**/CMakeLists.txt') }}
- name: ⬇️ Update brew packages
if: ${{matrix.needs_update}}
run: |
brew update
- name: ⬇️ Install dependencies - name: ⬇️ Install dependencies
run: | run: |
set -x
brew reinstall python || brew link --overwrite python
brew bundle --no-lock --file dist/Brewfile brew bundle --no-lock --file dist/Brewfile
rm -rf /usr/local/Cellar/capstone rm -rf /usr/local/Cellar/capstone
@@ -163,13 +185,13 @@ jobs:
brew install glfw brew install glfw
- name: ⬇️ Install .NET - name: ⬇️ Install .NET
uses: actions/setup-dotnet@v4 uses: actions/setup-dotnet@v3
with: with:
dotnet-version: '8.0.100' dotnet-version: '7.0.x'
- name: 🧰 Checkout glfw - name: 🧰 Checkout glfw
if: ${{matrix.custom_glfw}} if: ${{matrix.custom_glfw}}
uses: actions/checkout@v4 uses: actions/checkout@v3
with: with:
repository: glfw/glfw repository: glfw/glfw
path: glfw path: glfw
@@ -178,7 +200,6 @@ jobs:
- name: ⬇️ Patch and install custom glfw - name: ⬇️ Patch and install custom glfw
if: ${{matrix.custom_glfw}} if: ${{matrix.custom_glfw}}
run: | run: |
set -x
cd glfw cd glfw
git apply ../dist/macOS/0001-glfw-SW.patch git apply ../dist/macOS/0001-glfw-SW.patch
@@ -196,160 +217,43 @@ jobs:
ninja install ninja install
# MacOS cmake build # MacOS cmake build
- name: 🛠️ Configure CMake - name: 🛠️ Build
run: | run: |
set -x
mkdir -p build mkdir -p build
cd build cd build
CC=$(brew --prefix gcc@12)/bin/gcc-12 \ CC=$(brew --prefix llvm)/bin/clang \
CXX=$(brew --prefix gcc@12)/bin/g++-12 \ CXX=$(brew --prefix llvm)/bin/clang++ \
OBJC=$(brew --prefix llvm)/bin/clang \ OBJC=$(brew --prefix llvm)/bin/clang \
OBJCXX=$(brew --prefix llvm)/bin/clang++ \ OBJCXX=$(brew --prefix llvm)/bin/clang++ \
PKG_CONFIG_PATH="$(brew --prefix openssl)/lib/pkgconfig":"$(brew --prefix)/lib/pkgconfig" \ PKG_CONFIG_PATH="$(brew --prefix openssl)/lib/pkgconfig":"$(brew --prefix)/lib/pkgconfig" \
cmake -G "Ninja" \ cmake -G "Ninja" \
-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \ -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \
-DIMHEX_GENERATE_PACKAGE=ON \ -DCMAKE_TOOLCHAIN_FILE="${{matrix.toolchain_file}}" \
-DCREATE_BUNDLE=ON \
-DCREATE_PACKAGE=ON \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \ -DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \ -DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
-DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \ -DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_INSTALL_PREFIX="./install" \ -DNATIVE_CMAKE_C_COMPILER="$(brew --prefix gcc@12)/bin/gcc-12" \
-DNATIVE_CMAKE_CXX_COMPILER="$(brew --prefix gcc@12)/bin/g++-12" \
-DIMHEX_PATTERNS_PULL_MASTER=ON \ -DIMHEX_PATTERNS_PULL_MASTER=ON \
-DIMHEX_COMMIT_HASH_SHORT="${GITHUB_SHA::7}" \
-DIMHEX_COMMIT_HASH_LONG="${GITHUB_SHA}" \ -DIMHEX_COMMIT_HASH_LONG="${GITHUB_SHA}" \
-DIMHEX_COMMIT_BRANCH="${GITHUB_REF##*/}" \ -DIMHEX_COMMIT_BRANCH="${GITHUB_REF##*/}" \
-DCPACK_PACKAGE_FILE_NAME="imhex-${{env.IMHEX_VERSION}}-macOS${{matrix.suffix}}-x86_64" \
.. ..
ninja package
- name: 🛠️ Build
run: cd build && ninja install
- name: ✒️ Fix Signature
run: |
set -x
cd build/install
mv imhex.app ImHex.app
codesign --remove-signature ImHex.app
codesign --force --deep --sign - ImHex.app
- name: 📁 Fix permissions
run: |
set -x
cd build/install
chmod -R 755 ImHex.app/
- name: 📦 Create DMG
run: |
set -x
mkdir bundle
mv build/install/ImHex.app bundle
cd bundle
ln -s /Applications Applications
cd ..
hdiutil create -volname "ImHex" -srcfolder bundle -ov -format UDZO imhex-${{env.IMHEX_VERSION}}-macOS${{matrix.suffix}}-x86_64.dmg
- name: ⬆️ Upload DMG - name: ⬆️ Upload DMG
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
if-no-files-found: error
name: macOS DMG${{matrix.suffix}} x86_64 name: macOS DMG${{matrix.suffix}} x86_64
path: ./*.dmg path: build/*.dmg
macos-arm64-build:
runs-on: ubuntu-22.04
name: 🍎 macOS 12.1 arm64
outputs:
IMHEX_VERSION: ${{ steps.build.outputs.IMHEX_VERSION }}
steps:
- name: 🧰 Checkout
uses: actions/checkout@v4
with:
submodules: recursive
- name: 📁 Restore docker /cache
uses: actions/cache@v4
with:
path: cache
key: build-macos-arm64-cache
- name: 🐳 Inject /cache into docker
uses: reproducible-containers/buildkit-cache-dance@v2
with:
cache-source: cache
cache-target: /cache
- name: 🛠️ Build using docker
id: build
run: |
echo "IMHEX_VERSION=`cat VERSION`" >> $GITHUB_OUTPUT
docker buildx build . -f dist/macOS/arm64.Dockerfile --progress=plain --build-arg 'JOBS=4' --build-arg "BUILD_TYPE=$(BUILD_TYPE)" --build-context imhex=$(pwd) --output out
- name: ⬆️ Upload artifacts
uses: actions/upload-artifact@v4
with:
name: macos_arm64_intermediate
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
gh actions-cache delete "build-macos-arm64-cache" --confirm || true
macos-arm64-package:
runs-on: macos-12
name: 🍎 macOS 12.1 arm64 Packaging
needs: macos-arm64-build
env:
IMHEX_VERSION: ${{ needs.macos-arm64-build.outputs.IMHEX_VERSION }}
steps:
- name: ⬇️ Download artifact
uses: actions/download-artifact@v4
with:
name: macos_arm64_intermediate
path: out
- name: 🗑️ Delete artifact
uses: geekyeggo/delete-artifact@v5
with:
name: macos_arm64_intermediate
- name: ✒️ Fix Signature
run: |
set -x
cd out
mv imhex.app ImHex.app
codesign --remove-signature ImHex.app
codesign --force --deep --sign - ImHex.app
- name: 📁 Fix permissions
run: |
set -x
cd out
chmod -R 755 ImHex.app/
- name: 📦 Create DMG
run: |
set -x
mkdir bundle
mv out/ImHex.app bundle
cd bundle
ln -s /Applications Applications
cd ..
hdiutil create -volname "ImHex" -srcfolder bundle -ov -format UDZO imhex-${{env.IMHEX_VERSION}}-macOS-arm64.dmg
- name: ⬆️ Upload DMG
uses: actions/upload-artifact@v4
with:
if-no-files-found: error
name: macOS DMG arm64
path: ./*.dmg
# Ubuntu build # Ubuntu build
ubuntu: ubuntu:
strategy: strategy:
fail-fast: false
matrix: matrix:
include: include:
- name: Ubuntu - name: Ubuntu
@@ -369,32 +273,43 @@ jobs:
run: apt update && apt install -y git curl run: apt update && apt install -y git curl
- name: 🧰 Checkout - name: 🧰 Checkout
uses: actions/checkout@v4 uses: actions/checkout@v3
with: with:
submodules: recursive submodules: recursive
- name: 📜 Setup ccache - name: 📜 Setup ccache
uses: hendrikmuhs/ccache-action@v1 uses: hendrikmuhs/ccache-action@v1.2
with: with:
key: Ubuntu-${{matrix.release_num}}-ccache-${{ github.run_id }} key: Ubuntu-${{matrix.release_num}}-ccache-${{ github.run_id }}
restore-keys: Ubuntu-${{matrix.release_num}}-ccache restore-keys: Ubuntu-${{matrix.release_num}}-ccache
max-size: 1G max-size: 1G
- name: 📜 Restore CMakeCache
uses: actions/cache@v3
with:
path: |
build/CMakeCache.txt
key: Ubuntu-${{matrix.release_num}}-cmakecache-${{ hashFiles('**/CMakeLists.txt') }}
- name: ⬇️ Install dependencies - name: ⬇️ Install dependencies
run: | run: |
apt update apt update
bash dist/get_deps_debian.sh bash dist/get_deps_debian.sh
- name: ⬇️ Install .NET - name: ⬇️ Install .NET
uses: actions/setup-dotnet@v4 uses: actions/setup-dotnet@v3
with: with:
dotnet-version: '8.0.100' dotnet-version: '7.0.x'
- name: 🏔️ Set Environment variables
run: |
echo COMMIT_SHA_SHORT=$(git rev-parse --short HEAD) >> $GITHUB_ENV
echo COMMIT_SHA_LONG=$(git rev-parse HEAD) >> $GITHUB_ENV
echo COMMIT_BRANCH=$(git rev-parse --abbrev-ref HEAD) >> $GITHUB_ENV
# Ubuntu cmake build # Ubuntu cmake build
- name: 🛠️ Configure CMake - name: 🛠️ Build
shell: bash
run: | run: |
set -x
git config --global --add safe.directory '*' git config --global --add safe.directory '*'
mkdir -p build mkdir -p build
cd build cd build
@@ -404,15 +319,14 @@ jobs:
-DCMAKE_C_COMPILER_LAUNCHER=ccache \ -DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DIMHEX_PATTERNS_PULL_MASTER=ON \ -DIMHEX_PATTERNS_PULL_MASTER=ON \
-DIMHEX_COMMIT_HASH_LONG="${GITHUB_SHA}" \ -DIMHEX_COMMIT_HASH_SHORT="${{ env.COMMIT_SHA_SHORT }}" \
-DIMHEX_COMMIT_BRANCH="${GITHUB_REF##*/}" \ -DIMHEX_COMMIT_HASH_LONG="${{ env.COMMIT_SHA_LONG }}" \
-DIMHEX_COMMIT_BRANCH="${{ env.COMMIT_BRANCH }}" \
-DIMHEX_ENABLE_LTO=ON \ -DIMHEX_ENABLE_LTO=ON \
-DIMHEX_USE_GTK_FILE_PICKER=ON \ -DIMHEX_USE_GTK_FILE_PICKER=ON \
-DDOTNET_EXECUTABLE="dotnet" \ -DDOTNET_EXECUTABLE="dotnet" \
.. ..
DESTDIR=DebDir ninja install
- name: 🛠️ Build
run: cd build && DESTDIR=DebDir ninja install
- name: 📜 Set version variable - name: 📜 Set version variable
run: | run: |
@@ -425,9 +339,8 @@ jobs:
mv build/DebDir.deb imhex-${{env.IMHEX_VERSION}}-Ubuntu-${{ matrix.release_num }}-x86_64.deb mv build/DebDir.deb imhex-${{env.IMHEX_VERSION}}-Ubuntu-${{ matrix.release_num }}-x86_64.deb
- name: ⬆️ Upload DEB - name: ⬆️ Upload DEB
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
if-no-files-found: error
name: Ubuntu ${{ matrix.release_num }} DEB x86_64 name: Ubuntu ${{ matrix.release_num }} DEB x86_64
path: '*.deb' path: '*.deb'
@@ -437,19 +350,19 @@ jobs:
name: ⬇️ AppImage name: ⬇️ AppImage
steps: steps:
- name: 🧰 Checkout - name: 🧰 Checkout
uses: actions/checkout@v4 uses: actions/checkout@v3
with: with:
submodules: recursive submodules: recursive
- name: 📁 Restore docker /cache - name: 📁 Restore docker /cache
uses: actions/cache@v4 uses: actions/cache@v3
with: with:
path: cache path: cache
key: appimage-ccache-${{ github.run_id }} key: appimage-ccache-${{ github.run_id }}
restore-keys: appimage-cache restore-keys: appimage-cache
- name: 🐳 Inject /cache into docker - name: 🐳 Inject /cache into docker
uses: reproducible-containers/buildkit-cache-dance@v2 uses: reproducible-containers/buildkit-cache-dance@v2.1.2
with: with:
cache-source: cache cache-source: cache
cache-target: /cache cache-target: /cache
@@ -461,16 +374,14 @@ jobs:
- name: ⬆️ Upload AppImage - name: ⬆️ Upload AppImage
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
if-no-files-found: error
name: Linux AppImage x86_64 name: Linux AppImage x86_64
path: 'out/*.AppImage' path: 'out/*.AppImage'
- name: ⬆️ Upload AppImage zsync - name: ⬆️ Upload AppImage zsync
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
if-no-files-found: error
name: Linux AppImage zsync x86_64 name: Linux AppImage zsync x86_64
path: 'out/*.AppImage.zsync' path: 'out/*.AppImage.zsync'
@@ -492,7 +403,7 @@ jobs:
pacman -Syu git ccache --noconfirm pacman -Syu git ccache --noconfirm
- name: 🧰 Checkout - name: 🧰 Checkout
uses: actions/checkout@v4 uses: actions/checkout@v3
with: with:
submodules: recursive submodules: recursive
@@ -501,21 +412,27 @@ jobs:
dist/get_deps_archlinux.sh --noconfirm dist/get_deps_archlinux.sh --noconfirm
- name: ⬇️ Install .NET - name: ⬇️ Install .NET
uses: actions/setup-dotnet@v4 uses: actions/setup-dotnet@v3
with: with:
dotnet-version: '8.0.100' dotnet-version: '7.0.x'
- name: 📜 Setup ccache - name: 📜 Setup ccache
uses: hendrikmuhs/ccache-action@v1 uses: hendrikmuhs/ccache-action@v1.2
with: with:
key: archlinux-ccache-${{ github.run_id }} key: archlinux-ccache-${{ github.run_id }}
restore-keys: archlinux-ccache restore-keys: archlinux-ccache
max-size: 1G max-size: 1G
- name: 📜 Restore CMakeCache
uses: actions/cache@v3
with:
path: |
build/CMakeCache.txt
key: archlinux-cmakecache-${{ hashFiles('**/CMakeLists.txt') }}
# ArchLinux cmake build # ArchLinux cmake build
- name: 🛠️ Configure CMake - name: 🛠️ Build
run: | run: |
set -x
mkdir -p build mkdir -p build
cd build cd build
CC=gcc CXX=g++ cmake -G "Ninja" \ CC=gcc CXX=g++ cmake -G "Ninja" \
@@ -528,14 +445,13 @@ jobs:
-DUSE_SYSTEM_NLOHMANN_JSON=ON \ -DUSE_SYSTEM_NLOHMANN_JSON=ON \
-DUSE_SYSTEM_CAPSTONE=OFF \ -DUSE_SYSTEM_CAPSTONE=OFF \
-DIMHEX_PATTERNS_PULL_MASTER=ON \ -DIMHEX_PATTERNS_PULL_MASTER=ON \
-DIMHEX_COMMIT_HASH_SHORT="${GITHUB_SHA::7}" \
-DIMHEX_COMMIT_HASH_LONG="${GITHUB_SHA}" \ -DIMHEX_COMMIT_HASH_LONG="${GITHUB_SHA}" \
-DIMHEX_COMMIT_BRANCH="${GITHUB_REF##*/}" \ -DIMHEX_COMMIT_BRANCH="${GITHUB_REF##*/}" \
-DIMHEX_ENABLE_LTO=ON \ -DIMHEX_ENABLE_LTO=ON \
-DIMHEX_USE_GTK_FILE_PICKER=ON \ -DIMHEX_USE_GTK_FILE_PICKER=ON \
.. ..
DESTDIR=installDir ninja install
- name: 🛠️ Build
run: cd build && DESTDIR=installDir ninja install
- name: 📜 Set version variable - name: 📜 Set version variable
run: | run: |
@@ -549,7 +465,6 @@ jobs:
# makepkg doesn't want to run as root, so I had to chmod 777 all over # makepkg doesn't want to run as root, so I had to chmod 777 all over
- name: 📦 Package ArchLinux .pkg.tar.zst - name: 📦 Package ArchLinux .pkg.tar.zst
run: | run: |
set -x
cd build cd build
# the name is a small trick to make makepkg recognize it as the source # the name is a small trick to make makepkg recognize it as the source
@@ -562,13 +477,11 @@ jobs:
# Replace the old file # Replace the old file
rm imhex-${{env.IMHEX_VERSION}}-ArchLinux-x86_64.pkg.tar.zst rm imhex-${{env.IMHEX_VERSION}}-ArchLinux-x86_64.pkg.tar.zst
rm *imhex-bin-debug* # rm debug package which is created for some reason
mv *.pkg.tar.zst imhex-${{env.IMHEX_VERSION}}-ArchLinux-x86_64.pkg.tar.zst mv *.pkg.tar.zst imhex-${{env.IMHEX_VERSION}}-ArchLinux-x86_64.pkg.tar.zst
- name: ⬆️ Upload imhex-archlinux.pkg.tar.zst - name: ⬆️ Upload imhex-archlinux.pkg.tar.zst
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
if-no-files-found: error
name: ArchLinux .pkg.tar.zst x86_64 name: ArchLinux .pkg.tar.zst x86_64
path: | path: |
build/imhex-${{env.IMHEX_VERSION}}-ArchLinux-x86_64.pkg.tar.zst build/imhex-${{env.IMHEX_VERSION}}-ArchLinux-x86_64.pkg.tar.zst
@@ -583,14 +496,14 @@ jobs:
mock_release: rawhide mock_release: rawhide
release_num: rawhide release_num: rawhide
mock_config: fedora-rawhide mock_config: fedora-rawhide
- name: Fedora
mock_release: f39
release_num: 39
mock_config: fedora-39
- name: Fedora - name: Fedora
mock_release: f38 mock_release: f38
release_num: 38 release_num: 38
mock_config: fedora-38 mock_config: fedora-38
- name: Fedora
mock_release: f37
release_num: 37
mock_config: fedora-37
- name: RHEL-AlmaLinux - name: RHEL-AlmaLinux
mock_release: epel9 mock_release: epel9
release_num: 9 release_num: 9
@@ -608,13 +521,13 @@ jobs:
run: dnf install --disablerepo="*" --enablerepo="fedora" git-core -y run: dnf install --disablerepo="*" --enablerepo="fedora" git-core -y
- name: 🧰 Checkout - name: 🧰 Checkout
uses: actions/checkout@v4 uses: actions/checkout@v3
with: with:
path: ImHex path: ImHex
submodules: recursive submodules: recursive
- name: 📜 Setup DNF Cache - name: 📜 Setup DNF Cache
uses: actions/cache@v4 uses: actions/cache@v3
with: with:
path: /var/cache/dnf path: /var/cache/dnf
key: ${{ matrix.mock_release }}-dnf-${{ github.run_id }} key: ${{ matrix.mock_release }}-dnf-${{ github.run_id }}
@@ -623,19 +536,18 @@ jobs:
- name: ⬇️ Update all packages and install dependencies - name: ⬇️ Update all packages and install dependencies
run: | run: |
set -x
dnf upgrade --disablerepo="*" --enablerepo="fedora,updates" -y dnf upgrade --disablerepo="*" --enablerepo="fedora,updates" -y
dnf install --disablerepo="*" --enablerepo="fedora,updates" -y \ dnf install --disablerepo="*" --enablerepo="fedora,updates" -y \
fedpkg \ fedpkg \
ccache ccache
- name: ⬇️ Install .NET - name: ⬇️ Install .NET
uses: actions/setup-dotnet@v4 uses: actions/setup-dotnet@v3
with: with:
dotnet-version: '8.0.100' dotnet-version: '7.0.x'
- name: 📜 Setup ccache - name: 📜 Setup ccache
uses: hendrikmuhs/ccache-action@v1 uses: hendrikmuhs/ccache-action@v1.2.5
with: with:
key: ${{ matrix.mock_release }}-rpm-${{ github.run_id }} key: ${{ matrix.mock_release }}-rpm-${{ github.run_id }}
restore-keys: ${{ matrix.mock_release }}-rpm restore-keys: ${{ matrix.mock_release }}-rpm
@@ -651,11 +563,11 @@ jobs:
- name: ✒️ Modify spec file - name: ✒️ Modify spec file
run: | run: |
sed -i \ sed -i \
-e 's/Version: VERSION$/Version: ${{env.IMHEX_VERSION}}/g' \ -e 's/Version: [0-9]*\.[0-9]*\.[0-9]*$/Version: ${{env.IMHEX_VERSION}}/g' \
-e 's/IMHEX_OFFLINE_BUILD=ON/IMHEX_OFFLINE_BUILD=OFF/g' \ -e 's/IMHEX_OFFLINE_BUILD=ON/IMHEX_OFFLINE_BUILD=OFF/g' \
-e '/IMHEX_OFFLINE_BUILD=OFF/a -D IMHEX_PATTERNS_PULL_MASTER=ON \\' \ -e '/IMHEX_OFFLINE_BUILD=OFF/a -D IMHEX_PATTERNS_PULL_MASTER=ON \\' \
-e '/BuildRequires: cmake/a BuildRequires: git-core' \ -e '/BuildRequires: cmake/a BuildRequires: git-core' \
-e '/%files/a %{_datadir}/%{name}/' \ -e '/%files/a %{_datadir}/%{name}/' \
$GITHUB_WORKSPACE/ImHex/dist/rpm/imhex.spec $GITHUB_WORKSPACE/ImHex/dist/rpm/imhex.spec
- name: 📜 Fix ccache on EL9 - name: 📜 Fix ccache on EL9
@@ -676,7 +588,7 @@ jobs:
EOT EOT
- name: 📜 Setup Mock Cache - name: 📜 Setup Mock Cache
uses: actions/cache@v4 uses: actions/cache@v3
with: with:
path: /var/cache/mock path: /var/cache/mock
key: ${{ matrix.mock_release }}-mock-${{ github.run_id }} key: ${{ matrix.mock_release }}-mock-${{ github.run_id }}
@@ -694,9 +606,8 @@ jobs:
$GITHUB_WORKSPACE/imhex-${{env.IMHEX_VERSION}}-${{matrix.name}}-${{matrix.release_num}}-x86_64.rpm $GITHUB_WORKSPACE/imhex-${{env.IMHEX_VERSION}}-${{matrix.name}}-${{matrix.release_num}}-x86_64.rpm
- name: ⬆️ Upload RPM - name: ⬆️ Upload RPM
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
if-no-files-found: error
name: ${{ matrix.name }} ${{ matrix.release_num }} RPM x86_64 name: ${{ matrix.name }} ${{ matrix.release_num }} RPM x86_64
path: | path: |
imhex-${{env.IMHEX_VERSION}}-${{matrix.name}}-${{matrix.release_num}}-x86_64.rpm imhex-${{env.IMHEX_VERSION}}-${{matrix.name}}-${{matrix.release_num}}-x86_64.rpm

View File

@@ -2,9 +2,7 @@ name: Build for the web
on: on:
push: push:
branches: branches: ["*"]
- 'master'
- 'releases/**'
pull_request: pull_request:
workflow_dispatch: workflow_dispatch:
@@ -23,29 +21,31 @@ jobs:
name: 🌍 WebAssembly name: 🌍 WebAssembly
steps: steps:
- name: 🧰 Checkout - name: 🧰 Checkout
uses: actions/checkout@v4 uses: actions/checkout@v3
with: with:
submodules: recursive submodules: recursive
- name: 📁 Restore docker /cache - name: 📁 Restore docker /cache
uses: actions/cache@v4 uses: actions/cache@v3
with: with:
path: cache path: cache
key: web-cmakecache-${{ hashFiles('**/CMakeLists.txt') }} key: build-web-cache
- name: 🐳 Inject /cache into docker - name: 🐳 Inject /cache into docker
uses: reproducible-containers/buildkit-cache-dance@v2 uses: reproducible-containers/buildkit-cache-dance@v2.1.2
with: with:
cache-source: cache cache-source: cache
cache-target: /cache cache-target: /cache
- name: 🛠️ Build using docker - name: 🛠️ Build using docker
run: | run: |
docker buildx build . -f dist/web/Dockerfile --progress=plain --build-arg 'JOBS=4' --output out --target raw docker buildx build . -f dist/web/Dockerfile --progress=plain --build-arg 'JOBS=4' --output out
- name: 🔨 Fix permissions - name: 🔨 Fix permissions
run: | run: |
chmod -c -R +rX "out/" chmod -c -R +rX "out/" | while read line; do
echo "::warning title=Invalid file permissions automatically fixed::$line"
done
- name: ⬆️ Upload artifacts - name: ⬆️ Upload artifacts
uses: actions/upload-pages-artifact@v2 uses: actions/upload-pages-artifact@v2

View File

@@ -15,13 +15,12 @@ jobs:
steps: steps:
- name: 🧰 Checkout - name: 🧰 Checkout
uses: actions/checkout@v4 uses: actions/checkout@v3
with: with:
path: ImHex path: ImHex
- name: 📜 Verify version and set version variable - name: 📜 Verify version and set version variable
run: | run: |
set -x
project_version=`cat ImHex/VERSION` project_version=`cat ImHex/VERSION`
tag_version="${{github.event.release.tag_name}}" tag_version="${{github.event.release.tag_name}}"
tag_version="${tag_version:1}" tag_version="${tag_version:1}"
@@ -52,30 +51,19 @@ jobs:
repo: ImHex-Patterns repo: ImHex-Patterns
token: ${{ secrets.RELEASE_TOKEN }} token: ${{ secrets.RELEASE_TOKEN }}
- name: 🎫 Create imhex-download-sdk release
uses: ncipollo/release-action@v1
env:
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
if: "${{ env.RELEASE_TOKEN != '' }}"
with:
tag: v${{ env.IMHEX_VERSION }}
repo: imhex-download-sdk
token: ${{ secrets.RELEASE_TOKEN }}
release-upload-artifacts: release-upload-artifacts:
runs-on: ubuntu-latest runs-on: ubuntu-latest
name: Release Upload Artifacts name: Release Upload Artifacts
steps: steps:
- name: 🧰 Checkout - name: 🧰 Checkout
uses: actions/checkout@v4 uses: actions/checkout@v3
with: with:
path: ImHex path: ImHex
submodules: recursive submodules: recursive
- name: 📜 Verify version and set version variable - name: 📜 Verify version and set version variable
run: | run: |
set -x
project_version=`cat ImHex/VERSION` project_version=`cat ImHex/VERSION`
tag_version="${{github.event.release.tag_name}}" tag_version="${{github.event.release.tag_name}}"
tag_version="${tag_version:1}" tag_version="${tag_version:1}"
@@ -90,7 +78,7 @@ jobs:
run: tar --exclude-vcs -czvf Full.Sources.tar.gz ImHex run: tar --exclude-vcs -czvf Full.Sources.tar.gz ImHex
- name: ⬇️ Download artifacts from latest workflow - name: ⬇️ Download artifacts from latest workflow
uses: dawidd6/action-download-artifact@v3 uses: dawidd6/action-download-artifact@v2
with: with:
github_token: ${{secrets.GITHUB_TOKEN}} github_token: ${{secrets.GITHUB_TOKEN}}
workflow: build.yml workflow: build.yml
@@ -100,7 +88,6 @@ jobs:
- name: 🗜️ Unzip files when needed - name: 🗜️ Unzip files when needed
run: | run: |
set -x
for zipfile in ./*.zip for zipfile in ./*.zip
do do
if [ `zipinfo -1 "$zipfile" | wc -l` -eq 1 ]; if [ `zipinfo -1 "$zipfile" | wc -l` -eq 1 ];
@@ -119,13 +106,12 @@ jobs:
mv "Windows Portable NoGPU x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-NoGPU-x86_64.zip mv "Windows Portable NoGPU x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-NoGPU-x86_64.zip
- name: ⬆️ Upload everything to release - name: ⬆️ Upload everything to release
uses: softprops/action-gh-release@4634c16e79c963813287e889244c50009e7f0981 uses: softprops/action-gh-release@v1
with: with:
files: '*' files: '*'
- name: ✒️ Prepare PKGBUILD - name: ✒️ Prepare PKGBUILD
run: | run: |
set -x
cp ImHex/dist/Arch/PKGBUILD . cp ImHex/dist/Arch/PKGBUILD .
hash=`md5sum imhex-${{ env.IMHEX_VERSION }}-ArchLinux-x86_64.pkg.tar.zst | cut -d ' ' -f 1` hash=`md5sum imhex-${{ env.IMHEX_VERSION }}-ArchLinux-x86_64.pkg.tar.zst | cut -d ' ' -f 1`

View File

@@ -2,13 +2,9 @@ name: "Unit Tests"
on: on:
push: push:
branches: branches: [ master ]
- 'master'
- 'releases/**'
pull_request: pull_request:
branches: branches: [ master ]
- 'master'
- 'releases/**'
workflow_dispatch: workflow_dispatch:
jobs: jobs:
@@ -22,12 +18,12 @@ jobs:
steps: steps:
- name: 🧰 Checkout - name: 🧰 Checkout
uses: actions/checkout@v4 uses: actions/checkout@v3
with: with:
submodules: recursive submodules: recursive
- name: 📜 Setup ccache - name: 📜 Setup ccache
uses: hendrikmuhs/ccache-action@v1 uses: hendrikmuhs/ccache-action@v1.2
with: with:
key: ${{ runner.os }}-tests-build-${{ github.run_id }} key: ${{ runner.os }}-tests-build-${{ github.run_id }}
restore-keys: ${{ runner.os }}-tests-build restore-keys: ${{ runner.os }}-tests-build
@@ -35,7 +31,7 @@ jobs:
- name: 📜 Restore CMakeCache - name: 📜 Restore CMakeCache
uses: actions/cache@v4 uses: actions/cache@v3
with: with:
path: | path: |
build/CMakeCache.txt build/CMakeCache.txt
@@ -48,12 +44,10 @@ jobs:
- name: 🛠️ Build - name: 🛠️ Build
run: | run: |
set -x
mkdir -p build mkdir -p build
cd build cd build
CC=gcc-12 CXX=g++-12 cmake \ CC=gcc-12 CXX=g++-12 cmake \
-DCMAKE_BUILD_TYPE=Debug \ -DCMAKE_BUILD_TYPE=Debug \
-DIMHEX_ENABLE_UNIT_TESTS=ON \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \ -DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_C_FLAGS="-fuse-ld=lld -fsanitize=address,leak,undefined -fno-sanitize-recover=all" \ -DCMAKE_C_FLAGS="-fuse-ld=lld -fsanitize=address,leak,undefined -fno-sanitize-recover=all" \
@@ -66,17 +60,3 @@ jobs:
run: | run: |
cd build cd build
ctest --output-on-failure ctest --output-on-failure
langs:
name: 🧪 Langs
runs-on: ubuntu-22.04
steps:
- name: 🧰 Checkout
uses: actions/checkout@v4
with:
submodules: recursive
- name: Check langs
run:
python3 tests/check_langs.py

2
.gitignore vendored
View File

@@ -3,11 +3,9 @@
cmake-build-*/ cmake-build-*/
build*/ build*/
local/
venv/ venv/
*.mgc *.mgc
imgui.ini imgui.ini
.DS_Store .DS_Store
./CMakeUserPresets.json ./CMakeUserPresets.json
Brewfile.lock.json

32
.gitmodules vendored
View File

@@ -1,25 +1,25 @@
[submodule "lib/third_party/nativefiledialog"] [submodule "lib/external/nativefiledialog"]
path = lib/third_party/nativefiledialog path = lib/external/nativefiledialog
url = https://github.com/btzy/nativefiledialog-extended url = https://github.com/btzy/nativefiledialog-extended
ignore = dirty ignore = dirty
[submodule "lib/third_party/yara/yara"] [submodule "lib/external/yara/yara"]
path = lib/third_party/yara/yara path = lib/external/yara/yara
url = https://github.com/VirusTotal/yara url = https://github.com/VirusTotal/yara
ignore = dirty ignore = dirty
[submodule "lib/third_party/xdgpp"] [submodule "lib/external/xdgpp"]
path = lib/third_party/xdgpp path = lib/external/xdgpp
url = https://github.com/WerWolv/xdgpp url = https://git.sr.ht/~danyspin97/xdgpp
ignore = dirty ignore = dirty
[submodule "lib/third_party/fmt"] [submodule "lib/external/fmt"]
path = lib/third_party/fmt path = lib/external/fmt
url = https://github.com/fmtlib/fmt url = https://github.com/fmtlib/fmt
ignore = dirty ignore = dirty
[submodule "lib/third_party/capstone"] [submodule "lib/external/capstone"]
path = lib/third_party/capstone path = lib/external/capstone
url = https://github.com/capstone-engine/capstone url = https://github.com/capstone-engine/capstone
ignore = dirty ignore = dirty
[submodule "lib/third_party/jthread/jthread"] [submodule "lib/external/jthread/jthread"]
path = lib/third_party/jthread/jthread path = lib/external/jthread/jthread
url = https://github.com/josuttis/jthread url = https://github.com/josuttis/jthread
ignore = dirty ignore = dirty
@@ -33,9 +33,3 @@
path = lib/external/libwolv path = lib/external/libwolv
url = https://github.com/WerWolv/libwolv url = https://github.com/WerWolv/libwolv
[submodule "lib/third_party/HashLibPlus"]
path = lib/third_party/HashLibPlus
url = https://github.com/WerWolv/HashLibPlus
[submodule "lib/third_party/edlib"]
path = lib/third_party/edlib
url = https://github.com/Martinsos/edlib

View File

@@ -1,31 +1,24 @@
cmake_minimum_required(VERSION 3.20) cmake_minimum_required(VERSION 3.20)
# Options # Options
option(IMHEX_PLUGINS_IN_SHARE "Put the plugins in share/imhex/plugins instead of lib[..]/imhex/plugins (Linux only)" OFF) option(IMHEX_PLUGINS_IN_SHARE "Put the plugins in share/imhex/plugins instead of lib[..]/imhex/plugins" OFF)
option(IMHEX_STRIP_RELEASE "Strip the release builds" ON ) option(IMHEX_STRIP_RELEASE "Strip the release builds" ON)
option(IMHEX_OFFLINE_BUILD "Enable offline build" OFF) option(IMHEX_OFFLINE_BUILD "Enable offline build" OFF)
option(IMHEX_IGNORE_BAD_CLONE "Disable the bad clone prevention checks" OFF) option(IMHEX_IGNORE_BAD_CLONE "Disable the bad clone prevention checks" OFF)
option(IMHEX_PATTERNS_PULL_MASTER "Download latest files from master branch of the ImHex-Patterns repo" OFF) option(IMHEX_PATTERNS_PULL_MASTER "Download latest files from master branch of the ImHex-Patterns repo" OFF)
option(IMHEX_IGNORE_BAD_COMPILER "Allow compiling with an unsupported compiler" OFF) option(IMHEX_IGNORE_BAD_COMPILER "Allow compiling with an unsupported compiler" OFF)
option(IMHEX_USE_GTK_FILE_PICKER "Use GTK file picker instead of xdg-desktop-portals (Linux only)" OFF) option(IMHEX_USE_GTK_FILE_PICKER "Use GTK file picker instead of xdg-desktop-portals" OFF)
option(IMHEX_DISABLE_STACKTRACE "Disables support for printing stack traces" OFF) option(IMHEX_DISABLE_STACKTRACE "Disables support for printing stack traces" OFF)
option(IMHEX_BUNDLE_DOTNET "Bundle .NET runtime" ON ) option(IMHEX_BUNDLE_DOTNET "Bundle .NET runtime" ON)
option(IMHEX_ENABLE_LTO "Enables Link Time Optimizations if possible" OFF) option(IMHEX_ENABLE_LTO "Enables Link Time Optimizations if possible" OFF)
option(IMHEX_USE_DEFAULT_BUILD_SETTINGS "Use default build settings" OFF) option(IMHEX_USE_DEFAULT_BUILD_SETTINGS "Use default build settings" OFF)
option(IMHEX_STRICT_WARNINGS "Enable most available warnings and treat them as errors" ON ) option(IMHEX_STRICT_WARNINGS "Enable most available warnings and treat them as errors" ON)
option(IMHEX_STATIC_LINK_PLUGINS "Statically link all plugins into the main executable" OFF) option(IMHEX_STATIC_LINK_PLUGINS "Statically link all plugins into the main executable" OFF)
option(IMHEX_GENERATE_PACKAGE "Specify if a native package should be built. (Windows and MacOS only)" OFF)
option(IMHEX_ENABLE_UNITY_BUILD "Enables building ImHex as a unity build." OFF)
option(IMHEX_GENERATE_PDBS "Enable generating PDB files in non-debug builds (Windows only)" OFF)
option(IMHEX_REPLACE_DWARF_WITH_PDB "Remove DWARF information from binaries when generating PDBS (Windows only)" OFF)
option(IMHEX_ENABLE_STD_ASSERTS "Enable debug asserts in the C++ std library. (Breaks Plugin ABI!)" OFF)
option(IMHEX_ENABLE_UNIT_TESTS "Enable building unit tests" OFF)
option(IMHEX_ENABLE_PRECOMPILED_HEADERS "Enable precompiled headers" OFF)
# Basic compiler and cmake configurations # Basic compiler and cmake configurations
set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD 23)
set(CMAKE_INCLUDE_DIRECTORIES_BEFORE ON) set(CMAKE_INCLUDE_DIRECTORIES_BEFORE ON)
set(IMHEX_BASE_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}") set(IMHEX_BASE_FOLDER ${CMAKE_CURRENT_SOURCE_DIR})
set(CMAKE_MODULE_PATH "${IMHEX_BASE_FOLDER}/cmake/modules") set(CMAKE_MODULE_PATH "${IMHEX_BASE_FOLDER}/cmake/modules")
include("${IMHEX_BASE_FOLDER}/cmake/build_helpers.cmake") include("${IMHEX_BASE_FOLDER}/cmake/build_helpers.cmake")
@@ -34,44 +27,41 @@ loadVersion(IMHEX_VERSION)
setVariableInParent(IMHEX_VERSION ${IMHEX_VERSION}) setVariableInParent(IMHEX_VERSION ${IMHEX_VERSION})
configureCMake() configureCMake()
project(imhex project(imhex
LANGUAGES C CXX LANGUAGES C CXX VERSION ${IMHEX_VERSION}
VERSION ${IMHEX_VERSION} DESCRIPTION "The ImHex Hex Editor"
DESCRIPTION "The ImHex Hex Editor" HOMEPAGE_URL "https://imhex.werwolv.net"
HOMEPAGE_URL "https://imhex.werwolv.net"
) )
# Add ImHex sources
add_custom_target(imhex_all ALL)
# Make sure project is configured correctly # Make sure project is configured correctly
setDefaultBuiltTypeIfUnset() setDefaultBuiltTypeIfUnset()
detectBadClone() detectBadClone()
verifyCompiler() verifyCompiler()
detectBundledPlugins() # List plugin names here. Project name must match folder name
set(PLUGINS
builtin
windows
script_loader
)
# Add various defines # Add various defines
detectOS() detectOS()
detectArch()
addDefines() addDefines()
# Configure packaging and install targets
configurePackingResources() configurePackingResources()
setUninstallTarget() setUninstallTarget()
addBundledLibraries() addBundledLibraries()
# Add ImHex sources
add_custom_target(imhex_all ALL)
add_subdirectory(lib/libimhex) add_subdirectory(lib/libimhex)
add_subdirectory(main) add_subdirectory(main)
addPluginDirectories()
# Add unit tests # Add unit tests
if (IMHEX_ENABLE_UNIT_TESTS) enable_testing()
enable_testing() add_subdirectory(tests EXCLUDE_FROM_ALL)
add_subdirectory(tests EXCLUDE_FROM_ALL)
endif ()
# Configure more resources that will be added to the install package # Configure packaging
generatePDBs()
generateSDKDirectory()
# Handle package generation
createPackage() createPackage()
generatePDBs()

345
README.md
View File

@@ -10,19 +10,33 @@
<p align="center">A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.</p> <p align="center">A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.</p>
<p align="center"> <p align="center">
<a title="'Build' workflow Status" href="https://github.com/WerWolv/ImHex/actions?query=workflow%3ABuild"><img alt="'Build' workflow Status" src="https://img.shields.io/github/actions/workflow/status/WerWolv/ImHex/build.yml?longCache=true&style=for-the-badge&label=Build&logoColor=fff&logo=GitHub%20Actions&branch=master"></a> <a title="'Build' workflow Status" href="https://github.com/WerWolv/ImHex/actions?query=workflow%3ABuild">
<a title="Discord Server" href="https://discord.gg/X63jZ36xBY"><img alt="Discord Server" src="https://img.shields.io/discord/789833418631675954?label=Discord&logo=Discord&logoColor=fff&style=for-the-badge"></a> <img alt="'Build' workflow Status" src="https://img.shields.io/github/actions/workflow/status/WerWolv/ImHex/build.yml?longCache=true&style=for-the-badge&label=Build&logoColor=fff&logo=GitHub%20Actions&branch=master">
<a title="Total Downloads" href="https://github.com/WerWolv/ImHex/releases/latest"><img alt="Total Downloads" src="https://img.shields.io/github/downloads/WerWolv/ImHex/total?longCache=true&style=for-the-badge&label=Downloads&logoColor=fff&logo=GitHub"></a> </a>
<a title="Code Quality" href="https://www.codefactor.io/repository/github/werwolv/imhex"><img alt="Code Quality" src="https://img.shields.io/codefactor/grade/github/WerWolv/ImHex?longCache=true&style=for-the-badge&label=Code%20Quality&logoColor=fff&logo=CodeFactor&branch=master"></a> <a title="Discord Server" href="https://discord.gg/X63jZ36xBY">
<a title="Translation" href="https://weblate.werwolv.net/projects/imhex/"><img alt="Translation" src="https://img.shields.io/weblate/progress/imhex?logo=weblate&logoColor=%23FFFFFF&server=https%3A%2F%2Fweblate.werwolv.net&style=for-the-badge"></a> <img alt="Discord Server" src="https://img.shields.io/discord/789833418631675954?label=Discord&logo=Discord&logoColor=fff&style=for-the-badge">
<a title="Plugins" href="https://github.com/WerWolv/ImHex/blob/master/PLUGINS.md"><img alt="Plugins" src="https://img.shields.io/badge/Plugins-Supported-brightgreen?logo=stackedit&logoColor=%23FFFFFF&style=for-the-badge"></a> </a>
<a title="Total Downloads" href="https://github.com/WerWolv/ImHex/releases/latest">
<img alt="Total Downloads" src="https://img.shields.io/github/downloads/WerWolv/ImHex/total?longCache=true&style=for-the-badge&label=Downloads&logoColor=fff&logo=GitHub">
</a>
<a title="Code Quality" href="https://www.codefactor.io/repository/github/werwolv/imhex">
<img alt="Code Quality" src="https://img.shields.io/codefactor/grade/github/WerWolv/ImHex?longCache=true&style=for-the-badge&label=Code%20Quality&logoColor=fff&logo=CodeFactor&branch=master">
</a>
<a title="Translation" href="https://weblate.werwolv.net/projects/imhex/">
<img alt="Translation" src="https://img.shields.io/weblate/progress/imhex?logo=weblate&logoColor=%23FFFFFF&server=https%3A%2F%2Fweblate.werwolv.net&style=for-the-badge">
</a>
<a title="Documentation" href="https://imhex.werwolv.net/docs">
<img alt="Documentation" src="https://img.shields.io/badge/Docs-Available-brightgreen?logo=gitbook&logoColor=%23FFFFFF&style=for-the-badge">
</a>
<a title="Plugins" href="https://github.com/WerWolv/ImHex/blob/master/PLUGINS.md">
<img alt="Plugins" src="https://img.shields.io/badge/Plugins-Supported-brightgreen?logo=stackedit&logoColor=%23FFFFFF&style=for-the-badge">
</a>
</p> </p>
<p align="center"> <p align="center">
<a title="Download the latest version of ImHex" href="https://imhex.download"><img alt="Download the latest version of ImHex!" src="resources/dist/common/get_release_banner.png"></a> <a title="Use the Web version of ImHex right in your browser!" href="https://web.imhex.werwolv.net">
<a title="Download the latest nightly pre-release version of ImHex" href="https://imhex.download/#nightly"><img alt="Download the latest nightly pre-release version of ImHex" src="resources/dist/common/get_nightly_banner.png"></a> <img alt="Use the Web version of ImHex right in your browser!" src="resources/dist/common/try_online_banner.png">
<a title="Use the Web version of ImHex right in your browser!" href="https://web.imhex.werwolv.net"><img alt="Use the Web version of ImHex right in your browser!" src="resources/dist/common/try_online_banner.png"></a> </a>
<a title="Read the documentation of ImHex!" href="https://docs.werwolv.net"><img alt="Read the documentation of ImHex!" src="resources/dist/common/read_docs_banner.png"></a>
</p> </p>
## Supporting ## Supporting
@@ -30,265 +44,93 @@
If you like my work, please consider supporting me on GitHub Sponsors, Patreon or PayPal. Thanks a lot! If you like my work, please consider supporting me on GitHub Sponsors, Patreon or PayPal. Thanks a lot!
<p align="center"> <p align="center">
<a href="https://github.com/sponsors/WerWolv"><img src="https://werwolv.net/assets/github_banner.png" alt="GitHub donate button" /></a> <a href="https://github.com/sponsors/WerWolv"><img src="https://werwolv.net/assets/github_banner.png" alt="GitHub donate button" /> </a>
<a href="https://www.patreon.com/werwolv"><img src="https://c5.patreon.com/external/logo/become_a_patron_button.png" alt="Patreon donate button" /></a> <a href="https://www.patreon.com/werwolv"><img src="https://c5.patreon.com/external/logo/become_a_patron_button.png" alt="Patreon donate button" /> </a>
<a href="https://werwolv.net/donate"><img src="https://werwolv.net/assets/paypal_banner.png" alt="PayPal donate button" /></a> <a href="https://werwolv.net/donate"><img src="https://werwolv.net/assets/paypal_banner.png" alt="PayPal donate button" /> </a>
</p> </p>
## Screenshots ## Screenshots
![Hex editor, patterns and data information](https://github.com/WerWolv/ImHex/assets/10835354/4f358238-2d27-41aa-9015-a2c6cc3708cf)
![Bookmarks, disassembler and data processor](https://github.com/WerWolv/ImHex/assets/10835354/183bc2cc-2439-4ded-b4c5-b140e19fc92f)
<details> ![Hex editor, patterns and data information](https://user-images.githubusercontent.com/10835354/139717326-8044769d-527b-4d88-8adf-2d4ecafdca1f.png)
<summary><strong>More Screenshots</strong></summary> ![Bookmarks, disassembler and data processor](https://user-images.githubusercontent.com/10835354/139717323-1f8c9d52-f7eb-4f43-9f11-097ac728ed6c.png)
![Data Processor decrypting some data and displaying it as an image](https://github.com/WerWolv/ImHex/assets/10835354/d0623081-3094-4840-a8a8-647b38724db8)
![STL Parser written in the Pattern Language visualizing a 3D model](https://github.com/WerWolv/ImHex/assets/10835354/62cbcd18-1c3f-4dd6-a877-2bf2bf4bb2a5)
![Data Information view displaying various stats about the file](https://github.com/WerWolv/ImHex/assets/10835354/d4706c01-c258-45c9-80b8-fe7a10d5a1de)
</details>
## Features ## Features
<details> - Featureful hex view
<summary><strong>Featureful hex view</strong></summary>
- Byte patching - Byte patching
- Patch management - Patch management
- Infinite Undo/Redo - Copy bytes as feature
- "Copy bytes as..."
- Bytes - Bytes
- Hex string - Hex string
- C, C++, C#, Rust, Python, Java & JavaScript array - C, C++, C#, Rust, Python, Java & JavaScript array
- ASCII-Art hex view - ASCII-Art hex view
- HTML self-contained div - HTML self-contained div
- Simple string and hex search - String and hex search
- Goto from start, end and current cursor position
- Colorful highlighting - Colorful highlighting
- Configurable foreground highlighting rules - Goto from start, end and current cursor position
- Background highlighting using patterns, find results and bookmarks - Custom C++-like pattern language for parsing highlighting a file's content
- Displaying data as a list of many different types - Automatic loading based on MIME type
- Hexadecimal integers (8, 16, 32, 64 bit) - arrays, pointers, structs, unions, enums, bitfields, namespaces, little and big endian support, conditionals and much more!
- Signed and unsigned decimal integers (8, 16, 32, 64 bit)
- Floats (16, 32, 64 bit)
- RGBA8 Colors
- HexII
- Binary
- Decoding data as ASCII and custom encodings
- Built-in support for UTF-8, UTF-16, ShiftJIS, most Windows encodings and many more
- Paged data view
</details>
<details>
<summary><strong>Custom C++-like pattern language for parsing highlighting a file's content</strong></summary>
- Automatic loading based on MIME types and magic values
- Arrays, pointers, structs, unions, enums, bitfields, namespaces, little and big endian support, conditionals and much more!
- Useful error messages, syntax highlighting and error marking - Useful error messages, syntax highlighting and error marking
- Support for visualizing many different types of data - Doesn't burn out your retinas when used in late-night sessions
- Images - Dark mode by default, but a light mode is available as well
- Audio - Data importing
- 3D Models
- Coordinates
- Time stamps
</details>
<details>
<summary><strong>Theming support</strong></summary>
- Doesn't burn out your retinas when used in late-night sessions
- Dark mode by default, but a light mode is available as well
- Customizable colors and styles for all UI elements through shareable theme files
- Support for custom fonts
</details>
<details>
<summary><strong>Importing and Exporting data</strong></summary>
- Base64 files - Base64 files
- IPS and IPS32 patches - IPS and IPS32 patches
- Markdown reports - Data exporting
</details> - IPS and IPS32 patches
<details> - Data inspector allowing interpretation of data as many different types (little and big endian)
<summary><strong>Data Inspector</strong></summary> - Huge file support with fast and efficient loading
- String search
- Interpreting data as many different types with endianess, decimal, hexadecimal and octal support and bit inversion - Copying of strings
- Unsigned and signed integers (8, 16, 24, 32, 48, 64 bit) - Copying of demangled strings
- Floats (16, 32, 64 bit) - File hashing support
- Signed and Unsigned LEB128 - CRC16 and CRC32 with custom initial values and polynomials
- ASCII, Wide and UTF-8 characters and strings - MD4, MD5
- time32_t, time64_t, DOS date and time - SHA-1, SHA-224, SHA-256, SHA-384, SHA-512
- GUIDs - Disassembler supporting many architectures (frontend for Capstone)
- RGBA8 and RGB65 Colors - ARM32 (ARM, Thumb, Cortex-M, AArch32)
- Copying and modifying bytes through the inspector - ARM64
- Adding new data types through the pattern language - MIPS (MIPS32, MIPS64, MIPS32R6, Micro)
- Support for hiding rows that aren't used - x86 (16-bit, 32-bit, 64-bit)
</details> - PowerPC (32-bit, 64-bit)
<details> - SPARC
<summary><strong>Node-based data pre-processor</strong></summary> - IBM SystemZ
- xCORE
- Modify, decrypt and decode data before it's being displayed in the hex editor - M68K
- Modify data without touching the underlying source - TMS320C64X
- Support for adding custom nodes - M680X
</details> - Ethereum
<details> - RISC-V
<summary><strong>Loading data from many different data sources</strong></summary> - WebAssembly
- MOS65XX
- Local Files - Berkeley Packet Filter
- Support for huge files with fast and efficient loading - Bookmarks
- Raw Disks - Region highlighting
- Loading data from raw disks and partitions - Comments
- GDB Server - Data Analyzer
- Access the RAM of a running process or embedded devices through GDB
- Intel Hex and Motorola SREC data
- Process Memory
- Inspect the entire address space of a running process
</details>
<details>
<summary><strong>Data searching</strong></summary>
- Support for searching the entire file or only a selection
- String extraction
- Option to specify minimum length and character set (lower case, upper case, digits, symbols)
- Option to specify encoding (ASCII, UTF-8, UTF-16 big and little endian)
- Sequence search
- Search for a sequence of bytes or characters
- Option to ignore character case
- Regex search
- Search for strings using regular expressions
- Binary Pattern
- Search for sequences of bytes with optional wildcards
- Numeric Value search
- Search for signed/unsigned integers and floats
- Search for ranges of values
- Option to specify size and endianess
- Option to ignore unaligned values
</details>
<details>
<summary><strong>Data hashing support</strong></summary>
- Many different algorithms available
- CRC8, CRC16 and CRC32 with custom initial values and polynomials
- Many default polynomials available
- MD5
- SHA-1, SHA-224, SHA-256, SHA-384, SHA-512
- Adler32
- AP
- BKDR
- Bernstein, Bernstein1
- DEK, DJB, ELF, FNV1, FNV1a, JS, PJW, RS, SDBM
- OneAtTime, Rotating, ShiftAndXor, SuperFast
- Murmur2_32, MurmurHash3_x86_32, MurmurHash3_x86_128, MurmurHash3_x64_128
- SipHash64, SipHash128
- XXHash32, XXHash64
- Tiger, Tiger2
- Blake2B, Blake2S
- Hashing of specific regions of the loaded data
- Hashing of arbitrary strings
</details>
<details>
<summary><strong>Diffing support</strong></summary>
- Compare data of different data sources
- Difference highlighting
- Table view of differences
</details>
<details>
<summary><strong>Integrated disassembler</strong></summary>
- Support for all architectures supported by Capstone
- ARM32 (ARM, Thumb, Cortex-M, AArch32)
- ARM64
- MIPS (MIPS32, MIPS64, MIPS32R6, Micro)
- x86 (16-bit, 32-bit, 64-bit)
- PowerPC (32-bit, 64-bit)
- SPARC
- IBM SystemZ
- xCORE
- M68K
- TMS320C64X
- M680X
- Ethereum
- RISC-V
- WebAssembly
- MOS65XX
- Berkeley Packet Filter
</details>
<details>
<summary><strong>Bookmarks</strong></summary>
- Support for bookmarks with custom names and colors
- Highlighting of bookmarked region in the hex editor
- Jump to bookmarks
- Open content of bookmark in a new tab
- Add comments to bookmarks
</details>
<details>
<summary><strong>Featureful data analyzer and visualizer</strong></summary>
- File magic-based file parser and MIME type database - File magic-based file parser and MIME type database
- Byte type distribution graph - Byte distribution graph
- Entropy graph - Entropy graph
- Highest and average entropy - Highest and average entropy
- Encrypted / Compressed file detection - Encrypted / Compressed file detection
- Digram and Layered distribution graphs - Built-in Content Store
</details> - Download all files found in the database directly from within ImHex
<details> - Yara Rules support
<summary><strong>YARA Rule support</strong></summary> - Quickly scan a file for vulnerabilities with official yara rules
- Helpful tools
- Scan a file for vulnerabilities with official yara rules - Itanium and MSVC demangler
- Highlight matches in the hex editor
- Jump to matches
- Apply multiple rules at once
</details>
<details>
<summary><strong>Helpful tools</strong></summary>
- Itanium, MSVC, Rust and D-Lang demangler based on LLVM
- ASCII table - ASCII table
- Regex replacer - Regex replacer
- Mathematical expression evaluator (Calculator) - Mathematical expression evaluator (Calculator)
- Graphing calculator - Hexadecimal Color picker
- Hexadecimal Color picker with support for many different formats
- Base converter - Base converter
- Byte swapper
- UNIX Permissions calculator - UNIX Permissions calculator
- Wikipedia term definition finder - Wikipedia term definition finder
- File utilities - File utilities
- File splitter - File splitter
- File combiner - File combiner
- File shredder - File shredder
- IEEE754 Float visualizer
- Division by invariant multiplication calculator
- TCP Client/Server
- Euclidean algorithm calculator
</details>
<details>
<summary><strong>Built-in Content updater</strong></summary>
- Download all files found in the database directly from within ImHex
- Pattern files for decoding various file formats
- Libraries for the pattern language
- Magic files for file type detection
- Custom data processor nodes
- Custom encodings
- Custom themes
- Yara rules
</details>
<details>
<summary><strong>Modern Interface</strong></summary>
- Support for multiple workspaces
- Support for custom layouts
- Detachable windows
</details>
<details>
<summary><strong>Easy to get started</strong></summary>
- Support for many different languages
- Simplified mode for beginners
- Extensive documentation
- Many example files available on [the Database](https://github.com/WerWolv/ImHex-Patterns)
- Achievements guiding you through the features of ImHex
- Interactive tutorials
</details>
## Pattern Language ## Pattern Language
@@ -306,13 +148,7 @@ For format patterns, libraries, magic and constant files, check out the [ImHex-P
## Requirements ## Requirements
To use ImHex, the following minimal system requirements need to be met. To use ImHex, the following minimal system requirements need to be met:
> [!IMPORTANT]
> ImHex requires a GPU with OpenGL 3.0 support in general.
> There are releases available (with the `-NoGPU` suffix) that are software rendered and don't require a GPU, however these can be a lot slower than the GPU accelerated versions.
>
> If possible at all, make ImHex use the dedicated GPU on your system instead of the integrated one (especially Intel HD GPUs are known to cause issues).
- **OS**: - **OS**:
- **Windows**: Windows 7 or higher (Windows 10/11 recommended) - **Windows**: Windows 7 or higher (Windows 10/11 recommended)
@@ -339,9 +175,8 @@ To compile ImHex on any platform, GCC (or Clang) is required with a version that
On macOS, Clang is also required to compile some ObjC code. On macOS, Clang is also required to compile some ObjC code.
All releases are being built using latest available GCC. All releases are being built using latest available GCC.
> [!NOTE] Many dependencies are bundled into the repository using submodules so make sure to clone it using the `--recurse-submodules` option.
> Many dependencies are bundled into the repository using submodules so make sure to clone it using the `--recurse-submodules` option. All dependencies that aren't bundled, can be installed using the dependency installer scripts found in the `/dist` folder.
> All dependencies that aren't bundled, can be installed using the dependency installer scripts found in the `/dist` folder.
For more information, check out the [Compiling](/dist/compiling) guide. For more information, check out the [Compiling](/dist/compiling) guide.
@@ -350,8 +185,9 @@ See [Contributing](/CONTRIBUTING.md)
## Plugin development ## Plugin development
To develop plugins for ImHex, use the following template project to get started. You then have access to the entirety of libimhex as well as the ImHex API and the Content Registry to interact with ImHex or to add new content. To develop plugins for ImHex, use one of the following two templates projects to get started. You then have access to the entirety of libimhex as well as the ImHex API and the Content Registry to interact with ImHex or to add new content.
- [ImHex Plugin Template](https://github.com/WerWolv/ImHex-Plugin-Template) - [C++ Plugin Template](https://github.com/WerWolv/ImHex-Cpp-Plugin-Template)
- [Rust Plugin Template](https://github.com/WerWolv/ImHex-Rust-Plugin-Template)
## Credits ## Credits
@@ -362,7 +198,7 @@ To develop plugins for ImHex, use the following template project to get started.
- [Roblabla](https://github.com/Roblabla) for adding MSI Installer support to ImHex - [Roblabla](https://github.com/Roblabla) for adding MSI Installer support to ImHex
- [jam1garner](https://github.com/jam1garner) and [raytwo](https://github.com/raytwo) for their help with adding Rust support to plugins - [jam1garner](https://github.com/jam1garner) and [raytwo](https://github.com/raytwo) for their help with adding Rust support to plugins
- [Mailaender](https://github.com/Mailaender) for getting ImHex onto Flathub - [Mailaender](https://github.com/Mailaender) for getting ImHex onto Flathub
- [iTrooz](https://github.com/iTrooz) for many improvements and new features to Imhex - [iTrooz](https://github.com/iTrooz) for many improvements related to release packaging and the GitHub Action runners.
- Everybody else who has reported issues on Discord or GitHub that I had great conversations with :) - Everybody else who has reported issues on Discord or GitHub that I had great conversations with :)
### Dependencies ### Dependencies
@@ -377,12 +213,3 @@ To develop plugins for ImHex, use the following template project to get started.
- Thanks to btzy for [nativefiledialog-extended](https://github.com/btzy/nativefiledialog-extended) - Thanks to btzy for [nativefiledialog-extended](https://github.com/btzy/nativefiledialog-extended)
- Thanks to danyspin97 for [xdgpp](https://sr.ht/~danyspin97/xdgpp) - Thanks to danyspin97 for [xdgpp](https://sr.ht/~danyspin97/xdgpp)
- Thanks to all other groups and organizations whose libraries are used in ImHex - Thanks to all other groups and organizations whose libraries are used in ImHex
### License
The biggest part of ImHex is under the GPLv2-only license.
Notable exceptions to this are the following parts which are under the LGPLv2.1 license:
- **/lib/libimhex**: The library that allows Plugins to interact with ImHex.
- **/plugins/ui**: The UI plugin library that contains some common UI elements that can be used by other plugins
The reason for this is to allow for proprietary plugins to be developed for ImHex.

View File

@@ -7,4 +7,4 @@ If you built ImHex yourself and experience issues that are not present in the ve
## Reporting a Vulnerability ## Reporting a Vulnerability
Any critical vulnerabilities can be reported through Discord (@werwolv). Any critical vulnerabilities can be reported through Discord @WerWolv#1337

View File

@@ -1 +1 @@
1.33.0 1.31.0

View File

@@ -22,7 +22,7 @@ macro(addDefines)
add_compile_definitions(NDEBUG) add_compile_definitions(NDEBUG)
elseif (CMAKE_BUILD_TYPE STREQUAL "Debug") elseif (CMAKE_BUILD_TYPE STREQUAL "Debug")
set(IMHEX_VERSION_STRING ${IMHEX_VERSION_STRING}-Debug) set(IMHEX_VERSION_STRING ${IMHEX_VERSION_STRING}-Debug)
add_compile_definitions(DEBUG) add_compile_definitions(DEBUG _GLIBCXX_DEBUG _GLIBCXX_VERBOSE)
elseif (CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") elseif (CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
set(IMHEX_VERSION_STRING ${IMHEX_VERSION_STRING}) set(IMHEX_VERSION_STRING ${IMHEX_VERSION_STRING})
add_compile_definitions(NDEBUG) add_compile_definitions(NDEBUG)
@@ -31,10 +31,6 @@ macro(addDefines)
add_compile_definitions(NDEBUG) add_compile_definitions(NDEBUG)
endif () endif ()
if (IMHEX_ENABLE_STD_ASSERTS)
add_compile_definitions(_GLIBCXX_DEBUG _GLIBCXX_VERBOSE)
endif()
if (IMHEX_STATIC_LINK_PLUGINS) if (IMHEX_STATIC_LINK_PLUGINS)
add_compile_definitions(IMHEX_STATIC_LINK_PLUGINS) add_compile_definitions(IMHEX_STATIC_LINK_PLUGINS)
endif () endif ()
@@ -46,9 +42,6 @@ function(addDefineToSource SOURCE DEFINE)
APPEND APPEND
PROPERTY COMPILE_DEFINITIONS "${DEFINE}" PROPERTY COMPILE_DEFINITIONS "${DEFINE}"
) )
# Disable precompiled headers for this file
set_source_files_properties(${SOURCE} PROPERTIES SKIP_PRECOMPILE_HEADERS ON)
endfunction() endfunction()
# Detect current OS / System # Detect current OS / System
@@ -58,7 +51,6 @@ macro(detectOS)
set(CMAKE_INSTALL_BINDIR ".") set(CMAKE_INSTALL_BINDIR ".")
set(CMAKE_INSTALL_LIBDIR ".") set(CMAKE_INSTALL_LIBDIR ".")
set(PLUGINS_INSTALL_LOCATION "plugins") set(PLUGINS_INSTALL_LOCATION "plugins")
add_compile_definitions(WIN32_LEAN_AND_MEAN)
elseif (APPLE) elseif (APPLE)
add_compile_definitions(OS_MACOS) add_compile_definitions(OS_MACOS)
set(CMAKE_INSTALL_BINDIR ".") set(CMAKE_INSTALL_BINDIR ".")
@@ -70,19 +62,14 @@ macro(detectOS)
add_compile_definitions(OS_WEB) add_compile_definitions(OS_WEB)
elseif (UNIX AND NOT APPLE) elseif (UNIX AND NOT APPLE)
add_compile_definitions(OS_LINUX) add_compile_definitions(OS_LINUX)
if (BSD AND BSD STREQUAL "FreeBSD")
add_compile_definitions(OS_FREEBSD)
endif()
include(GNUInstallDirs) include(GNUInstallDirs)
if(IMHEX_PLUGINS_IN_SHARE) if(IMHEX_PLUGINS_IN_SHARE)
set(PLUGINS_INSTALL_LOCATION "share/imhex/plugins") set(PLUGINS_INSTALL_LOCATION "share/imhex/plugins")
else() else()
set(PLUGINS_INSTALL_LOCATION "${CMAKE_INSTALL_LIBDIR}/imhex/plugins") set(PLUGINS_INSTALL_LOCATION "${CMAKE_INSTALL_LIBDIR}/imhex/plugins")
# Warning : Do not work with portable versions such as appimage (because the path is hardcoded)
# Add System plugin location for plugins to be loaded from add_compile_definitions(SYSTEM_PLUGINS_LOCATION="${CMAKE_INSTALL_FULL_LIBDIR}/imhex") # "plugins" will be appended from the app
# IMPORTANT: This does not work for Sandboxed or portable builds such as the Flatpak or AppImage release
add_compile_definitions(SYSTEM_PLUGINS_LOCATION="${CMAKE_INSTALL_FULL_LIBDIR}/imhex")
endif() endif()
else () else ()
@@ -91,8 +78,24 @@ macro(detectOS)
endmacro() endmacro()
# Detect 32 vs. 64 bit system
macro(detectArch)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
add_compile_definitions(ARCH_64_BIT)
elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
add_compile_definitions(ARCH_32_BIT)
endif()
endmacro()
macro(configurePackingResources) macro(configurePackingResources)
set(LIBRARY_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) set(IMHEX_FORCE_LINK_PLUGINS "")
option (CREATE_PACKAGE "Create a package with CPack" OFF)
if (APPLE)
option (CREATE_BUNDLE "Create a bundle on macOS" OFF)
endif()
if (WIN32) if (WIN32)
if (NOT (CMAKE_BUILD_TYPE STREQUAL "Debug")) if (NOT (CMAKE_BUILD_TYPE STREQUAL "Debug"))
@@ -101,7 +104,7 @@ macro(configurePackingResources)
set(IMHEX_ICON "${IMHEX_BASE_FOLDER}/resources/resource.rc") set(IMHEX_ICON "${IMHEX_BASE_FOLDER}/resources/resource.rc")
if (IMHEX_GENERATE_PACKAGE) if (CREATE_PACKAGE)
set(CPACK_GENERATOR "WIX") set(CPACK_GENERATOR "WIX")
set(CPACK_PACKAGE_NAME "ImHex") set(CPACK_PACKAGE_NAME "ImHex")
set(CPACK_PACKAGE_VENDOR "WerWolv") set(CPACK_PACKAGE_VENDOR "WerWolv")
@@ -113,14 +116,13 @@ macro(configurePackingResources)
set(CPACK_PACKAGE_INSTALL_DIRECTORY "ImHex") set(CPACK_PACKAGE_INSTALL_DIRECTORY "ImHex")
set_property(INSTALL "$<TARGET_FILE_NAME:main>" set_property(INSTALL "$<TARGET_FILE_NAME:main>"
PROPERTY CPACK_START_MENU_SHORTCUTS "ImHex" PROPERTY CPACK_START_MENU_SHORTCUTS "ImHex"
) )
set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/resources/dist/windows/LICENSE.rtf") set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/resources/dist/windows/LICENSE.rtf")
endif() endif()
elseif (APPLE OR ${CMAKE_HOST_SYSTEM_NAME} MATCHES "Darwin") elseif (APPLE)
set(IMHEX_ICON "${IMHEX_BASE_FOLDER}/resources/dist/macos/AppIcon.icns") set (IMHEX_ICON "${IMHEX_BASE_FOLDER}/resources/dist/macos/AppIcon.icns")
set(BUNDLE_NAME "imhex.app")
if (IMHEX_GENERATE_PACKAGE) if (CREATE_BUNDLE)
set(APPLICATION_TYPE MACOSX_BUNDLE) set(APPLICATION_TYPE MACOSX_BUNDLE)
set_source_files_properties(${IMHEX_ICON} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources") set_source_files_properties(${IMHEX_ICON} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
set(MACOSX_BUNDLE_ICON_FILE "AppIcon.icns") set(MACOSX_BUNDLE_ICON_FILE "AppIcon.icns")
@@ -129,16 +131,15 @@ macro(configurePackingResources)
set(MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/resources/dist/macos/Info.plist.in") set(MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/resources/dist/macos/Info.plist.in")
set(MACOSX_BUNDLE_BUNDLE_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") set(MACOSX_BUNDLE_BUNDLE_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
set(MACOSX_BUNDLE_GUI_IDENTIFIER "net.WerWolv.ImHex") set(MACOSX_BUNDLE_GUI_IDENTIFIER "net.WerWolv.ImHex")
string(SUBSTRING "${IMHEX_COMMIT_HASH_LONG}" 0 7 COMMIT_HASH_SHORT) set(MACOSX_BUNDLE_LONG_VERSION_STRING "${PROJECT_VERSION}-${IMHEX_COMMIT_HASH_SHORT}")
set(MACOSX_BUNDLE_LONG_VERSION_STRING "${PROJECT_VERSION}-${COMMIT_HASH_SHORT}")
set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}") set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
string(TIMESTAMP CURR_YEAR "%Y") string(TIMESTAMP CURR_YEAR "%Y")
set(MACOSX_BUNDLE_COPYRIGHT "Copyright © 2020 - ${CURR_YEAR} WerWolv. All rights reserved." ) set(MACOSX_BUNDLE_COPYRIGHT "Copyright © 2020 - ${CURR_YEAR} WerWolv. All rights reserved." )
if ("${CMAKE_GENERATOR}" STREQUAL "Xcode") if ("${CMAKE_GENERATOR}" STREQUAL "Xcode")
set (IMHEX_BUNDLE_PATH "${CMAKE_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${BUNDLE_NAME}") set (IMHEX_BUNDLE_PATH "${CMAKE_BINARY_DIR}/${CMAKE_BUILD_TYPE}/ImHex.app")
else () else ()
set (IMHEX_BUNDLE_PATH "${CMAKE_BINARY_DIR}/${BUNDLE_NAME}") set (IMHEX_BUNDLE_PATH "${CMAKE_BINARY_DIR}/ImHex.app")
endif() endif()
set(PLUGINS_INSTALL_LOCATION "${IMHEX_BUNDLE_PATH}/Contents/MacOS/plugins") set(PLUGINS_INSTALL_LOCATION "${IMHEX_BUNDLE_PATH}/Contents/MacOS/plugins")
@@ -147,55 +148,54 @@ macro(configurePackingResources)
endif() endif()
endmacro() endmacro()
macro(addPluginDirectories) macro(createPackage)
set(LIBRARY_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
file(MAKE_DIRECTORY "plugins") file(MAKE_DIRECTORY "plugins")
foreach (plugin IN LISTS PLUGINS) foreach (plugin IN LISTS PLUGINS)
add_subdirectory("plugins/${plugin}") add_subdirectory("plugins/${plugin}")
if (TARGET ${plugin}) if (TARGET ${plugin})
get_target_property(IS_RUST_PROJECT ${plugin} RUST_PROJECT)
set_target_properties(${plugin} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins) set_target_properties(${plugin} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins)
set_target_properties(${plugin} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins) set_target_properties(${plugin} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins)
if (APPLE) if (IS_RUST_PROJECT)
if (IMHEX_GENERATE_PACKAGE) set_target_properties(${plugin} PROPERTIES CARGO_BUILD_TARGET_DIR ${CMAKE_BINARY_DIR}/plugins)
set_target_properties(${plugin} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PLUGINS_INSTALL_LOCATION})
else () get_target_property(PLUGIN_LOCATION ${plugin} LOCATION)
set_target_properties(${plugin} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins)
endif () install(FILES "${PLUGIN_LOCATION}/../${plugin}.hexplug" DESTINATION "${PLUGINS_INSTALL_LOCATION}" PERMISSIONS ${LIBRARY_PERMISSIONS})
else () else ()
if (WIN32) if (WIN32)
get_target_property(target_type ${plugin} TYPE) install(TARGETS ${plugin} RUNTIME DESTINATION ${PLUGINS_INSTALL_LOCATION})
if (target_type STREQUAL "SHARED_LIBRARY") elseif (APPLE)
install(TARGETS ${plugin} RUNTIME DESTINATION ${PLUGINS_INSTALL_LOCATION}) if (CREATE_BUNDLE)
set_target_properties(${plugin} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PLUGINS_INSTALL_LOCATION})
else () else ()
install(TARGETS ${plugin} LIBRARY DESTINATION ${PLUGINS_INSTALL_LOCATION}) set_target_properties(${plugin} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins)
endif() endif ()
else() else ()
install(TARGETS ${plugin} LIBRARY DESTINATION ${PLUGINS_INSTALL_LOCATION}) install(TARGETS ${plugin} LIBRARY DESTINATION ${PLUGINS_INSTALL_LOCATION})
endif() endif ()
endif ()
endif()
add_dependencies(imhex_all ${plugin}) add_dependencies(imhex_all ${plugin})
endif () endif ()
endforeach() endforeach()
endmacro()
macro(createPackage) set_target_properties(libimhex PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
if (WIN32) if (WIN32)
# Install binaries directly in the prefix, usually C:\Program Files\ImHex. # Install binaries directly in the prefix, usually C:\Program Files\ImHex.
set(CMAKE_INSTALL_BINDIR ".") set(CMAKE_INSTALL_BINDIR ".")
set(PLUGIN_TARGET_FILES "")
foreach (plugin IN LISTS PLUGINS)
list(APPEND PLUGIN_TARGET_FILES "$<TARGET_FILE:${plugin}>")
endforeach ()
# Grab all dynamically linked dependencies. # Grab all dynamically linked dependencies.
install(CODE "set(CMAKE_INSTALL_BINDIR \"${CMAKE_INSTALL_BINDIR}\")") INSTALL(CODE "set(CMAKE_INSTALL_BINDIR \"${CMAKE_INSTALL_BINDIR}\")")
install(CODE "set(PLUGIN_TARGET_FILES \"${PLUGIN_TARGET_FILES}\")") INSTALL(CODE "LIST(APPEND DEP_FOLDERS \${PY_PARENT})")
install(CODE [[ install(CODE [[
file(GET_RUNTIME_DEPENDENCIES file(GET_RUNTIME_DEPENDENCIES
EXECUTABLES ${PLUGIN_TARGET_FILES} $<TARGET_FILE:libimhex> $<TARGET_FILE:main> EXECUTABLES $<TARGET_FILE:builtin> $<TARGET_FILE:libimhex> $<TARGET_FILE:main>
RESOLVED_DEPENDENCIES_VAR _r_deps RESOLVED_DEPENDENCIES_VAR _r_deps
UNRESOLVED_DEPENDENCIES_VAR _u_deps UNRESOLVED_DEPENDENCIES_VAR _u_deps
CONFLICTING_DEPENDENCIES_PREFIX _c_deps CONFLICTING_DEPENDENCIES_PREFIX _c_deps
@@ -217,6 +217,7 @@ macro(createPackage)
endforeach() endforeach()
]]) ]])
install(FILES "$<TARGET_FILE:libimhex>" DESTINATION "${CMAKE_INSTALL_LIBDIR}" PERMISSIONS ${LIBRARY_PERMISSIONS})
downloadImHexPatternsFiles("./") downloadImHexPatternsFiles("./")
elseif(UNIX AND NOT APPLE) elseif(UNIX AND NOT APPLE)
@@ -227,6 +228,7 @@ macro(createPackage)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE DESTINATION ${CMAKE_INSTALL_PREFIX}/share/licenses/imhex) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE DESTINATION ${CMAKE_INSTALL_PREFIX}/share/licenses/imhex)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/dist/imhex.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/dist/imhex.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/icon.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps RENAME imhex.png) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/icon.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps RENAME imhex.png)
install(FILES "$<TARGET_FILE:libimhex>" DESTINATION "${CMAKE_INSTALL_LIBDIR}" PERMISSIONS ${LIBRARY_PERMISSIONS})
downloadImHexPatternsFiles("./share/imhex") downloadImHexPatternsFiles("./share/imhex")
# install AppStream file # install AppStream file
@@ -238,56 +240,42 @@ macro(createPackage)
endif() endif()
if (APPLE) if (CREATE_BUNDLE)
if (IMHEX_GENERATE_PACKAGE) include(PostprocessBundle)
include(PostprocessBundle)
set_target_properties(libimhex PROPERTIES SOVERSION ${IMHEX_VERSION}) set_target_properties(libimhex PROPERTIES SOVERSION ${IMHEX_VERSION})
set_property(TARGET main PROPERTY MACOSX_BUNDLE_INFO_PLIST ${MACOSX_BUNDLE_INFO_PLIST}) set_property(TARGET main PROPERTY MACOSX_BUNDLE_INFO_PLIST ${MACOSX_BUNDLE_INFO_PLIST})
# Fix rpath # Fix rpath
install(CODE "execute_process(COMMAND ${CMAKE_INSTALL_NAME_TOOL} -add_rpath \"@executable_path/../Frameworks/\" $<TARGET_FILE:main>)") add_custom_command(TARGET imhex_all POST_BUILD COMMAND ${CMAKE_INSTALL_NAME_TOOL} -add_rpath "@executable_path/../Frameworks/" $<TARGET_FILE:main>)
add_custom_target(build-time-make-plugins-directory ALL COMMAND ${CMAKE_COMMAND} -E make_directory "${IMHEX_BUNDLE_PATH}/Contents/MacOS/plugins") # FIXME: Remove this once we move/integrate the plugins directory.
add_custom_target(build-time-make-resources-directory ALL COMMAND ${CMAKE_COMMAND} -E make_directory "${IMHEX_BUNDLE_PATH}/Contents/Resources") add_custom_target(build-time-make-plugins-directory ALL COMMAND ${CMAKE_COMMAND} -E make_directory "${IMHEX_BUNDLE_PATH}/Contents/MacOS/plugins")
add_custom_target(build-time-make-resources-directory ALL COMMAND ${CMAKE_COMMAND} -E make_directory "${IMHEX_BUNDLE_PATH}/Contents/Resources")
downloadImHexPatternsFiles("${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME}/Contents/MacOS") downloadImHexPatternsFiles("${IMHEX_BUNDLE_PATH}/Contents/MacOS")
install(FILES ${IMHEX_ICON} DESTINATION "${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME}/Contents/Resources") install(FILES ${IMHEX_ICON} DESTINATION "${IMHEX_BUNDLE_PATH}/Contents/Resources")
install(TARGETS main BUNDLE DESTINATION ".") install(TARGETS main BUNDLE DESTINATION ".")
install(FILES $<TARGET_FILE:main> DESTINATION "${IMHEX_BUNDLE_PATH}")
# Update library references to make the bundle portable # Update library references to make the bundle portable
postprocess_bundle(imhex_all main) postprocess_bundle(imhex_all main)
# Enforce DragNDrop packaging. # Enforce DragNDrop packaging.
set(CPACK_GENERATOR "DragNDrop") set(CPACK_GENERATOR "DragNDrop")
set(CPACK_BUNDLE_ICON "${CMAKE_SOURCE_DIR}/resources/dist/macos/AppIcon.icns")
set(CPACK_BUNDLE_PLIST "${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME}/Contents/Info.plist")
if (IMHEX_RESIGN_BUNDLE)
find_program(CODESIGN_PATH codesign)
if (CODESIGN_PATH)
install(CODE "message(STATUS \"Signing bundle '${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME}'...\")")
install(CODE "execute_process(COMMAND ${CODESIGN_PATH} --force --deep --sign - ${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME} COMMAND_ERROR_IS_FATAL ANY)")
endif()
endif()
install(CODE [[ message(STATUS "MacOS Bundle finalized. DO NOT TOUCH IT ANYMORE! ANY MODIFICATIONS WILL BREAK IT FROM NOW ON!") ]])
endif()
else() else()
install(TARGETS main RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) install(TARGETS main RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
if (TARGET updater) if(WIN32) # Forwarder is only needed on Windows
install(TARGETS updater RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
if (TARGET main-forwarder)
install(TARGETS main-forwarder BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR}) install(TARGETS main-forwarder BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR})
endif() endif()
endif() endif()
if (IMHEX_GENERATE_PACKAGE) if (CREATE_PACKAGE)
set(CPACK_BUNDLE_NAME "ImHex") set (CPACK_BUNDLE_NAME "ImHex")
set (CPACK_BUNDLE_ICON "${CMAKE_SOURCE_DIR}/resources/dist/macos/AppIcon.icns" )
set (CPACK_BUNDLE_PLIST "${CMAKE_BINARY_DIR}/ImHex.app/Contents/Info.plist")
include(CPack) include(CPack)
endif() endif()
@@ -309,7 +297,9 @@ macro(configureCMake)
# Enable C and C++ languages # Enable C and C++ languages
enable_language(C CXX) enable_language(C CXX)
set(CMAKE_POSITION_INDEPENDENT_CODE ON CACHE BOOL "Enable position independent code for all targets" FORCE) if (CMAKE_CROSSCOMPILING)
message(STATUS "ImHex is being Cross-Compiled for ${CMAKE_SYSTEM_NAME}!")
endif ()
# Configure use of recommended build tools # Configure use of recommended build tools
if (IMHEX_USE_DEFAULT_BUILD_SETTINGS) if (IMHEX_USE_DEFAULT_BUILD_SETTINGS)
@@ -372,10 +362,6 @@ macro(configureCMake)
# display a warning about options being set using set() instead of option(). # display a warning about options being set using set() instead of option().
# Explicitly set the policy to NEW to suppress the warning. # Explicitly set the policy to NEW to suppress the warning.
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
set(CMAKE_POLICY_DEFAULT_CMP0063 NEW)
set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "Disable deprecated warnings" FORCE)
endmacro() endmacro()
macro(setDefaultBuiltTypeIfUnset) macro(setDefaultBuiltTypeIfUnset)
@@ -398,7 +384,7 @@ function(detectBadClone)
return() return()
endif() endif()
file (GLOB EXTERNAL_DIRS "lib/external/*" "lib/third_party/*") file (GLOB EXTERNAL_DIRS "lib/external/*")
foreach (EXTERNAL_DIR ${EXTERNAL_DIRS}) foreach (EXTERNAL_DIR ${EXTERNAL_DIRS})
file(GLOB_RECURSE RESULT "${EXTERNAL_DIR}/*") file(GLOB_RECURSE RESULT "${EXTERNAL_DIR}/*")
list(LENGTH RESULT ENTRY_COUNT) list(LENGTH RESULT ENTRY_COUNT)
@@ -422,35 +408,6 @@ function(verifyCompiler)
endif() endif()
endfunction() endfunction()
macro(detectBundledPlugins)
file(GLOB PLUGINS_DIRS "plugins/*")
if (NOT DEFINED IMHEX_INCLUDE_PLUGINS)
foreach(PLUGIN_DIR ${PLUGINS_DIRS})
if (EXISTS "${PLUGIN_DIR}/CMakeLists.txt")
get_filename_component(PLUGIN_NAME ${PLUGIN_DIR} NAME)
if (NOT (${PLUGIN_NAME} IN_LIST IMHEX_EXCLUDE_PLUGINS))
list(APPEND PLUGINS ${PLUGIN_NAME})
endif ()
endif()
endforeach()
else()
set(PLUGINS ${IMHEX_INCLUDE_PLUGINS})
endif()
foreach(PLUGIN_NAME ${PLUGINS})
message(STATUS "Enabled bundled plugin '${PLUGIN_NAME}'")
endforeach()
if (NOT PLUGINS)
message(FATAL_ERROR "No bundled plugins enabled")
endif()
if (NOT ("builtin" IN_LIST PLUGINS))
message(FATAL_ERROR "The 'builtin' plugin is required for ImHex to work!")
endif ()
endmacro()
macro(setVariableInParent variable value) macro(setVariableInParent variable value)
get_directory_property(hasParent PARENT_DIRECTORY) get_directory_property(hasParent PARENT_DIRECTORY)
@@ -470,9 +427,9 @@ function(downloadImHexPatternsFiles dest)
endif () endif ()
FetchContent_Declare( FetchContent_Declare(
imhex_patterns imhex_patterns
GIT_REPOSITORY https://github.com/WerWolv/ImHex-Patterns.git GIT_REPOSITORY https://github.com/WerWolv/ImHex-Patterns.git
GIT_TAG origin/master GIT_TAG origin/master
) )
message(STATUS "Downloading ImHex-Patterns repo branch ${PATTERNS_BRANCH}...") message(STATUS "Downloading ImHex-Patterns repo branch ${PATTERNS_BRANCH}...")
@@ -485,7 +442,7 @@ function(downloadImHexPatternsFiles dest)
endif () endif ()
if (EXISTS ${imhex_patterns_SOURCE_DIR}) if (EXISTS ${imhex_patterns_SOURCE_DIR})
set(PATTERNS_FOLDERS_TO_INSTALL constants encodings includes patterns magic nodes) set(PATTERNS_FOLDERS_TO_INSTALL constants encodings includes patterns magic)
foreach (FOLDER ${PATTERNS_FOLDERS_TO_INSTALL}) foreach (FOLDER ${PATTERNS_FOLDERS_TO_INSTALL})
install(DIRECTORY "${imhex_patterns_SOURCE_DIR}/${FOLDER}" DESTINATION ${dest} PATTERN "**/_schema.json" EXCLUDE) install(DIRECTORY "${imhex_patterns_SOURCE_DIR}/${FOLDER}" DESTINATION ${dest} PATTERN "**/_schema.json" EXCLUDE)
endforeach () endforeach ()
@@ -495,41 +452,23 @@ endfunction()
macro(setupCompilerFlags target) macro(setupCompilerFlags target)
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
# Define strict compilation flags
if (IMHEX_STRICT_WARNINGS) if (IMHEX_STRICT_WARNINGS)
set(IMHEX_COMMON_FLAGS "${IMHEX_COMMON_FLAGS} -Wall -Wextra -Wpedantic -Werror") set(IMHEX_COMMON_FLAGS "-Wall -Wextra -Wpedantic -Werror")
endif()
if (UNIX AND NOT APPLE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU")
set(IMHEX_COMMON_FLAGS "${IMHEX_COMMON_FLAGS} -rdynamic")
endif() endif()
set(IMHEX_C_FLAGS "${IMHEX_COMMON_FLAGS} -Wno-array-bounds -Wno-deprecated-declarations")
set(IMHEX_CXX_FLAGS "-fexceptions -frtti") set(IMHEX_CXX_FLAGS "-fexceptions -frtti")
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
# Disable some warnings set(IMHEX_C_FLAGS "${IMHEX_C_FLAGS} -Wno-restrict -Wno-stringop-overread -Wno-stringop-overflow -Wno-dangling-reference")
set(IMHEX_C_CXX_FLAGS "-Wno-unknown-warning-option -Wno-array-bounds -Wno-deprecated-declarations -Wno-unknown-pragmas") endif()
endif() endif()
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
if (IMHEX_ENABLE_UNITY_BUILD AND WIN32)
set(IMHEX_COMMON_FLAGS "${IMHEX_COMMON_FLAGS} -Wa,-mbig-obj")
endif ()
endif()
# Disable some warnings for gcc
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
set(IMHEX_C_CXX_FLAGS "${IMHEX_C_CXX_FLAGS} -Wno-restrict -Wno-stringop-overread -Wno-stringop-overflow -Wno-dangling-reference")
endif()
# Define emscripten-specific disabled warnings
if (EMSCRIPTEN) if (EMSCRIPTEN)
set(IMHEX_C_CXX_FLAGS "${IMHEX_C_CXX_FLAGS} -pthread -Wno-dollar-in-identifier-extension -Wno-pthreads-mem-growth") set(IMHEX_C_FLAGS "${IMHEX_C_FLAGS} -pthread -Wno-dollar-in-identifier-extension -Wno-pthreads-mem-growth")
endif () endif ()
# Set actual CMake flags set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${IMHEX_C_FLAGS}")
set_target_properties(${target} PROPERTIES COMPILE_FLAGS "${IMHEX_COMMON_FLAGS} ${IMHEX_C_CXX_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${IMHEX_CXX_FLAGS} ${IMHEX_C_FLAGS}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${IMHEX_COMMON_FLAGS} ${IMHEX_C_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${IMHEX_COMMON_FLAGS} ${IMHEX_C_CXX_FLAGS} ${IMHEX_CXX_FLAGS}")
set(CMAKE_OBJC_FLAGS "${CMAKE_OBJC_FLAGS} ${IMHEX_COMMON_FLAGS}") set(CMAKE_OBJC_FLAGS "${CMAKE_OBJC_FLAGS} ${IMHEX_COMMON_FLAGS}")
endmacro() endmacro()
@@ -537,34 +476,46 @@ endmacro()
macro(setUninstallTarget) macro(setUninstallTarget)
if(NOT TARGET uninstall) if(NOT TARGET uninstall)
configure_file( configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
IMMEDIATE @ONLY) IMMEDIATE @ONLY)
add_custom_target(uninstall add_custom_target(uninstall
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
endif() endif()
endmacro() endmacro()
macro(addBundledLibraries) macro(addBundledLibraries)
set(EXTERNAL_LIBS_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}/lib/external") find_package(PkgConfig REQUIRED)
set(THIRD_PARTY_LIBS_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}/lib/third_party")
set(EXTERN_LIBS_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}/lib/external")
set(BUILD_SHARED_LIBS OFF) set(BUILD_SHARED_LIBS OFF)
add_subdirectory(${THIRD_PARTY_LIBS_FOLDER}/imgui) add_subdirectory(${EXTERN_LIBS_FOLDER}/imgui)
set_target_properties(imgui PROPERTIES POSITION_INDEPENDENT_CODE ON)
add_subdirectory(${THIRD_PARTY_LIBS_FOLDER}/microtar EXCLUDE_FROM_ALL) add_subdirectory(${EXTERN_LIBS_FOLDER}/microtar EXCLUDE_FROM_ALL)
set_target_properties(microtar PROPERTIES POSITION_INDEPENDENT_CODE ON)
add_subdirectory(${EXTERNAL_LIBS_FOLDER}/libwolv EXCLUDE_FROM_ALL) add_subdirectory(${EXTERN_LIBS_FOLDER}/libwolv EXCLUDE_FROM_ALL)
set_property(TARGET libwolv-types PROPERTY POSITION_INDEPENDENT_CODE ON)
set_property(TARGET libwolv-utils PROPERTY POSITION_INDEPENDENT_CODE ON)
set_property(TARGET libwolv-io PROPERTY POSITION_INDEPENDENT_CODE ON)
set_property(TARGET libwolv-hash PROPERTY POSITION_INDEPENDENT_CODE ON)
set_property(TARGET libwolv-containers PROPERTY POSITION_INDEPENDENT_CODE ON)
set_property(TARGET libwolv-net PROPERTY POSITION_INDEPENDENT_CODE ON)
set(XDGPP_INCLUDE_DIRS "${THIRD_PARTY_LIBS_FOLDER}/xdgpp") set(XDGPP_INCLUDE_DIRS "${EXTERN_LIBS_FOLDER}/xdgpp")
set(FPHSA_NAME_MISMATCHED ON CACHE BOOL "") set(FPHSA_NAME_MISMATCHED ON CACHE BOOL "")
find_package(PkgConfig REQUIRED)
if(NOT USE_SYSTEM_FMT) if(NOT USE_SYSTEM_FMT)
add_subdirectory(${THIRD_PARTY_LIBS_FOLDER}/fmt EXCLUDE_FROM_ALL) add_subdirectory(${EXTERN_LIBS_FOLDER}/fmt EXCLUDE_FROM_ALL)
set_target_properties(fmt PROPERTIES POSITION_INDEPENDENT_CODE ON)
set(FMT_LIBRARIES fmt::fmt-header-only) set(FMT_LIBRARIES fmt::fmt-header-only)
else() else()
find_package(fmt REQUIRED) find_package(fmt 8.0.0 REQUIRED)
set(FMT_LIBRARIES fmt::fmt) set(FMT_LIBRARIES fmt::fmt)
endif() endif()
@@ -576,11 +527,13 @@ macro(addBundledLibraries)
if (NOT EMSCRIPTEN) if (NOT EMSCRIPTEN)
# curl # curl
find_package(CURL REQUIRED) find_package(PkgConfig REQUIRED)
pkg_check_modules(LIBCURL REQUIRED IMPORTED_TARGET libcurl>=7.60.0)
# nfd # nfd
if (NOT USE_SYSTEM_NFD) if (NOT USE_SYSTEM_NFD)
add_subdirectory(${THIRD_PARTY_LIBS_FOLDER}/nativefiledialog EXCLUDE_FROM_ALL) add_subdirectory(${EXTERN_LIBS_FOLDER}/nativefiledialog EXCLUDE_FROM_ALL)
set_target_properties(nfd PROPERTIES POSITION_INDEPENDENT_CODE ON)
set(NFD_LIBRARIES nfd) set(NFD_LIBRARIES nfd)
else() else()
find_package(nfd) find_package(nfd)
@@ -589,7 +542,7 @@ macro(addBundledLibraries)
endif() endif()
if(NOT USE_SYSTEM_NLOHMANN_JSON) if(NOT USE_SYSTEM_NLOHMANN_JSON)
add_subdirectory(${THIRD_PARTY_LIBS_FOLDER}/nlohmann_json EXCLUDE_FROM_ALL) add_subdirectory(${EXTERN_LIBS_FOLDER}/nlohmann_json EXCLUDE_FROM_ALL)
set(NLOHMANN_JSON_LIBRARIES nlohmann_json) set(NLOHMANN_JSON_LIBRARIES nlohmann_json)
else() else()
find_package(nlohmann_json 3.10.2 REQUIRED) find_package(nlohmann_json 3.10.2 REQUIRED)
@@ -597,13 +550,32 @@ macro(addBundledLibraries)
endif() endif()
if (NOT USE_SYSTEM_LLVM) if (NOT USE_SYSTEM_LLVM)
add_subdirectory(${THIRD_PARTY_LIBS_FOLDER}/llvm-demangle EXCLUDE_FROM_ALL) add_subdirectory(${EXTERN_LIBS_FOLDER}/llvm-demangle EXCLUDE_FROM_ALL)
set_target_properties(LLVMDemangle PROPERTIES POSITION_INDEPENDENT_CODE ON)
else() else()
find_package(LLVM REQUIRED Demangle) find_package(LLVM REQUIRED Demangle)
endif() endif()
if (NOT USE_SYSTEM_YARA)
add_subdirectory(${EXTERN_LIBS_FOLDER}/yara EXCLUDE_FROM_ALL)
set_target_properties(libyara PROPERTIES POSITION_INDEPENDENT_CODE ON)
set(YARA_LIBRARIES libyara)
else()
find_package(PkgConfig REQUIRED)
pkg_check_modules(YARA REQUIRED IMPORTED_TARGET yara)
endif()
if (NOT USE_SYSTEM_MINIAUDIO)
add_subdirectory(${EXTERN_LIBS_FOLDER}/miniaudio EXCLUDE_FROM_ALL)
set_target_properties(miniaudio PROPERTIES POSITION_INDEPENDENT_CODE ON)
set(MINIAUDIO_LIBRARIES miniaudio)
else()
find_package(PkgConfig REQUIRED)
pkg_check_modules(miniaudio REQUIRED IMPORTED_TARGET miniaudio)
endif()
if (NOT USE_SYSTEM_JTHREAD) if (NOT USE_SYSTEM_JTHREAD)
add_subdirectory(${THIRD_PARTY_LIBS_FOLDER}/jthread EXCLUDE_FROM_ALL) add_subdirectory(${EXTERN_LIBS_FOLDER}/jthread EXCLUDE_FROM_ALL)
set(JTHREAD_LIBRARIES jthread) set(JTHREAD_LIBRARIES jthread)
else() else()
find_path(JOSUTTIS_JTHREAD_INCLUDE_DIRS "condition_variable_any2.hpp") find_path(JOSUTTIS_JTHREAD_INCLUDE_DIRS "condition_variable_any2.hpp")
@@ -614,40 +586,32 @@ macro(addBundledLibraries)
set(JTHREAD_LIBRARIES jthread) set(JTHREAD_LIBRARIES jthread)
endif() endif()
set(LIBPL_BUILD_CLI_AS_EXECUTABLE OFF CACHE BOOL "" FORCE) if (NOT USE_SYSTEM_CAPSTONE)
set(LIBPL_ENABLE_PRECOMPILED_HEADERS ${IMHEX_ENABLE_PRECOMPILED_HEADERS} CACHE BOOL "" FORCE) set(CAPSTONE_BUILD_STATIC_RUNTIME OFF CACHE BOOL "Disable shared library building")
set(CAPSTONE_BUILD_SHARED OFF CACHE BOOL "Disable shared library building")
if (WIN32) set(CAPSTONE_BUILD_TESTS OFF CACHE BOOL "Disable tests")
set(LIBPL_SHARED_LIBRARY ON CACHE BOOL "" FORCE) add_subdirectory(${EXTERN_LIBS_FOLDER}/capstone EXCLUDE_FROM_ALL)
set_target_properties(capstone PROPERTIES POSITION_INDEPENDENT_CODE ON)
target_compile_options(capstone PRIVATE -Wno-unused-function)
set(CAPSTONE_LIBRARIES "capstone")
set(CAPSTONE_INCLUDE_DIRS ${EXTERN_LIBS_FOLDER}/capstone/include)
else() else()
set(LIBPL_SHARED_LIBRARY OFF CACHE BOOL "" FORCE) find_package(PkgConfig REQUIRED)
pkg_search_module(CAPSTONE 4.0.2 REQUIRED capstone)
endif() endif()
add_subdirectory(${EXTERNAL_LIBS_FOLDER}/pattern_language EXCLUDE_FROM_ALL) set(LIBPL_BUILD_CLI_AS_EXECUTABLE OFF)
add_subdirectory(${EXTERN_LIBS_FOLDER}/pattern_language EXCLUDE_FROM_ALL)
if (LIBPL_SHARED_LIBRARY) set_target_properties(libpl PROPERTIES POSITION_INDEPENDENT_CODE ON)
install(
TARGETS
libpl
DESTINATION
"${CMAKE_INSTALL_LIBDIR}"
PERMISSIONS
OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
)
endif()
if (WIN32)
set_target_properties(
libpl
PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}
)
endif()
enableUnityBuild(libpl)
find_package(mbedTLS 3.4.0 REQUIRED) find_package(mbedTLS 3.4.0 REQUIRED)
find_package(Magic 5.39 REQUIRED)
pkg_search_module(MAGIC libmagic>=5.39)
if(NOT MAGIC_FOUND)
find_library(MAGIC 5.39 magic REQUIRED)
else()
set(MAGIC_INCLUDE_DIRS ${MAGIC_INCLUDEDIR})
endif()
if (NOT IMHEX_DISABLE_STACKTRACE) if (NOT IMHEX_DISABLE_STACKTRACE)
if (WIN32) if (WIN32)
@@ -658,33 +622,23 @@ macro(addBundledLibraries)
if (${Backtrace_FOUND}) if (${Backtrace_FOUND})
message(STATUS "Backtrace enabled! Header: ${Backtrace_HEADER}") message(STATUS "Backtrace enabled! Header: ${Backtrace_HEADER}")
if (Backtrace_HEADER STREQUAL "backtrace.h") if (Backtrace_HEADER STREQUAL "execinfo.h")
set(LIBBACKTRACE_LIBRARIES ${Backtrace_LIBRARY}) set(LIBBACKTRACE_LIBRARIES ${Backtrace_LIBRARY})
set(LIBBACKTRACE_INCLUDE_DIRS ${Backtrace_INCLUDE_DIR}) set(LIBBACKTRACE_INCLUDE_DIRS ${Backtrace_INCLUDE_DIR})
add_compile_definitions(BACKTRACE_HEADER=<${Backtrace_HEADER}>) add_compile_definitions(BACKTRACE_HEADER=\"${Backtrace_HEADER}\")
add_compile_definitions(HEX_HAS_BACKTRACE)
elseif (Backtrace_HEADER STREQUAL "execinfo.h")
set(LIBBACKTRACE_LIBRARIES ${Backtrace_LIBRARY})
set(LIBBACKTRACE_INCLUDE_DIRS ${Backtrace_INCLUDE_DIR})
add_compile_definitions(BACKTRACE_HEADER=<${Backtrace_HEADER}>)
add_compile_definitions(HEX_HAS_EXECINFO) add_compile_definitions(HEX_HAS_EXECINFO)
endif() elseif (Backtrace_HEADER STREQUAL "backtrace.h")
set(LIBBACKTRACE_LIBRARIES ${Backtrace_LIBRARY})
set(LIBBACKTRACE_INCLUDE_DIRS ${Backtrace_INCLUDE_DIR})
add_compile_definitions(BACKTRACE_HEADER=\"${Backtrace_HEADER}\")
add_compile_definitions(HEX_HAS_BACKTRACE)
endif ()
endif() endif()
endif() endif ()
endif() endif ()
endmacro() endmacro()
function(enableUnityBuild TARGET)
if (IMHEX_ENABLE_UNITY_BUILD)
set_target_properties(${TARGET} PROPERTIES UNITY_BUILD ON UNITY_BUILD_MODE BATCH)
endif ()
endfunction()
function(generatePDBs) function(generatePDBs)
if (NOT IMHEX_GENERATE_PDBS)
return()
endif ()
if (NOT WIN32 OR CMAKE_BUILD_TYPE STREQUAL "Debug") if (NOT WIN32 OR CMAKE_BUILD_TYPE STREQUAL "Debug")
return() return()
endif () endif ()
@@ -698,6 +652,7 @@ function(generatePDBs)
FetchContent_Populate(cv2pdb) FetchContent_Populate(cv2pdb)
set(PDBS_TO_GENERATE main main-forwarder libimhex ${PLUGINS}) set(PDBS_TO_GENERATE main main-forwarder libimhex ${PLUGINS})
add_custom_target(pdbs)
foreach (PDB ${PDBS_TO_GENERATE}) foreach (PDB ${PDBS_TO_GENERATE})
if (PDB STREQUAL "main") if (PDB STREQUAL "main")
set(GENERATED_PDB imhex) set(GENERATED_PDB imhex)
@@ -709,73 +664,26 @@ function(generatePDBs)
set(GENERATED_PDB plugins/${PDB}) set(GENERATED_PDB plugins/${PDB})
endif () 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 add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/${GENERATED_PDB}.pdb
WORKING_DIRECTORY ${CMAKE_BINARY_DIR} WORKING_DIRECTORY ${cv2pdb_SOURCE_DIR}
COMMAND COMMAND
( (${CMAKE_COMMAND} -E remove -f ${CMAKE_BINARY_DIR}/${GENERATED_PDB}.pdb &&
${CMAKE_COMMAND} -E remove -f ${CMAKE_BINARY_DIR}/${GENERATED_PDB}.pdb && ${cv2pdb_SOURCE_DIR}/cv2pdb64.exe
${cv2pdb_SOURCE_DIR}/cv2pdb64.exe $<TARGET_FILE:${PDB}> ${PDB_OUTPUT_PATH} && $<TARGET_FILE:${PDB}>) || (exit 0)
${CMAKE_COMMAND} -E remove -f ${CMAKE_BINARY_DIR}/${GENERATED_PDB} DEPENDS $<TARGET_FILE:${PDB}>
) || (exit 0)
COMMAND_EXPAND_LISTS) COMMAND_EXPAND_LISTS)
target_sources(imhex_all PRIVATE ${CMAKE_BINARY_DIR}/${GENERATED_PDB}.pdb)
install(FILES ${CMAKE_BINARY_DIR}/${GENERATED_PDB}.pdb DESTINATION ".") install(FILES ${CMAKE_BINARY_DIR}/${GENERATED_PDB}.pdb DESTINATION ".")
add_dependencies(imhex_all ${PDB}_pdb)
endforeach () endforeach ()
endfunction() endfunction()
function(generateSDKDirectory) function(generateSDKDirectory)
if (WIN32) set(SDK_PATH "./sdk")
set(SDK_PATH "./sdk")
elseif (APPLE)
set(SDK_PATH "${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME}/Contents/Resources/sdk")
else()
set(SDK_PATH "share/imhex/sdk")
endif()
set(SDK_BUILD_PATH "${CMAKE_BINARY_DIR}/sdk") install(DIRECTORY ${CMAKE_SOURCE_DIR}/lib/libimhex/include DESTINATION "${SDK_PATH}")
install(FILES ${CMAKE_SOURCE_DIR}/cmake/modules/ImHexPlugin.cmake DESTINATION "${SDK_PATH}/cmake/modules")
install(DIRECTORY ${CMAKE_SOURCE_DIR}/lib/libimhex DESTINATION "${SDK_PATH}/lib" PATTERN "**/source/*" EXCLUDE)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/lib/external DESTINATION "${SDK_PATH}/lib")
install(DIRECTORY ${CMAKE_SOURCE_DIR}/lib/third_party/imgui DESTINATION "${SDK_PATH}/lib/third_party" PATTERN "**/source/*" EXCLUDE)
if (NOT USE_SYSTEM_FMT)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/lib/third_party/fmt DESTINATION "${SDK_PATH}/lib/third_party")
endif()
if (NOT USE_SYSTEM_NLOHMANN_JSON)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/lib/third_party/nlohmann_json DESTINATION "${SDK_PATH}/lib/third_party")
endif()
install(DIRECTORY ${CMAKE_SOURCE_DIR}/cmake/modules DESTINATION "${SDK_PATH}/cmake")
install(FILES ${CMAKE_SOURCE_DIR}/cmake/build_helpers.cmake DESTINATION "${SDK_PATH}/cmake")
install(DIRECTORY ${CMAKE_SOURCE_DIR}/cmake/sdk/ DESTINATION "${SDK_PATH}")
install(TARGETS libimhex ARCHIVE DESTINATION "${SDK_PATH}/lib") install(TARGETS libimhex ARCHIVE DESTINATION "${SDK_PATH}/lib")
endfunction() install(TARGETS libimhex RUNTIME DESTINATION "${SDK_PATH}/lib")
function(addIncludesFromLibrary target library)
get_target_property(library_include_dirs ${library} INTERFACE_INCLUDE_DIRECTORIES)
target_include_directories(${target} PRIVATE ${library_include_dirs})
endfunction()
function(precompileHeaders target includeFolder)
if (NOT IMHEX_ENABLE_PRECOMPILED_HEADERS)
return()
endif()
file(GLOB_RECURSE TARGET_INCLUDES "${includeFolder}/**/*.hpp")
set(SYSTEM_INCLUDES "<algorithm>;<array>;<atomic>;<chrono>;<cmath>;<cstddef>;<cstdint>;<cstdio>;<cstdlib>;<cstring>;<exception>;<filesystem>;<functional>;<iterator>;<limits>;<list>;<map>;<memory>;<optional>;<ranges>;<set>;<stdexcept>;<string>;<string_view>;<thread>;<tuple>;<type_traits>;<unordered_map>;<unordered_set>;<utility>;<variant>;<vector>")
set(INCLUDES "${SYSTEM_INCLUDES};${TARGET_INCLUDES}")
string(REPLACE ">" "$<ANGLE-R>" INCLUDES "${INCLUDES}")
target_precompile_headers(${target}
PUBLIC
"$<$<COMPILE_LANGUAGE:CXX>:${INCLUDES}>"
)
endfunction() endfunction()

View File

@@ -1,8 +0,0 @@
find_path(CAPSTONE_INCLUDE_DIR capstone.h PATH_SUFFIXES capstone)
find_library(CAPSTONE_LIBRARY NAMES capstone)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Capstone DEFAULT_MSG CAPSTONE_LIBRARY CAPSTONE_INCLUDE_DIR)
mark_as_advanced(CAPSTONE_INCLUDE_DIR CAPSTONE_LIBRARY)

View File

@@ -16,7 +16,7 @@ if (NOT DOTNET_EXECUTABLE)
set(DOTNET_EXECUTABLE dotnet) set(DOTNET_EXECUTABLE dotnet)
endif () endif ()
set(CORECLR_VERSION "8.0") set(CORECLR_VERSION "7.0")
execute_process(COMMAND ${DOTNET_EXECUTABLE} "--list-runtimes" OUTPUT_VARIABLE CORECLR_LIST_RUNTIMES_OUTPUT OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process(COMMAND ${DOTNET_EXECUTABLE} "--list-runtimes" OUTPUT_VARIABLE CORECLR_LIST_RUNTIMES_OUTPUT OUTPUT_STRIP_TRAILING_WHITESPACE)
if (CORECLR_LIST_RUNTIMES_OUTPUT STREQUAL "") if (CORECLR_LIST_RUNTIMES_OUTPUT STREQUAL "")
@@ -49,16 +49,13 @@ endif()
set(CoreClrEmbed_ROOT_PATH "${CORECLR_RUNTIME_ROOT_PATH}") set(CoreClrEmbed_ROOT_PATH "${CORECLR_RUNTIME_ROOT_PATH}")
file(GLOB _CORECLR_HOST_ARCH_PATH_LIST "${CORECLR_RUNTIME_ROOT_PATH}/packs/Microsoft.NETCore.App.Host.*-${CORECLR_SUBARCH}") file(GLOB _CORECLR_HOST_ARCH_PATH "${CORECLR_RUNTIME_ROOT_PATH}/packs/Microsoft.NETCore.App.Host.*-${CORECLR_SUBARCH}")
if (_CORECLR_HOST_ARCH_PATH_LIST) if (_CORECLR_HOST_ARCH_PATH)
foreach(_CORECLR_HOST_ARCH_PATH ${_CORECLR_HOST_ARCH_PATH_LIST}) get_filename_component(_CORECLR_HOST_ARCH_FILENAME ${_CORECLR_HOST_ARCH_PATH} NAME)
get_filename_component(_CORECLR_HOST_ARCH_FILENAME ${_CORECLR_HOST_ARCH_PATH} NAME) string(REPLACE "Microsoft.NETCore.App.Host." "" _CORECLR_COMPUTED_ARCH "${_CORECLR_HOST_ARCH_FILENAME}")
string(REPLACE "Microsoft.NETCore.App.Host." "" _CORECLR_COMPUTED_ARCH "${_CORECLR_HOST_ARCH_FILENAME}") if (_CORECLR_COMPUTED_ARCH)
if (_CORECLR_COMPUTED_ARCH) set(CORECLR_ARCH "${_CORECLR_COMPUTED_ARCH}")
set(CORECLR_ARCH "${_CORECLR_COMPUTED_ARCH}") endif()
break()
endif()
endforeach()
endif() endif()
set(CORECLR_HOST_BASE_PATH "${CORECLR_RUNTIME_ROOT_PATH}/packs/Microsoft.NETCore.App.Host.${CORECLR_ARCH}/${CORECLR_RUNTIME_VERSION_FULL}") set(CORECLR_HOST_BASE_PATH "${CORECLR_RUNTIME_ROOT_PATH}/packs/Microsoft.NETCore.App.Host.${CORECLR_ARCH}/${CORECLR_RUNTIME_VERSION_FULL}")
@@ -78,7 +75,7 @@ find_file(CoreClrEmbed_SHARED_LIBRARY nethost.dll nethost.so libnethost.so netho
if (CoreClrEmbed_INCLUDE_DIR AND CoreClrEmbed_LIBRARY) if (CoreClrEmbed_INCLUDE_DIR AND CoreClrEmbed_LIBRARY)
set(CoreClrEmbed_FOUND TRUE) set(CoreClrEmbed_FOUND TRUE)
set(CoreClrEmbed_LIBRARIES "${CoreClrEmbed_LIBRARY}" CACHE STRING "CoreClrEmbed libraries" FORCE) set(CoreClrEmbed_LIBRARIES "${CoreClrEmbed_LIBRARY}")
set(CoreClrEmbed_SHARED_LIBRARIES "${CoreClrEmbed_SHARED_LIBRARY}" CACHE STRING "CoreClrEmbed shared libraries" FORCE) set(CoreClrEmbed_SHARED_LIBRARIES "${CoreClrEmbed_SHARED_LIBRARY}")
set(CoreClrEmbed_INCLUDE_DIRS "${CoreClrEmbed_INCLUDE_DIR}" CACHE STRING "CoreClrEmbed include directories" FORCE) set(CoreClrEmbed_INCLUDE_DIRS "${CoreClrEmbed_INCLUDE_DIR}")
endif() endif()

View File

@@ -1,139 +0,0 @@
#.rst:
# Find GLFW
# ---------
#
# Finds the GLFW library using its cmake config if that exists, otherwise
# falls back to finding it manually. This module defines:
#
# GLFW_FOUND - True if GLFW library is found
# GLFW::GLFW - GLFW imported target
#
# Additionally, in case the config was not found, these variables are defined
# for internal usage:
#
# GLFW_LIBRARY - GLFW library
# GLFW_DLL_DEBUG - GLFW debug DLL on Windows, if found
# GLFW_DLL_RELEASE - GLFW release DLL on Windows, if found
# GLFW_INCLUDE_DIR - Root include dir
#
#
# This file is part of Magnum.
#
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
# 2020, 2021, 2022 Vladimír Vondruš <mosra@centrum.cz>
# Copyright © 2016 Jonathan Hale <squareys@googlemail.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
# GLFW installs cmake package config files which handles dependencies in case
# GLFW is built statically. Try to find first, quietly, so it doesn't print
# loud messages when it's not found, since that's okay. If the glfw target
# already exists, it means we're using it through a CMake subproject -- don't
# attempt to find the package in that case.
if(NOT TARGET glfw)
find_package(glfw3 CONFIG QUIET)
endif()
# If either a glfw config file was found or we have a subproject, point
# GLFW::GLFW to that and exit -- nothing else to do here.
if(TARGET glfw)
if(NOT TARGET GLFW::GLFW)
# Aliases of (global) targets are only supported in CMake 3.11, so we
# work around it by this. This is easier than fetching all possible
# properties (which are impossible to track of) and then attempting to
# rebuild them into a new target.
add_library(GLFW::GLFW INTERFACE IMPORTED)
set_target_properties(GLFW::GLFW PROPERTIES INTERFACE_LINK_LIBRARIES glfw)
endif()
# Just to make FPHSA print some meaningful location, nothing else
get_target_property(_GLFW_INTERFACE_INCLUDE_DIRECTORIES glfw INTERFACE_INCLUDE_DIRECTORIES)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args("GLFW" DEFAULT_MSG
_GLFW_INTERFACE_INCLUDE_DIRECTORIES)
if(CORRADE_TARGET_WINDOWS)
# .dll is in LOCATION, .lib is in IMPLIB. Yay, useful!
get_target_property(GLFW_DLL_DEBUG glfw IMPORTED_LOCATION_DEBUG)
get_target_property(GLFW_DLL_RELEASE glfw IMPORTED_LOCATION_RELEASE)
endif()
return()
endif()
if(CORRADE_TARGET_WINDOWS)
if(MSVC)
if(MSVC_VERSION VERSION_LESS 1910)
set(_GLFW_LIBRARY_PATH_SUFFIX lib-vc2015)
elseif(MSVC_VERSION VERSION_LESS 1920)
set(_GLFW_LIBRARY_PATH_SUFFIX lib-vc2017)
elseif(MSVC_VERSION VERSION_LESS 1930)
set(_GLFW_LIBRARY_PATH_SUFFIX lib-vc2019)
elseif(MSVC_VERSION VERSION_LESS 1940)
set(_GLFW_LIBRARY_PATH_SUFFIX lib-vc2022)
else()
message(FATAL_ERROR "Unsupported MSVC version")
endif()
elseif(MINGW)
set(_GLFW_LIBRARY_PATH_SUFFIX lib-mingw-w64)
else()
message(FATAL_ERROR "Unsupported compiler")
endif()
endif()
# In case no config file was found, try manually finding the library. Prefer
# the glfw3dll as it's a dynamic library.
find_library(GLFW_LIBRARY
NAMES glfw glfw3dll glfw3
PATH_SUFFIXES ${_GLFW_LIBRARY_PATH_SUFFIX})
if(CORRADE_TARGET_WINDOWS AND GLFW_LIBRARY MATCHES "glfw3dll.(lib|a)$")
# TODO: debug?
find_file(GLFW_DLL_RELEASE
NAMES glfw3.dll
PATH_SUFFIXES ${_GLFW_LIBRARY_PATH_SUFFIX})
endif()
# Include dir
find_path(GLFW_INCLUDE_DIR
NAMES GLFW/glfw3.h)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args("GLFW" DEFAULT_MSG
GLFW_LIBRARY
GLFW_INCLUDE_DIR)
if(NOT TARGET GLFW::GLFW)
add_library(GLFW::GLFW UNKNOWN IMPORTED)
# Work around BUGGY framework support on macOS
# https://cmake.org/Bug/view.php?id=14105
if(CORRADE_TARGET_APPLE AND GLFW_LIBRARY MATCHES "\\.framework$")
set_property(TARGET GLFW::GLFW PROPERTY IMPORTED_LOCATION ${GLFW_LIBRARY}/GLFW)
else()
set_property(TARGET GLFW::GLFW PROPERTY IMPORTED_LOCATION ${GLFW_LIBRARY})
endif()
set_property(TARGET GLFW::GLFW PROPERTY
INTERFACE_INCLUDE_DIRECTORIES ${GLFW_INCLUDE_DIR})
endif()
mark_as_advanced(GLFW_LIBRARY GLFW_INCLUDE_DIR)

View File

@@ -1,18 +0,0 @@
find_path(LIBMAGIC_INCLUDE_DIR magic.h)
find_library(LIBMAGIC_LIBRARY NAMES magic)
if (LIBMAGIC_INCLUDE_DIR AND LIBMAGIC_LIBRARY)
set(LIBMAGIC_FOUND TRUE)
endif (LIBMAGIC_INCLUDE_DIR AND LIBMAGIC_LIBRARY)
find_package_handle_standard_args("libmagic" DEFAULT_MSG
LIBMAGIC_LIBRARY
LIBMAGIC_INCLUDE_DIR
)
mark_as_advanced(
LIBMAGIC_INCLUDE_DIR
LIBMAGIC_LIBRARY
LIBMAGIC_FOUND
)

View File

@@ -1,4 +0,0 @@
find_library(YARA_LIBRARIES NAMES yara)
find_file(yara.h YARA_INCLUDE_DIRS)
mark_as_advanced(YARA_LIBRARIES YARA_INCLUDE_DIRS)

View File

@@ -1,41 +0,0 @@
# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# - Try to find Facebook zstd library
# This will define
# ZSTD_FOUND
# ZSTD_INCLUDE_DIR
# ZSTD_LIBRARY
#
find_path(ZSTD_INCLUDE_DIR NAMES zstd.h)
find_library(ZSTD_LIBRARY_DEBUG NAMES zstdd zstd_staticd)
find_library(ZSTD_LIBRARY_RELEASE NAMES zstd zstd_static)
include(SelectLibraryConfigurations)
SELECT_LIBRARY_CONFIGURATIONS(ZSTD)
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(
ZSTD DEFAULT_MSG
ZSTD_LIBRARY ZSTD_INCLUDE_DIR
)
if (ZSTD_FOUND)
message(STATUS "Found Zstd: ${ZSTD_LIBRARY}")
endif()
mark_as_advanced(ZSTD_INCLUDE_DIR ZSTD_LIBRARY)

View File

@@ -1,15 +1,10 @@
macro(add_imhex_plugin) macro(add_imhex_plugin)
# Parse arguments # Parse arguments
set(options LIBRARY_PLUGIN) set(options "")
set(oneValueArgs NAME IMHEX_VERSION) set(oneValueArgs NAME)
set(multiValueArgs SOURCES INCLUDES LIBRARIES FEATURES) set(multiValueArgs SOURCES INCLUDES LIBRARIES)
cmake_parse_arguments(IMHEX_PLUGIN "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) cmake_parse_arguments(IMHEX_PLUGIN "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if (IMHEX_PLUGIN_IMHEX_VERSION)
message(STATUS "Compiling plugin ${IMHEX_PLUGIN_NAME} for ImHex Version ${IMHEX_PLUGIN_IMHEX_VERSION}")
set(IMHEX_VERSION_STRING "${IMHEX_PLUGIN_IMHEX_VERSION}")
endif()
if (IMHEX_STATIC_LINK_PLUGINS) if (IMHEX_STATIC_LINK_PLUGINS)
set(IMHEX_PLUGIN_LIBRARY_TYPE STATIC) set(IMHEX_PLUGIN_LIBRARY_TYPE STATIC)
@@ -17,15 +12,8 @@ macro(add_imhex_plugin)
configure_file(${CMAKE_SOURCE_DIR}/dist/web/plugin-bundle.cpp.in ${CMAKE_CURRENT_BINARY_DIR}/plugin-bundle.cpp @ONLY) configure_file(${CMAKE_SOURCE_DIR}/dist/web/plugin-bundle.cpp.in ${CMAKE_CURRENT_BINARY_DIR}/plugin-bundle.cpp @ONLY)
target_sources(main PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/plugin-bundle.cpp) target_sources(main PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/plugin-bundle.cpp)
set(IMHEX_PLUGIN_SUFFIX ".hexplug")
else() else()
if (IMHEX_PLUGIN_LIBRARY_PLUGIN) set(IMHEX_PLUGIN_LIBRARY_TYPE SHARED)
set(IMHEX_PLUGIN_LIBRARY_TYPE SHARED)
set(IMHEX_PLUGIN_SUFFIX ".hexpluglib")
else()
set(IMHEX_PLUGIN_LIBRARY_TYPE MODULE)
set(IMHEX_PLUGIN_SUFFIX ".hexplug")
endif()
endif() endif()
# Define new project for plugin # Define new project for plugin
@@ -36,12 +24,7 @@ macro(add_imhex_plugin)
# Add include directories and link libraries # Add include directories and link libraries
target_include_directories(${IMHEX_PLUGIN_NAME} PUBLIC ${IMHEX_PLUGIN_INCLUDES}) target_include_directories(${IMHEX_PLUGIN_NAME} PUBLIC ${IMHEX_PLUGIN_INCLUDES})
target_link_libraries(${IMHEX_PLUGIN_NAME} PUBLIC ${IMHEX_PLUGIN_LIBRARIES}) target_link_libraries(${IMHEX_PLUGIN_NAME} PRIVATE libimhex ${FMT_LIBRARIES} ${IMHEX_PLUGIN_LIBRARIES})
target_link_libraries(${IMHEX_PLUGIN_NAME} PRIVATE libimhex ${FMT_LIBRARIES} imgui_all_includes libwolv)
addIncludesFromLibrary(${IMHEX_PLUGIN_NAME} libpl)
addIncludesFromLibrary(${IMHEX_PLUGIN_NAME} libpl-gen)
precompileHeaders(${IMHEX_PLUGIN_NAME} "${CMAKE_CURRENT_SOURCE_DIR}/include")
# Add IMHEX_PROJECT_NAME and IMHEX_VERSION define # Add IMHEX_PROJECT_NAME and IMHEX_VERSION define
target_compile_definitions(${IMHEX_PLUGIN_NAME} PRIVATE IMHEX_PROJECT_NAME="${IMHEX_PLUGIN_NAME}") target_compile_definitions(${IMHEX_PLUGIN_NAME} PRIVATE IMHEX_PROJECT_NAME="${IMHEX_PLUGIN_NAME}")
@@ -49,7 +32,7 @@ macro(add_imhex_plugin)
target_compile_definitions(${IMHEX_PLUGIN_NAME} PRIVATE IMHEX_PLUGIN_NAME=${IMHEX_PLUGIN_NAME}) target_compile_definitions(${IMHEX_PLUGIN_NAME} PRIVATE IMHEX_PLUGIN_NAME=${IMHEX_PLUGIN_NAME})
# Enable required compiler flags # Enable required compiler flags
enableUnityBuild(${IMHEX_PLUGIN_NAME}) set_target_properties(${IMHEX_PLUGIN_NAME} PROPERTIES POSITION_INDEPENDENT_CODE ON)
setupCompilerFlags(${IMHEX_PLUGIN_NAME}) setupCompilerFlags(${IMHEX_PLUGIN_NAME})
# Configure build properties # Configure build properties
@@ -58,46 +41,18 @@ macro(add_imhex_plugin)
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins
CXX_STANDARD 23 CXX_STANDARD 23
PREFIX "" PREFIX ""
SUFFIX ${IMHEX_PLUGIN_SUFFIX} SUFFIX ".hexplug"
) )
# Set rpath of plugin libraries to the plugins folder
if (APPLE)
set_target_properties(${IMHEX_PLUGIN_NAME} PROPERTIES BUILD_RPATH "@executable_path/../Frameworks;@executable_path/plugins")
endif()
# Setup a romfs for the plugin # Setup a romfs for the plugin
list(APPEND LIBROMFS_RESOURCE_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/romfs) list(APPEND LIBROMFS_RESOURCE_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/romfs)
set(LIBROMFS_PROJECT_NAME ${IMHEX_PLUGIN_NAME}) set(LIBROMFS_PROJECT_NAME ${IMHEX_PLUGIN_NAME})
add_subdirectory(${IMHEX_BASE_FOLDER}/lib/external/libromfs ${CMAKE_CURRENT_BINARY_DIR}/libromfs) add_subdirectory(${IMHEX_BASE_FOLDER}/lib/external/libromfs ${CMAKE_CURRENT_BINARY_DIR}/libromfs)
set_target_properties(${LIBROMFS_LIBRARY} PROPERTIES POSITION_INDEPENDENT_CODE ON)
target_link_libraries(${IMHEX_PLUGIN_NAME} PRIVATE ${LIBROMFS_LIBRARY}) target_link_libraries(${IMHEX_PLUGIN_NAME} PRIVATE ${LIBROMFS_LIBRARY})
foreach(feature ${IMHEX_PLUGIN_FEATURES})
string(TOUPPER ${feature} feature)
add_definitions(-DIMHEX_PLUGIN_${IMHEX_PLUGIN_NAME}_FEATURE_${feature}=0)
endforeach()
# Add the new plugin to the main dependency list so it gets built by default # Add the new plugin to the main dependency list so it gets built by default
if (TARGET imhex_all) add_dependencies(imhex_all ${IMHEX_PLUGIN_NAME})
add_dependencies(imhex_all ${IMHEX_PLUGIN_NAME})
endif()
if (IMHEX_EXTERNAL_PLUGIN_BUILD)
install(TARGETS ${IMHEX_PLUGIN_NAME} DESTINATION ".")
endif()
# Fix rpath
if (APPLE)
set_target_properties(${IMHEX_PLUGIN_NAME} PROPERTIES INSTALL_RPATH "@executable_path/../Frameworks;@executable_path/plugins")
elseif (UNIX)
set_target_properties(${IMHEX_PLUGIN_NAME} PROPERTIES INSTALL_RPATH_USE_ORIGIN ON INSTALL_RPATH "$ORIGIN/")
endif()
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/tests/CMakeLists.txt AND IMHEX_ENABLE_UNIT_TESTS)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/tests)
target_link_libraries(${IMHEX_PLUGIN_NAME} PUBLIC ${IMHEX_PLUGIN_NAME}_tests)
target_compile_definitions(${IMHEX_PLUGIN_NAME}_tests PRIVATE IMHEX_PROJECT_NAME="${IMHEX_PLUGIN_NAME}-tests")
endif()
endmacro() endmacro()
macro(add_romfs_resource input output) macro(add_romfs_resource input output)
@@ -105,13 +60,3 @@ macro(add_romfs_resource input output)
list(APPEND LIBROMFS_RESOURCE_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/romfs) list(APPEND LIBROMFS_RESOURCE_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/romfs)
endmacro() endmacro()
macro (enable_plugin_feature feature)
string(TOUPPER ${feature} feature)
if (NOT (feature IN_LIST IMHEX_PLUGIN_FEATURES))
message(FATAL_ERROR "Feature ${feature} is not enabled for plugin ${IMHEX_PLUGIN_NAME}")
endif()
remove_definitions(-DIMHEX_PLUGIN_${IMHEX_PLUGIN_NAME}_FEATURE_${feature}=0)
add_definitions(-DIMHEX_PLUGIN_${IMHEX_PLUGIN_NAME}_FEATURE_${feature}=1)
endmacro()

View File

@@ -14,47 +14,41 @@ if(CMAKE_GENERATOR)
# Being called as include(PostprocessBundle), so define a helper function. # Being called as include(PostprocessBundle), so define a helper function.
set(_POSTPROCESS_BUNDLE_MODULE_LOCATION "${CMAKE_CURRENT_LIST_FILE}") set(_POSTPROCESS_BUNDLE_MODULE_LOCATION "${CMAKE_CURRENT_LIST_FILE}")
function(postprocess_bundle out_target in_target) function(postprocess_bundle out_target in_target)
add_custom_command(TARGET ${out_target} POST_BUILD
install(CODE "set(BUNDLE_PATH ${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME})") COMMAND ${CMAKE_COMMAND} -DBUNDLE_PATH="$<TARGET_FILE_DIR:${in_target}>/../.."
install(CODE "set(CODE_SIGN_CERTIFICATE_ID ${CODE_SIGN_CERTIFICATE_ID})") -DCODE_SIGN_CERTIFICATE_ID="${CODE_SIGN_CERTIFICATE_ID}"
install(CODE "set(EXTRA_BUNDLE_LIBRARY_PATHS ${EXTRA_BUNDLE_LIBRARY_PATHS})") -DEXTRA_BUNDLE_LIBRARY_PATHS="${EXTRA_BUNDLE_LIBRARY_PATHS}"
install(SCRIPT ${_POSTPROCESS_BUNDLE_MODULE_LOCATION}) -P "${_POSTPROCESS_BUNDLE_MODULE_LOCATION}"
)
endfunction() endfunction()
return() return()
endif() endif()
# IMHEX PATCH BEGIN
# The function defined above doesn't keep in mind that if we are cross-compiling to MacOS, APPLE must be 1,
# so we force it here (where else would this script be run anyway ? This seems to be MacOS-specific code)
SET(APPLE 1)
# IMHEX PATCHE END
get_filename_component(BUNDLE_PATH "${BUNDLE_PATH}" ABSOLUTE) get_filename_component(BUNDLE_PATH "${BUNDLE_PATH}" ABSOLUTE)
message(STATUS "Fixing up application bundle: ${BUNDLE_PATH}") message(STATUS "Fixing up application bundle: ${BUNDLE_PATH}")
# Make sure to fix up any included ImHex plugin. # Make sure to fix up any included ImHex plugin.
file(GLOB_RECURSE plugins "${BUNDLE_PATH}/Contents/MacOS/plugins/*.hexplug") file(GLOB_RECURSE extra_libs "${BUNDLE_PATH}/Contents/MacOS/plugins/*.hexplug")
# BundleUtilities doesn't support DYLD_FALLBACK_LIBRARY_PATH behavior, which # BundleUtilities doesn't support DYLD_FALLBACK_LIBRARY_PATH behavior, which
# makes it sometimes break on libraries that do weird things with @rpath. Specify # makes it sometimes break on libraries that do weird things with @rpath. Specify
# equivalent search directories until https://gitlab.kitware.com/cmake/cmake/issues/16625 # equivalent search directories until https://gitlab.kitware.com/cmake/cmake/issues/16625
# is fixed and in our minimum CMake version. # is fixed and in our minimum CMake version.
set(extra_dirs "/usr/local/lib" "/lib" "/usr/lib" ${EXTRA_BUNDLE_LIBRARY_PATHS} "${BUNDLE_PATH}/Contents/MacOS/plugins" "${BUNDLE_PATH}/Contents/Frameworks") set(extra_dirs "/usr/local/lib" "/lib" "/usr/lib" ${EXTRA_BUNDLE_LIBRARY_PATHS})
message(STATUS "Fixing up application bundle: ${extra_dirs}") message(STATUS "Fixing up application bundle: ${extra_dirs}")
# BundleUtilities is overly verbose, so disable most of its messages # BundleUtilities is overly verbose, so disable most of its messages
#function(message) function(message)
# if(NOT ARGV MATCHES "^STATUS;") if(NOT ARGV MATCHES "^STATUS;")
# _message(${ARGV}) _message(${ARGV})
# endif() endif()
#endfunction() endfunction()
include(BundleUtilities) include(BundleUtilities)
set(BU_CHMOD_BUNDLE_ITEMS ON) set(BU_CHMOD_BUNDLE_ITEMS ON)
fixup_bundle("${BUNDLE_PATH}" "${extra_libs}" "${extra_dirs}")
fixup_bundle("${BUNDLE_PATH}" "${plugins}" "${extra_dirs}")
if (CODE_SIGN_CERTIFICATE_ID) if (CODE_SIGN_CERTIFICATE_ID)
# Hack around Apple Silicon signing bugs by copying the real app, signing it and moving it back. # Hack around Apple Silicon signing bugs by copying the real app, signing it and moving it back.
@@ -67,12 +61,3 @@ endif()
# Add a necessary rpath to the imhex binary # Add a necessary rpath to the imhex binary
get_bundle_main_executable("${BUNDLE_PATH}" IMHEX_EXECUTABLE) get_bundle_main_executable("${BUNDLE_PATH}" IMHEX_EXECUTABLE)
file(GLOB_RECURSE plugin_libs "${BUNDLE_PATH}/Contents/MacOS/*.hexpluglib")
foreach(plugin_lib ${plugin_libs})
get_filename_component(plugin_lib_name ${plugin_lib} NAME)
set(plugin_lib_dest "${BUNDLE_PATH}/Contents/MacOS/plugins/${plugin_lib_name}")
configure_file(${plugin_lib} "${plugin_lib_dest}" COPYONLY)
message(STATUS "Copying plugin library: ${plugin_lib} to ${plugin_lib_dest}")
endforeach ()

View File

@@ -1,58 +0,0 @@
cmake_minimum_required(VERSION 3.20)
project(ImHexSDK)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")
set(CMAKE_POSITION_INDEPENDENT_CODE ON CACHE BOOL "" FORCE)
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/build_helpers.cmake")
set(IMHEX_BASE_FOLDER ${CMAKE_CURRENT_SOURCE_DIR} PARENT_SCOPE)
include(ImHexPlugin)
function(add_subdirectory_if_exists folder)
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${folder}/CMakeLists.txt")
add_subdirectory("${folder}" EXCLUDE_FROM_ALL)
endif()
endfunction()
set(IMHEX_EXTERNAL_PLUGIN_BUILD ON PARENT_SCOPE)
set(IMHEX_EXTERNAL_PLUGIN_BUILD ON)
add_custom_target(imhex_all)
add_subdirectory(lib/third_party/imgui EXCLUDE_FROM_ALL)
set(FMT_INSTALL OFF CACHE BOOL "" FORCE)
add_subdirectory_if_exists(lib/third_party/fmt)
set(FMT_LIBRARIES fmt::fmt-header-only PARENT_SCOPE)
set(FMT_LIBRARIES fmt::fmt-header-only)
add_subdirectory_if_exists(lib/third_party/nlohmann_json)
set(NLOHMANN_JSON_LIBRARIES nlohmann_json PARENT_SCOPE)
set(NLOHMANN_JSON_LIBRARIES nlohmann_json)
add_subdirectory(lib/external/libwolv EXCLUDE_FROM_ALL)
set(LIBPL_ENABLE_CLI OFF CACHE BOOL "" FORCE)
add_subdirectory(lib/external/pattern_language EXCLUDE_FROM_ALL)
find_package(CURL REQUIRED)
find_package(mbedTLS 3.4.0 REQUIRED)
set(CURL_LIBRARIES ${CURL_LIBRARIES} PARENT_SCOPE)
set(MBEDTLS_LIBRARIES ${MBEDTLS_LIBRARIES} PARENT_SCOPE)
add_subdirectory(lib/libimhex)
if (WIN32)
set_target_properties(libimhex PROPERTIES
IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/../libimhex.dll"
IMPORTED_IMPLIB "${CMAKE_CURRENT_SOURCE_DIR}/lib/liblibimhex.dll.a"
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/lib/libimhex/include")
elseif (APPLE)
file(GLOB LIBIMHEX_DYLIB "${CMAKE_CURRENT_SOURCE_DIR}/../../Frameworks/libimhex.*.dylib")
set_target_properties(libimhex PROPERTIES
IMPORTED_LOCATION "${LIBIMHEX_DYLIB}"
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/lib/libimhex/include")
else()
set_target_properties(libimhex PROPERTIES
IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/../libimhex.so"
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/lib/libimhex/include")
endif()

View File

@@ -1,60 +0,0 @@
# ImHex Plugin Template
# =====================
# This is the official CMake template for making your own ImHex plugins
# To use this template, copy the file into its own directory and modify it to your needs
# For the most part, this is a regular CMake project with some extra functions provided by the ImHex SDK
#
# [NOTE FOR NON-C++ PLUGINS]
# The template is laid out for a C++ plugin, however you can write your plugin in any language you want
# and just make the plugin statically link against your code. The only thing that's required is a .cpp file with
# the IMHEX_PLUGIN_SETUP() macro used in it. This macro is used to setup the plugin and register it with ImHex
#
# [CMAKE FUNCTIONS]
# add_imhex_plugin(): Registers a new plugin
# NAME: The name of the plugin
# IMHEX_VERSION: The ImHex version this plugin is compatible with. If unset, the plugin will be loaded on all versions (this may not work though)
# SOURCES: Source files of the plugin
# INCLUDES: Include directories of the plugin
# LIBRARIES: Libraries to link against
# FEATURES: Optional features that can be enabled or disabled
# LIBRARY_PLUGIN: If set, turns this plugin into a library plugin. Library plugins can be linked against by other plugins
#
# add_romfs_resource(filePath romfsPath): Adds a file to the romfs of the plugin
# The RomFS is a virtual filesystem whose files can be accessed by the plugin using the functions in the `romfs::` namespace
# This function is used to add a single file to the romfs. You can however also simply create a `romfs` directory in your plugin directory and place your files and folders in there
# filePath: The path to the file on the disk
# romfsPath: The path to the file in the romfs
#
# enable_plugin_feature(feature): Enables a plugin feature
# Features are optional parts of the plugin that may or may not be available depending on build settings
# When a feature is enabled, `IMHEX_FEATURE_ENABLED(feature)` will be defined to true. Otherwise, it will be defined to false
# Use the `IMHEX_PLUGIN_FEATURES` macro in the main plugin file to define names to each feature and have them be listed in the plugin list
# feature: The name of the feature to enable
cmake_minimum_required(VERSION 3.20)
project(ImHexPlugin)
# Include the ImHex SDK
# For this to work, you need to set the IMHEX_SDK_PATH environment variable to the path of the ImHex SDK
#
# On Windows, the SDK is next to the ImHex executable
# On Linux, the SDK is usually in /usr/share/imhex/sdk but this may vary depending on your distribution
# On MacOS, the SDK is located inside of the ImHex.app bundle under ImHex.app/Contents/Resources/sdk
if (NOT EXISTS $ENV{IMHEX_SDK_PATH})
message(FATAL_ERROR "The IMHEX_SDK_PATH environment variable is not set")
endif()
add_subdirectory($ENV{IMHEX_SDK_PATH} ImHexSDK)
# Register the plugin
# This will configure everything you need to make your plugin work
# Modify the arguments to your needs. Right now it defines a plugin called `example_plugin`
# with a single source file called `example_plugin.cpp` in the `source` directory
# By default you have access to the libimhex library to interact with ImHex
# as well as libwolv, libromfs, libfmt and ImGui, but you can link against any libraries you want
add_imhex_plugin(
NAME
example_plugin
SOURCES
source/example_plugin.cpp
)

View File

@@ -1,11 +0,0 @@
#include <hex/plugin.hpp>
// Browse through the headers in lib/libimhex/include/hex/api/ to see what you can do with the API.
// Most important ones are <hex/api/imhex_api.hpp> and <hex/api/content_registry.hpp>
// This is the main entry point of your plugin. The code in the body of this construct will be executed
// when ImHex starts up and loads the plugin.
// The strings in the header are used to display information about the plugin in the UI.
IMHEX_PLUGIN_SETUP("Example Plugin", "Author", "Description") {
// Put your init code here
}

5
dist/Arch/PKGBUILD vendored
View File

@@ -8,7 +8,7 @@ pkgdesc="A Hex Editor for Reverse Engineers, Programmers and people who value th
arch=("x86_64") arch=("x86_64")
url="https://github.com/WerWolv/ImHex" url="https://github.com/WerWolv/ImHex"
license=('GPL2') license=('GPL2')
depends=(glfw mbedtls freetype2 libglvnd dbus gtk3 curl fmt yara nlohmann-json zlib bzip2 xz zstd) depends=(glfw mbedtls freetype2 libglvnd dbus gtk3 curl fmt yara nlohmann-json)
makedepends=(git) makedepends=(git)
provides=(imhex) provides=(imhex)
conflicts=(imhex) conflicts=(imhex)
@@ -17,10 +17,9 @@ md5sums=(SKIP)
package() { package() {
install -Dm755 "$srcdir/usr/bin/imhex" "$pkgdir/usr/bin/imhex" install -Dm755 "$srcdir/usr/bin/imhex" "$pkgdir/usr/bin/imhex"
install -Dm755 "$srcdir/usr/bin/imhex-updater" "$pkgdir/usr/bin/imhex-updater"
install -Dm644 "$srcdir/usr/lib/libimhex.so.$pkgver" "$pkgdir/usr/lib/libimhex.so.$pkgver" install -Dm644 "$srcdir/usr/lib/libimhex.so.$pkgver" "$pkgdir/usr/lib/libimhex.so.$pkgver"
for plugin in "$srcdir/usr/lib/imhex/plugins/"*.hexplug*; do for plugin in "$srcdir/usr/lib/imhex/plugins/"*.hexplug; do
install -Dm644 "$plugin" "$pkgdir/usr/lib/imhex/plugins/${plugin##*/}" install -Dm644 "$plugin" "$pkgdir/usr/lib/imhex/plugins/${plugin##*/}"
done done

4
dist/Brewfile vendored
View File

@@ -10,7 +10,3 @@ brew "gcc@12"
brew "llvm" brew "llvm"
brew "glfw" brew "glfw"
brew "ninja" brew "ninja"
brew "zlib"
brew "xz"
brew "bzip2"
brew "zstd"

View File

@@ -4,7 +4,7 @@ Section: editors
Priority: optional Priority: optional
Architecture: amd64 Architecture: amd64
License: GNU GPL-2 License: GNU GPL-2
Depends: libglfw3 | libglfw3-wayland, libmagic1, libmbedtls14, libfreetype6, libopengl0, libdbus-1-3, xdg-desktop-portal Depends: libglfw3, libmagic1, libmbedtls14, libfreetype6, libopengl0, libdbus-1-3, xdg-desktop-portal
Maintainer: WerWolv <hey@werwolv.net> Maintainer: WerWolv <hey@werwolv.net>
Description: ImHex Hex Editor Description: ImHex Hex Editor
A Hex Editor for Reverse Engineers, Programmers and A Hex Editor for Reverse Engineers, Programmers and

View File

@@ -24,9 +24,5 @@ RDEPEND="${DEPEND}
dev-cpp/nlohmann_json dev-cpp/nlohmann_json
dbus dbus
xdg-desktop-portal xdg-desktop-portal
sys-libs/zlib
app-arch/bzip2
app-arch/lzma
app-arch/zstd
" "
BDEPEND="${DEPEND}" BDEPEND="${DEPEND}"

View File

@@ -53,6 +53,7 @@ CC=gcc-12 CXX=g++-12 cmake -G "Ninja" \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \ -DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DIMHEX_PATTERNS_PULL_MASTER=ON \ -DIMHEX_PATTERNS_PULL_MASTER=ON \
-DIMHEX_COMMIT_HASH_SHORT="${GIT_COMMIT_HASH::7}" \
-DIMHEX_COMMIT_HASH_LONG="${GIT_COMMIT_HASH}" \ -DIMHEX_COMMIT_HASH_LONG="${GIT_COMMIT_HASH}" \
-DIMHEX_COMMIT_BRANCH="${GIT_BRANCH}" \ -DIMHEX_COMMIT_BRANCH="${GIT_BRANCH}" \
-DIMHEX_ENABLE_LTO=${LTO} \ -DIMHEX_ENABLE_LTO=${LTO} \

View File

@@ -1,49 +0,0 @@
For a TLDR of commands see [How to build](#How-to-build)
# Introduction
The original CI we used (vanilla Github Actions) was great for specifying what steps to execute to build packages. It could even do some custom steps with reusable actions. But it had problem: no local reproducibility. This meant that:
- We couldn't test code properly locally, we were dependent on GitHub to do it
- If something was wrong and we had to debug the build script, it was *long and painful* because we had to wait for Github runners to finish builds, and couldn't quickly iterate
To solve this, we are now trying to move the CI build script to docker containers (so using Dockerfiles)
# How to build
Commands are available in the [CI](../../.github/workflows/build.yml) and you should prefer copying them from there.
But here is a general command that should work for every build we have:
```
docker buildx build . -f <DOCKERFILE_PATH> --progress plain --build-arg 'JOBS=4' --build-arg 'BUILD_TYPE=Debug' --build-context imhex=$(pwd) --output local
```
where `<DOCKERFILE_PATH>` should be replaced by the wanted Dockerfile base d on the build you want to do:
| Wanted build | Dockerfile path | Target |
|--------------|-----------------------------|--------|
| MacOS M1 | dist/macOS/arm64.Dockerfile | - |
| AppImage | dist/appimage/Dockerfile | - |
| Web version | dist/web/Dockerfile | raw |
We'll explain this command in the next section
# Useful knowledge about Docker builds
Docker-based builds work with a Dockerfile. You run the Dockerfile, it builds the package.
We are using a base environment (often given to us by dockerhub) (e.g. ubuntu:22.04) which is really just a root filesystem, and we then run shell commands in that env, just like a shell script
Docker-based builds have two kind of caches used:
- layer cache, which mean that if a layer (instruction) hasn't been changed, and previous layers haven't changed, it will not be run again
- a `COPY` layer will be invalidated if one of the file copied has changed
- mount cache, which are per-instructions mounts that will be cached and restored in the next run. Mounts on different folders will not collide
Docker cache tends to grow very quickly when constantly making changes in the Dockerfile and rebuilding (a.k.a debugging what's going on), you can clear it with something like `docker system prune -a`
In the command saw earlier:
- `.` is the base folder that the Dockerfile will be allowed to see
- `-f <path>` is to specify the Dockerfile path
- `--progress plain` is to allow you to see the output of instructions
- `--build-arg <key>=<value>` is to allow to specify arguments to the build (like -DKEY=VALUE in CMake)
- `--build-context key=<folder>` is to specify folders other than the base folder that the Dockerfile is allowed to see
- `--output <path>` is the path to write the output package to. If not specified, Docker will create an image as the output (probably not what you want)
- `--target <target>` specifies which docker target to build

View File

@@ -9,12 +9,17 @@ On Linux, ImHex is built through regular GCC (or optionally Clang).
cd ImHex cd ImHex
mkdir -p build mkdir -p build
cd build cd build
CC=gcc-12 CXX=g++-12 \ CC=gcc-12 CXX=g++-12 cmake \
cmake -G "Ninja" \
-DCMAKE_BUILD_TYPE=Release \ -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX="/usr" \ -DCMAKE_INSTALL_PREFIX="/usr" \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_C_FLAGS="-fuse-ld=lld" \
-DCMAKE_CXX_FLAGS="-fuse-ld=lld" \
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
-DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
.. ..
ninja install make -j 4 install
``` ```
All paths follow the XDG Base Directories standard, and can thus be modified All paths follow the XDG Base Directories standard, and can thus be modified

View File

@@ -9,14 +9,24 @@ On macOS, ImHex is built through regular GCC and LLVM clang.
cd ImHex cd ImHex
mkdir -p build mkdir -p build
cd build cd build
CC=$(brew --prefix llvm)/bin/clang \ CC=$(brew --prefix gcc@12)/bin/gcc-12 \
CXX=$(brew --prefix llvm)/bin/clang++ \ CXX=$(brew --prefix gcc@12)/bin/g++-12 \
OBJC=$(brew --prefix llvm)/bin/clang \ OBJC=$(brew --prefix llvm)/bin/clang \
OBJCXX=$(brew --prefix llvm)/bin/clang++ \ OBJCXX=$(brew --prefix llvm)/bin/clang++ \
cmake -G "Ninja" \ PKG_CONFIG_PATH="$(brew --prefix openssl)/lib/pkgconfig":"$(brew --prefix)/lib/pkgconfig" \
MACOSX_DEPLOYMENT_TARGET="10.15" \
cmake \
-DCMAKE_BUILD_TYPE=Release \ -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX="./install" \ -DCREATE_BUNDLE=ON \
-DIMHEX_GENERATE_PACKAGE=ON \ -DCREATE_PACKAGE=ON \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
-DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
.. ..
ninja install make -j4 package
``` ```
If the build fails while trying to find the macOS libraries, make sure you have
Xcode installed with `xcode-select --install`. Homebrew will also help get the
most recent SDK installed and configured with `brew doctor`.

View File

@@ -14,7 +14,7 @@ mkdir build
cd build cd build
cmake -G "Ninja" \ cmake -G "Ninja" \
-DCMAKE_BUILD_TYPE=Release \ -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX="./install" \ -DCMAKE_INSTALL_PREFIX="$PWD/install" \
-DIMHEX_USE_DEFAULT_BUILD_SETTINGS=ON \ -DIMHEX_USE_DEFAULT_BUILD_SETTINGS=ON \
.. ..
ninja install ninja install

View File

@@ -1,21 +1,17 @@
#!/usr/bin/env sh #!/usr/bin/env sh
pacman -S $@ --needed \ pacman -S $@ --needed \
cmake \ cmake \
gcc \ gcc \
lld \ lld \
glfw \ glfw \
file \ file \
mbedtls \ mbedtls \
freetype2 \ freetype2 \
dbus \ dbus \
gtk3 \ gtk3 \
curl \ curl \
fmt \ fmt \
yara \ yara \
nlohmann-json \ nlohmann-json \
ninja \ ninja
zlib \
bzip2 \
xz \
zstd

View File

@@ -22,8 +22,4 @@ apt install -y \
libdbus-1-dev \ libdbus-1-dev \
libcurl4-gnutls-dev \ libcurl4-gnutls-dev \
libgtk-3-dev \ libgtk-3-dev \
ninja-build \ ninja-build
zlib1g-dev \
libbz2-dev \
liblzma-dev \
libzstd-dev

View File

@@ -12,8 +12,4 @@ dnf install -y \
glfw-devel \ glfw-devel \
lld \ lld \
mbedtls-devel \ mbedtls-devel \
gtk3-devel \ gtk3-devel
libzstd-devel \
zlib-devel \
bzip2-devel \
xz-devel

View File

@@ -1,20 +1,15 @@
#!/usr/bin/env sh #!/usr/bin/env sh
pacman -S --needed --noconfirm pactoys pacman -S --needed --noconfirm \
pacboy -S --needed --noconfirm \ mingw-w64-x86_64-gcc \
gcc:p \ mingw-w64-x86_64-lld \
lld:p \ mingw-w64-x86_64-cmake \
cmake:p \ mingw-w64-x86_64-ccache \
ccache:p \ mingw-w64-x86_64-glfw \
glfw:p \ mingw-w64-x86_64-file \
file:p \ mingw-w64-x86_64-curl-winssl \
curl-winssl:p \ mingw-w64-x86_64-mbedtls \
mbedtls:p \ mingw-w64-x86_64-freetype \
freetype:p \ mingw-w64-x86_64-dlfcn \
dlfcn:p \ mingw-w64-x86_64-ninja \
ninja:p \ mingw-w64-x86_64-capstone
capstone:p \
zlib:p \
bzip2:p \
xz:p \
zstd:p

View File

@@ -1,173 +0,0 @@
# This base image is also known as "crosscompile". See arm64.crosscompile.Dockerfile
FROM ghcr.io/itrooz/macos-crosscompile:clang17-nosdk as build
ENV MACOSX_DEPLOYMENT_TARGET 12.1
# -- DOWNLOADING STUFF
## Install make
RUN --mount=type=cache,target=/var/lib/apt/lists/ apt update && apt install -y make
## fix environment
### add install_name_tool for cmake command that won't have the right env set (see PostprocessBundle.cmake function postprocess_bundle())
RUN cp /osxcross/build/cctools-port/cctools/misc/install_name_tool /usr/bin/install_name_tool
### a cmake thing wants 'otool' and not '' apparently
RUN cp /osxcross/target/bin/aarch64-apple-darwin23-otool /usr/bin/otool
## Clone glfw
RUN <<EOF
set -xe
if [ "$CUSTOM_GLFW" ]; then
git clone https://github.com/glfw/glfw /mnt/glfw
fi
EOF
RUN --mount=type=cache,target=/cache <<EOF
## Download SDK is missing (it may have been removed from the image)
set -xe
if [ ! -d /osxcross/target/SDK/MacOSX14.0.sdk ]; then
wget https://github.com/joseluisq/macosx-sdks/releases/download/14.0/MacOSX14.0.sdk.tar.xz -O /cache/MacOSX14.0.sdk.tar.xz -nc || true
mkdir -p /osxcross/target/SDK
tar -C /osxcross/target/SDK -xf /cache/MacOSX14.0.sdk.tar.xz
fi
EOF
## Download libmagic
### Clone libmagic
RUN git clone https://github.com/file/file /mnt/file
### Download libmagic dependencies
RUN --mount=type=cache,target=/var/lib/apt/lists/ apt install -y libtool autoconf
# -- DOWNLOADING + BUILDING STUFF
ENV VCPKG_DEFAULT_BINARY_CACHE /cache/vcpkg
RUN --mount=type=cache,target=/cache <<EOF
## Install dependencies with vcpkg
set -xe
mkdir -p $VCPKG_DEFAULT_BINARY_CACHE
vcpkg install --triplet=arm-osx-mytriplet curl
vcpkg install --triplet=arm-osx-mytriplet mbedtls
vcpkg install --triplet=arm-osx-mytriplet freetype
vcpkg install --triplet=arm-osx-mytriplet josuttis-jthread
vcpkg install --triplet=arm-osx-mytriplet zlib
vcpkg install --triplet=arm-osx-mytriplet bzip2
vcpkg install --triplet=arm-osx-mytriplet liblzma
vcpkg install --triplet=arm-osx-mytriplet zstd
EOF
## Install glfw3 dep
ARG CUSTOM_GLFW
RUN --mount=type=cache,target=/cache <<EOF
set -xe
if [ "$CUSTOM_GLFW" ]; then
echo "Flag confirmation: using custom GLFW for software rendering"
else
echo "Flag confirmation: using system GLFW"
vcpkg install --triplet=arm-osx-mytriplet glfw3
fi
EOF
# -- BUILDING STUFF
ARG JOBS 1
ARG BUILD_TYPE Debug
## Build libmagic
RUN --mount=type=cache,target=/cache <<EOF
ccache -zs
set -xe
cd /mnt/file
autoreconf -is
# when cross-compiling, libmagic needs to have an the same version installed in the system.
# So we install it normally first
./configure --prefix /usr
make -j $JOBS install
# Now, we cross-compile it and install it in the libraries folder
CC=/osxcross/target/bin/aarch64-apple-darwin23-clang CXX=/osxcross/target/bin/aarch64-apple-darwin23-clang++ ./configure --prefix /vcpkg/installed/arm-osx-mytriplet --host $OSXCROSS_HOST
make -j $JOBS
make install
ccache -s
EOF
## Patch glfw
COPY --from=imhex /dist/macOS/0001-glfw-SW.patch /tmp
RUN <<EOF
set -xe
if [ "$CUSTOM_GLFW" ]; then
cd /mnt/glfw
git apply /tmp/0001-glfw-SW.patch
fi
EOF
RUN mkdir -p /vcpkg/installed/arm-osx-mytriplet/lib/pkgconfig
RUN mkdir -p /osxcross/target/macports/pkgs/vcpkg/installed/arm-osx-mytriplet/lib/pkgconfig
## Build glfw
RUN --mount=type=cache,target=/cache <<EOF
set -xe
if [ "$CUSTOM_GLFW" ]; then
ccache -zs
cd /mnt/glfw
mkdir build
cd build
CC=o64-gcc CXX=o64-g++ cmake -G "Ninja" \
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
-DBUILD_SHARED_LIBS=ON \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
-DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_INSTALL_PREFIX=/vcpkg/installed/arm-osx-mytriplet \
-DVCPKG_TARGET_TRIPLET=arm-osx-mytriplet -DCMAKE_TOOLCHAIN_FILE=/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/osxcross/target/toolchain.cmake -DCMAKE_OSX_SYSROOT=/osxcross/target/SDK/MacOSX14.0.sdk -DCMAKE_OSX_DEPLOYMENT_TARGET=12.1 \
..
ninja -j $JOBS install
ccache -s
fi
EOF
# Build ImHex
## Copy ImHex
COPY --from=imhex / /mnt/ImHex
## Patch ImHex with hacks
# COPY toolchain.cmake.2 /osxcross/target/toolchain.cmake
# Configure ImHex build
RUN --mount=type=cache,target=/cache --mount=type=cache,target=/mnt/ImHex/build/_deps \
cd /mnt/ImHex && \
# compilers
CC=o64-clang CXX=o64-clang++ OBJC=/osxcross/target/bin/aarch64-apple-darwin23-clang OBJCXX=/osxcross/target/bin/aarch64-apple-darwin23-clang++ \
cmake -G "Ninja" \
`# ccache flags` \
-DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_OBJC_COMPILER_LAUNCHER=ccache -DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
`# MacOS cross-compiling flags` \
-DVCPKG_TARGET_TRIPLET=arm-osx-mytriplet -DCMAKE_TOOLCHAIN_FILE=/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/osxcross/target/toolchain.cmake -DCMAKE_OSX_SYSROOT=/osxcross/target/SDK/MacOSX14.0.sdk -DCMAKE_OSX_DEPLOYMENT_TARGET=12.1 \
`# Override compilers for code generators` \
-DNATIVE_CMAKE_C_COMPILER=/usr/bin/clang -DNATIVE_CMAKE_CXX_COMPILER=/usr/bin/clang++ \
`# Normal ImHex flags` \
-DIMHEX_GENERATE_PACKAGE=ON -DCMAKE_BUILD_TYPE=$BUILD_TYPE \
`# other flags` \
-DIMHEX_STRICT_WARNINGS=OFF \
-DCMAKE_INSTALL_PREFIX=/mnt/ImHex/build/install \
-B build
## Build ImHex
RUN --mount=type=cache,target=/cache --mount=type=cache,target=/mnt/ImHex/build/_deps <<EOF
ccache -zs
set -xe
cd /mnt/ImHex
cmake --build build --parallel $JOBS --target install
ccache -s
EOF
FROM scratch
COPY --from=build /mnt/ImHex/build/install/imhex.app imhex.app

View File

@@ -1,96 +0,0 @@
# 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
FROM ubuntu:22.04
ENV PATH $PATH:/osxcross/target/bin
ENV LD_LIBRARY_PATH /osxcross/target/lib
ENV OSXCROSS_SDK /osxcross/target/SDK/MacOSX14.0.sdk
ENV OSXCROSS_TARGET darwin23
ENV OSXCROSS_TARGET_DIR /osxcross/target
ENV OSXCROSS_HOST aarch64-apple-darwin23
# -- DOWNLOADING STUFF
# Install common stuff
RUN --mount=type=cache,target=/var/lib/apt/lists/ export DEBIAN_FRONTEND=noninteractive &&\
export TZ=Etc/UTC &&\
dpkg --add-architecture i386 &&\
apt update &&\
apt -y install lsb-release build-essential python3 python3-pip git wget zip unzip pkg-config curl ninja-build software-properties-common gnupg libssl-dev ccache
# Install clang 17
RUN --mount=type=cache,target=/var/lib/apt/lists/ wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh && ./llvm.sh 17 &&\
ln -s /usr/bin/clang-17 /usr/bin/clang &&\
ln -s /usr/bin/clang++-17 /usr/bin/clang++
# Install vcpkg
RUN cd / &&\
git clone --depth 1 https://github.com/Microsoft/vcpkg.git vcpkg &&\
cd /vcpkg &&\
./bootstrap-vcpkg.sh -disableMetrics &&\
ln -s /vcpkg/vcpkg /usr/bin/ &&\
vcpkg install vcpkg-cmake &&\
ln -s /vcpkg/downloads/tools/cmake-*/cmake-*/bin/cmake /usr/bin/
RUN --mount=type=cache,target=/cache <<EOF
## Clone osxcross
set -xe
git clone https://github.com/tpoechtrager/osxcross /cache/osxcross || true
cd /cache/osxcross
git pull
cp -r /cache/osxcross /osxcross
EOF
RUN --mount=type=cache,target=/cache <<EOF
## Download SDK
set -xe
wget https://github.com/joseluisq/macosx-sdks/releases/download/14.0/MacOSX14.0.sdk.tar.xz -O /cache/MacOSX14.0.sdk.tar.xz -nc || true
cp /cache/MacOSX14.0.sdk.tar.xz /osxcross/tarballs
EOF
# Init stuff
## setup ccache dir
ENV CCACHE_DIR /cache/ccache
# Install triplet file
COPY arm-osx-mytriplet.cmake /vcpkg/triplets/community
# -- BUILDING STUFF
ARG JOBS 1
# Install osxcross
## Build cross-compiler clang-17
RUN --mount=type=cache,target=/cache <<EOF
set -xe
ccache -zs
cd /osxcross
UNATTENDED=1 CC=/usr/lib/ccache/clang-17 CXX=/usr/lib/ccache/clang++-17 ./build.sh
ccache -s
EOF
# Not needed, because we don't use gcc for cross-compiling anymore
# ## Install dependencies for gcc-13
# RUN apt install -y gcc g++ zlib1g-dev libmpc-dev libmpfr-dev libgmp-dev
# ## Build cross-compiler gcc-13
# RUN --mount=type=cache,target=/cache <<EOF
# set -xe
# ccache -zs
# cd /osxcross
# UNATTENDED=1 CC=/usr/lib/ccache/gcc CXX=/usr/lib/ccache/g++ GCC_VERSION=13.2.0 ./build_gcc.sh
# ccache -s
# EOF
ARG DELETE_SDK=1
RUN <<EOF
# Conditionally delete the SDK from the image
set -xe
if [ "$DELETE_SDK" ]; then
rm -r /osxcross/target/SDK
echo "Deleted the SDK from the image"
else
echo "NOT deleting the SDK from the image"
fi
EOF

4
dist/macOS/macos_arm_toolchain.cmake vendored Normal file
View File

@@ -0,0 +1,4 @@
set(CMAKE_SYSTEM_NAME Darwin)
set(CMAKE_SYSTEM_PROCESSOR arm64)
set(CMAKE_OSX_ARCHITECTURES arm64 CACHE INTERNAL "" FORCE)
SET(CMAKE_OSX_SYSROOT macosx CACHE INTERNAL "" FORCE)

6
dist/msys2/PKGBUILD vendored
View File

@@ -16,11 +16,7 @@ makedepends=("${MINGW_PACKAGE_PREFIX}-gcc"
"${MINGW_PACKAGE_PREFIX}-file" "${MINGW_PACKAGE_PREFIX}-file"
"${MINGW_PACKAGE_PREFIX}-mbedtls" "${MINGW_PACKAGE_PREFIX}-mbedtls"
"${MINGW_PACKAGE_PREFIX}-polly" "${MINGW_PACKAGE_PREFIX}-polly"
"${MINGW_PACKAGE_PREFIX}-freetype" "${MINGW_PACKAGE_PREFIX}-freetype")
"${MINGW_PACKAGE_PREFIX}-zlib"
"${MINGW_PACKAGE_PREFIX}-bzip2"
"${MINGW_PACKAGE_PREFIX}-xz"
"${MINGW_PACKAGE_PREFIX}-zstd")
source=() source=()
sha256sums=() sha256sums=()

View File

@@ -12,10 +12,49 @@ finish-args:
- --device=all - --device=all
modules: modules:
- name: imhex - name: libiconv
buildsystem: cmake sources:
- type: archive
url: https://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.16.tar.gz
sha256: e6a1b1b589654277ee790cce3734f07876ac4ccfaecbee8afa0b649cf529cc04
- name: glfw
buildsystem: cmake-ninja
builddir: true
config-opts: config-opts:
- -DCMAKE_BUILD_TYPE=RelWithDebInfo - -DCMAKE_BUILD_TYPE=RelWithDebInfo
- -DBUILD_SHARED_LIBS:BOOL=ON
sources:
- type: archive
url: https://github.com/glfw/glfw/releases/download/3.3.2/glfw-3.3.2.zip
sha256: 08a33a512f29d7dbf78eab39bd7858576adcc95228c9efe8e4bc5f0f3261efc7
cleanup:
- /include
- /lib/pkgconfig
- name: mbedtls
buildsystem: cmake-ninja
config-opts:
- -DCMAKE_C_FLAGS=-fPIC
sources:
- type: archive
url: https://github.com/ARMmbed/mbedtls/archive/refs/tags/v2.27.0.tar.gz
sha256: 2a07856e541f0e5f6eaee4f78018c52f25bd244ed76f9020dea54a8b02cac6ea
- name: nlohmann-json
buildsystem: cmake-ninja
builddir: true
config-opts:
- -DCMAKE_BUILD_TYPE=RelWithDebInfo
- -DBUILD_TESTING=OFF
sources:
- type: archive
url: https://github.com/nlohmann/json/archive/v3.9.1.tar.gz
sha256: 4cf0df69731494668bdd6460ed8cb269b68de9c19ad8c27abc24cd72605b2d5b
- name: imhex
buildsystem: cmake
sources: sources:
- type: git - type: git

26
dist/rpm/imhex.spec vendored
View File

@@ -1,5 +1,5 @@
Name: imhex Name: imhex
Version: VERSION Version: 1.26.2
Release: 0%{?dist} Release: 0%{?dist}
Summary: A hex editor for reverse engineers and programmers Summary: A hex editor for reverse engineers and programmers
@@ -26,11 +26,7 @@ BuildRequires: llvm-devel
BuildRequires: mbedtls-devel BuildRequires: mbedtls-devel
BuildRequires: yara-devel BuildRequires: yara-devel
BuildRequires: nativefiledialog-extended-devel BuildRequires: nativefiledialog-extended-devel
BuildRequires: dotnet-sdk-8.0 BuildRequires: dotnet-sdk-7.0
BuildRequires: libzstd-devel
BuildRequires: zlib-devel
BuildRequires: bzip2-devel
BuildRequires: xz-devel
%if 0%{?rhel} %if 0%{?rhel}
BuildRequires: gcc-toolset-12 BuildRequires: gcc-toolset-12
%endif %endif
@@ -40,6 +36,7 @@ Provides: bundled(capstone) = 5.0-rc2
Provides: bundled(imgui) Provides: bundled(imgui)
Provides: bundled(libromfs) Provides: bundled(libromfs)
Provides: bundled(microtar) Provides: bundled(microtar)
Provides: bundled(libpl)
Provides: bundled(xdgpp) Provides: bundled(xdgpp)
# ftbfs on these arches. armv7hl might compile when capstone 5.x # ftbfs on these arches. armv7hl might compile when capstone 5.x
@@ -64,7 +61,7 @@ same time ImHex is completely free and open source under the GPLv2 language.
%prep %prep
%autosetup -n ImHex %autosetup -n ImHex
# remove bundled libs we aren't using # remove bundled libs we aren't using
rm -rf lib/third_party/{fmt,nlohmann_json,yara} rm -rf lib/external/{curl,fmt,llvm,nlohmann_json,yara}
%build %build
%if 0%{?rhel} %if 0%{?rhel}
@@ -95,6 +92,10 @@ CXXFLAGS+=" -std=gnu++2b"
%set_build_flags %set_build_flags
CXXFLAGS+=" -std=gnu++2b" CXXFLAGS+=" -std=gnu++2b"
%endif %endif
# build binaries required for tests
%cmake_build --target unit_tests
%ctest --exclude-regex '(Helpers/StoreAPI|Helpers/TipsAPI|Helpers/ContentAPI)'
# Helpers/*API exclude tests that require network access
%install %install
@@ -108,18 +109,17 @@ rm -f %{buildroot}%{_metainfodir}/net.werwolv.%{name}.appdata.xml
appstream-util validate-relax --nonet %{buildroot}%{_metainfodir}/net.werwolv.%{name}.metainfo.xml appstream-util validate-relax --nonet %{buildroot}%{_metainfodir}/net.werwolv.%{name}.metainfo.xml
# install licenses # install licenses
cp -a lib/third_party/nativefiledialog/LICENSE %{buildroot}%{_datadir}/licenses/%{name}/nativefiledialog-LICENSE cp -a lib/external/nativefiledialog/LICENSE %{buildroot}%{_datadir}/licenses/%{name}/nativefiledialog-LICENSE
cp -a lib/third_party/capstone/LICENSE.TXT %{buildroot}%{_datadir}/licenses/%{name}/capstone-LICENSE cp -a lib/external/capstone/LICENSE.TXT %{buildroot}%{_datadir}/licenses/%{name}/capstone-LICENSE
cp -a lib/third_party/capstone/suite/regress/LICENSE %{buildroot}%{_datadir}/licenses/%{name}/capstone-regress-LICENSE cp -a lib/external/capstone/suite/regress/LICENSE %{buildroot}%{_datadir}/licenses/%{name}/capstone-regress-LICENSE
cp -a lib/third_party/microtar/LICENSE %{buildroot}%{_datadir}/licenses/%{name}/microtar-LICENSE cp -a lib/external/microtar/LICENSE %{buildroot}%{_datadir}/licenses/%{name}/microtar-LICENSE
cp -a lib/third_party/xdgpp/LICENSE %{buildroot}%{_datadir}/licenses/%{name}/xdgpp-LICENSE cp -a lib/external/xdgpp/LICENSE %{buildroot}%{_datadir}/licenses/%{name}/xdgpp-LICENSE
%files %files
%license %{_datadir}/licenses/%{name}/ %license %{_datadir}/licenses/%{name}/
%doc README.md %doc README.md
%{_bindir}/imhex %{_bindir}/imhex
%{_bindir}/imhex-updater
%{_datadir}/pixmaps/%{name}.png %{_datadir}/pixmaps/%{name}.png
%{_datadir}/applications/%{name}.desktop %{_datadir}/applications/%{name}.desktop
%{_libdir}/libimhex.so* %{_libdir}/libimhex.so*

19
dist/web/Dockerfile vendored
View File

@@ -1,4 +1,4 @@
FROM emscripten/emsdk:3.1.51 as build FROM emscripten/emsdk:latest as build
# Used to invalidate layer cache but not mount cache # Used to invalidate layer cache but not mount cache
# See https://github.com/moby/moby/issues/41715#issuecomment-733976493 # See https://github.com/moby/moby/issues/41715#issuecomment-733976493
@@ -37,10 +37,6 @@ mkdir -p $VCPKG_DEFAULT_BINARY_CACHE
/vcpkg/vcpkg install --triplet=wasm32-emscripten libmagic /vcpkg/vcpkg install --triplet=wasm32-emscripten libmagic
/vcpkg/vcpkg install --triplet=wasm32-emscripten freetype /vcpkg/vcpkg install --triplet=wasm32-emscripten freetype
/vcpkg/vcpkg install --triplet=wasm32-emscripten mbedtls /vcpkg/vcpkg install --triplet=wasm32-emscripten mbedtls
/vcpkg/vcpkg install --triplet=wasm32-emscripten zlib
/vcpkg/vcpkg install --triplet=wasm32-emscripten bzip2
/vcpkg/vcpkg install --triplet=wasm32-emscripten liblzma
/vcpkg/vcpkg install --triplet=wasm32-emscripten zstd
EOF EOF
# Build ImHex # Build ImHex
@@ -58,7 +54,6 @@ ccache -zs
cmake /imhex \ cmake /imhex \
-DIMHEX_OFFLINE_BUILD=ON \ -DIMHEX_OFFLINE_BUILD=ON \
-DIMHEX_STATIC_LINK_PLUGINS=ON \ -DIMHEX_STATIC_LINK_PLUGINS=ON \
-DIMHEX_EXCLUDE_PLUGINS="script_loader" \
-DNATIVE_CMAKE_C_COMPILER=gcc \ -DNATIVE_CMAKE_C_COMPILER=gcc \
-DNATIVE_CMAKE_CXX_COMPILER=g++ \ -DNATIVE_CMAKE_CXX_COMPILER=g++ \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \ -DCMAKE_C_COMPILER_LAUNCHER=ccache \
@@ -73,15 +68,10 @@ cp /imhex/dist/web/source/* /build
ccache -s ccache -s
EOF EOF
# Create a file dedicated to store wasm size, because I know no way to get the wasm content length if the web server uses compression FROM scratch
# 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
COPY --from=build [ \ COPY --from=build [ \
# ImHex \ # ImHex \
"/build/imhex.wasm", \ "/build/imhex.wasm", \
"/build/imhex.wasm.size", \
"/build/imhex.js", \ "/build/imhex.js", \
"/build/imhex.worker.js", \ "/build/imhex.worker.js", \
\ \
@@ -93,12 +83,7 @@ COPY --from=build [ \
"/build/favicon.ico", \ "/build/favicon.ico", \
"/build/icon.png", \ "/build/icon.png", \
"/build/manifest.json", \ "/build/manifest.json", \
"/build/robots.txt", \
"/build/sitemap.xml", \
\ \
# Destination \ # Destination \
"./" \ "./" \
] ]
FROM nginx
COPY --from=raw . /usr/share/nginx/html

10
dist/web/compose.yml vendored
View File

@@ -1,10 +0,0 @@
# docker compose -f dist/web/compose.yml up --build
version: '3'
services:
imhex_web:
image: imhex_web:latest
build:
context: ../../ # ImHex folder
dockerfile: ./dist/web/Dockerfile
ports:
- 8080:80

View File

@@ -2,12 +2,10 @@
extern "C" void forceLinkPlugin_@IMHEX_PLUGIN_NAME@(); extern "C" void forceLinkPlugin_@IMHEX_PLUGIN_NAME@();
namespace {
struct StaticLoad { struct StaticLoad {
StaticLoad() { StaticLoad() {
forceLinkPlugin_@IMHEX_PLUGIN_NAME@(); forceLinkPlugin_@IMHEX_PLUGIN_NAME@();
} }
}; };
}
static StaticLoad staticLoad; static StaticLoad staticLoad;

View File

@@ -1,22 +1,23 @@
<!doctype html> <!doctype html>
<html lang="en-us"> <html lang="en-us">
<head> <head>
<title>ImHex Web - Free Online Hex Editor for Reverse Engineers</title> <link rel="manifest" href="manifest.json" />
<meta charset="utf-8">
<link rel="manifest" href="manifest.json">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<!-- Primary Meta Tags --> <!-- Primary Meta Tags -->
<title>ImHex Web - Online Hex Editor</title>
<meta name="title" content="ImHex"> <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."> <meta name="description" content="A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.">
<link rel="icon" type="image/x-icon" href="favicon.ico"> <link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="apple-touch-icon" href="icon.png">
<!-- Open Graph / Facebook --> <!-- Open Graph / Facebook -->
<meta property="og:type" content="website"> <meta property="og:type" content="website">
<meta property="og:url" content="https://imhex.werwolv.net/"> <meta property="og:url" content="https://imhex.werwolv.net/">
<meta property="og:title" content="ImHex Web - Online Hex Editor"> <meta property="og:title" content="ImHex Web - Online Hex Editor">
<meta property="og:description">
<meta name="description" content="A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.">
<meta property="og:image" content="https://imhex.werwolv.net/assets/splash_wasm.png"> <meta property="og:image" content="https://imhex.werwolv.net/assets/splash_wasm.png">
<!-- Twitter --> <!-- Twitter -->
@@ -27,7 +28,9 @@
content="A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM."> content="A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.">
<meta property="twitter:image" content="https://imhex.werwolv.net/assets/splash_wasm.png"> <meta property="twitter:image" content="https://imhex.werwolv.net/assets/splash_wasm.png">
<link rel="stylesheet" type="text/css" href="style.css"> <meta name="viewport" content="width=device-width">
<link rel="stylesheet" type="text/css" href="style.css" />
<script type="application/ld+json"> <script type="application/ld+json">
{ {
@@ -57,48 +60,15 @@
} }
</script> </script>
<title>ImHex Web</title>
<script src="enable-threads.js"></script> <script src="enable-threads.js"></script>
<link rel="stylesheet" href="style.css"> <link rel="stylesheet" href="style.css">
</head> </head>
<body> <body>
<div id="loading" class="centered"> <p id="loading_text">ImHex is loading...</p>
<img src="https://raw.githubusercontent.com/WerWolv/ImHex/master/plugins/builtin/romfs/assets/dark/banner.png" id="logo" alt="ImHex Logo"> <canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
<h1>A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.</h1>
<h2>Available both natively and on the web</h2>
<h5>ImHex runs directly in your web browser with the help of Emscripten and WebAssembly.</h5>
<div style="height: 50%"> <script type="text/javascript" src="wasm-config.js"></script>
<div style="height: 30%"> </div> <script async type="text/javascript" src="imhex.js"></script>
<h2 id="not_working">
Not loading in your Browser? <a href="https://imhex.werwolv.net">Try the native version</a>
</h2>
<div class="progress-bar-container">
<div class="progress progress-moved">
<div class="progress-bar" id="progress-bar-content">
</div>
</div>
</div>
</div>
<div class="loading_ripple">
<div class="lds-ripple"><div></div><div></div></div>
</div>
<div style="height: 10%">
</div>
<div class="footer">
<a href="https://imhex.werwolv.net">Homepage</a>
<p>Made with ♥️ by the ImHex Team</p>
<a href="https://github.com/WerWolv/ImHex">GitHub</a>
</div>
</div>
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
<script src="wasm-config.js"></script>
<script async src="imhex.js"></script>
</body> </body>
</html> </html>

View File

@@ -1,4 +0,0 @@
User-agent: *
Allow: /
Sitemap: https://imhex.werwolv.net/sitemap.xml

View File

@@ -1,62 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset
xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
<url>
<loc>https://web.imhex.werwolv.net/</loc>
<lastmod>2024-01-02T11:44:00+00:00</lastmod>
<priority>1.00</priority>
</url>
<url>
<title>English</title>
<loc>https://web.imhex.werwolv.net?lang=en-US</loc>
<lastmod>2024-01-02T11:44:00+00:00</lastmod>
<priority>1.00</priority>
</url>
<url>
<title>Deutsch</title>
<loc>https://web.imhex.werwolv.net?lang=de-DE</loc>
<lastmod>2024-01-02T11:44:00+00:00</lastmod>
<priority>1.00</priority>
</url>
<url>
<title>Português</title>
<loc>https://web.imhex.werwolv.net?lang=pt-BR</loc>
<lastmod>2024-01-02T11:44:00+00:00</lastmod>
</url>
<url>
<title>中国</title>
<loc>https://web.imhex.werwolv.net?lang=zh-CN</loc>
<lastmod>2024-01-02T11:44:00+00:00</lastmod>
</url>
<url>
<title>國語</title>
<loc>https://web.imhex.werwolv.net?lang=zh-TW</loc>
<lastmod>2024-01-02T11:44:00+00:00</lastmod>
</url>
<url>
<title>日本語</title>
<loc>https://web.imhex.werwolv.net?lang=ja-JP</loc>
<lastmod>2024-01-02T11:44:00+00:00</lastmod>
</url>
<url>
<title>한국어</title>
<loc>https://web.imhex.werwolv.net?lang=ko-KR</loc>
<lastmod>2024-01-02T11:44:00+00:00</lastmod>
</url>
<url>
<title>Español</title>
<loc>https://web.imhex.werwolv.net?lang=es-ES</loc>
<lastmod>2024-01-02T11:44:00+00:00</lastmod>
</url>
<url>
<title>Italiano</title>
<loc>https://web.imhex.werwolv.net?lang=it-IT</loc>
<lastmod>2024-01-02T11:44:00+00:00</lastmod>
</url>
</urlset>

View File

@@ -1,6 +1,6 @@
html, body { html, body {
height: 100%; height: 100%;
margin: 0; margin: 0px;
user-select: none; user-select: none;
} }
@@ -16,162 +16,21 @@ body {
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
display: none; display: none;
border: 0 none; border: 0px none;
image-rendering: smooth;
} }
h1, h2, h5 { .canvas_full_screen {
color: #F0F0F0;
font-size: 20px;
font-family: monospace;
width: 100%;
text-align: center;
margin-top: 60px;
margin-bottom: 10px;
}
h2 {
margin-top: 15px;
font-size: 17px;
}
h5 {
margin-top: 0;
font-size: 17px;
}
#not_working {
opacity: 0;
}
#not_working.visible {
opacity: 1;
transition: opacity 2s ease;
}
a {
color: #7893ff;
text-decoration: none;
}
a:hover {
text-shadow: #3a4677 0 0 10px;
}
.footer {
width: 100%;
height: 20px;
position: absolute;
bottom: 0;
text-align: center;
color: #F0F0F0;
background-color: #0A0A0A;
padding: 10px;
font-family: monospace;
font-size: 15px;
display: flex;
justify-content: center;
align-items: center;
flex-direction: row;
gap: 10%;
}
.centered {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100%; width: 100%;
height: 100%; height: 100%;
}
.lds-ripple {
display: inline-block;
position: relative;
width: 80px;
height: 80px;
}
.lds-ripple div {
position: absolute; position: absolute;
border: 4px solid #fff; top: 0;
opacity: 1; left: 0;
border-radius: 50%;
animation: lds-ripple 1s cubic-bezier(0, 0.2, 0.8, 1) infinite;
}
.lds-ripple div:nth-child(2) {
animation-delay: -0.5s;
}
@keyframes lds-ripple {
0% {
top: 36px;
left: 36px;
width: 0;
height: 0;
opacity: 0;
}
4.9% {
top: 36px;
left: 36px;
width: 0;
height: 0;
opacity: 0;
}
5% {
top: 36px;
left: 36px;
width: 0;
height: 0;
opacity: 1;
}
100% {
top: 0;
left: 0;
width: 72px;
height: 72px;
opacity: 0;
}
} }
#loading_text {
:root { color: #F0F0F0;
--progress: 25%; font-size: 30px;
} font-family: monospace;
width: 100%;
.progress-bar-container {
margin: 100px auto;
width: 600px;
text-align: center; text-align: center;
} }
.progress {
padding: 6px;
border-radius: 30px;
background: rgba(0, 0, 0, 0.25);
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.25),
0 1px rgba(255, 255, 255, 0.08);
}
.progress-bar {
color: rgba(240, 240, 240, 0.9);
height: 18px;
border-radius: 30px;
font-size: 13px;
font-family: monospace;
font-weight: bold;
text-wrap: avoid;
white-space: nowrap;
overflow: hidden;
background-image: linear-gradient(
to bottom,
rgba(255, 255, 255, 0.2),
rgba(255, 255, 255, 0.0)
);
}
.progress-moved .progress-bar {
width: var(--progress);
background-color: #3864cb;
}

View File

@@ -1,67 +1,3 @@
let wasmSize = null;
// See comment in dist/web/Dockerfile about imhex.wasm.size
fetch("imhex.wasm.size").then(async (resp) => {
wasmSize = parseInt((await resp.text()).trim());
console.log(`Real WASM binary size is ${wasmSize} bytes`);
});
// Monkeypatch WebAssembly to have a progress bar
// inspired from: https://github.com/WordPress/wordpress-playground/pull/46 (but had to be modified)
function monkeyPatch(progressFun) {
const _instantiateStreaming = WebAssembly.instantiateStreaming;
WebAssembly.instantiateStreaming = (response, ...args) => {
// Do not collect wasm content length here see above
const file = response.url.substring(
new URL(response.url).origin.length + 1
);
const reportingResponse = new Response(
new ReadableStream(
{
async start(controller) {
const reader = response.clone().body.getReader();
let loaded = 0;
for (; ;) {
const { done, value } = await reader.read();
if (done) {
if(wasmSize) progressFun(file, wasmSize);
break;
}
loaded += value.byteLength;
progressFun(file, loaded);
controller.enqueue(value);
}
controller.close();
}
},
{
status: response.status,
statusText: response.statusText
}
)
);
for (const pair of response.headers.entries()) {
reportingResponse.headers.set(pair[0], pair[1]);
}
return _instantiateStreaming(reportingResponse, ...args);
}
}
monkeyPatch((file, done) => {
if (!wasmSize) return;
if (done > wasmSize) {
console.warn(`Downloaded binary size ${done} is larger than expected WASM size ${wasmSize}`);
return;
}
const percent = ((done / wasmSize) * 100).toFixed(0);
const mibNow = (done / 1024**2).toFixed(1);
const mibTotal = (wasmSize / 1024**2).toFixed(1);
let root = document.querySelector(':root');
root.style.setProperty("--progress", `${percent}%`)
document.getElementById("progress-bar-content").innerHTML = `${percent}% &nbsp;[${mibNow} MiB / ${mibTotal} MiB]`;
});
function glfwSetCursorCustom(wnd, shape) { function glfwSetCursorCustom(wnd, shape) {
let body = document.getElementsByTagName("body")[0] let body = document.getElementsByTagName("body")[0]
switch (shape) { switch (shape) {
@@ -94,22 +30,16 @@ function glfwCreateStandardCursorCustom(shape) {
return shape return shape
} }
var notWorkingTimer = setTimeout(() => {
document.getElementById("not_working").classList.add("visible")
}, 5000);
var Module = { var Module = {
preRun: [], preRun: [],
postRun: [], postRun: [],
onRuntimeInitialized: function() { onRuntimeInitialized: function() {
// Triggered when the wasm module is loaded and ready to use. // Triggered when the wasm module is loaded and ready to use.
document.getElementById("loading").style.display = "none" document.getElementById("loading_text").style.display = "none"
document.getElementById("canvas").style.display = "initial" document.getElementById("canvas").style.display = "initial"
clearTimeout(notWorkingTimer);
}, },
print: (function() { })(), print: (function() { })(),
printErr: function(text) { }, printErr: function(text) { },
canvas: (function() { canvas: (function() {
let canvas = document.getElementById('canvas'); let canvas = document.getElementById('canvas');
// As a default initial behavior, pop up an alert when webgl context is lost. To make your // As a default initial behavior, pop up an alert when webgl context is lost. To make your
@@ -121,25 +51,14 @@ var Module = {
})(), })(),
setStatus: function(text) { }, setStatus: function(text) { },
totalDependencies: 0, totalDependencies: 0,
monitorRunDependencies: function(left) { monitorRunDependencies: function(left) { },
},
instantiateWasm: function(imports, successCallback) { instantiateWasm: function(imports, successCallback) {
imports.env.glfwSetCursor = glfwSetCursorCustom imports.env.glfwSetCursor = glfwSetCursorCustom
imports.env.glfwCreateStandardCursor = glfwCreateStandardCursorCustom imports.env.glfwCreateStandardCursor = glfwCreateStandardCursorCustom
instantiateAsync(wasmBinary, wasmBinaryFile, imports, (result) => { instantiateAsync(wasmBinary, wasmBinaryFile, imports, (result) => successCallback(result.instance, result.module));
successCallback(result.instance, result.module) }
});
},
arguments: []
}; };
// Handle passing arguments to the wasm module
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
if (urlParams.has("lang")) {
Module["arguments"].push("--language");
Module["arguments"].push(urlParams.get("lang"));
}
window.addEventListener('resize', js_resizeCanvas, false); window.addEventListener('resize', js_resizeCanvas, false);
function js_resizeCanvas() { function js_resizeCanvas() {
@@ -148,10 +67,4 @@ function js_resizeCanvas() {
canvas.height = Math.min(document.documentElement.clientHeight, window.innerHeight || 0); canvas.height = Math.min(document.documentElement.clientHeight, window.innerHeight || 0);
canvas.classList.add("canvas_full_screen") canvas.classList.add("canvas_full_screen")
if (GLFW.active && GLFW.active.windowPosFunc) {
getWasmTableEntry(GLFW.active.windowPosFunc)(GLFW.active.id, GLFW.active.x, GLFW.active.y);
}
GLFW.onWindowSizeChanged();
} }

1
lib/external/fmt vendored Submodule

Submodule lib/external/fmt added at f918289363

40
lib/external/imgui/CMakeLists.txt vendored Normal file
View File

@@ -0,0 +1,40 @@
cmake_minimum_required(VERSION 3.16)
project(imgui)
set(CMAKE_CXX_STANDARD 17)
find_package(PkgConfig REQUIRED)
find_package(Freetype REQUIRED)
find_package(OpenGL REQUIRED)
pkg_search_module(GLFW REQUIRED glfw3)
add_library(imgui OBJECT
source/imgui.cpp
source/imgui_demo.cpp
source/imgui_draw.cpp
include/misc/freetype/imgui_freetype.cpp # TODO move source and includes in the same directory
source/imgui_impl_glfw.cpp
source/imgui_impl_opengl3.cpp
source/imgui_tables.cpp
source/imgui_widgets.cpp
source/TextEditor.cpp
source/imnodes.cpp
source/implot.cpp
source/implot_items.cpp
source/implot_demo.cpp
source/fonts/fontawesome_font.c
source/fonts/codicons_font.c
source/fonts/unifont_font.c
)
target_compile_definitions(imgui PUBLIC IMGUI_IMPL_OPENGL_LOADER_GLAD)
target_compile_definitions(imgui PUBLIC IMGUI_USER_CONFIG="imgui_config.h")
target_compile_options(imgui PRIVATE -Wno-unknown-warning-option)
target_include_directories(imgui PUBLIC include ${FREETYPE_INCLUDE_DIRS} ${GLFW_INCLUDE_DIRS} ${OpenGL_INCLUDE_DIRS})
target_link_directories(imgui PUBLIC ${GLFW_LIBRARY_DIRS} ${OpenGL_LIBRARY_DIRS})
target_link_libraries(imgui PUBLIC Freetype::Freetype ${GLFW_LIBRARIES} ${OPENGL_LIBRARIES})

View File

@@ -25,11 +25,8 @@ public:
Identifier, Identifier,
KnownIdentifier, KnownIdentifier,
PreprocIdentifier, PreprocIdentifier,
GlobalDocComment,
DocComment,
Comment, Comment,
MultiLineComment, MultiLineComment,
PreprocessorDeactivated,
Background, Background,
Cursor, Cursor,
Selection, Selection,
@@ -143,12 +140,9 @@ public:
bool mComment : 1; bool mComment : 1;
bool mMultiLineComment : 1; bool mMultiLineComment : 1;
bool mPreprocessor : 1; bool mPreprocessor : 1;
bool mDocComment : 1;
bool mGlobalDocComment : 1;
bool mDeactivated : 1;
Glyph(Char aChar, PaletteIndex aColorIndex) : mChar(aChar), mColorIndex(aColorIndex), mComment(false), Glyph(Char aChar, PaletteIndex aColorIndex) : mChar(aChar), mColorIndex(aColorIndex),
mMultiLineComment(false), mPreprocessor(false), mDocComment(false), mGlobalDocComment(false), mDeactivated(false) {} mComment(false), mMultiLineComment(false), mPreprocessor(false) {}
}; };
typedef std::vector<Glyph> Line; typedef std::vector<Glyph> Line;
@@ -164,7 +158,7 @@ public:
Keywords mKeywords; Keywords mKeywords;
Identifiers mIdentifiers; Identifiers mIdentifiers;
Identifiers mPreprocIdentifiers; Identifiers mPreprocIdentifiers;
std::string mCommentStart, mCommentEnd, mSingleLineComment, mGlobalDocComment, mDocComment; std::string mCommentStart, mCommentEnd, mSingleLineComment;
char mPreprocChar; char mPreprocChar;
bool mAutoIndentation; bool mAutoIndentation;
@@ -209,10 +203,7 @@ public:
std::string GetSelectedText() const; std::string GetSelectedText() const;
std::string GetCurrentLineText()const; std::string GetCurrentLineText()const;
class FindReplaceHandler;
public:
FindReplaceHandler *GetFindReplaceHandler() { return &mFindReplaceHandler; }
int GetTotalLines() const { return (int)mLines.size(); } int GetTotalLines() const { return (int)mLines.size(); }
bool IsOverwrite() const { return mOverwrite; } bool IsOverwrite() const { return mOverwrite; }
@@ -269,8 +260,6 @@ public:
void Paste(); void Paste();
void Delete(); void Delete();
ImVec2 &GetCharAdvance() { return mCharAdvance; }
bool CanUndo() const; bool CanUndo() const;
bool CanRedo() const; bool CanRedo() const;
void Undo(int aSteps = 1); void Undo(int aSteps = 1);
@@ -290,75 +279,6 @@ private:
Coordinates mCursorPosition; Coordinates mCursorPosition;
}; };
public:
class FindReplaceHandler {
public:
FindReplaceHandler();
typedef std::vector<EditorState> Matches;
Matches &GetMatches() { return mMatches; }
bool FindNext(TextEditor *editor,bool wrapAround);
unsigned FindMatch(TextEditor *editor,bool isNex);
bool Replace(TextEditor *editor,bool right);
bool ReplaceAll(TextEditor *editor);
std::string &GetFindWord() { return mFindWord; }
void SetFindWord(TextEditor *editor, const std::string &aFindWord) {
if (aFindWord != mFindWord) {
FindAllMatches(editor, aFindWord);
mFindWord = aFindWord;
}
}
std::string &GetReplaceWord() { return mReplaceWord; }
void SetReplaceWord(const std::string &aReplaceWord) { mReplaceWord = aReplaceWord; }
void SelectFound(TextEditor *editor, int found);
void FindAllMatches(TextEditor *editor,std::string findWord);
unsigned FindPosition( TextEditor *editor, Coordinates pos, bool isNext);
bool GetMatchCase() const { return mMatchCase; }
void SetMatchCase(TextEditor *editor, bool matchCase) {
if (matchCase != mMatchCase) {
mMatchCase = matchCase;
mOptionsChanged = true;
FindAllMatches(editor, mFindWord);
}
}
bool GetWholeWord() const { return mWholeWord; }
void SetWholeWord(TextEditor *editor, bool wholeWord) {
if (wholeWord != mWholeWord) {
mWholeWord = wholeWord;
mOptionsChanged = true;
FindAllMatches(editor, mFindWord);
}
}
bool GetFindRegEx() const { return mFindRegEx; }
void SetFindRegEx(TextEditor *editor, bool findRegEx) {
if (findRegEx != mFindRegEx) {
mFindRegEx = findRegEx;
mOptionsChanged = true;
FindAllMatches(editor, mFindWord);
}
}
void resetMatches() {
mMatches.clear();
mFindWord = "";
}
void SetFindWindowPos(const ImVec2 &pos) { mFindWindowPos = pos; }
void SetFindWindowSize(const ImVec2 &size) { mFindWindowSize = size; }
ImVec2 GetFindWindowPos() const { return mFindWindowPos; }
ImVec2 GetFindWindowSize() const { return mFindWindowSize; }
private:
std::string mFindWord;
std::string mReplaceWord;
bool mMatchCase;
bool mWholeWord;
bool mFindRegEx;
bool mOptionsChanged;
Matches mMatches;
ImVec2 mFindWindowPos;
ImVec2 mFindWindowSize;
};
FindReplaceHandler mFindReplaceHandler;
private:
class UndoRecord class UndoRecord
{ {
public: public:
@@ -415,8 +335,6 @@ private:
int GetCharacterIndex(const Coordinates& aCoordinates) const; int GetCharacterIndex(const Coordinates& aCoordinates) const;
int GetCharacterColumn(int aLine, int aIndex) const; int GetCharacterColumn(int aLine, int aIndex) const;
int GetLineCharacterCount(int aLine) const; int GetLineCharacterCount(int aLine) const;
unsigned long long GetLineByteCount(int aLine) const;
int GetStringCharacterCount(std::string str) const;
int GetLineMaxColumn(int aLine) const; int GetLineMaxColumn(int aLine) const;
bool IsOnWordBoundary(const Coordinates& aAt) const; bool IsOnWordBoundary(const Coordinates& aAt) const;
void RemoveLine(int aStart, int aEnd); void RemoveLine(int aStart, int aEnd);
@@ -438,8 +356,6 @@ private:
EditorState mState; EditorState mState;
UndoBuffer mUndoBuffer; UndoBuffer mUndoBuffer;
int mUndoIndex; int mUndoIndex;
bool mScrollToBottom;
float mTopMargin;
int mTabSize; int mTabSize;
bool mOverwrite; bool mOverwrite;
@@ -463,14 +379,14 @@ private:
Palette mPalette; Palette mPalette;
LanguageDefinition mLanguageDefinition; LanguageDefinition mLanguageDefinition;
RegexList mRegexList; RegexList mRegexList;
bool mCheckComments;
bool mCheckComments;
Breakpoints mBreakpoints; Breakpoints mBreakpoints;
ErrorMarkers mErrorMarkers; ErrorMarkers mErrorMarkers;
ImVec2 mCharAdvance; ImVec2 mCharAdvance;
Coordinates mInteractiveStart, mInteractiveEnd; Coordinates mInteractiveStart, mInteractiveEnd;
std::string mLineBuffer; std::string mLineBuffer;
uint64_t mStartTime; uint64_t mStartTime;
std::vector<std::string> mDefines;
float mLastClick; float mLastClick;
bool mShowCursor; bool mShowCursor;

View File

@@ -1,13 +1,15 @@
// Generated by https://github.com/juliettef/IconFontCppHeaders script GenerateIconFontCppHeaders.py for languages C and C++ // Generated by https://github.com/juliettef/IconFontCppHeaders script GenerateIconFontCppHeaders.py for languages C and C++
// from https://raw.githubusercontent.com/microsoft/vscode-codicons/main/dist/codicon.css // from https://raw.githubusercontent.com/microsoft/vscode-codicons/main/dist/codicon.css
// for use with https://github.com/microsoft/vscode-codicons/blob/main/dist/codicon.ttf // for use with https://github.com/microsoft/vscode-codicons/raw/main/dist/codicon.ttf
#pragma once #pragma once
#define FONT_ICON_FILE_NAME_VS "codicon.ttf" #define FONT_ICON_FILE_NAME_VS "codicon.ttf"
extern const unsigned int codicons_compressed_size;
extern const unsigned int codicons_compressed_data[52184/4];
#define ICON_MIN_VS 0xea60 #define ICON_MIN_VS 0xea60
#define ICON_MAX_16_VS 0xec25 #define ICON_MAX_VS 0xebdd
#define ICON_MAX_VS 0xec25
#define ICON_VS_ADD "\xee\xa9\xa0" // U+ea60 #define ICON_VS_ADD "\xee\xa9\xa0" // U+ea60
#define ICON_VS_PLUS "\xee\xa9\xa0" // U+ea60 #define ICON_VS_PLUS "\xee\xa9\xa0" // U+ea60
#define ICON_VS_GIST_NEW "\xee\xa9\xa0" // U+ea60 #define ICON_VS_GIST_NEW "\xee\xa9\xa0" // U+ea60
@@ -23,7 +25,6 @@
#define ICON_VS_RECORD_KEYS "\xee\xa9\xa5" // U+ea65 #define ICON_VS_RECORD_KEYS "\xee\xa9\xa5" // U+ea65
#define ICON_VS_KEYBOARD "\xee\xa9\xa5" // U+ea65 #define ICON_VS_KEYBOARD "\xee\xa9\xa5" // U+ea65
#define ICON_VS_TAG "\xee\xa9\xa6" // U+ea66 #define ICON_VS_TAG "\xee\xa9\xa6" // U+ea66
#define ICON_VS_GIT_PULL_REQUEST_LABEL "\xee\xa9\xa6" // U+ea66
#define ICON_VS_TAG_ADD "\xee\xa9\xa6" // U+ea66 #define ICON_VS_TAG_ADD "\xee\xa9\xa6" // U+ea66
#define ICON_VS_TAG_REMOVE "\xee\xa9\xa6" // U+ea66 #define ICON_VS_TAG_REMOVE "\xee\xa9\xa6" // U+ea66
#define ICON_VS_PERSON "\xee\xa9\xa7" // U+ea67 #define ICON_VS_PERSON "\xee\xa9\xa7" // U+ea67
@@ -59,7 +60,6 @@
#define ICON_VS_DEBUG_BREAKPOINT "\xee\xa9\xb1" // U+ea71 #define ICON_VS_DEBUG_BREAKPOINT "\xee\xa9\xb1" // U+ea71
#define ICON_VS_DEBUG_BREAKPOINT_DISABLED "\xee\xa9\xb1" // U+ea71 #define ICON_VS_DEBUG_BREAKPOINT_DISABLED "\xee\xa9\xb1" // U+ea71
#define ICON_VS_DEBUG_HINT "\xee\xa9\xb1" // U+ea71 #define ICON_VS_DEBUG_HINT "\xee\xa9\xb1" // U+ea71
#define ICON_VS_TERMINAL_DECORATION_SUCCESS "\xee\xa9\xb1" // U+ea71
#define ICON_VS_PRIMITIVE_SQUARE "\xee\xa9\xb2" // U+ea72 #define ICON_VS_PRIMITIVE_SQUARE "\xee\xa9\xb2" // U+ea72
#define ICON_VS_EDIT "\xee\xa9\xb3" // U+ea73 #define ICON_VS_EDIT "\xee\xa9\xb3" // U+ea73
#define ICON_VS_PENCIL "\xee\xa9\xb3" // U+ea73 #define ICON_VS_PENCIL "\xee\xa9\xb3" // U+ea73
@@ -179,9 +179,7 @@
#define ICON_VS_CHROME_MINIMIZE "\xee\xaa\xba" // U+eaba #define ICON_VS_CHROME_MINIMIZE "\xee\xaa\xba" // U+eaba
#define ICON_VS_CHROME_RESTORE "\xee\xaa\xbb" // U+eabb #define ICON_VS_CHROME_RESTORE "\xee\xaa\xbb" // U+eabb
#define ICON_VS_CIRCLE_OUTLINE "\xee\xaa\xbc" // U+eabc #define ICON_VS_CIRCLE_OUTLINE "\xee\xaa\xbc" // U+eabc
#define ICON_VS_CIRCLE "\xee\xaa\xbc" // U+eabc
#define ICON_VS_DEBUG_BREAKPOINT_UNVERIFIED "\xee\xaa\xbc" // U+eabc #define ICON_VS_DEBUG_BREAKPOINT_UNVERIFIED "\xee\xaa\xbc" // U+eabc
#define ICON_VS_TERMINAL_DECORATION_INCOMPLETE "\xee\xaa\xbc" // U+eabc
#define ICON_VS_CIRCLE_SLASH "\xee\xaa\xbd" // U+eabd #define ICON_VS_CIRCLE_SLASH "\xee\xaa\xbd" // U+eabd
#define ICON_VS_CIRCUIT_BOARD "\xee\xaa\xbe" // U+eabe #define ICON_VS_CIRCUIT_BOARD "\xee\xaa\xbe" // U+eabe
#define ICON_VS_CLEAR_ALL "\xee\xaa\xbf" // U+eabf #define ICON_VS_CLEAR_ALL "\xee\xaa\xbf" // U+eabf
@@ -216,7 +214,6 @@
#define ICON_VS_DIFF_REMOVED "\xee\xab\x9f" // U+eadf #define ICON_VS_DIFF_REMOVED "\xee\xab\x9f" // U+eadf
#define ICON_VS_DIFF_RENAMED "\xee\xab\xa0" // U+eae0 #define ICON_VS_DIFF_RENAMED "\xee\xab\xa0" // U+eae0
#define ICON_VS_DIFF "\xee\xab\xa1" // U+eae1 #define ICON_VS_DIFF "\xee\xab\xa1" // U+eae1
#define ICON_VS_DIFF_SIDEBYSIDE "\xee\xab\xa1" // U+eae1
#define ICON_VS_DISCARD "\xee\xab\xa2" // U+eae2 #define ICON_VS_DISCARD "\xee\xab\xa2" // U+eae2
#define ICON_VS_EDITOR_LAYOUT "\xee\xab\xa3" // U+eae3 #define ICON_VS_EDITOR_LAYOUT "\xee\xab\xa3" // U+eae3
#define ICON_VS_EMPTY_WINDOW "\xee\xab\xa4" // U+eae4 #define ICON_VS_EMPTY_WINDOW "\xee\xab\xa4" // U+eae4
@@ -280,7 +277,6 @@
#define ICON_VS_MEGAPHONE "\xee\xac\x9e" // U+eb1e #define ICON_VS_MEGAPHONE "\xee\xac\x9e" // U+eb1e
#define ICON_VS_MENTION "\xee\xac\x9f" // U+eb1f #define ICON_VS_MENTION "\xee\xac\x9f" // U+eb1f
#define ICON_VS_MILESTONE "\xee\xac\xa0" // U+eb20 #define ICON_VS_MILESTONE "\xee\xac\xa0" // U+eb20
#define ICON_VS_GIT_PULL_REQUEST_MILESTONE "\xee\xac\xa0" // U+eb20
#define ICON_VS_MORTAR_BOARD "\xee\xac\xa1" // U+eb21 #define ICON_VS_MORTAR_BOARD "\xee\xac\xa1" // U+eb21
#define ICON_VS_MOVE "\xee\xac\xa2" // U+eb22 #define ICON_VS_MOVE "\xee\xac\xa2" // U+eb22
#define ICON_VS_MULTIPLE_WINDOWS "\xee\xac\xa3" // U+eb23 #define ICON_VS_MULTIPLE_WINDOWS "\xee\xac\xa3" // U+eb23
@@ -390,9 +386,7 @@
#define ICON_VS_DEBUG_BREAKPOINT_FUNCTION "\xee\xae\x88" // U+eb88 #define ICON_VS_DEBUG_BREAKPOINT_FUNCTION "\xee\xae\x88" // U+eb88
#define ICON_VS_DEBUG_BREAKPOINT_FUNCTION_DISABLED "\xee\xae\x88" // U+eb88 #define ICON_VS_DEBUG_BREAKPOINT_FUNCTION_DISABLED "\xee\xae\x88" // U+eb88
#define ICON_VS_DEBUG_STACKFRAME_ACTIVE "\xee\xae\x89" // U+eb89 #define ICON_VS_DEBUG_STACKFRAME_ACTIVE "\xee\xae\x89" // U+eb89
#define ICON_VS_CIRCLE_SMALL_FILLED "\xee\xae\x8a" // U+eb8a
#define ICON_VS_DEBUG_STACKFRAME_DOT "\xee\xae\x8a" // U+eb8a #define ICON_VS_DEBUG_STACKFRAME_DOT "\xee\xae\x8a" // U+eb8a
#define ICON_VS_TERMINAL_DECORATION_MARK "\xee\xae\x8a" // U+eb8a
#define ICON_VS_DEBUG_STACKFRAME "\xee\xae\x8b" // U+eb8b #define ICON_VS_DEBUG_STACKFRAME "\xee\xae\x8b" // U+eb8b
#define ICON_VS_DEBUG_STACKFRAME_FOCUSED "\xee\xae\x8b" // U+eb8b #define ICON_VS_DEBUG_STACKFRAME_FOCUSED "\xee\xae\x8b" // U+eb8b
#define ICON_VS_DEBUG_BREAKPOINT_UNSUPPORTED "\xee\xae\x8c" // U+eb8c #define ICON_VS_DEBUG_BREAKPOINT_UNSUPPORTED "\xee\xae\x8c" // U+eb8c
@@ -406,11 +400,9 @@
#define ICON_VS_MENU "\xee\xae\x94" // U+eb94 #define ICON_VS_MENU "\xee\xae\x94" // U+eb94
#define ICON_VS_EXPAND_ALL "\xee\xae\x95" // U+eb95 #define ICON_VS_EXPAND_ALL "\xee\xae\x95" // U+eb95
#define ICON_VS_FEEDBACK "\xee\xae\x96" // U+eb96 #define ICON_VS_FEEDBACK "\xee\xae\x96" // U+eb96
#define ICON_VS_GIT_PULL_REQUEST_REVIEWER "\xee\xae\x96" // U+eb96
#define ICON_VS_GROUP_BY_REF_TYPE "\xee\xae\x97" // U+eb97 #define ICON_VS_GROUP_BY_REF_TYPE "\xee\xae\x97" // U+eb97
#define ICON_VS_UNGROUP_BY_REF_TYPE "\xee\xae\x98" // U+eb98 #define ICON_VS_UNGROUP_BY_REF_TYPE "\xee\xae\x98" // U+eb98
#define ICON_VS_ACCOUNT "\xee\xae\x99" // U+eb99 #define ICON_VS_ACCOUNT "\xee\xae\x99" // U+eb99
#define ICON_VS_GIT_PULL_REQUEST_ASSIGNEE "\xee\xae\x99" // U+eb99
#define ICON_VS_BELL_DOT "\xee\xae\x9a" // U+eb9a #define ICON_VS_BELL_DOT "\xee\xae\x9a" // U+eb9a
#define ICON_VS_DEBUG_CONSOLE "\xee\xae\x9b" // U+eb9b #define ICON_VS_DEBUG_CONSOLE "\xee\xae\x9b" // U+eb9b
#define ICON_VS_LIBRARY "\xee\xae\x9c" // U+eb9c #define ICON_VS_LIBRARY "\xee\xae\x9c" // U+eb9c
@@ -439,7 +431,6 @@
#define ICON_VS_PINNED_DIRTY "\xee\xae\xb2" // U+ebb2 #define ICON_VS_PINNED_DIRTY "\xee\xae\xb2" // U+ebb2
#define ICON_VS_PASS_FILLED "\xee\xae\xb3" // U+ebb3 #define ICON_VS_PASS_FILLED "\xee\xae\xb3" // U+ebb3
#define ICON_VS_CIRCLE_LARGE_FILLED "\xee\xae\xb4" // U+ebb4 #define ICON_VS_CIRCLE_LARGE_FILLED "\xee\xae\xb4" // U+ebb4
#define ICON_VS_CIRCLE_LARGE "\xee\xae\xb5" // U+ebb5
#define ICON_VS_CIRCLE_LARGE_OUTLINE "\xee\xae\xb5" // U+ebb5 #define ICON_VS_CIRCLE_LARGE_OUTLINE "\xee\xae\xb5" // U+ebb5
#define ICON_VS_COMBINE "\xee\xae\xb6" // U+ebb6 #define ICON_VS_COMBINE "\xee\xae\xb6" // U+ebb6
#define ICON_VS_GATHER "\xee\xae\xb6" // U+ebb6 #define ICON_VS_GATHER "\xee\xae\xb6" // U+ebb6
@@ -482,77 +473,3 @@
#define ICON_VS_GIT_PULL_REQUEST_DRAFT "\xee\xaf\x9b" // U+ebdb #define ICON_VS_GIT_PULL_REQUEST_DRAFT "\xee\xaf\x9b" // U+ebdb
#define ICON_VS_DEBUG_ALL "\xee\xaf\x9c" // U+ebdc #define ICON_VS_DEBUG_ALL "\xee\xaf\x9c" // U+ebdc
#define ICON_VS_DEBUG_COVERAGE "\xee\xaf\x9d" // U+ebdd #define ICON_VS_DEBUG_COVERAGE "\xee\xaf\x9d" // U+ebdd
#define ICON_VS_RUN_ERRORS "\xee\xaf\x9e" // U+ebde
#define ICON_VS_FOLDER_LIBRARY "\xee\xaf\x9f" // U+ebdf
#define ICON_VS_DEBUG_CONTINUE_SMALL "\xee\xaf\xa0" // U+ebe0
#define ICON_VS_BEAKER_STOP "\xee\xaf\xa1" // U+ebe1
#define ICON_VS_GRAPH_LINE "\xee\xaf\xa2" // U+ebe2
#define ICON_VS_GRAPH_SCATTER "\xee\xaf\xa3" // U+ebe3
#define ICON_VS_PIE_CHART "\xee\xaf\xa4" // U+ebe4
#define ICON_VS_BRACKET "\xee\xac\x8f" // U+eb0f
#define ICON_VS_BRACKET_DOT "\xee\xaf\xa5" // U+ebe5
#define ICON_VS_BRACKET_ERROR "\xee\xaf\xa6" // U+ebe6
#define ICON_VS_LOCK_SMALL "\xee\xaf\xa7" // U+ebe7
#define ICON_VS_AZURE_DEVOPS "\xee\xaf\xa8" // U+ebe8
#define ICON_VS_VERIFIED_FILLED "\xee\xaf\xa9" // U+ebe9
#define ICON_VS_NEWLINE "\xee\xaf\xaa" // U+ebea
#define ICON_VS_LAYOUT "\xee\xaf\xab" // U+ebeb
#define ICON_VS_LAYOUT_ACTIVITYBAR_LEFT "\xee\xaf\xac" // U+ebec
#define ICON_VS_LAYOUT_ACTIVITYBAR_RIGHT "\xee\xaf\xad" // U+ebed
#define ICON_VS_LAYOUT_PANEL_LEFT "\xee\xaf\xae" // U+ebee
#define ICON_VS_LAYOUT_PANEL_CENTER "\xee\xaf\xaf" // U+ebef
#define ICON_VS_LAYOUT_PANEL_JUSTIFY "\xee\xaf\xb0" // U+ebf0
#define ICON_VS_LAYOUT_PANEL_RIGHT "\xee\xaf\xb1" // U+ebf1
#define ICON_VS_LAYOUT_PANEL "\xee\xaf\xb2" // U+ebf2
#define ICON_VS_LAYOUT_SIDEBAR_LEFT "\xee\xaf\xb3" // U+ebf3
#define ICON_VS_LAYOUT_SIDEBAR_RIGHT "\xee\xaf\xb4" // U+ebf4
#define ICON_VS_LAYOUT_STATUSBAR "\xee\xaf\xb5" // U+ebf5
#define ICON_VS_LAYOUT_MENUBAR "\xee\xaf\xb6" // U+ebf6
#define ICON_VS_LAYOUT_CENTERED "\xee\xaf\xb7" // U+ebf7
#define ICON_VS_TARGET "\xee\xaf\xb8" // U+ebf8
#define ICON_VS_INDENT "\xee\xaf\xb9" // U+ebf9
#define ICON_VS_RECORD_SMALL "\xee\xaf\xba" // U+ebfa
#define ICON_VS_ERROR_SMALL "\xee\xaf\xbb" // U+ebfb
#define ICON_VS_TERMINAL_DECORATION_ERROR "\xee\xaf\xbb" // U+ebfb
#define ICON_VS_ARROW_CIRCLE_DOWN "\xee\xaf\xbc" // U+ebfc
#define ICON_VS_ARROW_CIRCLE_LEFT "\xee\xaf\xbd" // U+ebfd
#define ICON_VS_ARROW_CIRCLE_RIGHT "\xee\xaf\xbe" // U+ebfe
#define ICON_VS_ARROW_CIRCLE_UP "\xee\xaf\xbf" // U+ebff
#define ICON_VS_LAYOUT_SIDEBAR_RIGHT_OFF "\xee\xb0\x80" // U+ec00
#define ICON_VS_LAYOUT_PANEL_OFF "\xee\xb0\x81" // U+ec01
#define ICON_VS_LAYOUT_SIDEBAR_LEFT_OFF "\xee\xb0\x82" // U+ec02
#define ICON_VS_BLANK "\xee\xb0\x83" // U+ec03
#define ICON_VS_HEART_FILLED "\xee\xb0\x84" // U+ec04
#define ICON_VS_MAP "\xee\xb0\x85" // U+ec05
#define ICON_VS_MAP_FILLED "\xee\xb0\x86" // U+ec06
#define ICON_VS_CIRCLE_SMALL "\xee\xb0\x87" // U+ec07
#define ICON_VS_BELL_SLASH "\xee\xb0\x88" // U+ec08
#define ICON_VS_BELL_SLASH_DOT "\xee\xb0\x89" // U+ec09
#define ICON_VS_COMMENT_UNRESOLVED "\xee\xb0\x8a" // U+ec0a
#define ICON_VS_GIT_PULL_REQUEST_GO_TO_CHANGES "\xee\xb0\x8b" // U+ec0b
#define ICON_VS_GIT_PULL_REQUEST_NEW_CHANGES "\xee\xb0\x8c" // U+ec0c
#define ICON_VS_SEARCH_FUZZY "\xee\xb0\x8d" // U+ec0d
#define ICON_VS_COMMENT_DRAFT "\xee\xb0\x8e" // U+ec0e
#define ICON_VS_SEND "\xee\xb0\x8f" // U+ec0f
#define ICON_VS_SPARKLE "\xee\xb0\x90" // U+ec10
#define ICON_VS_INSERT "\xee\xb0\x91" // U+ec11
#define ICON_VS_MIC "\xee\xb0\x92" // U+ec12
#define ICON_VS_THUMBSDOWN_FILLED "\xee\xb0\x93" // U+ec13
#define ICON_VS_THUMBSUP_FILLED "\xee\xb0\x94" // U+ec14
#define ICON_VS_COFFEE "\xee\xb0\x95" // U+ec15
#define ICON_VS_SNAKE "\xee\xb0\x96" // U+ec16
#define ICON_VS_GAME "\xee\xb0\x97" // U+ec17
#define ICON_VS_VR "\xee\xb0\x98" // U+ec18
#define ICON_VS_CHIP "\xee\xb0\x99" // U+ec19
#define ICON_VS_PIANO "\xee\xb0\x9a" // U+ec1a
#define ICON_VS_MUSIC "\xee\xb0\x9b" // U+ec1b
#define ICON_VS_MIC_FILLED "\xee\xb0\x9c" // U+ec1c
#define ICON_VS_GIT_FETCH "\xee\xb0\x9d" // U+ec1d
#define ICON_VS_COPILOT "\xee\xb0\x9e" // U+ec1e
#define ICON_VS_LIGHTBULB_SPARKLE "\xee\xb0\x9f" // U+ec1f
#define ICON_VS_ROBOT "\xee\xb0\xa0" // U+ec20
#define ICON_VS_SPARKLE_FILLED "\xee\xb0\xa1" // U+ec21
#define ICON_VS_DIFF_SINGLE "\xee\xb0\xa2" // U+ec22
#define ICON_VS_DIFF_MULTIPLE "\xee\xb0\xa3" // U+ec23
#define ICON_VS_SURROUND_WITH "\xee\xb0\xa4" // U+ec24
#define ICON_VS_SHARE "\xee\xb0\xa5" // U+ec25

File diff suppressed because it is too large Load Diff

View File

@@ -126,19 +126,3 @@ namespace ImGui
void MyFunction(const char* name, const MyMatrix44& v); void MyFunction(const char* name, const MyMatrix44& v);
} }
*/ */
#define IMGUI_ENABLE_TEST_ENGINE
// IMPLOT CONFIG
#define IMPLOT_CUSTOM_NUMERIC_TYPES (ImS8)(ImU8)(ImS16)(ImU16)(ImS32)(ImU32)(ImS64)(ImU64)(float)(double)(long double)
#define IM_OFFSETOF(_TYPE,_MEMBER) offsetof(_TYPE, _MEMBER)
#define IM_FLOOR IM_TRUNC
#define IMGUI_DEFINE_MATH_OPERATORS
#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
#define IMGUI_DISABLE_OBSOLETE_KEYIO
#define IMGUI_ENABLE_FREETYPE
#define ImDrawIdx unsigned int
#define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX

View File

@@ -0,0 +1,9 @@
// ImGui config (check imconfig.h for more information about these definitions)
#pragma once
#define IMGUI_DEFINE_MATH_OPERATORS
#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
#define IMGUI_DISABLE_OBSOLETE_KEYIO
#define IMGUI_ENABLE_FREETYPE
#define ImDrawIdx unsigned int
#define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX

View File

@@ -16,15 +16,11 @@
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// Learn about Dear ImGui: // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// - FAQ https://dearimgui.com/faq // Read online: https://github.com/ocornut/imgui/tree/master/docs
// - Getting Started https://dearimgui.com/getting-started
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
// - Introduction, links and more at the top of imgui.cpp
#pragma once #pragma once
#include "imgui.h" // IMGUI_IMPL_API #include "imgui.h" // IMGUI_IMPL_API
#ifndef IMGUI_DISABLE
struct GLFWwindow; struct GLFWwindow;
struct GLFWmonitor; struct GLFWmonitor;
@@ -35,11 +31,6 @@ IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOther(GLFWwindow* window, bool ins
IMGUI_IMPL_API void ImGui_ImplGlfw_Shutdown(); IMGUI_IMPL_API void ImGui_ImplGlfw_Shutdown();
IMGUI_IMPL_API void ImGui_ImplGlfw_NewFrame(); IMGUI_IMPL_API void ImGui_ImplGlfw_NewFrame();
// Emscripten related initialization phase methods
#ifdef __EMSCRIPTEN__
IMGUI_IMPL_API void ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback(const char* canvas_selector);
#endif
// GLFW callbacks install // GLFW callbacks install
// - When calling Init with 'install_callbacks=true': ImGui_ImplGlfw_InstallCallbacks() is called. GLFW callbacks will be installed for you. They will chain-call user's previously installed callbacks, if any. // - When calling Init with 'install_callbacks=true': ImGui_ImplGlfw_InstallCallbacks() is called. GLFW callbacks will be installed for you. They will chain-call user's previously installed callbacks, if any.
// - When calling Init with 'install_callbacks=false': GLFW callbacks won't be installed. You will need to call individual function yourself from your own GLFW callbacks. // - When calling Init with 'install_callbacks=false': GLFW callbacks won't be installed. You will need to call individual function yourself from your own GLFW callbacks.
@@ -59,5 +50,3 @@ IMGUI_IMPL_API void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double
IMGUI_IMPL_API void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); IMGUI_IMPL_API void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
IMGUI_IMPL_API void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c); IMGUI_IMPL_API void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c);
IMGUI_IMPL_API void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor* monitor, int event); IMGUI_IMPL_API void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor* monitor, int event);
#endif // #ifndef IMGUI_DISABLE

View File

@@ -8,18 +8,10 @@
// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices (Desktop OpenGL only). // [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices (Desktop OpenGL only).
// [X] Renderer: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. // [X] Renderer: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// About WebGL/ES:
// - You need to '#define IMGUI_IMPL_OPENGL_ES2' or '#define IMGUI_IMPL_OPENGL_ES3' to use WebGL or OpenGL ES.
// - This is done automatically on iOS, Android and Emscripten targets.
// - For other targets, the define needs to be visible from the imgui_impl_opengl3.cpp compilation unit. If unsure, define globally or in imconfig.h.
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// Learn about Dear ImGui: // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// - FAQ https://dearimgui.com/faq // Read online: https://github.com/ocornut/imgui/tree/master/docs
// - Getting Started https://dearimgui.com/getting-started
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
// - Introduction, links and more at the top of imgui.cpp
// About GLSL version: // About GLSL version:
// The 'glsl_version' initialization parameter should be nullptr (default) or a "#version XXX" string. // The 'glsl_version' initialization parameter should be nullptr (default) or a "#version XXX" string.
@@ -28,7 +20,6 @@
#pragma once #pragma once
#include "imgui.h" // IMGUI_IMPL_API #include "imgui.h" // IMGUI_IMPL_API
#ifndef IMGUI_DISABLE
// Backend API // Backend API
IMGUI_IMPL_API bool ImGui_ImplOpenGL3_Init(const char* glsl_version = nullptr); IMGUI_IMPL_API bool ImGui_ImplOpenGL3_Init(const char* glsl_version = nullptr);
@@ -63,5 +54,3 @@ IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyDeviceObjects();
#endif #endif
#endif #endif
#endif // #ifndef IMGUI_DISABLE

View File

@@ -32,12 +32,6 @@
#ifndef __gl3w_h_ #ifndef __gl3w_h_
#define __gl3w_h_ #define __gl3w_h_
#if defined(__APPLE__)
#include <OpenGL/gl.h>
#elif !defined(__EMSCRIPTEN__)
#include <GL/gl.h>
#endif
#if __has_include(<KHR/khrplatform.h>) #if __has_include(<KHR/khrplatform.h>)
#include <KHR/khrplatform.h> #include <KHR/khrplatform.h>
#else #else
@@ -1163,9 +1157,7 @@ typedef khronos_uint16_t GLhalf;
#define GL_TEXTURE_DEPTH_TYPE 0x8C16 #define GL_TEXTURE_DEPTH_TYPE 0x8C16
#define GL_UNSIGNED_NORMALIZED 0x8C17 #define GL_UNSIGNED_NORMALIZED 0x8C17
#define GL_FRAMEBUFFER_BINDING 0x8CA6 #define GL_FRAMEBUFFER_BINDING 0x8CA6
#ifndef __APPLE__
#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6 #define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6
#endif
#define GL_RENDERBUFFER_BINDING 0x8CA7 #define GL_RENDERBUFFER_BINDING 0x8CA7
#define GL_READ_FRAMEBUFFER 0x8CA8 #define GL_READ_FRAMEBUFFER 0x8CA8
#define GL_DRAW_FRAMEBUFFER 0x8CA9 #define GL_DRAW_FRAMEBUFFER 0x8CA9

View File

@@ -1,6 +1,6 @@
// MIT License // MIT License
// Copyright (c) 2023 Evan Pezent // Copyright (c) 2022 Evan Pezent
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
@@ -20,7 +20,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE. // SOFTWARE.
// ImPlot v0.17 // ImPlot v0.14
// Table of Contents: // Table of Contents:
// //
@@ -60,7 +60,7 @@
#endif #endif
// ImPlot version string. // ImPlot version string.
#define IMPLOT_VERSION "0.17" #define IMPLOT_VERSION "0.14"
// Indicates variable should deduced automatically. // Indicates variable should deduced automatically.
#define IMPLOT_AUTO -1 #define IMPLOT_AUTO -1
// Special color used to indicate that a color should be deduced automatically. // Special color used to indicate that a color should be deduced automatically.
@@ -135,9 +135,10 @@ enum ImPlotFlags_ {
ImPlotFlags_NoInputs = 1 << 3, // the user will not be able to interact with the plot ImPlotFlags_NoInputs = 1 << 3, // the user will not be able to interact with the plot
ImPlotFlags_NoMenus = 1 << 4, // the user will not be able to open context menus ImPlotFlags_NoMenus = 1 << 4, // the user will not be able to open context menus
ImPlotFlags_NoBoxSelect = 1 << 5, // the user will not be able to box-select ImPlotFlags_NoBoxSelect = 1 << 5, // the user will not be able to box-select
ImPlotFlags_NoFrame = 1 << 6, // the ImGui frame will not be rendered ImPlotFlags_NoChild = 1 << 6, // a child window region will not be used to capture mouse scroll (can boost performance for single ImGui window applications)
ImPlotFlags_Equal = 1 << 7, // x and y axes pairs will be constrained to have the same units/pixel ImPlotFlags_NoFrame = 1 << 7, // the ImGui frame will not be rendered
ImPlotFlags_Crosshairs = 1 << 8, // the default mouse cursor will be replaced with a crosshair when hovered ImPlotFlags_Equal = 1 << 8, // x and y axes pairs will be constrained to have the same units/pixel
ImPlotFlags_Crosshairs = 1 << 9, // the default mouse cursor will be replaced with a crosshair when hovered
ImPlotFlags_CanvasOnly = ImPlotFlags_NoTitle | ImPlotFlags_NoLegend | ImPlotFlags_NoMenus | ImPlotFlags_NoBoxSelect | ImPlotFlags_NoMouseText ImPlotFlags_CanvasOnly = ImPlotFlags_NoTitle | ImPlotFlags_NoLegend | ImPlotFlags_NoMenus | ImPlotFlags_NoBoxSelect | ImPlotFlags_NoMouseText
}; };
@@ -286,9 +287,8 @@ enum ImPlotInfLinesFlags_ {
// Flags for PlotPieChart // Flags for PlotPieChart
enum ImPlotPieChartFlags_ { enum ImPlotPieChartFlags_ {
ImPlotPieChartFlags_None = 0, // default ImPlotPieChartFlags_None = 0, // default
ImPlotPieChartFlags_Normalize = 1 << 10, // force normalization of pie chart values (i.e. always make a full circle if sum < 0) ImPlotPieChartFlags_Normalize = 1 << 10 // force normalization of pie chart values (i.e. always make a full circle if sum < 0)
ImPlotPieChartFlags_IgnoreHidden = 1 << 11 // ignore hidden slices when drawing the pie chart (as if they were not there)
}; };
// Flags for PlotHeatmap // Flags for PlotHeatmap
@@ -464,43 +464,41 @@ enum ImPlotBin_ {
}; };
// Double precision version of ImVec2 used by ImPlot. Extensible by end users. // Double precision version of ImVec2 used by ImPlot. Extensible by end users.
IM_MSVC_RUNTIME_CHECKS_OFF
struct ImPlotPoint { struct ImPlotPoint {
double x, y; double x, y;
constexpr ImPlotPoint() : x(0.0), y(0.0) { } ImPlotPoint() { x = y = 0.0; }
constexpr ImPlotPoint(double _x, double _y) : x(_x), y(_y) { } ImPlotPoint(double _x, double _y) { x = _x; y = _y; }
constexpr ImPlotPoint(const ImVec2& p) : x((double)p.x), y((double)p.y) { } ImPlotPoint(const ImVec2& p) { x = p.x; y = p.y; }
double& operator[] (size_t idx) { IM_ASSERT(idx == 0 || idx == 1); return ((double*)(void*)(char*)this)[idx]; } double operator[] (size_t idx) const { return (&x)[idx]; }
double operator[] (size_t idx) const { IM_ASSERT(idx == 0 || idx == 1); return ((const double*)(const void*)(const char*)this)[idx]; } double& operator[] (size_t idx) { return (&x)[idx]; }
#ifdef IMPLOT_POINT_CLASS_EXTRA #ifdef IMPLOT_POINT_CLASS_EXTRA
IMPLOT_POINT_CLASS_EXTRA // Define additional constructors and implicit cast operators in imconfig.h IMPLOT_POINT_CLASS_EXTRA // Define additional constructors and implicit cast operators in imconfig.h
// to convert back and forth between your math types and ImPlotPoint. // to convert back and forth between your math types and ImPlotPoint.
#endif #endif
}; };
IM_MSVC_RUNTIME_CHECKS_RESTORE
// Range defined by a min/max value. // Range defined by a min/max value.
struct ImPlotRange { struct ImPlotRange {
double Min, Max; double Min, Max;
constexpr ImPlotRange() : Min(0.0), Max(0.0) { } ImPlotRange() { Min = 0; Max = 0; }
constexpr ImPlotRange(double _min, double _max) : Min(_min), Max(_max) { } ImPlotRange(double _min, double _max) { Min = _min; Max = _max; }
bool Contains(double value) const { return value >= Min && value <= Max; } bool Contains(double value) const { return value >= Min && value <= Max; }
double Size() const { return Max - Min; } double Size() const { return Max - Min; }
double Clamp(double value) const { return (value < Min) ? Min : (value > Max) ? Max : value; } double Clamp(double value) const { return (value < Min) ? Min : (value > Max) ? Max : value; }
}; };
// Combination of two range limits for X and Y axes. Also an AABB defined by Min()/Max(). // Combination of two range limits for X and Y axes. Also an AABB defined by Min()/Max().
struct ImPlotRect { struct ImPlotRect {
ImPlotRange X, Y; ImPlotRange X, Y;
constexpr ImPlotRect() : X(0.0,0.0), Y(0.0,0.0) { } ImPlotRect() { }
constexpr ImPlotRect(double x_min, double x_max, double y_min, double y_max) : X(x_min, x_max), Y(y_min, y_max) { } ImPlotRect(double x_min, double x_max, double y_min, double y_max) { X.Min = x_min; X.Max = x_max; Y.Min = y_min; Y.Max = y_max; }
bool Contains(const ImPlotPoint& p) const { return Contains(p.x, p.y); } bool Contains(const ImPlotPoint& p) const { return Contains(p.x, p.y); }
bool Contains(double x, double y) const { return X.Contains(x) && Y.Contains(y); } bool Contains(double x, double y) const { return X.Contains(x) && Y.Contains(y); }
ImPlotPoint Size() const { return ImPlotPoint(X.Size(), Y.Size()); } ImPlotPoint Size() const { return ImPlotPoint(X.Size(), Y.Size()); }
ImPlotPoint Clamp(const ImPlotPoint& p) { return Clamp(p.x, p.y); } ImPlotPoint Clamp(const ImPlotPoint& p) { return Clamp(p.x, p.y); }
ImPlotPoint Clamp(double x, double y) { return ImPlotPoint(X.Clamp(x),Y.Clamp(y)); } ImPlotPoint Clamp(double x, double y) { return ImPlotPoint(X.Clamp(x),Y.Clamp(y)); }
ImPlotPoint Min() const { return ImPlotPoint(X.Min, Y.Min); } ImPlotPoint Min() const { return ImPlotPoint(X.Min, Y.Min); }
ImPlotPoint Max() const { return ImPlotPoint(X.Max, Y.Max); } ImPlotPoint Max() const { return ImPlotPoint(X.Max, Y.Max); }
}; };
// Plot style structure // Plot style structure
@@ -730,7 +728,7 @@ IMPLOT_API void EndSubplots();
// Enables an axis or sets the label and/or flags for an existing axis. Leave #label = nullptr for no label. // Enables an axis or sets the label and/or flags for an existing axis. Leave #label = nullptr for no label.
IMPLOT_API void SetupAxis(ImAxis axis, const char* label=nullptr, ImPlotAxisFlags flags=0); IMPLOT_API void SetupAxis(ImAxis axis, const char* label=nullptr, ImPlotAxisFlags flags=0);
// Sets an axis range limits. If ImPlotCond_Always is used, the axes limits will be locked. Inversion with v_min > v_max is not supported; use SetupAxisLimits instead. // Sets an axis range limits. If ImPlotCond_Always is used, the axes limits will be locked.
IMPLOT_API void SetupAxisLimits(ImAxis axis, double v_min, double v_max, ImPlotCond cond = ImPlotCond_Once); IMPLOT_API void SetupAxisLimits(ImAxis axis, double v_min, double v_max, ImPlotCond cond = ImPlotCond_Once);
// Links an axis range limits to external values. Set to nullptr for no linkage. The pointer data must remain valid until EndPlot. // Links an axis range limits to external values. Set to nullptr for no linkage. The pointer data must remain valid until EndPlot.
IMPLOT_API void SetupAxisLinks(ImAxis axis, double* link_min, double* link_max); IMPLOT_API void SetupAxisLinks(ImAxis axis, double* link_min, double* link_max);
@@ -756,7 +754,7 @@ IMPLOT_API void SetupAxes(const char* x_label, const char* y_label, ImPlotAxisFl
// Sets the primary X and Y axes range limits. If ImPlotCond_Always is used, the axes limits will be locked (shorthand for two calls to SetupAxisLimits). // Sets the primary X and Y axes range limits. If ImPlotCond_Always is used, the axes limits will be locked (shorthand for two calls to SetupAxisLimits).
IMPLOT_API void SetupAxesLimits(double x_min, double x_max, double y_min, double y_max, ImPlotCond cond = ImPlotCond_Once); IMPLOT_API void SetupAxesLimits(double x_min, double x_max, double y_min, double y_max, ImPlotCond cond = ImPlotCond_Once);
// Sets up the plot legend. This can also be called immediately after BeginSubplots when using ImPlotSubplotFlags_ShareItems. // Sets up the plot legend.
IMPLOT_API void SetupLegend(ImPlotLocation location, ImPlotLegendFlags flags=0); IMPLOT_API void SetupLegend(ImPlotLocation location, ImPlotLegendFlags flags=0);
// Set the location of the current plot's mouse position text (default = South|East). // Set the location of the current plot's mouse position text (default = South|East).
IMPLOT_API void SetupMouseText(ImPlotLocation location, ImPlotMouseTextFlags flags=0); IMPLOT_API void SetupMouseText(ImPlotLocation location, ImPlotMouseTextFlags flags=0);
@@ -893,7 +891,6 @@ IMPLOT_TMP void PlotStems(const char* label_id, const T* xs, const T* ys, int co
IMPLOT_TMP void PlotInfLines(const char* label_id, const T* values, int count, ImPlotInfLinesFlags flags=0, int offset=0, int stride=sizeof(T)); IMPLOT_TMP void PlotInfLines(const char* label_id, const T* values, int count, ImPlotInfLinesFlags flags=0, int offset=0, int stride=sizeof(T));
// Plots a pie chart. Center and radius are in plot units. #label_fmt can be set to nullptr for no labels. // Plots a pie chart. Center and radius are in plot units. #label_fmt can be set to nullptr for no labels.
IMPLOT_TMP void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, ImPlotFormatter fmt, void* fmt_data=nullptr, double angle0=90, ImPlotPieChartFlags flags=0);
IMPLOT_TMP void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, const char* label_fmt="%.1f", double angle0=90, ImPlotPieChartFlags flags=0); IMPLOT_TMP void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, const char* label_fmt="%.1f", double angle0=90, ImPlotPieChartFlags flags=0);
// Plots a 2D heatmap chart. Values are expected to be in row-major order by default. Leave #scale_min and scale_max both at 0 for automatic color scaling, or set them to a predefined range. #label_fmt can be set to nullptr for no labels. // Plots a 2D heatmap chart. Values are expected to be in row-major order by default. Leave #scale_min and scale_max both at 0 for automatic color scaling, or set them to a predefined range. #label_fmt can be set to nullptr for no labels.
@@ -926,18 +923,16 @@ IMPLOT_API void PlotDummy(const char* label_id, ImPlotDummyFlags flags=0);
// The following can be used to render interactive elements and/or annotations. // The following can be used to render interactive elements and/or annotations.
// Like the item plotting functions above, they apply to the current x and y // Like the item plotting functions above, they apply to the current x and y
// axes, which can be changed with `SetAxis/SetAxes`. These functions return true // axes, which can be changed with `SetAxis/SetAxes`.
// when user interaction causes the provided coordinates to change. Additional
// user interactions can be retrieved through the optional output parameters.
// Shows a draggable point at x,y. #col defaults to ImGuiCol_Text. // Shows a draggable point at x,y. #col defaults to ImGuiCol_Text.
IMPLOT_API bool DragPoint(int id, double* x, double* y, const ImVec4& col, float size = 4, ImPlotDragToolFlags flags = 0, bool* out_clicked = nullptr, bool* out_hovered = nullptr, bool* held = nullptr); IMPLOT_API bool DragPoint(int id, double* x, double* y, const ImVec4& col, float size = 4, ImPlotDragToolFlags flags=0);
// Shows a draggable vertical guide line at an x-value. #col defaults to ImGuiCol_Text. // Shows a draggable vertical guide line at an x-value. #col defaults to ImGuiCol_Text.
IMPLOT_API bool DragLineX(int id, double* x, const ImVec4& col, float thickness = 1, ImPlotDragToolFlags flags = 0, bool* out_clicked = nullptr, bool* out_hovered = nullptr, bool* held = nullptr); IMPLOT_API bool DragLineX(int id, double* x, const ImVec4& col, float thickness = 1, ImPlotDragToolFlags flags=0);
// Shows a draggable horizontal guide line at a y-value. #col defaults to ImGuiCol_Text. // Shows a draggable horizontal guide line at a y-value. #col defaults to ImGuiCol_Text.
IMPLOT_API bool DragLineY(int id, double* y, const ImVec4& col, float thickness = 1, ImPlotDragToolFlags flags = 0, bool* out_clicked = nullptr, bool* out_hovered = nullptr, bool* held = nullptr); IMPLOT_API bool DragLineY(int id, double* y, const ImVec4& col, float thickness = 1, ImPlotDragToolFlags flags=0);
// Shows a draggable and resizeable rectangle. // Shows a draggable and resizeable rectangle.
IMPLOT_API bool DragRect(int id, double* x1, double* y1, double* x2, double* y2, const ImVec4& col, ImPlotDragToolFlags flags = 0, bool* out_clicked = nullptr, bool* out_hovered = nullptr, bool* held = nullptr); IMPLOT_API bool DragRect(int id, double* x1, double* y1, double* x2, double* y2, const ImVec4& col, ImPlotDragToolFlags flags=0);
// Shows an annotation callout at a chosen point. Clamping keeps annotations in the plot area. Annotations are always rendered on top. // Shows an annotation callout at a chosen point. Clamping keeps annotations in the plot area. Annotations are always rendered on top.
IMPLOT_API void Annotation(double x, double y, const ImVec4& col, const ImVec2& pix_offset, bool clamp, bool round = false); IMPLOT_API void Annotation(double x, double y, const ImVec4& col, const ImVec2& pix_offset, bool clamp, bool round = false);

View File

@@ -1,6 +1,6 @@
// MIT License // MIT License
// Copyright (c) 2023 Evan Pezent // Copyright (c) 2022 Evan Pezent
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
@@ -20,7 +20,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE. // SOFTWARE.
// ImPlot v0.17 // ImPlot v0.14
// You may use this file to debug, understand or extend ImPlot features but we // You may use this file to debug, understand or extend ImPlot features but we
// don't provide any guarantee of forward compatibility! // don't provide any guarantee of forward compatibility!
@@ -907,9 +907,8 @@ struct ImPlotAxis
} }
void PullLinks() { void PullLinks() {
if (LinkedMin && LinkedMax) { SetRange(*LinkedMin, *LinkedMax); } if (LinkedMin) { SetMin(*LinkedMin,true); }
else if (LinkedMin) { SetMin(*LinkedMin,true); } if (LinkedMax) { SetMax(*LinkedMax,true); }
else if (LinkedMax) { SetMax(*LinkedMax,true); }
} }
}; };
@@ -966,11 +965,9 @@ struct ImPlotLegend
ImPlotLegendFlags PreviousFlags; ImPlotLegendFlags PreviousFlags;
ImPlotLocation Location; ImPlotLocation Location;
ImPlotLocation PreviousLocation; ImPlotLocation PreviousLocation;
ImVec2 Scroll;
ImVector<int> Indices; ImVector<int> Indices;
ImGuiTextBuffer Labels; ImGuiTextBuffer Labels;
ImRect Rect; ImRect Rect;
ImRect RectClamped;
bool Hovered; bool Hovered;
bool Held; bool Held;
bool CanGoInside; bool CanGoInside;
@@ -980,7 +977,6 @@ struct ImPlotLegend
CanGoInside = true; CanGoInside = true;
Hovered = Held = false; Hovered = Held = false;
Location = PreviousLocation = ImPlotLocation_NorthWest; Location = PreviousLocation = ImPlotLocation_NorthWest;
Scroll = ImVec2(0,0);
} }
void Reset() { Indices.shrink(0); Labels.Buf.shrink(0); } void Reset() { Indices.shrink(0); Labels.Buf.shrink(0); }
@@ -1140,6 +1136,7 @@ struct ImPlotSubplot {
ID = 0; ID = 0;
Flags = PreviousFlags = ImPlotSubplotFlags_None; Flags = PreviousFlags = ImPlotSubplotFlags_None;
Rows = Cols = CurrentIdx = 0; Rows = Cols = CurrentIdx = 0;
FrameHovered = false;
Items.Legend.Location = ImPlotLocation_North; Items.Legend.Location = ImPlotLocation_North;
Items.Legend.Flags = ImPlotLegendFlags_Horizontal|ImPlotLegendFlags_Outside; Items.Legend.Flags = ImPlotLegendFlags_Horizontal|ImPlotLegendFlags_Outside;
Items.Legend.CanGoInside = false; Items.Legend.CanGoInside = false;
@@ -1218,6 +1215,9 @@ struct ImPlotContext {
ImPlotAnnotationCollection Annotations; ImPlotAnnotationCollection Annotations;
ImPlotTagCollection Tags; ImPlotTagCollection Tags;
// Flags
bool ChildWindowMade;
// Style and Colormaps // Style and Colormaps
ImPlotStyle Style; ImPlotStyle Style;
ImVector<ImGuiColorMod> ColorModifiers; ImVector<ImGuiColorMod> ColorModifiers;
@@ -1414,15 +1414,13 @@ IMPLOT_API void ShowAxisContextMenu(ImPlotAxis& axis, ImPlotAxis* equal_axis, bo
// Gets the position of an inner rect that is located inside of an outer rect according to an ImPlotLocation and padding amount. // Gets the position of an inner rect that is located inside of an outer rect according to an ImPlotLocation and padding amount.
IMPLOT_API ImVec2 GetLocationPos(const ImRect& outer_rect, const ImVec2& inner_size, ImPlotLocation location, const ImVec2& pad = ImVec2(0,0)); IMPLOT_API ImVec2 GetLocationPos(const ImRect& outer_rect, const ImVec2& inner_size, ImPlotLocation location, const ImVec2& pad = ImVec2(0,0));
// Calculates the bounding box size of a legend _before_ clipping. // Calculates the bounding box size of a legend
IMPLOT_API ImVec2 CalcLegendSize(ImPlotItemGroup& items, const ImVec2& pad, const ImVec2& spacing, bool vertical); IMPLOT_API ImVec2 CalcLegendSize(ImPlotItemGroup& items, const ImVec2& pad, const ImVec2& spacing, bool vertical);
// Clips calculated legend size
IMPLOT_API bool ClampLegendRect(ImRect& legend_rect, const ImRect& outer_rect, const ImVec2& pad);
// Renders legend entries into a bounding box // Renders legend entries into a bounding box
IMPLOT_API bool ShowLegendEntries(ImPlotItemGroup& items, const ImRect& legend_bb, bool interactable, const ImVec2& pad, const ImVec2& spacing, bool vertical, ImDrawList& DrawList); IMPLOT_API bool ShowLegendEntries(ImPlotItemGroup& items, const ImRect& legend_bb, bool interactable, const ImVec2& pad, const ImVec2& spacing, bool vertical, ImDrawList& DrawList);
// Shows an alternate legend for the plot identified by #title_id, outside of the plot frame (can be called before or after of Begin/EndPlot but must occur in the same ImGui window! This is not thoroughly tested nor scrollable!). // Shows an alternate legend for the plot identified by #title_id, outside of the plot frame (can be called before or after of Begin/EndPlot but must occur in the same ImGui window!).
IMPLOT_API void ShowAltLegend(const char* title_id, bool vertical = true, const ImVec2 size = ImVec2(0,0), bool interactable = true); IMPLOT_API void ShowAltLegend(const char* title_id, bool vertical = true, const ImVec2 size = ImVec2(0,0), bool interactable = true);
// Shows a legend's context menu. // Shows an legends's context menu.
IMPLOT_API bool ShowLegendContextMenu(ImPlotLegend& legend, bool visible); IMPLOT_API bool ShowLegendContextMenu(ImPlotLegend& legend, bool visible);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View File

@@ -2,9 +2,8 @@
// This is a slightly modified version of stb_textedit.h 1.14. // This is a slightly modified version of stb_textedit.h 1.14.
// Those changes would need to be pushed into nothings/stb: // Those changes would need to be pushed into nothings/stb:
// - Fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321) // - Fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321)
// - Fix in stb_textedit_find_charpos to handle last line (see https://github.com/ocornut/imgui/issues/6000 + #6783) // - Fix in stb_textedit_find_charpos to handle last line (see https://github.com/ocornut/imgui/issues/6000)
// Grep for [DEAR IMGUI] to find the changes. // Grep for [DEAR IMGUI] to find the changes.
// - Also renamed macros used or defined outside of IMSTB_TEXTEDIT_IMPLEMENTATION block from STB_TEXTEDIT_* to IMSTB_TEXTEDIT_*
// stb_textedit.h - v1.14 - public domain - Sean Barrett // stb_textedit.h - v1.14 - public domain - Sean Barrett
// Development of this library was sponsored by RAD Game Tools // Development of this library was sponsored by RAD Game Tools
@@ -31,7 +30,7 @@
// DEPENDENCIES // DEPENDENCIES
// //
// Uses the C runtime function 'memmove', which you can override // Uses the C runtime function 'memmove', which you can override
// by defining IMSTB_TEXTEDIT_memmove before the implementation. // by defining STB_TEXTEDIT_memmove before the implementation.
// Uses no other functions. Performs no runtime allocations. // Uses no other functions. Performs no runtime allocations.
// //
// //
@@ -275,8 +274,8 @@
//// ////
//// ////
#ifndef INCLUDE_IMSTB_TEXTEDIT_H #ifndef INCLUDE_STB_TEXTEDIT_H
#define INCLUDE_IMSTB_TEXTEDIT_H #define INCLUDE_STB_TEXTEDIT_H
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// //
@@ -287,33 +286,33 @@
// and undo state. // and undo state.
// //
#ifndef IMSTB_TEXTEDIT_UNDOSTATECOUNT #ifndef STB_TEXTEDIT_UNDOSTATECOUNT
#define IMSTB_TEXTEDIT_UNDOSTATECOUNT 99 #define STB_TEXTEDIT_UNDOSTATECOUNT 99
#endif #endif
#ifndef IMSTB_TEXTEDIT_UNDOCHARCOUNT #ifndef STB_TEXTEDIT_UNDOCHARCOUNT
#define IMSTB_TEXTEDIT_UNDOCHARCOUNT 999 #define STB_TEXTEDIT_UNDOCHARCOUNT 999
#endif #endif
#ifndef IMSTB_TEXTEDIT_CHARTYPE #ifndef STB_TEXTEDIT_CHARTYPE
#define IMSTB_TEXTEDIT_CHARTYPE int #define STB_TEXTEDIT_CHARTYPE int
#endif #endif
#ifndef IMSTB_TEXTEDIT_POSITIONTYPE #ifndef STB_TEXTEDIT_POSITIONTYPE
#define IMSTB_TEXTEDIT_POSITIONTYPE int #define STB_TEXTEDIT_POSITIONTYPE int
#endif #endif
typedef struct typedef struct
{ {
// private data // private data
IMSTB_TEXTEDIT_POSITIONTYPE where; STB_TEXTEDIT_POSITIONTYPE where;
IMSTB_TEXTEDIT_POSITIONTYPE insert_length; STB_TEXTEDIT_POSITIONTYPE insert_length;
IMSTB_TEXTEDIT_POSITIONTYPE delete_length; STB_TEXTEDIT_POSITIONTYPE delete_length;
int char_storage; int char_storage;
} StbUndoRecord; } StbUndoRecord;
typedef struct typedef struct
{ {
// private data // private data
StbUndoRecord undo_rec [IMSTB_TEXTEDIT_UNDOSTATECOUNT]; StbUndoRecord undo_rec [STB_TEXTEDIT_UNDOSTATECOUNT];
IMSTB_TEXTEDIT_CHARTYPE undo_char[IMSTB_TEXTEDIT_UNDOCHARCOUNT]; STB_TEXTEDIT_CHARTYPE undo_char[STB_TEXTEDIT_UNDOCHARCOUNT];
short undo_point, redo_point; short undo_point, redo_point;
int undo_char_point, redo_char_point; int undo_char_point, redo_char_point;
} StbUndoState; } StbUndoState;
@@ -372,7 +371,7 @@ typedef struct
float ymin,ymax; // height of row above and below baseline float ymin,ymax; // height of row above and below baseline
int num_chars; int num_chars;
} StbTexteditRow; } StbTexteditRow;
#endif //INCLUDE_IMSTB_TEXTEDIT_H #endif //INCLUDE_STB_TEXTEDIT_H
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
@@ -385,11 +384,11 @@ typedef struct
// implementation isn't include-guarded, since it might have indirectly // implementation isn't include-guarded, since it might have indirectly
// included just the "header" portion // included just the "header" portion
#ifdef IMSTB_TEXTEDIT_IMPLEMENTATION #ifdef STB_TEXTEDIT_IMPLEMENTATION
#ifndef IMSTB_TEXTEDIT_memmove #ifndef STB_TEXTEDIT_memmove
#include <string.h> #include <string.h>
#define IMSTB_TEXTEDIT_memmove memmove #define STB_TEXTEDIT_memmove memmove
#endif #endif
@@ -399,7 +398,7 @@ typedef struct
// //
// traverse the layout to locate the nearest character to a display position // traverse the layout to locate the nearest character to a display position
static int stb_text_locate_coord(IMSTB_TEXTEDIT_STRING *str, float x, float y) static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y)
{ {
StbTexteditRow r; StbTexteditRow r;
int n = STB_TEXTEDIT_STRINGLEN(str); int n = STB_TEXTEDIT_STRINGLEN(str);
@@ -459,7 +458,7 @@ static int stb_text_locate_coord(IMSTB_TEXTEDIT_STRING *str, float x, float y)
} }
// API click: on mouse down, move the cursor to the clicked location, and reset the selection // API click: on mouse down, move the cursor to the clicked location, and reset the selection
static void stb_textedit_click(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) static void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
{ {
// In single-line mode, just always make y = 0. This lets the drag keep working if the mouse // In single-line mode, just always make y = 0. This lets the drag keep working if the mouse
// goes off the top or bottom of the text // goes off the top or bottom of the text
@@ -477,7 +476,7 @@ static void stb_textedit_click(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *st
} }
// API drag: on mouse drag, move the cursor and selection endpoint to the clicked location // API drag: on mouse drag, move the cursor and selection endpoint to the clicked location
static void stb_textedit_drag(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) static void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
{ {
int p = 0; int p = 0;
@@ -503,11 +502,11 @@ static void stb_textedit_drag(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *sta
// //
// forward declarations // forward declarations
static void stb_text_undo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state); static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state);
static void stb_text_redo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state); static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state);
static void stb_text_makeundo_delete(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length); static void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length);
static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length); static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length);
static void stb_text_makeundo_replace(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length); static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length);
typedef struct typedef struct
{ {
@@ -519,7 +518,7 @@ typedef struct
// find the x/y location of a character, and remember info about the previous row in // find the x/y location of a character, and remember info about the previous row in
// case we get a move-up event (for page up, we'll have to rescan) // case we get a move-up event (for page up, we'll have to rescan)
static void stb_textedit_find_charpos(StbFindState *find, IMSTB_TEXTEDIT_STRING *str, int n, int single_line) static void stb_textedit_find_charpos(StbFindState *find, STB_TEXTEDIT_STRING *str, int n, int single_line)
{ {
StbTexteditRow r; StbTexteditRow r;
int prev_start = 0; int prev_start = 0;
@@ -550,10 +549,7 @@ static void stb_textedit_find_charpos(StbFindState *find, IMSTB_TEXTEDIT_STRING
i += r.num_chars; i += r.num_chars;
find->y += r.baseline_y_delta; find->y += r.baseline_y_delta;
if (i == z) // [DEAR IMGUI] if (i == z) // [DEAR IMGUI]
{
r.num_chars = 0; // [DEAR IMGUI]
break; // [DEAR IMGUI] break; // [DEAR IMGUI]
}
} }
find->first_char = first = i; find->first_char = first = i;
@@ -570,7 +566,7 @@ static void stb_textedit_find_charpos(StbFindState *find, IMSTB_TEXTEDIT_STRING
#define STB_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end) #define STB_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end)
// make the selection/cursor state valid if client altered the string // make the selection/cursor state valid if client altered the string
static void stb_textedit_clamp(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state) static void stb_textedit_clamp(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
{ {
int n = STB_TEXTEDIT_STRINGLEN(str); int n = STB_TEXTEDIT_STRINGLEN(str);
if (STB_TEXT_HAS_SELECTION(state)) { if (STB_TEXT_HAS_SELECTION(state)) {
@@ -584,7 +580,7 @@ static void stb_textedit_clamp(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *st
} }
// delete characters while updating undo // delete characters while updating undo
static void stb_textedit_delete(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int len) static void stb_textedit_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int len)
{ {
stb_text_makeundo_delete(str, state, where, len); stb_text_makeundo_delete(str, state, where, len);
STB_TEXTEDIT_DELETECHARS(str, where, len); STB_TEXTEDIT_DELETECHARS(str, where, len);
@@ -592,7 +588,7 @@ static void stb_textedit_delete(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *s
} }
// delete the section // delete the section
static void stb_textedit_delete_selection(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state) static void stb_textedit_delete_selection(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
{ {
stb_textedit_clamp(str, state); stb_textedit_clamp(str, state);
if (STB_TEXT_HAS_SELECTION(state)) { if (STB_TEXT_HAS_SELECTION(state)) {
@@ -629,7 +625,7 @@ static void stb_textedit_move_to_first(STB_TexteditState *state)
} }
// move cursor to last character of selection // move cursor to last character of selection
static void stb_textedit_move_to_last(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state) static void stb_textedit_move_to_last(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
{ {
if (STB_TEXT_HAS_SELECTION(state)) { if (STB_TEXT_HAS_SELECTION(state)) {
stb_textedit_sortselection(state); stb_textedit_sortselection(state);
@@ -641,13 +637,13 @@ static void stb_textedit_move_to_last(IMSTB_TEXTEDIT_STRING *str, STB_TexteditSt
} }
#ifdef STB_TEXTEDIT_IS_SPACE #ifdef STB_TEXTEDIT_IS_SPACE
static int is_word_boundary( IMSTB_TEXTEDIT_STRING *str, int idx ) static int is_word_boundary( STB_TEXTEDIT_STRING *str, int idx )
{ {
return idx > 0 ? (STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str,idx-1) ) && !STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str, idx) ) ) : 1; return idx > 0 ? (STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str,idx-1) ) && !STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str, idx) ) ) : 1;
} }
#ifndef STB_TEXTEDIT_MOVEWORDLEFT #ifndef STB_TEXTEDIT_MOVEWORDLEFT
static int stb_textedit_move_to_word_previous( IMSTB_TEXTEDIT_STRING *str, int c ) static int stb_textedit_move_to_word_previous( STB_TEXTEDIT_STRING *str, int c )
{ {
--c; // always move at least one character --c; // always move at least one character
while( c >= 0 && !is_word_boundary( str, c ) ) while( c >= 0 && !is_word_boundary( str, c ) )
@@ -662,7 +658,7 @@ static int stb_textedit_move_to_word_previous( IMSTB_TEXTEDIT_STRING *str, int c
#endif #endif
#ifndef STB_TEXTEDIT_MOVEWORDRIGHT #ifndef STB_TEXTEDIT_MOVEWORDRIGHT
static int stb_textedit_move_to_word_next( IMSTB_TEXTEDIT_STRING *str, int c ) static int stb_textedit_move_to_word_next( STB_TEXTEDIT_STRING *str, int c )
{ {
const int len = STB_TEXTEDIT_STRINGLEN(str); const int len = STB_TEXTEDIT_STRINGLEN(str);
++c; // always move at least one character ++c; // always move at least one character
@@ -689,7 +685,7 @@ static void stb_textedit_prep_selection_at_cursor(STB_TexteditState *state)
} }
// API cut: delete selection // API cut: delete selection
static int stb_textedit_cut(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state) static int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
{ {
if (STB_TEXT_HAS_SELECTION(state)) { if (STB_TEXT_HAS_SELECTION(state)) {
stb_textedit_delete_selection(str,state); // implicitly clamps stb_textedit_delete_selection(str,state); // implicitly clamps
@@ -700,7 +696,7 @@ static int stb_textedit_cut(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state
} }
// API paste: replace existing selection with passed-in text // API paste: replace existing selection with passed-in text
static int stb_textedit_paste_internal(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, IMSTB_TEXTEDIT_CHARTYPE *text, int len) static int stb_textedit_paste_internal(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len)
{ {
// if there's a selection, the paste should delete it // if there's a selection, the paste should delete it
stb_textedit_clamp(str, state); stb_textedit_clamp(str, state);
@@ -721,14 +717,14 @@ static int stb_textedit_paste_internal(IMSTB_TEXTEDIT_STRING *str, STB_TexteditS
#endif #endif
// API key: process a keyboard input // API key: process a keyboard input
static void stb_textedit_key(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_KEYTYPE key) static void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_KEYTYPE key)
{ {
retry: retry:
switch (key) { switch (key) {
default: { default: {
int c = STB_TEXTEDIT_KEYTOTEXT(key); int c = STB_TEXTEDIT_KEYTOTEXT(key);
if (c > 0) { if (c > 0) {
IMSTB_TEXTEDIT_CHARTYPE ch = (IMSTB_TEXTEDIT_CHARTYPE) c; STB_TEXTEDIT_CHARTYPE ch = (STB_TEXTEDIT_CHARTYPE) c;
// can't add newline in single-line mode // can't add newline in single-line mode
if (c == '\n' && state->single_line) if (c == '\n' && state->single_line)
@@ -893,8 +889,8 @@ retry:
x = row.x0; x = row.x0;
for (i=0; i < row.num_chars; ++i) { for (i=0; i < row.num_chars; ++i) {
float dx = STB_TEXTEDIT_GETWIDTH(str, start, i); float dx = STB_TEXTEDIT_GETWIDTH(str, start, i);
#ifdef IMSTB_TEXTEDIT_GETWIDTH_NEWLINE #ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE
if (dx == IMSTB_TEXTEDIT_GETWIDTH_NEWLINE) if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE)
break; break;
#endif #endif
x += dx; x += dx;
@@ -955,8 +951,8 @@ retry:
x = row.x0; x = row.x0;
for (i=0; i < row.num_chars; ++i) { for (i=0; i < row.num_chars; ++i) {
float dx = STB_TEXTEDIT_GETWIDTH(str, find.prev_first, i); float dx = STB_TEXTEDIT_GETWIDTH(str, find.prev_first, i);
#ifdef IMSTB_TEXTEDIT_GETWIDTH_NEWLINE #ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE
if (dx == IMSTB_TEXTEDIT_GETWIDTH_NEWLINE) if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE)
break; break;
#endif #endif
x += dx; x += dx;
@@ -1113,8 +1109,8 @@ retry:
static void stb_textedit_flush_redo(StbUndoState *state) static void stb_textedit_flush_redo(StbUndoState *state)
{ {
state->redo_point = IMSTB_TEXTEDIT_UNDOSTATECOUNT; state->redo_point = STB_TEXTEDIT_UNDOSTATECOUNT;
state->redo_char_point = IMSTB_TEXTEDIT_UNDOCHARCOUNT; state->redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT;
} }
// discard the oldest entry in the undo list // discard the oldest entry in the undo list
@@ -1126,13 +1122,13 @@ static void stb_textedit_discard_undo(StbUndoState *state)
int n = state->undo_rec[0].insert_length, i; int n = state->undo_rec[0].insert_length, i;
// delete n characters from all other records // delete n characters from all other records
state->undo_char_point -= n; state->undo_char_point -= n;
IMSTB_TEXTEDIT_memmove(state->undo_char, state->undo_char + n, (size_t) (state->undo_char_point*sizeof(IMSTB_TEXTEDIT_CHARTYPE))); STB_TEXTEDIT_memmove(state->undo_char, state->undo_char + n, (size_t) (state->undo_char_point*sizeof(STB_TEXTEDIT_CHARTYPE)));
for (i=0; i < state->undo_point; ++i) for (i=0; i < state->undo_point; ++i)
if (state->undo_rec[i].char_storage >= 0) if (state->undo_rec[i].char_storage >= 0)
state->undo_rec[i].char_storage -= n; // @OPTIMIZE: get rid of char_storage and infer it state->undo_rec[i].char_storage -= n; // @OPTIMIZE: get rid of char_storage and infer it
} }
--state->undo_point; --state->undo_point;
IMSTB_TEXTEDIT_memmove(state->undo_rec, state->undo_rec+1, (size_t) (state->undo_point*sizeof(state->undo_rec[0]))); STB_TEXTEDIT_memmove(state->undo_rec, state->undo_rec+1, (size_t) (state->undo_point*sizeof(state->undo_rec[0])));
} }
} }
@@ -1142,7 +1138,7 @@ static void stb_textedit_discard_undo(StbUndoState *state)
// fill up even though the undo buffer didn't // fill up even though the undo buffer didn't
static void stb_textedit_discard_redo(StbUndoState *state) static void stb_textedit_discard_redo(StbUndoState *state)
{ {
int k = IMSTB_TEXTEDIT_UNDOSTATECOUNT-1; int k = STB_TEXTEDIT_UNDOSTATECOUNT-1;
if (state->redo_point <= k) { if (state->redo_point <= k) {
// if the k'th undo state has characters, clean those up // if the k'th undo state has characters, clean those up
@@ -1150,7 +1146,7 @@ static void stb_textedit_discard_redo(StbUndoState *state)
int n = state->undo_rec[k].insert_length, i; int n = state->undo_rec[k].insert_length, i;
// move the remaining redo character data to the end of the buffer // move the remaining redo character data to the end of the buffer
state->redo_char_point += n; state->redo_char_point += n;
IMSTB_TEXTEDIT_memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((IMSTB_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point)*sizeof(IMSTB_TEXTEDIT_CHARTYPE))); STB_TEXTEDIT_memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((STB_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point)*sizeof(STB_TEXTEDIT_CHARTYPE)));
// adjust the position of all the other records to account for above memmove // adjust the position of all the other records to account for above memmove
for (i=state->redo_point; i < k; ++i) for (i=state->redo_point; i < k; ++i)
if (state->undo_rec[i].char_storage >= 0) if (state->undo_rec[i].char_storage >= 0)
@@ -1158,12 +1154,12 @@ static void stb_textedit_discard_redo(StbUndoState *state)
} }
// now move all the redo records towards the end of the buffer; the first one is at 'redo_point' // now move all the redo records towards the end of the buffer; the first one is at 'redo_point'
// [DEAR IMGUI] // [DEAR IMGUI]
size_t move_size = (size_t)((IMSTB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point - 1) * sizeof(state->undo_rec[0])); size_t move_size = (size_t)((STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point - 1) * sizeof(state->undo_rec[0]));
const char* buf_begin = (char*)state->undo_rec; (void)buf_begin; const char* buf_begin = (char*)state->undo_rec; (void)buf_begin;
const char* buf_end = (char*)state->undo_rec + sizeof(state->undo_rec); (void)buf_end; const char* buf_end = (char*)state->undo_rec + sizeof(state->undo_rec); (void)buf_end;
IM_ASSERT(((char*)(state->undo_rec + state->redo_point)) >= buf_begin); IM_ASSERT(((char*)(state->undo_rec + state->redo_point)) >= buf_begin);
IM_ASSERT(((char*)(state->undo_rec + state->redo_point + 1) + move_size) <= buf_end); IM_ASSERT(((char*)(state->undo_rec + state->redo_point + 1) + move_size) <= buf_end);
IMSTB_TEXTEDIT_memmove(state->undo_rec + state->redo_point+1, state->undo_rec + state->redo_point, move_size); STB_TEXTEDIT_memmove(state->undo_rec + state->redo_point+1, state->undo_rec + state->redo_point, move_size);
// now move redo_point to point to the new one // now move redo_point to point to the new one
++state->redo_point; ++state->redo_point;
@@ -1177,32 +1173,32 @@ static StbUndoRecord *stb_text_create_undo_record(StbUndoState *state, int numch
// if we have no free records, we have to make room, by sliding the // if we have no free records, we have to make room, by sliding the
// existing records down // existing records down
if (state->undo_point == IMSTB_TEXTEDIT_UNDOSTATECOUNT) if (state->undo_point == STB_TEXTEDIT_UNDOSTATECOUNT)
stb_textedit_discard_undo(state); stb_textedit_discard_undo(state);
// if the characters to store won't possibly fit in the buffer, we can't undo // if the characters to store won't possibly fit in the buffer, we can't undo
if (numchars > IMSTB_TEXTEDIT_UNDOCHARCOUNT) { if (numchars > STB_TEXTEDIT_UNDOCHARCOUNT) {
state->undo_point = 0; state->undo_point = 0;
state->undo_char_point = 0; state->undo_char_point = 0;
return NULL; return NULL;
} }
// if we don't have enough free characters in the buffer, we have to make room // if we don't have enough free characters in the buffer, we have to make room
while (state->undo_char_point + numchars > IMSTB_TEXTEDIT_UNDOCHARCOUNT) while (state->undo_char_point + numchars > STB_TEXTEDIT_UNDOCHARCOUNT)
stb_textedit_discard_undo(state); stb_textedit_discard_undo(state);
return &state->undo_rec[state->undo_point++]; return &state->undo_rec[state->undo_point++];
} }
static IMSTB_TEXTEDIT_CHARTYPE *stb_text_createundo(StbUndoState *state, int pos, int insert_len, int delete_len) static STB_TEXTEDIT_CHARTYPE *stb_text_createundo(StbUndoState *state, int pos, int insert_len, int delete_len)
{ {
StbUndoRecord *r = stb_text_create_undo_record(state, insert_len); StbUndoRecord *r = stb_text_create_undo_record(state, insert_len);
if (r == NULL) if (r == NULL)
return NULL; return NULL;
r->where = pos; r->where = pos;
r->insert_length = (IMSTB_TEXTEDIT_POSITIONTYPE) insert_len; r->insert_length = (STB_TEXTEDIT_POSITIONTYPE) insert_len;
r->delete_length = (IMSTB_TEXTEDIT_POSITIONTYPE) delete_len; r->delete_length = (STB_TEXTEDIT_POSITIONTYPE) delete_len;
if (insert_len == 0) { if (insert_len == 0) {
r->char_storage = -1; r->char_storage = -1;
@@ -1214,7 +1210,7 @@ static IMSTB_TEXTEDIT_CHARTYPE *stb_text_createundo(StbUndoState *state, int pos
} }
} }
static void stb_text_undo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state) static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
{ {
StbUndoState *s = &state->undostate; StbUndoState *s = &state->undostate;
StbUndoRecord u, *r; StbUndoRecord u, *r;
@@ -1241,7 +1237,7 @@ static void stb_text_undo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
// characters stored for *undoing* don't leave room for redo // characters stored for *undoing* don't leave room for redo
// if the last is true, we have to bail // if the last is true, we have to bail
if (s->undo_char_point + u.delete_length >= IMSTB_TEXTEDIT_UNDOCHARCOUNT) { if (s->undo_char_point + u.delete_length >= STB_TEXTEDIT_UNDOCHARCOUNT) {
// the undo records take up too much character space; there's no space to store the redo characters // the undo records take up too much character space; there's no space to store the redo characters
r->insert_length = 0; r->insert_length = 0;
} else { } else {
@@ -1250,7 +1246,7 @@ static void stb_text_undo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
// there's definitely room to store the characters eventually // there's definitely room to store the characters eventually
while (s->undo_char_point + u.delete_length > s->redo_char_point) { while (s->undo_char_point + u.delete_length > s->redo_char_point) {
// should never happen: // should never happen:
if (s->redo_point == IMSTB_TEXTEDIT_UNDOSTATECOUNT) if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT)
return; return;
// there's currently not enough room, so discard a redo record // there's currently not enough room, so discard a redo record
stb_textedit_discard_redo(s); stb_textedit_discard_redo(s);
@@ -1282,11 +1278,11 @@ static void stb_text_undo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
s->redo_point--; s->redo_point--;
} }
static void stb_text_redo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state) static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
{ {
StbUndoState *s = &state->undostate; StbUndoState *s = &state->undostate;
StbUndoRecord *u, r; StbUndoRecord *u, r;
if (s->redo_point == IMSTB_TEXTEDIT_UNDOSTATECOUNT) if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT)
return; return;
// we need to do two things: apply the redo record, and create an undo record // we need to do two things: apply the redo record, and create an undo record
@@ -1338,20 +1334,20 @@ static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int le
stb_text_createundo(&state->undostate, where, 0, length); stb_text_createundo(&state->undostate, where, 0, length);
} }
static void stb_text_makeundo_delete(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length) static void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length)
{ {
int i; int i;
IMSTB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, length, 0); STB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, length, 0);
if (p) { if (p) {
for (i=0; i < length; ++i) for (i=0; i < length; ++i)
p[i] = STB_TEXTEDIT_GETCHAR(str, where+i); p[i] = STB_TEXTEDIT_GETCHAR(str, where+i);
} }
} }
static void stb_text_makeundo_replace(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length) static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length)
{ {
int i; int i;
IMSTB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, old_length, new_length); STB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, old_length, new_length);
if (p) { if (p) {
for (i=0; i < old_length; ++i) for (i=0; i < old_length; ++i)
p[i] = STB_TEXTEDIT_GETCHAR(str, where+i); p[i] = STB_TEXTEDIT_GETCHAR(str, where+i);
@@ -1363,8 +1359,8 @@ static void stb_textedit_clear_state(STB_TexteditState *state, int is_single_lin
{ {
state->undostate.undo_point = 0; state->undostate.undo_point = 0;
state->undostate.undo_char_point = 0; state->undostate.undo_char_point = 0;
state->undostate.redo_point = IMSTB_TEXTEDIT_UNDOSTATECOUNT; state->undostate.redo_point = STB_TEXTEDIT_UNDOSTATECOUNT;
state->undostate.redo_char_point = IMSTB_TEXTEDIT_UNDOCHARCOUNT; state->undostate.redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT;
state->select_end = state->select_start = 0; state->select_end = state->select_start = 0;
state->cursor = 0; state->cursor = 0;
state->has_preferred_x = 0; state->has_preferred_x = 0;
@@ -1387,16 +1383,16 @@ static void stb_textedit_initialize_state(STB_TexteditState *state, int is_singl
#pragma GCC diagnostic ignored "-Wcast-qual" #pragma GCC diagnostic ignored "-Wcast-qual"
#endif #endif
static int stb_textedit_paste(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, IMSTB_TEXTEDIT_CHARTYPE const *ctext, int len) static int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE const *ctext, int len)
{ {
return stb_textedit_paste_internal(str, state, (IMSTB_TEXTEDIT_CHARTYPE *) ctext, len); return stb_textedit_paste_internal(str, state, (STB_TEXTEDIT_CHARTYPE *) ctext, len);
} }
#if defined(__GNUC__) || defined(__clang__) #if defined(__GNUC__) || defined(__clang__)
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#endif #endif
#endif//IMSTB_TEXTEDIT_IMPLEMENTATION #endif//STB_TEXTEDIT_IMPLEMENTATION
/* /*
------------------------------------------------------------------------------ ------------------------------------------------------------------------------

View File

@@ -6,14 +6,13 @@
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (minor and older changes stripped away, please see git history for details)
// 2023/11/13: added support for ImFontConfig::RasterizationDensity field for scaling render density without scaling metrics.
// 2023/08/01: added support for SVG fonts, enable by using '#define IMGUI_ENABLE_FREETYPE_LUNASVG' (#6591)
// 2023/01/04: fixed a packing issue which in some occurrences would prevent large amount of glyphs from being packed correctly. // 2023/01/04: fixed a packing issue which in some occurrences would prevent large amount of glyphs from being packed correctly.
// 2021/08/23: fixed crash when FT_Render_Glyph() fails to render a glyph and returns NULL. // 2021/08/23: fixed crash when FT_Render_Glyph() fails to render a glyph and returns NULL.
// 2021/03/05: added ImGuiFreeTypeBuilderFlags_Bitmap to load bitmap glyphs. // 2021/03/05: added ImGuiFreeTypeBuilderFlags_Bitmap to load bitmap glyphs.
// 2021/03/02: set 'atlas->TexPixelsUseColors = true' to help some backends with deciding of a prefered texture format. // 2021/03/02: set 'atlas->TexPixelsUseColors = true' to help some backends with deciding of a prefered texture format.
// 2021/01/28: added support for color-layered glyphs via ImGuiFreeTypeBuilderFlags_LoadColor (require Freetype 2.10+). // 2021/01/28: added support for color-layered glyphs via ImGuiFreeTypeBuilderFlags_LoadColor (require Freetype 2.10+).
// 2021/01/26: simplified integration by using '#define IMGUI_ENABLE_FREETYPE'. renamed ImGuiFreeType::XXX flags to ImGuiFreeTypeBuilderFlags_XXX for consistency with other API. removed ImGuiFreeType::BuildFontAtlas(). // 2021/01/26: simplified integration by using '#define IMGUI_ENABLE_FREETYPE'.
// renamed ImGuiFreeType::XXX flags to ImGuiFreeTypeBuilderFlags_XXX for consistency with other API. removed ImGuiFreeType::BuildFontAtlas().
// 2020/06/04: fix for rare case where FT_Get_Char_Index() succeed but FT_Load_Glyph() fails. // 2020/06/04: fix for rare case where FT_Get_Char_Index() succeed but FT_Load_Glyph() fails.
// 2019/02/09: added RasterizerFlags::Monochrome flag to disable font anti-aliasing (combine with ::MonoHinting for best results!) // 2019/02/09: added RasterizerFlags::Monochrome flag to disable font anti-aliasing (combine with ::MonoHinting for best results!)
// 2019/01/15: added support for imgui allocators + added FreeType only override function SetAllocatorFunctions(). // 2019/01/15: added support for imgui allocators + added FreeType only override function SetAllocatorFunctions().
@@ -34,8 +33,6 @@
// FIXME: cfg.OversampleH, OversampleV are not supported (but perhaps not so necessary with this rasterizer). // FIXME: cfg.OversampleH, OversampleV are not supported (but perhaps not so necessary with this rasterizer).
#include "imgui.h"
#ifndef IMGUI_DISABLE
#include "imgui_freetype.h" #include "imgui_freetype.h"
#include "imgui_internal.h" // ImMin,ImMax,ImFontAtlasBuild*, #include "imgui_internal.h" // ImMin,ImMax,ImFontAtlasBuild*,
#include <stdint.h> #include <stdint.h>
@@ -45,15 +42,6 @@
#include FT_GLYPH_H // <freetype/ftglyph.h> #include FT_GLYPH_H // <freetype/ftglyph.h>
#include FT_SYNTHESIS_H // <freetype/ftsynth.h> #include FT_SYNTHESIS_H // <freetype/ftsynth.h>
#ifdef IMGUI_ENABLE_FREETYPE_LUNASVG
#include FT_OTSVG_H // <freetype/otsvg.h>
#include FT_BBOX_H // <freetype/ftbbox.h>
#include <lunasvg.h>
#if !((FREETYPE_MAJOR >= 2) && (FREETYPE_MINOR >= 12))
#error IMGUI_ENABLE_FREETYPE_LUNASVG requires FreeType version >= 2.12
#endif
#endif
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning (push) #pragma warning (push)
#pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff) #pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff)
@@ -64,10 +52,8 @@
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
#pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used #pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used
#ifndef __clang__
#pragma GCC diagnostic ignored "-Wsubobject-linkage" // warning: 'xxxx' has a field 'xxxx' whose type uses the anonymous namespace #pragma GCC diagnostic ignored "-Wsubobject-linkage" // warning: 'xxxx' has a field 'xxxx' whose type uses the anonymous namespace
#endif #endif
#endif
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// Data // Data
@@ -82,14 +68,6 @@ static void* (*GImGuiFreeTypeAllocFunc)(size_t size, void* user_data) = ImGuiFre
static void (*GImGuiFreeTypeFreeFunc)(void* ptr, void* user_data) = ImGuiFreeTypeDefaultFreeFunc; static void (*GImGuiFreeTypeFreeFunc)(void* ptr, void* user_data) = ImGuiFreeTypeDefaultFreeFunc;
static void* GImGuiFreeTypeAllocatorUserData = nullptr; static void* GImGuiFreeTypeAllocatorUserData = nullptr;
// Lunasvg support
#ifdef IMGUI_ENABLE_FREETYPE_LUNASVG
static FT_Error ImGuiLunasvgPortInit(FT_Pointer* state);
static void ImGuiLunasvgPortFree(FT_Pointer* state);
static FT_Error ImGuiLunasvgPortRender(FT_GlyphSlot slot, FT_Pointer* _state);
static FT_Error ImGuiLunasvgPortPresetSlot(FT_GlyphSlot slot, FT_Bool cache, FT_Pointer* _state);
#endif
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// Code // Code
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
@@ -167,8 +145,6 @@ namespace
unsigned int UserFlags; // = ImFontConfig::RasterizerFlags unsigned int UserFlags; // = ImFontConfig::RasterizerFlags
FT_Int32 LoadFlags; FT_Int32 LoadFlags;
FT_Render_Mode RenderMode; FT_Render_Mode RenderMode;
float RasterizationDensity;
float InvRasterizationDensity;
}; };
// From SDL_ttf: Handy routines for converting from fixed point // From SDL_ttf: Handy routines for converting from fixed point
@@ -211,9 +187,6 @@ namespace
if (UserFlags & ImGuiFreeTypeBuilderFlags_LoadColor) if (UserFlags & ImGuiFreeTypeBuilderFlags_LoadColor)
LoadFlags |= FT_LOAD_COLOR; LoadFlags |= FT_LOAD_COLOR;
RasterizationDensity = cfg.RasterizerDensity;
InvRasterizationDensity = 1.0f / RasterizationDensity;
memset(&Info, 0, sizeof(Info)); memset(&Info, 0, sizeof(Info));
SetPixelHeight((uint32_t)cfg.SizePixels); SetPixelHeight((uint32_t)cfg.SizePixels);
@@ -237,19 +210,19 @@ namespace
FT_Size_RequestRec req; FT_Size_RequestRec req;
req.type = (UserFlags & ImGuiFreeTypeBuilderFlags_Bitmap) ? FT_SIZE_REQUEST_TYPE_NOMINAL : FT_SIZE_REQUEST_TYPE_REAL_DIM; req.type = (UserFlags & ImGuiFreeTypeBuilderFlags_Bitmap) ? FT_SIZE_REQUEST_TYPE_NOMINAL : FT_SIZE_REQUEST_TYPE_REAL_DIM;
req.width = 0; req.width = 0;
req.height = (uint32_t)(pixel_height * 64 * RasterizationDensity); req.height = (uint32_t)pixel_height * 64;
req.horiResolution = 0; req.horiResolution = 0;
req.vertResolution = 0; req.vertResolution = 0;
FT_Request_Size(Face, &req); FT_Request_Size(Face, &req);
// Update font info // Update font info
FT_Size_Metrics metrics = Face->size->metrics; FT_Size_Metrics metrics = Face->size->metrics;
Info.PixelHeight = (uint32_t)(pixel_height * InvRasterizationDensity); Info.PixelHeight = (uint32_t)pixel_height;
Info.Ascender = (float)FT_CEIL(metrics.ascender) * InvRasterizationDensity; Info.Ascender = (float)FT_CEIL(metrics.ascender);
Info.Descender = (float)FT_CEIL(metrics.descender) * InvRasterizationDensity; Info.Descender = (float)FT_CEIL(metrics.descender);
Info.LineSpacing = (float)FT_CEIL(metrics.height) * InvRasterizationDensity; Info.LineSpacing = (float)FT_CEIL(metrics.height);
Info.LineGap = (float)FT_CEIL(metrics.height - metrics.ascender + metrics.descender) * InvRasterizationDensity; Info.LineGap = (float)FT_CEIL(metrics.height - metrics.ascender + metrics.descender);
Info.MaxAdvanceWidth = (float)FT_CEIL(metrics.max_advance) * InvRasterizationDensity; Info.MaxAdvanceWidth = (float)FT_CEIL(metrics.max_advance);
} }
const FT_Glyph_Metrics* FreeTypeFont::LoadGlyph(uint32_t codepoint) const FT_Glyph_Metrics* FreeTypeFont::LoadGlyph(uint32_t codepoint)
@@ -269,14 +242,7 @@ namespace
// Need an outline for this to work // Need an outline for this to work
FT_GlyphSlot slot = Face->glyph; FT_GlyphSlot slot = Face->glyph;
#ifdef IMGUI_ENABLE_FREETYPE_LUNASVG
IM_ASSERT(slot->format == FT_GLYPH_FORMAT_OUTLINE || slot->format == FT_GLYPH_FORMAT_BITMAP || slot->format == FT_GLYPH_FORMAT_SVG);
#else
#if ((FREETYPE_MAJOR >= 2) && (FREETYPE_MINOR >= 12))
IM_ASSERT(slot->format != FT_GLYPH_FORMAT_SVG && "The font contains SVG glyphs, you'll need to enable IMGUI_ENABLE_FREETYPE_LUNASVG in imconfig.h and install required libraries in order to use this font");
#endif
IM_ASSERT(slot->format == FT_GLYPH_FORMAT_OUTLINE || slot->format == FT_GLYPH_FORMAT_BITMAP); IM_ASSERT(slot->format == FT_GLYPH_FORMAT_OUTLINE || slot->format == FT_GLYPH_FORMAT_BITMAP);
#endif // IMGUI_ENABLE_FREETYPE_LUNASVG
// Apply convenience transform (this is not picking from real "Bold"/"Italic" fonts! Merely applying FreeType helper transform. Oblique == Slanting) // Apply convenience transform (this is not picking from real "Bold"/"Italic" fonts! Merely applying FreeType helper transform. Oblique == Slanting)
if (UserFlags & ImGuiFreeTypeBuilderFlags_Bold) if (UserFlags & ImGuiFreeTypeBuilderFlags_Bold)
@@ -437,7 +403,7 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u
ImFontAtlasBuildInit(atlas); ImFontAtlasBuildInit(atlas);
// Clear atlas // Clear atlas
atlas->TexID = 0; atlas->TexID = (ImTextureID)nullptr;
atlas->TexWidth = atlas->TexHeight = 0; atlas->TexWidth = atlas->TexHeight = 0;
atlas->TexUvScale = ImVec2(0.0f, 0.0f); atlas->TexUvScale = ImVec2(0.0f, 0.0f);
atlas->TexUvWhitePixel = ImVec2(0.0f, 0.0f); atlas->TexUvWhitePixel = ImVec2(0.0f, 0.0f);
@@ -703,15 +669,15 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u
const int ty = pack_rect.y + padding; const int ty = pack_rect.y + padding;
// Register glyph // Register glyph
float x0 = info.OffsetX * src_tmp.Font.InvRasterizationDensity + font_off_x; float x0 = info.OffsetX + font_off_x;
float y0 = info.OffsetY * src_tmp.Font.InvRasterizationDensity + font_off_y; float y0 = info.OffsetY + font_off_y;
float x1 = x0 + info.Width * src_tmp.Font.InvRasterizationDensity; float x1 = x0 + info.Width;
float y1 = y0 + info.Height * src_tmp.Font.InvRasterizationDensity; float y1 = y0 + info.Height;
float u0 = (tx) / (float)atlas->TexWidth; float u0 = (tx) / (float)atlas->TexWidth;
float v0 = (ty) / (float)atlas->TexHeight; float v0 = (ty) / (float)atlas->TexHeight;
float u1 = (tx + info.Width) / (float)atlas->TexWidth; float u1 = (tx + info.Width) / (float)atlas->TexWidth;
float v1 = (ty + info.Height) / (float)atlas->TexHeight; float v1 = (ty + info.Height) / (float)atlas->TexHeight;
dst_font->AddGlyph(&cfg, (ImWchar)src_glyph.Codepoint, x0, y0, x1, y1, u0, v0, u1, v1, info.AdvanceX * src_tmp.Font.InvRasterizationDensity); dst_font->AddGlyph(&cfg, (ImWchar)src_glyph.Codepoint, x0, y0, x1, y1, u0, v0, u1, v1, info.AdvanceX);
ImFontGlyph* dst_glyph = &dst_font->Glyphs.back(); ImFontGlyph* dst_glyph = &dst_font->Glyphs.back();
IM_ASSERT(dst_glyph->Codepoint == src_glyph.Codepoint); IM_ASSERT(dst_glyph->Codepoint == src_glyph.Codepoint);
@@ -804,14 +770,6 @@ static bool ImFontAtlasBuildWithFreeType(ImFontAtlas* atlas)
// If you don't call FT_Add_Default_Modules() the rest of code may work, but FreeType won't use our custom allocator. // If you don't call FT_Add_Default_Modules() the rest of code may work, but FreeType won't use our custom allocator.
FT_Add_Default_Modules(ft_library); FT_Add_Default_Modules(ft_library);
#ifdef IMGUI_ENABLE_FREETYPE_LUNASVG
// Install svg hooks for FreeType
// https://freetype.org/freetype2/docs/reference/ft2-properties.html#svg-hooks
// https://freetype.org/freetype2/docs/reference/ft2-svg_fonts.html#svg_fonts
SVG_RendererHooks hooks = { ImGuiLunasvgPortInit, ImGuiLunasvgPortFree, ImGuiLunasvgPortRender, ImGuiLunasvgPortPresetSlot };
FT_Property_Set(ft_library, "ot-svg", "svg-hooks", &hooks);
#endif // IMGUI_ENABLE_FREETYPE_LUNASVG
bool ret = ImFontAtlasBuildWithFreeTypeEx(ft_library, atlas, atlas->FontBuilderFlags); bool ret = ImFontAtlasBuildWithFreeTypeEx(ft_library, atlas, atlas->FontBuilderFlags);
FT_Done_Library(ft_library); FT_Done_Library(ft_library);
@@ -832,115 +790,6 @@ void ImGuiFreeType::SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* u
GImGuiFreeTypeAllocatorUserData = user_data; GImGuiFreeTypeAllocatorUserData = user_data;
} }
#ifdef IMGUI_ENABLE_FREETYPE_LUNASVG
// For more details, see https://gitlab.freedesktop.org/freetype/freetype-demos/-/blob/master/src/rsvg-port.c
// The original code from the demo is licensed under CeCILL-C Free Software License Agreement (https://gitlab.freedesktop.org/freetype/freetype/-/blob/master/LICENSE.TXT)
struct LunasvgPortState
{
FT_Error err = FT_Err_Ok;
lunasvg::Matrix matrix;
std::unique_ptr<lunasvg::Document> svg = nullptr;
};
static FT_Error ImGuiLunasvgPortInit(FT_Pointer* _state)
{
*_state = IM_NEW(LunasvgPortState)();
return FT_Err_Ok;
}
static void ImGuiLunasvgPortFree(FT_Pointer* _state)
{
IM_DELETE(*(LunasvgPortState**)_state);
}
static FT_Error ImGuiLunasvgPortRender(FT_GlyphSlot slot, FT_Pointer* _state)
{
LunasvgPortState* state = *(LunasvgPortState**)_state;
// If there was an error while loading the svg in ImGuiLunasvgPortPresetSlot(), the renderer hook still get called, so just returns the error.
if (state->err != FT_Err_Ok)
return state->err;
// rows is height, pitch (or stride) equals to width * sizeof(int32)
lunasvg::Bitmap bitmap((uint8_t*)slot->bitmap.buffer, slot->bitmap.width, slot->bitmap.rows, slot->bitmap.pitch);
state->svg->setMatrix(state->svg->matrix().identity()); // Reset the svg matrix to the default value
state->svg->render(bitmap, state->matrix); // state->matrix is already scaled and translated
state->err = FT_Err_Ok;
return state->err;
}
static FT_Error ImGuiLunasvgPortPresetSlot(FT_GlyphSlot slot, FT_Bool cache, FT_Pointer* _state)
{
FT_SVG_Document document = (FT_SVG_Document)slot->other;
LunasvgPortState* state = *(LunasvgPortState**)_state;
FT_Size_Metrics& metrics = document->metrics;
// This function is called twice, once in the FT_Load_Glyph() and another right before ImGuiLunasvgPortRender().
// If it's the latter, don't do anything because it's // already done in the former.
if (cache)
return state->err;
state->svg = lunasvg::Document::loadFromData((const char*)document->svg_document, document->svg_document_length);
if (state->svg == nullptr)
{
state->err = FT_Err_Invalid_SVG_Document;
return state->err;
}
lunasvg::Box box = state->svg->box();
double scale = std::min(metrics.x_ppem / box.w, metrics.y_ppem / box.h);
double xx = (double)document->transform.xx / (1 << 16);
double xy = -(double)document->transform.xy / (1 << 16);
double yx = -(double)document->transform.yx / (1 << 16);
double yy = (double)document->transform.yy / (1 << 16);
double x0 = (double)document->delta.x / 64 * box.w / metrics.x_ppem;
double y0 = -(double)document->delta.y / 64 * box.h / metrics.y_ppem;
// Scale and transform, we don't translate the svg yet
state->matrix.identity();
state->matrix.scale(scale, scale);
state->matrix.transform(xx, xy, yx, yy, x0, y0);
state->svg->setMatrix(state->matrix);
// Pre-translate the matrix for the rendering step
state->matrix.translate(-box.x, -box.y);
// Get the box again after the transformation
box = state->svg->box();
// Calculate the bitmap size
slot->bitmap_left = FT_Int(box.x);
slot->bitmap_top = FT_Int(-box.y);
slot->bitmap.rows = (unsigned int)(ImCeil((float)box.h));
slot->bitmap.width = (unsigned int)(ImCeil((float)box.w));
slot->bitmap.pitch = slot->bitmap.width * 4;
slot->bitmap.pixel_mode = FT_PIXEL_MODE_BGRA;
// Compute all the bearings and set them correctly. The outline is scaled already, we just need to use the bounding box.
double metrics_width = box.w;
double metrics_height = box.h;
double horiBearingX = box.x;
double horiBearingY = -box.y;
double vertBearingX = slot->metrics.horiBearingX / 64.0 - slot->metrics.horiAdvance / 64.0 / 2.0;
double vertBearingY = (slot->metrics.vertAdvance / 64.0 - slot->metrics.height / 64.0) / 2.0;
slot->metrics.width = FT_Pos(IM_ROUND(metrics_width * 64.0)); // Using IM_ROUND() assume width and height are positive
slot->metrics.height = FT_Pos(IM_ROUND(metrics_height * 64.0));
slot->metrics.horiBearingX = FT_Pos(horiBearingX * 64);
slot->metrics.horiBearingY = FT_Pos(horiBearingY * 64);
slot->metrics.vertBearingX = FT_Pos(vertBearingX * 64);
slot->metrics.vertBearingY = FT_Pos(vertBearingY * 64);
if (slot->metrics.vertAdvance == 0)
slot->metrics.vertAdvance = FT_Pos(metrics_height * 1.2 * 64.0);
state->err = FT_Err_Ok;
return state->err;
}
#endif // #ifdef IMGUI_ENABLE_FREETYPE_LUNASVG
//-----------------------------------------------------------------------------
#ifdef __GNUC__ #ifdef __GNUC__
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#endif #endif
@@ -948,5 +797,3 @@ static FT_Error ImGuiLunasvgPortPresetSlot(FT_GlyphSlot slot, FT_Bool cache, FT_
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning (pop) #pragma warning (pop)
#endif #endif
#endif // #ifndef IMGUI_DISABLE

View File

@@ -2,8 +2,8 @@
// (headers) // (headers)
#pragma once #pragma once
#include "imgui.h" // IMGUI_API #include "imgui.h" // IMGUI_API
#ifndef IMGUI_DISABLE
// Forward declarations // Forward declarations
struct ImFontAtlas; struct ImFontAtlas;
@@ -43,9 +43,8 @@ namespace ImGuiFreeType
IMGUI_API void SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void (*free_func)(void* ptr, void* user_data), void* user_data = nullptr); IMGUI_API void SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void (*free_func)(void* ptr, void* user_data), void* user_data = nullptr);
// Obsolete names (will be removed soon) // Obsolete names (will be removed soon)
// Prefer using '#define IMGUI_ENABLE_FREETYPE'
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
//static inline bool BuildFontAtlas(ImFontAtlas* atlas, unsigned int flags = 0) { atlas->FontBuilderIO = GetBuilderForFreeType(); atlas->FontBuilderFlags = flags; return atlas->Build(); } // Prefer using '#define IMGUI_ENABLE_FREETYPE' static inline bool BuildFontAtlas(ImFontAtlas* atlas, unsigned int flags = 0) { atlas->FontBuilderIO = GetBuilderForFreeType(); atlas->FontBuilderFlags = flags; return atlas->Build(); }
#endif #endif
} }
#endif // #ifndef IMGUI_DISABLE

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -16,19 +16,12 @@
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// Learn about Dear ImGui: // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// - FAQ https://dearimgui.com/faq // Read online: https://github.com/ocornut/imgui/tree/master/docs
// - Getting Started https://dearimgui.com/getting-started
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
// - Introduction, links and more at the top of imgui.cpp
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (minor and older changes stripped away, please see git history for details)
// 2023-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. // 2023-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 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)
// 2023-06-12: Accept glfwGetTime() not returning a monotonically increasing value. This seems to happens on some Windows setup when peripherals disconnect, and is likely to also happen on browser + Emscripten. (#6491)
// 2023-04-04: Inputs: Added support for io.AddMouseSourceEvent() to discriminate ImGuiMouseSource_Mouse/ImGuiMouseSource_TouchScreen/ImGuiMouseSource_Pen on Windows ONLY, using a custom WndProc hook. (#2702) // 2023-04-04: Inputs: Added support for io.AddMouseSourceEvent() to discriminate ImGuiMouseSource_Mouse/ImGuiMouseSource_TouchScreen/ImGuiMouseSource_Pen on Windows ONLY, using a custom WndProc hook. (#2702)
// 2023-03-16: Inputs: Fixed key modifiers handling on secondary viewports (docking branch). Broken on 2023/01/04. (#6248, #6034) // 2023-03-16: Inputs: Fixed key modifiers handling on secondary viewports (docking branch). Broken on 2023/01/04. (#6248, #6034)
// 2023-03-14: Emscripten: Avoid using glfwGetError() and glfwGetGamepadState() which are not correctly implemented in Emscripten emulation. (#6240) // 2023-03-14: Emscripten: Avoid using glfwGetError() and glfwGetGamepadState() which are not correctly implemented in Emscripten emulation. (#6240)
@@ -39,7 +32,7 @@
// 2022-10-18: Perform a dummy glfwGetError() read to cancel missing mouse cursors errors. Using GLFW_VERSION_COMBINED directly. (#5785) // 2022-10-18: Perform a dummy glfwGetError() read to cancel missing mouse cursors errors. Using GLFW_VERSION_COMBINED directly. (#5785)
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11. // 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
// 2022-09-26: Inputs: Renamed ImGuiKey_ModXXX introduced in 1.87 to ImGuiMod_XXX (old names still supported). // 2022-09-26: Inputs: Renamed ImGuiKey_ModXXX introduced in 1.87 to ImGuiMod_XXX (old names still supported).
// 2022-09-01: Inputs: Honor GLFW_CURSOR_DISABLED by not setting mouse position *EDIT* Reverted 2023-07-18. // 2022-09-01: Inputs: Honor GLFW_CURSOR_DISABLED by not setting mouse position.
// 2022-04-30: Inputs: Fixed ImGui_ImplGlfw_TranslateUntranslatedKey() for lower case letters on OSX. // 2022-04-30: Inputs: Fixed ImGui_ImplGlfw_TranslateUntranslatedKey() for lower case letters on OSX.
// 2022-03-23: Inputs: Fixed a regression in 1.87 which resulted in keyboard modifiers events being reported incorrectly on Linux/X11. // 2022-03-23: Inputs: Fixed a regression in 1.87 which resulted in keyboard modifiers events being reported incorrectly on Linux/X11.
// 2022-02-07: Added ImGui_ImplGlfw_InstallCallbacks()/ImGui_ImplGlfw_RestoreCallbacks() helpers to facilitate user installing callbacks after initializing backend. // 2022-02-07: Added ImGui_ImplGlfw_InstallCallbacks()/ImGui_ImplGlfw_RestoreCallbacks() helpers to facilitate user installing callbacks after initializing backend.
@@ -76,7 +69,6 @@
// 2016-10-15: Misc: Added a void* user_data parameter to Clipboard function handlers. // 2016-10-15: Misc: Added a void* user_data parameter to Clipboard function handlers.
#include "imgui.h" #include "imgui.h"
#ifndef IMGUI_DISABLE
#include "imgui_impl_glfw.h" #include "imgui_impl_glfw.h"
// Clang warnings with -Weverything // Clang warnings with -Weverything
@@ -107,11 +99,6 @@
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
#include <emscripten.h> #include <emscripten.h>
#include <emscripten/html5.h> #include <emscripten/html5.h>
// IMHEX PATCH BEGIN
#include <emscripten_browser_clipboard.h>
static std::string clipboardContent;
// IMHEX PATCH END
#endif #endif
// We gather version tests as define in order to easily see which features are version-dependent. // We gather version tests as define in order to easily see which features are version-dependent.
@@ -120,11 +107,7 @@ static std::string clipboardContent;
#define GLFW_HAS_WINDOW_HOVERED (GLFW_VERSION_COMBINED >= 3300) // 3.3+ GLFW_HOVERED #define GLFW_HAS_WINDOW_HOVERED (GLFW_VERSION_COMBINED >= 3300) // 3.3+ GLFW_HOVERED
#define GLFW_HAS_WINDOW_ALPHA (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwSetWindowOpacity #define GLFW_HAS_WINDOW_ALPHA (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwSetWindowOpacity
#define GLFW_HAS_PER_MONITOR_DPI (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwGetMonitorContentScale #define GLFW_HAS_PER_MONITOR_DPI (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwGetMonitorContentScale
#if defined(__EMSCRIPTEN__) || defined(__SWITCH__) // no Vulkan support in GLFW for Emscripten or homebrew Nintendo Switch
#define GLFW_HAS_VULKAN (0)
#else
#define GLFW_HAS_VULKAN (GLFW_VERSION_COMBINED >= 3200) // 3.2+ glfwCreateWindowSurface #define GLFW_HAS_VULKAN (GLFW_VERSION_COMBINED >= 3200) // 3.2+ glfwCreateWindowSurface
#endif
#define GLFW_HAS_FOCUS_WINDOW (GLFW_VERSION_COMBINED >= 3200) // 3.2+ glfwFocusWindow #define GLFW_HAS_FOCUS_WINDOW (GLFW_VERSION_COMBINED >= 3200) // 3.2+ glfwFocusWindow
#define GLFW_HAS_FOCUS_ON_SHOW (GLFW_VERSION_COMBINED >= 3300) // 3.3+ GLFW_FOCUS_ON_SHOW #define GLFW_HAS_FOCUS_ON_SHOW (GLFW_VERSION_COMBINED >= 3300) // 3.3+ GLFW_FOCUS_ON_SHOW
#define GLFW_HAS_MONITOR_WORK_AREA (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwGetMonitorWorkarea #define GLFW_HAS_MONITOR_WORK_AREA (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwGetMonitorWorkarea
@@ -143,12 +126,14 @@ static std::string clipboardContent;
#define GLFW_HAS_GETKEYNAME (GLFW_VERSION_COMBINED >= 3200) // 3.2+ glfwGetKeyName() #define GLFW_HAS_GETKEYNAME (GLFW_VERSION_COMBINED >= 3200) // 3.2+ glfwGetKeyName()
#define GLFW_HAS_GETERROR (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwGetError() #define GLFW_HAS_GETERROR (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwGetError()
#undef GLFW_HAS_VULKAN
// GLFW data // GLFW data
enum GlfwClientApi enum GlfwClientApi
{ {
GlfwClientApi_Unknown, GlfwClientApi_Unknown,
GlfwClientApi_OpenGL, GlfwClientApi_OpenGL,
GlfwClientApi_Vulkan, GlfwClientApi_Vulkan
}; };
struct ImGui_ImplGlfw_Data struct ImGui_ImplGlfw_Data
@@ -163,9 +148,6 @@ struct ImGui_ImplGlfw_Data
bool InstalledCallbacks; bool InstalledCallbacks;
bool CallbacksChainForAllWindows; bool CallbacksChainForAllWindows;
bool WantUpdateMonitors; bool WantUpdateMonitors;
#ifdef __EMSCRIPTEN__
const char* CanvasSelector;
#endif
// Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any. // Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any.
GLFWwindowfocusfun PrevUserCallbackWindowFocus; GLFWwindowfocusfun PrevUserCallbackWindowFocus;
@@ -177,7 +159,7 @@ struct ImGui_ImplGlfw_Data
GLFWcharfun PrevUserCallbackChar; GLFWcharfun PrevUserCallbackChar;
GLFWmonitorfun PrevUserCallbackMonitor; GLFWmonitorfun PrevUserCallbackMonitor;
#ifdef _WIN32 #ifdef _WIN32
WNDPROC PrevWndProc; WNDPROC GlfwWndProc;
#endif #endif
ImGui_ImplGlfw_Data() { memset((void*)this, 0, sizeof(*this)); } ImGui_ImplGlfw_Data() { memset((void*)this, 0, sizeof(*this)); }
@@ -203,24 +185,12 @@ static void ImGui_ImplGlfw_ShutdownPlatformInterface();
// Functions // Functions
static const char* ImGui_ImplGlfw_GetClipboardText(void* user_data) static const char* ImGui_ImplGlfw_GetClipboardText(void* user_data)
{ {
// IMHEX PATCH BEGIN
#ifdef __EMSCRIPTEN__
return clipboardContent.c_str();
#else
return glfwGetClipboardString((GLFWwindow*)user_data); return glfwGetClipboardString((GLFWwindow*)user_data);
#endif
// IMHEX PATCH END
} }
static void ImGui_ImplGlfw_SetClipboardText(void* user_data, const char* text) static void ImGui_ImplGlfw_SetClipboardText(void* user_data, const char* text)
{ {
glfwSetClipboardString((GLFWwindow*)user_data, text); glfwSetClipboardString((GLFWwindow*)user_data, text);
// IMHEX PATCH BEGIN
#ifdef __EMSCRIPTEN__
clipboardContent = text;
emscripten_browser_clipboard::copy(clipboardContent);
#endif
// IMHEX PATCH END
} }
static ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int key) static ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int key)
@@ -332,18 +302,6 @@ static ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int key)
case GLFW_KEY_F10: return ImGuiKey_F10; case GLFW_KEY_F10: return ImGuiKey_F10;
case GLFW_KEY_F11: return ImGuiKey_F11; case GLFW_KEY_F11: return ImGuiKey_F11;
case GLFW_KEY_F12: return ImGuiKey_F12; case GLFW_KEY_F12: return ImGuiKey_F12;
case GLFW_KEY_F13: return ImGuiKey_F13;
case GLFW_KEY_F14: return ImGuiKey_F14;
case GLFW_KEY_F15: return ImGuiKey_F15;
case GLFW_KEY_F16: return ImGuiKey_F16;
case GLFW_KEY_F17: return ImGuiKey_F17;
case GLFW_KEY_F18: return ImGuiKey_F18;
case GLFW_KEY_F19: return ImGuiKey_F19;
case GLFW_KEY_F20: return ImGuiKey_F20;
case GLFW_KEY_F21: return ImGuiKey_F21;
case GLFW_KEY_F22: return ImGuiKey_F22;
case GLFW_KEY_F23: return ImGuiKey_F23;
case GLFW_KEY_F24: return ImGuiKey_F24;
default: return ImGuiKey_None; default: return ImGuiKey_None;
} }
} }
@@ -463,6 +421,8 @@ void ImGui_ImplGlfw_CursorPosCallback(GLFWwindow* window, double x, double y)
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
if (bd->PrevUserCallbackCursorPos != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window)) if (bd->PrevUserCallbackCursorPos != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window))
bd->PrevUserCallbackCursorPos(window, x, y); bd->PrevUserCallbackCursorPos(window, x, y);
if (glfwGetInputMode(window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED)
return;
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
@@ -483,6 +443,8 @@ void ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window, int entered)
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
if (bd->PrevUserCallbackCursorEnter != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window)) if (bd->PrevUserCallbackCursorEnter != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window))
bd->PrevUserCallbackCursorEnter(window, entered); bd->PrevUserCallbackCursorEnter(window, entered);
if (glfwGetInputMode(window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED)
return;
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
if (entered) if (entered)
@@ -533,7 +495,48 @@ static EM_BOOL ImGui_ImplEmscripten_WheelCallback(int, const EmscriptenWheelEven
#endif #endif
#ifdef _WIN32 #ifdef _WIN32
static LRESULT CALLBACK ImGui_ImplGlfw_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); // GLFW doesn't allow to distinguish Mouse vs TouchScreen vs Pen.
// Add support for Win32 (based on imgui_impl_win32), because we rely on _TouchScreen info to trickle inputs differently.
static ImGuiMouseSource GetMouseSourceFromMessageExtraInfo()
{
LPARAM extra_info = ::GetMessageExtraInfo();
if ((extra_info & 0xFFFFFF80) == 0xFF515700)
return ImGuiMouseSource_Pen;
if ((extra_info & 0xFFFFFF80) == 0xFF515780)
return ImGuiMouseSource_TouchScreen;
return ImGuiMouseSource_Mouse;
}
static LRESULT CALLBACK ImGui_ImplGlfw_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
switch (msg)
{
case WM_MOUSEMOVE: case WM_NCMOUSEMOVE:
case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: case WM_LBUTTONUP:
case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK: case WM_RBUTTONUP:
case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK: case WM_MBUTTONUP:
case WM_XBUTTONDOWN: case WM_XBUTTONDBLCLK: case WM_XBUTTONUP:
ImGui::GetIO().AddMouseSourceEvent(GetMouseSourceFromMessageExtraInfo());
break;
// We have submitted https://github.com/glfw/glfw/pull/1568 to allow GLFW to support "transparent inputs".
// In the meanwhile we implement custom per-platform workarounds here (FIXME-VIEWPORT: Implement same work-around for Linux/OSX!)
#if !GLFW_HAS_MOUSE_PASSTHROUGH && GLFW_HAS_WINDOW_HOVERED
case WM_NCHITTEST:
{
// Let mouse pass-through the window. This will allow the backend to call io.AddMouseViewportEvent() properly (which is OPTIONAL).
// The ImGuiViewportFlags_NoInputs flag is set while dragging a viewport, as want to detect the window behind the one we are dragging.
// If you cannot easily access those viewport flags from your windowing/event code: you may manually synchronize its state e.g. in
// your main loop after calling UpdatePlatformWindows(). Iterate all viewports/platform windows and pass the flag to your windowing system.
ImGuiViewport* viewport = (ImGuiViewport*)::GetPropA(hWnd, "IMGUI_VIEWPORT");
if (viewport && (viewport->Flags & ImGuiViewportFlags_NoInputs))
return HTTRANSPARENT;
break;
}
#endif
}
return ::CallWindowProc(bd->GlfwWndProc, hWnd, msg, wParam, lParam);
}
#endif #endif
void ImGui_ImplGlfw_InstallCallbacks(GLFWwindow* window) void ImGui_ImplGlfw_InstallCallbacks(GLFWwindow* window)
@@ -611,15 +614,6 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
bd->Time = 0.0; bd->Time = 0.0;
bd->WantUpdateMonitors = true; bd->WantUpdateMonitors = true;
// IMHEX PATCH BEGIN
#ifdef __EMSCRIPTEN__
// Callback to handle clipboard paste from browser
emscripten_browser_clipboard::paste([](std::string const &paste_data, void *callback_data [[maybe_unused]]) {
clipboardContent = std::move(paste_data);
});
#endif
// IMHEX PATCH END
io.SetClipboardTextFn = ImGui_ImplGlfw_SetClipboardText; io.SetClipboardTextFn = ImGui_ImplGlfw_SetClipboardText;
io.GetClipboardTextFn = ImGui_ImplGlfw_GetClipboardText; io.GetClipboardTextFn = ImGui_ImplGlfw_GetClipboardText;
io.ClipboardUserData = bd->Window; io.ClipboardUserData = bd->Window;
@@ -682,9 +676,9 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
// Windows: register a WndProc hook so we can intercept some messages. // Windows: register a WndProc hook so we can intercept some messages.
#ifdef _WIN32 #ifdef _WIN32
bd->PrevWndProc = (WNDPROC)::GetWindowLongPtrW((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC); bd->GlfwWndProc = (WNDPROC)::GetWindowLongPtr((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC);
IM_ASSERT(bd->PrevWndProc != nullptr); IM_ASSERT(bd->GlfwWndProc != nullptr);
::SetWindowLongPtrW((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC, (LONG_PTR)ImGui_ImplGlfw_WndProc); ::SetWindowLongPtr((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC, (LONG_PTR)ImGui_ImplGlfw_WndProc);
#endif #endif
bd->ClientApi = client_api; bd->ClientApi = client_api;
@@ -716,18 +710,15 @@ void ImGui_ImplGlfw_Shutdown()
if (bd->InstalledCallbacks) if (bd->InstalledCallbacks)
ImGui_ImplGlfw_RestoreCallbacks(bd->Window); ImGui_ImplGlfw_RestoreCallbacks(bd->Window);
#ifdef __EMSCRIPTEN__
emscripten_set_wheel_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, nullptr, false, nullptr);
#endif
for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++) for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)
glfwDestroyCursor(bd->MouseCursors[cursor_n]); glfwDestroyCursor(bd->MouseCursors[cursor_n]);
// Windows: restore our WndProc hook // Windows: register a WndProc hook so we can intercept some messages.
#ifdef _WIN32 #ifdef _WIN32
ImGuiViewport* main_viewport = ImGui::GetMainViewport(); ImGuiViewport* main_viewport = ImGui::GetMainViewport();
::SetWindowLongPtrW((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC, (LONG_PTR)bd->PrevWndProc); ::SetWindowLongPtr((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC, (LONG_PTR)bd->GlfwWndProc);
bd->PrevWndProc = nullptr; bd->GlfwWndProc = nullptr;
#endif #endif
io.BackendPlatformName = nullptr; io.BackendPlatformName = nullptr;
@@ -742,6 +733,12 @@ static void ImGui_ImplGlfw_UpdateMouseData()
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
if (glfwGetInputMode(bd->Window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED)
{
io.AddMousePosEvent(-FLT_MAX, -FLT_MAX);
return;
}
ImGuiID mouse_viewport_id = 0; ImGuiID mouse_viewport_id = 0;
const ImVec2 mouse_pos_prev = io.MousePos; const ImVec2 mouse_pos_prev = io.MousePos;
for (int n = 0; n < platform_io.Viewports.Size; n++) for (int n = 0; n < platform_io.Viewports.Size; n++)
@@ -896,14 +893,17 @@ static void ImGui_ImplGlfw_UpdateMonitors()
{ {
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
bd->WantUpdateMonitors = false;
int monitors_count = 0; int monitors_count = 0;
GLFWmonitor** glfw_monitors = glfwGetMonitors(&monitors_count); GLFWmonitor** glfw_monitors = glfwGetMonitors(&monitors_count);
if (monitors_count == 0) // Preserve existing monitor list if there are none. Happens on macOS sleeping (#5683)
return;
platform_io.Monitors.resize(0); // IMHEX PATCH BEGIN
// REASON: Prevent occasional crash when having ImHex open and connecting to the computer over RDP
// NOTE: Untested with this ImGui version
if (monitors_count > 0)
platform_io.Monitors.resize(0);
// IMHEX PATCH END
bd->WantUpdateMonitors = false;
for (int n = 0; n < monitors_count; n++) for (int n = 0; n < monitors_count; n++)
{ {
ImGuiPlatformMonitor monitor; ImGuiPlatformMonitor monitor;
@@ -927,12 +927,7 @@ static void ImGui_ImplGlfw_UpdateMonitors()
// Warning: the validity of monitor DPI information on Windows depends on the application DPI awareness settings, which generally needs to be set in the manifest or at runtime. // Warning: the validity of monitor DPI information on Windows depends on the application DPI awareness settings, which generally needs to be set in the manifest or at runtime.
float x_scale, y_scale; float x_scale, y_scale;
glfwGetMonitorContentScale(glfw_monitors[n], &x_scale, &y_scale); glfwGetMonitorContentScale(glfw_monitors[n], &x_scale, &y_scale);
monitor.DpiScale = x_scale;
// IMHEX PATCH BEGIN
// REASON: Prevent occasional crash when a monitor connection status is changed
if (x_scale > 0)
monitor.DpiScale = x_scale;
// IMHEX PATCH END
#endif #endif
monitor.PlatformHandle = (void*)glfw_monitors[n]; // [...] GLFW doc states: "guaranteed to be valid only until the monitor configuration changes" monitor.PlatformHandle = (void*)glfw_monitors[n]; // [...] GLFW doc states: "guaranteed to be valid only until the monitor configuration changes"
platform_io.Monitors.push_back(monitor); platform_io.Monitors.push_back(monitor);
@@ -957,10 +952,7 @@ void ImGui_ImplGlfw_NewFrame()
ImGui_ImplGlfw_UpdateMonitors(); ImGui_ImplGlfw_UpdateMonitors();
// Setup time step // Setup time step
// (Accept glfwGetTime() not returning a monotonically increasing value. Seems to happens on disconnecting peripherals and probably on VMs and Emscripten, see #6491, #6189, #6114, #3644)
double current_time = glfwGetTime(); double current_time = glfwGetTime();
if (current_time <= bd->Time)
current_time = bd->Time + 0.00001f;
io.DeltaTime = bd->Time > 0.0 ? (float)(current_time - bd->Time) : (float)(1.0f / 60.0f); io.DeltaTime = bd->Time > 0.0 ? (float)(current_time - bd->Time) : (float)(1.0f / 60.0f);
bd->Time = current_time; bd->Time = current_time;
@@ -971,43 +963,6 @@ void ImGui_ImplGlfw_NewFrame()
ImGui_ImplGlfw_UpdateGamepads(); ImGui_ImplGlfw_UpdateGamepads();
} }
#ifdef __EMSCRIPTEN__
static EM_BOOL ImGui_ImplGlfw_OnCanvasSizeChange(int event_type, const EmscriptenUiEvent* event, void* user_data)
{
ImGui_ImplGlfw_Data* bd = (ImGui_ImplGlfw_Data*)user_data;
double canvas_width, canvas_height;
emscripten_get_element_css_size(bd->CanvasSelector, &canvas_width, &canvas_height);
glfwSetWindowSize(bd->Window, (int)canvas_width, (int)canvas_height);
return true;
}
static EM_BOOL ImGui_ImplEmscripten_FullscreenChangeCallback(int event_type, const EmscriptenFullscreenChangeEvent* event, void* user_data)
{
ImGui_ImplGlfw_Data* bd = (ImGui_ImplGlfw_Data*)user_data;
double canvas_width, canvas_height;
emscripten_get_element_css_size(bd->CanvasSelector, &canvas_width, &canvas_height);
glfwSetWindowSize(bd->Window, (int)canvas_width, (int)canvas_height);
return true;
}
// '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)
{
IM_ASSERT(canvas_selector != nullptr);
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplGlfw_InitForXXX()?");
bd->CanvasSelector = canvas_selector;
emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, bd, false, ImGui_ImplGlfw_OnCanvasSizeChange);
emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, bd, false, ImGui_ImplEmscripten_FullscreenChangeCallback);
// Change the size of the GLFW window according to the size of the canvas
ImGui_ImplGlfw_OnCanvasSizeChange(EMSCRIPTEN_EVENT_RESIZE, {}, bd);
}
#endif
//-------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------
// MULTI-VIEWPORT / PLATFORM INTERFACE SUPPORT // MULTI-VIEWPORT / PLATFORM INTERFACE SUPPORT
// This is an _advanced_ and _optional_ feature, allowing the backend to create and handle multiple viewports simultaneously. // This is an _advanced_ and _optional_ feature, allowing the backend to create and handle multiple viewports simultaneously.
@@ -1021,11 +976,8 @@ struct ImGui_ImplGlfw_ViewportData
bool WindowOwned; bool WindowOwned;
int IgnoreWindowPosEventFrame; int IgnoreWindowPosEventFrame;
int IgnoreWindowSizeEventFrame; int IgnoreWindowSizeEventFrame;
#ifdef _WIN32
WNDPROC PrevWndProc;
#endif
ImGui_ImplGlfw_ViewportData() { memset(this, 0, sizeof(*this)); IgnoreWindowSizeEventFrame = IgnoreWindowPosEventFrame = -1; } ImGui_ImplGlfw_ViewportData() { Window = nullptr; WindowOwned = false; IgnoreWindowSizeEventFrame = IgnoreWindowPosEventFrame = -1; }
~ImGui_ImplGlfw_ViewportData() { IM_ASSERT(Window == nullptr); } ~ImGui_ImplGlfw_ViewportData() { IM_ASSERT(Window == nullptr); }
}; };
@@ -1134,10 +1086,9 @@ static void ImGui_ImplGlfw_DestroyWindow(ImGuiViewport* viewport)
// Release any keys that were pressed in the window being destroyed and are still held down, // Release any keys that were pressed in the window being destroyed and are still held down,
// because we will not receive any release events after window is destroyed. // because we will not receive any release events after window is destroyed.
for (int i = 0; i < IM_ARRAYSIZE(bd->KeyOwnerWindows); i++) { for (int i = 0; i < IM_ARRAYSIZE(bd->KeyOwnerWindows); i++)
if (bd->KeyOwnerWindows[i] == vd->Window) if (bd->KeyOwnerWindows[i] == vd->Window)
ImGui_ImplGlfw_KeyCallback(vd->Window, i, 0, GLFW_RELEASE, 0); // Later params are only used for main viewport, on which this function is never called. ImGui_ImplGlfw_KeyCallback(vd->Window, i, 0, GLFW_RELEASE, 0); // Later params are only used for main viewport, on which this function is never called.
}
glfwDestroyWindow(vd->Window); glfwDestroyWindow(vd->Window);
} }
@@ -1164,9 +1115,10 @@ static void ImGui_ImplGlfw_ShowWindow(ImGuiViewport* viewport)
// GLFW hack: install hook for WM_NCHITTEST message handler // GLFW hack: install hook for WM_NCHITTEST message handler
#if !GLFW_HAS_MOUSE_PASSTHROUGH && GLFW_HAS_WINDOW_HOVERED && defined(_WIN32) #if !GLFW_HAS_MOUSE_PASSTHROUGH && GLFW_HAS_WINDOW_HOVERED && defined(_WIN32)
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
::SetPropA(hwnd, "IMGUI_VIEWPORT", viewport); ::SetPropA(hwnd, "IMGUI_VIEWPORT", viewport);
vd->PrevWndProc = (WNDPROC)::GetWindowLongPtrW(hwnd, GWLP_WNDPROC); IM_ASSERT(bd->GlfwWndProc == (WNDPROC)::GetWindowLongPtr(hwnd, GWLP_WNDPROC));
::SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR)ImGui_ImplGlfw_WndProc); ::SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)ImGui_ImplGlfw_WndProc);
#endif #endif
#if !GLFW_HAS_FOCUS_ON_SHOW #if !GLFW_HAS_FOCUS_ON_SHOW
@@ -1351,63 +1303,6 @@ static void ImGui_ImplGlfw_ShutdownPlatformInterface()
ImGui::DestroyPlatformWindows(); ImGui::DestroyPlatformWindows();
} }
//-----------------------------------------------------------------------------
// WndProc hook (declared here because we will need access to ImGui_ImplGlfw_ViewportData)
#ifdef _WIN32
static ImGuiMouseSource GetMouseSourceFromMessageExtraInfo()
{
LPARAM extra_info = ::GetMessageExtraInfo();
if ((extra_info & 0xFFFFFF80) == 0xFF515700)
return ImGuiMouseSource_Pen;
if ((extra_info & 0xFFFFFF80) == 0xFF515780)
return ImGuiMouseSource_TouchScreen;
return ImGuiMouseSource_Mouse;
}
static LRESULT CALLBACK ImGui_ImplGlfw_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
WNDPROC prev_wndproc = bd->PrevWndProc;
ImGuiViewport* viewport = (ImGuiViewport*)::GetPropA(hWnd, "IMGUI_VIEWPORT");
if (viewport != NULL)
if (ImGui_ImplGlfw_ViewportData* vd = (ImGui_ImplGlfw_ViewportData*)viewport->PlatformUserData)
prev_wndproc = vd->PrevWndProc;
switch (msg)
{
// GLFW doesn't allow to distinguish Mouse vs TouchScreen vs Pen.
// Add support for Win32 (based on imgui_impl_win32), because we rely on _TouchScreen info to trickle inputs differently.
case WM_MOUSEMOVE: case WM_NCMOUSEMOVE:
case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: case WM_LBUTTONUP:
case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK: case WM_RBUTTONUP:
case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK: case WM_MBUTTONUP:
case WM_XBUTTONDOWN: case WM_XBUTTONDBLCLK: case WM_XBUTTONUP:
ImGui::GetIO().AddMouseSourceEvent(GetMouseSourceFromMessageExtraInfo());
break;
// We have submitted https://github.com/glfw/glfw/pull/1568 to allow GLFW to support "transparent inputs".
// In the meanwhile we implement custom per-platform workarounds here (FIXME-VIEWPORT: Implement same work-around for Linux/OSX!)
#if !GLFW_HAS_MOUSE_PASSTHROUGH && GLFW_HAS_WINDOW_HOVERED
case WM_NCHITTEST:
{
// Let mouse pass-through the window. This will allow the backend to call io.AddMouseViewportEvent() properly (which is OPTIONAL).
// The ImGuiViewportFlags_NoInputs flag is set while dragging a viewport, as want to detect the window behind the one we are dragging.
// If you cannot easily access those viewport flags from your windowing/event code: you may manually synchronize its state e.g. in
// your main loop after calling UpdatePlatformWindows(). Iterate all viewports/platform windows and pass the flag to your windowing system.
if (viewport && (viewport->Flags & ImGuiViewportFlags_NoInputs))
return HTTRANSPARENT;
break;
}
#endif
}
return ::CallWindowProcW(prev_wndproc, hWnd, msg, wParam, lParam);
}
#endif // #ifdef _WIN32
//-----------------------------------------------------------------------------
#if defined(__clang__) #if defined(__clang__)
#pragma clang diagnostic pop #pragma clang diagnostic pop
#endif #endif
#endif // #ifndef IMGUI_DISABLE

View File

@@ -8,26 +8,14 @@
// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices (Desktop OpenGL only). // [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices (Desktop OpenGL only).
// [X] Renderer: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'. // [X] Renderer: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
// About WebGL/ES:
// - You need to '#define IMGUI_IMPL_OPENGL_ES2' or '#define IMGUI_IMPL_OPENGL_ES3' to use WebGL or OpenGL ES.
// - This is done automatically on iOS, Android and Emscripten targets.
// - For other targets, the define needs to be visible from the imgui_impl_opengl3.cpp compilation unit. If unsure, define globally or in imconfig.h.
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// Learn about Dear ImGui: // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// - FAQ https://dearimgui.com/faq // Read online: https://github.com/ocornut/imgui/tree/master/docs
// - Getting Started https://dearimgui.com/getting-started
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
// - Introduction, links and more at the top of imgui.cpp
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (minor and older changes stripped away, please see git history for details)
// 2023-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. // 2023-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2024-01-09: OpenGL: Update GL3W based imgui_impl_opengl3_loader.h to load "libGL.so" and variants, fixing regression on distros missing a symlink.
// 2023-11-08: OpenGL: Update GL3W based imgui_impl_opengl3_loader.h to load "libGL.so" instead of "libGL.so.1", accommodating for NetBSD systems having only "libGL.so.3" available. (#6983)
// 2023-10-05: OpenGL: Rename symbols in our internal loader so that LTO compilation with another copy of gl3w is possible. (#6875, #6668, #4445)
// 2023-06-20: OpenGL: Fixed erroneous use glGetIntegerv(GL_CONTEXT_PROFILE_MASK) on contexts lower than 3.2. (#6539, #6333)
// 2023-05-09: OpenGL: Support for glBindSampler() backup/restore on ES3. (#6375) // 2023-05-09: OpenGL: Support for glBindSampler() backup/restore on ES3. (#6375)
// 2023-04-18: OpenGL: Restore front and back polygon mode separately when supported by context. (#6333) // 2023-04-18: OpenGL: Restore front and back polygon mode separately when supported by context. (#6333)
// 2023-03-23: OpenGL: Properly restoring "no shader program bound" if it was the case prior to running the rendering function. (#6267, #6220, #6224) // 2023-03-23: OpenGL: Properly restoring "no shader program bound" if it was the case prior to running the rendering function. (#6267, #6220, #6224)
@@ -112,10 +100,13 @@
#endif #endif
#include "imgui.h" #include "imgui.h"
#ifndef IMGUI_DISABLE
#include "imgui_impl_opengl3.h" #include "imgui_impl_opengl3.h"
#include <stdio.h> #include <stdio.h>
#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
#include <stddef.h> // intptr_t
#else
#include <stdint.h> // intptr_t #include <stdint.h> // intptr_t
#endif
#if defined(__APPLE__) #if defined(__APPLE__)
#include <TargetConditionals.h> #include <TargetConditionals.h>
#endif #endif
@@ -178,20 +169,9 @@
#define GL_VERTEX_ARRAY_BINDING GL_VERTEX_ARRAY_BINDING_OES #define GL_VERTEX_ARRAY_BINDING GL_VERTEX_ARRAY_BINDING_OES
#endif #endif
// Desktop GL 2.0+ has extension and glPolygonMode() which GL ES and WebGL don't have.. // Desktop GL 2.0+ has glPolygonMode() which GL ES and WebGL don't have.
#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) #ifdef GL_POLYGON_MODE
#define IMGUI_IMPL_OPENGL_HAS_EXTENSIONS // has glGetIntegerv(GL_NUM_EXTENSIONS) #define IMGUI_IMPL_HAS_POLYGON_MODE
#define IMGUI_IMPL_OPENGL_HAS_POLYGON_MODE // has glPolygonMode()
#endif
// Desktop GL 2.1+ and GL ES 3.0+ have glBindBuffer() with GL_PIXEL_UNPACK_BUFFER target.
#if !defined(IMGUI_IMPL_OPENGL_ES2)
#define IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_BUFFER_PIXEL_UNPACK
#endif
// Desktop GL 3.1+ has GL_PRIMITIVE_RESTART state
#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && defined(GL_VERSION_3_1)
#define IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART
#endif #endif
// Desktop GL 3.2+ has glDrawElementsBaseVertex() which GL ES and WebGL don't have. // Desktop GL 3.2+ has glDrawElementsBaseVertex() which GL ES and WebGL don't have.
@@ -204,6 +184,16 @@
#define IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER #define IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
#endif #endif
// Desktop GL 3.1+ has GL_PRIMITIVE_RESTART state
#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && defined(GL_VERSION_3_1)
#define IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART
#endif
// Desktop GL use extension detection
#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3)
#define IMGUI_IMPL_OPENGL_MAY_HAVE_EXTENSIONS
#endif
// [Debugging] // [Debugging]
//#define IMGUI_IMPL_OPENGL_DEBUG //#define IMGUI_IMPL_OPENGL_DEBUG
#ifdef IMGUI_IMPL_OPENGL_DEBUG #ifdef IMGUI_IMPL_OPENGL_DEBUG
@@ -294,12 +284,7 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
io.BackendRendererName = "imgui_impl_opengl3"; io.BackendRendererName = "imgui_impl_opengl3";
// Query for GL version (e.g. 320 for GL 3.2) // Query for GL version (e.g. 320 for GL 3.2)
#if defined(IMGUI_IMPL_OPENGL_ES2) #if !defined(IMGUI_IMPL_OPENGL_ES2)
// GLES 2
bd->GlVersion = 200;
bd->GlProfileIsES2 = true;
#else
// Desktop or GLES 3
GLint major = 0; GLint major = 0;
GLint minor = 0; GLint minor = 0;
glGetIntegerv(GL_MAJOR_VERSION, &major); glGetIntegerv(GL_MAJOR_VERSION, &major);
@@ -312,15 +297,10 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
} }
bd->GlVersion = (GLuint)(major * 100 + minor * 10); bd->GlVersion = (GLuint)(major * 100 + minor * 10);
#if defined(GL_CONTEXT_PROFILE_MASK) #if defined(GL_CONTEXT_PROFILE_MASK)
if (bd->GlVersion >= 320) glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &bd->GlProfileMask);
glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &bd->GlProfileMask);
bd->GlProfileIsCompat = (bd->GlProfileMask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) != 0; bd->GlProfileIsCompat = (bd->GlProfileMask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) != 0;
#endif #endif
#if defined(IMGUI_IMPL_OPENGL_ES3)
bd->GlProfileIsES3 = true;
#endif
bd->UseBufferSubData = false; bd->UseBufferSubData = false;
/* /*
// Query vendor to enable glBufferSubData kludge // Query vendor to enable glBufferSubData kludge
@@ -330,10 +310,16 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
bd->UseBufferSubData = true; bd->UseBufferSubData = true;
#endif #endif
*/ */
#elif defined(IMGUI_IMPL_OPENGL_ES2)
bd->GlVersion = 200; // GLES 2
bd->GlProfileIsES2 = true;
#elif defined(IMGUI_IMPL_OPENGL_ES3)
bd->GlVersion = 200; // Don't raise version as it is intended as a desktop version check for now.
bd->GlProfileIsES3 = true;
#endif #endif
#ifdef IMGUI_IMPL_OPENGL_DEBUG #ifdef IMGUI_IMPL_OPENGL_DEBUG
printf("GlVersion = %d\nGlProfileIsCompat = %d\nGlProfileMask = 0x%X\nGlProfileIsES2 = %d, GlProfileIsES3 = %d\nGL_VENDOR = '%s'\nGL_RENDERER = '%s'\n", bd->GlVersion, bd->GlProfileIsCompat, bd->GlProfileMask, bd->GlProfileIsES2, bd->GlProfileIsES3, (const char*)glGetString(GL_VENDOR), (const char*)glGetString(GL_RENDERER)); // [DEBUG] printf("GL_MAJOR_VERSION = %d\nGL_MINOR_VERSION = %d\nGL_VENDOR = '%s'\nGL_RENDERER = '%s'\n", major, minor, (const char*)glGetString(GL_VENDOR), (const char*)glGetString(GL_RENDERER)); // [DEBUG]
#endif #endif
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET
@@ -367,7 +353,7 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
// Detect extensions we support // Detect extensions we support
bd->HasClipOrigin = (bd->GlVersion >= 450); bd->HasClipOrigin = (bd->GlVersion >= 450);
#ifdef IMGUI_IMPL_OPENGL_HAS_EXTENSIONS #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_EXTENSIONS
GLint num_extensions = 0; GLint num_extensions = 0;
glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions); glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions);
for (GLint i = 0; i < num_extensions; i++) for (GLint i = 0; i < num_extensions; i++)
@@ -423,7 +409,7 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
if (bd->GlVersion >= 310) if (bd->GlVersion >= 310)
glDisable(GL_PRIMITIVE_RESTART); glDisable(GL_PRIMITIVE_RESTART);
#endif #endif
#ifdef IMGUI_IMPL_OPENGL_HAS_POLYGON_MODE #ifdef IMGUI_IMPL_HAS_POLYGON_MODE
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
#endif #endif
@@ -475,9 +461,9 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
GL_CALL(glEnableVertexAttribArray(bd->AttribLocationVtxPos)); GL_CALL(glEnableVertexAttribArray(bd->AttribLocationVtxPos));
GL_CALL(glEnableVertexAttribArray(bd->AttribLocationVtxUV)); GL_CALL(glEnableVertexAttribArray(bd->AttribLocationVtxUV));
GL_CALL(glEnableVertexAttribArray(bd->AttribLocationVtxColor)); GL_CALL(glEnableVertexAttribArray(bd->AttribLocationVtxColor));
GL_CALL(glVertexAttribPointer(bd->AttribLocationVtxPos, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)offsetof(ImDrawVert, pos))); GL_CALL(glVertexAttribPointer(bd->AttribLocationVtxPos, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos)));
GL_CALL(glVertexAttribPointer(bd->AttribLocationVtxUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)offsetof(ImDrawVert, uv))); GL_CALL(glVertexAttribPointer(bd->AttribLocationVtxUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv)));
GL_CALL(glVertexAttribPointer(bd->AttribLocationVtxColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)offsetof(ImDrawVert, col))); GL_CALL(glVertexAttribPointer(bd->AttribLocationVtxColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col)));
} }
// OpenGL3 Render function. // OpenGL3 Render function.
@@ -512,7 +498,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
GLuint last_vertex_array_object; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, (GLint*)&last_vertex_array_object); GLuint last_vertex_array_object; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, (GLint*)&last_vertex_array_object);
#endif #endif
#ifdef IMGUI_IMPL_OPENGL_HAS_POLYGON_MODE #ifdef IMGUI_IMPL_HAS_POLYGON_MODE
GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode); GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode);
#endif #endif
GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport); GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);
@@ -651,7 +637,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
if (bd->GlVersion >= 310) { if (last_enable_primitive_restart) glEnable(GL_PRIMITIVE_RESTART); else glDisable(GL_PRIMITIVE_RESTART); } if (bd->GlVersion >= 310) { if (last_enable_primitive_restart) glEnable(GL_PRIMITIVE_RESTART); else glDisable(GL_PRIMITIVE_RESTART); }
#endif #endif
#ifdef IMGUI_IMPL_OPENGL_HAS_POLYGON_MODE #ifdef IMGUI_IMPL_HAS_POLYGON_MODE
// Desktop OpenGL 3.0 and OpenGL 3.1 had separate polygon draw modes for front-facing and back-facing faces of polygons // Desktop OpenGL 3.0 and OpenGL 3.1 had separate polygon draw modes for front-facing and back-facing faces of polygons
if (bd->GlVersion <= 310 || bd->GlProfileIsCompat) if (bd->GlVersion <= 310 || bd->GlProfileIsCompat)
{ {
@@ -662,7 +648,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
{ {
glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]); glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]);
} }
#endif // IMGUI_IMPL_OPENGL_HAS_POLYGON_MODE #endif // IMGUI_IMPL_HAS_POLYGON_MODE
glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]);
glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]); glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]);
@@ -759,10 +745,6 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects()
GLint last_texture, last_array_buffer; GLint last_texture, last_array_buffer;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer); glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_BUFFER_PIXEL_UNPACK
GLint last_pixel_unpack_buffer;
if (bd->GlVersion >= 210) { glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &last_pixel_unpack_buffer); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); }
#endif
#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
GLint last_vertex_array; GLint last_vertex_array;
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array); glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
@@ -936,9 +918,6 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects()
// Restore modified GL state // Restore modified GL state
glBindTexture(GL_TEXTURE_2D, last_texture); glBindTexture(GL_TEXTURE_2D, last_texture);
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer); glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_BUFFER_PIXEL_UNPACK
if (bd->GlVersion >= 210) { glBindBuffer(GL_PIXEL_UNPACK_BUFFER, last_pixel_unpack_buffer); }
#endif
#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
glBindVertexArray(last_vertex_array); glBindVertexArray(last_vertex_array);
#endif #endif
@@ -983,13 +962,9 @@ static void ImGui_ImplOpenGL3_ShutdownPlatformInterface()
ImGui::DestroyPlatformWindows(); ImGui::DestroyPlatformWindows();
} }
//-----------------------------------------------------------------------------
#if defined(__GNUC__) #if defined(__GNUC__)
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#endif #endif
#if defined(__clang__) #if defined(__clang__)
#pragma clang diagnostic pop #pragma clang diagnostic pop
#endif #endif
#endif // #ifndef IMGUI_DISABLE

View File

@@ -1,6 +1,6 @@
// MIT License // MIT License
// Copyright (c) 2023 Evan Pezent // Copyright (c) 2022 Evan Pezent
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
@@ -20,7 +20,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE. // SOFTWARE.
// ImPlot v0.17 // ImPlot v0.14
/* /*
@@ -31,9 +31,6 @@ Below is a change-log of API breaking changes only. If you are using one of the
When you are not sure about a old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all implot files. When you are not sure about a old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all implot files.
You can read releases logs https://github.com/epezent/implot/releases for more details. You can read releases logs https://github.com/epezent/implot/releases for more details.
- 2023/08/20 (0.17) - ImPlotFlags_NoChild was removed as child windows are no longer needed to capture scroll. You can safely remove this flag if you were using it.
- 2023/06/26 (0.15) - Various build fixes related to updates in Dear ImGui internals.
- 2022/11/25 (0.15) - Make PlotText honor ImPlotItemFlags_NoFit.
- 2022/06/19 (0.14) - The signature of ColormapScale has changed to accommodate a new ImPlotColormapScaleFlags parameter - 2022/06/19 (0.14) - The signature of ColormapScale has changed to accommodate a new ImPlotColormapScaleFlags parameter
- 2022/06/17 (0.14) - **IMPORTANT** All PlotX functions now take an ImPlotX_Flags `flags` parameter. Where applicable, it is located before the existing `offset` and `stride` parameters. - 2022/06/17 (0.14) - **IMPORTANT** All PlotX functions now take an ImPlotX_Flags `flags` parameter. Where applicable, it is located before the existing `offset` and `stride` parameters.
If you were providing offset and stride values, you will need to update your function call to include a `flags` value. If you fail to do this, you will likely see If you were providing offset and stride values, you will need to update your function call to include a `flags` value. If you fail to do this, you will likely see
@@ -136,11 +133,6 @@ You can read releases logs https://github.com/epezent/implot/releases for more d
#define ImDrawFlags_RoundCornersAll ImDrawCornerFlags_All #define ImDrawFlags_RoundCornersAll ImDrawCornerFlags_All
#endif #endif
// Support for pre-1.89.7 versions.
#if (IMGUI_VERSION_NUM < 18966)
#define ImGuiButtonFlags_AllowOverlap ImGuiButtonFlags_AllowItemOverlap
#endif
// Visual Studio warnings // Visual Studio warnings
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen #pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
@@ -293,35 +285,35 @@ struct ImPlotStyleVarInfo {
static const ImPlotStyleVarInfo GPlotStyleVarInfo[] = static const ImPlotStyleVarInfo GPlotStyleVarInfo[] =
{ {
{ ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlotStyle, LineWeight) }, // ImPlotStyleVar_LineWeight { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, LineWeight) }, // ImPlotStyleVar_LineWeight
{ ImGuiDataType_S32, 1, (ImU32)offsetof(ImPlotStyle, Marker) }, // ImPlotStyleVar_Marker { ImGuiDataType_S32, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, Marker) }, // ImPlotStyleVar_Marker
{ ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlotStyle, MarkerSize) }, // ImPlotStyleVar_MarkerSize { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, MarkerSize) }, // ImPlotStyleVar_MarkerSize
{ ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlotStyle, MarkerWeight) }, // ImPlotStyleVar_MarkerWeight { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, MarkerWeight) }, // ImPlotStyleVar_MarkerWeight
{ ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlotStyle, FillAlpha) }, // ImPlotStyleVar_FillAlpha { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, FillAlpha) }, // ImPlotStyleVar_FillAlpha
{ ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlotStyle, ErrorBarSize) }, // ImPlotStyleVar_ErrorBarSize { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, ErrorBarSize) }, // ImPlotStyleVar_ErrorBarSize
{ ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlotStyle, ErrorBarWeight) }, // ImPlotStyleVar_ErrorBarWeight { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, ErrorBarWeight) }, // ImPlotStyleVar_ErrorBarWeight
{ ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlotStyle, DigitalBitHeight) }, // ImPlotStyleVar_DigitalBitHeight { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, DigitalBitHeight) }, // ImPlotStyleVar_DigitalBitHeight
{ ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlotStyle, DigitalBitGap) }, // ImPlotStyleVar_DigitalBitGap { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, DigitalBitGap) }, // ImPlotStyleVar_DigitalBitGap
{ ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlotStyle, PlotBorderSize) }, // ImPlotStyleVar_PlotBorderSize { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, PlotBorderSize) }, // ImPlotStyleVar_PlotBorderSize
{ ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlotStyle, MinorAlpha) }, // ImPlotStyleVar_MinorAlpha { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImPlotStyle, MinorAlpha) }, // ImPlotStyleVar_MinorAlpha
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, MajorTickLen) }, // ImPlotStyleVar_MajorTickLen { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, MajorTickLen) }, // ImPlotStyleVar_MajorTickLen
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, MinorTickLen) }, // ImPlotStyleVar_MinorTickLen { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, MinorTickLen) }, // ImPlotStyleVar_MinorTickLen
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, MajorTickSize) }, // ImPlotStyleVar_MajorTickSize { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, MajorTickSize) }, // ImPlotStyleVar_MajorTickSize
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, MinorTickSize) }, // ImPlotStyleVar_MinorTickSize { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, MinorTickSize) }, // ImPlotStyleVar_MinorTickSize
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, MajorGridSize) }, // ImPlotStyleVar_MajorGridSize { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, MajorGridSize) }, // ImPlotStyleVar_MajorGridSize
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, MinorGridSize) }, // ImPlotStyleVar_MinorGridSize { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, MinorGridSize) }, // ImPlotStyleVar_MinorGridSize
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, PlotPadding) }, // ImPlotStyleVar_PlotPadding { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, PlotPadding) }, // ImPlotStyleVar_PlotPadding
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, LabelPadding) }, // ImPlotStyleVar_LabelPaddine { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, LabelPadding) }, // ImPlotStyleVar_LabelPaddine
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, LegendPadding) }, // ImPlotStyleVar_LegendPadding { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, LegendPadding) }, // ImPlotStyleVar_LegendPadding
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, LegendInnerPadding) }, // ImPlotStyleVar_LegendInnerPadding { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, LegendInnerPadding) }, // ImPlotStyleVar_LegendInnerPadding
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, LegendSpacing) }, // ImPlotStyleVar_LegendSpacing { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, LegendSpacing) }, // ImPlotStyleVar_LegendSpacing
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, MousePosPadding) }, // ImPlotStyleVar_MousePosPadding { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, MousePosPadding) }, // ImPlotStyleVar_MousePosPadding
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, AnnotationPadding) }, // ImPlotStyleVar_AnnotationPadding { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, AnnotationPadding) }, // ImPlotStyleVar_AnnotationPadding
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, FitPadding) }, // ImPlotStyleVar_FitPadding { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, FitPadding) }, // ImPlotStyleVar_FitPadding
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, PlotDefaultSize) }, // ImPlotStyleVar_PlotDefaultSize { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, PlotDefaultSize) }, // ImPlotStyleVar_PlotDefaultSize
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlotStyle, PlotMinSize) } // ImPlotStyleVar_PlotMinSize { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImPlotStyle, PlotMinSize) } // ImPlotStyleVar_PlotMinSize
}; };
static const ImPlotStyleVarInfo* GetPlotStyleVarInfo(ImPlotStyleVar idx) { static const ImPlotStyleVarInfo* GetPlotStyleVarInfo(ImPlotStyleVar idx) {
@@ -341,8 +333,8 @@ void AddTextVertical(ImDrawList *DrawList, ImVec2 pos, ImU32 col, const char *te
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImFont* font = g.Font; ImFont* font = g.Font;
// Align to be pixel perfect // Align to be pixel perfect
pos.x = ImFloor(pos.x); pos.x = IM_FLOOR(pos.x);
pos.y = ImFloor(pos.y); pos.y = IM_FLOOR(pos.y);
const float scale = g.FontSize / font->FontSize; const float scale = g.FontSize / font->FontSize;
const char* s = text_begin; const char* s = text_begin;
int chars_exp = (int)(text_end - s); int chars_exp = (int)(text_end - s);
@@ -493,6 +485,10 @@ void Initialize(ImPlotContext* ctx) {
} }
void ResetCtxForNextPlot(ImPlotContext* ctx) { void ResetCtxForNextPlot(ImPlotContext* ctx) {
// end child window if it was made
if (ctx->ChildWindowMade)
ImGui::EndChild();
ctx->ChildWindowMade = false;
// reset the next plot/item data // reset the next plot/item data
ctx->NextPlotData.Reset(); ctx->NextPlotData.Reset();
ctx->NextItemData.Reset(); ctx->NextItemData.Reset();
@@ -586,28 +582,6 @@ ImVec2 CalcLegendSize(ImPlotItemGroup& items, const ImVec2& pad, const ImVec2& s
return legend_size; return legend_size;
} }
bool ClampLegendRect(ImRect& legend_rect, const ImRect& outer_rect, const ImVec2& pad) {
bool clamped = false;
ImRect outer_rect_pad(outer_rect.Min + pad, outer_rect.Max - pad);
if (legend_rect.Min.x < outer_rect_pad.Min.x) {
legend_rect.Min.x = outer_rect_pad.Min.x;
clamped = true;
}
if (legend_rect.Min.y < outer_rect_pad.Min.y) {
legend_rect.Min.y = outer_rect_pad.Min.y;
clamped = true;
}
if (legend_rect.Max.x > outer_rect_pad.Max.x) {
legend_rect.Max.x = outer_rect_pad.Max.x;
clamped = true;
}
if (legend_rect.Max.y > outer_rect_pad.Max.y) {
legend_rect.Max.y = outer_rect_pad.Max.y;
clamped = true;
}
return clamped;
}
int LegendSortingComp(const void* _a, const void* _b) { int LegendSortingComp(const void* _a, const void* _b) {
ImPlotItemGroup* items = GImPlot->SortItems; ImPlotItemGroup* items = GImPlot->SortItems;
const int a = *(const int*)_a; const int a = *(const int*)_a;
@@ -1322,12 +1296,12 @@ bool DragFloat(const char*, F*, float, F, F) {
template <> template <>
bool DragFloat<double>(const char* label, double* v, float v_speed, double v_min, double v_max) { bool DragFloat<double>(const char* label, double* v, float v_speed, double v_min, double v_max) {
return ImGui::DragScalar(label, ImGuiDataType_Double, v, v_speed, &v_min, &v_max, "%.3g", 1); return ImGui::DragScalar(label, ImGuiDataType_Double, v, v_speed, &v_min, &v_max, "%.3f", 1);
} }
template <> template <>
bool DragFloat<float>(const char* label, float* v, float v_speed, float v_min, float v_max) { bool DragFloat<float>(const char* label, float* v, float v_speed, float v_min, float v_max) {
return ImGui::DragScalar(label, ImGuiDataType_Float, v, v_speed, &v_min, &v_max, "%.3g", 1); return ImGui::DragScalar(label, ImGuiDataType_Float, v, v_speed, &v_min, &v_max, "%.3f", 1);
} }
inline void BeginDisabledControls(bool cond) { inline void BeginDisabledControls(bool cond) {
@@ -1574,7 +1548,7 @@ void ShowPlotContextMenu(ImPlotPlot& plot) {
ImFlipFlag(plot.Flags, ImPlotFlags_Crosshairs); ImFlipFlag(plot.Flags, ImPlotFlags_Crosshairs);
ImGui::EndMenu(); ImGui::EndMenu();
} }
if (gp.CurrentSubplot != nullptr && !ImHasFlag(gp.CurrentSubplot->Flags, ImPlotSubplotFlags_NoMenus)) { if (gp.CurrentSubplot != nullptr && !ImHasFlag(gp.CurrentPlot->Flags, ImPlotSubplotFlags_NoMenus)) {
ImGui::Separator(); ImGui::Separator();
if ((ImGui::BeginMenu("Subplots"))) { if ((ImGui::BeginMenu("Subplots"))) {
ShowSubplotsContextMenu(*gp.CurrentSubplot); ShowSubplotsContextMenu(*gp.CurrentSubplot);
@@ -1834,7 +1808,7 @@ bool UpdateInput(ImPlotPlot& plot) {
// BUTTON STATE ----------------------------------------------------------- // BUTTON STATE -----------------------------------------------------------
const ImGuiButtonFlags plot_button_flags = ImGuiButtonFlags_AllowOverlap const ImGuiButtonFlags plot_button_flags = ImGuiButtonFlags_AllowItemOverlap
| ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnClick
| ImGuiButtonFlags_PressedOnDoubleClick | ImGuiButtonFlags_PressedOnDoubleClick
| ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonLeft
@@ -1844,9 +1818,7 @@ bool UpdateInput(ImPlotPlot& plot) {
| plot_button_flags; | plot_button_flags;
const bool plot_clicked = ImGui::ButtonBehavior(plot.PlotRect,plot.ID,&plot.Hovered,&plot.Held,plot_button_flags); const bool plot_clicked = ImGui::ButtonBehavior(plot.PlotRect,plot.ID,&plot.Hovered,&plot.Held,plot_button_flags);
#if (IMGUI_VERSION_NUM < 18966) ImGui::SetItemAllowOverlap();
ImGui::SetItemAllowOverlap(); // Handled by ButtonBehavior()
#endif
if (plot_clicked) { if (plot_clicked) {
if (!ImHasFlag(plot.Flags, ImPlotFlags_NoBoxSelect) && IO.MouseClicked[gp.InputMap.Select] && ImHasFlag(IO.KeyMods, gp.InputMap.SelectMod)) { if (!ImHasFlag(plot.Flags, ImPlotFlags_NoBoxSelect) && IO.MouseClicked[gp.InputMap.Select] && ImHasFlag(IO.KeyMods, gp.InputMap.SelectMod)) {
@@ -1979,12 +1951,10 @@ bool UpdateInput(ImPlotPlot& plot) {
// SCROLL INPUT ----------------------------------------------------------- // SCROLL INPUT -----------------------------------------------------------
if (any_hov && ImHasFlag(IO.KeyMods, gp.InputMap.ZoomMod)) { if (any_hov && IO.MouseWheel != 0 && ImHasFlag(IO.KeyMods, gp.InputMap.ZoomMod)) {
float zoom_rate = gp.InputMap.ZoomRate; float zoom_rate = gp.InputMap.ZoomRate;
if (IO.MouseWheel == 0.0f) if (IO.MouseWheel > 0)
zoom_rate = 0;
else if (IO.MouseWheel > 0)
zoom_rate = (-zoom_rate) / (1.0f + (2.0f * zoom_rate)); zoom_rate = (-zoom_rate) / (1.0f + (2.0f * zoom_rate));
ImVec2 rect_size = plot.PlotRect.GetSize(); ImVec2 rect_size = plot.PlotRect.GetSize();
float tx = ImRemap(IO.MousePos.x, plot.PlotRect.Min.x, plot.PlotRect.Max.x, 0.0f, 1.0f); float tx = ImRemap(IO.MousePos.x, plot.PlotRect.Min.x, plot.PlotRect.Max.x, 0.0f, 1.0f);
@@ -1995,17 +1965,14 @@ bool UpdateInput(ImPlotPlot& plot) {
const bool equal_zoom = axis_equal && x_axis.OrthoAxis != nullptr; const bool equal_zoom = axis_equal && x_axis.OrthoAxis != nullptr;
const bool equal_locked = (equal_zoom != false) && x_axis.OrthoAxis->IsInputLocked(); const bool equal_locked = (equal_zoom != false) && x_axis.OrthoAxis->IsInputLocked();
if (x_hov[i] && !x_axis.IsInputLocked() && !equal_locked) { if (x_hov[i] && !x_axis.IsInputLocked() && !equal_locked) {
ImGui::SetKeyOwner(ImGuiKey_MouseWheelY, plot.ID); float correction = (plot.Hovered && equal_zoom) ? 0.5f : 1.0f;
if (zoom_rate != 0.0f) { const double plot_l = x_axis.PixelsToPlot(plot.PlotRect.Min.x - rect_size.x * tx * zoom_rate * correction);
float correction = (plot.Hovered && equal_zoom) ? 0.5f : 1.0f; const double plot_r = x_axis.PixelsToPlot(plot.PlotRect.Max.x + rect_size.x * (1 - tx) * zoom_rate * correction);
const double plot_l = x_axis.PixelsToPlot(plot.PlotRect.Min.x - rect_size.x * tx * zoom_rate * correction); x_axis.SetMin(x_axis.IsInverted() ? plot_r : plot_l);
const double plot_r = x_axis.PixelsToPlot(plot.PlotRect.Max.x + rect_size.x * (1 - tx) * zoom_rate * correction); x_axis.SetMax(x_axis.IsInverted() ? plot_l : plot_r);
x_axis.SetMin(x_axis.IsInverted() ? plot_r : plot_l); if (axis_equal && x_axis.OrthoAxis != nullptr)
x_axis.SetMax(x_axis.IsInverted() ? plot_l : plot_r); x_axis.OrthoAxis->SetAspect(x_axis.GetAspect());
if (axis_equal && x_axis.OrthoAxis != nullptr) changed = true;
x_axis.OrthoAxis->SetAspect(x_axis.GetAspect());
changed = true;
}
} }
} }
for (int i = 0; i < IMPLOT_NUM_Y_AXES; i++) { for (int i = 0; i < IMPLOT_NUM_Y_AXES; i++) {
@@ -2013,17 +1980,14 @@ bool UpdateInput(ImPlotPlot& plot) {
const bool equal_zoom = axis_equal && y_axis.OrthoAxis != nullptr; const bool equal_zoom = axis_equal && y_axis.OrthoAxis != nullptr;
const bool equal_locked = equal_zoom && y_axis.OrthoAxis->IsInputLocked(); const bool equal_locked = equal_zoom && y_axis.OrthoAxis->IsInputLocked();
if (y_hov[i] && !y_axis.IsInputLocked() && !equal_locked) { if (y_hov[i] && !y_axis.IsInputLocked() && !equal_locked) {
ImGui::SetKeyOwner(ImGuiKey_MouseWheelY, plot.ID); float correction = (plot.Hovered && equal_zoom) ? 0.5f : 1.0f;
if (zoom_rate != 0.0f) { const double plot_t = y_axis.PixelsToPlot(plot.PlotRect.Min.y - rect_size.y * ty * zoom_rate * correction);
float correction = (plot.Hovered && equal_zoom) ? 0.5f : 1.0f; const double plot_b = y_axis.PixelsToPlot(plot.PlotRect.Max.y + rect_size.y * (1 - ty) * zoom_rate * correction);
const double plot_t = y_axis.PixelsToPlot(plot.PlotRect.Min.y - rect_size.y * ty * zoom_rate * correction); y_axis.SetMin(y_axis.IsInverted() ? plot_t : plot_b);
const double plot_b = y_axis.PixelsToPlot(plot.PlotRect.Max.y + rect_size.y * (1 - ty) * zoom_rate * correction); y_axis.SetMax(y_axis.IsInverted() ? plot_b : plot_t);
y_axis.SetMin(y_axis.IsInverted() ? plot_t : plot_b); if (axis_equal && y_axis.OrthoAxis != nullptr)
y_axis.SetMax(y_axis.IsInverted() ? plot_b : plot_t); y_axis.OrthoAxis->SetAspect(y_axis.GetAspect());
if (axis_equal && y_axis.OrthoAxis != nullptr) changed = true;
y_axis.OrthoAxis->SetAspect(y_axis.GetAspect());
changed = true;
}
} }
} }
} }
@@ -2305,19 +2269,19 @@ void SetupAxesLimits(double x_min, double x_max, double y_min, double y_max, ImP
void SetupLegend(ImPlotLocation location, ImPlotLegendFlags flags) { void SetupLegend(ImPlotLocation location, ImPlotLegendFlags flags) {
ImPlotContext& gp = *GImPlot; ImPlotContext& gp = *GImPlot;
IM_ASSERT_USER_ERROR((gp.CurrentPlot != nullptr && !gp.CurrentPlot->SetupLocked) || (gp.CurrentSubplot != nullptr && gp.CurrentPlot == nullptr), IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr && !gp.CurrentPlot->SetupLocked,
"Setup needs to be called after BeginPlot or BeginSubplots and before any setup locking functions (e.g. PlotX)!"); "Setup needs to be called after BeginPlot and before any setup locking functions (e.g. PlotX)!");
if (gp.CurrentItems) { IM_ASSERT_USER_ERROR(gp.CurrentItems != nullptr,
ImPlotLegend& legend = gp.CurrentItems->Legend; "SetupLegend() needs to be called within an itemized context!");
// check and set location ImPlotLegend& legend = gp.CurrentItems->Legend;
if (location != legend.PreviousLocation) // check and set location
legend.Location = location; if (location != legend.PreviousLocation)
legend.PreviousLocation = location; legend.Location = location;
// check and set flags legend.PreviousLocation = location;
if (flags != legend.PreviousFlags) // check and set flags
legend.Flags = flags; if (flags != legend.PreviousFlags)
legend.PreviousFlags = flags; legend.Flags = flags;
} legend.PreviousFlags = flags;
} }
void SetupMouseText(ImPlotLocation location, ImPlotMouseTextFlags flags) { void SetupMouseText(ImPlotLocation location, ImPlotMouseTextFlags flags) {
@@ -2429,6 +2393,22 @@ bool BeginPlot(const char* title_id, const ImVec2& size, ImPlotFlags flags) {
for (int i = 0; i < ImAxis_COUNT; ++i) for (int i = 0; i < ImAxis_COUNT; ++i)
ApplyNextPlotData(i); ApplyNextPlotData(i);
// capture scroll with a child region
if (!ImHasFlag(plot.Flags, ImPlotFlags_NoChild)) {
ImVec2 child_size;
if (gp.CurrentSubplot != nullptr)
child_size = gp.CurrentSubplot->CellSize;
else
child_size = ImVec2(size.x == 0 ? gp.Style.PlotDefaultSize.x : size.x, size.y == 0 ? gp.Style.PlotDefaultSize.y : size.y);
ImGui::BeginChild(title_id, child_size, false, ImGuiWindowFlags_NoScrollbar);
Window = ImGui::GetCurrentWindow();
Window->ScrollMax.y = 1.0f;
gp.ChildWindowMade = true;
}
else {
gp.ChildWindowMade = false;
}
// clear text buffers // clear text buffers
plot.ClearTextBuffer(); plot.ClearTextBuffer();
plot.SetTitle(title_id); plot.SetTitle(title_id);
@@ -2570,7 +2550,7 @@ void SetupFinish() {
// (2) get y tick labels (needed for left/right pad) // (2) get y tick labels (needed for left/right pad)
for (int i = 0; i < IMPLOT_NUM_Y_AXES; i++) { for (int i = 0; i < IMPLOT_NUM_Y_AXES; i++) {
ImPlotAxis& axis = plot.YAxis(i); ImPlotAxis& axis = plot.YAxis(i);
if (axis.WillRender() && axis.ShowDefaultTicks && plot_height > 0) { if (axis.WillRender() && axis.ShowDefaultTicks) {
axis.Locator(axis.Ticker, axis.Range, plot_height, true, axis.Formatter, axis.FormatterData); axis.Locator(axis.Ticker, axis.Range, plot_height, true, axis.Formatter, axis.FormatterData);
} }
} }
@@ -2583,7 +2563,7 @@ void SetupFinish() {
// (4) get x ticks // (4) get x ticks
for (int i = 0; i < IMPLOT_NUM_X_AXES; i++) { for (int i = 0; i < IMPLOT_NUM_X_AXES; i++) {
ImPlotAxis& axis = plot.XAxis(i); ImPlotAxis& axis = plot.XAxis(i);
if (axis.WillRender() && axis.ShowDefaultTicks && plot_width > 0) { if (axis.WillRender() && axis.ShowDefaultTicks) {
axis.Locator(axis.Ticker, axis.Range, plot_width, false, axis.Formatter, axis.FormatterData); axis.Locator(axis.Ticker, axis.Range, plot_width, false, axis.Formatter, axis.FormatterData);
} }
} }
@@ -2778,7 +2758,7 @@ void EndPlot() {
// FINAL RENDER ----------------------------------------------------------- // FINAL RENDER -----------------------------------------------------------
const bool render_border = gp.Style.PlotBorderSize > 0 && GetStyleColorVec4(ImPlotCol_PlotBorder).w > 0; const bool render_border = gp.Style.PlotBorderSize > 0 && gp.Style.Colors[ImPlotCol_PlotBorder].w > 0;
const bool any_x_held = plot.Held || AnyAxesHeld(&plot.Axes[ImAxis_X1], IMPLOT_NUM_X_AXES); const bool any_x_held = plot.Held || AnyAxesHeld(&plot.Axes[ImAxis_X1], IMPLOT_NUM_X_AXES);
const bool any_y_held = plot.Held || AnyAxesHeld(&plot.Axes[ImAxis_Y1], IMPLOT_NUM_Y_AXES); const bool any_y_held = plot.Held || AnyAxesHeld(&plot.Axes[ImAxis_Y1], IMPLOT_NUM_Y_AXES);
@@ -3043,57 +3023,24 @@ void EndPlot() {
legend.Location, legend.Location,
legend_out ? gp.Style.PlotPadding : gp.Style.LegendPadding); legend_out ? gp.Style.PlotPadding : gp.Style.LegendPadding);
legend.Rect = ImRect(legend_pos, legend_pos + legend_size); legend.Rect = ImRect(legend_pos, legend_pos + legend_size);
legend.RectClamped = legend.Rect; // test hover
const bool legend_scrollable = ClampLegendRect(legend.RectClamped, legend.Hovered = ImGui::IsWindowHovered() && legend.Rect.Contains(IO.MousePos);
legend_out ? plot.FrameRect : plot.PlotRect,
legend_out ? gp.Style.PlotPadding : gp.Style.LegendPadding
);
const ImGuiButtonFlags legend_button_flags = ImGuiButtonFlags_AllowOverlap
| ImGuiButtonFlags_PressedOnClick
| ImGuiButtonFlags_PressedOnDoubleClick
| ImGuiButtonFlags_MouseButtonLeft
| ImGuiButtonFlags_MouseButtonRight
| ImGuiButtonFlags_MouseButtonMiddle
| ImGuiButtonFlags_FlattenChildren;
ImGui::KeepAliveID(plot.Items.ID);
ImGui::ButtonBehavior(legend.RectClamped, plot.Items.ID, &legend.Hovered, &legend.Held, legend_button_flags);
legend.Hovered = legend.Hovered || (ImGui::IsWindowHovered() && legend.RectClamped.Contains(IO.MousePos));
if (legend_scrollable) { if (legend_out)
if (legend.Hovered) { ImGui::PushClipRect(plot.FrameRect.Min, plot.FrameRect.Max, true);
ImGui::SetKeyOwner(ImGuiKey_MouseWheelY, plot.Items.ID); else
if (IO.MouseWheel != 0.0f) { PushPlotClipRect();
ImVec2 max_step = legend.Rect.GetSize() * 0.67f; ImU32 col_bg = GetStyleColorU32(ImPlotCol_LegendBg);
float font_size = ImGui::GetCurrentWindow()->CalcFontSize(); ImU32 col_bd = GetStyleColorU32(ImPlotCol_LegendBorder);
float scroll_step = ImFloor(ImMin(2 * font_size, max_step.x)); DrawList.AddRectFilled(legend.Rect.Min, legend.Rect.Max, col_bg);
legend.Scroll.x += scroll_step * IO.MouseWheel; DrawList.AddRect(legend.Rect.Min, legend.Rect.Max, col_bd);
legend.Scroll.y += scroll_step * IO.MouseWheel;
}
}
const ImVec2 min_scroll_offset = legend.RectClamped.GetSize() - legend.Rect.GetSize();
legend.Scroll.x = ImClamp(legend.Scroll.x, min_scroll_offset.x, 0.0f);
legend.Scroll.y = ImClamp(legend.Scroll.y, min_scroll_offset.y, 0.0f);
const ImVec2 scroll_offset = legend_horz ? ImVec2(legend.Scroll.x, 0) : ImVec2(0, legend.Scroll.y);
ImVec2 legend_offset = legend.RectClamped.Min - legend.Rect.Min + scroll_offset;
legend.Rect.Min += legend_offset;
legend.Rect.Max += legend_offset;
} else {
legend.Scroll = ImVec2(0,0);
}
const ImU32 col_bg = GetStyleColorU32(ImPlotCol_LegendBg);
const ImU32 col_bd = GetStyleColorU32(ImPlotCol_LegendBorder);
ImGui::PushClipRect(legend.RectClamped.Min, legend.RectClamped.Max, true);
DrawList.AddRectFilled(legend.RectClamped.Min, legend.RectClamped.Max, col_bg);
bool legend_contextable = ShowLegendEntries(plot.Items, legend.Rect, legend.Hovered, gp.Style.LegendInnerPadding, gp.Style.LegendSpacing, !legend_horz, DrawList) bool legend_contextable = ShowLegendEntries(plot.Items, legend.Rect, legend.Hovered, gp.Style.LegendInnerPadding, gp.Style.LegendSpacing, !legend_horz, DrawList)
&& !ImHasFlag(legend.Flags, ImPlotLegendFlags_NoMenus); && !ImHasFlag(legend.Flags, ImPlotLegendFlags_NoMenus);
DrawList.AddRect(legend.RectClamped.Min, legend.RectClamped.Max, col_bd);
ImGui::PopClipRect();
// main ctx menu // main ctx menu
if (gp.OpenContextThisFrame && legend_contextable && !ImHasFlag(plot.Flags, ImPlotFlags_NoMenus)) if (gp.OpenContextThisFrame && legend_contextable && !ImHasFlag(plot.Flags, ImPlotFlags_NoMenus))
ImGui::OpenPopup("##LegendContext"); ImGui::OpenPopup("##LegendContext");
ImGui::PopClipRect();
if (ImGui::BeginPopup("##LegendContext")) { if (ImGui::BeginPopup("##LegendContext")) {
ImGui::Text("Legend"); ImGui::Separator(); ImGui::Text("Legend"); ImGui::Separator();
if (ShowLegendContextMenu(legend, !ImHasFlag(plot.Flags, ImPlotFlags_NoLegend))) if (ShowLegendContextMenu(legend, !ImHasFlag(plot.Flags, ImPlotFlags_NoLegend)))
@@ -3403,7 +3350,7 @@ bool BeginSubplots(const char* title, int rows, int cols, const ImVec2& size, Im
subplot.FrameRect = ImRect(Window->DC.CursorPos, Window->DC.CursorPos + frame_size); subplot.FrameRect = ImRect(Window->DC.CursorPos, Window->DC.CursorPos + frame_size);
subplot.GridRect.Min = subplot.FrameRect.Min + half_pad + ImVec2(0,pad_top); subplot.GridRect.Min = subplot.FrameRect.Min + half_pad + ImVec2(0,pad_top);
subplot.GridRect.Max = subplot.FrameRect.Max - half_pad; subplot.GridRect.Max = subplot.FrameRect.Max - half_pad;
subplot.FrameHovered = subplot.FrameRect.Contains(ImGui::GetMousePos()) && ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows|ImGuiHoveredFlags_AllowWhenBlockedByActiveItem); subplot.FrameHovered = subplot.FrameRect.Contains(ImGui::GetMousePos()) && ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows);
// outside legend adjustments (TODO: make function) // outside legend adjustments (TODO: make function)
const bool share_items = ImHasFlag(subplot.Flags, ImPlotSubplotFlags_ShareItems); const bool share_items = ImHasFlag(subplot.Flags, ImPlotSubplotFlags_ShareItems);
@@ -3450,7 +3397,7 @@ bool BeginSubplots(const char* title, int rows, int cols, const ImVec2& size, Im
ImGui::KeepAliveID(sep_id); ImGui::KeepAliveID(sep_id);
const ImRect sep_bb = ImRect(subplot.GridRect.Min.x, ypos-SUBPLOT_SPLITTER_HALF_THICKNESS, subplot.GridRect.Max.x, ypos+SUBPLOT_SPLITTER_HALF_THICKNESS); const ImRect sep_bb = ImRect(subplot.GridRect.Min.x, ypos-SUBPLOT_SPLITTER_HALF_THICKNESS, subplot.GridRect.Max.x, ypos+SUBPLOT_SPLITTER_HALF_THICKNESS);
bool sep_hov = false, sep_hld = false; bool sep_hov = false, sep_hld = false;
const bool sep_clk = ImGui::ButtonBehavior(sep_bb, sep_id, &sep_hov, &sep_hld, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnDoubleClick); const bool sep_clk = ImGui::ButtonBehavior(sep_bb, sep_id, &sep_hov, &sep_hld, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_AllowItemOverlap | ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnDoubleClick);
if ((sep_hov && G.HoveredIdTimer > SUBPLOT_SPLITTER_FEEDBACK_TIMER) || sep_hld) { if ((sep_hov && G.HoveredIdTimer > SUBPLOT_SPLITTER_FEEDBACK_TIMER) || sep_hld) {
if (sep_clk && ImGui::IsMouseDoubleClicked(0)) { if (sep_clk && ImGui::IsMouseDoubleClicked(0)) {
float p = (subplot.RowRatios[r] + subplot.RowRatios[r+1])/2; float p = (subplot.RowRatios[r] + subplot.RowRatios[r+1])/2;
@@ -3480,7 +3427,7 @@ bool BeginSubplots(const char* title, int rows, int cols, const ImVec2& size, Im
ImGui::KeepAliveID(sep_id); ImGui::KeepAliveID(sep_id);
const ImRect sep_bb = ImRect(xpos-SUBPLOT_SPLITTER_HALF_THICKNESS, subplot.GridRect.Min.y, xpos+SUBPLOT_SPLITTER_HALF_THICKNESS, subplot.GridRect.Max.y); const ImRect sep_bb = ImRect(xpos-SUBPLOT_SPLITTER_HALF_THICKNESS, subplot.GridRect.Min.y, xpos+SUBPLOT_SPLITTER_HALF_THICKNESS, subplot.GridRect.Max.y);
bool sep_hov = false, sep_hld = false; bool sep_hov = false, sep_hld = false;
const bool sep_clk = ImGui::ButtonBehavior(sep_bb, sep_id, &sep_hov, &sep_hld, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnDoubleClick); const bool sep_clk = ImGui::ButtonBehavior(sep_bb, sep_id, &sep_hov, &sep_hld, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_AllowItemOverlap | ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnDoubleClick);
if ((sep_hov && G.HoveredIdTimer > SUBPLOT_SPLITTER_FEEDBACK_TIMER) || sep_hld) { if ((sep_hov && G.HoveredIdTimer > SUBPLOT_SPLITTER_FEEDBACK_TIMER) || sep_hld) {
if (sep_clk && ImGui::IsMouseDoubleClicked(0)) { if (sep_clk && ImGui::IsMouseDoubleClicked(0)) {
float p = (subplot.ColRatios[c] + subplot.ColRatios[c+1])/2; float p = (subplot.ColRatios[c] + subplot.ColRatios[c+1])/2;
@@ -3541,7 +3488,6 @@ void EndSubplots() {
ImPlotContext& gp = *GImPlot; ImPlotContext& gp = *GImPlot;
IM_ASSERT_USER_ERROR(gp.CurrentSubplot != nullptr, "Mismatched BeginSubplots()/EndSubplots()!"); IM_ASSERT_USER_ERROR(gp.CurrentSubplot != nullptr, "Mismatched BeginSubplots()/EndSubplots()!");
ImPlotSubplot& subplot = *gp.CurrentSubplot; ImPlotSubplot& subplot = *gp.CurrentSubplot;
const ImGuiIO& IO = ImGui::GetIO();
// set alignments // set alignments
for (int r = 0; r < subplot.Rows; ++r) for (int r = 0; r < subplot.Rows; ++r)
subplot.RowAlignmentData[r].End(); subplot.RowAlignmentData[r].End();
@@ -3560,60 +3506,24 @@ void EndSubplots() {
const bool share_items = ImHasFlag(subplot.Flags, ImPlotSubplotFlags_ShareItems); const bool share_items = ImHasFlag(subplot.Flags, ImPlotSubplotFlags_ShareItems);
ImDrawList& DrawList = *ImGui::GetWindowDrawList(); ImDrawList& DrawList = *ImGui::GetWindowDrawList();
if (share_items && !ImHasFlag(subplot.Flags, ImPlotSubplotFlags_NoLegend) && subplot.Items.GetLegendCount() > 0) { if (share_items && !ImHasFlag(subplot.Flags, ImPlotSubplotFlags_NoLegend) && subplot.Items.GetLegendCount() > 0) {
ImPlotLegend& legend = subplot.Items.Legend; const bool legend_horz = ImHasFlag(subplot.Items.Legend.Flags, ImPlotLegendFlags_Horizontal);
const bool legend_horz = ImHasFlag(legend.Flags, ImPlotLegendFlags_Horizontal);
const ImVec2 legend_size = CalcLegendSize(subplot.Items, gp.Style.LegendInnerPadding, gp.Style.LegendSpacing, !legend_horz); const ImVec2 legend_size = CalcLegendSize(subplot.Items, gp.Style.LegendInnerPadding, gp.Style.LegendSpacing, !legend_horz);
const ImVec2 legend_pos = GetLocationPos(subplot.FrameRect, legend_size, legend.Location, gp.Style.PlotPadding); const ImVec2 legend_pos = GetLocationPos(subplot.FrameRect, legend_size, subplot.Items.Legend.Location, gp.Style.PlotPadding);
legend.Rect = ImRect(legend_pos, legend_pos + legend_size); subplot.Items.Legend.Rect = ImRect(legend_pos, legend_pos + legend_size);
legend.RectClamped = legend.Rect; subplot.Items.Legend.Hovered = subplot.FrameHovered && subplot.Items.Legend.Rect.Contains(ImGui::GetIO().MousePos);
const bool legend_scrollable = ClampLegendRect(legend.RectClamped,subplot.FrameRect, gp.Style.PlotPadding); ImGui::PushClipRect(subplot.FrameRect.Min, subplot.FrameRect.Max, true);
const ImGuiButtonFlags legend_button_flags = ImGuiButtonFlags_AllowOverlap ImU32 col_bg = GetStyleColorU32(ImPlotCol_LegendBg);
| ImGuiButtonFlags_PressedOnClick ImU32 col_bd = GetStyleColorU32(ImPlotCol_LegendBorder);
| ImGuiButtonFlags_PressedOnDoubleClick DrawList.AddRectFilled(subplot.Items.Legend.Rect.Min, subplot.Items.Legend.Rect.Max, col_bg);
| ImGuiButtonFlags_MouseButtonLeft DrawList.AddRect(subplot.Items.Legend.Rect.Min, subplot.Items.Legend.Rect.Max, col_bd);
| ImGuiButtonFlags_MouseButtonRight bool legend_contextable = ShowLegendEntries(subplot.Items, subplot.Items.Legend.Rect, subplot.Items.Legend.Hovered, gp.Style.LegendInnerPadding, gp.Style.LegendSpacing, !legend_horz, DrawList)
| ImGuiButtonFlags_MouseButtonMiddle && !ImHasFlag(subplot.Items.Legend.Flags, ImPlotLegendFlags_NoMenus);
| ImGuiButtonFlags_FlattenChildren;
ImGui::KeepAliveID(subplot.Items.ID);
ImGui::ButtonBehavior(legend.RectClamped, subplot.Items.ID, &legend.Hovered, &legend.Held, legend_button_flags);
legend.Hovered = legend.Hovered || (subplot.FrameHovered && legend.RectClamped.Contains(ImGui::GetIO().MousePos));
if (legend_scrollable) {
if (legend.Hovered) {
ImGui::SetKeyOwner(ImGuiKey_MouseWheelY, subplot.Items.ID);
if (IO.MouseWheel != 0.0f) {
ImVec2 max_step = legend.Rect.GetSize() * 0.67f;
float font_size = ImGui::GetCurrentWindow()->CalcFontSize();
float scroll_step = ImFloor(ImMin(2 * font_size, max_step.x));
legend.Scroll.x += scroll_step * IO.MouseWheel;
legend.Scroll.y += scroll_step * IO.MouseWheel;
}
}
const ImVec2 min_scroll_offset = legend.RectClamped.GetSize() - legend.Rect.GetSize();
legend.Scroll.x = ImClamp(legend.Scroll.x, min_scroll_offset.x, 0.0f);
legend.Scroll.y = ImClamp(legend.Scroll.y, min_scroll_offset.y, 0.0f);
const ImVec2 scroll_offset = legend_horz ? ImVec2(legend.Scroll.x, 0) : ImVec2(0, legend.Scroll.y);
ImVec2 legend_offset = legend.RectClamped.Min - legend.Rect.Min + scroll_offset;
legend.Rect.Min += legend_offset;
legend.Rect.Max += legend_offset;
} else {
legend.Scroll = ImVec2(0,0);
}
const ImU32 col_bg = GetStyleColorU32(ImPlotCol_LegendBg);
const ImU32 col_bd = GetStyleColorU32(ImPlotCol_LegendBorder);
ImGui::PushClipRect(legend.RectClamped.Min, legend.RectClamped.Max, true);
DrawList.AddRectFilled(legend.RectClamped.Min, legend.RectClamped.Max, col_bg);
bool legend_contextable = ShowLegendEntries(subplot.Items, legend.Rect, legend.Hovered, gp.Style.LegendInnerPadding, gp.Style.LegendSpacing, !legend_horz, DrawList)
&& !ImHasFlag(legend.Flags, ImPlotLegendFlags_NoMenus);
DrawList.AddRect(legend.RectClamped.Min, legend.RectClamped.Max, col_bd);
ImGui::PopClipRect();
if (legend_contextable && !ImHasFlag(subplot.Flags, ImPlotSubplotFlags_NoMenus) && ImGui::GetIO().MouseReleased[gp.InputMap.Menu]) if (legend_contextable && !ImHasFlag(subplot.Flags, ImPlotSubplotFlags_NoMenus) && ImGui::GetIO().MouseReleased[gp.InputMap.Menu])
ImGui::OpenPopup("##LegendContext"); ImGui::OpenPopup("##LegendContext");
ImGui::PopClipRect();
if (ImGui::BeginPopup("##LegendContext")) { if (ImGui::BeginPopup("##LegendContext")) {
ImGui::Text("Legend"); ImGui::Separator(); ImGui::Text("Legend"); ImGui::Separator();
if (ShowLegendContextMenu(legend, !ImHasFlag(subplot.Flags, ImPlotFlags_NoLegend))) if (ShowLegendContextMenu(subplot.Items.Legend, !ImHasFlag(subplot.Flags, ImPlotFlags_NoLegend)))
ImFlipFlag(subplot.Flags, ImPlotFlags_NoLegend); ImFlipFlag(subplot.Flags, ImPlotFlags_NoLegend);
ImGui::EndPopup(); ImGui::EndPopup();
} }
@@ -3894,7 +3804,7 @@ IMPLOT_API void TagYV(double y, const ImVec4& color, const char* fmt, va_list ar
static const float DRAG_GRAB_HALF_SIZE = 4.0f; static const float DRAG_GRAB_HALF_SIZE = 4.0f;
bool DragPoint(int n_id, double* x, double* y, const ImVec4& col, float radius, ImPlotDragToolFlags flags, bool* out_clicked, bool* out_hovered, bool* out_held) { bool DragPoint(int n_id, double* x, double* y, const ImVec4& col, float radius, ImPlotDragToolFlags flags) {
ImGui::PushID("#IMPLOT_DRAG_POINT"); ImGui::PushID("#IMPLOT_DRAG_POINT");
IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != nullptr, "DragPoint() needs to be called between BeginPlot() and EndPlot()!"); IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != nullptr, "DragPoint() needs to be called between BeginPlot() and EndPlot()!");
SetupLock(); SetupLock();
@@ -3916,34 +3826,30 @@ bool DragPoint(int n_id, double* x, double* y, const ImVec4& col, float radius,
bool hovered = false, held = false; bool hovered = false, held = false;
ImGui::KeepAliveID(id); ImGui::KeepAliveID(id);
if (input) { if (input)
bool clicked = ImGui::ButtonBehavior(rect,id,&hovered,&held); ImGui::ButtonBehavior(rect,id,&hovered,&held);
if (out_clicked) *out_clicked = clicked;
if (out_hovered) *out_hovered = hovered;
if (out_held) *out_held = held;
}
bool modified = false; bool dragging = false;
if (held && ImGui::IsMouseDragging(0)) { if (held && ImGui::IsMouseDragging(0)) {
*x = ImPlot::GetPlotMousePos(IMPLOT_AUTO,IMPLOT_AUTO).x; *x = ImPlot::GetPlotMousePos(IMPLOT_AUTO,IMPLOT_AUTO).x;
*y = ImPlot::GetPlotMousePos(IMPLOT_AUTO,IMPLOT_AUTO).y; *y = ImPlot::GetPlotMousePos(IMPLOT_AUTO,IMPLOT_AUTO).y;
modified = true; dragging = true;
} }
PushPlotClipRect(); PushPlotClipRect();
ImDrawList& DrawList = *GetPlotDrawList(); ImDrawList& DrawList = *GetPlotDrawList();
if ((hovered || held) && show_curs) if ((hovered || held) && show_curs)
ImGui::SetMouseCursor(ImGuiMouseCursor_Hand); ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
if (modified && no_delay) if (dragging && no_delay)
pos = PlotToPixels(*x,*y,IMPLOT_AUTO,IMPLOT_AUTO); pos = PlotToPixels(*x,*y,IMPLOT_AUTO,IMPLOT_AUTO);
DrawList.AddCircleFilled(pos, radius, col32); DrawList.AddCircleFilled(pos, radius, col32);
PopPlotClipRect(); PopPlotClipRect();
ImGui::PopID(); ImGui::PopID();
return modified; return dragging;
} }
bool DragLineX(int n_id, double* value, const ImVec4& col, float thickness, ImPlotDragToolFlags flags, bool* out_clicked, bool* out_hovered, bool* out_held) { bool DragLineX(int n_id, double* value, const ImVec4& col, float thickness, ImPlotDragToolFlags flags) {
// ImGui::PushID("#IMPLOT_DRAG_LINE_X"); // ImGui::PushID("#IMPLOT_DRAG_LINE_X");
ImPlotContext& gp = *GImPlot; ImPlotContext& gp = *GImPlot;
IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, "DragLineX() needs to be called between BeginPlot() and EndPlot()!"); IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, "DragLineX() needs to be called between BeginPlot() and EndPlot()!");
@@ -3965,12 +3871,8 @@ bool DragLineX(int n_id, double* value, const ImVec4& col, float thickness, ImPl
bool hovered = false, held = false; bool hovered = false, held = false;
ImGui::KeepAliveID(id); ImGui::KeepAliveID(id);
if (input) { if (input)
bool clicked = ImGui::ButtonBehavior(rect,id,&hovered,&held); ImGui::ButtonBehavior(rect,id,&hovered,&held);
if (out_clicked) *out_clicked = clicked;
if (out_hovered) *out_hovered = hovered;
if (out_held) *out_held = held;
}
if ((hovered || held) && show_curs) if ((hovered || held) && show_curs)
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW); ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW);
@@ -3979,15 +3881,15 @@ bool DragLineX(int n_id, double* value, const ImVec4& col, float thickness, ImPl
ImVec4 color = IsColorAuto(col) ? ImGui::GetStyleColorVec4(ImGuiCol_Text) : col; ImVec4 color = IsColorAuto(col) ? ImGui::GetStyleColorVec4(ImGuiCol_Text) : col;
ImU32 col32 = ImGui::ColorConvertFloat4ToU32(color); ImU32 col32 = ImGui::ColorConvertFloat4ToU32(color);
bool modified = false; bool dragging = false;
if (held && ImGui::IsMouseDragging(0)) { if (held && ImGui::IsMouseDragging(0)) {
*value = ImPlot::GetPlotMousePos(IMPLOT_AUTO,IMPLOT_AUTO).x; *value = ImPlot::GetPlotMousePos(IMPLOT_AUTO,IMPLOT_AUTO).x;
modified = true; dragging = true;
} }
PushPlotClipRect(); PushPlotClipRect();
ImDrawList& DrawList = *GetPlotDrawList(); ImDrawList& DrawList = *GetPlotDrawList();
if (modified && no_delay) if (dragging && no_delay)
x = IM_ROUND(PlotToPixels(*value,0,IMPLOT_AUTO,IMPLOT_AUTO).x); x = IM_ROUND(PlotToPixels(*value,0,IMPLOT_AUTO,IMPLOT_AUTO).x);
DrawList.AddLine(ImVec2(x,yt), ImVec2(x,yb), col32, thickness); DrawList.AddLine(ImVec2(x,yt), ImVec2(x,yb), col32, thickness);
DrawList.AddLine(ImVec2(x,yt), ImVec2(x,yt+len), col32, 3*thickness); DrawList.AddLine(ImVec2(x,yt), ImVec2(x,yt+len), col32, 3*thickness);
@@ -3995,10 +3897,10 @@ bool DragLineX(int n_id, double* value, const ImVec4& col, float thickness, ImPl
PopPlotClipRect(); PopPlotClipRect();
// ImGui::PopID(); // ImGui::PopID();
return modified; return dragging;
} }
bool DragLineY(int n_id, double* value, const ImVec4& col, float thickness, ImPlotDragToolFlags flags, bool* out_clicked, bool* out_hovered, bool* out_held) { bool DragLineY(int n_id, double* value, const ImVec4& col, float thickness, ImPlotDragToolFlags flags) {
ImGui::PushID("#IMPLOT_DRAG_LINE_Y"); ImGui::PushID("#IMPLOT_DRAG_LINE_Y");
ImPlotContext& gp = *GImPlot; ImPlotContext& gp = *GImPlot;
IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, "DragLineY() needs to be called between BeginPlot() and EndPlot()!"); IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, "DragLineY() needs to be called between BeginPlot() and EndPlot()!");
@@ -4021,12 +3923,8 @@ bool DragLineY(int n_id, double* value, const ImVec4& col, float thickness, ImPl
bool hovered = false, held = false; bool hovered = false, held = false;
ImGui::KeepAliveID(id); ImGui::KeepAliveID(id);
if (input) { if (input)
bool clicked = ImGui::ButtonBehavior(rect,id,&hovered,&held); ImGui::ButtonBehavior(rect,id,&hovered,&held);
if (out_clicked) *out_clicked = clicked;
if (out_hovered) *out_hovered = hovered;
if (out_held) *out_held = held;
}
if ((hovered || held) && show_curs) if ((hovered || held) && show_curs)
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeNS); ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeNS);
@@ -4035,15 +3933,15 @@ bool DragLineY(int n_id, double* value, const ImVec4& col, float thickness, ImPl
ImVec4 color = IsColorAuto(col) ? ImGui::GetStyleColorVec4(ImGuiCol_Text) : col; ImVec4 color = IsColorAuto(col) ? ImGui::GetStyleColorVec4(ImGuiCol_Text) : col;
ImU32 col32 = ImGui::ColorConvertFloat4ToU32(color); ImU32 col32 = ImGui::ColorConvertFloat4ToU32(color);
bool modified = false; bool dragging = false;
if (held && ImGui::IsMouseDragging(0)) { if (held && ImGui::IsMouseDragging(0)) {
*value = ImPlot::GetPlotMousePos(IMPLOT_AUTO,IMPLOT_AUTO).y; *value = ImPlot::GetPlotMousePos(IMPLOT_AUTO,IMPLOT_AUTO).y;
modified = true; dragging = true;
} }
PushPlotClipRect(); PushPlotClipRect();
ImDrawList& DrawList = *GetPlotDrawList(); ImDrawList& DrawList = *GetPlotDrawList();
if (modified && no_delay) if (dragging && no_delay)
y = IM_ROUND(PlotToPixels(0, *value,IMPLOT_AUTO,IMPLOT_AUTO).y); y = IM_ROUND(PlotToPixels(0, *value,IMPLOT_AUTO,IMPLOT_AUTO).y);
DrawList.AddLine(ImVec2(xl,y), ImVec2(xr,y), col32, thickness); DrawList.AddLine(ImVec2(xl,y), ImVec2(xr,y), col32, thickness);
DrawList.AddLine(ImVec2(xl,y), ImVec2(xl+len,y), col32, 3*thickness); DrawList.AddLine(ImVec2(xl,y), ImVec2(xl+len,y), col32, 3*thickness);
@@ -4051,10 +3949,10 @@ bool DragLineY(int n_id, double* value, const ImVec4& col, float thickness, ImPl
PopPlotClipRect(); PopPlotClipRect();
ImGui::PopID(); ImGui::PopID();
return modified; return dragging;
} }
bool DragRect(int n_id, double* x_min, double* y_min, double* x_max, double* y_max, const ImVec4& col, ImPlotDragToolFlags flags, bool* out_clicked, bool* out_hovered, bool* out_held) { bool DragRect(int n_id, double* x_min, double* y_min, double* x_max, double* y_max, const ImVec4& col, ImPlotDragToolFlags flags) {
ImGui::PushID("#IMPLOT_DRAG_RECT"); ImGui::PushID("#IMPLOT_DRAG_RECT");
IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != nullptr, "DragRect() needs to be called between BeginPlot() and EndPlot()!"); IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != nullptr, "DragRect() needs to be called between BeginPlot() and EndPlot()!");
SetupLock(); SetupLock();
@@ -4091,18 +3989,13 @@ bool DragRect(int n_id, double* x_min, double* y_min, double* x_max, double* y_m
ImU32 col32_a = ImGui::ColorConvertFloat4ToU32(color); ImU32 col32_a = ImGui::ColorConvertFloat4ToU32(color);
const ImGuiID id = ImGui::GetCurrentWindow()->GetID(n_id); const ImGuiID id = ImGui::GetCurrentWindow()->GetID(n_id);
bool modified = false; bool dragging = false;
bool clicked = false, hovered = false, held = false; bool hovered = false, held = false;
ImRect b_rect(pc.x-DRAG_GRAB_HALF_SIZE,pc.y-DRAG_GRAB_HALF_SIZE,pc.x+DRAG_GRAB_HALF_SIZE,pc.y+DRAG_GRAB_HALF_SIZE); ImRect b_rect(pc.x-DRAG_GRAB_HALF_SIZE,pc.y-DRAG_GRAB_HALF_SIZE,pc.x+DRAG_GRAB_HALF_SIZE,pc.y+DRAG_GRAB_HALF_SIZE);
ImGui::KeepAliveID(id); ImGui::KeepAliveID(id);
if (input) { if (input)
// middle point ImGui::ButtonBehavior(b_rect,id,&hovered,&held);
clicked = ImGui::ButtonBehavior(b_rect,id,&hovered,&held);
if (out_clicked) *out_clicked = clicked;
if (out_hovered) *out_hovered = hovered;
if (out_held) *out_held = held;
}
if ((hovered || held) && show_curs) if ((hovered || held) && show_curs)
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeAll); ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeAll);
@@ -4112,7 +4005,7 @@ bool DragRect(int n_id, double* x_min, double* y_min, double* x_max, double* y_m
*y[i] = pp.y; *y[i] = pp.y;
*x[i] = pp.x; *x[i] = pp.x;
} }
modified = true; dragging = true;
} }
for (int i = 0; i < 4; ++i) { for (int i = 0; i < 4; ++i) {
@@ -4120,19 +4013,15 @@ bool DragRect(int n_id, double* x_min, double* y_min, double* x_max, double* y_m
b_rect = ImRect(p[i].x-DRAG_GRAB_HALF_SIZE,p[i].y-DRAG_GRAB_HALF_SIZE,p[i].x+DRAG_GRAB_HALF_SIZE,p[i].y+DRAG_GRAB_HALF_SIZE); b_rect = ImRect(p[i].x-DRAG_GRAB_HALF_SIZE,p[i].y-DRAG_GRAB_HALF_SIZE,p[i].x+DRAG_GRAB_HALF_SIZE,p[i].y+DRAG_GRAB_HALF_SIZE);
ImGuiID p_id = id + i + 1; ImGuiID p_id = id + i + 1;
ImGui::KeepAliveID(p_id); ImGui::KeepAliveID(p_id);
if (input) { if (input)
clicked = ImGui::ButtonBehavior(b_rect,p_id,&hovered,&held); ImGui::ButtonBehavior(b_rect,p_id,&hovered,&held);
if (out_clicked) *out_clicked = *out_clicked || clicked;
if (out_hovered) *out_hovered = *out_hovered || hovered;
if (out_held) *out_held = *out_held || held;
}
if ((hovered || held) && show_curs) if ((hovered || held) && show_curs)
ImGui::SetMouseCursor(cur[i]); ImGui::SetMouseCursor(cur[i]);
if (held && ImGui::IsMouseDragging(0)) { if (held && ImGui::IsMouseDragging(0)) {
*x[i] = ImPlot::GetPlotMousePos(IMPLOT_AUTO,IMPLOT_AUTO).x; *x[i] = ImPlot::GetPlotMousePos(IMPLOT_AUTO,IMPLOT_AUTO).x;
*y[i] = ImPlot::GetPlotMousePos(IMPLOT_AUTO,IMPLOT_AUTO).y; *y[i] = ImPlot::GetPlotMousePos(IMPLOT_AUTO,IMPLOT_AUTO).y;
modified = true; dragging = true;
} }
// edges // edges
@@ -4142,12 +4031,8 @@ bool DragRect(int n_id, double* x_min, double* y_min, double* x_max, double* y_m
: ImRect(e_min.x - DRAG_GRAB_HALF_SIZE, e_min.y + DRAG_GRAB_HALF_SIZE, e_max.x + DRAG_GRAB_HALF_SIZE, e_max.y - DRAG_GRAB_HALF_SIZE); : ImRect(e_min.x - DRAG_GRAB_HALF_SIZE, e_min.y + DRAG_GRAB_HALF_SIZE, e_max.x + DRAG_GRAB_HALF_SIZE, e_max.y - DRAG_GRAB_HALF_SIZE);
ImGuiID e_id = id + i + 5; ImGuiID e_id = id + i + 5;
ImGui::KeepAliveID(e_id); ImGui::KeepAliveID(e_id);
if (input) { if (input)
clicked = ImGui::ButtonBehavior(b_rect,e_id,&hovered,&held); ImGui::ButtonBehavior(b_rect,e_id,&hovered,&held);
if (out_clicked) *out_clicked = *out_clicked || clicked;
if (out_hovered) *out_hovered = *out_hovered || hovered;
if (out_held) *out_held = *out_held || held;
}
if ((hovered || held) && show_curs) if ((hovered || held) && show_curs)
h[i] ? ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeNS) : ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW); h[i] ? ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeNS) : ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW);
if (held && ImGui::IsMouseDragging(0)) { if (held && ImGui::IsMouseDragging(0)) {
@@ -4155,7 +4040,7 @@ bool DragRect(int n_id, double* x_min, double* y_min, double* x_max, double* y_m
*y[i] = ImPlot::GetPlotMousePos(IMPLOT_AUTO,IMPLOT_AUTO).y; *y[i] = ImPlot::GetPlotMousePos(IMPLOT_AUTO,IMPLOT_AUTO).y;
else else
*x[i] = ImPlot::GetPlotMousePos(IMPLOT_AUTO,IMPLOT_AUTO).x; *x[i] = ImPlot::GetPlotMousePos(IMPLOT_AUTO,IMPLOT_AUTO).x;
modified = true; dragging = true;
} }
if (hovered && ImGui::IsMouseDoubleClicked(0)) if (hovered && ImGui::IsMouseDoubleClicked(0))
{ {
@@ -4164,22 +4049,14 @@ bool DragRect(int n_id, double* x_min, double* y_min, double* x_max, double* y_m
*y[i] = ((y[i] == y_min && *y_min < *y_max) || (y[i] == y_max && *y_max < *y_min)) ? b.Y.Min : b.Y.Max; *y[i] = ((y[i] == y_min && *y_min < *y_max) || (y[i] == y_max && *y_max < *y_min)) ? b.Y.Min : b.Y.Max;
else else
*x[i] = ((x[i] == x_min && *x_min < *x_max) || (x[i] == x_max && *x_max < *x_min)) ? b.X.Min : b.X.Max; *x[i] = ((x[i] == x_min && *x_min < *x_max) || (x[i] == x_max && *x_max < *x_min)) ? b.X.Min : b.X.Max;
modified = true; dragging = true;
} }
} }
const bool mouse_inside = rect_grab.Contains(ImGui::GetMousePos());
const bool mouse_clicked = ImGui::IsMouseClicked(0);
const bool mouse_down = ImGui::IsMouseDown(0);
if (input && mouse_inside) {
if (out_clicked) *out_clicked = *out_clicked || mouse_clicked;
if (out_hovered) *out_hovered = true;
if (out_held) *out_held = *out_held || mouse_down;
}
PushPlotClipRect(); PushPlotClipRect();
ImDrawList& DrawList = *GetPlotDrawList(); ImDrawList& DrawList = *GetPlotDrawList();
if (modified && no_delay) { if (dragging && no_delay) {
for (int i = 0; i < 4; ++i) for (int i = 0; i < 4; ++i)
p[i] = PlotToPixels(*x[i],*y[i],IMPLOT_AUTO,IMPLOT_AUTO); p[i] = PlotToPixels(*x[i],*y[i],IMPLOT_AUTO,IMPLOT_AUTO);
pc = PlotToPixels((*x_min+*x_max)/2,(*y_min+*y_max)/2,IMPLOT_AUTO,IMPLOT_AUTO); pc = PlotToPixels((*x_min+*x_max)/2,(*y_min+*y_max)/2,IMPLOT_AUTO,IMPLOT_AUTO);
@@ -4187,18 +4064,18 @@ bool DragRect(int n_id, double* x_min, double* y_min, double* x_max, double* y_m
} }
DrawList.AddRectFilled(rect.Min, rect.Max, col32_a); DrawList.AddRectFilled(rect.Min, rect.Max, col32_a);
DrawList.AddRect(rect.Min, rect.Max, col32); DrawList.AddRect(rect.Min, rect.Max, col32);
if (input && (modified || mouse_inside)) { if (input && (dragging || rect_grab.Contains(ImGui::GetMousePos()))) {
DrawList.AddCircleFilled(pc,DRAG_GRAB_HALF_SIZE,col32); DrawList.AddCircleFilled(pc,DRAG_GRAB_HALF_SIZE,col32);
for (int i = 0; i < 4; ++i) for (int i = 0; i < 4; ++i)
DrawList.AddCircleFilled(p[i],DRAG_GRAB_HALF_SIZE,col32); DrawList.AddCircleFilled(p[i],DRAG_GRAB_HALF_SIZE,col32);
} }
PopPlotClipRect(); PopPlotClipRect();
ImGui::PopID(); ImGui::PopID();
return modified; return dragging;
} }
bool DragRect(int id, ImPlotRect* bounds, const ImVec4& col, ImPlotDragToolFlags flags, bool* out_clicked, bool* out_hovered, bool* out_held) { bool DragRect(int id, ImPlotRect* bounds, const ImVec4& col, ImPlotDragToolFlags flags) {
return DragRect(id, &bounds->X.Min, &bounds->Y.Min,&bounds->X.Max, &bounds->Y.Max, col, flags, out_clicked, out_hovered, out_held); return DragRect(id, &bounds->X.Min, &bounds->Y.Min,&bounds->X.Max, &bounds->Y.Max, col, flags);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -4294,7 +4171,7 @@ bool BeginDragDropTargetAxis(ImAxis axis) {
bool BeginDragDropTargetLegend() { bool BeginDragDropTargetLegend() {
SetupLock(); SetupLock();
ImPlotItemGroup& items = *GImPlot->CurrentItems; ImPlotItemGroup& items = *GImPlot->CurrentItems;
ImRect rect = items.Legend.RectClamped; ImRect rect = items.Legend.Rect;
return ImGui::BeginDragDropTargetCustom(rect, items.ID); return ImGui::BeginDragDropTargetCustom(rect, items.ID);
} }
@@ -5233,7 +5110,6 @@ void ShowMetricsWindow(bool* p_popen) {
static bool show_frame_rects = false; static bool show_frame_rects = false;
static bool show_subplot_frame_rects = false; static bool show_subplot_frame_rects = false;
static bool show_subplot_grid_rects = false; static bool show_subplot_grid_rects = false;
static bool show_legend_rects = false;
ImDrawList& fg = *ImGui::GetForegroundDrawList(); ImDrawList& fg = *ImGui::GetForegroundDrawList();
@@ -5258,7 +5134,6 @@ void ShowMetricsWindow(bool* p_popen) {
ImGui::Checkbox("Show Axis Rects", &show_axis_rects); ImGui::Checkbox("Show Axis Rects", &show_axis_rects);
ImGui::Checkbox("Show Subplot Frame Rects", &show_subplot_frame_rects); ImGui::Checkbox("Show Subplot Frame Rects", &show_subplot_frame_rects);
ImGui::Checkbox("Show Subplot Grid Rects", &show_subplot_grid_rects); ImGui::Checkbox("Show Subplot Grid Rects", &show_subplot_grid_rects);
ImGui::Checkbox("Show Legend Rects", &show_legend_rects);
ImGui::TreePop(); ImGui::TreePop();
} }
const int n_plots = gp.Plots.GetBufSize(); const int n_plots = gp.Plots.GetBufSize();
@@ -5280,10 +5155,6 @@ void ShowMetricsWindow(bool* p_popen) {
fg.AddRect(plot->Axes[i].HoverRect.Min, plot->Axes[i].HoverRect.Max, IM_COL32(0,255,0,255)); fg.AddRect(plot->Axes[i].HoverRect.Min, plot->Axes[i].HoverRect.Max, IM_COL32(0,255,0,255));
} }
} }
if (show_legend_rects && plot->Items.GetLegendCount() > 0) {
fg.AddRect(plot->Items.Legend.Rect.Min, plot->Items.Legend.Rect.Max, IM_COL32(255,192,0,255));
fg.AddRect(plot->Items.Legend.RectClamped.Min, plot->Items.Legend.RectClamped.Max, IM_COL32(255,128,0,255));
}
} }
for (int p = 0; p < n_subplots; ++p) { for (int p = 0; p < n_subplots; ++p) {
ImPlotSubplot* subplot = gp.Subplots.GetByIndex(p); ImPlotSubplot* subplot = gp.Subplots.GetByIndex(p);
@@ -5291,10 +5162,6 @@ void ShowMetricsWindow(bool* p_popen) {
fg.AddRect(subplot->FrameRect.Min, subplot->FrameRect.Max, IM_COL32(255,0,0,255)); fg.AddRect(subplot->FrameRect.Min, subplot->FrameRect.Max, IM_COL32(255,0,0,255));
if (show_subplot_grid_rects) if (show_subplot_grid_rects)
fg.AddRect(subplot->GridRect.Min, subplot->GridRect.Max, IM_COL32(0,0,255,255)); fg.AddRect(subplot->GridRect.Min, subplot->GridRect.Max, IM_COL32(0,0,255,255));
if (show_legend_rects && subplot->Items.GetLegendCount() > 0) {
fg.AddRect(subplot->Items.Legend.Rect.Min, subplot->Items.Legend.Rect.Max, IM_COL32(255,192,0,255));
fg.AddRect(subplot->Items.Legend.RectClamped.Min, subplot->Items.Legend.RectClamped.Max, IM_COL32(255,128,0,255));
}
} }
if (ImGui::TreeNode("Plots","Plots (%d)", n_plots)) { if (ImGui::TreeNode("Plots","Plots (%d)", n_plots)) {
for (int p = 0; p < n_plots; ++p) { for (int p = 0; p < n_plots; ++p) {

View File

@@ -1,6 +1,6 @@
// MIT License // MIT License
// Copyright (c) 2023 Evan Pezent // Copyright (c) 2022 Evan Pezent
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
@@ -20,7 +20,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE. // SOFTWARE.
// ImPlot v0.17 // ImPlot v0.14
// We define this so that the demo does not accidentally use deprecated API // We define this so that the demo does not accidentally use deprecated API
#ifndef IMPLOT_DISABLE_OBSOLETE_FUNCTIONS #ifndef IMPLOT_DISABLE_OBSOLETE_FUNCTIONS
@@ -610,8 +610,10 @@ void Demo_PieCharts() {
static ImPlotPieChartFlags flags = 0; static ImPlotPieChartFlags flags = 0;
ImGui::SetNextItemWidth(250); ImGui::SetNextItemWidth(250);
ImGui::DragFloat4("Values", data1, 0.01f, 0, 1); ImGui::DragFloat4("Values", data1, 0.01f, 0, 1);
CHECKBOX_FLAG(flags, ImPlotPieChartFlags_Normalize); if ((data1[0] + data1[1] + data1[2] + data1[3]) < 1) {
CHECKBOX_FLAG(flags, ImPlotPieChartFlags_IgnoreHidden); ImGui::SameLine();
CHECKBOX_FLAG(flags,ImPlotPieChartFlags_Normalize);
}
if (ImPlot::BeginPlot("##Pie1", ImVec2(250,250), ImPlotFlags_Equal | ImPlotFlags_NoMouseText)) { if (ImPlot::BeginPlot("##Pie1", ImVec2(250,250), ImPlotFlags_Equal | ImPlotFlags_NoMouseText)) {
ImPlot::SetupAxes(nullptr, nullptr, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations); ImPlot::SetupAxes(nullptr, nullptr, ImPlotAxisFlags_NoDecorations, ImPlotAxisFlags_NoDecorations);
@@ -1145,7 +1147,7 @@ void Demo_MultipleAxes() {
ImPlot::SetAxes(ImAxis_X1, ImAxis_Y2); ImPlot::SetAxes(ImAxis_X1, ImAxis_Y2);
ImPlot::PlotLine("f(x) = cos(x)*.2+.5", xs, ys2, 1001); ImPlot::PlotLine("f(x) = cos(x)*.2+.5", xs, ys2, 1001);
} }
if (x2_axis && y3_axis) { if (y3_axis) {
ImPlot::SetAxes(ImAxis_X2, ImAxis_Y3); ImPlot::SetAxes(ImAxis_X2, ImAxis_Y3);
ImPlot::PlotLine("f(x) = sin(x+.5)*100+200 ", xs2, ys3, 1001); ImPlot::PlotLine("f(x) = sin(x+.5)*100+200 ", xs2, ys3, 1001);
} }
@@ -1262,7 +1264,7 @@ ImPlotPoint SinewaveGetter(int i, void* data) {
void Demo_SubplotsSizing() { void Demo_SubplotsSizing() {
static ImPlotSubplotFlags flags = ImPlotSubplotFlags_ShareItems|ImPlotSubplotFlags_NoLegend; static ImPlotSubplotFlags flags = ImPlotSubplotFlags_None;
ImGui::CheckboxFlags("ImPlotSubplotFlags_NoResize", (unsigned int*)&flags, ImPlotSubplotFlags_NoResize); ImGui::CheckboxFlags("ImPlotSubplotFlags_NoResize", (unsigned int*)&flags, ImPlotSubplotFlags_NoResize);
ImGui::CheckboxFlags("ImPlotSubplotFlags_NoTitle", (unsigned int*)&flags, ImPlotSubplotFlags_NoTitle); ImGui::CheckboxFlags("ImPlotSubplotFlags_NoTitle", (unsigned int*)&flags, ImPlotSubplotFlags_NoTitle);
@@ -1270,26 +1272,17 @@ void Demo_SubplotsSizing() {
static int cols = 3; static int cols = 3;
ImGui::SliderInt("Rows",&rows,1,5); ImGui::SliderInt("Rows",&rows,1,5);
ImGui::SliderInt("Cols",&cols,1,5); ImGui::SliderInt("Cols",&cols,1,5);
if (rows < 1 || cols < 1) {
ImGui::TextColored(ImVec4(1,0,0,1), "Nice try, but the number of rows and columns must be greater than 0!");
return;
}
static float rratios[] = {5,1,1,1,1,1}; static float rratios[] = {5,1,1,1,1,1};
static float cratios[] = {5,1,1,1,1,1}; static float cratios[] = {5,1,1,1,1,1};
ImGui::DragScalarN("Row Ratios",ImGuiDataType_Float,rratios,rows,0.01f,nullptr); ImGui::DragScalarN("Row Ratios",ImGuiDataType_Float,rratios,rows,0.01f,nullptr);
ImGui::DragScalarN("Col Ratios",ImGuiDataType_Float,cratios,cols,0.01f,nullptr); ImGui::DragScalarN("Col Ratios",ImGuiDataType_Float,cratios,cols,0.01f,nullptr);
if (ImPlot::BeginSubplots("My Subplots", rows, cols, ImVec2(-1,400), flags, rratios, cratios)) { if (ImPlot::BeginSubplots("My Subplots", rows, cols, ImVec2(-1,400), flags, rratios, cratios)) {
int id = 0;
for (int i = 0; i < rows*cols; ++i) { for (int i = 0; i < rows*cols; ++i) {
if (ImPlot::BeginPlot("",ImVec2(),ImPlotFlags_NoLegend)) { if (ImPlot::BeginPlot("",ImVec2(),ImPlotFlags_NoLegend)) {
ImPlot::SetupAxes(nullptr,nullptr,ImPlotAxisFlags_NoDecorations,ImPlotAxisFlags_NoDecorations); ImPlot::SetupAxes(nullptr,nullptr,ImPlotAxisFlags_NoDecorations,ImPlotAxisFlags_NoDecorations);
float fi = 0.01f * (i+1); float fi = 0.01f * (i+1);
if (rows*cols > 1) { ImPlot::SetNextLineStyle(SampleColormap((float)i/(float)(rows*cols-1),ImPlotColormap_Jet));
ImPlot::SetNextLineStyle(SampleColormap((float)i/(float)(rows*cols-1),ImPlotColormap_Jet)); ImPlot::PlotLineG("data",SinewaveGetter,&fi,1000);
}
char label[16];
snprintf(label, sizeof(label), "data%d", id++);
ImPlot::PlotLineG(label,SinewaveGetter,&fi,1000);
ImPlot::EndPlot(); ImPlot::EndPlot();
} }
} }
@@ -1309,7 +1302,6 @@ void Demo_SubplotItemSharing() {
static int id[] = {0,1,2,3,4,5}; static int id[] = {0,1,2,3,4,5};
static int curj = -1; static int curj = -1;
if (ImPlot::BeginSubplots("##ItemSharing", rows, cols, ImVec2(-1,400), flags)) { if (ImPlot::BeginSubplots("##ItemSharing", rows, cols, ImVec2(-1,400), flags)) {
ImPlot::SetupLegend(ImPlotLocation_South, ImPlotLegendFlags_Sort|ImPlotLegendFlags_Horizontal);
for (int i = 0; i < rows*cols; ++i) { for (int i = 0; i < rows*cols; ++i) {
if (ImPlot::BeginPlot("")) { if (ImPlot::BeginPlot("")) {
float fc = 0.01f; float fc = 0.01f;
@@ -1384,9 +1376,6 @@ void Demo_LegendOptions() {
ImGui::SliderFloat2("LegendInnerPadding", (float*)&GetStyle().LegendInnerPadding, 0.0f, 10.0f, "%.0f"); ImGui::SliderFloat2("LegendInnerPadding", (float*)&GetStyle().LegendInnerPadding, 0.0f, 10.0f, "%.0f");
ImGui::SliderFloat2("LegendSpacing", (float*)&GetStyle().LegendSpacing, 0.0f, 5.0f, "%.0f"); ImGui::SliderFloat2("LegendSpacing", (float*)&GetStyle().LegendSpacing, 0.0f, 5.0f, "%.0f");
static int num_dummy_items = 25;
ImGui::SliderInt("Num Dummy Items (Demo Scrolling)", &num_dummy_items, 0, 100);
if (ImPlot::BeginPlot("##Legend",ImVec2(-1,0))) { if (ImPlot::BeginPlot("##Legend",ImVec2(-1,0))) {
ImPlot::SetupLegend(loc, flags); ImPlot::SetupLegend(loc, flags);
static MyImPlot::WaveData data1(0.001, 0.2, 4, 0.2); static MyImPlot::WaveData data1(0.001, 0.2, 4, 0.2);
@@ -1395,17 +1384,12 @@ void Demo_LegendOptions() {
static MyImPlot::WaveData data4(0.001, 0.2, 4, 0.8); static MyImPlot::WaveData data4(0.001, 0.2, 4, 0.8);
static MyImPlot::WaveData data5(0.001, 0.2, 4, 1.0); static MyImPlot::WaveData data5(0.001, 0.2, 4, 1.0);
ImPlot::PlotLineG("Item 002", MyImPlot::SawWave, &data1, 1000); // "Item B" added to legend ImPlot::PlotLineG("Item B", MyImPlot::SawWave, &data1, 1000); // "Item B" added to legend
ImPlot::PlotLineG("Item 001##IDText", MyImPlot::SawWave, &data2, 1000); // "Item A" added to legend, text after ## used for ID only ImPlot::PlotLineG("Item A##IDText", MyImPlot::SawWave, &data2, 1000); // "Item A" added to legend, text after ## used for ID only
ImPlot::PlotLineG("##NotListed", MyImPlot::SawWave, &data3, 1000); // plotted, but not added to legend ImPlot::PlotLineG("##NotListed", MyImPlot::SawWave, &data3, 1000); // plotted, but not added to legend
ImPlot::PlotLineG("Item 003", MyImPlot::SawWave, &data4, 1000); // "Item C" added to legend ImPlot::PlotLineG("Item C", MyImPlot::SawWave, &data4, 1000); // "Item C" added to legend
ImPlot::PlotLineG("Item 003", MyImPlot::SawWave, &data5, 1000); // combined with previous "Item C" ImPlot::PlotLineG("Item C", MyImPlot::SawWave, &data5, 1000); // combined with previous "Item C"
for (int i = 0; i < num_dummy_items; ++i) {
char label[16];
snprintf(label, sizeof(label), "Item %03d", i+4);
ImPlot::PlotDummy(label);
}
ImPlot::EndPlot(); ImPlot::EndPlot();
} }
} }
@@ -1419,18 +1403,15 @@ void Demo_DragPoints() {
ImGui::CheckboxFlags("NoFit", (unsigned int*)&flags, ImPlotDragToolFlags_NoFit); ImGui::SameLine(); ImGui::CheckboxFlags("NoFit", (unsigned int*)&flags, ImPlotDragToolFlags_NoFit); ImGui::SameLine();
ImGui::CheckboxFlags("NoInput", (unsigned int*)&flags, ImPlotDragToolFlags_NoInputs); ImGui::CheckboxFlags("NoInput", (unsigned int*)&flags, ImPlotDragToolFlags_NoInputs);
ImPlotAxisFlags ax_flags = ImPlotAxisFlags_NoTickLabels | ImPlotAxisFlags_NoTickMarks; ImPlotAxisFlags ax_flags = ImPlotAxisFlags_NoTickLabels | ImPlotAxisFlags_NoTickMarks;
bool clicked[4] = {false, false, false, false};
bool hovered[4] = {false, false, false, false};
bool held[4] = {false, false, false, false};
if (ImPlot::BeginPlot("##Bezier",ImVec2(-1,0),ImPlotFlags_CanvasOnly)) { if (ImPlot::BeginPlot("##Bezier",ImVec2(-1,0),ImPlotFlags_CanvasOnly)) {
ImPlot::SetupAxes(nullptr,nullptr,ax_flags,ax_flags); ImPlot::SetupAxes(nullptr,nullptr,ax_flags,ax_flags);
ImPlot::SetupAxesLimits(0,1,0,1); ImPlot::SetupAxesLimits(0,1,0,1);
static ImPlotPoint P[] = {ImPlotPoint(.05f,.05f), ImPlotPoint(0.2,0.4), ImPlotPoint(0.8,0.6), ImPlotPoint(.95f,.95f)}; static ImPlotPoint P[] = {ImPlotPoint(.05f,.05f), ImPlotPoint(0.2,0.4), ImPlotPoint(0.8,0.6), ImPlotPoint(.95f,.95f)};
ImPlot::DragPoint(0,&P[0].x,&P[0].y, ImVec4(0,0.9f,0,1),4,flags, &clicked[0], &hovered[0], &held[0]); ImPlot::DragPoint(0,&P[0].x,&P[0].y, ImVec4(0,0.9f,0,1),4,flags);
ImPlot::DragPoint(1,&P[1].x,&P[1].y, ImVec4(1,0.5f,1,1),4,flags, &clicked[1], &hovered[1], &held[1]); ImPlot::DragPoint(1,&P[1].x,&P[1].y, ImVec4(1,0.5f,1,1),4,flags);
ImPlot::DragPoint(2,&P[2].x,&P[2].y, ImVec4(0,0.5f,1,1),4,flags, &clicked[2], &hovered[2], &held[2]); ImPlot::DragPoint(2,&P[2].x,&P[2].y, ImVec4(0,0.5f,1,1),4,flags);
ImPlot::DragPoint(3,&P[3].x,&P[3].y, ImVec4(0,0.9f,0,1),4,flags, &clicked[3], &hovered[3], &held[3]); ImPlot::DragPoint(3,&P[3].x,&P[3].y, ImVec4(0,0.9f,0,1),4,flags);
static ImPlotPoint B[100]; static ImPlotPoint B[100];
for (int i = 0; i < 100; ++i) { for (int i = 0; i < 100; ++i) {
@@ -1443,12 +1424,14 @@ void Demo_DragPoints() {
B[i] = ImPlotPoint(w1*P[0].x + w2*P[1].x + w3*P[2].x + w4*P[3].x, w1*P[0].y + w2*P[1].y + w3*P[2].y + w4*P[3].y); B[i] = ImPlotPoint(w1*P[0].x + w2*P[1].x + w3*P[2].x + w4*P[3].x, w1*P[0].y + w2*P[1].y + w3*P[2].y + w4*P[3].y);
} }
ImPlot::SetNextLineStyle(ImVec4(1,0.5f,1,1),hovered[1]||held[1] ? 2.0f : 1.0f);
ImPlot::SetNextLineStyle(ImVec4(1,0.5f,1,1));
ImPlot::PlotLine("##h1",&P[0].x, &P[0].y, 2, 0, 0, sizeof(ImPlotPoint)); ImPlot::PlotLine("##h1",&P[0].x, &P[0].y, 2, 0, 0, sizeof(ImPlotPoint));
ImPlot::SetNextLineStyle(ImVec4(0,0.5f,1,1), hovered[2]||held[2] ? 2.0f : 1.0f); ImPlot::SetNextLineStyle(ImVec4(0,0.5f,1,1));
ImPlot::PlotLine("##h2",&P[2].x, &P[2].y, 2, 0, 0, sizeof(ImPlotPoint)); ImPlot::PlotLine("##h2",&P[2].x, &P[2].y, 2, 0, 0, sizeof(ImPlotPoint));
ImPlot::SetNextLineStyle(ImVec4(0,0.9f,0,1), hovered[0]||held[0]||hovered[3]||held[3] ? 3.0f : 2.0f); ImPlot::SetNextLineStyle(ImVec4(0,0.9f,0,1), 2);
ImPlot::PlotLine("##bez",&B[0].x, &B[0].y, 100, 0, 0, sizeof(ImPlotPoint)); ImPlot::PlotLine("##bez",&B[0].x, &B[0].y, 100, 0, 0, sizeof(ImPlotPoint));
ImPlot::EndPlot(); ImPlot::EndPlot();
} }
} }
@@ -1462,9 +1445,6 @@ void Demo_DragLines() {
static double y1 = 0.25; static double y1 = 0.25;
static double y2 = 0.75; static double y2 = 0.75;
static double f = 0.1; static double f = 0.1;
bool clicked = false;
bool hovered = false;
bool held = false;
static ImPlotDragToolFlags flags = ImPlotDragToolFlags_None; static ImPlotDragToolFlags flags = ImPlotDragToolFlags_None;
ImGui::CheckboxFlags("NoCursors", (unsigned int*)&flags, ImPlotDragToolFlags_NoCursors); ImGui::SameLine(); ImGui::CheckboxFlags("NoCursors", (unsigned int*)&flags, ImPlotDragToolFlags_NoCursors); ImGui::SameLine();
ImGui::CheckboxFlags("NoFit", (unsigned int*)&flags, ImPlotDragToolFlags_NoFit); ImGui::SameLine(); ImGui::CheckboxFlags("NoFit", (unsigned int*)&flags, ImPlotDragToolFlags_NoFit); ImGui::SameLine();
@@ -1480,9 +1460,8 @@ void Demo_DragLines() {
xs[i] = (x2+x1)/2+fabs(x2-x1)*(i/1000.0f - 0.5f); xs[i] = (x2+x1)/2+fabs(x2-x1)*(i/1000.0f - 0.5f);
ys[i] = (y1+y2)/2+fabs(y2-y1)/2*sin(f*i/10); ys[i] = (y1+y2)/2+fabs(y2-y1)/2*sin(f*i/10);
} }
ImPlot::DragLineY(120482,&f,ImVec4(1,0.5f,1,1),1,flags, &clicked, &hovered, &held);
ImPlot::SetNextLineStyle(IMPLOT_AUTO_COL, hovered||held ? 2.0f : 1.0f);
ImPlot::PlotLine("Interactive Data", xs, ys, 1000); ImPlot::PlotLine("Interactive Data", xs, ys, 1000);
ImPlot::DragLineY(120482,&f,ImVec4(1,0.5f,1,1),1,flags);
ImPlot::EndPlot(); ImPlot::EndPlot();
} }
} }
@@ -1497,9 +1476,6 @@ void Demo_DragRects() {
static float y_data3[512]; static float y_data3[512];
static float sampling_freq = 44100; static float sampling_freq = 44100;
static float freq = 500; static float freq = 500;
bool clicked = false;
bool hovered = false;
bool held = false;
for (size_t i = 0; i < 512; ++i) { for (size_t i = 0; i < 512; ++i) {
const float t = i / sampling_freq; const float t = i / sampling_freq;
x_data[i] = t; x_data[i] = t;
@@ -1509,7 +1485,6 @@ void Demo_DragRects() {
y_data3[i] = y_data2[i] * -0.6f + sinf(3 * arg) * 0.4f; y_data3[i] = y_data2[i] * -0.6f + sinf(3 * arg) * 0.4f;
} }
ImGui::BulletText("Click and drag the edges, corners, and center of the rect."); ImGui::BulletText("Click and drag the edges, corners, and center of the rect.");
ImGui::BulletText("Double click edges to expand rect to plot extents.");
static ImPlotRect rect(0.0025,0.0045,0,0.5); static ImPlotRect rect(0.0025,0.0045,0,0.5);
static ImPlotDragToolFlags flags = ImPlotDragToolFlags_None; static ImPlotDragToolFlags flags = ImPlotDragToolFlags_None;
ImGui::CheckboxFlags("NoCursors", (unsigned int*)&flags, ImPlotDragToolFlags_NoCursors); ImGui::SameLine(); ImGui::CheckboxFlags("NoCursors", (unsigned int*)&flags, ImPlotDragToolFlags_NoCursors); ImGui::SameLine();
@@ -1522,11 +1497,9 @@ void Demo_DragRects() {
ImPlot::PlotLine("Signal 1", x_data, y_data1, 512); ImPlot::PlotLine("Signal 1", x_data, y_data1, 512);
ImPlot::PlotLine("Signal 2", x_data, y_data2, 512); ImPlot::PlotLine("Signal 2", x_data, y_data2, 512);
ImPlot::PlotLine("Signal 3", x_data, y_data3, 512); ImPlot::PlotLine("Signal 3", x_data, y_data3, 512);
ImPlot::DragRect(0,&rect.X.Min,&rect.Y.Min,&rect.X.Max,&rect.Y.Max,ImVec4(1,0,1,1),flags, &clicked, &hovered, &held); ImPlot::DragRect(0,&rect.X.Min,&rect.Y.Min,&rect.X.Max,&rect.Y.Max,ImVec4(1,0,1,1),flags);
ImPlot::EndPlot(); ImPlot::EndPlot();
} }
ImVec4 bg_col = held ? ImVec4(0.5f,0,0.5f,1) : (hovered ? ImVec4(0.25f,0,0.25f,1) : ImPlot::GetStyle().Colors[ImPlotCol_PlotBg]);
ImPlot::PushStyleColor(ImPlotCol_PlotBg, bg_col);
if (ImPlot::BeginPlot("##rect",ImVec2(-1,150), ImPlotFlags_CanvasOnly)) { if (ImPlot::BeginPlot("##rect",ImVec2(-1,150), ImPlotFlags_CanvasOnly)) {
ImPlot::SetupAxes(nullptr,nullptr,ImPlotAxisFlags_NoDecorations,ImPlotAxisFlags_NoDecorations); ImPlot::SetupAxes(nullptr,nullptr,ImPlotAxisFlags_NoDecorations,ImPlotAxisFlags_NoDecorations);
ImPlot::SetupAxesLimits(rect.X.Min, rect.X.Max, rect.Y.Min, rect.Y.Max, ImGuiCond_Always); ImPlot::SetupAxesLimits(rect.X.Min, rect.X.Max, rect.Y.Min, rect.Y.Max, ImGuiCond_Always);
@@ -1535,8 +1508,6 @@ void Demo_DragRects() {
ImPlot::PlotLine("Signal 3", x_data, y_data3, 512); ImPlot::PlotLine("Signal 3", x_data, y_data3, 512);
ImPlot::EndPlot(); ImPlot::EndPlot();
} }
ImPlot::PopStyleColor();
ImGui::Text("Rect is %sclicked, %shovered, %sheld", clicked ? "" : "not ", hovered ? "" : "not ", held ? "" : "not ");
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -2328,7 +2299,7 @@ ImPlotPoint Spiral(int idx, void*) {
void Sparkline(const char* id, const float* values, int count, float min_v, float max_v, int offset, const ImVec4& col, const ImVec2& size) { void Sparkline(const char* id, const float* values, int count, float min_v, float max_v, int offset, const ImVec4& col, const ImVec2& size) {
ImPlot::PushStyleVar(ImPlotStyleVar_PlotPadding, ImVec2(0,0)); ImPlot::PushStyleVar(ImPlotStyleVar_PlotPadding, ImVec2(0,0));
if (ImPlot::BeginPlot(id,size,ImPlotFlags_CanvasOnly)) { if (ImPlot::BeginPlot(id,size,ImPlotFlags_CanvasOnly|ImPlotFlags_NoChild)) {
ImPlot::SetupAxes(nullptr,nullptr,ImPlotAxisFlags_NoDecorations,ImPlotAxisFlags_NoDecorations); ImPlot::SetupAxes(nullptr,nullptr,ImPlotAxisFlags_NoDecorations,ImPlotAxisFlags_NoDecorations);
ImPlot::SetupAxesLimits(0, count - 1, min_v, max_v, ImGuiCond_Always); ImPlot::SetupAxesLimits(0, count - 1, min_v, max_v, ImGuiCond_Always);
ImPlot::SetNextLineStyle(col); ImPlot::SetNextLineStyle(col);

View File

@@ -1,6 +1,6 @@
// MIT License // MIT License
// Copyright (c) 2023 Evan Pezent // Copyright (c) 2020 Evan Pezent
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
@@ -20,7 +20,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE. // SOFTWARE.
// ImPlot v0.17 // ImPlot v0.14
#define IMGUI_DEFINE_MATH_OPERATORS #define IMGUI_DEFINE_MATH_OPERATORS
#include "implot.h" #include "implot.h"
@@ -98,11 +98,11 @@ static IMPLOT_INLINE float ImInvSqrt(float x) { return 1.0f / sqrtf(x); }
#define _CAT(x, y) _CAT_(x, y) #define _CAT(x, y) _CAT_(x, y)
#define _CAT_(x,y) x ## y #define _CAT_(x,y) x ## y
#define _INSTANTIATE_FOR_NUMERIC_TYPES(chain) _CAT(_INSTANTIATE_FOR_NUMERIC_TYPES_1 chain, _END) #define _INSTANTIATE_FOR_NUMERIC_TYPES(chain) _CAT(_INSTANTIATE_FOR_NUMERIC_TYPES_1 chain, _END)
#define _INSTANTIATE_FOR_NUMERIC_TYPES_1(T) INSTANTIATE_MACRO(T) _INSTANTIATE_FOR_NUMERIC_TYPES_2 #define _INSTANTIATE_FOR_NUMERIC_TYPES_1(T) INSTANTIATE_MACRO(T); _INSTANTIATE_FOR_NUMERIC_TYPES_2
#define _INSTANTIATE_FOR_NUMERIC_TYPES_2(T) INSTANTIATE_MACRO(T) _INSTANTIATE_FOR_NUMERIC_TYPES_1 #define _INSTANTIATE_FOR_NUMERIC_TYPES_2(T) INSTANTIATE_MACRO(T); _INSTANTIATE_FOR_NUMERIC_TYPES_1
#define _INSTANTIATE_FOR_NUMERIC_TYPES_1_END #define _INSTANTIATE_FOR_NUMERIC_TYPES_1_END
#define _INSTANTIATE_FOR_NUMERIC_TYPES_2_END #define _INSTANTIATE_FOR_NUMERIC_TYPES_2_END
#define CALL_INSTANTIATE_FOR_NUMERIC_TYPES() _INSTANTIATE_FOR_NUMERIC_TYPES(IMPLOT_NUMERIC_TYPES) #define CALL_INSTANTIATE_FOR_NUMERIC_TYPES() _INSTANTIATE_FOR_NUMERIC_TYPES(IMPLOT_NUMERIC_TYPES);
namespace ImPlot { namespace ImPlot {
@@ -1287,7 +1287,7 @@ struct RendererShaded : RendererBase {
return false; return false;
} }
const int intersect = (P11.y > P12.y && P22.y > P21.y) || (P12.y > P11.y && P21.y > P22.y); const int intersect = (P11.y > P12.y && P22.y > P21.y) || (P12.y > P11.y && P21.y > P22.y);
const ImVec2 intersection = intersect == 0 ? ImVec2(0,0) : Intersection(P11,P21,P12,P22); ImVec2 intersection = Intersection(P11,P21,P12,P22);
draw_list._VtxWritePtr[0].pos = P11; draw_list._VtxWritePtr[0].pos = P11;
draw_list._VtxWritePtr[0].uv = UV; draw_list._VtxWritePtr[0].uv = UV;
draw_list._VtxWritePtr[0].col = Col; draw_list._VtxWritePtr[0].col = Col;
@@ -1569,10 +1569,6 @@ void RenderMarkers(const _Getter& getter, ImPlotMarker marker, float size, bool
template <typename _Getter> template <typename _Getter>
void PlotLineEx(const char* label_id, const _Getter& getter, ImPlotLineFlags flags) { void PlotLineEx(const char* label_id, const _Getter& getter, ImPlotLineFlags flags) {
if (BeginItemEx(label_id, Fitter1<_Getter>(getter), flags, ImPlotCol_Line)) { if (BeginItemEx(label_id, Fitter1<_Getter>(getter), flags, ImPlotCol_Line)) {
if (getter.Count <= 0) {
EndItem();
return;
}
const ImPlotNextItemData& s = GetItemData(); const ImPlotNextItemData& s = GetItemData();
if (getter.Count > 1) { if (getter.Count > 1) {
if (ImHasFlag(flags, ImPlotLineFlags_Shaded) && s.RenderFill) { if (ImHasFlag(flags, ImPlotLineFlags_Shaded) && s.RenderFill) {
@@ -1644,10 +1640,6 @@ void PlotLineG(const char* label_id, ImPlotGetter getter_func, void* data, int c
template <typename Getter> template <typename Getter>
void PlotScatterEx(const char* label_id, const Getter& getter, ImPlotScatterFlags flags) { void PlotScatterEx(const char* label_id, const Getter& getter, ImPlotScatterFlags flags) {
if (BeginItemEx(label_id, Fitter1<Getter>(getter), flags, ImPlotCol_MarkerOutline)) { if (BeginItemEx(label_id, Fitter1<Getter>(getter), flags, ImPlotCol_MarkerOutline)) {
if (getter.Count <= 0) {
EndItem();
return;
}
const ImPlotNextItemData& s = GetItemData(); const ImPlotNextItemData& s = GetItemData();
ImPlotMarker marker = s.Marker == ImPlotMarker_None ? ImPlotMarker_Circle: s.Marker; ImPlotMarker marker = s.Marker == ImPlotMarker_None ? ImPlotMarker_Circle: s.Marker;
if (marker != ImPlotMarker_None) { if (marker != ImPlotMarker_None) {
@@ -1694,12 +1686,8 @@ void PlotScatterG(const char* label_id, ImPlotGetter getter_func, void* data, in
template <typename Getter> template <typename Getter>
void PlotStairsEx(const char* label_id, const Getter& getter, ImPlotStairsFlags flags) { void PlotStairsEx(const char* label_id, const Getter& getter, ImPlotStairsFlags flags) {
if (BeginItemEx(label_id, Fitter1<Getter>(getter), flags, ImPlotCol_Line)) { if (BeginItemEx(label_id, Fitter1<Getter>(getter), flags, ImPlotCol_Line)) {
if (getter.Count <= 0) {
EndItem();
return;
}
const ImPlotNextItemData& s = GetItemData(); const ImPlotNextItemData& s = GetItemData();
if (getter.Count > 1) { if (getter.Count > 1 ) {
if (s.RenderFill && ImHasFlag(flags,ImPlotStairsFlags_Shaded)) { if (s.RenderFill && ImHasFlag(flags,ImPlotStairsFlags_Shaded)) {
const ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_Fill]); const ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_Fill]);
if (ImHasFlag(flags, ImPlotStairsFlags_PreStep)) if (ImHasFlag(flags, ImPlotStairsFlags_PreStep))
@@ -1758,10 +1746,6 @@ void PlotStairsG(const char* label_id, ImPlotGetter getter_func, void* data, int
template <typename Getter1, typename Getter2> template <typename Getter1, typename Getter2>
void PlotShadedEx(const char* label_id, const Getter1& getter1, const Getter2& getter2, ImPlotShadedFlags flags) { void PlotShadedEx(const char* label_id, const Getter1& getter1, const Getter2& getter2, ImPlotShadedFlags flags) {
if (BeginItemEx(label_id, Fitter2<Getter1,Getter2>(getter1,getter2), flags, ImPlotCol_Fill)) { if (BeginItemEx(label_id, Fitter2<Getter1,Getter2>(getter1,getter2), flags, ImPlotCol_Fill)) {
if (getter1.Count <= 0 || getter2.Count <= 0) {
EndItem();
return;
}
const ImPlotNextItemData& s = GetItemData(); const ImPlotNextItemData& s = GetItemData();
if (s.RenderFill) { if (s.RenderFill) {
const ImU32 col = ImGui::GetColorU32(s.Colors[ImPlotCol_Fill]); const ImU32 col = ImGui::GetColorU32(s.Colors[ImPlotCol_Fill]);
@@ -1822,10 +1806,6 @@ void PlotShadedG(const char* label_id, ImPlotGetter getter_func1, void* data1, I
template <typename Getter1, typename Getter2> template <typename Getter1, typename Getter2>
void PlotBarsVEx(const char* label_id, const Getter1& getter1, const Getter2 getter2, double width, ImPlotBarsFlags flags) { void PlotBarsVEx(const char* label_id, const Getter1& getter1, const Getter2 getter2, double width, ImPlotBarsFlags flags) {
if (BeginItemEx(label_id, FitterBarV<Getter1,Getter2>(getter1,getter2,width), flags, ImPlotCol_Fill)) { if (BeginItemEx(label_id, FitterBarV<Getter1,Getter2>(getter1,getter2,width), flags, ImPlotCol_Fill)) {
if (getter1.Count <= 0 || getter2.Count <= 0) {
EndItem();
return;
}
const ImPlotNextItemData& s = GetItemData(); const ImPlotNextItemData& s = GetItemData();
const ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_Fill]); const ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_Fill]);
const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]); const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]);
@@ -1846,10 +1826,6 @@ void PlotBarsVEx(const char* label_id, const Getter1& getter1, const Getter2 get
template <typename Getter1, typename Getter2> template <typename Getter1, typename Getter2>
void PlotBarsHEx(const char* label_id, const Getter1& getter1, const Getter2& getter2, double height, ImPlotBarsFlags flags) { void PlotBarsHEx(const char* label_id, const Getter1& getter1, const Getter2& getter2, double height, ImPlotBarsFlags flags) {
if (BeginItemEx(label_id, FitterBarH<Getter1,Getter2>(getter1,getter2,height), flags, ImPlotCol_Fill)) { if (BeginItemEx(label_id, FitterBarH<Getter1,Getter2>(getter1,getter2,height), flags, ImPlotCol_Fill)) {
if (getter1.Count <= 0 || getter2.Count <= 0) {
EndItem();
return;
}
const ImPlotNextItemData& s = GetItemData(); const ImPlotNextItemData& s = GetItemData();
const ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_Fill]); const ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_Fill]);
const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]); const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]);
@@ -2006,10 +1982,6 @@ CALL_INSTANTIATE_FOR_NUMERIC_TYPES()
template <typename _GetterPos, typename _GetterNeg> template <typename _GetterPos, typename _GetterNeg>
void PlotErrorBarsVEx(const char* label_id, const _GetterPos& getter_pos, const _GetterNeg& getter_neg, ImPlotErrorBarsFlags flags) { void PlotErrorBarsVEx(const char* label_id, const _GetterPos& getter_pos, const _GetterNeg& getter_neg, ImPlotErrorBarsFlags flags) {
if (BeginItemEx(label_id, Fitter2<_GetterPos,_GetterNeg>(getter_pos, getter_neg), flags, IMPLOT_AUTO)) { if (BeginItemEx(label_id, Fitter2<_GetterPos,_GetterNeg>(getter_pos, getter_neg), flags, IMPLOT_AUTO)) {
if (getter_pos.Count <= 0 || getter_neg.Count <= 0) {
EndItem();
return;
}
const ImPlotNextItemData& s = GetItemData(); const ImPlotNextItemData& s = GetItemData();
ImDrawList& draw_list = *GetPlotDrawList(); ImDrawList& draw_list = *GetPlotDrawList();
const ImU32 col = ImGui::GetColorU32(s.Colors[ImPlotCol_ErrorBar]); const ImU32 col = ImGui::GetColorU32(s.Colors[ImPlotCol_ErrorBar]);
@@ -2031,10 +2003,6 @@ void PlotErrorBarsVEx(const char* label_id, const _GetterPos& getter_pos, const
template <typename _GetterPos, typename _GetterNeg> template <typename _GetterPos, typename _GetterNeg>
void PlotErrorBarsHEx(const char* label_id, const _GetterPos& getter_pos, const _GetterNeg& getter_neg, ImPlotErrorBarsFlags flags) { void PlotErrorBarsHEx(const char* label_id, const _GetterPos& getter_pos, const _GetterNeg& getter_neg, ImPlotErrorBarsFlags flags) {
if (BeginItemEx(label_id, Fitter2<_GetterPos,_GetterNeg>(getter_pos, getter_neg), flags, IMPLOT_AUTO)) { if (BeginItemEx(label_id, Fitter2<_GetterPos,_GetterNeg>(getter_pos, getter_neg), flags, IMPLOT_AUTO)) {
if (getter_pos.Count <= 0 || getter_neg.Count <= 0) {
EndItem();
return;
}
const ImPlotNextItemData& s = GetItemData(); const ImPlotNextItemData& s = GetItemData();
ImDrawList& draw_list = *GetPlotDrawList(); ImDrawList& draw_list = *GetPlotDrawList();
const ImU32 col = ImGui::GetColorU32(s.Colors[ImPlotCol_ErrorBar]); const ImU32 col = ImGui::GetColorU32(s.Colors[ImPlotCol_ErrorBar]);
@@ -2092,17 +2060,13 @@ CALL_INSTANTIATE_FOR_NUMERIC_TYPES()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <typename _GetterM, typename _GetterB> template <typename _GetterM, typename _GetterB>
void PlotStemsEx(const char* label_id, const _GetterM& getter_mark, const _GetterB& getter_base, ImPlotStemsFlags flags) { void PlotStemsEx(const char* label_id, const _GetterM& get_mark, const _GetterB& get_base, ImPlotStemsFlags flags) {
if (BeginItemEx(label_id, Fitter2<_GetterM,_GetterB>(getter_mark,getter_base), flags, ImPlotCol_Line)) { if (BeginItemEx(label_id, Fitter2<_GetterM,_GetterB>(get_mark,get_base), flags, ImPlotCol_Line)) {
if (getter_mark.Count <= 0 || getter_base.Count <= 0) {
EndItem();
return;
}
const ImPlotNextItemData& s = GetItemData(); const ImPlotNextItemData& s = GetItemData();
// render stems // render stems
if (s.RenderLine) { if (s.RenderLine) {
const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]); const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]);
RenderPrimitives2<RendererLineSegments2>(getter_mark, getter_base, col_line, s.LineWeight); RenderPrimitives2<RendererLineSegments2>(get_mark, get_base, col_line, s.LineWeight);
} }
// render markers // render markers
if (s.Marker != ImPlotMarker_None) { if (s.Marker != ImPlotMarker_None) {
@@ -2110,7 +2074,7 @@ void PlotStemsEx(const char* label_id, const _GetterM& getter_mark, const _Gette
PushPlotClipRect(s.MarkerSize); PushPlotClipRect(s.MarkerSize);
const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_MarkerOutline]); const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_MarkerOutline]);
const ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_MarkerFill]); const ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_MarkerFill]);
RenderMarkers<_GetterM>(getter_mark, s.Marker, s.MarkerSize, s.RenderMarkerFill, col_fill, s.RenderMarkerLine, col_line, s.MarkerWeight); RenderMarkers<_GetterM>(get_mark, s.Marker, s.MarkerSize, s.RenderMarkerFill, col_fill, s.RenderMarkerLine, col_line, s.MarkerWeight);
} }
EndItem(); EndItem();
} }
@@ -2159,17 +2123,13 @@ template <typename T>
void PlotInfLines(const char* label_id, const T* values, int count, ImPlotInfLinesFlags flags, int offset, int stride) { void PlotInfLines(const char* label_id, const T* values, int count, ImPlotInfLinesFlags flags, int offset, int stride) {
const ImPlotRect lims = GetPlotLimits(IMPLOT_AUTO,IMPLOT_AUTO); const ImPlotRect lims = GetPlotLimits(IMPLOT_AUTO,IMPLOT_AUTO);
if (ImHasFlag(flags, ImPlotInfLinesFlags_Horizontal)) { if (ImHasFlag(flags, ImPlotInfLinesFlags_Horizontal)) {
GetterXY<IndexerConst,IndexerIdx<T>> getter_min(IndexerConst(lims.X.Min),IndexerIdx<T>(values,count,offset,stride),count); GetterXY<IndexerConst,IndexerIdx<T>> get_min(IndexerConst(lims.X.Min),IndexerIdx<T>(values,count,offset,stride),count);
GetterXY<IndexerConst,IndexerIdx<T>> getter_max(IndexerConst(lims.X.Max),IndexerIdx<T>(values,count,offset,stride),count); GetterXY<IndexerConst,IndexerIdx<T>> get_max(IndexerConst(lims.X.Max),IndexerIdx<T>(values,count,offset,stride),count);
if (BeginItemEx(label_id, FitterY<GetterXY<IndexerConst,IndexerIdx<T>>>(getter_min), flags, ImPlotCol_Line)) { if (BeginItemEx(label_id, FitterY<GetterXY<IndexerConst,IndexerIdx<T>>>(get_min), flags, ImPlotCol_Line)) {
if (count <= 0) {
EndItem();
return;
}
const ImPlotNextItemData& s = GetItemData(); const ImPlotNextItemData& s = GetItemData();
const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]); const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]);
if (s.RenderLine) if (s.RenderLine)
RenderPrimitives2<RendererLineSegments2>(getter_min, getter_max, col_line, s.LineWeight); RenderPrimitives2<RendererLineSegments2>(get_min, get_max, col_line, s.LineWeight);
EndItem(); EndItem();
} }
} }
@@ -2177,10 +2137,6 @@ void PlotInfLines(const char* label_id, const T* values, int count, ImPlotInfLin
GetterXY<IndexerIdx<T>,IndexerConst> get_min(IndexerIdx<T>(values,count,offset,stride),IndexerConst(lims.Y.Min),count); GetterXY<IndexerIdx<T>,IndexerConst> get_min(IndexerIdx<T>(values,count,offset,stride),IndexerConst(lims.Y.Min),count);
GetterXY<IndexerIdx<T>,IndexerConst> get_max(IndexerIdx<T>(values,count,offset,stride),IndexerConst(lims.Y.Max),count); GetterXY<IndexerIdx<T>,IndexerConst> get_max(IndexerIdx<T>(values,count,offset,stride),IndexerConst(lims.Y.Max),count);
if (BeginItemEx(label_id, FitterX<GetterXY<IndexerIdx<T>,IndexerConst>>(get_min), flags, ImPlotCol_Line)) { if (BeginItemEx(label_id, FitterX<GetterXY<IndexerIdx<T>,IndexerConst>>(get_min), flags, ImPlotCol_Line)) {
if (count <= 0) {
EndItem();
return;
}
const ImPlotNextItemData& s = GetItemData(); const ImPlotNextItemData& s = GetItemData();
const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]); const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]);
if (s.RenderLine) if (s.RenderLine)
@@ -2216,121 +2172,57 @@ IMPLOT_INLINE void RenderPieSlice(ImDrawList& draw_list, const ImPlotPoint& cent
} }
template <typename T> template <typename T>
double PieChartSum(const T* values, int count, bool ignore_hidden) { void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, const char* fmt, double angle0, ImPlotPieChartFlags flags) {
IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != nullptr, "PlotPieChart() needs to be called between BeginPlot() and EndPlot()!");
ImDrawList & draw_list = *GetPlotDrawList();
double sum = 0; double sum = 0;
if (ignore_hidden) { for (int i = 0; i < count; ++i)
ImPlotContext& gp = *GImPlot; sum += (double)values[i];
ImPlotItemGroup& Items = *gp.CurrentItems; const bool normalize = ImHasFlag(flags,ImPlotPieChartFlags_Normalize) || sum > 1.0;
for (int i = 0; i < count; ++i) { ImPlotPoint center(x,y);
if (i >= Items.GetItemCount()) PushPlotClipRect();
break;
ImPlotItem* item = Items.GetItemByIndex(i);
IM_ASSERT(item != nullptr);
if (item->Show) {
sum += (double)values[i];
}
}
}
else {
for (int i = 0; i < count; ++i) {
sum += (double)values[i];
}
}
return sum;
}
template <typename T>
void PlotPieChartEx(const char* const label_ids[], const T* values, int count, ImPlotPoint center, double radius, double angle0, ImPlotPieChartFlags flags) {
ImDrawList& draw_list = *GetPlotDrawList();
const bool ignore_hidden = ImHasFlag(flags, ImPlotPieChartFlags_IgnoreHidden);
const double sum = PieChartSum(values, count, ignore_hidden);
const bool normalize = ImHasFlag(flags, ImPlotPieChartFlags_Normalize) || sum > 1.0;
double a0 = angle0 * 2 * IM_PI / 360.0; double a0 = angle0 * 2 * IM_PI / 360.0;
double a1 = angle0 * 2 * IM_PI / 360.0; double a1 = angle0 * 2 * IM_PI / 360.0;
ImPlotPoint Pmin = ImPlotPoint(center.x - radius, center.y - radius); ImPlotPoint Pmin = ImPlotPoint(x-radius,y-radius);
ImPlotPoint Pmax = ImPlotPoint(center.x + radius, center.y + radius); ImPlotPoint Pmax = ImPlotPoint(x+radius,y+radius);
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
ImPlotItem* item = GetItem(label_ids[i]); double percent = normalize ? (double)values[i] / sum : (double)values[i];
a1 = a0 + 2 * IM_PI * percent;
const double percent = normalize ? (double)values[i] / sum : (double)values[i]; if (BeginItemEx(label_ids[i], FitterRect(Pmin,Pmax))) {
const bool skip = sum <= 0.0 || (ignore_hidden && item != nullptr && !item->Show); ImU32 col = GetCurrentItem()->Color;
if (!skip) if (percent < 0.5) {
a1 = a0 + 2 * IM_PI * percent; RenderPieSlice(draw_list, center, radius, a0, a1, col);
}
if (BeginItemEx(label_ids[i], FitterRect(Pmin, Pmax))) { else {
if (sum > 0.0) { RenderPieSlice(draw_list, center, radius, a0, a0 + (a1 - a0) * 0.5, col);
ImU32 col = GetCurrentItem()->Color; RenderPieSlice(draw_list, center, radius, a0 + (a1 - a0) * 0.5, a1, col);
if (percent < 0.5) {
RenderPieSlice(draw_list, center, radius, a0, a1, col);
}
else {
RenderPieSlice(draw_list, center, radius, a0, a0 + (a1 - a0) * 0.5, col);
RenderPieSlice(draw_list, center, radius, a0 + (a1 - a0) * 0.5, a1, col);
}
} }
EndItem(); EndItem();
} }
if (!skip) a0 = a1;
a0 = a1;
} }
}
int PieChartFormatter(double value, char* buff, int size, void* data) {
const char* fmt = (const char*)data;
return snprintf(buff, size, fmt, value);
};
template <typename T>
void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, const char* fmt, double angle0, ImPlotPieChartFlags flags) {
PlotPieChart<T>(label_ids, values, count, x, y, radius, PieChartFormatter, (void*)fmt, angle0, flags);
}
#define INSTANTIATE_MACRO(T) template IMPLOT_API void PlotPieChart<T>(const char* const label_ids[], const T* values, int count, double x, double y, double radius, const char* fmt, double angle0, ImPlotPieChartFlags flags);
CALL_INSTANTIATE_FOR_NUMERIC_TYPES()
#undef INSTANTIATE_MACRO
template <typename T>
void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, ImPlotFormatter fmt, void* fmt_data, double angle0, ImPlotPieChartFlags flags) {
IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != nullptr, "PlotPieChart() needs to be called between BeginPlot() and EndPlot()!");
ImDrawList& draw_list = *GetPlotDrawList();
const bool ignore_hidden = ImHasFlag(flags, ImPlotPieChartFlags_IgnoreHidden);
const double sum = PieChartSum(values, count, ignore_hidden);
const bool normalize = ImHasFlag(flags, ImPlotPieChartFlags_Normalize) || sum > 1.0;
ImPlotPoint center(x, y);
PushPlotClipRect();
PlotPieChartEx(label_ids, values, count, center, radius, angle0, flags);
if (fmt != nullptr) { if (fmt != nullptr) {
double a0 = angle0 * 2 * IM_PI / 360.0; a0 = angle0 * 2 * IM_PI / 360.0;
double a1 = angle0 * 2 * IM_PI / 360.0; a1 = angle0 * 2 * IM_PI / 360.0;
char buffer[32]; char buffer[32];
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
ImPlotItem* item = GetItem(label_ids[i]); ImPlotItem* item = GetItem(label_ids[i]);
IM_ASSERT(item != nullptr); double percent = normalize ? (double)values[i] / sum : (double)values[i];
a1 = a0 + 2 * IM_PI * percent;
const double percent = normalize ? (double)values[i] / sum : (double)values[i]; if (item->Show) {
const bool skip = ignore_hidden && item != nullptr && !item->Show; ImFormatString(buffer, 32, fmt, (double)values[i]);
ImVec2 size = ImGui::CalcTextSize(buffer);
if (!skip) { double angle = a0 + (a1 - a0) * 0.5;
a1 = a0 + 2 * IM_PI * percent; ImVec2 pos = PlotToPixels(center.x + 0.5 * radius * cos(angle), center.y + 0.5 * radius * sin(angle),IMPLOT_AUTO,IMPLOT_AUTO);
if (item->Show) { ImU32 col = CalcTextColor(ImGui::ColorConvertU32ToFloat4(item->Color));
fmt((double)values[i], buffer, 32, fmt_data); draw_list.AddText(pos - size * 0.5f, col, buffer);
ImVec2 size = ImGui::CalcTextSize(buffer);
double angle = a0 + (a1 - a0) * 0.5;
ImVec2 pos = PlotToPixels(center.x + 0.5 * radius * cos(angle), center.y + 0.5 * radius * sin(angle), IMPLOT_AUTO, IMPLOT_AUTO);
ImU32 col = CalcTextColor(ImGui::ColorConvertU32ToFloat4(item->Color));
draw_list.AddText(pos - size * 0.5f, col, buffer);
}
a0 = a1;
} }
a0 = a1;
} }
} }
PopPlotClipRect(); PopPlotClipRect();
} }
#define INSTANTIATE_MACRO(T) template IMPLOT_API void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, ImPlotFormatter fmt, void* fmt_data, double angle0, ImPlotPieChartFlags flags); #define INSTANTIATE_MACRO(T) template IMPLOT_API void PlotPieChart<T>(const char* const label_ids[], const T* values, int count, double x, double y, double radius, const char* fmt, double angle0, ImPlotPieChartFlags flags);
CALL_INSTANTIATE_FOR_NUMERIC_TYPES() CALL_INSTANTIATE_FOR_NUMERIC_TYPES()
#undef INSTANTIATE_MACRO #undef INSTANTIATE_MACRO
@@ -2391,8 +2283,8 @@ struct GetterHeatmapColMaj {
{ } { }
template <typename I> IMPLOT_INLINE RectC operator()(I idx) const { template <typename I> IMPLOT_INLINE RectC operator()(I idx) const {
double val = (double)Values[idx]; double val = (double)Values[idx];
const int r = idx % Rows; const int r = idx % Cols;
const int c = idx / Rows; const int c = idx / Cols;
const ImPlotPoint p(XRef + HalfSize.x + c*Width, YRef + YDir * (HalfSize.y + r*Height)); const ImPlotPoint p(XRef + HalfSize.x + c*Width, YRef + YDir * (HalfSize.y + r*Height));
RectC rect; RectC rect;
rect.Pos = p; rect.Pos = p;
@@ -2483,10 +2375,6 @@ void RenderHeatmap(ImDrawList& draw_list, const T* values, int rows, int cols, d
template <typename T> template <typename T>
void PlotHeatmap(const char* label_id, const T* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max, ImPlotHeatmapFlags flags) { void PlotHeatmap(const char* label_id, const T* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max, ImPlotHeatmapFlags flags) {
if (BeginItemEx(label_id, FitterRect(bounds_min, bounds_max))) { if (BeginItemEx(label_id, FitterRect(bounds_min, bounds_max))) {
if (rows <= 0 || cols <= 0) {
EndItem();
return;
}
ImDrawList& draw_list = *GetPlotDrawList(); ImDrawList& draw_list = *GetPlotDrawList();
const bool col_maj = ImHasFlag(flags, ImPlotHeatmapFlags_ColMajor); const bool col_maj = ImHasFlag(flags, ImPlotHeatmapFlags_ColMajor);
RenderHeatmap(draw_list, values, rows, cols, scale_min, scale_max, fmt, bounds_min, bounds_max, true, col_maj); RenderHeatmap(draw_list, values, rows, cols, scale_min, scale_max, fmt, bounds_min, bounds_max, true, col_maj);
@@ -2651,10 +2539,6 @@ double PlotHistogram2D(const char* label_id, const T* xs, const T* ys, int count
} }
if (BeginItemEx(label_id, FitterRect(range))) { if (BeginItemEx(label_id, FitterRect(range))) {
if (y_bins <= 0 || x_bins <= 0) {
EndItem();
return max_count;
}
ImDrawList& draw_list = *GetPlotDrawList(); ImDrawList& draw_list = *GetPlotDrawList();
RenderHeatmap(draw_list, &bin_counts.Data[0], y_bins, x_bins, 0, max_count, nullptr, range.Min(), range.Max(), false, col_maj); RenderHeatmap(draw_list, &bin_counts.Data[0], y_bins, x_bins, 0, max_count, nullptr, range.Min(), range.Max(), false, col_maj);
EndItem(); EndItem();
@@ -2713,8 +2597,8 @@ void PlotDigitalEx(const char* label_id, Getter getter, ImPlotDigitalFlags flags
//do not extend plot outside plot range //do not extend plot outside plot range
if (pMin.x < x_axis.PixelMin) pMin.x = x_axis.PixelMin; if (pMin.x < x_axis.PixelMin) pMin.x = x_axis.PixelMin;
if (pMax.x < x_axis.PixelMin) pMax.x = x_axis.PixelMin; if (pMax.x < x_axis.PixelMin) pMax.x = x_axis.PixelMin;
if (pMin.x > x_axis.PixelMax) pMin.x = x_axis.PixelMax - 1; //fix issue related to https://github.com/ocornut/imgui/issues/3976 if (pMin.x > x_axis.PixelMax) pMin.x = x_axis.PixelMax;
if (pMax.x > x_axis.PixelMax) pMax.x = x_axis.PixelMax - 1; //fix issue related to https://github.com/ocornut/imgui/issues/3976 if (pMax.x > x_axis.PixelMax) pMax.x = x_axis.PixelMax;
//plot a rectangle that extends up to x2 with y1 height //plot a rectangle that extends up to x2 with y1 height
if ((pMax.x > pMin.x) && (gp.CurrentPlot->PlotRect.Contains(pMin) || gp.CurrentPlot->PlotRect.Contains(pMax))) { if ((pMax.x > pMin.x) && (gp.CurrentPlot->PlotRect.Contains(pMin) || gp.CurrentPlot->PlotRect.Contains(pMax))) {
// ImVec4 colAlpha = item->Color; // ImVec4 colAlpha = item->Color;

Some files were not shown because too many files have changed in this diff Show More