mirror of
https://github.com/ocornut/imgui.git
synced 2026-09-29 04:35:49 +03:00
Compare commits
254 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
580c00c316 | ||
|
|
db436a15bc | ||
|
|
09f7a0f062 | ||
|
|
aa0181478b | ||
|
|
5c6a86a9d2 | ||
|
|
e728936797 | ||
|
|
623ba46120 | ||
|
|
cc072ca90e | ||
|
|
a6784c378f | ||
|
|
7bfc192814 | ||
|
|
d12321803d | ||
|
|
58d7570b8b | ||
|
|
6cf8332f93 | ||
|
|
e19fea020f | ||
|
|
d5c68c301a | ||
|
|
420f179341 | ||
|
|
249e5a939d | ||
|
|
565564bb5c | ||
|
|
c0041b7d3c | ||
|
|
c74e7e93a3 | ||
|
|
54f86be71e | ||
|
|
fc98dc4a72 | ||
|
|
a14bebd948 | ||
|
|
f7ada78e32 | ||
|
|
c8fc1829d0 | ||
|
|
f09485d7be | ||
|
|
6d07f6eb09 | ||
|
|
5a0ac1678c | ||
|
|
eabff0fd08 | ||
|
|
25e16fd8b6 | ||
|
|
333f5186e3 | ||
|
|
b5135f270f | ||
|
|
09b7ff9385 | ||
|
|
8d3e37eb53 | ||
|
|
7cb5ded5d2 | ||
|
|
a5b5f2d85a | ||
|
|
8e174685ae | ||
|
|
b00dd14a34 | ||
|
|
c8b9f0d6be | ||
|
|
ea60e7b748 | ||
|
|
e0a2f6dea9 | ||
|
|
e8602501bb | ||
|
|
ea6d21687b | ||
|
|
db5b735a5d | ||
|
|
32c3f6095a | ||
|
|
148d128f6e | ||
|
|
334f484892 | ||
|
|
dd32dace81 | ||
|
|
04b37d6d23 | ||
|
|
9090ba71e5 | ||
|
|
53d421955f | ||
|
|
687f7fb8ac | ||
|
|
4ebb04333b | ||
|
|
4898533613 | ||
|
|
080319c4ce | ||
|
|
96b6eb7728 | ||
|
|
f150bf09f9 | ||
|
|
51c3c0c992 | ||
|
|
5316e70614 | ||
|
|
7edd2b1f12 | ||
|
|
1807b25b9a | ||
|
|
4dbb921b22 | ||
|
|
e2e9533991 | ||
|
|
a15761f11c | ||
|
|
f562ab8e32 | ||
|
|
e0537bf72b | ||
|
|
ebc7307db5 | ||
|
|
fd74775a0d | ||
|
|
19ead810d2 | ||
|
|
7e0de0e411 | ||
|
|
35a13e9948 | ||
|
|
e44b1129bd | ||
|
|
6d1f88fe4a | ||
|
|
760dff3244 | ||
|
|
d3c5ff395c | ||
|
|
1e51b6ffdc | ||
|
|
0af8f475d1 | ||
|
|
1d7b37dc9b | ||
|
|
3e9d0f7e82 | ||
|
|
46d39d56fe | ||
|
|
551a0a6bc0 | ||
|
|
5de45fb1d9 | ||
|
|
49fa47fc19 | ||
|
|
5b6e19bb50 | ||
|
|
70e60a3c4c | ||
|
|
2ddb5fc095 | ||
|
|
98f3efcf07 | ||
|
|
730f099239 | ||
|
|
724c69b182 | ||
|
|
6a6d7bc3ca | ||
|
|
a5a3e1bd04 | ||
|
|
2de0a07cd4 | ||
|
|
7c9f0c148c | ||
|
|
40ec568762 | ||
|
|
5108603789 | ||
|
|
fdc1152281 | ||
|
|
b647af2100 | ||
|
|
ebd752a0ec | ||
|
|
9b7699f325 | ||
|
|
f1cc2ae15e | ||
|
|
448ef2baa9 | ||
|
|
b9adace7b5 | ||
|
|
ed252c55aa | ||
|
|
ffbf21af6b | ||
|
|
e47e6b0d9d | ||
|
|
950d27137e | ||
|
|
8c131021b0 | ||
|
|
ff135cf5e5 | ||
|
|
a9e7a8c880 | ||
|
|
01380c5797 | ||
|
|
e722165561 | ||
|
|
d94d0f3649 | ||
|
|
f31f98f4cd | ||
|
|
f594633b54 | ||
|
|
b335bf4328 | ||
|
|
6f41d13c7a | ||
|
|
548389359c | ||
|
|
295385ff96 | ||
|
|
c9c458c40a | ||
|
|
e4f7c5c722 | ||
|
|
d00a87565b | ||
|
|
7038887c32 | ||
|
|
61a093635c | ||
|
|
26b8292635 | ||
|
|
c958f16059 | ||
|
|
4853f5c96b | ||
|
|
18d63b12be | ||
|
|
2392a52660 | ||
|
|
baeea39c1a | ||
|
|
0ff4a8a900 | ||
|
|
e3927dc004 | ||
|
|
35a7e8e864 | ||
|
|
909082890a | ||
|
|
0302703a7d | ||
|
|
0720d59bb7 | ||
|
|
addbfa5021 | ||
|
|
bad1ee71f8 | ||
|
|
003ee19d9e | ||
|
|
b62bfd6b06 | ||
|
|
da137cbbb0 | ||
|
|
9bb131fb2f | ||
|
|
62399b5bfe | ||
|
|
68fce9f3bd | ||
|
|
f903a7e8e2 | ||
|
|
112d6d9eab | ||
|
|
2c49da44be | ||
|
|
85593d0869 | ||
|
|
d1eb8d031c | ||
|
|
481f2cea17 | ||
|
|
520a29dd51 | ||
|
|
cfdc953ba9 | ||
|
|
f626c1c793 | ||
|
|
5d56c09432 | ||
|
|
0785cdb2bb | ||
|
|
aca69173df | ||
|
|
9f7d8086fe | ||
|
|
0e479b9554 | ||
|
|
776bf2ab0d | ||
|
|
4f1ea369ea | ||
|
|
a977144955 | ||
|
|
e616ace74d | ||
|
|
5c2160ac85 | ||
|
|
5fb77dfde1 | ||
|
|
f7e8343ee9 | ||
|
|
7d43c74b59 | ||
|
|
8fc25800e0 | ||
|
|
6824e2c2e4 | ||
|
|
e9ea19086b | ||
|
|
caddd26fb9 | ||
|
|
fc6395365d | ||
|
|
93dd4c1567 | ||
|
|
279d04f7a3 | ||
|
|
0edad6d097 | ||
|
|
e408733ecc | ||
|
|
9e6c0416fe | ||
|
|
c66d9a8190 | ||
|
|
76f5be2749 | ||
|
|
60fbdbb8d8 | ||
|
|
ac6f9683b5 | ||
|
|
1c1241136a | ||
|
|
0e355af09e | ||
|
|
26432cfdc6 | ||
|
|
be374fa598 | ||
|
|
e74453760b | ||
|
|
ec69495ca8 | ||
|
|
b522576054 | ||
|
|
570c0e03b7 | ||
|
|
b9cf21733d | ||
|
|
7930405c73 | ||
|
|
f2fcdfe97f | ||
|
|
2f94e7dc13 | ||
|
|
b2377d616d | ||
|
|
d15966ff6c | ||
|
|
9a5c070308 | ||
|
|
73a6610e81 | ||
|
|
7aaf10f15b | ||
|
|
13fc81fc82 | ||
|
|
2064059a7f | ||
|
|
b47a3898b4 | ||
|
|
138c0e6c7d | ||
|
|
b46a37eac9 | ||
|
|
e6147a3993 | ||
|
|
721da6a34c | ||
|
|
360183924b | ||
|
|
2aaa6d8173 | ||
|
|
3240201de2 | ||
|
|
94a3dcc5fa | ||
|
|
fea6f4603a | ||
|
|
d43c3f929c | ||
|
|
36ea9728d1 | ||
|
|
2e0f949039 | ||
|
|
924f57181b | ||
|
|
e5ff2d07d7 | ||
|
|
b10137f92f | ||
|
|
aa377352ef | ||
|
|
4312c4399f | ||
|
|
f1dd18b75c | ||
|
|
5220a3f48d | ||
|
|
6acba3b47d | ||
|
|
fc5e2f28fe | ||
|
|
7950c96f0e | ||
|
|
14278db024 | ||
|
|
c4eaac6d48 | ||
|
|
5a42cddcd2 | ||
|
|
995e4a65ff | ||
|
|
a054a016e2 | ||
|
|
045a0907f4 | ||
|
|
5aa0393a15 | ||
|
|
f241419b78 | ||
|
|
3495e329f3 | ||
|
|
3b99fc4883 | ||
|
|
70f02b0558 | ||
|
|
cac16b0d16 | ||
|
|
1d33ea939f | ||
|
|
75f985998b | ||
|
|
12b7977555 | ||
|
|
33bb693b4c | ||
|
|
783eba926f | ||
|
|
ac07da2b5b | ||
|
|
243097ca8f | ||
|
|
fbcf95193f | ||
|
|
24a80f74a4 | ||
|
|
904b663184 | ||
|
|
3e7b79aa17 | ||
|
|
e41d691da1 | ||
|
|
93e396ffb7 | ||
|
|
068e055510 | ||
|
|
db161b84c9 | ||
|
|
4088a4f40c | ||
|
|
46a050fff2 | ||
|
|
c7767926ce | ||
|
|
310c719a1f | ||
|
|
b2546a5c93 | ||
|
|
e0f5f9a14c |
126 changed files with 8415 additions and 1591 deletions
1
.github/ISSUE_TEMPLATE/issue_template.yml
vendored
1
.github/ISSUE_TEMPLATE/issue_template.yml
vendored
|
|
@ -14,6 +14,7 @@ body:
|
|||
attributes:
|
||||
value: |
|
||||
**Prerequisites:**
|
||||
- I am not using a LLM to think or write for me. Please distill information to what's necessary and meaningful.
|
||||
- I have read [Frequently Asked Questions](https://github.com/ocornut/imgui/blob/master/docs/FAQ.md).
|
||||
- I have read [Contributing Guidelines -> General Advices](https://github.com/ocornut/imgui/blob/master/docs/CONTRIBUTING.md#getting-started--general-advice).
|
||||
- I have read [Contributing Guidelines -> How to open an Issue](https://github.com/ocornut/imgui/blob/master/docs/CONTRIBUTING.md#how-to-open-an-issue).
|
||||
|
|
|
|||
6
.github/pull_request_template.md
vendored
6
.github/pull_request_template.md
vendored
|
|
@ -1,10 +1,12 @@
|
|||
(Click "Preview" to turn any http URL into a clickable link)
|
||||
|
||||
1. PLEASE CAREFULLY READ: [Contributing Guidelines](https://github.com/ocornut/imgui/blob/master/docs/CONTRIBUTING.md)
|
||||
1. PLEASE CAREFULLY READ: [Contributing Guidelines](https://github.com/ocornut/imgui/blob/master/docs/CONTRIBUTING.md). By submitting a PR you are agreeing with the [CLA](https://github.com/ocornut/imgui/blob/master/docs/CONTRIBUTING.md#copyright--contributor-license-agreement).
|
||||
|
||||
2. **Make sure you're using a special branch just for this pull request**. (In git, 1 PR = 1 branch. If you update the branch the PR will be updated.)
|
||||
|
||||
3. Consider running the [imgui_test_suite](https://github.com/ocornut/imgui_test_engine) or adding new tests to test for expected behaviors.
|
||||
|
||||
4. Clear this template before submitting your PR.
|
||||
4. PLEASE DO NOT SUBMIT AI-GENERATED PROSE. ONLY SUBMIT CODE THAT YOU REVIEWED AND UNDERSTAND. Submissions that are lacking proper human review/judgement before being passed to us are not welcome.
|
||||
|
||||
5. Clear this template before submitting your PR.
|
||||
|
||||
|
|
|
|||
30
.github/workflows/build.yml
vendored
30
.github/workflows/build.yml
vendored
|
|
@ -25,8 +25,8 @@ jobs:
|
|||
working-directory: ${{ github.workspace }}/imgui
|
||||
|
||||
env:
|
||||
VS_PATH: C:\Program Files\Microsoft Visual Studio\2022\Enterprise\
|
||||
MSBUILD_PATH: C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\
|
||||
VS_PATH: C:\Program Files\Microsoft Visual Studio\18\Enterprise
|
||||
MSBUILD_PATH: C:\Program Files\Microsoft Visual Studio\18\Enterprise\MSBuild\Current\Bin\
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
|
|
@ -116,7 +116,7 @@ jobs:
|
|||
cl.exe /D_USRDLL /D_WINDLL /I. example_single_file.cpp /LD /FeImGui.dll /link
|
||||
cl.exe /DIMGUI_API=__declspec(dllimport) -DIMGUI_IMPL_API= /I. ImGui.lib /Feexample_null.exe examples/example_null/main.cpp
|
||||
|
||||
# Win64 examples are more frequently compilted than the Win32 examples.
|
||||
# Win64 examples are more frequently compiled than the Win32 examples.
|
||||
# More of the Win32 examples requires 'workflow_run' to reduce waste.
|
||||
- name: Build Win32 example_glfw_opengl2
|
||||
shell: cmd
|
||||
|
|
@ -160,6 +160,7 @@ jobs:
|
|||
- name: Build Win32 example_sdl3_opengl3
|
||||
shell: cmd
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl3_opengl3/example_sdl3_opengl3.vcxproj /p:Platform=Win32 /p:Configuration=Release'
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build Win32 example_sdl3_sdlgpu3
|
||||
shell: cmd
|
||||
|
|
@ -200,6 +201,7 @@ jobs:
|
|||
- name: Build Win64 example_glfw_opengl3
|
||||
shell: cmd
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_glfw_opengl3/example_glfw_opengl3.vcxproj /p:Platform=x64 /p:Configuration=Release'
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build Win64 example_glfw_vulkan
|
||||
shell: cmd
|
||||
|
|
@ -228,6 +230,7 @@ jobs:
|
|||
- name: Build Win64 example_sdl2_directx11
|
||||
shell: cmd
|
||||
run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl2_directx11/example_sdl2_directx11.vcxproj /p:Platform=x64 /p:Configuration=Release'
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build Win64 example_sdl3_opengl3
|
||||
shell: cmd
|
||||
|
|
@ -506,7 +509,7 @@ jobs:
|
|||
run: g++ -c -I. -std=c++11 -DIMGUI_IMPL_VULKAN_NO_PROTOTYPES=1 backends/imgui_impl_vulkan.cpp
|
||||
|
||||
Build-MacOS:
|
||||
runs-on: macos-latest
|
||||
runs-on: macos-26
|
||||
name: Build - MacOS
|
||||
|
||||
defaults:
|
||||
|
|
@ -572,6 +575,9 @@ jobs:
|
|||
- name: Build macOS example_sdl2_metal
|
||||
run: make -C examples/example_sdl2_metal
|
||||
|
||||
- name: Build macOS example_sdl3_metal4
|
||||
run: make -C examples/example_sdl3_metal4
|
||||
|
||||
- name: Build macOS example_sdl2_opengl2
|
||||
run: make -C examples/example_sdl2_opengl2
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
|
@ -587,10 +593,18 @@ jobs:
|
|||
run: xcodebuild -project examples/example_apple_metal/example_apple_metal.xcodeproj -target example_apple_metal_macos
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build macOS example_apple_metal4
|
||||
run: xcodebuild -project examples/example_apple_metal4/example_apple_metal4.xcodeproj -target example_apple_metal_macos
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build macOS example_apple_opengl2
|
||||
run: xcodebuild -project examples/example_apple_opengl2/example_apple_opengl2.xcodeproj -target example_osx_opengl2
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
- name: Build macOS example_apple_opengl3
|
||||
run: xcodebuild -project examples/example_apple_opengl3/example_apple_opengl3.xcodeproj -target example_osx_opengl3
|
||||
if: github.event_name == 'workflow_run'
|
||||
|
||||
Build-iOS:
|
||||
runs-on: macos-14
|
||||
name: Build - iOS
|
||||
|
|
@ -651,8 +665,12 @@ jobs:
|
|||
name: Build - Android
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Setup Gradle 9.4.1
|
||||
uses: gradle/actions/setup-gradle@v6
|
||||
with:
|
||||
gradle-version: '9.4.1'
|
||||
|
||||
- uses: actions/checkout@v6
|
||||
- name: Build example_android_opengl3
|
||||
run: |
|
||||
cd examples/example_android_opengl3/android
|
||||
|
|
@ -667,7 +685,7 @@ jobs:
|
|||
working-directory: ${{ github.workspace }}/imgui
|
||||
|
||||
env:
|
||||
MSBUILD_PATH: C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\
|
||||
MSBUILD_PATH: C:\Program Files\Microsoft Visual Studio\18\Enterprise\MSBuild\Current\Bin\
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
|
|
|||
4
.github/workflows/static-analysis.yml
vendored
4
.github/workflows/static-analysis.yml
vendored
|
|
@ -23,9 +23,9 @@ jobs:
|
|||
run: |
|
||||
if [[ "$PVS_STUDIO_LICENSE" != "" ]];
|
||||
then
|
||||
wget -q https://files.viva64.com/etc/pubkey.txt
|
||||
wget -q https://files.pvs-studio.com/etc/pubkey.txt
|
||||
sudo apt-key add pubkey.txt
|
||||
sudo wget -O /etc/apt/sources.list.d/viva64.list https://files.viva64.com/etc/viva64.list
|
||||
sudo wget -O /etc/apt/sources.list.d/viva64.list https://files.pvs-studio.com/etc/viva64.list
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y pvs-studio
|
||||
pvs-studio-analyzer credentials -o pvs-studio.lic $PVS_STUDIO_LICENSE
|
||||
|
|
|
|||
9
.gitignore
vendored
9
.gitignore
vendored
|
|
@ -9,6 +9,8 @@ imgui*.ini
|
|||
|
||||
## General build artifacts
|
||||
*.o
|
||||
*.so*
|
||||
*.a
|
||||
*.obj
|
||||
*.exe
|
||||
examples/*/Debug/*
|
||||
|
|
@ -57,9 +59,15 @@ examples/example_sdl3_wgpu/web/*
|
|||
.idea
|
||||
cmake-build-*
|
||||
|
||||
## QNX artifacts
|
||||
*.pinfo
|
||||
*.dep
|
||||
*.gcno
|
||||
|
||||
## Unix executables from our example Makefiles
|
||||
examples/example_apple_metal/example_apple_metal
|
||||
examples/example_apple_opengl2/example_apple_opengl2
|
||||
examples/example_apple_opengl3/example_apple_opengl3
|
||||
examples/example_glfw_metal/example_glfw_metal
|
||||
examples/example_glfw_opengl2/example_glfw_opengl2
|
||||
examples/example_glfw_opengl3/example_glfw_opengl3
|
||||
|
|
@ -72,6 +80,7 @@ examples/example_sdl2_opengl3/example_sdl2_opengl3
|
|||
examples/example_sdl2_sdlrenderer2/example_sdl2_sdlrenderer2
|
||||
examples/example_sdl2_vulkan/example_sdl2_vulkan
|
||||
examples/example_sdl3_metal/example_sdl3_metal
|
||||
examples/example_sdl3_metal4/example_sdl3_metal4
|
||||
examples/example_sdl3_opengl3/example_sdl3_opengl3
|
||||
examples/example_sdl3_sdlgpu3/example_sdl3_sdlgpu3
|
||||
examples/example_sdl3_sdlrenderer3/example_sdl3_sdlrenderer3
|
||||
|
|
|
|||
|
|
@ -268,8 +268,7 @@ void ImGui_ImplAllegro5_UpdateTexture(ImTextureData* tex)
|
|||
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == nullptr);
|
||||
IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
|
||||
|
||||
// Create texture
|
||||
// (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
|
||||
// Create texture (bilinear sampling is required)
|
||||
const int new_bitmap_flags = al_get_new_bitmap_flags();
|
||||
int new_bitmap_format = al_get_new_bitmap_format();
|
||||
al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP | ALLEGRO_MIN_LINEAR | ALLEGRO_MAG_LINEAR);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// dear imgui: Platform Binding for Android native app
|
||||
// This needs to be used along with the OpenGL 3 Renderer (imgui_impl_opengl3)
|
||||
// This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan..)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy AKEYCODE_* values are obsolete since 1.87 and not supported since 1.91.5]
|
||||
|
|
@ -23,7 +23,9 @@
|
|||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2022-09-26: Inputs: Renamed ImGuiKey_ModXXX introduced in 1.87 to ImGuiMod_XXX (old names still supported).
|
||||
// 2026-07-15: Inputs: clear mouse position on touch release (AMOTION_EVENT_ACTION_UP) to prevent items from staying in hovered state. (#6627, #9474)
|
||||
// 2023-04-11: Inputs: calling new io.AddMouseSourceEvent() to discriminate Mouse from Touch events.
|
||||
// 2022-09-26: Inputs: renamed ImGuiKey_ModXXX introduced in 1.87 to ImGuiMod_XXX (old names still supported).
|
||||
// 2022-01-26: Inputs: replaced short-lived io.AddKeyModsEvent() (added two weeks ago) with io.AddKeyEvent() using ImGuiKey_ModXXX flags. Sorry for the confusion.
|
||||
// 2022-01-17: Inputs: calling new io.AddMousePosEvent(), io.AddMouseButtonEvent(), io.AddMouseWheelEvent() API (1.87+).
|
||||
// 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModsEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range.
|
||||
|
|
@ -230,6 +232,8 @@ int32_t ImGui_ImplAndroid_HandleInputEvent(const AInputEvent* input_event)
|
|||
{
|
||||
io.AddMousePosEvent(AMotionEvent_getX(input_event, event_pointer_index), AMotionEvent_getY(input_event, event_pointer_index));
|
||||
io.AddMouseButtonEvent(0, event_action == AMOTION_EVENT_ACTION_DOWN);
|
||||
if (event_action == AMOTION_EVENT_ACTION_UP) // (#6627, #9474)
|
||||
io.AddMousePosEvent(-FLT_MAX, -FLT_MAX);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// dear imgui: Platform Binding for Android native app
|
||||
// This needs to be used along with the OpenGL 3 Renderer (imgui_impl_opengl3)
|
||||
// This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan..)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy AKEYCODE_* values are obsolete since 1.87 and not supported since 1.91.5]
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
// [X] Renderer: User texture binding. Use 'ID3D10ShaderResourceView*' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access with ImGui_ImplDX10_GetRenderState().
|
||||
|
||||
// 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.
|
||||
|
|
@ -16,6 +17,7 @@
|
|||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-09-07: Round framebuffer dimensions to the nearest integer instead of truncating them. (#9538, 9515, #8628)
|
||||
// 2026-04-23: DirectX10: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. Obsoleting samplers from ImGui_ImplDX10_RenderState. (#9378)
|
||||
// 2026-01-19: DirectX10: Added 'SamplerNearest' in ImGui_ImplDX10_RenderState. Renamed 'SamplerDefault' to 'SamplerLinear'.
|
||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
||||
|
|
@ -99,6 +101,11 @@ static ImGui_ImplDX10_Data* ImGui_ImplDX10_GetBackendData()
|
|||
return ImGui::GetCurrentContext() ? (ImGui_ImplDX10_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
|
||||
}
|
||||
|
||||
ImGui_ImplDX10_RenderState* ImGui_ImplDX10_GetRenderState()
|
||||
{
|
||||
return (ImGui_ImplDX10_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState;
|
||||
}
|
||||
|
||||
// Functions
|
||||
static void ImGui_ImplDX10_SetupRenderState(ImDrawData* draw_data, ID3D10Device* device)
|
||||
{
|
||||
|
|
@ -106,8 +113,8 @@ static void ImGui_ImplDX10_SetupRenderState(ImDrawData* draw_data, ID3D10Device*
|
|||
|
||||
// Setup viewport
|
||||
D3D10_VIEWPORT vp = {};
|
||||
vp.Width = (UINT)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
|
||||
vp.Height = (UINT)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
|
||||
vp.Width = (UINT)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
|
||||
vp.Height = (UINT)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
|
||||
vp.MinDepth = 0.0f;
|
||||
vp.MaxDepth = 1.0f;
|
||||
vp.TopLeftX = vp.TopLeftY = 0;
|
||||
|
|
@ -148,7 +155,7 @@ static void ImGui_ImplDX10_SetupRenderState(ImDrawData* draw_data, ID3D10Device*
|
|||
device->GSSetShader(nullptr);
|
||||
|
||||
// Setup render state
|
||||
const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };
|
||||
const float blend_factor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
device->OMSetBlendState(bd->pBlendState, blend_factor, 0xffffffff);
|
||||
device->OMSetDepthStencilState(bd->pDepthStencilState, 0);
|
||||
device->RSSetState(bd->pRasterizerState);
|
||||
|
|
@ -446,7 +453,7 @@ bool ImGui_ImplDX10_CreateDeviceObjects()
|
|||
PS_INPUT main(VS_INPUT input)\
|
||||
{\
|
||||
PS_INPUT output;\
|
||||
output.pos = mul( ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));\
|
||||
output.pos = mul( ProjectionMatrix, float4(input.pos.xy, 0.0f, 1.0f));\
|
||||
output.col = input.col;\
|
||||
output.uv = input.uv;\
|
||||
return output;\
|
||||
|
|
@ -557,8 +564,7 @@ bool ImGui_ImplDX10_CreateDeviceObjects()
|
|||
bd->pd3dDevice->CreateDepthStencilState(&desc, &bd->pDepthStencilState);
|
||||
}
|
||||
|
||||
// Create texture sampler
|
||||
// (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
|
||||
// Create texture sampler (bilinear sampling is required)
|
||||
{
|
||||
D3D10_SAMPLER_DESC desc;
|
||||
ZeroMemory(&desc, sizeof(desc));
|
||||
|
|
@ -566,10 +572,10 @@ bool ImGui_ImplDX10_CreateDeviceObjects()
|
|||
desc.AddressU = D3D10_TEXTURE_ADDRESS_CLAMP;
|
||||
desc.AddressV = D3D10_TEXTURE_ADDRESS_CLAMP;
|
||||
desc.AddressW = D3D10_TEXTURE_ADDRESS_CLAMP;
|
||||
desc.MipLODBias = 0.f;
|
||||
desc.MipLODBias = 0.0f;
|
||||
desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS;
|
||||
desc.MinLOD = 0.f;
|
||||
desc.MaxLOD = 0.f;
|
||||
desc.MinLOD = 0.0f;
|
||||
desc.MaxLOD = 0.0f;
|
||||
bd->pd3dDevice->CreateSamplerState(&desc, &bd->pTexSamplerLinear);
|
||||
desc.Filter = D3D10_FILTER_MIN_MAG_MIP_POINT;
|
||||
bd->pd3dDevice->CreateSamplerState(&desc, &bd->pTexSamplerNearest);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
// [X] Renderer: User texture binding. Use 'ID3D10ShaderResourceView*' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access with ImGui_ImplDX10_GetRenderState().
|
||||
|
||||
// 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.
|
||||
|
|
@ -45,5 +46,6 @@ struct ImGui_ImplDX10_RenderState
|
|||
//ID3D10SamplerState* SamplerLinear; // Use ImDrawList::AddCallback(ImGui::GetPlatform().DrawCallback_SetSamplerLinear)
|
||||
//ID3D10SamplerState* SamplerNearest; // Use ImDrawList::AddCallback(ImGui::GetPlatform().DrawCallback_SetSamplerNearest)
|
||||
};
|
||||
IMGUI_IMPL_API ImGui_ImplDX10_RenderState* ImGui_ImplDX10_GetRenderState();
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access with ImGui_ImplDX11_GetRenderState().
|
||||
|
||||
// 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.
|
||||
|
|
@ -103,6 +103,11 @@ static ImGui_ImplDX11_Data* ImGui_ImplDX11_GetBackendData()
|
|||
return ImGui::GetCurrentContext() ? (ImGui_ImplDX11_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
|
||||
}
|
||||
|
||||
ImGui_ImplDX11_RenderState* ImGui_ImplDX11_GetRenderState()
|
||||
{
|
||||
return (ImGui_ImplDX11_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState;
|
||||
}
|
||||
|
||||
// Functions
|
||||
static void ImGui_ImplDX11_SetupRenderState(const ImDrawData* draw_data, ID3D11DeviceContext* device_ctx)
|
||||
{
|
||||
|
|
@ -110,8 +115,8 @@ static void ImGui_ImplDX11_SetupRenderState(const ImDrawData* draw_data, ID3D11D
|
|||
|
||||
// Setup viewport
|
||||
D3D11_VIEWPORT vp = {};
|
||||
vp.Width = draw_data->DisplaySize.x * draw_data->FramebufferScale.x;
|
||||
vp.Height = draw_data->DisplaySize.y * draw_data->FramebufferScale.y;
|
||||
vp.Width = (float)(int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
|
||||
vp.Height = (float)(int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
|
||||
vp.MinDepth = 0.0f;
|
||||
vp.MaxDepth = 1.0f;
|
||||
vp.TopLeftX = vp.TopLeftY = 0;
|
||||
|
|
@ -155,7 +160,7 @@ static void ImGui_ImplDX11_SetupRenderState(const ImDrawData* draw_data, ID3D11D
|
|||
device_ctx->CSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used..
|
||||
|
||||
// Setup render state
|
||||
const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };
|
||||
const float blend_factor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
device_ctx->OMSetBlendState(bd->pBlendState, blend_factor, 0xffffffff);
|
||||
device_ctx->OMSetDepthStencilState(bd->pDepthStencilState, 0);
|
||||
device_ctx->RSSetState(bd->pRasterizerState);
|
||||
|
|
@ -462,7 +467,7 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
|
|||
PS_INPUT main(VS_INPUT input)\
|
||||
{\
|
||||
PS_INPUT output;\
|
||||
output.pos = mul( ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));\
|
||||
output.pos = mul( ProjectionMatrix, float4(input.pos.xy, 0.0f, 1.0f));\
|
||||
output.col = input.col;\
|
||||
output.uv = input.uv;\
|
||||
return output;\
|
||||
|
|
@ -574,7 +579,6 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
|
|||
}
|
||||
|
||||
// Create texture sampler
|
||||
// (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
|
||||
{
|
||||
D3D11_SAMPLER_DESC desc;
|
||||
ZeroMemory(&desc, sizeof(desc));
|
||||
|
|
@ -582,10 +586,10 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
|
|||
desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
desc.MipLODBias = 0.f;
|
||||
desc.MipLODBias = 0.0f;
|
||||
desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
|
||||
desc.MinLOD = 0.f;
|
||||
desc.MaxLOD = 0.f;
|
||||
desc.MinLOD = 0.0f;
|
||||
desc.MaxLOD = 0.0f;
|
||||
bd->pd3dDevice->CreateSamplerState(&desc, &bd->pTexSamplerLinear);
|
||||
desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
|
||||
bd->pd3dDevice->CreateSamplerState(&desc, &bd->pTexSamplerNearest);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access with ImGui_ImplDX11_GetRenderState().
|
||||
|
||||
// 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.
|
||||
|
|
@ -48,5 +48,6 @@ struct ImGui_ImplDX11_RenderState
|
|||
//ID3D11SamplerState* SamplerLinear; // Use ImDrawList::AddCallback(ImGui::GetPlatform().DrawCallback_SetSamplerLinear)
|
||||
//ID3D11SamplerState* SamplerNearest; // Use ImDrawList::AddCallback(ImGui::GetPlatform().DrawCallback_SetSamplerNearest)
|
||||
};
|
||||
IMGUI_IMPL_API ImGui_ImplDX11_RenderState* ImGui_ImplDX11_GetRenderState();
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
// [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access with ImGui_ImplDX12_GetRenderState().
|
||||
|
||||
// The aim of imgui_impl_dx12.h/.cpp is to be usable in your engine without any modification.
|
||||
// IF YOU FEEL YOU NEED TO MAKE ANY CHANGE TO THIS CODE, please share them and your feedback at https://github.com/ocornut/imgui/
|
||||
|
|
@ -20,6 +20,8 @@
|
|||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-09-07: Round framebuffer dimensions to the nearest integer instead of truncating them. (#9538, 9515, #8628)
|
||||
// 2026-08-05: DirectX12: *BREAKING CHANGE* Removed support for legacy `ImGui_ImplDX12_Init()` signature obsoleted in 1.91.6 (2024-11-15) because it needed to forcefully disable support for ImGuiBackendFlags_RendererHasTextures. (#9487)
|
||||
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)
|
||||
// 2025-10-11: DirectX12: Reuse texture upload buffer and grow it only when necessary. (#9002)
|
||||
// 2025-09-29: DirectX12: Rework synchronization logic. (#8961)
|
||||
|
|
@ -131,6 +133,11 @@ static ImGui_ImplDX12_Data* ImGui_ImplDX12_GetBackendData()
|
|||
return ImGui::GetCurrentContext() ? (ImGui_ImplDX12_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
|
||||
}
|
||||
|
||||
ImGui_ImplDX12_RenderState* ImGui_ImplDX12_GetRenderState()
|
||||
{
|
||||
return (ImGui_ImplDX12_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState;
|
||||
}
|
||||
|
||||
// Buffers used during the rendering of a frame
|
||||
struct ImGui_ImplDX12_RenderBuffers
|
||||
{
|
||||
|
|
@ -182,8 +189,8 @@ static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12Graphic
|
|||
|
||||
// Setup viewport
|
||||
D3D12_VIEWPORT vp = {};
|
||||
vp.Width = draw_data->DisplaySize.x * draw_data->FramebufferScale.x;
|
||||
vp.Height = draw_data->DisplaySize.y * draw_data->FramebufferScale.y;
|
||||
vp.Width = (float)(int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
|
||||
vp.Height = (float)(int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
|
||||
vp.MinDepth = 0.0f;
|
||||
vp.MaxDepth = 1.0f;
|
||||
vp.TopLeftX = vp.TopLeftY = 0.0f;
|
||||
|
|
@ -207,7 +214,7 @@ static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12Graphic
|
|||
command_list->SetGraphicsRoot32BitConstants(0, 16, &vertex_constant_buffer, 0);
|
||||
|
||||
// Setup blend factor
|
||||
const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };
|
||||
const float blend_factor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
command_list->OMSetBlendFactor(blend_factor);
|
||||
}
|
||||
|
||||
|
|
@ -608,17 +615,17 @@ bool ImGui_ImplDX12_CreateDeviceObjects()
|
|||
param[1].DescriptorTable.pDescriptorRanges = &descRange;
|
||||
param[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
|
||||
|
||||
// Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling.
|
||||
// Bilinear sampling is required
|
||||
D3D12_STATIC_SAMPLER_DESC staticSampler[1] = {};
|
||||
staticSampler[0].Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
staticSampler[0].AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
||||
staticSampler[0].AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
||||
staticSampler[0].AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
||||
staticSampler[0].MipLODBias = 0.f;
|
||||
staticSampler[0].MipLODBias = 0.0f;
|
||||
staticSampler[0].MaxAnisotropy = 0;
|
||||
staticSampler[0].ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS;
|
||||
staticSampler[0].BorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK;
|
||||
staticSampler[0].MinLOD = 0.f;
|
||||
staticSampler[0].MinLOD = 0.0f;
|
||||
staticSampler[0].MaxLOD = D3D12_FLOAT32_MAX;
|
||||
staticSampler[0].ShaderRegister = 0;
|
||||
staticSampler[0].RegisterSpace = 0;
|
||||
|
|
@ -721,7 +728,7 @@ bool ImGui_ImplDX12_CreateDeviceObjects()
|
|||
PS_INPUT main(VS_INPUT input)\
|
||||
{\
|
||||
PS_INPUT output;\
|
||||
output.pos = mul( ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));\
|
||||
output.pos = mul( ProjectionMatrix, float4(input.pos.xy, 0.0f, 1.0f));\
|
||||
output.col = input.col;\
|
||||
output.uv = input.uv;\
|
||||
return output;\
|
||||
|
|
@ -956,37 +963,6 @@ bool ImGui_ImplDX12_Init(ImGui_ImplDX12_InitInfo* init_info)
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
// Legacy initialization API Obsoleted in 1.91.5
|
||||
// font_srv_cpu_desc_handle and font_srv_gpu_desc_handle are handles to a single SRV descriptor to use for the internal font texture, they must be in 'srv_descriptor_heap'
|
||||
bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FORMAT rtv_format, ID3D12DescriptorHeap* srv_descriptor_heap, D3D12_CPU_DESCRIPTOR_HANDLE font_srv_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE font_srv_gpu_desc_handle)
|
||||
{
|
||||
ImGui_ImplDX12_InitInfo init_info;
|
||||
init_info.Device = device;
|
||||
init_info.NumFramesInFlight = num_frames_in_flight;
|
||||
init_info.RTVFormat = rtv_format;
|
||||
init_info.SrvDescriptorHeap = srv_descriptor_heap;
|
||||
init_info.LegacySingleSrvCpuDescriptor = font_srv_cpu_desc_handle;
|
||||
init_info.LegacySingleSrvGpuDescriptor = font_srv_gpu_desc_handle;
|
||||
|
||||
D3D12_COMMAND_QUEUE_DESC queueDesc = {};
|
||||
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
||||
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
|
||||
queueDesc.NodeMask = 1;
|
||||
HRESULT hr = device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&init_info.CommandQueue));
|
||||
IM_ASSERT(SUCCEEDED(hr));
|
||||
|
||||
bool ret = ImGui_ImplDX12_Init(&init_info);
|
||||
ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
|
||||
bd->commandQueueOwned = true;
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.BackendFlags &= ~ImGuiBackendFlags_RendererHasTextures; // Using legacy ImGui_ImplDX12_Init() call with 1 SRV descriptor we cannot support multiple textures.
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
void ImGui_ImplDX12_Shutdown()
|
||||
{
|
||||
ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
// [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access with ImGui_ImplDX12_GetRenderState().
|
||||
|
||||
// The aim of imgui_impl_dx12.h/.cpp is to be usable in your engine without any modification.
|
||||
// IF YOU FEEL YOU NEED TO MAKE ANY CHANGE TO THIS CODE, please share them and your feedback at https://github.com/ocornut/imgui/
|
||||
|
|
@ -59,13 +59,6 @@ IMGUI_IMPL_API void ImGui_ImplDX12_Shutdown();
|
|||
IMGUI_IMPL_API void ImGui_ImplDX12_NewFrame();
|
||||
IMGUI_IMPL_API void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandList* graphics_command_list);
|
||||
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
// Legacy initialization API Obsoleted in 1.91.5
|
||||
// - font_srv_cpu_desc_handle and font_srv_gpu_desc_handle are handles to a single SRV descriptor to use for the internal font texture, they must be in 'srv_descriptor_heap'
|
||||
// - When we introduced the ImGui_ImplDX12_InitInfo struct we also added a 'ID3D12CommandQueue* CommandQueue' field.
|
||||
IMGUI_IMPL_API bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FORMAT rtv_format, ID3D12DescriptorHeap* srv_descriptor_heap, D3D12_CPU_DESCRIPTOR_HANDLE font_srv_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE font_srv_gpu_desc_handle);
|
||||
#endif
|
||||
|
||||
// Use if you want to reset your rendering device without losing Dear ImGui state.
|
||||
IMGUI_IMPL_API bool ImGui_ImplDX12_CreateDeviceObjects();
|
||||
IMGUI_IMPL_API void ImGui_ImplDX12_InvalidateDeviceObjects();
|
||||
|
|
@ -81,6 +74,15 @@ struct ImGui_ImplDX12_RenderState
|
|||
ID3D12Device* Device;
|
||||
ID3D12GraphicsCommandList* CommandList;
|
||||
};
|
||||
IMGUI_IMPL_API ImGui_ImplDX12_RenderState* ImGui_ImplDX12_GetRenderState();
|
||||
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
// Legacy initialization API Obsoleted in 1.91.5
|
||||
// - font_srv_cpu_desc_handle and font_srv_gpu_desc_handle are handles to a single SRV descriptor to use for the internal font texture, they must be in 'srv_descriptor_heap'
|
||||
// - When we introduced the ImGui_ImplDX12_InitInfo struct we also added a 'ID3D12CommandQueue* CommandQueue' field.
|
||||
// - DOES NOT SUPPORT ImGuiBackendFlags_RendererHasTextures.
|
||||
//IMGUI_IMPL_API bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FORMAT rtv_format, ID3D12DescriptorHeap* srv_descriptor_heap, D3D12_CPU_DESCRIPTOR_HANDLE font_srv_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE font_srv_gpu_desc_handle);
|
||||
#endif
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ struct ImGui_ImplGlfw_Data
|
|||
bool IsWayland;
|
||||
bool InstalledCallbacks;
|
||||
bool CallbacksChainForAllWindows;
|
||||
char BackendPlatformName[32];
|
||||
char BackendPlatformName[40];
|
||||
#ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3
|
||||
const char* CanvasSelector;
|
||||
#endif
|
||||
|
|
@ -676,7 +676,13 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
|
|||
|
||||
// Setup backend capabilities flags
|
||||
ImGui_ImplGlfw_Data* bd = IM_NEW(ImGui_ImplGlfw_Data)();
|
||||
snprintf(bd->BackendPlatformName, sizeof(bd->BackendPlatformName), "imgui_impl_glfw (%d)", GLFW_VERSION_COMBINED);
|
||||
bd->Context = ImGui::GetCurrentContext();
|
||||
bd->Window = window;
|
||||
bd->Time = 0.0;
|
||||
bd->IsWayland = ImGui_ImplGlfw_IsWayland();
|
||||
ImGui_ImplGlfw_ContextMap_Add(window, bd->Context);
|
||||
|
||||
snprintf(bd->BackendPlatformName, sizeof(bd->BackendPlatformName), "imgui_impl_glfw (%d)%s", GLFW_VERSION_COMBINED, bd->IsWayland ? " (Wayland)" : "");
|
||||
io.BackendPlatformUserData = (void*)bd;
|
||||
io.BackendPlatformName = bd->BackendPlatformName;
|
||||
#if GLFW_HAS_CREATECURSOR
|
||||
|
|
@ -684,12 +690,6 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
|
|||
#endif
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
|
||||
|
||||
bd->Context = ImGui::GetCurrentContext();
|
||||
bd->Window = window;
|
||||
bd->Time = 0.0;
|
||||
bd->IsWayland = ImGui_ImplGlfw_IsWayland();
|
||||
ImGui_ImplGlfw_ContextMap_Add(window, bd->Context);
|
||||
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
#if GLFW_VERSION_COMBINED < 3300
|
||||
platform_io.Platform_SetClipboardTextFn = [](ImGuiContext*, const char* text) { glfwSetClipboardString(ImGui_ImplGlfw_GetBackendData()->Window, text); };
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-09-07: Round framebuffer dimensions to the nearest integer instead of truncating them. (#9538, 9515, #8628)
|
||||
// 2026-04-28: Added support for standard draw callbacks (in platform_io): DrawCallback_SetSamplerLinear and DrawCallback_SetSamplerNearest. (#9378, #9381)
|
||||
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState (others are not yet supported). (#9378)
|
||||
// 2026-04-14: Metal: use a dedicated bufferCacheLock to avoid crashing when bufferCache is replaced by a new object while being used for @synchronize(). (#9367)
|
||||
|
|
@ -123,7 +124,6 @@ void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data,
|
|||
ImGui_ImplMetal_RenderDrawData(draw_data,
|
||||
(__bridge id<MTLCommandBuffer>)(commandBuffer),
|
||||
(__bridge id<MTLRenderCommandEncoder>)(commandEncoder));
|
||||
|
||||
}
|
||||
|
||||
bool ImGui_ImplMetal_CreateDeviceObjects(MTL::Device* device)
|
||||
|
|
@ -164,8 +164,8 @@ static void ImGui_ImplMetal_SetupRenderState(ImDrawData* draw_data, id<MTLComman
|
|||
{
|
||||
.originX = 0.0,
|
||||
.originY = 0.0,
|
||||
.width = (double)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x),
|
||||
.height = (double)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y),
|
||||
.width = (double)(int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f),
|
||||
.height = (double)(int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f),
|
||||
.znear = 0.0,
|
||||
.zfar = 1.0
|
||||
};
|
||||
|
|
@ -204,8 +204,8 @@ void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data, id<MTLCommandBuffer>
|
|||
MetalContext* ctx = bd->SharedMetalContext;
|
||||
|
||||
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
||||
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
|
||||
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
|
||||
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
|
||||
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
|
||||
if (fb_width <= 0 || fb_height <= 0 || draw_data->CmdLists.Size == 0)
|
||||
return;
|
||||
|
||||
|
|
@ -585,7 +585,7 @@ void ImGui_ImplMetal_Shutdown()
|
|||
return [[MetalBuffer alloc] initWithBuffer:backing];
|
||||
}
|
||||
|
||||
// Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling.
|
||||
// Bilinear sampling is required.
|
||||
- (id<MTLRenderPipelineState>)renderPipelineStateForFramebufferDescriptor:(FramebufferDescriptor*)descriptor device:(id<MTLDevice>)device
|
||||
{
|
||||
NSError* error = nil;
|
||||
|
|
|
|||
89
backends/imgui_impl_metal4.h
Normal file
89
backends/imgui_impl_metal4.h
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
// dear imgui: Renderer Backend for Metal 4
|
||||
// This needs to be used along with a Platform Backend (e.g. OSX)
|
||||
// Metal 4 requires Apple Silicon and macOS 26+.
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'MTLTexture.gpuResourceID' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// Missing features or Issues:
|
||||
// [ ] Texture view pool support? Reevaluate which type to use for ImtextureID.
|
||||
|
||||
// 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.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - 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
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
#ifndef IMGUI_DISABLE
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ObjC API
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifdef __OBJC__
|
||||
|
||||
@class MTL4RenderPassDescriptor;
|
||||
@protocol MTLDevice, MTL4CommandBuffer, MTL4RenderCommandEncoder, MTL4CommandQueue;
|
||||
|
||||
// framesInFlight must match the number of frames your application keeps in flight (e.g. the size of your own
|
||||
// command buffer/allocator ring). The backend uses it to size its own per-frame-in-flight resources (constant
|
||||
// buffer, vertex/index buffer cache) so the CPU never overwrites a slot the GPU may still be reading.
|
||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||
IMGUI_IMPL_API bool ImGui_ImplMetal4_Init(id<MTLDevice> device, id<MTL4CommandQueue> commandQueue, int framesInFlight);
|
||||
IMGUI_IMPL_API void ImGui_ImplMetal4_Shutdown();
|
||||
// frameInFlightIndex must match the slot you use to index your own per-frame-in-flight resources
|
||||
// (e.g. the same index used to pick your command buffer/allocator), and must be < framesInFlight passed to Init().
|
||||
IMGUI_IMPL_API void ImGui_ImplMetal4_NewFrame(MTL4RenderPassDescriptor* renderPassDescriptor, int frameInFlightIndex);
|
||||
IMGUI_IMPL_API void ImGui_ImplMetal4_RenderDrawData(ImDrawData* drawData,
|
||||
id<MTL4CommandBuffer> commandBuffer,
|
||||
id<MTL4RenderCommandEncoder> commandEncoder);
|
||||
|
||||
// Called by Init/NewFrame/Shutdown
|
||||
IMGUI_IMPL_API bool ImGui_ImplMetal4_CreateDeviceObjects(id<MTLDevice> device);
|
||||
IMGUI_IMPL_API void ImGui_ImplMetal4_DestroyDeviceObjects();
|
||||
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.
|
||||
IMGUI_IMPL_API void ImGui_ImplMetal4_UpdateTexture(ImTextureData* tex);
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// C++ API
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Enable Metal C++ binding support with '#define IMGUI_IMPL_METAL_CPP' in your imconfig.h file
|
||||
// More info about using Metal from C++: https://developer.apple.com/metal/cpp/
|
||||
|
||||
#ifdef IMGUI_IMPL_METAL_CPP
|
||||
#ifndef __OBJC__
|
||||
|
||||
// Forward declare relevant classes from the MTL and MTL4 namespace
|
||||
namespace MTL { class Device; }
|
||||
namespace MTL4 { class CommandQueue; class CommandBuffer; class RenderPassDescriptor; class RenderCommandEncoder; }
|
||||
|
||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||
IMGUI_IMPL_API bool ImGui_ImplMetal4_Init(MTL::Device* device, MTL4::CommandQueue* commandQueue, int framesInFlight);
|
||||
IMGUI_IMPL_API void ImGui_ImplMetal4_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplMetal4_NewFrame(MTL4::RenderPassDescriptor* renderPassDescriptor, int frameInFlightIndex);
|
||||
IMGUI_IMPL_API void ImGui_ImplMetal4_RenderDrawData(ImDrawData* draw_data,
|
||||
MTL4::CommandBuffer* commandBuffer,
|
||||
MTL4::RenderCommandEncoder* commandEncoder);
|
||||
|
||||
// Called by Init/NewFrame/Shutdown
|
||||
IMGUI_IMPL_API bool ImGui_ImplMetal4_CreateDeviceObjects(MTL::Device* device);
|
||||
IMGUI_IMPL_API void ImGui_ImplMetal4_DestroyDeviceObjects();
|
||||
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.
|
||||
IMGUI_IMPL_API void ImGui_ImplMetal4_UpdateTexture(ImTextureData* tex);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
744
backends/imgui_impl_metal4.mm
Normal file
744
backends/imgui_impl_metal4.mm
Normal file
|
|
@ -0,0 +1,744 @@
|
|||
// dear imgui: Renderer Backend for Metal 4
|
||||
// This needs to be used along with a Platform Backend (e.g. OSX)
|
||||
// Metal 4 requires Apple Silicon and macOS 26+.
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'MTLTexture' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// Missing features or Issues:
|
||||
// [ ] Texture view pool support? Reevaluate which type to use for ImtextureID.
|
||||
|
||||
// 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.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - 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
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-09-07: Round framebuffer dimensions to the nearest integer instead of truncating them. (#9538, 9515, #8628)
|
||||
// 2026-07-07: Metal 4: Added metal-cpp support. (#9461)
|
||||
// 2026-07-02: Metal 4: Added new Metal 4 backend implementation. (#9458)
|
||||
|
||||
#include "imgui.h"
|
||||
#ifndef IMGUI_DISABLE
|
||||
#include "imgui_impl_metal4.h"
|
||||
#import <time.h>
|
||||
#import <Metal/Metal.h>
|
||||
|
||||
#ifdef IMGUI_IMPL_METAL_CPP
|
||||
#include <Metal/Metal.hpp>
|
||||
#endif
|
||||
|
||||
#pragma mark - Support classes and structs
|
||||
|
||||
struct ImGui_Metal4_ConstantData
|
||||
{
|
||||
float ModelViewProjectionMatrix[4][4];
|
||||
};
|
||||
|
||||
@interface MetalBuffer : NSObject
|
||||
@property (nonatomic, strong) id<MTLBuffer> buffer;
|
||||
@property (nonatomic, assign) double lastReuseTime;
|
||||
- (instancetype)initWithBuffer:(id<MTLBuffer>)buffer;
|
||||
@end
|
||||
|
||||
// An object that encapsulates the data necessary to uniquely identify a
|
||||
// render pipeline state. These are used as cache keys.
|
||||
@interface FramebufferDescriptor : NSObject<NSCopying>
|
||||
@property (nonatomic, assign) unsigned long sampleCount;
|
||||
@property (nonatomic, assign) MTLPixelFormat colorPixelFormat;
|
||||
@property (nonatomic, assign) MTLPixelFormat depthPixelFormat;
|
||||
@property (nonatomic, assign) MTLPixelFormat stencilPixelFormat;
|
||||
- (instancetype)initWithRenderPassDescriptor:(MTL4RenderPassDescriptor*)renderPassDescriptor;
|
||||
@end
|
||||
|
||||
@interface MetalTexture : NSObject
|
||||
@property (nonatomic, strong) id<MTLTexture> metalTexture;
|
||||
- (instancetype)initWithTexture:(id<MTLTexture>)metalTexture;
|
||||
@end
|
||||
|
||||
// A singleton that stores long-lived objects that are needed by the Metal
|
||||
// renderer backend. Stores the render pipeline state cache and the default
|
||||
// font texture, and manages the reusable buffer cache.
|
||||
@interface MetalContext : NSObject
|
||||
@property (nonatomic, strong) id<MTLDevice> device;
|
||||
@property (nonatomic, strong) id<MTL4CommandQueue> commandQueue;
|
||||
@property (nonatomic, strong) id<MTLDepthStencilState> depthStencilState;
|
||||
@property (nonatomic, strong) id<MTL4ArgumentTable> argumentTable;
|
||||
@property (nonatomic, strong) id<MTLSamplerState> samplerStateLinear;
|
||||
@property (nonatomic, strong) id<MTLSamplerState> samplerStateNearest;
|
||||
@property (nonatomic, strong) id<MTLResidencySet> residencySet;
|
||||
@property (nonatomic, strong) FramebufferDescriptor* framebufferDescriptor;
|
||||
@property (nonatomic, strong) NSMutableDictionary* renderPipelineStateCache;
|
||||
@property (nonatomic, assign) NSUInteger framesInFlight;
|
||||
@property (nonatomic, assign) NSUInteger currentFrameSlot;
|
||||
@property (nonatomic, strong) NSArray<id<MTLBuffer>>* constantBuffers;
|
||||
@property (nonatomic, assign) ImGui_Metal4_ConstantData** constantBufferContentsArray;
|
||||
@property (nonatomic, strong) NSMutableArray<NSMutableArray<MetalBuffer*>*>* bufferCaches;
|
||||
@property (nonatomic, strong) NSObject* bufferCacheLock;
|
||||
@property (nonatomic, assign) double lastBufferCachePurge;
|
||||
- (id<MTLBuffer>)currentConstantBuffer;
|
||||
- (ImGui_Metal4_ConstantData*)currentConstantBufferContents;
|
||||
- (MetalBuffer*)dequeueReusableBufferOfLength:(NSUInteger)length device:(id<MTLDevice>)device;
|
||||
- (id<MTLRenderPipelineState>)renderPipelineStateForFramebufferDescriptor:(FramebufferDescriptor*)descriptor device:(id<MTLDevice>)device;
|
||||
@end
|
||||
|
||||
struct ImGui_ImplMetal4_Data
|
||||
{
|
||||
MetalContext* SharedMetalContext;
|
||||
id<MTL4RenderCommandEncoder> RenderCommandEncoder;
|
||||
|
||||
ImGui_ImplMetal4_Data() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
static ImGui_ImplMetal4_Data* ImGui_ImplMetal4_GetBackendData() { return ImGui::GetCurrentContext() ? (ImGui_ImplMetal4_Data*)ImGui::GetIO().BackendRendererUserData : nullptr; }
|
||||
static void ImGui_ImplMetal4_DestroyBackendData(){ IM_DELETE(ImGui_ImplMetal4_GetBackendData()); }
|
||||
|
||||
static inline CFTimeInterval GetMachAbsoluteTimeInSeconds() { return (CFTimeInterval)(double)(clock_gettime_nsec_np(CLOCK_UPTIME_RAW) / 1e9); }
|
||||
|
||||
#ifdef IMGUI_IMPL_METAL_CPP
|
||||
|
||||
#pragma mark - Dear ImGui Metal C++ Backend API
|
||||
|
||||
bool ImGui_ImplMetal4_Init(MTL::Device* device, MTL4::CommandQueue* commandQueue, int framesInFlight)
|
||||
{
|
||||
return ImGui_ImplMetal4_Init((__bridge id<MTLDevice>)(device),(__bridge id<MTL4CommandQueue>)(commandQueue), framesInFlight);
|
||||
}
|
||||
|
||||
void ImGui_ImplMetal4_NewFrame(MTL4::RenderPassDescriptor* renderPassDescriptor, int frameInFlightIndex)
|
||||
{
|
||||
ImGui_ImplMetal4_NewFrame((__bridge MTL4RenderPassDescriptor*)(renderPassDescriptor), frameInFlightIndex);
|
||||
}
|
||||
|
||||
void ImGui_ImplMetal4_RenderDrawData(ImDrawData* draw_data,
|
||||
MTL4::CommandBuffer* commandBuffer,
|
||||
MTL4::RenderCommandEncoder* commandEncoder)
|
||||
{
|
||||
ImGui_ImplMetal4_RenderDrawData(draw_data,
|
||||
(__bridge id<MTL4CommandBuffer>)(commandBuffer),
|
||||
(__bridge id<MTL4RenderCommandEncoder>)(commandEncoder));
|
||||
}
|
||||
|
||||
bool ImGui_ImplMetal_CreateDeviceObjects(MTL::Device* device)
|
||||
{
|
||||
return ImGui_ImplMetal4_CreateDeviceObjects((__bridge id<MTLDevice>)(device));
|
||||
}
|
||||
|
||||
#endif // #ifdef IMGUI_IMPL_METAL_CPP
|
||||
|
||||
#pragma mark - Dear ImGui Metal Backend API
|
||||
|
||||
void ImGui_ImplMetal4_NewFrame(MTL4RenderPassDescriptor* renderPassDescriptor, int frameInFlightIndex)
|
||||
{
|
||||
ImGui_ImplMetal4_Data* bd = ImGui_ImplMetal4_GetBackendData();
|
||||
IM_ASSERT(bd != nil && "Context or backend not initialized! Did you call ImGui_ImplMetal4_Init()?");
|
||||
IM_ASSERT(frameInFlightIndex < bd->SharedMetalContext.framesInFlight && "frameInFlightIndex out of range! See framesInFlight passed to ImGui_ImplMetal4_Init().");
|
||||
#ifdef IMGUI_IMPL_METAL_CPP
|
||||
bd->SharedMetalContext.framebufferDescriptor = [[[FramebufferDescriptor alloc] initWithRenderPassDescriptor:renderPassDescriptor]autorelease];
|
||||
#else
|
||||
bd->SharedMetalContext.framebufferDescriptor = [[FramebufferDescriptor alloc] initWithRenderPassDescriptor:renderPassDescriptor];
|
||||
#endif
|
||||
bd->SharedMetalContext.currentFrameSlot = (NSUInteger)frameInFlightIndex;
|
||||
if (bd->SharedMetalContext.depthStencilState == nil)
|
||||
ImGui_ImplMetal4_CreateDeviceObjects(bd->SharedMetalContext.device);
|
||||
}
|
||||
|
||||
static void ImGui_ImplMetal4_SetupRenderState(ImDrawData* draw_data, id<MTL4CommandBuffer> commandBuffer,
|
||||
id<MTL4RenderCommandEncoder> commandEncoder, id<MTLRenderPipelineState> renderPipelineState,
|
||||
MetalBuffer* vertexBuffer, size_t vertexBufferOffset)
|
||||
{
|
||||
IM_UNUSED(commandBuffer);
|
||||
ImGui_ImplMetal4_Data* bd = ImGui_ImplMetal4_GetBackendData();
|
||||
[commandEncoder setCullMode:MTLCullModeNone];
|
||||
[commandEncoder setDepthStencilState:bd->SharedMetalContext.depthStencilState];
|
||||
|
||||
// Setup viewport, orthographic projection matrix
|
||||
// Our visible imgui space lies from draw_data->DisplayPos (top left) to
|
||||
// draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin is typically (0,0) for single viewport apps.
|
||||
MTLViewport viewport =
|
||||
{
|
||||
.originX = 0.0,
|
||||
.originY = 0.0,
|
||||
.width = (double)(int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f),
|
||||
.height = (double)(int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f),
|
||||
.znear = 0.0,
|
||||
.zfar = 1.0
|
||||
};
|
||||
[commandEncoder setViewport:viewport];
|
||||
|
||||
float L = draw_data->DisplayPos.x;
|
||||
float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;
|
||||
float T = draw_data->DisplayPos.y;
|
||||
float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y;
|
||||
float N = (float)viewport.znear;
|
||||
float F = (float)viewport.zfar;
|
||||
const float ortho_projection[4][4] =
|
||||
{
|
||||
{ 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 2.0f/(T-B), 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 1/(F-N), 0.0f },
|
||||
{ (R+L)/(L-R), (T+B)/(B-T), N/(F-N), 1.0f },
|
||||
};
|
||||
ImGui_Metal4_ConstantData* constantBufferContents = [bd->SharedMetalContext currentConstantBufferContents];
|
||||
memcpy(constantBufferContents->ModelViewProjectionMatrix, ortho_projection, sizeof(ortho_projection));
|
||||
|
||||
id<MTL4ArgumentTable> argumentTable = bd->SharedMetalContext.argumentTable;
|
||||
[argumentTable setAddress:[bd->SharedMetalContext currentConstantBuffer].gpuAddress atIndex:1];
|
||||
[argumentTable setAddress:(vertexBuffer.buffer.gpuAddress + vertexBufferOffset) attributeStride:sizeof(ImDrawVert) atIndex:0];
|
||||
[argumentTable setSamplerState:bd->SharedMetalContext.samplerStateLinear.gpuResourceID atIndex:0];
|
||||
[commandEncoder setArgumentTable:argumentTable atStages:MTLRenderStageVertex | MTLRenderStageFragment];
|
||||
[commandEncoder setRenderPipelineState:renderPipelineState];
|
||||
}
|
||||
|
||||
static void ImGui_ImplMetal4_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
|
||||
static void ImGui_ImplMetal4_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplMetal4_Data* bd = ImGui_ImplMetal4_GetBackendData(); [bd->SharedMetalContext.argumentTable setSamplerState:bd->SharedMetalContext.samplerStateLinear.gpuResourceID atIndex:0]; }
|
||||
static void ImGui_ImplMetal4_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplMetal4_Data* bd = ImGui_ImplMetal4_GetBackendData(); [bd->SharedMetalContext.argumentTable setSamplerState:bd->SharedMetalContext.samplerStateNearest.gpuResourceID atIndex:0]; }
|
||||
|
||||
void ImGui_ImplMetal4_RenderDrawData(ImDrawData* draw_data, id<MTL4CommandBuffer> commandBuffer, id<MTL4RenderCommandEncoder> commandEncoder)
|
||||
{
|
||||
ImGui_ImplMetal4_Data* bd = ImGui_ImplMetal4_GetBackendData();
|
||||
MetalContext* ctx = bd->SharedMetalContext;
|
||||
|
||||
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
||||
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
|
||||
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
|
||||
if (fb_width <= 0 || fb_height <= 0 || draw_data->CmdLists.Size == 0)
|
||||
return;
|
||||
|
||||
// Catch up with texture updates. Most of the times, the list will have 1 element with an OK status, aka nothing to do.
|
||||
// (This almost always points to ImGui::GetPlatformIO().Textures[] but is part of ImDrawData to allow overriding or disabling texture updates).
|
||||
if (draw_data->Textures != nullptr)
|
||||
for (ImTextureData* tex : *draw_data->Textures)
|
||||
if (tex->Status != ImTextureStatus_OK)
|
||||
ImGui_ImplMetal4_UpdateTexture(tex);
|
||||
|
||||
// Try to retrieve a render pipeline state that is compatible with the framebuffer config for this frame
|
||||
// The hit rate for this cache should be very near 100%.
|
||||
id<MTLRenderPipelineState> renderPipelineState = ctx.renderPipelineStateCache[ctx.framebufferDescriptor];
|
||||
if (renderPipelineState == nil)
|
||||
{
|
||||
// No luck; make a new render pipeline state
|
||||
renderPipelineState = [ctx renderPipelineStateForFramebufferDescriptor:ctx.framebufferDescriptor device:commandBuffer.device];
|
||||
|
||||
// Cache render pipeline state for later reuse
|
||||
ctx.renderPipelineStateCache[ctx.framebufferDescriptor] = renderPipelineState;
|
||||
}
|
||||
|
||||
size_t vertexBufferLength = (size_t)draw_data->TotalVtxCount * sizeof(ImDrawVert);
|
||||
size_t indexBufferLength = (size_t)draw_data->TotalIdxCount * sizeof(ImDrawIdx);
|
||||
MetalBuffer* vertexBuffer = [ctx dequeueReusableBufferOfLength:vertexBufferLength device:commandBuffer.device];
|
||||
MetalBuffer* indexBuffer = [ctx dequeueReusableBufferOfLength:indexBufferLength device:commandBuffer.device];
|
||||
|
||||
bd->RenderCommandEncoder = commandEncoder;
|
||||
ImGui_ImplMetal4_SetupRenderState(draw_data, commandBuffer, commandEncoder, renderPipelineState, vertexBuffer, 0);
|
||||
|
||||
// Will project scissor/clipping rectangles into framebuffer space
|
||||
ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
|
||||
ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2)
|
||||
|
||||
// Render command lists
|
||||
size_t vertexBufferOffset = 0;
|
||||
size_t indexBufferOffset = 0;
|
||||
for (const ImDrawList* draw_list : draw_data->CmdLists)
|
||||
{
|
||||
memcpy((char*)vertexBuffer.buffer.contents + vertexBufferOffset, draw_list->VtxBuffer.Data, (size_t)draw_list->VtxBuffer.Size * sizeof(ImDrawVert));
|
||||
memcpy((char*)indexBuffer.buffer.contents + indexBufferOffset, draw_list->IdxBuffer.Data, (size_t)draw_list->IdxBuffer.Size * sizeof(ImDrawIdx));
|
||||
|
||||
for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback)
|
||||
{
|
||||
// User callback, registered via ImDrawList::AddCallback()
|
||||
if (pcmd->UserCallback == ImGui_ImplMetal4_DrawCallback_ResetRenderState)
|
||||
ImGui_ImplMetal4_SetupRenderState(draw_data, commandBuffer, commandEncoder, renderPipelineState, vertexBuffer, vertexBufferOffset);
|
||||
else
|
||||
pcmd->UserCallback(draw_list, pcmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Project scissor/clipping rectangles into framebuffer space
|
||||
ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
|
||||
ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);
|
||||
|
||||
// Clamp to viewport as setScissorRect() won't accept values that are off bounds
|
||||
if (clip_min.x < 0.0f) { clip_min.x = 0.0f; }
|
||||
if (clip_min.y < 0.0f) { clip_min.y = 0.0f; }
|
||||
if (clip_max.x > (float)fb_width) { clip_max.x = (float)fb_width; }
|
||||
if (clip_max.y > (float)fb_height) { clip_max.y = (float)fb_height; }
|
||||
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
|
||||
continue;
|
||||
if (pcmd->ElemCount == 0) // drawIndexedPrimitives() validation doesn't accept this
|
||||
continue;
|
||||
|
||||
// Apply scissor/clipping rectangle
|
||||
MTLScissorRect scissorRect =
|
||||
{
|
||||
.x = NSUInteger(clip_min.x),
|
||||
.y = NSUInteger(clip_min.y),
|
||||
.width = NSUInteger(clip_max.x - clip_min.x),
|
||||
.height = NSUInteger(clip_max.y - clip_min.y)
|
||||
};
|
||||
[commandEncoder setScissorRect:scissorRect];
|
||||
|
||||
// Bind texture, Draw
|
||||
ImTextureID tex_id = pcmd->GetTexID();
|
||||
if (tex_id != ImTextureID_Invalid)
|
||||
{
|
||||
id<MTLTexture> texture = (__bridge id<MTLTexture>)(void*)(intptr_t)tex_id;
|
||||
[bd->SharedMetalContext.residencySet addAllocation:texture];
|
||||
[bd->SharedMetalContext.argumentTable setTexture:texture.gpuResourceID atIndex:0];
|
||||
}
|
||||
|
||||
[bd->SharedMetalContext.argumentTable setAddress:(vertexBuffer.buffer.gpuAddress + vertexBufferOffset + (pcmd->VtxOffset * sizeof(ImDrawVert))) attributeStride:sizeof(ImDrawVert) atIndex:0];
|
||||
|
||||
size_t indexBufferCmdOffset = indexBufferOffset + (pcmd->IdxOffset * sizeof(ImDrawIdx));
|
||||
[commandEncoder drawIndexedPrimitives:MTLPrimitiveTypeTriangle
|
||||
indexCount:pcmd->ElemCount
|
||||
indexType:sizeof(ImDrawIdx) == 2 ? MTLIndexTypeUInt16 : MTLIndexTypeUInt32
|
||||
indexBuffer:indexBuffer.buffer.gpuAddress + indexBufferCmdOffset
|
||||
indexBufferLength:indexBuffer.buffer.length - indexBufferCmdOffset];
|
||||
}
|
||||
}
|
||||
|
||||
vertexBufferOffset += (size_t)draw_list->VtxBuffer.Size * sizeof(ImDrawVert);
|
||||
indexBufferOffset += (size_t)draw_list->IdxBuffer.Size * sizeof(ImDrawIdx);
|
||||
}
|
||||
|
||||
MetalContext* sharedMetalContext = bd->SharedMetalContext;
|
||||
@synchronized(sharedMetalContext.bufferCacheLock)
|
||||
{
|
||||
NSMutableArray<MetalBuffer*>* slotCache = sharedMetalContext.bufferCaches[sharedMetalContext.currentFrameSlot];
|
||||
[slotCache addObject:vertexBuffer];
|
||||
[slotCache addObject:indexBuffer];
|
||||
}
|
||||
|
||||
// Commit residency set
|
||||
[bd->SharedMetalContext.residencySet commit];
|
||||
bd->RenderCommandEncoder = nil;
|
||||
}
|
||||
|
||||
static void ImGui_ImplMetal4_DestroyTexture(ImTextureData* tex)
|
||||
{
|
||||
if (MetalTexture* backend_tex = (__bridge_transfer MetalTexture*)(tex->BackendUserData))
|
||||
{
|
||||
IM_ASSERT(backend_tex.metalTexture == (__bridge id<MTLTexture>)(void*)(intptr_t)tex->TexID);
|
||||
backend_tex.metalTexture = nil;
|
||||
|
||||
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
|
||||
tex->SetTexID(ImTextureID_Invalid);
|
||||
tex->BackendUserData = nullptr;
|
||||
}
|
||||
tex->SetStatus(ImTextureStatus_Destroyed);
|
||||
}
|
||||
|
||||
void ImGui_ImplMetal4_UpdateTexture(ImTextureData* tex)
|
||||
{
|
||||
ImGui_ImplMetal4_Data* bd = ImGui_ImplMetal4_GetBackendData();
|
||||
if (tex->Status == ImTextureStatus_WantCreate)
|
||||
{
|
||||
// Create and upload new texture to graphics system
|
||||
//IMGUI_DEBUG_LOG("UpdateTexture #%03d: WantCreate %dx%d\n", tex->UniqueID, tex->Width, tex->Height);
|
||||
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == nullptr);
|
||||
IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
|
||||
|
||||
// We are retrieving and uploading the font atlas as a 4-channels RGBA texture here.
|
||||
// In theory we could call GetTexDataAsAlpha8() and upload a 1-channel texture to save on memory access bandwidth.
|
||||
// However, using a shader designed for 1-channel texture would make it less obvious to use the ImTextureID facility to render users own textures.
|
||||
// You can make that change in your implementation.
|
||||
MTLTextureDescriptor* textureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA8Unorm
|
||||
width:(NSUInteger)tex->Width
|
||||
height:(NSUInteger)tex->Height
|
||||
mipmapped:NO];
|
||||
textureDescriptor.usage = MTLTextureUsageShaderRead;
|
||||
textureDescriptor.storageMode = MTLStorageModeShared;
|
||||
|
||||
id <MTLTexture> texture = [bd->SharedMetalContext.device newTextureWithDescriptor:textureDescriptor];
|
||||
[bd->SharedMetalContext.residencySet addAllocation:texture];
|
||||
[texture replaceRegion:MTLRegionMake2D(0, 0, (NSUInteger)tex->Width, (NSUInteger)tex->Height) mipmapLevel:0 withBytes:tex->Pixels bytesPerRow:(NSUInteger)tex->Width * 4];
|
||||
MetalTexture* backend_tex = [[MetalTexture alloc] initWithTexture:texture];
|
||||
|
||||
// Store identifiers
|
||||
tex->SetTexID((ImTextureID)(intptr_t)texture);
|
||||
tex->SetStatus(ImTextureStatus_OK);
|
||||
tex->BackendUserData = (__bridge_retained void*)(backend_tex);
|
||||
}
|
||||
else if (tex->Status == ImTextureStatus_WantUpdates)
|
||||
{
|
||||
// Update selected blocks. We only ever write to textures regions which have never been used before!
|
||||
// This backend choose to use tex->Updates[] but you can use tex->UpdateRect to upload a single region.
|
||||
MetalTexture* backend_tex = (__bridge MetalTexture*)(tex->BackendUserData);
|
||||
for (ImTextureRect& r : tex->Updates)
|
||||
{
|
||||
[backend_tex.metalTexture replaceRegion:MTLRegionMake2D((NSUInteger)r.x, (NSUInteger)r.y, (NSUInteger)r.w, (NSUInteger)r.h)
|
||||
mipmapLevel:0
|
||||
withBytes:tex->GetPixelsAt(r.x, r.y)
|
||||
bytesPerRow:(NSUInteger)tex->Width * 4];
|
||||
}
|
||||
tex->SetStatus(ImTextureStatus_OK);
|
||||
}
|
||||
else if (tex->Status == ImTextureStatus_WantDestroy && tex->UnusedFrames > 0)
|
||||
{
|
||||
ImGui_ImplMetal4_DestroyTexture(tex);
|
||||
}
|
||||
}
|
||||
|
||||
bool ImGui_ImplMetal4_CreateDeviceObjects(id<MTLDevice> device)
|
||||
{
|
||||
ImGui_ImplMetal4_Data* bd = ImGui_ImplMetal4_GetBackendData();
|
||||
|
||||
MTLResidencySetDescriptor* residencySetDescriptor = [[MTLResidencySetDescriptor alloc] init];
|
||||
residencySetDescriptor.initialCapacity = 1000;
|
||||
|
||||
NSError* error = nil;
|
||||
bd->SharedMetalContext.residencySet = [device newResidencySetWithDescriptor:residencySetDescriptor error:&error];
|
||||
IM_ASSERT(bd->SharedMetalContext.residencySet != nil && error == nil);
|
||||
|
||||
[bd->SharedMetalContext.commandQueue addResidencySet:bd->SharedMetalContext.residencySet];
|
||||
|
||||
MTLDepthStencilDescriptor* depthStencilDescriptor = [[MTLDepthStencilDescriptor alloc] init];
|
||||
depthStencilDescriptor.depthWriteEnabled = NO;
|
||||
depthStencilDescriptor.depthCompareFunction = MTLCompareFunctionAlways;
|
||||
bd->SharedMetalContext.depthStencilState = [device newDepthStencilStateWithDescriptor:depthStencilDescriptor];
|
||||
MTLSamplerDescriptor* samplerDescriptor = [[MTLSamplerDescriptor alloc] init];
|
||||
samplerDescriptor.supportArgumentBuffers = YES;
|
||||
samplerDescriptor.minFilter = MTLSamplerMinMagFilterLinear;
|
||||
samplerDescriptor.magFilter = MTLSamplerMinMagFilterLinear;
|
||||
samplerDescriptor.mipFilter = MTLSamplerMipFilterLinear;
|
||||
bd->SharedMetalContext.samplerStateLinear = [device newSamplerStateWithDescriptor:samplerDescriptor];
|
||||
samplerDescriptor.minFilter = MTLSamplerMinMagFilterNearest;
|
||||
samplerDescriptor.magFilter = MTLSamplerMinMagFilterNearest;
|
||||
samplerDescriptor.mipFilter = MTLSamplerMipFilterNearest;
|
||||
bd->SharedMetalContext.samplerStateNearest = [device newSamplerStateWithDescriptor:samplerDescriptor];
|
||||
|
||||
NSMutableArray<id<MTLBuffer>>* constantBuffers = [NSMutableArray array];
|
||||
ImGui_Metal4_ConstantData** constantBufferContentsArray = (ImGui_Metal4_ConstantData**)malloc(sizeof(ImGui_Metal4_ConstantData*) * bd->SharedMetalContext.framesInFlight);
|
||||
for (NSUInteger i = 0; i < bd->SharedMetalContext.framesInFlight; i++)
|
||||
{
|
||||
id<MTLBuffer> constantBuffer = [device newBufferWithLength:sizeof(ImGui_Metal4_ConstantData) options:MTLResourceStorageModeShared];
|
||||
[constantBuffers addObject:constantBuffer];
|
||||
constantBufferContentsArray[i] = (ImGui_Metal4_ConstantData*)constantBuffer.contents;
|
||||
[bd->SharedMetalContext.residencySet addAllocation:constantBuffer];
|
||||
}
|
||||
bd->SharedMetalContext.constantBuffers = constantBuffers;
|
||||
bd->SharedMetalContext.constantBufferContentsArray = constantBufferContentsArray;
|
||||
|
||||
MTL4ArgumentTableDescriptor* argumentTableDescriptor = [[MTL4ArgumentTableDescriptor alloc] init];
|
||||
argumentTableDescriptor.maxBufferBindCount = 8;
|
||||
argumentTableDescriptor.maxTextureBindCount = 8;
|
||||
argumentTableDescriptor.maxSamplerStateBindCount = 8;
|
||||
argumentTableDescriptor.supportAttributeStrides = YES; // required: vertex buffer is bound via setAddress:stride:atIndex: for stage_in fetch
|
||||
|
||||
bd->SharedMetalContext.argumentTable = [device newArgumentTableWithDescriptor:argumentTableDescriptor error:&error];
|
||||
IM_ASSERT(bd->SharedMetalContext.argumentTable != nil && error == nil);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplMetal4_DestroyDeviceObjects()
|
||||
{
|
||||
ImGui_ImplMetal4_Data* bd = ImGui_ImplMetal4_GetBackendData();
|
||||
|
||||
// Destroy all textures
|
||||
for (ImTextureData* tex : ImGui::GetPlatformIO().Textures)
|
||||
if (tex->RefCount == 1)
|
||||
ImGui_ImplMetal4_DestroyTexture(tex);
|
||||
|
||||
[bd->SharedMetalContext.renderPipelineStateCache removeAllObjects];
|
||||
bd->SharedMetalContext.samplerStateLinear = nil;
|
||||
bd->SharedMetalContext.samplerStateNearest = nil;
|
||||
}
|
||||
|
||||
bool ImGui_ImplMetal4_Init(id<MTLDevice> device, id<MTL4CommandQueue> commandQueue, int framesInFlight)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IMGUI_CHECKVERSION();
|
||||
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
|
||||
IM_ASSERT(framesInFlight > 0 && "framesInFlight must be at least 1!");
|
||||
|
||||
ImGui_ImplMetal4_Data* bd = IM_NEW(ImGui_ImplMetal4_Data)();
|
||||
io.BackendRendererUserData = (void*)bd;
|
||||
io.BackendRendererName = "imgui_impl_metal4";
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
|
||||
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
platform_io.DrawCallback_ResetRenderState = ImGui_ImplMetal4_DrawCallback_ResetRenderState;
|
||||
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplMetal4_DrawCallback_SetSamplerLinear;
|
||||
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplMetal4_DrawCallback_SetSamplerNearest;
|
||||
|
||||
bd->SharedMetalContext = [[MetalContext alloc] init];
|
||||
bd->SharedMetalContext.device = device;
|
||||
bd->SharedMetalContext.commandQueue = commandQueue;
|
||||
bd->SharedMetalContext.framesInFlight = (NSUInteger)framesInFlight;
|
||||
NSMutableArray<NSMutableArray<MetalBuffer*>*>* bufferCaches = [NSMutableArray array];
|
||||
for (NSUInteger i = 0; i < framesInFlight; i++)
|
||||
[bufferCaches addObject:[NSMutableArray array]];
|
||||
bd->SharedMetalContext.bufferCaches = bufferCaches;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplMetal4_Shutdown()
|
||||
{
|
||||
ImGui_ImplMetal4_Data* bd = ImGui_ImplMetal4_GetBackendData();
|
||||
IM_UNUSED(bd);
|
||||
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
|
||||
ImGui_ImplMetal4_DestroyDeviceObjects();
|
||||
ImGui_ImplMetal4_DestroyBackendData();
|
||||
|
||||
io.BackendRendererName = nullptr;
|
||||
io.BackendRendererUserData = nullptr;
|
||||
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasVtxOffset | ImGuiBackendFlags_RendererHasTextures);
|
||||
platform_io.ClearRendererHandlers();
|
||||
}
|
||||
|
||||
@implementation MetalBuffer
|
||||
- (instancetype)initWithBuffer:(id<MTLBuffer>)buffer
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
_buffer = buffer;
|
||||
_lastReuseTime = GetMachAbsoluteTimeInSeconds();
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@end
|
||||
|
||||
#pragma mark - FramebufferDescriptor implementation
|
||||
|
||||
@implementation FramebufferDescriptor
|
||||
- (instancetype)initWithRenderPassDescriptor:(MTL4RenderPassDescriptor*)renderPassDescriptor
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
_sampleCount = renderPassDescriptor.colorAttachments[0].texture.sampleCount;
|
||||
_colorPixelFormat = renderPassDescriptor.colorAttachments[0].texture.pixelFormat;
|
||||
_depthPixelFormat = renderPassDescriptor.depthAttachment.texture.pixelFormat;
|
||||
_stencilPixelFormat = renderPassDescriptor.stencilAttachment.texture.pixelFormat;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (nonnull id)copyWithZone:(nullable NSZone*)zone
|
||||
{
|
||||
FramebufferDescriptor* copy = [[FramebufferDescriptor allocWithZone:zone] init];
|
||||
copy.sampleCount = self.sampleCount;
|
||||
copy.colorPixelFormat = self.colorPixelFormat;
|
||||
copy.depthPixelFormat = self.depthPixelFormat;
|
||||
copy.stencilPixelFormat = self.stencilPixelFormat;
|
||||
return copy;
|
||||
}
|
||||
|
||||
- (NSUInteger)hash
|
||||
{
|
||||
NSUInteger sc = _sampleCount & 0x3;
|
||||
NSUInteger cf = _colorPixelFormat & 0x3FF;
|
||||
NSUInteger df = _depthPixelFormat & 0x3FF;
|
||||
NSUInteger sf = _stencilPixelFormat & 0x3FF;
|
||||
NSUInteger hash = (sf << 22) | (df << 12) | (cf << 2) | sc;
|
||||
return hash;
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)object
|
||||
{
|
||||
FramebufferDescriptor* other = object;
|
||||
if (![other isKindOfClass:[FramebufferDescriptor class]])
|
||||
return NO;
|
||||
return other.sampleCount == self.sampleCount &&
|
||||
other.colorPixelFormat == self.colorPixelFormat &&
|
||||
other.depthPixelFormat == self.depthPixelFormat &&
|
||||
other.stencilPixelFormat == self.stencilPixelFormat;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark - MetalTexture implementation
|
||||
|
||||
@implementation MetalTexture
|
||||
- (instancetype)initWithTexture:(id<MTLTexture>)metalTexture
|
||||
{
|
||||
if ((self = [super init]))
|
||||
self.metalTexture = metalTexture;
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark - MetalContext implementation
|
||||
|
||||
@implementation MetalContext
|
||||
- (instancetype)init
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
self.renderPipelineStateCache = [NSMutableDictionary dictionary];
|
||||
self.bufferCacheLock = [[NSObject alloc] init];
|
||||
_lastBufferCachePurge = GetMachAbsoluteTimeInSeconds();
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
free(_constantBufferContentsArray);
|
||||
}
|
||||
|
||||
- (id<MTLBuffer>)currentConstantBuffer
|
||||
{
|
||||
return self.constantBuffers[self.currentFrameSlot];
|
||||
}
|
||||
|
||||
- (ImGui_Metal4_ConstantData*)currentConstantBufferContents
|
||||
{
|
||||
return self.constantBufferContentsArray[self.currentFrameSlot];
|
||||
}
|
||||
|
||||
- (MetalBuffer*)dequeueReusableBufferOfLength:(NSUInteger)length device:(id<MTLDevice>)device
|
||||
{
|
||||
double now = GetMachAbsoluteTimeInSeconds();
|
||||
NSMutableArray<MetalBuffer*>* slotCache = self.bufferCaches[self.currentFrameSlot];
|
||||
|
||||
@synchronized(self.bufferCacheLock)
|
||||
{
|
||||
// Purge old buffers that haven't been useful for a while
|
||||
if (now - self.lastBufferCachePurge > 1.0)
|
||||
{
|
||||
for (NSMutableArray<MetalBuffer*>* cache in self.bufferCaches)
|
||||
{
|
||||
NSMutableArray* survivors = [NSMutableArray array];
|
||||
for (MetalBuffer* candidate in cache)
|
||||
if (candidate.lastReuseTime > self.lastBufferCachePurge)
|
||||
[survivors addObject:candidate];
|
||||
[cache setArray:survivors];
|
||||
}
|
||||
self.lastBufferCachePurge = now;
|
||||
}
|
||||
|
||||
// See if we have a buffer we can reuse, from this frame-in-flight slot's own cache
|
||||
MetalBuffer* bestCandidate = nil;
|
||||
for (MetalBuffer* candidate in slotCache)
|
||||
if (candidate.buffer.length >= length && (bestCandidate == nil || bestCandidate.lastReuseTime > candidate.lastReuseTime))
|
||||
bestCandidate = candidate;
|
||||
|
||||
if (bestCandidate != nil)
|
||||
{
|
||||
[slotCache removeObject:bestCandidate];
|
||||
bestCandidate.lastReuseTime = now;
|
||||
return bestCandidate;
|
||||
}
|
||||
}
|
||||
|
||||
// No luck; make a new buffer
|
||||
id<MTLBuffer> backing = [device newBufferWithLength:length options:MTLResourceStorageModeShared];
|
||||
[self.residencySet addAllocation:backing];
|
||||
return [[MetalBuffer alloc] initWithBuffer:backing];
|
||||
}
|
||||
|
||||
const char* shaderCode = R"(
|
||||
#include <metal_stdlib>
|
||||
using namespace metal;
|
||||
|
||||
struct Uniforms {
|
||||
float4x4 projectionMatrix;
|
||||
};
|
||||
|
||||
struct VertexIn {
|
||||
float2 position [[attribute(0)]];
|
||||
float2 texCoords [[attribute(1)]];
|
||||
uchar4 color [[attribute(2)]];
|
||||
};
|
||||
|
||||
struct VertexOut {
|
||||
float4 position [[position]];
|
||||
float2 texCoords;
|
||||
float4 color;
|
||||
};
|
||||
|
||||
vertex VertexOut vertex_main(VertexIn in [[stage_in]],
|
||||
constant Uniforms &uniforms [[buffer(1)]])
|
||||
{
|
||||
VertexOut out;
|
||||
out.position = uniforms.projectionMatrix * float4(in.position, 0, 1);
|
||||
out.texCoords = in.texCoords;
|
||||
out.color = float4(in.color) / float4(255.0);
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment half4 fragment_main(VertexOut in [[stage_in]],
|
||||
texture2d<half, access::sample> texture [[texture(0)]],
|
||||
sampler textureSampler [[sampler(0)]])
|
||||
{
|
||||
half4 texColor = texture.sample(textureSampler, in.texCoords);
|
||||
return half4(in.color) * texColor;
|
||||
}
|
||||
)";
|
||||
|
||||
- (id<MTLRenderPipelineState>)renderPipelineStateForFramebufferDescriptor:(FramebufferDescriptor*)descriptor device:(id<MTLDevice>)device
|
||||
{
|
||||
NSError* error = nil;
|
||||
|
||||
id<MTLLibrary> library = [device newLibraryWithSource:[NSString stringWithUTF8String:shaderCode] options:nil error:&error];
|
||||
if (library == nil)
|
||||
{
|
||||
NSLog(@"Error: failed to create Metal library: %@", error);
|
||||
return nil;
|
||||
}
|
||||
|
||||
id<MTLFunction> vertexFunction = [library newFunctionWithName:@"vertex_main"];
|
||||
id<MTLFunction> fragmentFunction = [library newFunctionWithName:@"fragment_main"];
|
||||
|
||||
if (vertexFunction == nil || fragmentFunction == nil)
|
||||
{
|
||||
NSLog(@"Error: failed to find Metal shader functions in library: %@", error);
|
||||
return nil;
|
||||
}
|
||||
|
||||
MTLVertexDescriptor* vertexDescriptor = [MTLVertexDescriptor vertexDescriptor];
|
||||
vertexDescriptor.attributes[0].offset = offsetof(ImDrawVert, pos);
|
||||
vertexDescriptor.attributes[0].format = MTLVertexFormatFloat2; // position
|
||||
vertexDescriptor.attributes[0].bufferIndex = 0;
|
||||
vertexDescriptor.attributes[1].offset = offsetof(ImDrawVert, uv);
|
||||
vertexDescriptor.attributes[1].format = MTLVertexFormatFloat2; // texCoords
|
||||
vertexDescriptor.attributes[1].bufferIndex = 0;
|
||||
vertexDescriptor.attributes[2].offset = offsetof(ImDrawVert, col);
|
||||
vertexDescriptor.attributes[2].format = MTLVertexFormatUChar4; // color
|
||||
vertexDescriptor.attributes[2].bufferIndex = 0;
|
||||
vertexDescriptor.layouts[0].stepRate = 1;
|
||||
vertexDescriptor.layouts[0].stepFunction = MTLVertexStepFunctionPerVertex;
|
||||
vertexDescriptor.layouts[0].stride = sizeof(ImDrawVert);
|
||||
|
||||
MTLRenderPipelineDescriptor* pipelineDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
|
||||
pipelineDescriptor.vertexFunction = vertexFunction;
|
||||
pipelineDescriptor.fragmentFunction = fragmentFunction;
|
||||
pipelineDescriptor.vertexDescriptor = vertexDescriptor;
|
||||
pipelineDescriptor.rasterSampleCount = self.framebufferDescriptor.sampleCount;
|
||||
pipelineDescriptor.colorAttachments[0].pixelFormat = self.framebufferDescriptor.colorPixelFormat;
|
||||
pipelineDescriptor.colorAttachments[0].blendingEnabled = YES;
|
||||
pipelineDescriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd;
|
||||
pipelineDescriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorSourceAlpha;
|
||||
pipelineDescriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
|
||||
pipelineDescriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd;
|
||||
pipelineDescriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorOne;
|
||||
pipelineDescriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
|
||||
pipelineDescriptor.depthAttachmentPixelFormat = self.framebufferDescriptor.depthPixelFormat;
|
||||
pipelineDescriptor.stencilAttachmentPixelFormat = self.framebufferDescriptor.stencilPixelFormat;
|
||||
|
||||
id<MTLRenderPipelineState> renderPipelineState = [device newRenderPipelineStateWithDescriptor:pipelineDescriptor error:&error];
|
||||
if (error != nil)
|
||||
NSLog(@"Error: failed to create Metal pipeline state: %@", error);
|
||||
|
||||
return renderPipelineState;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
|
@ -26,6 +26,9 @@
|
|||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-09-17: OpenGL: Added support for platform_io.DrawCallback_SetSamplerFromTex. (#9378)
|
||||
// 2026-09-07: OpenGL: Round framebuffer dimensions to the nearest integer instead of truncating them. (#9538, 9515, #8628)
|
||||
// 2026-07-15: OpenGL: Backup and restore GL_UNPACK_ROW_LENGTH and GL_UNPACK_ALIGNMENT in UpdateTexture() to avoid corrupting caller GL state. (#8802, #9473)
|
||||
// 2026-04-23: OpenGL: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)
|
||||
// 2026-03-12: OpenGL: Fixed invalid assert in ImGui_ImplOpenGL3_UpdateTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295)
|
||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
||||
|
|
@ -130,6 +133,8 @@ static void ImGui_ImplOpenGL2_SetupRenderState(ImDrawData* draw_data, int fb_wid
|
|||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
glShadeModel(GL_SMOOTH);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
|
||||
bd->UseTexParameterToSetSampler = false;
|
||||
bd->NextSampler = GL_LINEAR;
|
||||
|
||||
// If you are using this code with non-legacy OpenGL header/contexts (which you should not, prefer using imgui_impl_opengl3.cpp!!),
|
||||
|
|
@ -156,9 +161,13 @@ static void ImGui_ImplOpenGL2_SetupRenderState(ImDrawData* draw_data, int fb_wid
|
|||
}
|
||||
|
||||
// Draw callbacks
|
||||
static void ImGui_ImplOpenGL2_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
|
||||
static void ImGui_ImplOpenGL2_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData(); bd->UseTexParameterToSetSampler = true; bd->NextSampler = GL_LINEAR; }
|
||||
static void ImGui_ImplOpenGL2_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData(); bd->UseTexParameterToSetSampler = true; bd->NextSampler = GL_NEAREST; }
|
||||
// - IMPORTANT: Using DrawCallback_SetSamplerLinear/DrawCallback_SetSamplerNearest will trash glTexParameteri() values for the texture!!
|
||||
// We cannot decently backup/restore that state because glGetTexParameteriv() is slow on many setups.
|
||||
// - Using DrawCallback_SetSamplerFromTex will basically instruct the backend to use existing glTexParameteri() values without modifying anything, which is the initial state.
|
||||
static void ImGui_ImplOpenGL2_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
|
||||
static void ImGui_ImplOpenGL2_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData(); bd->UseTexParameterToSetSampler = true; bd->NextSampler = GL_LINEAR; }
|
||||
static void ImGui_ImplOpenGL2_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData(); bd->UseTexParameterToSetSampler = true; bd->NextSampler = GL_NEAREST; }
|
||||
static void ImGui_ImplOpenGL2_DrawCallback_SetSamplerFromTex(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData(); bd->UseTexParameterToSetSampler = false; }
|
||||
|
||||
// OpenGL2 Render function.
|
||||
// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly.
|
||||
|
|
@ -167,8 +176,8 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
|
|||
{
|
||||
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
||||
ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData();
|
||||
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
|
||||
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
|
||||
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
|
||||
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
|
||||
if (fb_width == 0 || fb_height == 0)
|
||||
return;
|
||||
|
||||
|
|
@ -262,6 +271,10 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
|
|||
|
||||
void ImGui_ImplOpenGL2_UpdateTexture(ImTextureData* tex)
|
||||
{
|
||||
// Backup GL_UNPACK state that we modify, restore on exit.
|
||||
GLint last_unpack_row_length = 0; GL_CALL(glGetIntegerv(GL_UNPACK_ROW_LENGTH, &last_unpack_row_length));
|
||||
GLint last_unpack_alignment = 0; GL_CALL(glGetIntegerv(GL_UNPACK_ALIGNMENT, &last_unpack_alignment));
|
||||
|
||||
if (tex->Status == ImTextureStatus_WantCreate)
|
||||
{
|
||||
// Create and upload new texture to graphics system
|
||||
|
|
@ -271,8 +284,7 @@ void ImGui_ImplOpenGL2_UpdateTexture(ImTextureData* tex)
|
|||
const void* pixels = tex->GetPixels();
|
||||
GLuint gl_texture_id = 0;
|
||||
|
||||
// Upload texture to graphics system
|
||||
// (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
|
||||
// Upload texture to graphics system (bilinear sampling is required).
|
||||
GLint last_texture;
|
||||
GL_CALL(glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture));
|
||||
GL_CALL(glGenTextures(1, &gl_texture_id));
|
||||
|
|
@ -318,6 +330,10 @@ void ImGui_ImplOpenGL2_UpdateTexture(ImTextureData* tex)
|
|||
tex->SetTexID(ImTextureID_Invalid);
|
||||
tex->SetStatus(ImTextureStatus_Destroyed);
|
||||
}
|
||||
|
||||
// Restore GL_UNPACK state
|
||||
GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, last_unpack_row_length));
|
||||
GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, last_unpack_alignment));
|
||||
}
|
||||
|
||||
bool ImGui_ImplOpenGL2_CreateDeviceObjects()
|
||||
|
|
@ -351,6 +367,7 @@ bool ImGui_ImplOpenGL2_Init()
|
|||
platform_io.DrawCallback_ResetRenderState = ImGui_ImplOpenGL2_DrawCallback_ResetRenderState;
|
||||
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplOpenGL2_DrawCallback_SetSamplerLinear;
|
||||
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplOpenGL2_DrawCallback_SetSamplerNearest;
|
||||
platform_io.DrawCallback_SetSamplerFromTex = ImGui_ImplOpenGL2_DrawCallback_SetSamplerFromTex;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
// [x] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset) [Desktop OpenGL only!]
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access with ImGui_ImplOpenGL3_GetRenderState().
|
||||
|
||||
// About WebGL/ES:
|
||||
// - You need to '#define IMGUI_IMPL_OPENGL_ES2' or '#define IMGUI_IMPL_OPENGL_ES3' to use WebGL or OpenGL ES.
|
||||
|
|
@ -23,7 +24,13 @@
|
|||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-09-17: OpenGL: Added support for platform_io.DrawCallback_SetSamplerFromTex. (#9378)
|
||||
// 2026-09-07: OpenGL: Round framebuffer dimensions to the nearest integer instead of truncating them. (#9538, 9515, #8628)
|
||||
// 2026-07-15: OpenGL: Backup and restore GL_UNPACK_ROW_LENGTH and GL_UNPACK_ALIGNMENT in UpdateTexture() to avoid corrupting caller GL state. (#8802, #9473)
|
||||
// 2026-06-17: OpenGL: Expose selected render state in ImGui_ImplOpenGL3_RenderState, Allowing to dynamically select between use of glBindSampler() and glTexParameter(). You can access in 'void* platform_io.Renderer_RenderState' during rendering.
|
||||
// 2026-06-03: OpenGL: GLSL version detection assume GLSL 410 when GL context is 4.1. Fixes an issue running on macOS with Wine. (#9427, #6577)
|
||||
// 2026-04-23: OpenGL: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)
|
||||
// (Breaking): this change prioritize using glBindSampler() when available, which would override glTexParameter() settings you may have set on custom textures.
|
||||
// 2026-03-12: OpenGL: Fixed invalid assert in ImGui_ImplOpenGL3_UpdateTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295)
|
||||
// 2025-12-11: OpenGL: Fixed embedded loader multiple init/shutdown cycles broken on some platforms. (#8792, #9112)
|
||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
||||
|
|
@ -253,8 +260,6 @@ struct ImGui_ImplOpenGL3_Data
|
|||
bool HasBindSampler;
|
||||
bool HasClipOrigin;
|
||||
bool UseBufferSubData;
|
||||
bool UseTexParameterToSetSampler;
|
||||
GLuint NextSampler; // Used if !HasBindSampler && UseTexParameterToSetSampler.
|
||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
|
||||
GLuint TexSamplers[2]; // Used if HasBindSimpler. (0=linear, 1=nearest)
|
||||
#endif
|
||||
|
|
@ -271,6 +276,11 @@ static ImGui_ImplOpenGL3_Data* ImGui_ImplOpenGL3_GetBackendData()
|
|||
return ImGui::GetCurrentContext() ? (ImGui_ImplOpenGL3_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
|
||||
}
|
||||
|
||||
ImGui_ImplOpenGL3_RenderState* ImGui_ImplOpenGL3_GetRenderState()
|
||||
{
|
||||
return (ImGui_ImplOpenGL3_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState;
|
||||
}
|
||||
|
||||
// OpenGL vertex attribute state (for ES 1.0 and ES 2.0 only)
|
||||
#ifndef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
|
||||
struct ImGui_ImplOpenGL3_VtxAttribState
|
||||
|
|
@ -330,7 +340,7 @@ void ImGui_ImplOpenGL3_NewFrame()
|
|||
IM_ASSERT(0 && "ImGui_ImplOpenGL3_CreateDeviceObjects() failed!");
|
||||
}
|
||||
|
||||
static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height, GLuint vertex_array_object)
|
||||
static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, ImGui_ImplOpenGL3_RenderState* render_state, int fb_width, int fb_height, GLuint vertex_array_object)
|
||||
{
|
||||
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
|
||||
|
||||
|
|
@ -383,9 +393,16 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
|
|||
glUniform1i(bd->AttribLocationTex, 0);
|
||||
glUniformMatrix4fv(bd->AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
|
||||
|
||||
render_state->UseBindSampler = bd->HasBindSampler;
|
||||
render_state->UseTexParameterFilter = false;
|
||||
render_state->CurrentSampler = 0;
|
||||
render_state->CurrentTexParameterFilter = 0;
|
||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
|
||||
if (bd->HasBindSampler)
|
||||
glBindSampler(0, bd->TexSamplers[0]); // We use combined texture/sampler state. Applications using GL 3.3 and GL ES 3.0 may set that otherwise.
|
||||
if (bd->HasBindSampler && render_state->UseBindSampler)
|
||||
{
|
||||
render_state->CurrentSampler = bd->TexSamplers[0];
|
||||
glBindSampler(0, render_state->CurrentSampler); // We use combined texture/sampler state. Applications using GL 3.3 and GL ES 3.0 may set that otherwise.
|
||||
}
|
||||
#endif
|
||||
|
||||
(void)vertex_array_object;
|
||||
|
|
@ -404,15 +421,47 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
|
|||
GL_CALL(glVertexAttribPointer(bd->AttribLocationVtxColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)offsetof(ImDrawVert, col)));
|
||||
}
|
||||
|
||||
// Draw callbacks
|
||||
static void ImGui_ImplOpenGL3_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
|
||||
static void ImGui_ImplOpenGL3_DrawCallback_SetSampler(unsigned int sampler_idx, unsigned int tex_parameter_filter)
|
||||
{
|
||||
ImGui_ImplOpenGL3_RenderState* render_state = ImGui_ImplOpenGL3_GetRenderState();
|
||||
IM_UNUSED(sampler_idx);
|
||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
|
||||
static void ImGui_ImplOpenGL3_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); if (bd->HasBindSampler) { glBindSampler(0, bd->TexSamplers[0]); } else { bd->UseTexParameterToSetSampler = true; bd->NextSampler = GL_LINEAR; } }
|
||||
static void ImGui_ImplOpenGL3_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); if (bd->HasBindSampler) { glBindSampler(0, bd->TexSamplers[1]); } else { bd->UseTexParameterToSetSampler = true; bd->NextSampler = GL_NEAREST; } }
|
||||
#else
|
||||
static void ImGui_ImplOpenGL3_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); bd->UseTexParameterToSetSampler = true; bd->NextSampler = GL_LINEAR; }
|
||||
static void ImGui_ImplOpenGL3_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); bd->UseTexParameterToSetSampler = true; bd->NextSampler = GL_NEAREST; }
|
||||
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
|
||||
if (bd->HasBindSampler && render_state->UseBindSampler)
|
||||
{
|
||||
render_state->CurrentSampler = bd->TexSamplers[sampler_idx];
|
||||
render_state->UseTexParameterFilter = false;
|
||||
glBindSampler(0, render_state->CurrentSampler);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
render_state->UseTexParameterFilter = true;
|
||||
render_state->CurrentTexParameterFilter = tex_parameter_filter;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw callbacks
|
||||
// - IMPORTANT: Using DrawCallback_SetSamplerLinear/DrawCallback_SetSamplerNearest will trash glTexParameteri() values for the texture if used on a GL context not supporting glBindSampler()!!
|
||||
// We cannot decently backup/restore that state because glGetTexParameteriv() is slow on many setups.
|
||||
// - Using DrawCallback_SetSamplerFromTex will basically instruct the backend to use existing glTexParameteri() values without modifying anything.
|
||||
static void ImGui_ImplOpenGL3_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
|
||||
static void ImGui_ImplOpenGL3_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplOpenGL3_DrawCallback_SetSampler(0, GL_LINEAR); }
|
||||
static void ImGui_ImplOpenGL3_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplOpenGL3_DrawCallback_SetSampler(1, GL_NEAREST); }
|
||||
static void ImGui_ImplOpenGL3_DrawCallback_SetSamplerFromTex(const ImDrawList*, const ImDrawCmd*)
|
||||
{
|
||||
ImGui_ImplOpenGL3_RenderState* render_state = ImGui_ImplOpenGL3_GetRenderState();
|
||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
|
||||
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
|
||||
if (bd->HasBindSampler)
|
||||
{
|
||||
render_state->CurrentSampler = 0;
|
||||
glBindSampler(0, 0);
|
||||
}
|
||||
#endif
|
||||
render_state->UseBindSampler = false;
|
||||
render_state->UseTexParameterFilter = false;
|
||||
}
|
||||
|
||||
// OpenGL3 Render function.
|
||||
// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly.
|
||||
|
|
@ -420,8 +469,8 @@ static void ImGui_ImplOpenGL3_DrawCallback_SetSamplerNearest(const ImDrawList*,
|
|||
void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
||||
{
|
||||
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
||||
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
|
||||
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
|
||||
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
|
||||
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
|
||||
if (fb_width <= 0 || fb_height <= 0)
|
||||
return;
|
||||
|
||||
|
|
@ -482,7 +531,13 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
|||
#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
|
||||
GL_CALL(glGenVertexArrays(1, &vertex_array_object));
|
||||
#endif
|
||||
ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object);
|
||||
|
||||
// Setup render state structure (for callbacks and custom texture bindings)
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
ImGui_ImplOpenGL3_RenderState render_state = {};
|
||||
platform_io.Renderer_RenderState = &render_state;
|
||||
|
||||
ImGui_ImplOpenGL3_SetupRenderState(draw_data, &render_state, fb_width, fb_height, vertex_array_object);
|
||||
|
||||
// Will project scissor/clipping rectangles into framebuffer space
|
||||
ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
|
||||
|
|
@ -529,7 +584,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
|||
{
|
||||
// User callback, registered via ImDrawList::AddCallback()
|
||||
if (pcmd->UserCallback == ImGui_ImplOpenGL3_DrawCallback_ResetRenderState)
|
||||
ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object);
|
||||
ImGui_ImplOpenGL3_SetupRenderState(draw_data, &render_state, fb_width, fb_height, vertex_array_object);
|
||||
else
|
||||
pcmd->UserCallback(draw_list, pcmd);
|
||||
}
|
||||
|
|
@ -548,11 +603,11 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
|||
GL_CALL(glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID()));
|
||||
|
||||
// Emulate sampler change (even though it is technically part of texture data)
|
||||
// As a sort of hack/workaround, we only start writing using glTextParameter() if sampler is ever changed explicitly.
|
||||
if (!bd->HasBindSampler && bd->UseTexParameterToSetSampler)
|
||||
// As a sort of hack/workaround, we only start writing using glTexParameter() if sampler is ever changed explicitly.
|
||||
if (render_state.UseTexParameterFilter)
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, bd->NextSampler);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, bd->NextSampler);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, render_state.CurrentTexParameterFilter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, render_state.CurrentTexParameterFilter);
|
||||
}
|
||||
|
||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET
|
||||
|
|
@ -564,6 +619,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
|||
}
|
||||
}
|
||||
}
|
||||
platform_io.Renderer_RenderState = nullptr;
|
||||
|
||||
// Destroy the temporary VAO
|
||||
#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
|
||||
|
|
@ -622,13 +678,15 @@ static void ImGui_ImplOpenGL3_DestroyTexture(ImTextureData* tex)
|
|||
|
||||
void ImGui_ImplOpenGL3_UpdateTexture(ImTextureData* tex)
|
||||
{
|
||||
// FIXME: Consider backing up and restoring
|
||||
if (tex->Status == ImTextureStatus_WantCreate || tex->Status == ImTextureStatus_WantUpdates)
|
||||
// Backup GL_UNPACK state that we modify, restore on exit.
|
||||
GLint last_unpack_row_length = 0; (void)last_unpack_row_length;
|
||||
GLint last_unpack_alignment = 0; (void)last_unpack_alignment;
|
||||
const bool last_unpack_state_save_and_restore = (tex->Status == ImTextureStatus_WantCreate || tex->Status == ImTextureStatus_WantUpdates);
|
||||
if (last_unpack_state_save_and_restore)
|
||||
{
|
||||
#ifdef GL_UNPACK_ROW_LENGTH // Not on WebGL/ES
|
||||
GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, 0));
|
||||
#endif
|
||||
#ifdef GL_UNPACK_ALIGNMENT
|
||||
GL_CALL(glGetIntegerv(GL_UNPACK_ROW_LENGTH, &last_unpack_row_length));
|
||||
GL_CALL(glGetIntegerv(GL_UNPACK_ALIGNMENT, &last_unpack_alignment));
|
||||
GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
|
||||
#endif
|
||||
}
|
||||
|
|
@ -642,8 +700,7 @@ void ImGui_ImplOpenGL3_UpdateTexture(ImTextureData* tex)
|
|||
const void* pixels = tex->GetPixels();
|
||||
GLuint gl_texture_id = 0;
|
||||
|
||||
// Upload texture to graphics system
|
||||
// (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
|
||||
// Upload texture to graphics system (bilinear sampling is required).
|
||||
GLint last_texture;
|
||||
GL_CALL(glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture));
|
||||
GL_CALL(glGenTextures(1, &gl_texture_id));
|
||||
|
|
@ -652,6 +709,9 @@ void ImGui_ImplOpenGL3_UpdateTexture(ImTextureData* tex)
|
|||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
|
||||
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
|
||||
#if GL_UNPACK_ROW_LENGTH // Not on WebGL/ES
|
||||
GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, 0));
|
||||
#endif
|
||||
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex->Width, tex->Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
|
||||
|
||||
// Store identifiers
|
||||
|
|
@ -674,7 +734,6 @@ void ImGui_ImplOpenGL3_UpdateTexture(ImTextureData* tex)
|
|||
GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, tex->Width));
|
||||
for (ImTextureRect& r : tex->Updates)
|
||||
GL_CALL(glTexSubImage2D(GL_TEXTURE_2D, 0, r.x, r.y, r.w, r.h, GL_RGBA, GL_UNSIGNED_BYTE, tex->GetPixelsAt(r.x, r.y)));
|
||||
GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, 0));
|
||||
#else
|
||||
// GL ES doesn't have GL_UNPACK_ROW_LENGTH, so we need to (A) copy to a contiguous buffer or (B) upload line by line.
|
||||
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
|
||||
|
|
@ -694,6 +753,15 @@ void ImGui_ImplOpenGL3_UpdateTexture(ImTextureData* tex)
|
|||
}
|
||||
else if (tex->Status == ImTextureStatus_WantDestroy && tex->UnusedFrames > 0)
|
||||
ImGui_ImplOpenGL3_DestroyTexture(tex);
|
||||
|
||||
// Restore GL_UNPACK state
|
||||
if (last_unpack_state_save_and_restore)
|
||||
{
|
||||
#ifdef GL_UNPACK_ROW_LENGTH
|
||||
GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, last_unpack_row_length));
|
||||
GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, last_unpack_alignment));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// If you get an error please report on github. You may try different GL context version or GLSL version. See GL<>GLSL version table at the top of this file.
|
||||
|
|
@ -1036,6 +1104,7 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
|
|||
platform_io.DrawCallback_ResetRenderState = ImGui_ImplOpenGL3_DrawCallback_ResetRenderState;
|
||||
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplOpenGL3_DrawCallback_SetSamplerLinear;
|
||||
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplOpenGL3_DrawCallback_SetSamplerNearest;
|
||||
platform_io.DrawCallback_SetSamplerFromTex = ImGui_ImplOpenGL3_DrawCallback_SetSamplerFromTex;
|
||||
|
||||
// Store GLSL version string so we can refer to it later in case we recreate shaders.
|
||||
// Note: GLSL version is NOT the same as GL version. Leave this to nullptr if unsure.
|
||||
|
|
@ -1048,7 +1117,10 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
|
|||
#elif defined(__APPLE__)
|
||||
glsl_version = "#version 150";
|
||||
#else
|
||||
glsl_version = "#version 130";
|
||||
if (bd->GlVersion >= 410)
|
||||
glsl_version = "#version 410";
|
||||
else
|
||||
glsl_version = "#version 130";
|
||||
#endif
|
||||
}
|
||||
IM_ASSERT((int)strlen(glsl_version) + 2 < IM_COUNTOF(bd->GlslVersionString));
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
// [x] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset) [Desktop OpenGL only!]
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access with ImGui_ImplOpenGL3_GetRenderState().
|
||||
|
||||
// About WebGL/ES:
|
||||
// - You need to '#define IMGUI_IMPL_OPENGL_ES2' or '#define IMGUI_IMPL_OPENGL_ES3' to use WebGL or OpenGL ES.
|
||||
|
|
@ -65,4 +66,16 @@ IMGUI_IMPL_API void ImGui_ImplOpenGL3_UpdateTexture(ImTextureData* tex);
|
|||
|
||||
#endif
|
||||
|
||||
// [BETA] Selected render state data shared with callbacks.
|
||||
// This is temporarily stored in GetPlatformIO().Renderer_RenderState during the ImGui_ImplOpenGL3_RenderDrawData() call.
|
||||
// (Please open an issue if you feel you need access to more data)
|
||||
struct ImGui_ImplOpenGL3_RenderState
|
||||
{
|
||||
bool UseBindSampler;
|
||||
bool UseTexParameterFilter;
|
||||
unsigned int CurrentSampler; // (GLuint) Used if UseBindSampler == true (and are available), otherwise always 0
|
||||
unsigned int CurrentTexParameterFilter; // (GLuint) Used if UseTexParameterFilter == true
|
||||
};
|
||||
IMGUI_IMPL_API ImGui_ImplOpenGL3_RenderState* ImGui_ImplOpenGL3_GetRenderState();
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ extern "C" {
|
|||
#define GLAPI extern
|
||||
#endif
|
||||
/* glcorearb.h is for use with OpenGL core profile implementations.
|
||||
** It should should be placed in the same directory as gl.h and
|
||||
** It should be placed in the same directory as gl.h and
|
||||
** included as <GL/glcorearb.h>.
|
||||
**
|
||||
** glcorearb.h includes only APIs in the latest OpenGL core profile
|
||||
|
|
|
|||
759
backends/imgui_impl_qnx.cpp
Normal file
759
backends/imgui_impl_qnx.cpp
Normal file
|
|
@ -0,0 +1,759 @@
|
|||
// dear imgui: Platform Backend for QNX Screen
|
||||
// This needs to be used along with a Renderer Backend (e.g. OpenGL3, Vulkan).
|
||||
|
||||
// Implemented features:
|
||||
// [X] Platform: Keyboard support. Uses io.AddKeyEvent() and native QNX key symbols.
|
||||
// [X] Platform: Mouse support. Handles position, three buttons and horizontal/vertical wheels.
|
||||
// [X] Platform: Touch support. Maps the first active touch contact to the primary mouse button.
|
||||
// [X] Platform: Focus and window-size updates.
|
||||
// Missing features or Issues:
|
||||
// [ ] Platform: Clipboard support.
|
||||
// [ ] Platform: Gamepad support.
|
||||
// [ ] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors).
|
||||
// [ ] Platform: Multi-viewport support.
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-08-04: Initial QNX Screen backend. (#9492)
|
||||
|
||||
#include "imgui.h"
|
||||
#ifndef IMGUI_DISABLE
|
||||
#include "imgui_impl_qnx.h"
|
||||
|
||||
#include <float.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <sys/keycodes.h>
|
||||
#include <time.h>
|
||||
|
||||
static unsigned int ImGui_ImplQNX_KeySymToUnicode(unsigned int keysym);
|
||||
|
||||
struct ImGui_ImplQNX_Data
|
||||
{
|
||||
screen_context_t Context;
|
||||
screen_window_t Window;
|
||||
uint64_t TimeNanoseconds;
|
||||
int MouseButtons;
|
||||
int ActiveTouchId;
|
||||
bool LeftSuper;
|
||||
bool RightSuper;
|
||||
|
||||
ImGui_ImplQNX_Data()
|
||||
{
|
||||
memset(this, 0, sizeof(*this));
|
||||
ActiveTouchId = -1;
|
||||
}
|
||||
};
|
||||
|
||||
static ImGui_ImplQNX_Data* ImGui_ImplQNX_GetBackendData()
|
||||
{
|
||||
return ImGui::GetCurrentContext() != nullptr ? (ImGui_ImplQNX_Data*)ImGui::GetIO().BackendPlatformUserData : nullptr;
|
||||
}
|
||||
|
||||
static uint64_t ImGui_ImplQNX_GetTimeNanoseconds()
|
||||
{
|
||||
struct timespec timestamp = {};
|
||||
if (clock_gettime(CLOCK_MONOTONIC, ×tamp) != 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return (uint64_t)timestamp.tv_sec * UINT64_C(1000000000) + (uint64_t)timestamp.tv_nsec;
|
||||
}
|
||||
|
||||
static ImGuiKey ImGui_ImplQNX_KeyCodeToImGuiKey(int key_code)
|
||||
{
|
||||
switch (key_code)
|
||||
{
|
||||
case KEYCODE_TAB: return ImGuiKey_Tab;
|
||||
case KEYCODE_LEFT: return ImGuiKey_LeftArrow;
|
||||
case KEYCODE_RIGHT: return ImGuiKey_RightArrow;
|
||||
case KEYCODE_UP: return ImGuiKey_UpArrow;
|
||||
case KEYCODE_DOWN: return ImGuiKey_DownArrow;
|
||||
case KEYCODE_PG_UP: return ImGuiKey_PageUp;
|
||||
case KEYCODE_PG_DOWN: return ImGuiKey_PageDown;
|
||||
case KEYCODE_HOME: return ImGuiKey_Home;
|
||||
case KEYCODE_END: return ImGuiKey_End;
|
||||
case KEYCODE_INSERT: return ImGuiKey_Insert;
|
||||
case KEYCODE_DELETE: return ImGuiKey_Delete;
|
||||
case KEYCODE_BACKSPACE: return ImGuiKey_Backspace;
|
||||
case KEYCODE_SPACE: return ImGuiKey_Space;
|
||||
case KEYCODE_RETURN: return ImGuiKey_Enter;
|
||||
case KEYCODE_ESCAPE: return ImGuiKey_Escape;
|
||||
case KEYCODE_APOSTROPHE: return ImGuiKey_Apostrophe;
|
||||
case KEYCODE_COMMA: return ImGuiKey_Comma;
|
||||
case KEYCODE_MINUS: return ImGuiKey_Minus;
|
||||
case KEYCODE_PERIOD: return ImGuiKey_Period;
|
||||
case KEYCODE_SLASH: return ImGuiKey_Slash;
|
||||
case KEYCODE_SEMICOLON: return ImGuiKey_Semicolon;
|
||||
case KEYCODE_EQUAL: return ImGuiKey_Equal;
|
||||
case KEYCODE_LEFT_BRACKET: return ImGuiKey_LeftBracket;
|
||||
case KEYCODE_BACK_SLASH: return ImGuiKey_Backslash;
|
||||
case KEYCODE_RIGHT_BRACKET: return ImGuiKey_RightBracket;
|
||||
case KEYCODE_GRAVE: return ImGuiKey_GraveAccent;
|
||||
case KEYCODE_CAPS_LOCK: return ImGuiKey_CapsLock;
|
||||
case KEYCODE_SCROLL_LOCK: return ImGuiKey_ScrollLock;
|
||||
case KEYCODE_NUM_LOCK: return ImGuiKey_NumLock;
|
||||
case KEYCODE_PRINT: return ImGuiKey_PrintScreen;
|
||||
case KEYCODE_PAUSE: return ImGuiKey_Pause;
|
||||
case KEYCODE_KP_DIVIDE: return ImGuiKey_KeypadDivide;
|
||||
case KEYCODE_KP_MULTIPLY: return ImGuiKey_KeypadMultiply;
|
||||
case KEYCODE_KP_MINUS: return ImGuiKey_KeypadSubtract;
|
||||
case KEYCODE_KP_PLUS: return ImGuiKey_KeypadAdd;
|
||||
case KEYCODE_KP_ENTER: return ImGuiKey_KeypadEnter;
|
||||
// QNX reports keypad digits by their navigation key-cap names.
|
||||
case KEYCODE_KP_INSERT: return ImGuiKey_Keypad0;
|
||||
case KEYCODE_KP_END: return ImGuiKey_Keypad1;
|
||||
case KEYCODE_KP_DOWN: return ImGuiKey_Keypad2;
|
||||
case KEYCODE_KP_PG_DOWN: return ImGuiKey_Keypad3;
|
||||
case KEYCODE_KP_LEFT: return ImGuiKey_Keypad4;
|
||||
case KEYCODE_KP_FIVE: return ImGuiKey_Keypad5;
|
||||
case KEYCODE_KP_RIGHT: return ImGuiKey_Keypad6;
|
||||
case KEYCODE_KP_HOME: return ImGuiKey_Keypad7;
|
||||
case KEYCODE_KP_UP: return ImGuiKey_Keypad8;
|
||||
case KEYCODE_KP_PG_UP: return ImGuiKey_Keypad9;
|
||||
case KEYCODE_KP_DELETE: return ImGuiKey_KeypadDecimal;
|
||||
case KEYCODE_LEFT_CTRL: return ImGuiKey_LeftCtrl;
|
||||
case KEYCODE_LEFT_SHIFT: return ImGuiKey_LeftShift;
|
||||
case KEYCODE_LEFT_ALT: return ImGuiKey_LeftAlt;
|
||||
case KEYCODE_RIGHT_CTRL: return ImGuiKey_RightCtrl;
|
||||
case KEYCODE_RIGHT_SHIFT: return ImGuiKey_RightShift;
|
||||
case KEYCODE_RIGHT_ALT: return ImGuiKey_RightAlt;
|
||||
case KEYCODE_LEFT_HYPER: return ImGuiKey_LeftSuper;
|
||||
case KEYCODE_RIGHT_HYPER: return ImGuiKey_RightSuper;
|
||||
case KEYCODE_MENU: return ImGuiKey_Menu;
|
||||
case KEYCODE_ZERO: return ImGuiKey_0;
|
||||
case KEYCODE_ONE: return ImGuiKey_1;
|
||||
case KEYCODE_TWO: return ImGuiKey_2;
|
||||
case KEYCODE_THREE: return ImGuiKey_3;
|
||||
case KEYCODE_FOUR: return ImGuiKey_4;
|
||||
case KEYCODE_FIVE: return ImGuiKey_5;
|
||||
case KEYCODE_SIX: return ImGuiKey_6;
|
||||
case KEYCODE_SEVEN: return ImGuiKey_7;
|
||||
case KEYCODE_EIGHT: return ImGuiKey_8;
|
||||
case KEYCODE_NINE: return ImGuiKey_9;
|
||||
case KEYCODE_A: return ImGuiKey_A;
|
||||
case KEYCODE_B: return ImGuiKey_B;
|
||||
case KEYCODE_C: return ImGuiKey_C;
|
||||
case KEYCODE_D: return ImGuiKey_D;
|
||||
case KEYCODE_E: return ImGuiKey_E;
|
||||
case KEYCODE_F: return ImGuiKey_F;
|
||||
case KEYCODE_G: return ImGuiKey_G;
|
||||
case KEYCODE_H: return ImGuiKey_H;
|
||||
case KEYCODE_I: return ImGuiKey_I;
|
||||
case KEYCODE_J: return ImGuiKey_J;
|
||||
case KEYCODE_K: return ImGuiKey_K;
|
||||
case KEYCODE_L: return ImGuiKey_L;
|
||||
case KEYCODE_M: return ImGuiKey_M;
|
||||
case KEYCODE_N: return ImGuiKey_N;
|
||||
case KEYCODE_O: return ImGuiKey_O;
|
||||
case KEYCODE_P: return ImGuiKey_P;
|
||||
case KEYCODE_Q: return ImGuiKey_Q;
|
||||
case KEYCODE_R: return ImGuiKey_R;
|
||||
case KEYCODE_S: return ImGuiKey_S;
|
||||
case KEYCODE_T: return ImGuiKey_T;
|
||||
case KEYCODE_U: return ImGuiKey_U;
|
||||
case KEYCODE_V: return ImGuiKey_V;
|
||||
case KEYCODE_W: return ImGuiKey_W;
|
||||
case KEYCODE_X: return ImGuiKey_X;
|
||||
case KEYCODE_Y: return ImGuiKey_Y;
|
||||
case KEYCODE_Z: return ImGuiKey_Z;
|
||||
case KEYCODE_F1: return ImGuiKey_F1;
|
||||
case KEYCODE_F2: return ImGuiKey_F2;
|
||||
case KEYCODE_F3: return ImGuiKey_F3;
|
||||
case KEYCODE_F4: return ImGuiKey_F4;
|
||||
case KEYCODE_F5: return ImGuiKey_F5;
|
||||
case KEYCODE_F6: return ImGuiKey_F6;
|
||||
case KEYCODE_F7: return ImGuiKey_F7;
|
||||
case KEYCODE_F8: return ImGuiKey_F8;
|
||||
case KEYCODE_F9: return ImGuiKey_F9;
|
||||
case KEYCODE_F10: return ImGuiKey_F10;
|
||||
case KEYCODE_F11: return ImGuiKey_F11;
|
||||
case KEYCODE_F12: return ImGuiKey_F12;
|
||||
default: return ImGuiKey_None;
|
||||
}
|
||||
}
|
||||
|
||||
static void ImGui_ImplQNX_UpdateKeyModifiers(ImGuiIO& io, ImGui_ImplQNX_Data* bd, int modifiers, ImGuiKey key, bool down)
|
||||
{
|
||||
// SCREEN_PROPERTY_MODIFIERS is the authoritative state for Shift/Ctrl/Alt.
|
||||
// Tracking those keys locally loses sticky modifiers and can become stale if
|
||||
// a key transition is consumed elsewhere. qterm uses this same Screen state.
|
||||
if (key == ImGuiKey_LeftSuper)
|
||||
{
|
||||
bd->LeftSuper = down;
|
||||
}
|
||||
else if (key == ImGuiKey_RightSuper)
|
||||
{
|
||||
bd->RightSuper = down;
|
||||
}
|
||||
|
||||
io.AddKeyEvent(ImGuiMod_Ctrl, (modifiers & KEYMOD_CTRL) != 0);
|
||||
io.AddKeyEvent(ImGuiMod_Shift, (modifiers & KEYMOD_SHIFT) != 0);
|
||||
io.AddKeyEvent(ImGuiMod_Alt, (modifiers & KEYMOD_ALT) != 0);
|
||||
io.AddKeyEvent(ImGuiMod_Super, bd->LeftSuper || bd->RightSuper);
|
||||
}
|
||||
|
||||
static void ImGui_ImplQNX_ClearModifierState(ImGuiIO& io, ImGui_ImplQNX_Data* bd)
|
||||
{
|
||||
bd->LeftSuper = false;
|
||||
bd->RightSuper = false;
|
||||
io.AddKeyEvent(ImGuiMod_Ctrl, false);
|
||||
io.AddKeyEvent(ImGuiMod_Shift, false);
|
||||
io.AddKeyEvent(ImGuiMod_Alt, false);
|
||||
io.AddKeyEvent(ImGuiMod_Super, false);
|
||||
}
|
||||
|
||||
static bool ImGui_ImplQNX_IsTextCodePoint(unsigned int code_point)
|
||||
{
|
||||
// At this point the QNX keysym has already been converted to Unicode.
|
||||
// Do not reject Unicode private-use characters: a user keymap may emit one.
|
||||
const bool surrogate = code_point >= 0xd800u && code_point <= 0xdfffu;
|
||||
const bool control = code_point < 0x20u || (code_point >= 0x7fu && code_point <= 0x9fu);
|
||||
return code_point <= IM_UNICODE_CODEPOINT_MAX && !surrogate && !control;
|
||||
}
|
||||
|
||||
static bool ImGui_ImplQNX_ProcessKeyboardEvent(ImGui_ImplQNX_Data* bd, screen_event_t event)
|
||||
{
|
||||
int flags = 0;
|
||||
int modifiers = 0;
|
||||
if (screen_get_event_property_iv(event, SCREEN_PROPERTY_FLAGS, &flags) != 0 ||
|
||||
screen_get_event_property_iv(event, SCREEN_PROPERTY_MODIFIERS, &modifiers) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// KEY_CAP is the unmodified key identity used for ImGuiKey events. SYM is
|
||||
// the layout/modifier-translated QNX keysym used for text input.
|
||||
int key_cap = 0;
|
||||
int key_sym = 0;
|
||||
int scan_code = 0;
|
||||
const bool cap_valid = (flags & SCREEN_FLAG_CAP_VALID) != 0;
|
||||
const bool sym_valid = (flags & SCREEN_FLAG_SYM_VALID) != 0;
|
||||
const bool scan_valid = (flags & SCREEN_FLAG_SCAN_VALID) != 0;
|
||||
const bool down = (flags & (SCREEN_FLAG_KEY_DOWN | SCREEN_FLAG_KEY_REPEAT)) != 0;
|
||||
|
||||
if (cap_valid && screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_CAP, &key_cap) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (sym_valid && screen_get_event_property_iv(event, SCREEN_PROPERTY_SYM, &key_sym) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (scan_valid && screen_get_event_property_iv(event, SCREEN_PROPERTY_SCAN, &scan_code) != 0)
|
||||
{
|
||||
scan_code = 0;
|
||||
}
|
||||
|
||||
const ImGuiKey key = cap_valid ? ImGui_ImplQNX_KeyCodeToImGuiKey(key_cap) : ImGuiKey_None;
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
// Modifier events must precede the ordinary key event in Dear ImGui's queue.
|
||||
// Unlike qterm, we still submit the individual modifier key because ImGui
|
||||
// exposes Left/Right Ctrl, Shift, Alt and Super as named keys.
|
||||
ImGui_ImplQNX_UpdateKeyModifiers(io, bd, modifiers, key, down);
|
||||
|
||||
if (key != ImGuiKey_None)
|
||||
{
|
||||
io.AddKeyEvent(key, down);
|
||||
io.SetKeyEventNativeData(key, key_cap, scan_code);
|
||||
}
|
||||
|
||||
bool text_added = false;
|
||||
if (down && sym_valid && key_sym >= 0)
|
||||
{
|
||||
const unsigned int keysym = (unsigned int)key_sym;
|
||||
// QNX special/function symbols begin at KEYCODE_PC_KEYS. Printable
|
||||
// symbols below that boundary use X11 keysym encoding. Also accept the
|
||||
// standard directly encoded UCS keysym form (0x01000000 | codepoint).
|
||||
if (keysym < (unsigned int)KEYCODE_PC_KEYS || (keysym & 0xff000000u) == 0x01000000u)
|
||||
{
|
||||
const unsigned int code_point = ImGui_ImplQNX_KeySymToUnicode(keysym);
|
||||
if (ImGui_ImplQNX_IsTextCodePoint(code_point))
|
||||
{
|
||||
io.AddInputCharacter(code_point);
|
||||
text_added = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return key != ImGuiKey_None || text_added || cap_valid || sym_valid;
|
||||
}
|
||||
|
||||
static bool ImGui_ImplQNX_ProcessPointerEvent(ImGui_ImplQNX_Data* bd, screen_event_t event)
|
||||
{
|
||||
int position[2] = {};
|
||||
int buttons = 0;
|
||||
int wheel_vertical = 0;
|
||||
int wheel_horizontal = 0;
|
||||
|
||||
if (screen_get_event_property_iv(event, SCREEN_PROPERTY_SOURCE_POSITION, position) != 0 &&
|
||||
screen_get_event_property_iv(event, SCREEN_PROPERTY_POSITION, position) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (screen_get_event_property_iv(event, SCREEN_PROPERTY_BUTTONS, &buttons) != 0)
|
||||
{
|
||||
buttons = bd->MouseButtons;
|
||||
}
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.AddMouseSourceEvent(ImGuiMouseSource_Mouse);
|
||||
io.AddMousePosEvent((float)position[0], (float)position[1]);
|
||||
|
||||
const int changed_buttons = buttons ^ bd->MouseButtons;
|
||||
if ((changed_buttons & SCREEN_LEFT_MOUSE_BUTTON) != 0)
|
||||
{
|
||||
io.AddMouseButtonEvent(0, (buttons & SCREEN_LEFT_MOUSE_BUTTON) != 0);
|
||||
}
|
||||
if ((changed_buttons & SCREEN_RIGHT_MOUSE_BUTTON) != 0)
|
||||
{
|
||||
io.AddMouseButtonEvent(1, (buttons & SCREEN_RIGHT_MOUSE_BUTTON) != 0);
|
||||
}
|
||||
if ((changed_buttons & SCREEN_MIDDLE_MOUSE_BUTTON) != 0)
|
||||
{
|
||||
io.AddMouseButtonEvent(2, (buttons & SCREEN_MIDDLE_MOUSE_BUTTON) != 0);
|
||||
}
|
||||
bd->MouseButtons = buttons;
|
||||
|
||||
if (screen_get_event_property_iv(event, SCREEN_PROPERTY_MOUSE_WHEEL, &wheel_vertical) != 0)
|
||||
{
|
||||
wheel_vertical = 0;
|
||||
}
|
||||
if (screen_get_event_property_iv(event, SCREEN_PROPERTY_MOUSE_HORIZONTAL_WHEEL, &wheel_horizontal) != 0)
|
||||
{
|
||||
wheel_horizontal = 0;
|
||||
}
|
||||
if (wheel_vertical != 0 || wheel_horizontal != 0)
|
||||
{
|
||||
// Screen: up/left are negative. Dear ImGui: up/left are positive.
|
||||
io.AddMouseWheelEvent((float)-wheel_horizontal, (float)-wheel_vertical);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ImGui_ImplQNX_ProcessTouchEvent(ImGui_ImplQNX_Data* bd, screen_event_t event, int event_type)
|
||||
{
|
||||
int touch_id = -1;
|
||||
int position[2] = {};
|
||||
if (screen_get_event_property_iv(event, SCREEN_PROPERTY_TOUCH_ID, &touch_id) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool is_release = event_type == SCREEN_EVENT_MTOUCH_RELEASE;
|
||||
if (bd->ActiveTouchId != -1 && touch_id != bd->ActiveTouchId)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.AddMouseSourceEvent(ImGuiMouseSource_TouchScreen);
|
||||
|
||||
if (!is_release)
|
||||
{
|
||||
if (screen_get_event_property_iv(event, SCREEN_PROPERTY_SOURCE_POSITION, position) != 0 &&
|
||||
screen_get_event_property_iv(event, SCREEN_PROPERTY_POSITION, position) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
io.AddMousePosEvent((float)position[0], (float)position[1]);
|
||||
}
|
||||
|
||||
if (event_type == SCREEN_EVENT_MTOUCH_TOUCH)
|
||||
{
|
||||
bd->ActiveTouchId = touch_id;
|
||||
io.AddMouseButtonEvent(0, true);
|
||||
}
|
||||
else if (is_release)
|
||||
{
|
||||
io.AddMouseButtonEvent(0, false);
|
||||
io.AddMousePosEvent(-FLT_MAX, -FLT_MAX);
|
||||
bd->ActiveTouchId = -1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ImGui_ImplQNX_ProcessEvent(screen_event_t event)
|
||||
{
|
||||
ImGui_ImplQNX_Data* bd = ImGui_ImplQNX_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplQNX_Init()?");
|
||||
if (bd == nullptr || event == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int event_type = SCREEN_EVENT_NONE;
|
||||
if (screen_get_event_property_iv(event, SCREEN_PROPERTY_TYPE, &event_type) != 0 || event_type == SCREEN_EVENT_NONE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
switch (event_type)
|
||||
{
|
||||
case SCREEN_EVENT_KEYBOARD:
|
||||
return ImGui_ImplQNX_ProcessKeyboardEvent(bd, event);
|
||||
case SCREEN_EVENT_POINTER:
|
||||
return ImGui_ImplQNX_ProcessPointerEvent(bd, event);
|
||||
case SCREEN_EVENT_MTOUCH_TOUCH:
|
||||
case SCREEN_EVENT_MTOUCH_MOVE:
|
||||
case SCREEN_EVENT_MTOUCH_RELEASE:
|
||||
return ImGui_ImplQNX_ProcessTouchEvent(bd, event, event_type);
|
||||
case SCREEN_EVENT_PROPERTY:
|
||||
{
|
||||
int property = 0;
|
||||
if (screen_get_event_property_iv(event, SCREEN_PROPERTY_NAME, &property) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (property == SCREEN_PROPERTY_FOCUS)
|
||||
{
|
||||
int focused = 0;
|
||||
if (screen_get_window_property_iv(bd->Window, SCREEN_PROPERTY_FOCUS, &focused) == 0)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.AddFocusEvent(focused != 0);
|
||||
if (focused == 0)
|
||||
{
|
||||
ImGui_ImplQNX_ClearModifierState(io, bd);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (property == SCREEN_PROPERTY_SIZE || property == SCREEN_PROPERTY_BUFFER_SIZE || property == SCREEN_PROPERTY_VISIBLE)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case SCREEN_EVENT_CLOSE:
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.AddFocusEvent(false);
|
||||
ImGui_ImplQNX_ClearModifierState(io, bd);
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ImGui_ImplQNX_Init(screen_context_t context, screen_window_t window)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IMGUI_CHECKVERSION();
|
||||
IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!");
|
||||
IM_ASSERT(context != nullptr && window != nullptr);
|
||||
if (context == nullptr || window == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ImGui_ImplQNX_Data* bd = IM_NEW(ImGui_ImplQNX_Data)();
|
||||
io.BackendPlatformUserData = (void*)bd;
|
||||
io.BackendPlatformName = "imgui_impl_qnx";
|
||||
|
||||
bd->Context = context;
|
||||
bd->Window = window;
|
||||
bd->TimeNanoseconds = ImGui_ImplQNX_GetTimeNanoseconds();
|
||||
|
||||
int focused = 0;
|
||||
if (screen_get_window_property_iv(window, SCREEN_PROPERTY_FOCUS, &focused) == 0)
|
||||
{
|
||||
io.AddFocusEvent(focused != 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplQNX_Shutdown()
|
||||
{
|
||||
ImGui_ImplQNX_Data* bd = ImGui_ImplQNX_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?");
|
||||
if (bd == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.BackendPlatformName = nullptr;
|
||||
io.BackendPlatformUserData = nullptr;
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
|
||||
void ImGui_ImplQNX_NewFrame()
|
||||
{
|
||||
ImGui_ImplQNX_Data* bd = ImGui_ImplQNX_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplQNX_Init()?");
|
||||
if (bd == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
int size[2] = {};
|
||||
if (screen_get_window_property_iv(bd->Window, SCREEN_PROPERTY_BUFFER_SIZE, size) != 0 ||
|
||||
size[0] <= 0 || size[1] <= 0)
|
||||
{
|
||||
size[0] = 0;
|
||||
size[1] = 0;
|
||||
(void)screen_get_window_property_iv(bd->Window, SCREEN_PROPERTY_SIZE, size);
|
||||
}
|
||||
if (size[0] > 0 && size[1] > 0)
|
||||
{
|
||||
io.DisplaySize = ImVec2((float)size[0], (float)size[1]);
|
||||
io.DisplayFramebufferScale = ImVec2(1.0f, 1.0f);
|
||||
}
|
||||
|
||||
const uint64_t current_time = ImGui_ImplQNX_GetTimeNanoseconds();
|
||||
if (current_time > bd->TimeNanoseconds && bd->TimeNanoseconds != 0)
|
||||
{
|
||||
io.DeltaTime = (float)((double)(current_time - bd->TimeNanoseconds) / 1000000000.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
io.DeltaTime = 1.0f / 60.0f;
|
||||
}
|
||||
bd->TimeNanoseconds = current_time;
|
||||
}
|
||||
|
||||
// Generated by Markus Kuhn's public-domain unicode/convmap.pl from X11 keysymdef.h and UnicodeData.
|
||||
// Original source: https://www.cl.cam.ac.uk/~mgk25/ucs/keysym2ucs.c
|
||||
// The table must remain sorted by keysym for the binary search below.
|
||||
struct ImGui_ImplQNX_KeySymPair
|
||||
{
|
||||
uint16_t KeySym;
|
||||
uint16_t Unicode;
|
||||
};
|
||||
|
||||
static const ImGui_ImplQNX_KeySymPair ImGui_ImplQNX_KeySymTable[] =
|
||||
{
|
||||
{ 0x01a1, 0x0104 }, { 0x01a2, 0x02d8 }, { 0x01a3, 0x0141 }, { 0x01a5, 0x013d },
|
||||
{ 0x01a6, 0x015a }, { 0x01a9, 0x0160 }, { 0x01aa, 0x015e }, { 0x01ab, 0x0164 },
|
||||
{ 0x01ac, 0x0179 }, { 0x01ae, 0x017d }, { 0x01af, 0x017b }, { 0x01b1, 0x0105 },
|
||||
{ 0x01b2, 0x02db }, { 0x01b3, 0x0142 }, { 0x01b5, 0x013e }, { 0x01b6, 0x015b },
|
||||
{ 0x01b7, 0x02c7 }, { 0x01b9, 0x0161 }, { 0x01ba, 0x015f }, { 0x01bb, 0x0165 },
|
||||
{ 0x01bc, 0x017a }, { 0x01bd, 0x02dd }, { 0x01be, 0x017e }, { 0x01bf, 0x017c },
|
||||
{ 0x01c0, 0x0154 }, { 0x01c3, 0x0102 }, { 0x01c5, 0x0139 }, { 0x01c6, 0x0106 },
|
||||
{ 0x01c8, 0x010c }, { 0x01ca, 0x0118 }, { 0x01cc, 0x011a }, { 0x01cf, 0x010e },
|
||||
{ 0x01d0, 0x0110 }, { 0x01d1, 0x0143 }, { 0x01d2, 0x0147 }, { 0x01d5, 0x0150 },
|
||||
{ 0x01d8, 0x0158 }, { 0x01d9, 0x016e }, { 0x01db, 0x0170 }, { 0x01de, 0x0162 },
|
||||
{ 0x01e0, 0x0155 }, { 0x01e3, 0x0103 }, { 0x01e5, 0x013a }, { 0x01e6, 0x0107 },
|
||||
{ 0x01e8, 0x010d }, { 0x01ea, 0x0119 }, { 0x01ec, 0x011b }, { 0x01ef, 0x010f },
|
||||
{ 0x01f0, 0x0111 }, { 0x01f1, 0x0144 }, { 0x01f2, 0x0148 }, { 0x01f5, 0x0151 },
|
||||
{ 0x01f8, 0x0159 }, { 0x01f9, 0x016f }, { 0x01fb, 0x0171 }, { 0x01fe, 0x0163 },
|
||||
{ 0x01ff, 0x02d9 }, { 0x02a1, 0x0126 }, { 0x02a6, 0x0124 }, { 0x02a9, 0x0130 },
|
||||
{ 0x02ab, 0x011e }, { 0x02ac, 0x0134 }, { 0x02b1, 0x0127 }, { 0x02b6, 0x0125 },
|
||||
{ 0x02b9, 0x0131 }, { 0x02bb, 0x011f }, { 0x02bc, 0x0135 }, { 0x02c5, 0x010a },
|
||||
{ 0x02c6, 0x0108 }, { 0x02d5, 0x0120 }, { 0x02d8, 0x011c }, { 0x02dd, 0x016c },
|
||||
{ 0x02de, 0x015c }, { 0x02e5, 0x010b }, { 0x02e6, 0x0109 }, { 0x02f5, 0x0121 },
|
||||
{ 0x02f8, 0x011d }, { 0x02fd, 0x016d }, { 0x02fe, 0x015d }, { 0x03a2, 0x0138 },
|
||||
{ 0x03a3, 0x0156 }, { 0x03a5, 0x0128 }, { 0x03a6, 0x013b }, { 0x03aa, 0x0112 },
|
||||
{ 0x03ab, 0x0122 }, { 0x03ac, 0x0166 }, { 0x03b3, 0x0157 }, { 0x03b5, 0x0129 },
|
||||
{ 0x03b6, 0x013c }, { 0x03ba, 0x0113 }, { 0x03bb, 0x0123 }, { 0x03bc, 0x0167 },
|
||||
{ 0x03bd, 0x014a }, { 0x03bf, 0x014b }, { 0x03c0, 0x0100 }, { 0x03c7, 0x012e },
|
||||
{ 0x03cc, 0x0116 }, { 0x03cf, 0x012a }, { 0x03d1, 0x0145 }, { 0x03d2, 0x014c },
|
||||
{ 0x03d3, 0x0136 }, { 0x03d9, 0x0172 }, { 0x03dd, 0x0168 }, { 0x03de, 0x016a },
|
||||
{ 0x03e0, 0x0101 }, { 0x03e7, 0x012f }, { 0x03ec, 0x0117 }, { 0x03ef, 0x012b },
|
||||
{ 0x03f1, 0x0146 }, { 0x03f2, 0x014d }, { 0x03f3, 0x0137 }, { 0x03f9, 0x0173 },
|
||||
{ 0x03fd, 0x0169 }, { 0x03fe, 0x016b }, { 0x047e, 0x203e }, { 0x04a1, 0x3002 },
|
||||
{ 0x04a2, 0x300c }, { 0x04a3, 0x300d }, { 0x04a4, 0x3001 }, { 0x04a5, 0x30fb },
|
||||
{ 0x04a6, 0x30f2 }, { 0x04a7, 0x30a1 }, { 0x04a8, 0x30a3 }, { 0x04a9, 0x30a5 },
|
||||
{ 0x04aa, 0x30a7 }, { 0x04ab, 0x30a9 }, { 0x04ac, 0x30e3 }, { 0x04ad, 0x30e5 },
|
||||
{ 0x04ae, 0x30e7 }, { 0x04af, 0x30c3 }, { 0x04b0, 0x30fc }, { 0x04b1, 0x30a2 },
|
||||
{ 0x04b2, 0x30a4 }, { 0x04b3, 0x30a6 }, { 0x04b4, 0x30a8 }, { 0x04b5, 0x30aa },
|
||||
{ 0x04b6, 0x30ab }, { 0x04b7, 0x30ad }, { 0x04b8, 0x30af }, { 0x04b9, 0x30b1 },
|
||||
{ 0x04ba, 0x30b3 }, { 0x04bb, 0x30b5 }, { 0x04bc, 0x30b7 }, { 0x04bd, 0x30b9 },
|
||||
{ 0x04be, 0x30bb }, { 0x04bf, 0x30bd }, { 0x04c0, 0x30bf }, { 0x04c1, 0x30c1 },
|
||||
{ 0x04c2, 0x30c4 }, { 0x04c3, 0x30c6 }, { 0x04c4, 0x30c8 }, { 0x04c5, 0x30ca },
|
||||
{ 0x04c6, 0x30cb }, { 0x04c7, 0x30cc }, { 0x04c8, 0x30cd }, { 0x04c9, 0x30ce },
|
||||
{ 0x04ca, 0x30cf }, { 0x04cb, 0x30d2 }, { 0x04cc, 0x30d5 }, { 0x04cd, 0x30d8 },
|
||||
{ 0x04ce, 0x30db }, { 0x04cf, 0x30de }, { 0x04d0, 0x30df }, { 0x04d1, 0x30e0 },
|
||||
{ 0x04d2, 0x30e1 }, { 0x04d3, 0x30e2 }, { 0x04d4, 0x30e4 }, { 0x04d5, 0x30e6 },
|
||||
{ 0x04d6, 0x30e8 }, { 0x04d7, 0x30e9 }, { 0x04d8, 0x30ea }, { 0x04d9, 0x30eb },
|
||||
{ 0x04da, 0x30ec }, { 0x04db, 0x30ed }, { 0x04dc, 0x30ef }, { 0x04dd, 0x30f3 },
|
||||
{ 0x04de, 0x309b }, { 0x04df, 0x309c }, { 0x05ac, 0x060c }, { 0x05bb, 0x061b },
|
||||
{ 0x05bf, 0x061f }, { 0x05c1, 0x0621 }, { 0x05c2, 0x0622 }, { 0x05c3, 0x0623 },
|
||||
{ 0x05c4, 0x0624 }, { 0x05c5, 0x0625 }, { 0x05c6, 0x0626 }, { 0x05c7, 0x0627 },
|
||||
{ 0x05c8, 0x0628 }, { 0x05c9, 0x0629 }, { 0x05ca, 0x062a }, { 0x05cb, 0x062b },
|
||||
{ 0x05cc, 0x062c }, { 0x05cd, 0x062d }, { 0x05ce, 0x062e }, { 0x05cf, 0x062f },
|
||||
{ 0x05d0, 0x0630 }, { 0x05d1, 0x0631 }, { 0x05d2, 0x0632 }, { 0x05d3, 0x0633 },
|
||||
{ 0x05d4, 0x0634 }, { 0x05d5, 0x0635 }, { 0x05d6, 0x0636 }, { 0x05d7, 0x0637 },
|
||||
{ 0x05d8, 0x0638 }, { 0x05d9, 0x0639 }, { 0x05da, 0x063a }, { 0x05e0, 0x0640 },
|
||||
{ 0x05e1, 0x0641 }, { 0x05e2, 0x0642 }, { 0x05e3, 0x0643 }, { 0x05e4, 0x0644 },
|
||||
{ 0x05e5, 0x0645 }, { 0x05e6, 0x0646 }, { 0x05e7, 0x0647 }, { 0x05e8, 0x0648 },
|
||||
{ 0x05e9, 0x0649 }, { 0x05ea, 0x064a }, { 0x05eb, 0x064b }, { 0x05ec, 0x064c },
|
||||
{ 0x05ed, 0x064d }, { 0x05ee, 0x064e }, { 0x05ef, 0x064f }, { 0x05f0, 0x0650 },
|
||||
{ 0x05f1, 0x0651 }, { 0x05f2, 0x0652 }, { 0x06a1, 0x0452 }, { 0x06a2, 0x0453 },
|
||||
{ 0x06a3, 0x0451 }, { 0x06a4, 0x0454 }, { 0x06a5, 0x0455 }, { 0x06a6, 0x0456 },
|
||||
{ 0x06a7, 0x0457 }, { 0x06a8, 0x0458 }, { 0x06a9, 0x0459 }, { 0x06aa, 0x045a },
|
||||
{ 0x06ab, 0x045b }, { 0x06ac, 0x045c }, { 0x06ae, 0x045e }, { 0x06af, 0x045f },
|
||||
{ 0x06b0, 0x2116 }, { 0x06b1, 0x0402 }, { 0x06b2, 0x0403 }, { 0x06b3, 0x0401 },
|
||||
{ 0x06b4, 0x0404 }, { 0x06b5, 0x0405 }, { 0x06b6, 0x0406 }, { 0x06b7, 0x0407 },
|
||||
{ 0x06b8, 0x0408 }, { 0x06b9, 0x0409 }, { 0x06ba, 0x040a }, { 0x06bb, 0x040b },
|
||||
{ 0x06bc, 0x040c }, { 0x06be, 0x040e }, { 0x06bf, 0x040f }, { 0x06c0, 0x044e },
|
||||
{ 0x06c1, 0x0430 }, { 0x06c2, 0x0431 }, { 0x06c3, 0x0446 }, { 0x06c4, 0x0434 },
|
||||
{ 0x06c5, 0x0435 }, { 0x06c6, 0x0444 }, { 0x06c7, 0x0433 }, { 0x06c8, 0x0445 },
|
||||
{ 0x06c9, 0x0438 }, { 0x06ca, 0x0439 }, { 0x06cb, 0x043a }, { 0x06cc, 0x043b },
|
||||
{ 0x06cd, 0x043c }, { 0x06ce, 0x043d }, { 0x06cf, 0x043e }, { 0x06d0, 0x043f },
|
||||
{ 0x06d1, 0x044f }, { 0x06d2, 0x0440 }, { 0x06d3, 0x0441 }, { 0x06d4, 0x0442 },
|
||||
{ 0x06d5, 0x0443 }, { 0x06d6, 0x0436 }, { 0x06d7, 0x0432 }, { 0x06d8, 0x044c },
|
||||
{ 0x06d9, 0x044b }, { 0x06da, 0x0437 }, { 0x06db, 0x0448 }, { 0x06dc, 0x044d },
|
||||
{ 0x06dd, 0x0449 }, { 0x06de, 0x0447 }, { 0x06df, 0x044a }, { 0x06e0, 0x042e },
|
||||
{ 0x06e1, 0x0410 }, { 0x06e2, 0x0411 }, { 0x06e3, 0x0426 }, { 0x06e4, 0x0414 },
|
||||
{ 0x06e5, 0x0415 }, { 0x06e6, 0x0424 }, { 0x06e7, 0x0413 }, { 0x06e8, 0x0425 },
|
||||
{ 0x06e9, 0x0418 }, { 0x06ea, 0x0419 }, { 0x06eb, 0x041a }, { 0x06ec, 0x041b },
|
||||
{ 0x06ed, 0x041c }, { 0x06ee, 0x041d }, { 0x06ef, 0x041e }, { 0x06f0, 0x041f },
|
||||
{ 0x06f1, 0x042f }, { 0x06f2, 0x0420 }, { 0x06f3, 0x0421 }, { 0x06f4, 0x0422 },
|
||||
{ 0x06f5, 0x0423 }, { 0x06f6, 0x0416 }, { 0x06f7, 0x0412 }, { 0x06f8, 0x042c },
|
||||
{ 0x06f9, 0x042b }, { 0x06fa, 0x0417 }, { 0x06fb, 0x0428 }, { 0x06fc, 0x042d },
|
||||
{ 0x06fd, 0x0429 }, { 0x06fe, 0x0427 }, { 0x06ff, 0x042a }, { 0x07a1, 0x0386 },
|
||||
{ 0x07a2, 0x0388 }, { 0x07a3, 0x0389 }, { 0x07a4, 0x038a }, { 0x07a5, 0x03aa },
|
||||
{ 0x07a7, 0x038c }, { 0x07a8, 0x038e }, { 0x07a9, 0x03ab }, { 0x07ab, 0x038f },
|
||||
{ 0x07ae, 0x0385 }, { 0x07af, 0x2015 }, { 0x07b1, 0x03ac }, { 0x07b2, 0x03ad },
|
||||
{ 0x07b3, 0x03ae }, { 0x07b4, 0x03af }, { 0x07b5, 0x03ca }, { 0x07b6, 0x0390 },
|
||||
{ 0x07b7, 0x03cc }, { 0x07b8, 0x03cd }, { 0x07b9, 0x03cb }, { 0x07ba, 0x03b0 },
|
||||
{ 0x07bb, 0x03ce }, { 0x07c1, 0x0391 }, { 0x07c2, 0x0392 }, { 0x07c3, 0x0393 },
|
||||
{ 0x07c4, 0x0394 }, { 0x07c5, 0x0395 }, { 0x07c6, 0x0396 }, { 0x07c7, 0x0397 },
|
||||
{ 0x07c8, 0x0398 }, { 0x07c9, 0x0399 }, { 0x07ca, 0x039a }, { 0x07cb, 0x039b },
|
||||
{ 0x07cc, 0x039c }, { 0x07cd, 0x039d }, { 0x07ce, 0x039e }, { 0x07cf, 0x039f },
|
||||
{ 0x07d0, 0x03a0 }, { 0x07d1, 0x03a1 }, { 0x07d2, 0x03a3 }, { 0x07d4, 0x03a4 },
|
||||
{ 0x07d5, 0x03a5 }, { 0x07d6, 0x03a6 }, { 0x07d7, 0x03a7 }, { 0x07d8, 0x03a8 },
|
||||
{ 0x07d9, 0x03a9 }, { 0x07e1, 0x03b1 }, { 0x07e2, 0x03b2 }, { 0x07e3, 0x03b3 },
|
||||
{ 0x07e4, 0x03b4 }, { 0x07e5, 0x03b5 }, { 0x07e6, 0x03b6 }, { 0x07e7, 0x03b7 },
|
||||
{ 0x07e8, 0x03b8 }, { 0x07e9, 0x03b9 }, { 0x07ea, 0x03ba }, { 0x07eb, 0x03bb },
|
||||
{ 0x07ec, 0x03bc }, { 0x07ed, 0x03bd }, { 0x07ee, 0x03be }, { 0x07ef, 0x03bf },
|
||||
{ 0x07f0, 0x03c0 }, { 0x07f1, 0x03c1 }, { 0x07f2, 0x03c3 }, { 0x07f3, 0x03c2 },
|
||||
{ 0x07f4, 0x03c4 }, { 0x07f5, 0x03c5 }, { 0x07f6, 0x03c6 }, { 0x07f7, 0x03c7 },
|
||||
{ 0x07f8, 0x03c8 }, { 0x07f9, 0x03c9 }, { 0x08a1, 0x23b7 }, { 0x08a2, 0x250c },
|
||||
{ 0x08a3, 0x2500 }, { 0x08a4, 0x2320 }, { 0x08a5, 0x2321 }, { 0x08a6, 0x2502 },
|
||||
{ 0x08a7, 0x23a1 }, { 0x08a8, 0x23a3 }, { 0x08a9, 0x23a4 }, { 0x08aa, 0x23a6 },
|
||||
{ 0x08ab, 0x239b }, { 0x08ac, 0x239d }, { 0x08ad, 0x239e }, { 0x08ae, 0x23a0 },
|
||||
{ 0x08af, 0x23a8 }, { 0x08b0, 0x23ac }, { 0x08bc, 0x2264 }, { 0x08bd, 0x2260 },
|
||||
{ 0x08be, 0x2265 }, { 0x08bf, 0x222b }, { 0x08c0, 0x2234 }, { 0x08c1, 0x221d },
|
||||
{ 0x08c2, 0x221e }, { 0x08c5, 0x2207 }, { 0x08c8, 0x223c }, { 0x08c9, 0x2243 },
|
||||
{ 0x08cd, 0x21d4 }, { 0x08ce, 0x21d2 }, { 0x08cf, 0x2261 }, { 0x08d6, 0x221a },
|
||||
{ 0x08da, 0x2282 }, { 0x08db, 0x2283 }, { 0x08dc, 0x2229 }, { 0x08dd, 0x222a },
|
||||
{ 0x08de, 0x2227 }, { 0x08df, 0x2228 }, { 0x08ef, 0x2202 }, { 0x08f6, 0x0192 },
|
||||
{ 0x08fb, 0x2190 }, { 0x08fc, 0x2191 }, { 0x08fd, 0x2192 }, { 0x08fe, 0x2193 },
|
||||
{ 0x09e0, 0x25c6 }, { 0x09e1, 0x2592 }, { 0x09e2, 0x2409 }, { 0x09e3, 0x240c },
|
||||
{ 0x09e4, 0x240d }, { 0x09e5, 0x240a }, { 0x09e8, 0x2424 }, { 0x09e9, 0x240b },
|
||||
{ 0x09ea, 0x2518 }, { 0x09eb, 0x2510 }, { 0x09ec, 0x250c }, { 0x09ed, 0x2514 },
|
||||
{ 0x09ee, 0x253c }, { 0x09ef, 0x23ba }, { 0x09f0, 0x23bb }, { 0x09f1, 0x2500 },
|
||||
{ 0x09f2, 0x23bc }, { 0x09f3, 0x23bd }, { 0x09f4, 0x251c }, { 0x09f5, 0x2524 },
|
||||
{ 0x09f6, 0x2534 }, { 0x09f7, 0x252c }, { 0x09f8, 0x2502 }, { 0x0aa1, 0x2003 },
|
||||
{ 0x0aa2, 0x2002 }, { 0x0aa3, 0x2004 }, { 0x0aa4, 0x2005 }, { 0x0aa5, 0x2007 },
|
||||
{ 0x0aa6, 0x2008 }, { 0x0aa7, 0x2009 }, { 0x0aa8, 0x200a }, { 0x0aa9, 0x2014 },
|
||||
{ 0x0aaa, 0x2013 }, { 0x0aae, 0x2026 }, { 0x0aaf, 0x2025 }, { 0x0ab0, 0x2153 },
|
||||
{ 0x0ab1, 0x2154 }, { 0x0ab2, 0x2155 }, { 0x0ab3, 0x2156 }, { 0x0ab4, 0x2157 },
|
||||
{ 0x0ab5, 0x2158 }, { 0x0ab6, 0x2159 }, { 0x0ab7, 0x215a }, { 0x0ab8, 0x2105 },
|
||||
{ 0x0abb, 0x2012 }, { 0x0abc, 0x2329 }, { 0x0abe, 0x232a }, { 0x0ac3, 0x215b },
|
||||
{ 0x0ac4, 0x215c }, { 0x0ac5, 0x215d }, { 0x0ac6, 0x215e }, { 0x0ac9, 0x2122 },
|
||||
{ 0x0aca, 0x2613 }, { 0x0acc, 0x25c1 }, { 0x0acd, 0x25b7 }, { 0x0ace, 0x25cb },
|
||||
{ 0x0acf, 0x25af }, { 0x0ad0, 0x2018 }, { 0x0ad1, 0x2019 }, { 0x0ad2, 0x201c },
|
||||
{ 0x0ad3, 0x201d }, { 0x0ad4, 0x211e }, { 0x0ad6, 0x2032 }, { 0x0ad7, 0x2033 },
|
||||
{ 0x0ad9, 0x271d }, { 0x0adb, 0x25ac }, { 0x0adc, 0x25c0 }, { 0x0add, 0x25b6 },
|
||||
{ 0x0ade, 0x25cf }, { 0x0adf, 0x25ae }, { 0x0ae0, 0x25e6 }, { 0x0ae1, 0x25ab },
|
||||
{ 0x0ae2, 0x25ad }, { 0x0ae3, 0x25b3 }, { 0x0ae4, 0x25bd }, { 0x0ae5, 0x2606 },
|
||||
{ 0x0ae6, 0x2022 }, { 0x0ae7, 0x25aa }, { 0x0ae8, 0x25b2 }, { 0x0ae9, 0x25bc },
|
||||
{ 0x0aea, 0x261c }, { 0x0aeb, 0x261e }, { 0x0aec, 0x2663 }, { 0x0aed, 0x2666 },
|
||||
{ 0x0aee, 0x2665 }, { 0x0af0, 0x2720 }, { 0x0af1, 0x2020 }, { 0x0af2, 0x2021 },
|
||||
{ 0x0af3, 0x2713 }, { 0x0af4, 0x2717 }, { 0x0af5, 0x266f }, { 0x0af6, 0x266d },
|
||||
{ 0x0af7, 0x2642 }, { 0x0af8, 0x2640 }, { 0x0af9, 0x260e }, { 0x0afa, 0x2315 },
|
||||
{ 0x0afb, 0x2117 }, { 0x0afc, 0x2038 }, { 0x0afd, 0x201a }, { 0x0afe, 0x201e },
|
||||
{ 0x0ba3, 0x003c }, { 0x0ba6, 0x003e }, { 0x0ba8, 0x2228 }, { 0x0ba9, 0x2227 },
|
||||
{ 0x0bc0, 0x00af }, { 0x0bc2, 0x22a5 }, { 0x0bc3, 0x2229 }, { 0x0bc4, 0x230a },
|
||||
{ 0x0bc6, 0x005f }, { 0x0bca, 0x2218 }, { 0x0bcc, 0x2395 }, { 0x0bce, 0x22a4 },
|
||||
{ 0x0bcf, 0x25cb }, { 0x0bd3, 0x2308 }, { 0x0bd6, 0x222a }, { 0x0bd8, 0x2283 },
|
||||
{ 0x0bda, 0x2282 }, { 0x0bdc, 0x22a2 }, { 0x0bfc, 0x22a3 }, { 0x0cdf, 0x2017 },
|
||||
{ 0x0ce0, 0x05d0 }, { 0x0ce1, 0x05d1 }, { 0x0ce2, 0x05d2 }, { 0x0ce3, 0x05d3 },
|
||||
{ 0x0ce4, 0x05d4 }, { 0x0ce5, 0x05d5 }, { 0x0ce6, 0x05d6 }, { 0x0ce7, 0x05d7 },
|
||||
{ 0x0ce8, 0x05d8 }, { 0x0ce9, 0x05d9 }, { 0x0cea, 0x05da }, { 0x0ceb, 0x05db },
|
||||
{ 0x0cec, 0x05dc }, { 0x0ced, 0x05dd }, { 0x0cee, 0x05de }, { 0x0cef, 0x05df },
|
||||
{ 0x0cf0, 0x05e0 }, { 0x0cf1, 0x05e1 }, { 0x0cf2, 0x05e2 }, { 0x0cf3, 0x05e3 },
|
||||
{ 0x0cf4, 0x05e4 }, { 0x0cf5, 0x05e5 }, { 0x0cf6, 0x05e6 }, { 0x0cf7, 0x05e7 },
|
||||
{ 0x0cf8, 0x05e8 }, { 0x0cf9, 0x05e9 }, { 0x0cfa, 0x05ea }, { 0x0da1, 0x0e01 },
|
||||
{ 0x0da2, 0x0e02 }, { 0x0da3, 0x0e03 }, { 0x0da4, 0x0e04 }, { 0x0da5, 0x0e05 },
|
||||
{ 0x0da6, 0x0e06 }, { 0x0da7, 0x0e07 }, { 0x0da8, 0x0e08 }, { 0x0da9, 0x0e09 },
|
||||
{ 0x0daa, 0x0e0a }, { 0x0dab, 0x0e0b }, { 0x0dac, 0x0e0c }, { 0x0dad, 0x0e0d },
|
||||
{ 0x0dae, 0x0e0e }, { 0x0daf, 0x0e0f }, { 0x0db0, 0x0e10 }, { 0x0db1, 0x0e11 },
|
||||
{ 0x0db2, 0x0e12 }, { 0x0db3, 0x0e13 }, { 0x0db4, 0x0e14 }, { 0x0db5, 0x0e15 },
|
||||
{ 0x0db6, 0x0e16 }, { 0x0db7, 0x0e17 }, { 0x0db8, 0x0e18 }, { 0x0db9, 0x0e19 },
|
||||
{ 0x0dba, 0x0e1a }, { 0x0dbb, 0x0e1b }, { 0x0dbc, 0x0e1c }, { 0x0dbd, 0x0e1d },
|
||||
{ 0x0dbe, 0x0e1e }, { 0x0dbf, 0x0e1f }, { 0x0dc0, 0x0e20 }, { 0x0dc1, 0x0e21 },
|
||||
{ 0x0dc2, 0x0e22 }, { 0x0dc3, 0x0e23 }, { 0x0dc4, 0x0e24 }, { 0x0dc5, 0x0e25 },
|
||||
{ 0x0dc6, 0x0e26 }, { 0x0dc7, 0x0e27 }, { 0x0dc8, 0x0e28 }, { 0x0dc9, 0x0e29 },
|
||||
{ 0x0dca, 0x0e2a }, { 0x0dcb, 0x0e2b }, { 0x0dcc, 0x0e2c }, { 0x0dcd, 0x0e2d },
|
||||
{ 0x0dce, 0x0e2e }, { 0x0dcf, 0x0e2f }, { 0x0dd0, 0x0e30 }, { 0x0dd1, 0x0e31 },
|
||||
{ 0x0dd2, 0x0e32 }, { 0x0dd3, 0x0e33 }, { 0x0dd4, 0x0e34 }, { 0x0dd5, 0x0e35 },
|
||||
{ 0x0dd6, 0x0e36 }, { 0x0dd7, 0x0e37 }, { 0x0dd8, 0x0e38 }, { 0x0dd9, 0x0e39 },
|
||||
{ 0x0dda, 0x0e3a }, { 0x0ddf, 0x0e3f }, { 0x0de0, 0x0e40 }, { 0x0de1, 0x0e41 },
|
||||
{ 0x0de2, 0x0e42 }, { 0x0de3, 0x0e43 }, { 0x0de4, 0x0e44 }, { 0x0de5, 0x0e45 },
|
||||
{ 0x0de6, 0x0e46 }, { 0x0de7, 0x0e47 }, { 0x0de8, 0x0e48 }, { 0x0de9, 0x0e49 },
|
||||
{ 0x0dea, 0x0e4a }, { 0x0deb, 0x0e4b }, { 0x0dec, 0x0e4c }, { 0x0ded, 0x0e4d },
|
||||
{ 0x0df0, 0x0e50 }, { 0x0df1, 0x0e51 }, { 0x0df2, 0x0e52 }, { 0x0df3, 0x0e53 },
|
||||
{ 0x0df4, 0x0e54 }, { 0x0df5, 0x0e55 }, { 0x0df6, 0x0e56 }, { 0x0df7, 0x0e57 },
|
||||
{ 0x0df8, 0x0e58 }, { 0x0df9, 0x0e59 }, { 0x0ea1, 0x3131 }, { 0x0ea2, 0x3132 },
|
||||
{ 0x0ea3, 0x3133 }, { 0x0ea4, 0x3134 }, { 0x0ea5, 0x3135 }, { 0x0ea6, 0x3136 },
|
||||
{ 0x0ea7, 0x3137 }, { 0x0ea8, 0x3138 }, { 0x0ea9, 0x3139 }, { 0x0eaa, 0x313a },
|
||||
{ 0x0eab, 0x313b }, { 0x0eac, 0x313c }, { 0x0ead, 0x313d }, { 0x0eae, 0x313e },
|
||||
{ 0x0eaf, 0x313f }, { 0x0eb0, 0x3140 }, { 0x0eb1, 0x3141 }, { 0x0eb2, 0x3142 },
|
||||
{ 0x0eb3, 0x3143 }, { 0x0eb4, 0x3144 }, { 0x0eb5, 0x3145 }, { 0x0eb6, 0x3146 },
|
||||
{ 0x0eb7, 0x3147 }, { 0x0eb8, 0x3148 }, { 0x0eb9, 0x3149 }, { 0x0eba, 0x314a },
|
||||
{ 0x0ebb, 0x314b }, { 0x0ebc, 0x314c }, { 0x0ebd, 0x314d }, { 0x0ebe, 0x314e },
|
||||
{ 0x0ebf, 0x314f }, { 0x0ec0, 0x3150 }, { 0x0ec1, 0x3151 }, { 0x0ec2, 0x3152 },
|
||||
{ 0x0ec3, 0x3153 }, { 0x0ec4, 0x3154 }, { 0x0ec5, 0x3155 }, { 0x0ec6, 0x3156 },
|
||||
{ 0x0ec7, 0x3157 }, { 0x0ec8, 0x3158 }, { 0x0ec9, 0x3159 }, { 0x0eca, 0x315a },
|
||||
{ 0x0ecb, 0x315b }, { 0x0ecc, 0x315c }, { 0x0ecd, 0x315d }, { 0x0ece, 0x315e },
|
||||
{ 0x0ecf, 0x315f }, { 0x0ed0, 0x3160 }, { 0x0ed1, 0x3161 }, { 0x0ed2, 0x3162 },
|
||||
{ 0x0ed3, 0x3163 }, { 0x0ed4, 0x11a8 }, { 0x0ed5, 0x11a9 }, { 0x0ed6, 0x11aa },
|
||||
{ 0x0ed7, 0x11ab }, { 0x0ed8, 0x11ac }, { 0x0ed9, 0x11ad }, { 0x0eda, 0x11ae },
|
||||
{ 0x0edb, 0x11af }, { 0x0edc, 0x11b0 }, { 0x0edd, 0x11b1 }, { 0x0ede, 0x11b2 },
|
||||
{ 0x0edf, 0x11b3 }, { 0x0ee0, 0x11b4 }, { 0x0ee1, 0x11b5 }, { 0x0ee2, 0x11b6 },
|
||||
{ 0x0ee3, 0x11b7 }, { 0x0ee4, 0x11b8 }, { 0x0ee5, 0x11b9 }, { 0x0ee6, 0x11ba },
|
||||
{ 0x0ee7, 0x11bb }, { 0x0ee8, 0x11bc }, { 0x0ee9, 0x11bd }, { 0x0eea, 0x11be },
|
||||
{ 0x0eeb, 0x11bf }, { 0x0eec, 0x11c0 }, { 0x0eed, 0x11c1 }, { 0x0eee, 0x11c2 },
|
||||
{ 0x0eef, 0x316d }, { 0x0ef0, 0x3171 }, { 0x0ef1, 0x3178 }, { 0x0ef2, 0x317f },
|
||||
{ 0x0ef3, 0x3181 }, { 0x0ef4, 0x3184 }, { 0x0ef5, 0x3186 }, { 0x0ef6, 0x318d },
|
||||
{ 0x0ef7, 0x318e }, { 0x0ef8, 0x11eb }, { 0x0ef9, 0x11f0 }, { 0x0efa, 0x11f9 },
|
||||
{ 0x0eff, 0x20a9 }, { 0x13a4, 0x20ac }, { 0x13bc, 0x0152 }, { 0x13bd, 0x0153 },
|
||||
{ 0x13be, 0x0178 }, { 0x20ac, 0x20ac },
|
||||
};
|
||||
|
||||
static unsigned int ImGui_ImplQNX_KeySymToUnicode(unsigned int keysym)
|
||||
{
|
||||
// Latin-1 keysyms map directly to Unicode.
|
||||
if ((keysym >= 0x0020u && keysym <= 0x007eu) ||
|
||||
(keysym >= 0x00a0u && keysym <= 0x00ffu))
|
||||
{
|
||||
return keysym;
|
||||
}
|
||||
|
||||
// X11-style directly encoded UCS keysyms use 0x01000000 | codepoint.
|
||||
if ((keysym & 0xff000000u) == 0x01000000u)
|
||||
{
|
||||
const unsigned int codepoint = keysym & 0x00ffffffu;
|
||||
return codepoint <= IM_UNICODE_CODEPOINT_MAX ? codepoint : 0u;
|
||||
}
|
||||
|
||||
int min = 0;
|
||||
int max = (int)(sizeof(ImGui_ImplQNX_KeySymTable) / sizeof(ImGui_ImplQNX_KeySymTable[0])) - 1;
|
||||
while (max >= min)
|
||||
{
|
||||
const int mid = min + (max - min) / 2;
|
||||
if (ImGui_ImplQNX_KeySymTable[mid].KeySym < keysym)
|
||||
{
|
||||
min = mid + 1;
|
||||
}
|
||||
else if (ImGui_ImplQNX_KeySymTable[mid].KeySym > keysym)
|
||||
{
|
||||
max = mid - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ImGui_ImplQNX_KeySymTable[mid].Unicode;
|
||||
}
|
||||
}
|
||||
|
||||
return 0u;
|
||||
}
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
35
backends/imgui_impl_qnx.h
Normal file
35
backends/imgui_impl_qnx.h
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
// dear imgui: Platform Backend for QNX Screen
|
||||
// This needs to be used along with a Renderer Backend (e.g. OpenGL3, Vulkan).
|
||||
|
||||
// Implemented features:
|
||||
// [X] Platform: Keyboard support. Uses io.AddKeyEvent() and native QNX key symbols.
|
||||
// [X] Platform: Mouse support. Handles position, three buttons and horizontal/vertical wheels.
|
||||
// [X] Platform: Touch support. Maps the first active touch contact to the primary mouse button.
|
||||
// [X] Platform: Focus and window-size updates.
|
||||
// Missing features or Issues:
|
||||
// [ ] Platform: Clipboard support.
|
||||
// [ ] Platform: Gamepad support.
|
||||
// [ ] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors).
|
||||
|
||||
// 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.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - 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
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
#ifndef IMGUI_DISABLE
|
||||
|
||||
#include <screen/screen.h>
|
||||
|
||||
// The application owns the Screen context, window and event object.
|
||||
// Poll events with screen_get_event() and pass each non-NONE event to ProcessEvent().
|
||||
IMGUI_IMPL_API bool ImGui_ImplQNX_Init(screen_context_t context, screen_window_t window);
|
||||
IMGUI_IMPL_API void ImGui_ImplQNX_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplQNX_NewFrame();
|
||||
IMGUI_IMPL_API bool ImGui_ImplQNX_ProcessEvent(screen_event_t event);
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
|
@ -21,6 +21,8 @@
|
|||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-08-06: Fixed querying framebuffer scale when using Metal. (#5592)
|
||||
// 2026-07-15: Inputs: restore SDL_StartTextInput()/SDL_StopTextInput() in IME handler for on-screen keyboard support on Android/mobile. (#7636, #9474)
|
||||
// 2026-04-16: Made ImGui_ImplSDL2_GetContentScaleForWindow(), ImGui_ImplSDL2_GetContentScaleForDisplay() helpers return a minimum of 1.0f, as some Linux setup seems to report <1.0f value and this breaks scaling border size. (#9369)
|
||||
// 2026-02-13: Inputs: systems other than X11 are back to starting mouse capture on mouse down (reverts 2025-02-26 change). Only X11 requires waiting for a drag by default (not ideal, but a better default for X11 users). Added ImGui_ImplSDL2_SetMouseCaptureMode() for X11 debugger users. (#3650, #6410, #9235)
|
||||
// 2026-01-15: Changed GetClipboardText() handler to return nullptr on error aka clipboard contents is not text. Consistent with other backends. (#9168)
|
||||
|
|
@ -134,10 +136,18 @@
|
|||
#endif
|
||||
#define SDL_HAS_PER_MONITOR_DPI SDL_VERSION_ATLEAST(2,0,4)
|
||||
#define SDL_HAS_VULKAN SDL_VERSION_ATLEAST(2,0,6)
|
||||
#if defined(__APPLE__)
|
||||
#define SDL_HAS_METAL SDL_VERSION_ATLEAST(2,0,14)
|
||||
#else
|
||||
#define SDL_HAS_METAL 0
|
||||
#endif
|
||||
#define SDL_HAS_OPEN_URL SDL_VERSION_ATLEAST(2,0,14)
|
||||
#if SDL_HAS_VULKAN
|
||||
#include <SDL_vulkan.h>
|
||||
#endif
|
||||
#if SDL_HAS_METAL
|
||||
#include <SDL_metal.h>
|
||||
#endif
|
||||
|
||||
// SDL Data
|
||||
struct ImGui_ImplSDL2_Data
|
||||
|
|
@ -147,7 +157,8 @@ struct ImGui_ImplSDL2_Data
|
|||
SDL_Renderer* Renderer;
|
||||
Uint64 Time;
|
||||
char* ClipboardTextData;
|
||||
char BackendPlatformName[48];
|
||||
char BackendPlatformName[64];
|
||||
bool IsWayland;
|
||||
|
||||
// Mouse handling
|
||||
Uint32 MouseWindowID;
|
||||
|
|
@ -204,6 +215,18 @@ static void ImGui_ImplSDL2_PlatformSetImeData(ImGuiContext*, ImGuiViewport*, ImG
|
|||
r.w = 1;
|
||||
r.h = (int)data->InputLineHeight;
|
||||
SDL_SetTextInputRect(&r);
|
||||
|
||||
#ifdef __ANDROID__
|
||||
// SDL_StartTextInput() is needed on Android (and some other platforms) to show the on-screen keyboard. (#7636, #9474, #6306)
|
||||
// It was removed in a7703fe6 due to concerns about its relation to desktop IME, but is required on mobile.
|
||||
SDL_StartTextInput();
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef __ANDROID__
|
||||
SDL_StopTextInput();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -499,11 +522,12 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer, void
|
|||
SDL_version ver_runtime;
|
||||
SDL_VERSION(&ver_compiled);
|
||||
SDL_GetVersion(&ver_runtime);
|
||||
const char* sdl_video_driver = SDL_GetCurrentVideoDriver();
|
||||
|
||||
// Setup backend capabilities flags
|
||||
ImGui_ImplSDL2_Data* bd = IM_NEW(ImGui_ImplSDL2_Data)();
|
||||
snprintf(bd->BackendPlatformName, sizeof(bd->BackendPlatformName), "imgui_impl_sdl2 (%u.%u.%u, %u.%u.%u)",
|
||||
ver_compiled.major, ver_compiled.minor, ver_compiled.patch, ver_runtime.major, ver_runtime.minor, ver_runtime.patch);
|
||||
snprintf(bd->BackendPlatformName, sizeof(bd->BackendPlatformName), "imgui_impl_sdl2 (%u.%u.%u, %u.%u.%u) (%s)",
|
||||
ver_compiled.major, ver_compiled.minor, ver_compiled.patch, ver_runtime.major, ver_runtime.minor, ver_runtime.patch, sdl_video_driver);
|
||||
io.BackendPlatformUserData = (void*)bd;
|
||||
io.BackendPlatformName = bd->BackendPlatformName;
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
||||
|
|
@ -512,16 +536,16 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer, void
|
|||
bd->Window = window;
|
||||
bd->WindowID = SDL_GetWindowID(window);
|
||||
bd->Renderer = renderer;
|
||||
bd->IsWayland = strcmp(sdl_video_driver, "Wayland") == 0;
|
||||
|
||||
// Check and store if we are on a SDL backend that supports SDL_GetGlobalMouseState() and SDL_CaptureMouse()
|
||||
// ("wayland" and "rpi" don't support it, but we chose to use a white-list instead of a black-list)
|
||||
bd->MouseCanUseGlobalState = false;
|
||||
bd->MouseCaptureMode = ImGui_ImplSDL2_MouseCaptureMode_Disabled;
|
||||
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
|
||||
const char* sdl_backend = SDL_GetCurrentVideoDriver();
|
||||
const char* capture_and_global_state_whitelist[] = { "windows", "cocoa", "x11", "DIVE", "VMAN" };
|
||||
for (const char* item : capture_and_global_state_whitelist)
|
||||
if (strncmp(sdl_backend, item, strlen(item)) == 0)
|
||||
if (strncmp(sdl_video_driver, item, strlen(item)) == 0)
|
||||
{
|
||||
bd->MouseCanUseGlobalState = true;
|
||||
bd->MouseCaptureMode = (strcmp(item, "x11") == 0) ? ImGui_ImplSDL2_MouseCaptureMode_EnabledAfterDrag : ImGui_ImplSDL2_MouseCaptureMode_Enabled;
|
||||
|
|
@ -884,6 +908,10 @@ static void ImGui_ImplSDL2_GetWindowSizeAndFramebufferScale(SDL_Window* window,
|
|||
#if SDL_HAS_VULKAN
|
||||
else if (SDL_GetWindowFlags(window) & SDL_WINDOW_VULKAN)
|
||||
SDL_Vulkan_GetDrawableSize(window, &display_w, &display_h);
|
||||
#endif
|
||||
#if SDL_HAS_METAL
|
||||
else if (SDL_GetWindowFlags(window) & SDL_WINDOW_METAL)
|
||||
SDL_Metal_GetDrawableSize(window, &display_w, &display_h);
|
||||
#endif
|
||||
else
|
||||
SDL_GL_GetDrawableSize(window, &display_w, &display_h);
|
||||
|
|
|
|||
|
|
@ -111,7 +111,8 @@ struct ImGui_ImplSDL3_Data
|
|||
SDL_Renderer* Renderer;
|
||||
Uint64 Time;
|
||||
char* ClipboardTextData;
|
||||
char BackendPlatformName[48];
|
||||
char BackendPlatformName[64];
|
||||
bool IsWayland;
|
||||
|
||||
// IME handling
|
||||
SDL_Window* ImeWindow;
|
||||
|
|
@ -502,11 +503,13 @@ static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer, void
|
|||
//SDL_SetHint(SDL_HINT_EVENT_LOGGING, "2");
|
||||
|
||||
const int ver_linked = SDL_GetVersion();
|
||||
const char* sdl_video_driver = SDL_GetCurrentVideoDriver();
|
||||
|
||||
// Setup backend capabilities flags
|
||||
ImGui_ImplSDL3_Data* bd = IM_NEW(ImGui_ImplSDL3_Data)();
|
||||
snprintf(bd->BackendPlatformName, sizeof(bd->BackendPlatformName), "imgui_impl_sdl3 (%d.%d.%d; %d.%d.%d)",
|
||||
SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_MICRO_VERSION, SDL_VERSIONNUM_MAJOR(ver_linked), SDL_VERSIONNUM_MINOR(ver_linked), SDL_VERSIONNUM_MICRO(ver_linked));
|
||||
snprintf(bd->BackendPlatformName, sizeof(bd->BackendPlatformName), "imgui_impl_sdl3 (%d.%d.%d; %d.%d.%d) (%s)",
|
||||
SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_MICRO_VERSION, SDL_VERSIONNUM_MAJOR(ver_linked), SDL_VERSIONNUM_MINOR(ver_linked), SDL_VERSIONNUM_MICRO(ver_linked),
|
||||
sdl_video_driver);
|
||||
io.BackendPlatformUserData = (void*)bd;
|
||||
io.BackendPlatformName = bd->BackendPlatformName;
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
||||
|
|
@ -515,16 +518,16 @@ static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer, void
|
|||
bd->Window = window;
|
||||
bd->WindowID = SDL_GetWindowID(window);
|
||||
bd->Renderer = renderer;
|
||||
bd->IsWayland = strcmp(sdl_video_driver, "wayland") == 0;
|
||||
|
||||
// Check and store if we are on a SDL backend that supports SDL_GetGlobalMouseState() and SDL_CaptureMouse()
|
||||
// ("wayland" and "rpi" don't support it, but we chose to use a white-list instead of a black-list)
|
||||
bd->MouseCanUseGlobalState = false;
|
||||
bd->MouseCaptureMode = ImGui_ImplSDL3_MouseCaptureMode_Disabled;
|
||||
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
|
||||
const char* sdl_backend = SDL_GetCurrentVideoDriver();
|
||||
const char* capture_and_global_state_whitelist[] = { "windows", "cocoa", "x11", "DIVE", "VMAN" };
|
||||
for (const char* item : capture_and_global_state_whitelist)
|
||||
if (strncmp(sdl_backend, item, strlen(item)) == 0)
|
||||
if (strncmp(sdl_video_driver, item, strlen(item)) == 0)
|
||||
{
|
||||
bd->MouseCanUseGlobalState = true;
|
||||
bd->MouseCaptureMode = (strcmp(item, "x11") == 0) ? ImGui_ImplSDL3_MouseCaptureMode_EnabledAfterDrag : ImGui_ImplSDL3_MouseCaptureMode_Enabled;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
// [X] Renderer: User texture binding. Use 'SDL_GPUTexture*' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef! **IMPORTANT** Before 2025/08/08, ImTextureID was a reference to a SDL_GPUTextureSamplerBinding struct.
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access with ImGui_ImplSDLGPU3_GetRenderState().
|
||||
|
||||
// The aim of imgui_impl_sdlgpu3.h/.cpp is to be usable in your engine without any modification.
|
||||
// IF YOU FEEL YOU NEED TO MAKE ANY CHANGE TO THIS CODE, please share them and your feedback at https://github.com/ocornut/imgui/
|
||||
|
|
@ -22,6 +23,7 @@
|
|||
// Calling the function is MANDATORY, otherwise the ImGui will not upload neither the vertex nor the index buffer for the GPU. See imgui_impl_sdlgpu3.cpp for more info.
|
||||
|
||||
// CHANGELOG
|
||||
// 2026-09-07: Round framebuffer dimensions to the nearest integer instead of truncating them. (#9538, 9515, #8628)
|
||||
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. Obsoleting samplers from ImGui_ImplSDLGPU3_RenderState. (#9378)
|
||||
// 2026-03-19: Fixed issue in ImGui_ImplSDLGPU3_DestroyTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295, #9310)
|
||||
// 2026-02-25: Removed unnecessary call to SDL_WaitForGPUIdle when releasing vertex/index buffers. (#9262)
|
||||
|
|
@ -92,6 +94,11 @@ static ImGui_ImplSDLGPU3_Data* ImGui_ImplSDLGPU3_GetBackendData()
|
|||
return ImGui::GetCurrentContext() ? (ImGui_ImplSDLGPU3_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
|
||||
}
|
||||
|
||||
ImGui_ImplSDLGPU3_RenderState* ImGui_ImplSDLGPU3_GetRenderState()
|
||||
{
|
||||
return (ImGui_ImplSDLGPU3_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState;
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDLGPU3_SetupRenderState(ImDrawData* draw_data, SDL_GPUGraphicsPipeline* pipeline, SDL_GPUCommandBuffer* command_buffer, SDL_GPURenderPass* render_pass, ImGui_ImplSDLGPU3_FrameData* fd, uint32_t fb_width, uint32_t fb_height)
|
||||
{
|
||||
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
|
||||
|
|
@ -163,8 +170,8 @@ static void CreateOrResizeBuffers(SDL_GPUBuffer** buffer, SDL_GPUTransferBuffer*
|
|||
void ImGui_ImplSDLGPU3_PrepareDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer)
|
||||
{
|
||||
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
||||
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
|
||||
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
|
||||
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
|
||||
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
|
||||
if (fb_width <= 0 || fb_height <= 0 || draw_data->TotalVtxCount <= 0)
|
||||
return;
|
||||
|
||||
|
|
@ -229,8 +236,8 @@ static void ImGui_ImplSDLGPU3_DrawCallback_SetSamplerNearest(const ImDrawList*,
|
|||
void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer, SDL_GPURenderPass* render_pass, SDL_GPUGraphicsPipeline* pipeline)
|
||||
{
|
||||
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
||||
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
|
||||
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
|
||||
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
|
||||
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
|
||||
if (fb_width <= 0 || fb_height <= 0)
|
||||
return;
|
||||
|
||||
|
|
@ -591,7 +598,7 @@ void ImGui_ImplSDLGPU3_CreateDeviceObjects()
|
|||
|
||||
if (bd->TexSamplerLinear == nullptr)
|
||||
{
|
||||
// Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling.
|
||||
// Bilinear sampling is required.
|
||||
SDL_GPUSamplerCreateInfo sampler_info = {};
|
||||
sampler_info.min_filter = SDL_GPU_FILTER_LINEAR;
|
||||
sampler_info.mag_filter = SDL_GPU_FILTER_LINEAR;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
// [X] Renderer: User texture binding. Use 'SDL_GPUTexture*' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef! **IMPORTANT** Before 2025/08/08, ImTextureID was a reference to a SDL_GPUTextureSamplerBinding struct.
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access with ImGui_ImplSDLGPU3_GetRenderState().
|
||||
|
||||
// The aim of imgui_impl_sdlgpu3.h/.cpp is to be usable in your engine without any modification.
|
||||
// IF YOU FEEL YOU NEED TO MAKE ANY CHANGE TO THIS CODE, please share them and your feedback at https://github.com/ocornut/imgui/
|
||||
|
|
@ -58,5 +59,6 @@ struct ImGui_ImplSDLGPU3_RenderState
|
|||
{
|
||||
SDL_GPUDevice* Device;
|
||||
};
|
||||
IMGUI_IMPL_API ImGui_ImplSDLGPU3_RenderState* ImGui_ImplSDLGPU3_GetRenderState();
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
|
|
|||
|
|
@ -55,7 +55,8 @@
|
|||
#endif
|
||||
|
||||
// SDL
|
||||
#include <SDL.h>
|
||||
#include <SDL_render.h>
|
||||
#include <SDL_version.h>
|
||||
#if !SDL_VERSION_ATLEAST(2,0,17)
|
||||
#error This backend requires SDL 2.0.17+ because of SDL_RenderGeometry() function
|
||||
#endif
|
||||
|
|
@ -75,6 +76,11 @@ static ImGui_ImplSDLRenderer2_Data* ImGui_ImplSDLRenderer2_GetBackendData()
|
|||
return ImGui::GetCurrentContext() ? (ImGui_ImplSDLRenderer2_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
|
||||
}
|
||||
|
||||
ImGui_ImplSDLRenderer2_RenderState* ImGui_ImplSDLRenderer2_GetRenderState()
|
||||
{
|
||||
return (ImGui_ImplSDLRenderer2_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState;
|
||||
}
|
||||
|
||||
// Functions
|
||||
static void ImGui_ImplSDLRenderer2_SetupRenderState(SDL_Renderer* renderer)
|
||||
{
|
||||
|
|
@ -213,8 +219,7 @@ void ImGui_ImplSDLRenderer2_UpdateTexture(ImTextureData* tex)
|
|||
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == nullptr);
|
||||
IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
|
||||
|
||||
// Create texture
|
||||
// (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
|
||||
// Create texture (bilinear sampling is required)
|
||||
SDL_Texture* sdl_texture = SDL_CreateTexture(bd->Renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STATIC, tex->Width, tex->Height);
|
||||
IM_ASSERT(sdl_texture != nullptr && "Backend failed to create texture!");
|
||||
SDL_UpdateTexture(sdl_texture, nullptr, tex->GetPixels(), tex->GetPitch());
|
||||
|
|
|
|||
|
|
@ -51,5 +51,6 @@ struct ImGui_ImplSDLRenderer2_RenderState
|
|||
{
|
||||
SDL_Renderer* Renderer;
|
||||
};
|
||||
IMGUI_IMPL_API ImGui_ImplSDLRenderer2_RenderState* ImGui_ImplSDLRenderer2_GetRenderState();
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
// [X] Renderer: User texture binding. Use 'SDL_Texture*' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access with ImGui_ImplSDLRenderer3_GetRenderState().
|
||||
|
||||
// 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.
|
||||
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-09-17: Restore modified texture scale modes at the end of RenderDrawData(). Added DrawCallback_SetSamplerFromTex support. Added CurrentScaleMode in ImGui_ImplSDLRenderer3_RenderState (#9543, #9378)
|
||||
// 2026-07-15: Fixed default sampler state to be linear (broken 2026-04-23). (#9470, #9378)
|
||||
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)
|
||||
// 2026-03-12: Fixed invalid assert in ImGui_ImplSDLRenderer3_UpdateTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295)
|
||||
// 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
|
||||
|
|
@ -50,19 +52,24 @@
|
|||
#endif
|
||||
|
||||
// SDL
|
||||
#include <SDL3/SDL.h>
|
||||
#include <SDL3/SDL_render.h>
|
||||
#include <SDL3/SDL_version.h>
|
||||
#if !SDL_VERSION_ATLEAST(3,0,0)
|
||||
#error This backend requires SDL 3.0.0+
|
||||
#endif
|
||||
|
||||
// SDL_Renderer data
|
||||
struct ImGui_ImplSDLRenderer3_TexScaleModeEntry
|
||||
{
|
||||
SDL_Texture* Texture;
|
||||
SDL_ScaleMode ScaleModeBackup;
|
||||
};
|
||||
|
||||
struct ImGui_ImplSDLRenderer3_Data
|
||||
{
|
||||
SDL_Renderer* Renderer; // Main viewport's renderer
|
||||
ImVector<SDL_FColor> ColorBuffer;
|
||||
|
||||
// Render State
|
||||
SDL_ScaleMode CurrentScaleMode;
|
||||
ImVector<ImGui_ImplSDLRenderer3_TexScaleModeEntry> TexScaleModeBackups; // Backup of texture scale modes
|
||||
|
||||
ImGui_ImplSDLRenderer3_Data() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
|
@ -74,13 +81,21 @@ static ImGui_ImplSDLRenderer3_Data* ImGui_ImplSDLRenderer3_GetBackendData()
|
|||
return ImGui::GetCurrentContext() ? (ImGui_ImplSDLRenderer3_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
|
||||
}
|
||||
|
||||
ImGui_ImplSDLRenderer3_RenderState* ImGui_ImplSDLRenderer3_GetRenderState()
|
||||
{
|
||||
return (ImGui_ImplSDLRenderer3_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState;
|
||||
}
|
||||
|
||||
// Functions
|
||||
static void ImGui_ImplSDLRenderer3_SetupRenderState(SDL_Renderer* renderer)
|
||||
{
|
||||
ImGui_ImplSDLRenderer3_RenderState* render_state = ImGui_ImplSDLRenderer3_GetRenderState();
|
||||
|
||||
// Clear out any viewports and cliprect set by the user
|
||||
// FIXME: Technically speaking there are lots of other things we could backup/setup/restore during our render process.
|
||||
SDL_SetRenderViewport(renderer, nullptr);
|
||||
SDL_SetRenderClipRect(renderer, nullptr);
|
||||
render_state->CurrentScaleMode = SDL_SCALEMODE_LINEAR;
|
||||
}
|
||||
|
||||
void ImGui_ImplSDLRenderer3_NewFrame()
|
||||
|
|
@ -110,8 +125,61 @@ static int SDL_RenderGeometryRaw8BitColor(SDL_Renderer* renderer, ImVector<SDL_F
|
|||
|
||||
// Draw callbacks
|
||||
static void ImGui_ImplSDLRenderer3_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
|
||||
static void ImGui_ImplSDLRenderer3_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplSDLRenderer3_Data* bd = ImGui_ImplSDLRenderer3_GetBackendData(); bd->CurrentScaleMode = SDL_SCALEMODE_LINEAR; }
|
||||
static void ImGui_ImplSDLRenderer3_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplSDLRenderer3_Data* bd = ImGui_ImplSDLRenderer3_GetBackendData(); bd->CurrentScaleMode = SDL_SCALEMODE_NEAREST; }
|
||||
static void ImGui_ImplSDLRenderer3_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplSDLRenderer3_RenderState* render_state = ImGui_ImplSDLRenderer3_GetRenderState(); render_state->CurrentScaleMode = SDL_SCALEMODE_LINEAR; }
|
||||
static void ImGui_ImplSDLRenderer3_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplSDLRenderer3_RenderState* render_state = ImGui_ImplSDLRenderer3_GetRenderState(); render_state->CurrentScaleMode = SDL_SCALEMODE_NEAREST; }
|
||||
static void ImGui_ImplSDLRenderer3_DrawCallback_SetSamplerFromTex(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplSDLRenderer3_RenderState* render_state = ImGui_ImplSDLRenderer3_GetRenderState(); render_state->CurrentScaleMode = SDL_SCALEMODE_INVALID; } // SDL_SCALEMODE_INVALID = use/keep value in texture.
|
||||
|
||||
// SDLRenderer has various design issues which makes it hard to do it compared to regular graphics API.
|
||||
// - scale/filtering mode is tied to a texture.
|
||||
// - scale/filtering mode is not queued as part of the SDL_RenderGeometryXXX commands, so a change in one texture requires a flush.
|
||||
static void ImGui_ImplSDLRenderer3_TexScaleModeUpdate(SDL_Renderer* renderer, SDL_Texture* tex, SDL_ScaleMode desired_scale_mode)
|
||||
{
|
||||
ImGui_ImplSDLRenderer3_Data* bd = ImGui_ImplSDLRenderer3_GetBackendData();
|
||||
if (desired_scale_mode != SDL_SCALEMODE_INVALID)
|
||||
{
|
||||
// Enforce a scale mode
|
||||
SDL_ScaleMode tex_scale_mode = desired_scale_mode;
|
||||
if (!SDL_GetTextureScaleMode(tex, &tex_scale_mode) || tex_scale_mode == desired_scale_mode)
|
||||
return;
|
||||
SDL_FlushRenderer(renderer);
|
||||
SDL_SetTextureScaleMode(tex, desired_scale_mode);
|
||||
|
||||
// Store backup of old scale mode (FIXME-OPT)
|
||||
for (ImGui_ImplSDLRenderer3_TexScaleModeEntry& entry : bd->TexScaleModeBackups)
|
||||
if (entry.Texture == tex)
|
||||
{
|
||||
if (entry.ScaleModeBackup == SDL_SCALEMODE_INVALID)
|
||||
entry.ScaleModeBackup = tex_scale_mode;
|
||||
return;
|
||||
}
|
||||
ImGui_ImplSDLRenderer3_TexScaleModeEntry entry = { tex, tex_scale_mode };
|
||||
bd->TexScaleModeBackups.push_back(entry);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use scale mode that was set in texture by user. If there is an entry, restore it and clear the entry.
|
||||
for (ImGui_ImplSDLRenderer3_TexScaleModeEntry& entry : bd->TexScaleModeBackups)
|
||||
if (entry.Texture == tex && entry.ScaleModeBackup != SDL_SCALEMODE_INVALID)
|
||||
{
|
||||
SDL_FlushRenderer(renderer);
|
||||
SDL_SetTextureScaleMode(tex, entry.ScaleModeBackup);
|
||||
entry.ScaleModeBackup = SDL_SCALEMODE_INVALID;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ImGui_ImplSDLRenderer3_TexScaleModeRestoreBackups(SDL_Renderer* renderer)
|
||||
{
|
||||
ImGui_ImplSDLRenderer3_Data* bd = ImGui_ImplSDLRenderer3_GetBackendData();
|
||||
if (bd->TexScaleModeBackups.Size == 0)
|
||||
return;
|
||||
SDL_FlushRenderer(renderer);
|
||||
for (ImGui_ImplSDLRenderer3_TexScaleModeEntry& entry : bd->TexScaleModeBackups)
|
||||
if (entry.ScaleModeBackup != SDL_SCALEMODE_INVALID)
|
||||
SDL_SetTextureScaleMode(entry.Texture, entry.ScaleModeBackup);
|
||||
bd->TexScaleModeBackups.resize(0);
|
||||
}
|
||||
|
||||
void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data, SDL_Renderer* renderer)
|
||||
{
|
||||
|
|
@ -154,15 +222,16 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data, SDL_Renderer*
|
|||
SDL_GetRenderViewport(renderer, &old.Viewport);
|
||||
SDL_GetRenderClipRect(renderer, &old.ClipRect);
|
||||
|
||||
// Setup desired state
|
||||
ImGui_ImplSDLRenderer3_SetupRenderState(renderer);
|
||||
|
||||
// Setup render state structure (for callbacks and custom texture bindings)
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
ImGui_ImplSDLRenderer3_RenderState render_state;
|
||||
render_state.Renderer = renderer;
|
||||
platform_io.Renderer_RenderState = &render_state;
|
||||
|
||||
// Setup desired state
|
||||
ImGui_ImplSDLRenderer3_SetupRenderState(renderer);
|
||||
IM_ASSERT(bd->TexScaleModeBackups.Size == 0);
|
||||
|
||||
// Will project scissor/clipping rectangles into framebuffer space
|
||||
ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
|
||||
ImVec2 clip_scale = render_scale;
|
||||
|
|
@ -195,17 +264,17 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data, SDL_Renderer*
|
|||
if (clip_max.y > (float)fb_height) { clip_max.y = (float)fb_height; }
|
||||
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
|
||||
continue;
|
||||
|
||||
SDL_Rect r = { (int)(clip_min.x), (int)(clip_min.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y) };
|
||||
SDL_SetRenderClipRect(renderer, &r);
|
||||
|
||||
// Setup texture scale/filtering mode
|
||||
SDL_Texture* tex = (SDL_Texture*)pcmd->GetTexID();
|
||||
ImGui_ImplSDLRenderer3_TexScaleModeUpdate(renderer, tex, render_state.CurrentScaleMode);
|
||||
|
||||
// Draw
|
||||
const float* xy = (const float*)(const void*)((const char*)(vtx_buffer + pcmd->VtxOffset) + offsetof(ImDrawVert, pos));
|
||||
const float* uv = (const float*)(const void*)((const char*)(vtx_buffer + pcmd->VtxOffset) + offsetof(ImDrawVert, uv));
|
||||
const SDL_Color* color = (const SDL_Color*)(const void*)((const char*)(vtx_buffer + pcmd->VtxOffset) + offsetof(ImDrawVert, col)); // SDL 2.0.19+
|
||||
|
||||
// Bind texture, Draw
|
||||
SDL_Texture* tex = (SDL_Texture*)pcmd->GetTexID();
|
||||
SDL_SetTextureScaleMode(tex, bd->CurrentScaleMode);
|
||||
const SDL_Color* color = (const SDL_Color*)(const void*)((const char*)(vtx_buffer + pcmd->VtxOffset) + offsetof(ImDrawVert, col));
|
||||
SDL_RenderGeometryRaw8BitColor(renderer, bd->ColorBuffer, tex,
|
||||
xy, (int)sizeof(ImDrawVert),
|
||||
color, (int)sizeof(ImDrawVert),
|
||||
|
|
@ -220,6 +289,7 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data, SDL_Renderer*
|
|||
// Restore modified SDL_Renderer state
|
||||
SDL_SetRenderViewport(renderer, old.ViewportEnabled ? &old.Viewport : nullptr);
|
||||
SDL_SetRenderClipRect(renderer, old.ClipEnabled ? &old.ClipRect : nullptr);
|
||||
ImGui_ImplSDLRenderer3_TexScaleModeRestoreBackups(renderer);
|
||||
}
|
||||
|
||||
void ImGui_ImplSDLRenderer3_UpdateTexture(ImTextureData* tex)
|
||||
|
|
@ -233,8 +303,7 @@ void ImGui_ImplSDLRenderer3_UpdateTexture(ImTextureData* tex)
|
|||
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == nullptr);
|
||||
IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
|
||||
|
||||
// Create texture
|
||||
// (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
|
||||
// Create texture (bilinear sampling is required)
|
||||
SDL_Texture* sdl_texture = SDL_CreateTexture(bd->Renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STATIC, tex->Width, tex->Height);
|
||||
IM_ASSERT(sdl_texture != nullptr && "Backend failed to create texture!");
|
||||
SDL_UpdateTexture(sdl_texture, nullptr, tex->GetPixels(), tex->GetPitch());
|
||||
|
|
@ -302,6 +371,7 @@ bool ImGui_ImplSDLRenderer3_Init(SDL_Renderer* renderer)
|
|||
platform_io.DrawCallback_ResetRenderState = ImGui_ImplSDLRenderer3_DrawCallback_ResetRenderState;
|
||||
platform_io.DrawCallback_SetSamplerLinear = ImGui_ImplSDLRenderer3_DrawCallback_SetSamplerLinear;
|
||||
platform_io.DrawCallback_SetSamplerNearest = ImGui_ImplSDLRenderer3_DrawCallback_SetSamplerNearest;
|
||||
platform_io.DrawCallback_SetSamplerFromTex = ImGui_ImplSDLRenderer3_DrawCallback_SetSamplerFromTex;
|
||||
|
||||
bd->Renderer = renderer;
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
// [X] Renderer: User texture binding. Use 'SDL_Texture*' as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access with ImGui_ImplSDLRenderer3_GetRenderState().
|
||||
|
||||
// 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.
|
||||
|
|
@ -27,7 +27,8 @@
|
|||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
#ifndef IMGUI_DISABLE
|
||||
|
||||
struct SDL_Renderer;
|
||||
// For SDL_ScaleMode which cannot be forward declared.
|
||||
#include <SDL3/SDL_render.h>
|
||||
|
||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||
IMGUI_IMPL_API bool ImGui_ImplSDLRenderer3_Init(SDL_Renderer* renderer);
|
||||
|
|
@ -48,6 +49,8 @@ IMGUI_IMPL_API void ImGui_ImplSDLRenderer3_UpdateTexture(ImTextureData* tex)
|
|||
struct ImGui_ImplSDLRenderer3_RenderState
|
||||
{
|
||||
SDL_Renderer* Renderer;
|
||||
SDL_ScaleMode CurrentScaleMode; // Current scale mode during render. Set to SDL_SCALEMODE_INVALID to use "SetSamplerFromTex" mode.
|
||||
};
|
||||
IMGUI_IMPL_API ImGui_ImplSDLRenderer3_RenderState* ImGui_ImplSDLRenderer3_GetRenderState();
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
// [!] Renderer: User texture binding. Use a VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE 'VkDescriptorSet' as texture identifier. Call ImGui_ImplVulkan_AddTexture() to register one. Read the FAQ about ImTextureID/ImTextureRef + https://github.com/ocornut/imgui/pull/914 for discussions.
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access with ImGui_ImplVulkan_GetRenderState().
|
||||
|
||||
// The aim of imgui_impl_vulkan.h/.cpp is to be usable in your engine without any modification.
|
||||
// IF YOU FEEL YOU NEED TO MAKE ANY CHANGE TO THIS CODE, please share them and your feedback at https://github.com/ocornut/imgui/
|
||||
|
|
@ -27,6 +27,8 @@
|
|||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-09-07: Round framebuffer dimensions to the nearest integer instead of truncating them. (#9538, 9515, #8628)
|
||||
// 2026-09-03: Added for support for multiple Vulkan contexts with custom loaders. (#6616)
|
||||
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)
|
||||
// 2026-04-22: *BREAKING CHANGE* redesigned to use separate ImageView + Sampler instead of Combined Image Sampler. This change allows us to facilitate changing samplers, in line with other backends.
|
||||
// - When registering custom textures: changed ImGui_ImplVulkan_AddTexture() signature to remove Sampler.
|
||||
|
|
@ -230,10 +232,28 @@ static bool g_FunctionsLoaded = true;
|
|||
IMGUI_VULKAN_FUNC_MAP_MACRO(vkUpdateDescriptorSets) \
|
||||
IMGUI_VULKAN_FUNC_MAP_MACRO(vkWaitForFences)
|
||||
|
||||
struct ImGui_ImplVulkan_Functions
|
||||
{
|
||||
// Define function pointers
|
||||
#define IMGUI_VULKAN_FUNC_DEF(func) static PFN_##func func;
|
||||
#define IMGUI_VULKAN_FUNC_DEF(func) PFN_##func pfn_##func;
|
||||
IMGUI_VULKAN_FUNC_MAP(IMGUI_VULKAN_FUNC_DEF)
|
||||
#undef IMGUI_VULKAN_FUNC_DEF
|
||||
};
|
||||
|
||||
// Globally available function pointers used for initialization of the backend data
|
||||
static ImGui_ImplVulkan_Functions ImGuiImplVulkanFuncs;
|
||||
|
||||
// Multi Vulkan contexts support: wrap each Vulkan function pointer to properly dispatch it using the current backend data
|
||||
static ImGui_ImplVulkan_Functions& ImGui_ImplVulkan_GetFunctions();
|
||||
#define IMGUI_VULKAN_FUNC_WRAPPER(func) \
|
||||
template<typename... Args> \
|
||||
auto func(Args&&... args) -> decltype(ImGui_ImplVulkan_GetFunctions().pfn_##func(args...)) \
|
||||
{ \
|
||||
return ImGui_ImplVulkan_GetFunctions().pfn_##func(args...); \
|
||||
}
|
||||
IMGUI_VULKAN_FUNC_MAP(IMGUI_VULKAN_FUNC_WRAPPER)
|
||||
#undef IMGUI_VULKAN_FUNC_WRAPPER
|
||||
|
||||
#endif // IMGUI_IMPL_VULKAN_USE_LOADER
|
||||
|
||||
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
|
||||
|
|
@ -300,6 +320,11 @@ struct ImGui_ImplVulkan_Data
|
|||
// Render buffers for main window
|
||||
ImGui_ImplVulkan_WindowRenderBuffers MainWindowRenderBuffers;
|
||||
|
||||
// Vulkan function pointers loaded for this context
|
||||
#ifdef IMGUI_IMPL_VULKAN_USE_LOADER
|
||||
ImGui_ImplVulkan_Functions Functions;
|
||||
#endif
|
||||
|
||||
ImGui_ImplVulkan_Data()
|
||||
{
|
||||
memset((void*)this, 0, sizeof(*this));
|
||||
|
|
@ -434,6 +459,21 @@ static ImGui_ImplVulkan_Data* ImGui_ImplVulkan_GetBackendData()
|
|||
return ImGui::GetCurrentContext() ? (ImGui_ImplVulkan_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
|
||||
}
|
||||
|
||||
ImGui_ImplVulkan_RenderState* ImGui_ImplVulkan_GetRenderState()
|
||||
{
|
||||
return (ImGui_ImplVulkan_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState;
|
||||
}
|
||||
|
||||
#ifdef IMGUI_IMPL_VULKAN_USE_LOADER
|
||||
// Get the Vulkan function pointers used by the current backend.
|
||||
// If no backend is available, return the currently loaded global function pointers (ImGuiImplVulkanFuncs).
|
||||
static ImGui_ImplVulkan_Functions& ImGui_ImplVulkan_GetFunctions()
|
||||
{
|
||||
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
|
||||
return bd ? bd->Functions : ImGuiImplVulkanFuncs;
|
||||
}
|
||||
#endif
|
||||
|
||||
static uint32_t ImGui_ImplVulkan_MemoryType(VkMemoryPropertyFlags properties, uint32_t type_bits)
|
||||
{
|
||||
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
|
||||
|
|
@ -529,7 +569,7 @@ static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkPipeline
|
|||
constants[1] = 2.0f / draw_data->DisplaySize.y;
|
||||
constants[2] = -1.0f - draw_data->DisplayPos.x * constants[0]; // Translate
|
||||
constants[3] = -1.0f - draw_data->DisplayPos.y * constants[1];
|
||||
vkCmdPushConstants(command_buffer, bd->PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(float) * 4, constants);
|
||||
vkCmdPushConstants(command_buffer, bd->PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, (uint32_t)sizeof(float) * 4, constants);
|
||||
|
||||
// Setup sampler
|
||||
vkCmdBindDescriptorSets(bd->RenderState->CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->PipelineLayout, 1, 1, &bd->SamplerLinearDS, 0, nullptr);
|
||||
|
|
@ -537,15 +577,24 @@ static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkPipeline
|
|||
|
||||
// Draw callbacks
|
||||
static void ImGui_ImplVulkan_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
|
||||
static void ImGui_ImplVulkan_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); vkCmdBindDescriptorSets(bd->RenderState->CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->PipelineLayout, 1, 1, &bd->SamplerLinearDS, 0, nullptr); }
|
||||
static void ImGui_ImplVulkan_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); vkCmdBindDescriptorSets(bd->RenderState->CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->PipelineLayout, 1, 1, &bd->SamplerNearestDS, 0, nullptr); }
|
||||
static void ImGui_ImplVulkan_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); vkCmdBindDescriptorSets(bd->RenderState->CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->RenderState->PipelineLayout, 1, 1, &bd->SamplerLinearDS, 0, nullptr); }
|
||||
static void ImGui_ImplVulkan_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); vkCmdBindDescriptorSets(bd->RenderState->CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->RenderState->PipelineLayout, 1, 1, &bd->SamplerNearestDS, 0, nullptr); }
|
||||
|
||||
// If you want to use your own sampler, you can create your own callback, access ImGui_ImplVulkan_RenderState for command-buffer and pipeline layout, e.g.
|
||||
/*
|
||||
void ImGui_ImplVulkan_DrawCallback_SetSamplerCustom(const ImDrawList*, const ImDrawCmd* cmd)
|
||||
{
|
||||
ImGui_ImplVulkan_RenderState* render_state = (ImGui_ImplVulkan_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState;
|
||||
vkCmdBindDescriptorSets(render_state->CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, render_state->PipelineLayout, 1, 1, (VkDescriptorSet*)cmd->UserCallbackData, 0, nullptr);
|
||||
}
|
||||
*/
|
||||
|
||||
// Render function
|
||||
void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer, VkPipeline pipeline)
|
||||
{
|
||||
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
||||
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
|
||||
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
|
||||
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
|
||||
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
|
||||
if (fb_width <= 0 || fb_height <= 0)
|
||||
return;
|
||||
|
||||
|
|
@ -1144,8 +1193,7 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
|
|||
check_vk_result(err);
|
||||
}
|
||||
|
||||
// Create samplers
|
||||
// Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling.
|
||||
// Create samplers (bilinear sampling is required)
|
||||
if (!bd->SamplerLinear || !bd->SamplerNearest)
|
||||
{
|
||||
VkSamplerCreateInfo info = {};
|
||||
|
|
@ -1313,8 +1361,8 @@ bool ImGui_ImplVulkan_LoadFunctions(uint32_t api_version, PFN_vkVoidFunction(
|
|||
|
||||
#ifdef IMGUI_IMPL_VULKAN_USE_LOADER
|
||||
#define IMGUI_VULKAN_FUNC_LOAD(func) \
|
||||
func = reinterpret_cast<decltype(func)>(loader_func(#func, user_data)); \
|
||||
if (func == nullptr) \
|
||||
ImGuiImplVulkanFuncs.pfn_##func = reinterpret_cast<PFN_##func>(loader_func(#func, user_data)); \
|
||||
if (ImGuiImplVulkanFuncs.pfn_##func == nullptr) \
|
||||
return false;
|
||||
IMGUI_VULKAN_FUNC_MAP(IMGUI_VULKAN_FUNC_LOAD)
|
||||
#undef IMGUI_VULKAN_FUNC_LOAD
|
||||
|
|
@ -1382,6 +1430,9 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info)
|
|||
IM_ASSERT(info->PipelineInfoMain.RenderPass == VK_NULL_HANDLE);
|
||||
|
||||
bd->VulkanInitInfo = *info;
|
||||
#ifdef IMGUI_IMPL_VULKAN_USE_LOADER
|
||||
bd->Functions = ImGuiImplVulkanFuncs;
|
||||
#endif
|
||||
|
||||
VkPhysicalDeviceProperties properties;
|
||||
vkGetPhysicalDeviceProperties(info->PhysicalDevice, &properties);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
// [!] Renderer: User texture binding. Use a VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE 'VkDescriptorSet' as texture identifier. Call ImGui_ImplVulkan_AddTexture() to register one. Read the FAQ about ImTextureID/ImTextureRef + https://github.com/ocornut/imgui/pull/914 for discussions.
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access with ImGui_ImplVulkan_GetRenderState().
|
||||
|
||||
// The aim of imgui_impl_vulkan.h/.cpp is to be usable in your engine without any modification.
|
||||
// IF YOU FEEL YOU NEED TO MAKE ANY CHANGE TO THIS CODE, please share them and your feedback at https://github.com/ocornut/imgui/
|
||||
|
|
@ -167,6 +167,7 @@ IMGUI_IMPL_API bool ImGui_ImplVulkan_LoadFunctions(uint32_t api_vers
|
|||
|
||||
// [BETA] Selected render state data shared with callbacks.
|
||||
// This is temporarily stored in GetPlatformIO().Renderer_RenderState during the ImGui_ImplVulkan_RenderDrawData() call.
|
||||
// ImGui_ImplVulkan_RenderState* render_state = (ImGui_ImplVulkan_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState;
|
||||
// (Please open an issue if you feel you need access to more data)
|
||||
struct ImGui_ImplVulkan_RenderState
|
||||
{
|
||||
|
|
@ -174,6 +175,7 @@ struct ImGui_ImplVulkan_RenderState
|
|||
VkPipeline Pipeline;
|
||||
VkPipelineLayout PipelineLayout;
|
||||
};
|
||||
IMGUI_IMPL_API ImGui_ImplVulkan_RenderState* ImGui_ImplVulkan_GetRenderState();
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Internal / Miscellaneous Vulkan Helpers
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'WGPUTextureView' as ImTextureID. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
|
||||
// [X] Renderer: Texture updates support for dynamic font system (ImGuiBackendFlags_RendererHasTextures).
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access with ImGui_ImplWGPU_GetRenderState().
|
||||
|
||||
// Read imgui_impl_wgpu.h about how to use the IMGUI_IMPL_WEBGPU_BACKEND_WGPU or IMGUI_IMPL_WEBGPU_BACKEND_DAWN flags.
|
||||
|
||||
|
|
@ -20,6 +20,9 @@
|
|||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-09-07: Round framebuffer dimensions to the nearest integer instead of truncating them. (#9538, 9515, #8628)
|
||||
// 2026-08-31: Update to compile with wgpu-native 29.0. (#9377, #9532, #9530)
|
||||
// 2026-08-18: Fixed passing non-integer sizes to `wgpuRenderPassEncoderSetViewport() when FramebufferScale is >1.0f. (#9515, #8628)
|
||||
// 2026-04-23: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378)
|
||||
// 2026-03-25: Added support for WGVK native backend via IMGUI_IMPL_WEBGPU_BACKEND_WGVK define, with SPIRV shaders if WGSL is not available. (#9316, #9246, #9257)
|
||||
// 2026-03-09: Removed support for Emscripten < 4.0.10. (#9281)
|
||||
|
|
@ -65,12 +68,6 @@
|
|||
#error Emscripten <4.0.10 with '-sUSE_WEBGPU=1' is not supported anymore.
|
||||
#endif
|
||||
|
||||
#if defined IMGUI_IMPL_WEBGPU_BACKEND_DAWN || defined IMGUI_IMPL_WEBGPU_BACKEND_WGVK
|
||||
// Dawn renamed WGPUProgrammableStageDescriptor to WGPUComputeState (see: https://github.com/webgpu-native/webgpu-headers/pull/413)
|
||||
// Using type alias until WGPU adopts the same naming convention (#8369)
|
||||
using WGPUProgrammableStageDescriptor = WGPUComputeState;
|
||||
#endif
|
||||
|
||||
// Dear ImGui prototypes from imgui_internal.h
|
||||
extern ImGuiID ImHashData(const void* data_p, size_t data_size, ImU32 seed);
|
||||
#define MEMALIGN(_SIZE,_ALIGN) (((_SIZE) + ((_ALIGN) - 1)) & ~((_ALIGN) - 1)) // Memory align (copied from IM_ALIGN() macro).
|
||||
|
|
@ -132,6 +129,11 @@ static ImGui_ImplWGPU_Data* ImGui_ImplWGPU_GetBackendData()
|
|||
return ImGui::GetCurrentContext() ? (ImGui_ImplWGPU_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
|
||||
}
|
||||
|
||||
ImGui_ImplWGPU_RenderState* ImGui_ImplWGPU_GetRenderState()
|
||||
{
|
||||
return (ImGui_ImplWGPU_RenderState*)ImGui::GetPlatformIO().Renderer_RenderState;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SHADERS
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -316,7 +318,7 @@ static void SafeRelease(FrameResources& res)
|
|||
SafeRelease(res.VertexBufferHost);
|
||||
}
|
||||
|
||||
static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModuleWGSL(const char* wgsl_source)
|
||||
static WGPUComputeState ImGui_ImplWGPU_CreateShaderModuleWGSL(const char* wgsl_source)
|
||||
{
|
||||
ImGui_ImplWGPU_Data* bd = ImGui_ImplWGPU_GetBackendData();
|
||||
IM_UNUSED(bd);
|
||||
|
|
@ -343,7 +345,7 @@ static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModuleWGSL(con
|
|||
pop_cb.userdata1 = &validation_error;
|
||||
wgpuDevicePopErrorScope(bd->wgpuDevice, pop_cb);
|
||||
|
||||
WGPUProgrammableStageDescriptor stage_desc = {};
|
||||
WGPUComputeState stage_desc = {};
|
||||
if (module && !validation_error)
|
||||
{
|
||||
stage_desc.module = module;
|
||||
|
|
@ -356,7 +358,7 @@ static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModuleWGSL(con
|
|||
return stage_desc;
|
||||
}
|
||||
|
||||
static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModuleSPIRV(const void* spirv_binary, size_t spirv_length)
|
||||
static WGPUComputeState ImGui_ImplWGPU_CreateShaderModuleSPIRV(const void* spirv_binary, size_t spirv_length)
|
||||
{
|
||||
ImGui_ImplWGPU_Data* bd = ImGui_ImplWGPU_GetBackendData();
|
||||
|
||||
|
|
@ -368,7 +370,7 @@ static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModuleSPIRV(co
|
|||
WGPUShaderModuleDescriptor desc = {};
|
||||
desc.nextInChain = (WGPUChainedStruct*)&spirv_desc;
|
||||
|
||||
WGPUProgrammableStageDescriptor stage_desc = {};
|
||||
WGPUComputeState stage_desc = {};
|
||||
stage_desc.module = wgpuDeviceCreateShaderModule(bd->wgpuDevice, &desc);
|
||||
|
||||
stage_desc.entryPoint = { "main", WGPU_STRLEN };
|
||||
|
|
@ -440,7 +442,9 @@ static void ImGui_ImplWGPU_SetupRenderState(ImDrawData* draw_data, WGPURenderPas
|
|||
}
|
||||
|
||||
// Setup viewport
|
||||
wgpuRenderPassEncoderSetViewport(ctx, 0, 0, draw_data->FramebufferScale.x * draw_data->DisplaySize.x, draw_data->FramebufferScale.y * draw_data->DisplaySize.y, 0, 1);
|
||||
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
|
||||
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
|
||||
wgpuRenderPassEncoderSetViewport(ctx, 0, 0, (float)fb_width, (float)fb_height, 0, 1);
|
||||
|
||||
// Bind shader and vertex buffers
|
||||
wgpuRenderPassEncoderSetVertexBuffer(ctx, 0, fr->VertexBuffer, 0, fr->VertexBufferSize * sizeof(ImDrawVert));
|
||||
|
|
@ -449,7 +453,7 @@ static void ImGui_ImplWGPU_SetupRenderState(ImDrawData* draw_data, WGPURenderPas
|
|||
wgpuRenderPassEncoderSetBindGroup(ctx, 0, bd->renderResources.CommonBindGroupLinear, 0, nullptr);
|
||||
|
||||
// Setup blend factor
|
||||
WGPUColor blend_color = { 0.f, 0.f, 0.f, 0.f };
|
||||
WGPUColor blend_color = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
wgpuRenderPassEncoderSetBlendConstant(ctx, &blend_color);
|
||||
}
|
||||
|
||||
|
|
@ -462,8 +466,8 @@ static void ImGui_ImplWGPU_DrawCallback_SetSamplerNearest(const ImDrawList*, con
|
|||
void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder pass_encoder)
|
||||
{
|
||||
// Avoid rendering when minimized
|
||||
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
|
||||
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
|
||||
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
|
||||
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
|
||||
if (fb_width <= 0 || fb_height <= 0 || draw_data->CmdLists.Size == 0)
|
||||
return;
|
||||
|
||||
|
|
@ -769,7 +773,7 @@ bool ImGui_ImplWGPU_CreateDeviceObjects()
|
|||
graphics_pipeline_desc.layout = wgpuDeviceCreatePipelineLayout(bd->wgpuDevice, &layout_desc);
|
||||
|
||||
// Create the vertex shader
|
||||
WGPUProgrammableStageDescriptor vertex_shader_desc = ImGui_ImplWGPU_CreateShaderModuleWGSL(__shader_vert_wgsl);
|
||||
WGPUComputeState vertex_shader_desc = ImGui_ImplWGPU_CreateShaderModuleWGSL(__shader_vert_wgsl);
|
||||
if (!vertex_shader_desc.module) vertex_shader_desc = ImGui_ImplWGPU_CreateShaderModuleSPIRV(__shader_vert_spirv, sizeof(__shader_vert_spirv));
|
||||
graphics_pipeline_desc.vertex.module = vertex_shader_desc.module;
|
||||
graphics_pipeline_desc.vertex.entryPoint = vertex_shader_desc.entryPoint;
|
||||
|
|
@ -777,15 +781,9 @@ bool ImGui_ImplWGPU_CreateDeviceObjects()
|
|||
// Vertex input configuration
|
||||
WGPUVertexAttribute attribute_desc[] =
|
||||
{
|
||||
#if defined IMGUI_IMPL_WEBGPU_BACKEND_DAWN || defined IMGUI_IMPL_WEBGPU_BACKEND_WGVK
|
||||
{ nullptr, WGPUVertexFormat_Float32x2, (uint64_t)offsetof(ImDrawVert, pos), 0 },
|
||||
{ nullptr, WGPUVertexFormat_Float32x2, (uint64_t)offsetof(ImDrawVert, uv), 1 },
|
||||
{ nullptr, WGPUVertexFormat_Unorm8x4, (uint64_t)offsetof(ImDrawVert, col), 2 },
|
||||
#else
|
||||
{ WGPUVertexFormat_Float32x2, (uint64_t)offsetof(ImDrawVert, pos), 0 },
|
||||
{ WGPUVertexFormat_Float32x2, (uint64_t)offsetof(ImDrawVert, uv), 1 },
|
||||
{ WGPUVertexFormat_Unorm8x4, (uint64_t)offsetof(ImDrawVert, col), 2 },
|
||||
#endif
|
||||
};
|
||||
|
||||
WGPUVertexBufferLayout buffer_layouts[1];
|
||||
|
|
@ -798,7 +796,7 @@ bool ImGui_ImplWGPU_CreateDeviceObjects()
|
|||
graphics_pipeline_desc.vertex.buffers = buffer_layouts;
|
||||
|
||||
// Create the pixel shader
|
||||
WGPUProgrammableStageDescriptor pixel_shader_desc = ImGui_ImplWGPU_CreateShaderModuleWGSL(__shader_frag_wgsl);
|
||||
WGPUComputeState pixel_shader_desc = ImGui_ImplWGPU_CreateShaderModuleWGSL(__shader_frag_wgsl);
|
||||
if (!pixel_shader_desc.module) pixel_shader_desc = ImGui_ImplWGPU_CreateShaderModuleSPIRV(__shader_frag_spirv, sizeof(__shader_frag_spirv));
|
||||
|
||||
// Create the blending setup
|
||||
|
|
@ -844,8 +842,7 @@ bool ImGui_ImplWGPU_CreateDeviceObjects()
|
|||
|
||||
ImGui_ImplWGPU_CreateUniformBuffer();
|
||||
|
||||
// Create samplers (Linear/Nearest)
|
||||
// (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
|
||||
// Create samplers (Linear/Nearest) (bilinear sampling is required)
|
||||
WGPUSamplerDescriptor sampler_desc = {};
|
||||
sampler_desc.addressModeU = WGPUAddressMode_ClampToEdge;
|
||||
sampler_desc.addressModeV = WGPUAddressMode_ClampToEdge;
|
||||
|
|
@ -992,11 +989,7 @@ void ImGui_ImplWGPU_NewFrame()
|
|||
|
||||
bool ImGui_ImplWGPU_IsSurfaceStatusError(WGPUSurfaceGetCurrentTextureStatus status)
|
||||
{
|
||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGVK)
|
||||
return (status == WGPUSurfaceGetCurrentTextureStatus_Error);
|
||||
#else
|
||||
return (status == WGPUSurfaceGetCurrentTextureStatus_OutOfMemory || status == WGPUSurfaceGetCurrentTextureStatus_DeviceLost);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ImGui_ImplWGPU_IsSurfaceStatusSubOptimal(WGPUSurfaceGetCurrentTextureStatus status)
|
||||
|
|
@ -1009,7 +1002,6 @@ bool ImGui_ImplWGPU_IsSurfaceStatusSubOptimal(WGPUSurfaceGetCurrentTextureStatus
|
|||
}
|
||||
|
||||
// Helpers to obtain a string
|
||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGVK)
|
||||
const char* ImGui_ImplWGPU_GetErrorTypeName(WGPUErrorType type)
|
||||
{
|
||||
switch (type)
|
||||
|
|
@ -1032,7 +1024,7 @@ const char* ImGui_ImplWGPU_GetDeviceLostReasonName(WGPUDeviceLostReason type)
|
|||
default: return "Unknown";
|
||||
}
|
||||
}
|
||||
#elif !defined(__EMSCRIPTEN__)
|
||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) && !defined(__EMSCRIPTEN__)
|
||||
const char* ImGui_ImplWGPU_GetLogLevelName(WGPULogLevel level)
|
||||
{
|
||||
switch (level)
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@
|
|||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'WGPUTextureView' as ImTextureID. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
|
||||
// [X] Renderer: Texture updates support for dynamic font system (ImGuiBackendFlags_RendererHasTextures).
|
||||
// [X] Renderer: Expose selected render state for draw callbacks to use. Access with ImGui_ImplWGPU_GetRenderState().
|
||||
|
||||
// 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.
|
||||
|
|
@ -81,6 +81,7 @@ struct ImGui_ImplWGPU_RenderState
|
|||
WGPUDevice Device;
|
||||
WGPURenderPassEncoder RenderPassEncoder;
|
||||
};
|
||||
IMGUI_IMPL_API ImGui_ImplWGPU_RenderState* ImGui_ImplWGPU_GetRenderState();
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Internal Helpers
|
||||
|
|
@ -95,10 +96,9 @@ bool ImGui_ImplWGPU_IsSurfaceStatusSubOptimal(WGPUSurfaceGetCurrentTextur
|
|||
void ImGui_ImplWGPU_DebugPrintAdapterInfo(const WGPUAdapter& adapter);
|
||||
const char* ImGui_ImplWGPU_GetBackendTypeName(WGPUBackendType type);
|
||||
const char* ImGui_ImplWGPU_GetAdapterTypeName(WGPUAdapterType type);
|
||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
|
||||
const char* ImGui_ImplWGPU_GetDeviceLostReasonName(WGPUDeviceLostReason type);
|
||||
const char* ImGui_ImplWGPU_GetErrorTypeName(WGPUErrorType type);
|
||||
#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) && !defined(__EMSCRIPTEN__)
|
||||
const char* ImGui_ImplWGPU_GetLogLevelName(WGPULogLevel level);
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-05-19: DPI: ImGui_ImplWin32_EnableDpiAwareness() helper uses SetProcessDpiAwarenessContext() instead of SetThreadDpiAwarenessContext(), fixes DPI scaling issues with e.g. OpenGL. (#9403)
|
||||
// 2026-01-28: Inputs: Minor optimization not submitting gamepad input if packet number has not changed (reworked from 2025-09-23 attempt). (#9202, #8556)
|
||||
// 2025-12-03: Inputs: handle WM_IME_CHAR/WM_IME_COMPOSITION messages to support Unicode inputs on MBCS (non-Unicode) Windows. (#9099, #3653, #5961)
|
||||
// 2025-10-19: Inputs: Revert previous change to allow for io.ClearInputKeys() on focus-out not losing gamepad state.
|
||||
|
|
@ -886,6 +887,7 @@ DECLARE_HANDLE(DPI_AWARENESS_CONTEXT);
|
|||
typedef HRESULT(WINAPI* PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS); // Shcore.lib + dll, Windows 8.1+
|
||||
typedef HRESULT(WINAPI* PFN_GetDpiForMonitor)(HMONITOR, MONITOR_DPI_TYPE, UINT*, UINT*); // Shcore.lib + dll, Windows 8.1+
|
||||
typedef DPI_AWARENESS_CONTEXT(WINAPI* PFN_SetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT); // User32.lib + dll, Windows 10 v1607+ (Creators Update)
|
||||
typedef BOOL(WINAPI* PFN_SetProcessDpiAwarenessContext)(DPI_AWARENESS_CONTEXT); // User32.lib + dll, Windows 10 v1703+ (Creators Update)
|
||||
|
||||
// Helper function to enable DPI awareness without setting up a manifest
|
||||
void ImGui_ImplWin32_EnableDpiAwareness()
|
||||
|
|
@ -893,7 +895,12 @@ void ImGui_ImplWin32_EnableDpiAwareness()
|
|||
if (_IsWindows10OrGreater())
|
||||
{
|
||||
static HINSTANCE user32_dll = ::LoadLibraryA("user32.dll"); // Reference counted per-process
|
||||
if (PFN_SetThreadDpiAwarenessContext SetThreadDpiAwarenessContextFn = (PFN_SetThreadDpiAwarenessContext)::GetProcAddress(user32_dll, "SetThreadDpiAwarenessContext"))
|
||||
if (PFN_SetProcessDpiAwarenessContext SetProcessDpiAwarenessContextFn = (PFN_SetProcessDpiAwarenessContext)::GetProcAddress(user32_dll, "SetProcessDpiAwarenessContext")) // Windows 10 v1703+
|
||||
{
|
||||
SetProcessDpiAwarenessContextFn(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
|
||||
return;
|
||||
}
|
||||
if (PFN_SetThreadDpiAwarenessContext SetThreadDpiAwarenessContextFn = (PFN_SetThreadDpiAwarenessContext)::GetProcAddress(user32_dll, "SetThreadDpiAwarenessContext")) // Windows 10 v1607+
|
||||
{
|
||||
SetThreadDpiAwarenessContextFn(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -72,13 +72,14 @@ For example, the [example_win32_directx11](https://github.com/ocornut/imgui/tree
|
|||
|
||||
In the [backends/](https://github.com/ocornut/imgui/blob/master/backends) folder:
|
||||
|
||||
List of Platforms Backends:
|
||||
List of Platform Backends:
|
||||
|
||||
imgui_impl_android.cpp ; Android native app API
|
||||
imgui_impl_glfw.cpp ; GLFW (Windows, macOS, Linux, etc.) http://www.glfw.org/
|
||||
imgui_impl_osx.mm ; macOS native API (not as feature complete as glfw/sdl backends)
|
||||
imgui_impl_sdl2.cpp ; SDL2 (Windows, macOS, Linux, iOS, Android) https://www.libsdl.org
|
||||
imgui_impl_sdl3.cpp ; SDL3 (Windows, macOS, Linux, iOS, Android) https://www.libsdl.org
|
||||
imgui_impl_qnx.cpp ; QNX Screen
|
||||
imgui_impl_win32.cpp ; Win32 native API (Windows)
|
||||
imgui_impl_glut.cpp ; GLUT/FreeGLUT (this is prehistoric software and absolutely not recommended today!)
|
||||
|
||||
|
|
@ -89,6 +90,7 @@ List of Renderer Backends:
|
|||
imgui_impl_dx11.cpp ; DirectX11
|
||||
imgui_impl_dx12.cpp ; DirectX12
|
||||
imgui_impl_metal.mm ; Metal (ObjC or C++)
|
||||
imgui_impl_metal4.mm ; Metal 4 (ObjC or C++)
|
||||
imgui_impl_opengl2.cpp ; OpenGL 2 (legacy fixed pipeline. Don't use with modern OpenGL code!)
|
||||
imgui_impl_opengl3.cpp ; OpenGL 3/4, OpenGL ES 2/3, WebGL
|
||||
imgui_impl_sdlgpu3.cpp ; SDL_GPU (portable 3D graphics API of SDL3)
|
||||
|
|
@ -116,7 +118,7 @@ If you are not sure which backend to use, the recommended platform/frameworks fo
|
|||
| GLFW | https://github.com/glfw/glfw | imgui_impl_glfw.cpp | |
|
||||
| Sokol | https://github.com/floooh/sokol | [util/sokol_imgui.h](https://github.com/floooh/sokol/blob/master/util/sokol_imgui.h) | Lower-level than GLFW/SDL |
|
||||
|
||||
If your application runs on Windows or if you are using multi-viewport, the win32 backend handles some details a little better than other backends.
|
||||
If your application runs on Windows or if you are using multi-viewports, the imgui_impl_win32 backend handles some details better than other backends.
|
||||
|
||||
## Using third-party Backends
|
||||
|
||||
|
|
@ -233,9 +235,7 @@ void MyImGuiBackend_RenderDrawData(ImDrawData* draw_data)
|
|||
// - Scissor enabled
|
||||
MyEngineSetupenderState();
|
||||
|
||||
// TODO: Setup texture sampling state
|
||||
// - Sample with bilinear filtering (NOT point/nearest filtering).
|
||||
// - Use 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines;' to allow point/nearest filtering.
|
||||
// TODO: Setup texture sampler to bilinear (NOT point/nearest filtering).
|
||||
|
||||
// TODO: Setup viewport covering draw_data->DisplayPos to draw_data->DisplayPos + draw_data->DisplaySize
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,357 @@ HOW TO UPDATE?
|
|||
and API updates have been a little more frequent lately. They are documented below and in imgui.cpp and should not affect all users.
|
||||
- Please report any issue!
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
VERSION 1.93.0 WIP (In Progress)
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
Breaking Changes:
|
||||
|
||||
- Style: obsoleted `style.CurveTessellationTol (default 1.25)` which was in Pixels² unit in
|
||||
favor of `style.CurveTessellationMaxError` (default 1.12)` which is in Pixels unit. It is
|
||||
easier to tweak + this allows us to easily scale error threshold on high density screens.
|
||||
- style.CurveTessellationMaxError == sqrf(style.CurveTessellationTol).
|
||||
- ImGuiTextFilter: removed `float width` parameter of `Draw(const char* filter, float width)`:
|
||||
prefer using `SetNextItemWidth(float)` which is standard. Kept inline redirection function.
|
||||
- Backends:
|
||||
- DirectX12: Removed support for legacy `ImGui_ImplDX12_Init()` signature, which was
|
||||
obsoleted in 1.91.6 (December 2014), because it needed to forcefully disable support
|
||||
for `ImGuiBackendFlags_RendererHasTextures`. Use the new signature! (#9487)
|
||||
|
||||
Other Changes:
|
||||
|
||||
- Drags, Sliders:
|
||||
- Fixed an overflow using `ImGuiSliderFlags_Logarithmic` with S32/S64 types which
|
||||
leads to clamped interactions. (#9526, #3361, #1823, #1316, #642) [@lailoken]
|
||||
- Ongoing drags may be cancelled using Right-Click, Escape or Gamepad Triangle.
|
||||
Cancelling reverts to the initial value. (#8564, #9534)
|
||||
- TreeNode:
|
||||
- Fixed issues/asserts with 32+ deep trees when using ImGuiTreeNodeFlags_DrawLinesXXX
|
||||
features or other features requiring stack storage. (#9509) [@lasrod]
|
||||
- TabBar:
|
||||
- Improved scroll target when clicking a Tab that is larger than the scrolling
|
||||
section width.
|
||||
- Using <> scrolling buttons while the selected Tab is at either end of the
|
||||
section mid-section but not fully visible always makes it fully visible
|
||||
(before eventually selecting a Tab in the leading/trailing section)
|
||||
- Tables:
|
||||
- Fixed a bug restoring correct .ini columns order when table use is Sortable
|
||||
but had no user changes. (regression from 1.92.9). (#9519, #9108)
|
||||
- InpuText:
|
||||
- Fixed a crash in some cases when using Home key in a WordWrap+ReadOnly field. (#9561)
|
||||
- Selectable:
|
||||
- Fixed `ImGuiSelectableFlags_SelectOnNav` triggering during NavInit.
|
||||
- Fonts:
|
||||
- Reworked `AddFontDefault()` to use `io.DisplayFrameBufferScale` as part of the heuristic
|
||||
to select `AddFontDefaultVector()` by default, effectively using ProggyForever instead of
|
||||
ProggyClean on most Apple/Retina setups by default.
|
||||
- imgui_freetype: Fixed blurryness rendering `AddFontDefaultVector()`. Caused by a
|
||||
non-pixel aligned offset caused by `ExtraSizeScale`. (#9348, #9233) [@redpartizan, @RDMCz]
|
||||
- ColorEdit:
|
||||
- ColorButton, ColorEdit, ColorPicker: cancel-out alpha caused by BeginDisabled() so
|
||||
disabled color buttons have the same color as non-disabled oness. (#9511)
|
||||
- ColorButton: fixed issues/inconsistencies with checkerboard rendering when combining
|
||||
color alpha and global style alpha. (#9511) [@enjmiah, @ocornut]
|
||||
- Popups:
|
||||
- Amended context menu right-click opening code to check that the right-click
|
||||
hasn't been owned by another items. This is more correct and also necessary
|
||||
to avoid Drags/Sliders cancelling also triggering a cancel menu. (#8564, #9534)
|
||||
- Reworked `GetMousePosOnOpeningCurrentPopup()` to be legal to call within the
|
||||
BeginPopup/EndPopup scope of a popup which was just closed. (#9551) [@jkunstwald]
|
||||
- ImGuiTextFilter:
|
||||
- Added support for space as an "and" filter, which is the standard. (#2435, #30)
|
||||
e.g. w/ filter 'hello world' (without quotes) both words needs to be in input data.
|
||||
- Added support for double-quoted "xxx" blocks to e.g. match words sequences. (#2435)
|
||||
e.g. w/ filter "hello world" the exact sequence needs to be in input data.
|
||||
- Fixed filtering when mixing "include" and "-exclude" keyword so that an "-exclude"
|
||||
match always filters out. (#2435) [@kudaba, @ocornut]
|
||||
- Added `DrawWithHint()` function. (#6206, #6395, #6447)
|
||||
- Added a "incl -excl" hint by default when the search field is empty. (#6206, #6395, #6447)
|
||||
- Style:
|
||||
- Inverted `ImGuiCol_TitleBgXXX` colors for `StyleColorsLight()` so that the selected
|
||||
window title bar appears brighter.
|
||||
- Misc:
|
||||
- Added `ImGuiItemFlags_MixedValue` flag for representing mixed/indeterminate values.
|
||||
Supported by: Checkbox(), RadioButton(), DragXXX(), SliderXXX(), InputXXX(), ColorXXX()
|
||||
and Combo() functions.
|
||||
The scoped flag is designed for usage by advanced property editors. (#5518, #5677, #6865)
|
||||
- Fixed `GetBackgroundDrawList()`/`GetForegroundDrawList()` not being properly reset
|
||||
every frame when cumulated session time is very large (e.g. a few days). [@lailoken]
|
||||
- Added `IM_NODEBUGSTEP` helper to tag functions with `__declspec(non_user_code)` (MSVC)
|
||||
or `[[gnu::artificial]]` (Clang/GCC) in order to provide a hint to debuggers to skip
|
||||
trivial functions when stepping into.
|
||||
- Tagged various trivial functions using `IM_NODEBUGSTEP`: `ImVec2()`, `ImVec4()` etc.
|
||||
and various operators.
|
||||
- Fixed strict aliasing violation in `ImHashData()` affecting Clang 23 + SSE 4.2 + -flto.
|
||||
Could manifest as `ImFontAtlasBakedGetId()` computation omitting font size from
|
||||
the hashed data. (#9557, #9560) [@sthalik]
|
||||
- IO: restore default clipboard/ime/shell platform handlers on ClearPlatformHandlers(), fixing
|
||||
issues switching backends mid-session to one relying on default. (#9537, #8945, #2769) [@lstalmir]
|
||||
- DrawList:
|
||||
- Per-viewport FramebufferScale for Apple/Retina screen is applied to draw lists:
|
||||
- AA Fringe is scaled accordingly.
|
||||
- Circle and Curves tessellation error are scaled accordingly.
|
||||
- Reworked assert in PushTexture() to allow convenience grace period of using a
|
||||
texture that was queue for destroy during the frame. Make it safe to stick to
|
||||
an existing texture during the frame. (#9528, #8465)
|
||||
- Added optional `platform_io.DrawCallback_SetSamplerFromTex` standard backend-agnostic
|
||||
draw callback for requesting to use the sampler associated already associated to a texture.
|
||||
Currently only supported by the OpenGL2/3 and SDLRenderer3 backend. (#9378)
|
||||
- Fixed dangling ImDrawList::_OwnerName when using animated label. (#9552) [@ubi-dcastonguay]
|
||||
- Demo:
|
||||
- Added `Widgets->Mixed Values` section. (#5518, #5677, #6865)
|
||||
- Style Editor: fixed style/colors combo box applying style when opening Combo.
|
||||
- Backends:
|
||||
- QNX: added QNX Screen backend. (#9492) [@mgorchak-blackberry]
|
||||
- OpenGL2, OpenGL3: added support for `platform_io.DrawCallback_SetSamplerFromTex` draw
|
||||
callback to request using the sampler associated already associated to a texture. (#9378)
|
||||
- OpenGL2, OpenGL3: fixed `DrawCallback_ResetRenderState` handler not reseting all states
|
||||
in the glTexParameter() path. (#9378)
|
||||
- SDL2: fixed querying framebuffer scale/density when using Metal without
|
||||
going through a SDL_Renderer. (#5592) [@lailoken]
|
||||
- SDLRenderer3: restore any temporarily modified texture scale modes at the of `RenderDrawData()`. (#9378)
|
||||
- SDLRenderer3: expose CurrentScaleMode in ImGui_ImplSDLRenderer3_RenderState. (#9543, #9378) [@Clownacy]
|
||||
- SDLRenderer3: added support for `platform_io.DrawCallback_SetSamplerFromTex` draw callback to request
|
||||
using the sampler associated already associated to a texture via `SDL_SetTextureScaleMode()`. (#9378)
|
||||
It is equivalent to setting `render_state->CurrentScaleMode = SDL_SCALEMODE_INVALID`.
|
||||
Note: this callback is only supported by selected rendering backends: most other graphics API
|
||||
don't have the equivalent of `SDL_SetTextureScaleMode()` and the callback won't work with them.
|
||||
- Vulkan: added for support for multiple Vulkan contexts with custom loaders. (#6616) [@lstalmir]
|
||||
- WebGPU: fixed passing non-integer sizes to `wgpuRenderPassEncoderSetViewport()`
|
||||
when `FramebufferScale` is >1.0f. (#9515, #8628) [@WayU]
|
||||
- WebGPU: update to build with wgpu-native 29.0+. (#9377, #9532, #9530) [@lucascompython, @ivan-enzhaev]
|
||||
- Examples:
|
||||
- MSVC: disabled /JMC in Visual Studio projects (unnecessary overhead).
|
||||
- GLFW/SDL2/SDL3+WebGPU: fixed running with wgpu-native missing `wgpuInstanceWaitAny()`. (#9377)
|
||||
- SDL2+Metal: create Metal context without using a `SDL_Renderer`.
|
||||
- QNX+OpenGL3, QNX+Vulkan: added QNX Screen examples. (#9492) [@mgorchak-blackberry]
|
||||
- OSX+OpenGL3: added example_apple_opengl3/ (OSX/Cocoa + OpenGL 3.2 Core profile).
|
||||
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
VERSION 1.92.9b (Released 2026-07-31)
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.92.9b
|
||||
|
||||
Changes:
|
||||
|
||||
- DragXXX, SliderXXX: fixed a regression in 1.92.9 where clicking a previously
|
||||
Ctrl+Clicked field would flick it to text edit mode for a frame. (#9476, #701)
|
||||
- Tables:
|
||||
- Fixed Y2 position of lower horizontal border (ImGuiTableFlags_BordersOuterH)
|
||||
being off by one pixel when vertical ones are not also enabled. [@thedmd]
|
||||
- Fixed X position of angled borders being off by half a pixel. [@thedmd]
|
||||
- ImDrawData: fixed a regression in 1.92.9 where legacy `ImDrawData::CmdListsCount` was always 0.
|
||||
Prefer using `ImDrawData::CmdList.Size` anyway.
|
||||
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
VERSION 1.92.9 (Released 2026-07-25)
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.92.9
|
||||
|
||||
Breaking Changes:
|
||||
|
||||
- DragXXX, SliderXXX, InputScalar: with `ImGuiItemFlags_LiveEditOnInputScalar` now
|
||||
defaulting to being disabled: inputting a value with the keyboard doesn't write
|
||||
intermediate values to the backing variable. (#9476)
|
||||
Before: DragFloat() with user typing "123" --> write back 1, then 12, then 123.
|
||||
After: DragFloat() with user typing "123" --> write back 123 when validated/unfocused.
|
||||
You can enable the flag back for a given scope if needed by specific widget/behavior.
|
||||
Read below for details.
|
||||
- TreeNode: commented out legacy name `ImGuiTreeNodeFlags_SpanTextWidth` which
|
||||
was obsoleted in 1.90.7 (May 2024). Use `ImGuiTreeNodeFlags_SpanLabelWidth`.
|
||||
- ColorEdit: obsoleted SetColorEditOptions() function added in 1.51 (June 2017) in favor
|
||||
of directly poking to io.ConfigColorEditFlags. More consistent and easier to discover.
|
||||
- Drag and Drop: commented out legacy name `ImGuiDragDropFlags_SourceAutoExpirePayload`
|
||||
which obsoleted in 1.90.9 (July 2024). Use `ImGuiDragDropFlags_PayloadAutoExpire`.
|
||||
- ImDrawData: marked `CmdListsCount` as obsolete (technically was obsoleted in 1.89.8).
|
||||
Before: `draw_data->CmdListsCount`, After: `draw_data->CmdLists.Size`.
|
||||
|
||||
Other Changes:
|
||||
|
||||
- LiveEdit on/off: added `ImGuiItemFlags_LiveEditOnInputText` and `ImGuiItemFlags_LiveEditOnInputScalar`
|
||||
flags to configure the timing of applying edits of backing variables when typing
|
||||
values using a keyboard.
|
||||
(#9476, #701, #3936, #3946, #5904, #6284, #8149, #8065, #8665, #9117, #9299, #700, #1351,
|
||||
#1875, #2060, #2215, #2380, #2550, #3083, #3338, #3556, #4373, #4714, #4885, #5184,
|
||||
#5777, #6707, #6766, #8004, #8303, #8915, #9308)
|
||||
- ImGuiItemFlags_LiveEditOnInputText is enabled by default (same as before):
|
||||
- The expectation is that for strings/text, enabling LiveEdit is a better default.
|
||||
- ImGuiItemFlags_LiveEditOnInputScalar is disabled by default (new behavior):
|
||||
- The expectation is that for numeric/scalars values, disabling LiveEdit is a better default.
|
||||
- Until now:
|
||||
- Edits where always applied immediately to backing variable, which is equivalent
|
||||
to the `ImGuiItemFlags_LiveEditXXX` flags being enabled.
|
||||
- Typing '123' in an integer field would output successively 1, 12 then 123.
|
||||
- Most uses of `IsItemDeactivatedAfterEdit()` or `ImGuiInputTextFlags_EnterReturnsTrue`
|
||||
were actually workarounds for this issue. Advanced applications would typically
|
||||
use `IsItemDeactivatedAfterEdit()` to distinguish transactions.
|
||||
Workarounds often required a backing store for scalar values, and there were
|
||||
also a few niggles related to `IsItemDeactivatedAfterEdit()` when using +/-
|
||||
buttons of an `InputInt()` widgets.
|
||||
- Many of those situations can now be naturally simplified when disabling
|
||||
`ImGuiItemFlags_LiveEditOnInputScalar` is disabled.
|
||||
- The new flags allows disabling this behavior selectively for strings fields
|
||||
such as `InputText()` vs scalar fields: `SliderInt()`, `InputFloat()`, etc.
|
||||
- When LiveEdit is disabled, edits are applied when pressing enter, tabbing out,
|
||||
clearing a field or deactivating due to a focus loss.
|
||||
- The flag may be altered programmatically, e.g. for the entire frame scope:
|
||||
NewFrame();
|
||||
PushItemFlag(ImGuiItemFlags_LiveEditOnInputScalar, true); // Enable for scalars for the whole frame
|
||||
....
|
||||
PopItemFlag();
|
||||
EndFrame();
|
||||
Or for a specific widget:
|
||||
PushItemFlag(ImGuiItemFlags_LiveEditOnInput, true); // Enable for one widget
|
||||
SliderInt(...);
|
||||
PopItemFlag();
|
||||
- We intentionally are not adding `io.ConfigLiveEditXXX` fields to dictate the
|
||||
default value of each `ImGuiItemFlags_LiveEditXXX`, because this is not expected
|
||||
to be a user preference but a programmer/widget preferences.
|
||||
And we strive to make the toolkit consistent.
|
||||
- Windows:
|
||||
- Clicking on a window's empty-space to move/focus a window checks
|
||||
for lack of mouse button ownership. This gives an additional opportunity
|
||||
for user code to bypass it without using a clickable item. (#9382)
|
||||
- Clicking on a window's empty-space to move/focus a window checks
|
||||
for lack of queued focus request. (#9382)
|
||||
- Fixed double-click collapse toggle not owning the mouse button. If a
|
||||
`SetNextWindowPos()` with pivot was queued in the same frame, the second
|
||||
click could trigger another item in the same window. (#9439) [@Cleroth]
|
||||
- Popups:
|
||||
- Added bool return value to `OpenPopup()`, `OpenPopupOnItemClick()` functions
|
||||
to notify when the popup was just opened. (#9429)
|
||||
- InputText:
|
||||
- Added `style.InputTextCursorSize` to configure cursor/caret thickness. (#7031, #9409)
|
||||
It is automatically scaled by `style.ScaleAllSizes()`.
|
||||
- Reworked `io.ConfigInputTextEnterKeepActive` mode so that pressing
|
||||
Ctrl+Enter or Shift+Enter still allows to deactivate. (#9239)
|
||||
- Tables:
|
||||
- Redesigned/rewrote code to reconcile columns and settings on topology changes. (#9108)
|
||||
- When a column label is passed to TableSetupColumn(), the underlying identifier
|
||||
is used to match live columns data and .ini settings data when changing.
|
||||
This makes it possible to add/remove columns from a table without losing
|
||||
neither live data neither .ini settings data.
|
||||
- PS: Note that this is distinct from toggling column visibility or reordering
|
||||
columns, which was always possible. The new matching makes it easier to create
|
||||
tables that are entirely customized by user or code, without losing state.
|
||||
- Columns without identifiers or with duplicate identifiers are matched
|
||||
sequentially, matching old behavior.
|
||||
- Column ID are stored in .ini file.
|
||||
- Code is being tested both for live topology changes and for loading .ini
|
||||
data with mismatched topology.
|
||||
- Context Menu: added a "Reset" sub-menu with a "Reset Visibility" option.
|
||||
(which is greyed out when using default settings)
|
||||
- Headers: fixed label being clipped early to reserve space for a sort marker
|
||||
even when no sort marker is displayed. Auto-fitting a column still accounts
|
||||
for the possible marker, so that sorting after an auto-fit doesn't clip the label.
|
||||
- Multi-Select:
|
||||
- Reworked `ImGuiMultiSelectFlags_NoAutoSelect` as it carried side-effects that
|
||||
were hardcoded/designed to use multi-selection on checkboxes. (#9391)
|
||||
Specifically removed those undocumented behaviors from `_NoAutoSelect`:
|
||||
- Clicking a selected/checked item always unselect/uncheck.
|
||||
- Shift+Click inverts targets value and copy to range.
|
||||
- Shift+Keyboard copy selection source value to range.
|
||||
Those behaviors are still happening on checkboxes used within multi-selection.
|
||||
- Fonts:
|
||||
- Added `IMGUI_DISABLE_DEFAULT_FONT_BITMAP`/`IMGUI_DISABLE_DEFAULT_FONT_VECTOR` to
|
||||
disable embedding either fonts separately. (#9407)
|
||||
- Tweak `CalcTextSize()` awkward width rounding/ceiling code to reduce floating-point
|
||||
precision issues altering the result by 1 even at relatively small width. (#791)
|
||||
- Better document the fact that `ImFontAtlas::Clear()`/`ClearFonts()` functions are
|
||||
unlikely to be useful nowadays. Better recover to an edge case of mistakenly
|
||||
calling `ClearFonts()` during rendering.
|
||||
- Fixed an issue where passing a manually created ImFontAtlas to CreateContext() would
|
||||
incorrectly destroy it in `DestroyContext()` when ref-count gets back to zero. (#9426)
|
||||
- Destroying an ImGui context using a `ImFontAtlas` checks that the later has no references.
|
||||
- Nav:
|
||||
- Fixed context menu activation with gamepad erroneously testing for _NavEnableKeyboard
|
||||
instead of _NavEnableGamepad. (#9454, #8803, #9270) [@Clownacy]
|
||||
- TreeNode:
|
||||
- Fixed nav cursor rendering with rounding even though tree nodes don't have it. (#7589)
|
||||
- Inputs:
|
||||
- Added `GetItemClickedCountWithSingleClickDelay()` helper for easy disambiguation
|
||||
between single-click and double-click for actions that needs single-click to do
|
||||
something other than selection. (#8337)
|
||||
- Returns 1 on single-click but delayed by io.MouseSingleClickDelay.
|
||||
- Returns 2 on double-click, and 2+ on subsequent repeated clicks.
|
||||
- Added `io.MouseSingleClickDelay` to configure default delayed single click delay when
|
||||
using `GetItemClickedCountWithSingleClickDelay()` or `IsMouseReleasedWithDelay()`. (#8337)
|
||||
Note that `io.MouseSingleClickDelay` is always `> io.MouseDoubleClickTime`.
|
||||
- ColorEdit:
|
||||
- Added `io.ConfigColorEditFlags` to read/modify current color edit/picker settings.
|
||||
- ColorPicker: added `ImGuiColorEditFlags_PickerNoRotate` to disable rotation of the
|
||||
S/V triangle when in `ImGuiColorEditFlags_PickerHueWheel` mode. (#9337) [@SeanTheBuilder1]
|
||||
Likely best passed to `style.ColorEditFlags` to setup globally and once.
|
||||
- ColorButton: small rendering tweak/optimization for the alpha checkerboard.
|
||||
- Style:
|
||||
- Added style.MenuItemRounding, ImGuiStyleVar_MenuItemRounding. (#7589, #9375, #9453)
|
||||
- Added style.SelectableRounding, ImGuiStyleVar_SelectableRounding. (#7589, #9375, #9453)
|
||||
The use of this is discouraged because it can easily create problems rendering e.g.
|
||||
contiguous selection.
|
||||
- Scale the NavCursor border thickness when using large values with `ScallAllSizes()`.
|
||||
- Settings:
|
||||
- Windows/Tables settings entries can now record the last used date in YYYYMMDD format,
|
||||
allowing tools to run to e.g. delete entries that haven't been used in X months. (#9460)
|
||||
- Added `bool io.ConfigIniSettingsSaveLastUsedDate` to disable saving that info. (#9460)
|
||||
- Added `int io.ConfigIniSettingsAutoDiscardMonths` to enable a mode where unused settings
|
||||
are automatically discard after xx months. (#9460)
|
||||
- Added a trimming tool under Metrics->Settings, along with a yet-unexposed function.
|
||||
- The current system date is fed through `ImGuiPlatformIO::Platform_SessionDate`,
|
||||
which is automatically set by a call to time() done during context creation. (#9460)
|
||||
- Added `IMGUI_DISABLE_TIME_FUNCTIONS` to disable setting platform_io.Platform_SessionDate.
|
||||
A custom backend may still set it manually. (#9460)
|
||||
- DrawList:
|
||||
- Minor optimization to `AddLine()`, `AddLineH()`, `AddLineV()` functions. (#4091)
|
||||
- Added `ImDrawListFlags_TextNoPixelSnap` to disable snapping of AddText()
|
||||
coordinates for a given scope. (#3437, #9417, #2291)
|
||||
- Demo:
|
||||
- Extract 'Widgets->Tree Nodes->Selectable Nodes' out of the 'Advanced'
|
||||
demo for clarity (manual reimplementation of basic selection).
|
||||
- Debug Tools:
|
||||
- Added `IM_DEBUG_BREAK()` handler for GCC+AArch64/ARM64. [@tom-seddon]
|
||||
- Backends:
|
||||
- Android:
|
||||
- Clear mouse position on touch release (`AMOTION_EVENT_ACTION_UP`) to prevent
|
||||
items from staying in hovered state. (#6627, #9474) [@Turtle-PB]
|
||||
- Metal4:
|
||||
- Added new Metal 4 backend (forked from Metal 3 backend). (#9458, #9451) [@AmelieHeinrich]
|
||||
- Added Metal-cpp support enabled with `IMGUI_IMPL_METAL_CPP` define. (#9461) [@MERL10N]
|
||||
- OpenGL2:
|
||||
- Backup and restore `GL_UNPACK_ROW_LENGTH` and `GL_UNPACK_ALIGNMENT` when updating texture
|
||||
to avoid altering caller GL state. (#8802, #9473) [@Turtle-PB]
|
||||
- OpenGL3:
|
||||
- GLSL version detection assume GLSL 410 when GL context is 4.1.
|
||||
Fixes an issue running on macOS with Wine. [#9427, #6577) [@perminovVS]
|
||||
- Expose selected render state in `ImGui_ImplOpenGL3_RenderState`, allowing to
|
||||
dynamically select between use of `glBindSampler()` and `glTexParameter()`. (#9378)
|
||||
- Backup and restore `GL_UNPACK_ROW_LENGTH` and `GL_UNPACK_ALIGNMENT` when updating texture
|
||||
to avoid altering caller GL state. (#8802, #9473) [@Turtle-PB]
|
||||
- SDL2:
|
||||
- Restore SDL_StartTextInput()/SDL_StopTextInput() in IME handler for on-screen keyboard
|
||||
support on Android. (#7636, #9474) [@Turtle-PB]
|
||||
- SDLRenderer3:
|
||||
- Fixed sampler change which didn't work on all graphics backends. (#7616, #9470, #9378)
|
||||
- Fixed default sampler not being Linear. Regression in 1.92.8. (#7616, #9470, #9378) [@ShiroKSH]
|
||||
- Win32:
|
||||
- Uses `SetProcessDpiAwarenessContext()` instead of `SetThreadDpiAwarenessContext()`
|
||||
when available, fixing OpenGL DPI scaling issues as e.g. NVIDIA drivers tends
|
||||
to spawn multiple-thread to manage OpenGL. (#9403)
|
||||
- Examples:
|
||||
- Android: update to AGP 9.2.0 to support Gradle 9.6.0.
|
||||
- Apple+Metal4: added new example. (#9465, #9451) [@hoffstadt]
|
||||
- OpenGL3+GLFW/SDL2/SDL3: allow Wine compatibility by passing empty GLSL version
|
||||
string to ImGui_ImplOpenGL3_Init() to let backend decide of a GLSL version based
|
||||
on actual GL version obtained. (#9427, #6577) [@perminovVS]
|
||||
- OpenGL3+Win32: rework context creation to allow Wine compatibility. (#9427, #6577) [@perminovVS]
|
||||
- SDL2/SDL3: use `SDL_GetWindowSizeInPixels()` to create frame-buffers. Fixes issues
|
||||
with non-fractional framebuffer size on Wayland. (#8761, #9124) [@billtran1632001]
|
||||
- SDL3+Metal4: added new example. (#9458, #9451) [@AmelieHeinrich]
|
||||
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
VERSION 1.92.8 (Released 2026-05-12)
|
||||
-----------------------------------------------------------------------
|
||||
|
|
@ -64,9 +415,13 @@ Breaking Changes:
|
|||
The new order is also more convenient as `flags` are less frequently used than `thickness` in real code.
|
||||
- As a general policy in Dear ImGui, all our flags default to 0 so ImDrawFlags_None was likely written 0 in some call sites.
|
||||
- Consider adding `#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS` in your imconfig.h, even temporarily, to clean up legacy code.
|
||||
- Reminder: you do NOT need to specify `ImDrawFlags_RoundCornersAll` for rounding, it is already the default!
|
||||
- DrawList: obsoleted `ImDrawCallback_ResetRenderState` in favor of using `ImGui::GetPlatformIO().DrawCallback_ResetRenderState`,
|
||||
which is part of our new standard draw callbacks. (#9378)
|
||||
Redirecting the earlier value into the later one when set, so both old and new code should work.
|
||||
- DrawList: changed value of `ImDrawFlags_Closed`. It was previously advertised as "always == 1" when introduced
|
||||
in 1.82 (2021/02), in order to facilitate backward compatibility with the legacy `bool closed` flag. This
|
||||
guarantee has been removed. The bit is reserved, and `AddPolyline()`, `PathStroke()` will assert when it is used.
|
||||
- Backends:
|
||||
- Vulkan: redesigned to use separate ImageView + Sampler instead of Combined Image Sampler. (#914)
|
||||
This change allows us to facilitate changing samplers, in line with other backends. [@yaz0r, @ocornut]
|
||||
|
|
@ -81,6 +436,8 @@ Breaking Changes:
|
|||
- DirectX10, DirectX11, SDLGPU3, Vulkan: removed samplers from `ImGui_ImplXXXX_RenderState`.
|
||||
Prefer to use backend-agnostic DrawCallback_SetSamplerLinear which works everywhere! (#9378)
|
||||
If there is a legit need/request for them or any render state we can always add them back.
|
||||
- OpenGL3: the new sampler support system prioritize using glBindSampler() when available,
|
||||
which would override glTexParameter() settings you may have set on custom textures. (#9378)
|
||||
|
||||
Other Changes:
|
||||
|
||||
|
|
@ -97,6 +454,15 @@ Other Changes:
|
|||
#5999, #6452, #5156, #7342, #7592, #7511)
|
||||
- Made `AddCallback()` user data default to Null for convenience.
|
||||
- Added `AddLineH()`, `AddLineV()` helpers to draw horizontal and vertical lines. [@memononen]
|
||||
The new functions are more optimal and will be part of a larger effort in 1.93 to fix
|
||||
inconsistencies and improve the DrawList API. In the current API, `AddLine()` adds a "magic" +0.5f
|
||||
offset and then center the line, whereas AddLineH()/AddLineV() use the right side of the line to expand.
|
||||
For thickness=1.0f lines this is equivalent:
|
||||
`AddLine({10,3}, {20,3}, ...)` --> `AddLineH(x1=10, x2=20, y=3, ...)`.
|
||||
`AddLine({3,10}, {3,20}, ...)` --> `AddLineV(x=3, y1=10, y2=20, ...)`.
|
||||
For larger integer thickness, AddLine() will center but may be blurry, AddLineH()/AddLineV()
|
||||
will expand "inside" (to the right side) and will always be sharp.
|
||||
A subsequent release will expand on those concepts and add new options.
|
||||
- InputText:
|
||||
- InputTextMultiline: fixed an issue processing deactivation logic when an active
|
||||
multi-line edit is clipped due to being out of view.
|
||||
|
|
@ -885,7 +1251,7 @@ Other Changes:
|
|||
not available. (#5924, #5562)
|
||||
- SDL3+DirectX11: Added SDL3+DirectX11 example. (#8956, #8957) [@tomaz82]
|
||||
- Win32+DirectX12: Rework synchronization logic. (#8961) [@RT2Code]
|
||||
- Made examples's main.cpp consistent with returning 1 on error.
|
||||
- Made examples' main.cpp consistent with returning 1 on error.
|
||||
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
|
|
@ -1396,7 +1762,7 @@ Non-breaking Fonts/Textures related changes:
|
|||
- Fonts: ImFontAtlas::AddFontXXX() can fail more gracefully if error handling is configured
|
||||
to not assert (this will be better exposed via future font flags).
|
||||
- Fonts: added style.FontScaleBase scaling factor (previously called io.FontGlobalScale).
|
||||
- Fonts: added style.FontScaleDpi scaling factor. This is designed to be be changed on
|
||||
- Fonts: added style.FontScaleDpi scaling factor. This is designed to be changed on
|
||||
per-monitor/per-viewport basis, which `io.ConfigDpiScaleFonts` does automatically.
|
||||
(which is why it is separate from FontScaleBase).
|
||||
- Fonts: added optional font_size parameter to ImGui::PushFont() function.
|
||||
|
|
@ -2551,7 +2917,7 @@ Other changes:
|
|||
- Backends: Vulkan: Remove Volk/ from volk.h #include directives. (#7722, #6582, #4854)
|
||||
[@martin-ejdestig]
|
||||
- Examples: SDL3: Remove use of SDL_HINT_IME_NATIVE_UI since new SDL_HINT_IME_IMPLEMENTED_UI
|
||||
values has a more suitable default for our case case.
|
||||
values has a more suitable default for our case.
|
||||
- Examples: GLFW+Vulkan, SDL+Vulkan: handle swap chain resize even without Vulkan
|
||||
returning VK_SUBOPTIMAL_KHR, which doesn't seem to happen on Wayland. (#7671)
|
||||
[@AndreiNego, @ocornut]
|
||||
|
|
@ -3327,8 +3693,10 @@ Breaking changes:
|
|||
input queue. This is automatically cleared by io.ClearInputKeys(). (#4921)
|
||||
- ImDrawData: CmdLists[] array is now owned, changed from 'ImDrawList**' to
|
||||
'ImVector<ImDrawList*>'. Majority of users shouldn't be affected, but you
|
||||
cannot compare to NULL nor reassign manually anymore.
|
||||
Instead use AddDrawList(). Allocation count are identical. (#6406, #4879, #1878)
|
||||
cannot compare to NULL nor reassign manually anymore. (#6406, #4879, #1878)
|
||||
- Allocation count are identical.
|
||||
- Use `draw_data->CmdLists.Size` instead of `draw_list->CmdListsCount`!
|
||||
- Use `AddDrawList()` to add to a `ImDrawData`.
|
||||
|
||||
Other changes:
|
||||
|
||||
|
|
@ -4502,7 +4870,7 @@ Other Changes:
|
|||
- ColorPicker4: Fixed picker being unable to select exact 1.0f color when dragging toward the edges
|
||||
of the SV square (previously picked 0.999989986f). (#3517) [@rokups]
|
||||
- Menus: Fixed vertical alignments of MenuItem() calls within a menu bar (broken in 1.84). (#4538)
|
||||
- Menus: Improve closing logic when moving diagonally in empty between between parent and child menus to
|
||||
- Menus: Improve closing logic when moving diagonally in empty space between parent and child menus to
|
||||
accommodate for varying font size and dpi.
|
||||
- Menus: Fixed crash when navigating left inside a child window inside a sub-menu. (#4510).
|
||||
- Menus: Fixed an assertion happening in some situations when closing nested menus (broken in 1.83). (#4640)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
## Index
|
||||
|
||||
- [Getting Started & General Advice](#getting-started--general-advice)
|
||||
- [Issues vs Discussions](#issues-vs-discussions)
|
||||
- [Using "Issues" for almost everything!](using-issues-for-almost-everything)
|
||||
- [How to open an Issue](#how-to-open-an-issue)
|
||||
- [How to open a Pull Request](#how-to-open-a-pull-request)
|
||||
- [Copyright / Contributor License Agreement](#copyright--contributor-license-agreement)
|
||||
|
|
@ -23,18 +23,20 @@
|
|||
- If you get a crash or assert, use a debugger to locate the line triggering it and read the comments around.
|
||||
- Please don't be a [Help Vampire](https://slash7.com/2006/12/22/vampires/).
|
||||
|
||||
## 'Issues' vs 'Discussions'
|
||||
## Using "Issues" for almost everything!
|
||||
|
||||
We are happy to use 'Issues' for many type of open-ended questions. We are encouraging 'Issues' becoming an enormous, centralized and cross-referenced database of Dear ImGui contents.
|
||||
We are happy to use 'Issues' for many type of open-ended questions.
|
||||
We are encouraging 'Issues' becoming an enormous, centralized and cross-referenced database of Dear ImGui contents.
|
||||
|
||||
Only if you:
|
||||
- Need help using the API? Open an Issue!
|
||||
- Want to suggest a feature? Open an Issue!
|
||||
- etc.
|
||||
|
||||
ONLY IN THOSE CASE you can use the [Discussions forums](https://github.com/ocornut/imgui/discussions)
|
||||
- Cannot BUILD or LINK examples.
|
||||
- Cannot BUILD, or LINK, or RUN Dear ImGui in your application or custom engine.
|
||||
- Cannot LOAD a font.
|
||||
|
||||
Then please [use the Discussions forums](https://github.com/ocornut/imgui/discussions) instead of opening an issue.
|
||||
|
||||
If Dear ImGui is successfully showing in your app and you have used Dear ImGui before, you can open an Issue. Any form of discussions is welcome as a new issue.
|
||||
If Dear ImGui is successfully showing in your app and you have used Dear ImGui before, you can open an Issue. Any form of discussions is welcome as a new Issue.
|
||||
|
||||
## How to open an issue
|
||||
|
||||
|
|
|
|||
|
|
@ -60,16 +60,20 @@ Android + OpenGL3 (ES) example. <BR>
|
|||
|
||||
[example_apple_metal/](https://github.com/ocornut/imgui/tree/master/examples/example_apple_metal/) <BR>
|
||||
OSX & iOS + Metal example. <BR>
|
||||
= main.m + imgui_impl_osx.mm + imgui_impl_metal.mm <BR>
|
||||
= main.mm + imgui_impl_osx.mm + imgui_impl_metal.mm <BR>
|
||||
It is based on the "cross-platform" game template provided with Xcode as of Xcode 9.
|
||||
(NB: imgui_impl_osx.mm is currently not as feature complete as other platforms backends.
|
||||
You may prefer to use the GLFW Or SDL backends, which will also support Windows and Linux.)
|
||||
|
||||
[example_apple_metal4/](https://github.com/ocornut/imgui/blob/master/examples/example_apple_metal4/) <BR>
|
||||
OSX & iOS + Metal4 example, Mac only. <BR>
|
||||
= main.mm + imgui_impl_osx.mm + imgui_impl_metal4.mm <BR>
|
||||
|
||||
[example_apple_opengl2/](https://github.com/ocornut/imgui/blob/master/examples/example_apple_opengl2/) <BR>
|
||||
OSX + OpenGL2 example. <BR>
|
||||
= main.mm + imgui_impl_osx.mm + imgui_impl_opengl2.cpp <BR>
|
||||
(NB: imgui_impl_osx.mm is currently not as feature complete as other platforms backends.
|
||||
You may prefer to use the GLFW Or SDL backends, which will also support Windows and Linux.)
|
||||
|
||||
[example_apple_opengl3/](https://github.com/ocornut/imgui/blob/master/examples/example_apple_opengl3/) <BR>
|
||||
OSX + OpenGL3 example. <BR>
|
||||
= main.mm + imgui_impl_osx.mm + imgui_impl_opengl3.cpp <BR>
|
||||
|
||||
[example_glfw_wgpu/](https://github.com/ocornut/imgui/blob/master/examples/example_glfw_wgpu/) <BR>
|
||||
GLFW + WebGPU example. Supports Emscripten (web), Dawn (native), WGPU (native). <BR>
|
||||
|
|
@ -115,6 +119,16 @@ Because this application doesn't create a window nor a graphic context, there's
|
|||
Please note that imgui_impl_null itself is a rather empty backend. We provide it for consistency but
|
||||
it is similarly easy to create a skeleton application without the null backend.
|
||||
|
||||
[example_qnx_opengl3/](https://github.com/ocornut/imgui/blob/master/examples/example_qnx_opengl3/) <BR>
|
||||
QNX Screen + OpenGL ES 3 example. <BR>
|
||||
= main.cpp + imgui_impl_qnx.cpp + imgui_impl_opengl3.cpp <BR>
|
||||
Uses the QNX recursive make build system and compiles the OpenGL3 renderer with `IMGUI_IMPL_OPENGL_ES3`.
|
||||
|
||||
[example_qnx_vulkan/](https://github.com/ocornut/imgui/blob/master/examples/example_qnx_vulkan/) <BR>
|
||||
QNX Screen + Vulkan example using `VK_QNX_screen_surface`. <BR>
|
||||
= main.cpp + imgui_impl_qnx.cpp + imgui_impl_vulkan.cpp <BR>
|
||||
Uses the QNX recursive make build system and the Vulkan backend's example helper structures.
|
||||
|
||||
[example_sdl2_directx11/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl2_directx11/) <BR>
|
||||
SDL2 + DirectX11 example, Windows only. <BR>
|
||||
= main.cpp + imgui_impl_sdl2.cpp + imgui_impl_dx11.cpp <BR>
|
||||
|
|
@ -164,6 +178,10 @@ SDL3 + DirectX11 examples, Windows only. <BR>
|
|||
SDL3 + Metal example, Mac only. <BR>
|
||||
= main.cpp + imgui_impl_sdl3.cpp + imgui_impl_metal.mm <BR>
|
||||
|
||||
[example_sdl3_metal4/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl3_metal/) <BR>
|
||||
SDL3 + Metal4 example, Mac only. <BR>
|
||||
= main.cpp + imgui_impl_sdl3.cpp + imgui_impl_metal4.mm <BR>
|
||||
|
||||
[example_sdl3_opengl3/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl3_opengl3/) <BR>
|
||||
SDL3 (Win32, Mac, Linux, etc.) + OpenGL3+/ES2/ES3 example. <BR>
|
||||
= main.cpp + imgui_impl_sdl3.cpp + imgui_impl_opengl3.cpp <BR>
|
||||
|
|
|
|||
124
docs/FAQ.md
124
docs/FAQ.md
|
|
@ -9,42 +9,58 @@ or view this file with any Markdown viewer.
|
|||
|
||||
## Index
|
||||
|
||||
| **Q&A: Basics** |
|
||||
:---------------------------------------------------------- |
|
||||
| [Where is the documentation?](#q-where-is-the-documentation) |
|
||||
| [What is this library called?](#q-what-is-this-library-called) |
|
||||
| [What is the difference between Dear ImGui and traditional UI toolkits?](#q-what-is-the-difference-between-dear-imgui-and-traditional-ui-toolkits) |
|
||||
| [Which version should I get?](#q-which-version-should-i-get) |
|
||||
| **Q&A: Integration** |
|
||||
| **[How to get started?](#q-how-to-get-started)** |
|
||||
| **[How can I tell whether to dispatch mouse/keyboard to Dear ImGui or my application?](#q-how-can-i-tell-whether-to-dispatch-mousekeyboard-to-dear-imgui-or-my-application)** |
|
||||
| [How can I enable keyboard or gamepad controls?](#q-how-can-i-enable-keyboard-or-gamepad-controls) |
|
||||
| [How can I use this on a machine without mouse, keyboard or screen? (input share, remote display)](#q-how-can-i-use-this-on-a-machine-without-mouse-keyboard-or-screen-input-share-remote-display) |
|
||||
| [How can I create my own backend?](#q-how-can-i-create-my-own-backend)
|
||||
| [I integrated Dear ImGui in my engine and little squares are showing instead of text...](#q-i-integrated-dear-imgui-in-my-engine-and-little-squares-are-showing-instead-of-text) |
|
||||
| [I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around...](#q-i-integrated-dear-imgui-in-my-engine-and-some-elements-are-clipping-or-disappearing-when-i-move-windows-around) |
|
||||
| [I integrated Dear ImGui in my engine and some elements are displaying outside their expected windows boundaries...](#q-i-integrated-dear-imgui-in-my-engine-and-some-elements-are-displaying-outside-their-expected-windows-boundaries) |
|
||||
| **Q&A: Usage** |
|
||||
| **[About the ID Stack system...](#q-about-the-id-stack-system)**<br>**[How can I have multiple widgets with the same label?](#q-how-can-i-have-multiple-widgets-with-the-same-label) (using `##` or `PushID()`)**<br>**[How can I have widgets with an empty label?](#q-how-can-i-have-widgets-with-an-empty-label) (using `##`)**<br>**[How can I animate the label of an existing widget?](#q-how-can-i-change-the-label-of-an-existing-widget) (using `###`)**<br>**[General description of the label and ID Stack system.](#general-description-of-the-label-and-id-stack-system)** |
|
||||
| [How can I display an image?](#q-how-can-i-display-an-image)<br>[What are ImTextureID/ImTextureRef?](#q-what-are-imtextureidimtextureref)|
|
||||
| [How can I use maths operators with ImVec2?](#q-how-can-i-use-maths-operators-with-imvec2) |
|
||||
| [How can I use my own maths types instead of ImVec2/ImVec4?](#q-how-can-i-use-my-own-maths-types-instead-of-imvec2imvec4) |
|
||||
| [How can I interact with standard C++ types (such as std::string and std::vector)?](#q-how-can-i-interact-with-standard-c-types-such-as-stdstring-and-stdvector) |
|
||||
| [How can I display custom shapes? (using low-level ImDrawList API)](#q-how-can-i-display-custom-shapes-using-low-level-imdrawlist-api) |
|
||||
| **Q&A: Fonts, Text** |
|
||||
| [How should I handle DPI in my application?](#q-how-should-i-handle-dpi-in-my-application) |
|
||||
| [How can I load a different font than the default?](#q-how-can-i-load-a-different-font-than-the-default) |
|
||||
| [How can I easily use icons in my application?](#q-how-can-i-easily-use-icons-in-my-application) |
|
||||
| [How can I load multiple fonts?](#q-how-can-i-load-multiple-fonts) |
|
||||
| [How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic?](#q-how-can-i-display-and-input-non-latin-characters-such-as-chinese-japanese-korean-cyrillic) |
|
||||
| **Q&A: Concerns** |
|
||||
| [Who uses Dear ImGui?](#q-who-uses-dear-imgui) |
|
||||
| [Can you create elaborate/serious tools with Dear ImGui?](#q-can-you-create-elaborateserious-tools-with-dear-imgui) |
|
||||
| [Can you reskin the look of Dear ImGui?](#q-can-you-reskin-the-look-of-dear-imgui) |
|
||||
| [Why using C++ (as opposed to C)?](#q-why-using-c-as-opposed-to-c) |
|
||||
| **Q&A: Community** |
|
||||
| [How can I help?](#q-how-can-i-help) |
|
||||
### Basics
|
||||
|
||||
- [Where is the documentation?](#q-where-is-the-documentation)
|
||||
- [What is this library called?](#q-what-is-this-library-called)
|
||||
- [What is the difference between Dear ImGui and traditional UI toolkits?](#q-what-is-the-difference-between-dear-imgui-and-traditional-ui-toolkits)
|
||||
- [Which version should I get?](#q-which-version-should-i-get)
|
||||
|
||||
### Integration
|
||||
|
||||
- **[How to get started?](#q-how-to-get-started)**
|
||||
- **[How can I tell whether to dispatch mouse/keyboard to Dear ImGui or my application?](#q-how-can-i-tell-whether-to-dispatch-mousekeyboard-to-dear-imgui-or-my-application)**
|
||||
- [How can I enable keyboard or gamepad controls?](#q-how-can-i-enable-keyboard-or-gamepad-controls)
|
||||
- [How can I use this on a machine without mouse, keyboard or screen? (input share, remote display)](#q-how-can-i-use-this-on-a-machine-without-mouse-keyboard-or-screen-input-share-remote-display)
|
||||
- [How can I create my own backend?](#q-how-can-i-create-my-own-backend)
|
||||
- [I integrated Dear ImGui in my engine and little squares are showing instead of text...](#q-i-integrated-dear-imgui-in-my-engine-and-little-squares-are-showing-instead-of-text)
|
||||
- [I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around...](#q-i-integrated-dear-imgui-in-my-engine-and-some-elements-are-clipping-or-disappearing-when-i-move-windows-around)
|
||||
- [I integrated Dear ImGui in my engine and some elements are displaying outside their expected windows boundaries...](#q-i-integrated-dear-imgui-in-my-engine-and-some-elements-are-displaying-outside-their-expected-windows-boundaries)
|
||||
|
||||
### Usage
|
||||
|
||||
- **[About the ID Stack system...](#q-about-the-id-stack-system)**
|
||||
- **[How can I have multiple widgets with the same label?](#q-how-can-i-have-multiple-widgets-with-the-same-label) (using `##` or `PushID()`)**
|
||||
- **[How can I have widgets with an empty label?](#q-how-can-i-have-widgets-with-an-empty-label) (using `##`)**
|
||||
- **[How can I make a label dynamic?](#q-how-can-i-make-a-label-dynamic) (using `###`)**
|
||||
- **[General description of the label and ID Stack system.](#general-description-of-the-label-and-id-stack-system)**
|
||||
- [How can I display an image?](#q-how-can-i-display-an-image), [What are ImTextureID/ImTextureRef?](#q-what-are-imtextureidimtextureref)
|
||||
- [How can I use maths operators with ImVec2?](#q-how-can-i-use-maths-operators-with-imvec2)
|
||||
- [How can I use my own maths types instead of ImVec2/ImVec4?](#q-how-can-i-use-my-own-maths-types-instead-of-imvec2imvec4)
|
||||
- [How can I interact with standard C++ types (such as std::string and std::vector)?](#q-how-can-i-interact-with-standard-c-types-such-as-stdstring-and-stdvector)
|
||||
- [How can I display custom shapes? (using low-level ImDrawList API)](#q-how-can-i-display-custom-shapes-using-low-level-imdrawlist-api)
|
||||
- [About Multi-Threading](#about-multi-threading)
|
||||
|
||||
### Fonts, Text
|
||||
|
||||
- [How should I handle DPI in my application?](#q-how-should-i-handle-dpi-in-my-application)
|
||||
- [How can I load a different font than the default?](#q-how-can-i-load-a-different-font-than-the-default)
|
||||
- [How can I easily use icons in my application?](#q-how-can-i-easily-use-icons-in-my-application)
|
||||
- [How can I load multiple fonts?](#q-how-can-i-load-multiple-fonts)
|
||||
- [How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic?](#q-how-can-i-display-and-input-non-latin-characters-such-as-chinese-japanese-korean-cyrillic)
|
||||
|
||||
### Concerns
|
||||
|
||||
- [Who uses Dear ImGui?](#q-who-uses-dear-imgui)
|
||||
- [Can you create elaborate/serious tools with Dear ImGui?](#q-can-you-create-elaborateserious-tools-with-dear-imgui)
|
||||
- [Can you reskin the look of Dear ImGui?](#q-can-you-reskin-the-look-of-dear-imgui)
|
||||
- [Why using C++ (as opposed to C)?](#q-why-using-c-as-opposed-to-c)
|
||||
|
||||
### Community
|
||||
|
||||
- [How can I help?](#q-how-can-i-help)
|
||||
|
||||
--------
|
||||
|
||||
# Q&A: Basics
|
||||
|
||||
|
|
@ -85,16 +101,17 @@ Here's a very simplified comparison between the approach taken by Dear ImGui vs
|
|||
|--------------------------|--------------------------|
|
||||
| UI fully issued on every update. | UI issued once then later modified. |
|
||||
| UI layout is fully dynamic and can change at any time.<BR>UI is generally emitted programmatically, which empowers reflecting a dynamic set of data. | UI layout is mostly static.<BR>UI may be emitted programmatically or from data created by offline tools. UI need extra code to evolve, which is often tedious and error-prone if it needs to be reflecting dynamic data and systems. |
|
||||
| Application can submit UI based on arbitrary logic and then forget about it. | Application needs more bookkeeping of UI elements. |
|
||||
| UI system is optimized for the worst case and designed to be optimal even under frequent changes. | UI system is optimized for the case where nothing changes. Performances tends to degrade when anything changes. |
|
||||
| Application can submit UI based on arbitrary logic without bookkeeping all aspects of that logic. | Application needs more bookkeeping of UI elements. |
|
||||
| UI library stores minimal amounts of data. At one point in time, it typically doesn't know or remember which other widgets are displayed and which widgets are coming next. As a result, certain layout features (alignment, resizing) are not as easy to implement or require ad-hoc code. | UI library stores entire widgets tree and state. UI library can use this retained data to easily layout things. |
|
||||
| UI code may be added anywhere.<BR>You can even create UI to edit a local variable! | UI code needs to be added in dedicated spots. |
|
||||
| UI layout/logic/action/data bindings are all nearby in the code. | UI layout/logic/action/data bindings in distinct functions, files or formats. |
|
||||
| Data is naturally always synchronized. | Use callback/signal/slot for synchronizing data (error-prone). |
|
||||
| API is simple and easy to learn. In particular, doing basic things is very easy. | API is more complex and specialized. |
|
||||
| API is low-level (raw language types). | API are higher-level (more abstractions, advanced language features). |
|
||||
| Less fancy look and feel. | Standard look and feel. |
|
||||
| API is simple and easy to learn. In particular, doing basic things is very easy.<BR>Attractive to more programmers. | API is more complex and specialized.<BR>Tends to require specialized programmers. |
|
||||
| API is low-level. Few abstractions, uses raw language types and your existing data. | API are higher-level. More abstractions, advanced language features. |
|
||||
| Less fancy look and feel. But keeps improving :) | Standard look and feel. |
|
||||
| Compile yourself. Easy to debug, hack, modify, study. | Mostly use precompiled libraries. Compiling, modifying or studying is daunting if not impossible. |
|
||||
| Run on every platform. | Run on limited desktop platforms. |
|
||||
| Run on every platform (incl. web, consoles, mobiles, legacy systems). | Run on major desktop platforms. |
|
||||
|
||||
Idiomatic Dear ImGui code:
|
||||
```cpp
|
||||
|
|
@ -553,8 +570,8 @@ typedef ImU64 ImTextureID; // Default: store up to 64-bits (any pointer or inte
|
|||
// Store a ImTextureID _or_ a ImTextureData*.
|
||||
struct ImTextureRef
|
||||
{
|
||||
ImTextureRef() { _TexData = NULL; _TexID = ImTextureID_Invalid; }
|
||||
ImTextureRef(ImTextureID tex_id) { _TexData = NULL; _TexID = tex_id; }
|
||||
ImTextureRef() { _TexData = nullptr; _TexID = ImTextureID_Invalid; }
|
||||
ImTextureRef(ImTextureID tex_id) { _TexData = nullptr; _TexID = tex_id; }
|
||||
inline ImTextureID GetTexID() const { return _TexData ? _TexData->TexID : _TexID; }
|
||||
|
||||
// Members (either are set, never both!)
|
||||
|
|
@ -572,7 +589,7 @@ struct ImTextureRef
|
|||
We intentionally do not provide an `ImTextureRef` constructor for this: we don't expect this to be frequently useful to the end-user, and it would be erroneously called by many legacy code.
|
||||
- There is no constructor to create a `ImTextureRef` from a `ImTextureData*` as we don't expect this to be useful to the end-user, and it would be erroneously called by many legacy code.
|
||||
- If you want to bind the current atlas when using custom rectangles, you can use `io.Fonts->TexRef`.
|
||||
- Binding generators for languages such as C (which don't have constructors), should provide a helper, e.g. `inline ImTextureRef ImTextureRefFromID(ImTextureID tex_id) { ImTextureRef tex_ref = { ._TexData = NULL, .TexID = tex_id }; return tex_ref; }`
|
||||
- Binding generators for languages such as C (which don't have constructors), should provide a helper, e.g. `inline ImTextureRef ImTextureRefFromID(ImTextureID tex_id) { ImTextureRef tex_ref = { ._TexData = nullptr, .TexID = tex_id }; return tex_ref; }`
|
||||
|
||||
**Please read documentations or tutorials on your graphics API to understand how to display textures on the screen before moving onward.**
|
||||
|
||||
|
|
@ -666,6 +683,7 @@ This way you will be able to use your own types everywhere, e.g. passing `MyVect
|
|||
---
|
||||
|
||||
### Q: How can I interact with standard C++ types (such as std::string and std::vector)?
|
||||
|
||||
- Being highly portable (backends/bindings for several languages, frameworks, programming styles, obscure or older platforms/compilers), and aiming for compatibility & performance suitable for every modern real-time game engine, Dear ImGui does not use any of std C++ types. We use raw types (e.g. char* instead of std::string) because they adapt to more use cases.
|
||||
- To use ImGui::InputText() with a std::string or any resizable string class, see [misc/cpp/imgui_stdlib.h](https://github.com/ocornut/imgui/blob/master/misc/cpp/imgui_stdlib.h).
|
||||
- To use combo boxes and list boxes with `std::vector` or any other data structure: the `BeginCombo()/EndCombo()` API
|
||||
|
|
@ -685,6 +703,10 @@ One possible implementation of a helper to facilitate printf-style building of s
|
|||
This is a small helper where you can instance strings with configurable local buffers length. Many game engines will
|
||||
provide similar or better string helpers.
|
||||
|
||||
Using string views:
|
||||
|
||||
- String view types such as `std::string_view` may be used with the [feature/string_view](https://github.com/ocornut/imgui/tree/features/string_view) branch. This branch is actively maintained and supported. Please provide feedback if you use it. We are waiting for a good moment to merge it.
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
---
|
||||
|
|
@ -725,6 +747,20 @@ ImGui::End();
|
|||
|
||||
---
|
||||
|
||||
### About Multi-Threading
|
||||
|
||||
A same Dear ImGui context may be not used from multiple threads in parallel.
|
||||
|
||||
If you want to use a same context within parallel tasks for occasional debug purpose, consider using a lock.
|
||||
|
||||
If you want to submit contents from a main/update thread but render Dear ImGui output in a dedicated render thread, you'll need to stage `ImDrawData` and texture requests. See the `ImDrawDataSnapshot` and `ImTextureQueue` helpers in [imgui_threaded_rendering](https://github.com/ocornut/imgui_club#imgui_threaded_rendering). Also see topics with [label: multi-threading](https://github.com/ocornut/imgui/issues?q=label%3Amulti-threading).
|
||||
|
||||
If you use multiple Dear ImGui contexts and want to use them from multiple threads, you need to `#define GImGui` to become a TLS variable (see details near the definition of `GImGui`. If you need to display multiple contexts simultaneously, consider using [imgui_multicontext_compositor](https://github.com/ocornut/imgui_club#imgui_multicontext_compositor). Also see topics with [label: multi-contexts](https://github.com/ocornut/imgui/issues?q=label%3Amulti-contexts).
|
||||
|
||||
There is a script/patch to make the API take an explicit context pointer: [#5856](https://github.com/ocornut/imgui/pull/5856). It is presently unmaintained and likely to easy to update. It has been decided that the change is not currently worth applying to main-line but maybe will be in a future version.
|
||||
|
||||
---
|
||||
|
||||
# Q&A: Fonts, Text
|
||||
|
||||
### Q: How should I handle DPI in my application?
|
||||
|
|
@ -744,7 +780,7 @@ style.FontScaleDpi = 2.0f;
|
|||
|
||||
To change font size:
|
||||
```cpp
|
||||
ImGui::PushFont(NULL, 42.0f); // This will be multiplied by style.FontScaleDpi
|
||||
ImGui::PushFont(nullptr, 42.0f); // This will be multiplied by style.FontScaleDpi
|
||||
```
|
||||
To change font and font size:
|
||||
```cpp
|
||||
|
|
|
|||
|
|
@ -77,6 +77,17 @@ Some solutions:
|
|||
You can use the `ImFontGlyphRangesBuilder` for this purpose and rebuilding your atlas between frames when new characters are needed. This will be the biggest win!
|
||||
- Set `io.Fonts.Flags |= ImFontAtlasFlags_NoPowerOfTwoHeight;` to disable rounding the texture height to the next power of two.
|
||||
|
||||
### (5) Reduce texture resizes/copy on startup
|
||||
|
||||
🆕 Since 1.92, the ImFontAtlas is initially created using a 512x128 texture, then grows as glyphs and fonts are used. Atlas growth leads to alloc+copy, and both the old and new sized textures are present in memory for a short time (typically one frame). If you use known fonts and want to reduce initial growth, you may set `TexMinWidth` and `TexMinHeight` during initializaton.
|
||||
|
||||
```cpp
|
||||
ImFontAtlas* atlas = io.Fonts;
|
||||
atlas->TexMinWidth = 1024;
|
||||
atlas->TexMinHeight = 1024;
|
||||
atlas->AddFont(...);
|
||||
```
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
---------------------------------------
|
||||
|
|
@ -85,7 +96,7 @@ Some solutions:
|
|||
|
||||
v1.92 introduces a newer, dynamic font system. It requires backend to support the `ImGuiBackendFlags_HasTextures` feature:
|
||||
- Users of icons, Asian and non-English languages do not need to pre-build all glyphs ahead of time. Saving on loading time, memory, and also reducing issues with missing glyphs. Specifying glyph ranges is not needed anymore.
|
||||
- `PushFont(NULL, new_size)` may be used anytime to change font size.
|
||||
- `PushFont(nullptr, new_size)` may be used anytime to change font size.
|
||||
- Packing custom rectangles is more convenient as pixels may be written to immediately.
|
||||
- Any update to fonts previously required backend specific calls to re-upload the texture, and said calls were not portable across backends. It is now possible to scale fonts etc. in a way that doesn't require you to make backend-specific calls.
|
||||
- It is possible to plug a custom loader/backend to any font source.
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ Dear ImGui is particularly suited to integration in game engines (for tooling),
|
|||
|
||||
**Backends for a variety of graphics API and rendering platforms** are provided in the [backends/](https://github.com/ocornut/imgui/tree/master/backends) folder, along with example applications in the [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder. You may also create your own backend. Anywhere where you can render textured triangles, you can render Dear ImGui.
|
||||
|
||||
C++20 users wishing to use a module may the use [stripe2933/imgui-module](https://github.com/stripe2933/imgui-module) third-party extension.
|
||||
C++20 users wishing to use a module may use the [stripe2933/imgui-module](https://github.com/stripe2933/imgui-module) third-party extension.
|
||||
|
||||
See the [Getting Started & Integration](#getting-started--integration) section of this document for more details.
|
||||
|
||||
|
|
@ -141,7 +141,7 @@ Integrating Dear ImGui within your custom engine is a matter of mainly 1) wiring
|
|||
- Generally, **make sure to spend time reading the [FAQ](https://www.dearimgui.com/faq), comments, and the examples applications!**
|
||||
|
||||
Officially maintained backends (in repository):
|
||||
- Renderers: DirectX9, DirectX10, DirectX11, DirectX12, Metal, OpenGL/ES/ES2, SDL_GPU, SDL_Renderer2/3, Vulkan, WebGPU.
|
||||
- Renderers: DirectX9, DirectX10, DirectX11, DirectX12, Metal 3/4, OpenGL/ES/ES2, SDL_GPU, SDL_Renderer2/3, Vulkan, WebGPU.
|
||||
- Platforms: GLFW, SDL2/SDL3, Win32, Glut, OSX, Android.
|
||||
- Frameworks: Allegro5, Emscripten.
|
||||
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@
|
|||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<SupportJustMyCode>false</SupportJustMyCode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
|
|
@ -107,6 +108,7 @@
|
|||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<SupportJustMyCode>false</SupportJustMyCode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
plugins {
|
||||
alias(libs.plugins.android.application)
|
||||
alias(libs.plugins.kotlin.android)
|
||||
}
|
||||
|
||||
android {
|
||||
|
|
@ -25,9 +24,6 @@ android {
|
|||
sourceCompatibility JavaVersion.VERSION_11
|
||||
targetCompatibility JavaVersion.VERSION_11
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = '11'
|
||||
}
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
path file('../../CMakeLists.txt')
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[versions]
|
||||
agp = "8.12.0"
|
||||
kotlin = "2.0.21"
|
||||
agp = "9.2.0"
|
||||
kotlin = "2.3.21"
|
||||
|
||||
[plugins]
|
||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||
|
|
|
|||
21
examples/example_apple_metal4/Makefile
Normal file
21
examples/example_apple_metal4/Makefile
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
# Makefile for example_apple_metal4, for macOS only (**not iOS**)
|
||||
CXX = clang++
|
||||
EXE = example_apple_metal4
|
||||
IMGUI_DIR = ../../
|
||||
SOURCES = main.mm
|
||||
SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
|
||||
SOURCES += $(IMGUI_DIR)/backends/imgui_impl_osx.mm $(IMGUI_DIR)/backends/imgui_impl_metal4.mm
|
||||
|
||||
CXXFLAGS = -std=c++11 -ObjC++ -fobjc-arc -Wall -Wextra -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
|
||||
FRAMEWORKS = -framework AppKit -framework Metal -framework MetalKit -framework QuartzCore -framework GameController
|
||||
|
||||
all: $(EXE)
|
||||
|
||||
$(EXE): $(SOURCES)
|
||||
$(CXX) $(CXXFLAGS) $^ $(FRAMEWORKS) -o $@
|
||||
|
||||
run: all
|
||||
./$(EXE)
|
||||
|
||||
clean:
|
||||
rm -f $(EXE) *.o
|
||||
10
examples/example_apple_metal4/README.md
Normal file
10
examples/example_apple_metal4/README.md
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# iOS / OSX Metal4 example
|
||||
|
||||
## Introduction
|
||||
|
||||
This example shows how to integrate Dear ImGui with Metal4. It is based on the "cross-platform" game template provided with Xcode as of Xcode 9.
|
||||
|
||||
Consider basing your work off the example_glfw_metal/ or example_sdl2_metal/ examples. They are better supported and will be portable unlike this one.
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,535 @@
|
|||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 54;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
050450AB2768052600AB6805 /* imgui_tables.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5079822D257677DB0038A28D /* imgui_tables.cpp */; };
|
||||
050450AD276863B000AB6805 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 050450AC276863B000AB6805 /* QuartzCore.framework */; };
|
||||
05318E0F274C397200A8DE2E /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05318E0E274C397200A8DE2E /* GameController.framework */; };
|
||||
05A275442773BEA20084EF39 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05A275432773BEA20084EF39 /* QuartzCore.framework */; };
|
||||
07A82ED82139413D0078D120 /* imgui_widgets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07A82ED72139413C0078D120 /* imgui_widgets.cpp */; };
|
||||
07A82ED92139418F0078D120 /* imgui_widgets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07A82ED72139413C0078D120 /* imgui_widgets.cpp */; };
|
||||
5079822E257677DB0038A28D /* imgui_tables.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5079822D257677DB0038A28D /* imgui_tables.cpp */; };
|
||||
8309BD8F253CCAAA0045E2A1 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8309BD8E253CCAAA0045E2A1 /* UIKit.framework */; };
|
||||
8309BDA5253CCC070045E2A1 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8309BDA0253CCBC10045E2A1 /* main.mm */; };
|
||||
8309BDA8253CCC080045E2A1 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8309BDA0253CCBC10045E2A1 /* main.mm */; };
|
||||
8309BDBB253CCCAD0045E2A1 /* imgui_impl_metal4.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8309BDB5253CCC9D0045E2A1 /* imgui_impl_metal4.mm */; };
|
||||
8309BDBE253CCCB60045E2A1 /* imgui_impl_metal4.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8309BDB5253CCC9D0045E2A1 /* imgui_impl_metal4.mm */; };
|
||||
8309BDBF253CCCB60045E2A1 /* imgui_impl_osx.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8309BDB6253CCC9D0045E2A1 /* imgui_impl_osx.mm */; };
|
||||
8309BDC6253CCCFE0045E2A1 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8309BDC5253CCCFE0045E2A1 /* AppKit.framework */; };
|
||||
8309BDFC253CDAB30045E2A1 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8309BDF7253CDAAE0045E2A1 /* LaunchScreen.storyboard */; };
|
||||
8309BE04253CDAB60045E2A1 /* MainMenu.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8309BDFA253CDAAE0045E2A1 /* MainMenu.storyboard */; };
|
||||
83BBE9E520EB46B900295997 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83BBE9E420EB46B900295997 /* Metal.framework */; };
|
||||
83BBE9E720EB46BD00295997 /* MetalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83BBE9E620EB46BD00295997 /* MetalKit.framework */; };
|
||||
83BBE9EC20EB471700295997 /* MetalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83BBE9EA20EB471700295997 /* MetalKit.framework */; };
|
||||
83BBE9ED20EB471700295997 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83BBE9EB20EB471700295997 /* Metal.framework */; };
|
||||
83BBEA0520EB54E700295997 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83BBEA0120EB54E700295997 /* imgui_draw.cpp */; };
|
||||
83BBEA0620EB54E700295997 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83BBEA0120EB54E700295997 /* imgui_draw.cpp */; };
|
||||
83BBEA0720EB54E700295997 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83BBEA0220EB54E700295997 /* imgui_demo.cpp */; };
|
||||
83BBEA0820EB54E700295997 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83BBEA0220EB54E700295997 /* imgui_demo.cpp */; };
|
||||
83BBEA0920EB54E700295997 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83BBEA0320EB54E700295997 /* imgui.cpp */; };
|
||||
83BBEA0A20EB54E700295997 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83BBEA0320EB54E700295997 /* imgui.cpp */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
050450AC276863B000AB6805 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
|
||||
05318E0E274C397200A8DE2E /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = System/Library/Frameworks/GameController.framework; sourceTree = SDKROOT; };
|
||||
05A2754027728F5B0084EF39 /* imgui_impl_metal4.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui_impl_metal4.h; path = ../../backends/imgui_impl_metal4.h; sourceTree = "<group>"; };
|
||||
05A2754127728F5B0084EF39 /* imgui_impl_osx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui_impl_osx.h; path = ../../backends/imgui_impl_osx.h; sourceTree = "<group>"; };
|
||||
05A275432773BEA20084EF39 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS15.2.sdk/System/Library/Frameworks/QuartzCore.framework; sourceTree = DEVELOPER_DIR; };
|
||||
07A82ED62139413C0078D120 /* imgui_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui_internal.h; path = ../../imgui_internal.h; sourceTree = "<group>"; };
|
||||
07A82ED72139413C0078D120 /* imgui_widgets.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_widgets.cpp; path = ../../imgui_widgets.cpp; sourceTree = "<group>"; };
|
||||
5079822D257677DB0038A28D /* imgui_tables.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_tables.cpp; path = ../../imgui_tables.cpp; sourceTree = "<group>"; };
|
||||
8307E7C420E9F9C900473790 /* example_apple_metal.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = example_apple_metal.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
8307E7DA20E9F9C900473790 /* example_apple_metal.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = example_apple_metal.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
8309BD8E253CCAAA0045E2A1 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; };
|
||||
8309BDA0253CCBC10045E2A1 /* main.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = "<group>"; };
|
||||
8309BDB5253CCC9D0045E2A1 /* imgui_impl_metal4.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = imgui_impl_metal4.mm; path = ../../backends/imgui_impl_metal4.mm; sourceTree = "<group>"; };
|
||||
8309BDB6253CCC9D0045E2A1 /* imgui_impl_osx.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = imgui_impl_osx.mm; path = ../../backends/imgui_impl_osx.mm; sourceTree = "<group>"; };
|
||||
8309BDC5253CCCFE0045E2A1 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
|
||||
8309BDF7253CDAAE0045E2A1 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
8309BDF8253CDAAE0045E2A1 /* Info-iOS.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-iOS.plist"; sourceTree = "<group>"; };
|
||||
8309BDFA253CDAAE0045E2A1 /* MainMenu.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = MainMenu.storyboard; sourceTree = "<group>"; };
|
||||
8309BDFB253CDAAE0045E2A1 /* Info-macOS.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-macOS.plist"; sourceTree = "<group>"; };
|
||||
83BBE9E420EB46B900295997 /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.4.sdk/System/Library/Frameworks/Metal.framework; sourceTree = DEVELOPER_DIR; };
|
||||
83BBE9E620EB46BD00295997 /* MetalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.4.sdk/System/Library/Frameworks/MetalKit.framework; sourceTree = DEVELOPER_DIR; };
|
||||
83BBE9E820EB46C100295997 /* ModelIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ModelIO.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.4.sdk/System/Library/Frameworks/ModelIO.framework; sourceTree = DEVELOPER_DIR; };
|
||||
83BBE9EA20EB471700295997 /* MetalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalKit.framework; path = System/Library/Frameworks/MetalKit.framework; sourceTree = SDKROOT; };
|
||||
83BBE9EB20EB471700295997 /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; };
|
||||
83BBE9EE20EB471C00295997 /* ModelIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ModelIO.framework; path = System/Library/Frameworks/ModelIO.framework; sourceTree = SDKROOT; };
|
||||
83BBEA0020EB54E700295997 /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = "<group>"; };
|
||||
83BBEA0120EB54E700295997 /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = "<group>"; };
|
||||
83BBEA0220EB54E700295997 /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../imgui_demo.cpp; sourceTree = "<group>"; };
|
||||
83BBEA0320EB54E700295997 /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = "<group>"; };
|
||||
83BBEA0420EB54E700295997 /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
8307E7C120E9F9C900473790 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
05A275442773BEA20084EF39 /* QuartzCore.framework in Frameworks */,
|
||||
8309BD8F253CCAAA0045E2A1 /* UIKit.framework in Frameworks */,
|
||||
83BBE9E720EB46BD00295997 /* MetalKit.framework in Frameworks */,
|
||||
83BBE9E520EB46B900295997 /* Metal.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
8307E7D720E9F9C900473790 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
050450AD276863B000AB6805 /* QuartzCore.framework in Frameworks */,
|
||||
8309BDC6253CCCFE0045E2A1 /* AppKit.framework in Frameworks */,
|
||||
83BBE9EC20EB471700295997 /* MetalKit.framework in Frameworks */,
|
||||
05318E0F274C397200A8DE2E /* GameController.framework in Frameworks */,
|
||||
83BBE9ED20EB471700295997 /* Metal.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
8307E7B520E9F9C700473790 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
83BBE9F020EB544400295997 /* imgui */,
|
||||
8309BD9E253CCBA70045E2A1 /* example */,
|
||||
8307E7C520E9F9C900473790 /* Products */,
|
||||
83BBE9E320EB46B800295997 /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8307E7C520E9F9C900473790 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8307E7C420E9F9C900473790 /* example_apple_metal.app */,
|
||||
8307E7DA20E9F9C900473790 /* example_apple_metal.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8309BD9E253CCBA70045E2A1 /* example */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8309BDF6253CDAAE0045E2A1 /* iOS */,
|
||||
8309BDF9253CDAAE0045E2A1 /* macOS */,
|
||||
8309BDA0253CCBC10045E2A1 /* main.mm */,
|
||||
);
|
||||
name = example;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8309BDF6253CDAAE0045E2A1 /* iOS */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8309BDF7253CDAAE0045E2A1 /* LaunchScreen.storyboard */,
|
||||
8309BDF8253CDAAE0045E2A1 /* Info-iOS.plist */,
|
||||
);
|
||||
path = iOS;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8309BDF9253CDAAE0045E2A1 /* macOS */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8309BDFA253CDAAE0045E2A1 /* MainMenu.storyboard */,
|
||||
8309BDFB253CDAAE0045E2A1 /* Info-macOS.plist */,
|
||||
);
|
||||
path = macOS;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
83BBE9E320EB46B800295997 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
050450AC276863B000AB6805 /* QuartzCore.framework */,
|
||||
05A275432773BEA20084EF39 /* QuartzCore.framework */,
|
||||
05318E0E274C397200A8DE2E /* GameController.framework */,
|
||||
8309BDC5253CCCFE0045E2A1 /* AppKit.framework */,
|
||||
8309BD8E253CCAAA0045E2A1 /* UIKit.framework */,
|
||||
83BBE9EE20EB471C00295997 /* ModelIO.framework */,
|
||||
83BBE9EB20EB471700295997 /* Metal.framework */,
|
||||
83BBE9EA20EB471700295997 /* MetalKit.framework */,
|
||||
83BBE9E820EB46C100295997 /* ModelIO.framework */,
|
||||
83BBE9E620EB46BD00295997 /* MetalKit.framework */,
|
||||
83BBE9E420EB46B900295997 /* Metal.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
83BBE9F020EB544400295997 /* imgui */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
5079822D257677DB0038A28D /* imgui_tables.cpp */,
|
||||
05A2754027728F5B0084EF39 /* imgui_impl_metal4.h */,
|
||||
8309BDB5253CCC9D0045E2A1 /* imgui_impl_metal4.mm */,
|
||||
05A2754127728F5B0084EF39 /* imgui_impl_osx.h */,
|
||||
8309BDB6253CCC9D0045E2A1 /* imgui_impl_osx.mm */,
|
||||
83BBEA0420EB54E700295997 /* imconfig.h */,
|
||||
83BBEA0320EB54E700295997 /* imgui.cpp */,
|
||||
83BBEA0020EB54E700295997 /* imgui.h */,
|
||||
83BBEA0220EB54E700295997 /* imgui_demo.cpp */,
|
||||
83BBEA0120EB54E700295997 /* imgui_draw.cpp */,
|
||||
07A82ED62139413C0078D120 /* imgui_internal.h */,
|
||||
07A82ED72139413C0078D120 /* imgui_widgets.cpp */,
|
||||
);
|
||||
name = imgui;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
8307E7C320E9F9C900473790 /* example_apple_metal_ios */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 8307E7F020E9F9C900473790 /* Build configuration list for PBXNativeTarget "example_apple_metal_ios" */;
|
||||
buildPhases = (
|
||||
8307E7C020E9F9C900473790 /* Sources */,
|
||||
8307E7C120E9F9C900473790 /* Frameworks */,
|
||||
8307E7C220E9F9C900473790 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = example_apple_metal_ios;
|
||||
productName = "imguiex iOS";
|
||||
productReference = 8307E7C420E9F9C900473790 /* example_apple_metal.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
8307E7D920E9F9C900473790 /* example_apple_metal_macos */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 8307E7F320E9F9C900473790 /* Build configuration list for PBXNativeTarget "example_apple_metal_macos" */;
|
||||
buildPhases = (
|
||||
8307E7D620E9F9C900473790 /* Sources */,
|
||||
8307E7D720E9F9C900473790 /* Frameworks */,
|
||||
8307E7D820E9F9C900473790 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = example_apple_metal_macos;
|
||||
productName = "imguiex macOS";
|
||||
productReference = 8307E7DA20E9F9C900473790 /* example_apple_metal.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
8307E7B620E9F9C700473790 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
BuildIndependentTargetsInParallel = YES;
|
||||
LastUpgradeCheck = 1530;
|
||||
ORGANIZATIONNAME = "Warren Moore";
|
||||
TargetAttributes = {
|
||||
8307E7C320E9F9C900473790 = {
|
||||
CreatedOnToolsVersion = 9.4.1;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
8307E7D920E9F9C900473790 = {
|
||||
CreatedOnToolsVersion = 9.4.1;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 8307E7B920E9F9C700473790 /* Build configuration list for PBXProject "example_apple_metal" */;
|
||||
compatibilityVersion = "Xcode 8.0";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 8307E7B520E9F9C700473790;
|
||||
productRefGroup = 8307E7C520E9F9C900473790 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
8307E7C320E9F9C900473790 /* example_apple_metal_ios */,
|
||||
8307E7D920E9F9C900473790 /* example_apple_metal_macos */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
8307E7C220E9F9C900473790 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8309BDFC253CDAB30045E2A1 /* LaunchScreen.storyboard in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
8307E7D820E9F9C900473790 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8309BE04253CDAB60045E2A1 /* MainMenu.storyboard in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
8307E7C020E9F9C900473790 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8309BDBB253CCCAD0045E2A1 /* imgui_impl_metal4.mm in Sources */,
|
||||
83BBEA0920EB54E700295997 /* imgui.cpp in Sources */,
|
||||
83BBEA0720EB54E700295997 /* imgui_demo.cpp in Sources */,
|
||||
83BBEA0520EB54E700295997 /* imgui_draw.cpp in Sources */,
|
||||
5079822E257677DB0038A28D /* imgui_tables.cpp in Sources */,
|
||||
07A82ED82139413D0078D120 /* imgui_widgets.cpp in Sources */,
|
||||
8309BDA5253CCC070045E2A1 /* main.mm in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
8307E7D620E9F9C900473790 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8309BDBE253CCCB60045E2A1 /* imgui_impl_metal4.mm in Sources */,
|
||||
8309BDBF253CCCB60045E2A1 /* imgui_impl_osx.mm in Sources */,
|
||||
83BBEA0A20EB54E700295997 /* imgui.cpp in Sources */,
|
||||
83BBEA0820EB54E700295997 /* imgui_demo.cpp in Sources */,
|
||||
83BBEA0620EB54E700295997 /* imgui_draw.cpp in Sources */,
|
||||
050450AB2768052600AB6805 /* imgui_tables.cpp in Sources */,
|
||||
07A82ED92139418F0078D120 /* imgui_widgets.cpp in Sources */,
|
||||
8309BDA8253CCC080045E2A1 /* main.mm in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
8307E7EE20E9F9C900473790 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
8307E7EF20E9F9C900473790 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
8307E7F120E9F9C900473790 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
INFOPLIST_FILE = "$(SRCROOT)/iOS/Info-iOS.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.apple-metal-ios";
|
||||
PRODUCT_NAME = example_apple_metal;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../**";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
8307E7F220E9F9C900473790 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
INFOPLIST_FILE = "$(SRCROOT)/iOS/Info-iOS.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.apple-metal-ios";
|
||||
PRODUCT_NAME = example_apple_metal;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../**";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
8307E7F420E9F9C900473790 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
INFOPLIST_FILE = "$(SRCROOT)/macOS/Info-macOS.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 26.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.apple-metal-macos";
|
||||
PRODUCT_NAME = example_apple_metal;
|
||||
SDKROOT = macosx;
|
||||
USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../**";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
8307E7F520E9F9C900473790 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
INFOPLIST_FILE = "$(SRCROOT)/macOS/Info-macOS.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 26.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.apple-metal-macos";
|
||||
PRODUCT_NAME = example_apple_metal;
|
||||
SDKROOT = macosx;
|
||||
USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../**";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
8307E7B920E9F9C700473790 /* Build configuration list for PBXProject "example_apple_metal" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
8307E7EE20E9F9C900473790 /* Debug */,
|
||||
8307E7EF20E9F9C900473790 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
8307E7F020E9F9C900473790 /* Build configuration list for PBXNativeTarget "example_apple_metal_ios" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
8307E7F120E9F9C900473790 /* Debug */,
|
||||
8307E7F220E9F9C900473790 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
8307E7F320E9F9C900473790 /* Build configuration list for PBXNativeTarget "example_apple_metal_macos" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
8307E7F420E9F9C900473790 /* Debug */,
|
||||
8307E7F520E9F9C900473790 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 8307E7B620E9F9C700473790 /* Project object */;
|
||||
}
|
||||
49
examples/example_apple_metal4/iOS/Info-iOS.plist
Normal file
49
examples/example_apple_metal4/iOS/Info-iOS.plist
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>imgui</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
<string>metal</string>
|
||||
</array>
|
||||
<key>UIRequiresFullScreen</key>
|
||||
<true/>
|
||||
<key>UIStatusBarHidden</key>
|
||||
<true/>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
27
examples/example_apple_metal4/iOS/LaunchScreen.storyboard
Normal file
27
examples/example_apple_metal4/iOS/LaunchScreen.storyboard
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17156" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17125"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="EHf-IW-A2E">
|
||||
<objects>
|
||||
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<viewLayoutGuide key="safeArea" id="Bcu-3y-fUS"/>
|
||||
<color key="backgroundColor" red="0.27843137254901962" green="0.36078431372549019" blue="0.50196078431372548" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="53" y="375"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
||||
30
examples/example_apple_metal4/macOS/Info-macOS.plist
Normal file
30
examples/example_apple_metal4/macOS/Info-macOS.plist
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string></string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>imgui</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
|
||||
<key>NSMainStoryboardFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
</dict>
|
||||
</plist>
|
||||
93
examples/example_apple_metal4/macOS/MainMenu.storyboard
Normal file
93
examples/example_apple_metal4/macOS/MainMenu.storyboard
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="17156" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="17156"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--Application-->
|
||||
<scene sceneID="JPo-4y-FX3">
|
||||
<objects>
|
||||
<application id="hnw-xV-0zn" sceneMemberID="viewController">
|
||||
<menu key="mainMenu" title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
|
||||
<items>
|
||||
<menuItem title="ImGui" id="1Xt-HY-uBw">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="ImGui" systemMenu="apple" id="uQy-DD-JDr">
|
||||
<items>
|
||||
<menuItem title="Services" id="NMo-om-nkz">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Services" systemMenu="services" id="hz9-B4-Xy5"/>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="4je-JR-u6R"/>
|
||||
<menuItem title="Hide" keyEquivalent="h" id="Olw-nP-bQN">
|
||||
<connections>
|
||||
<action selector="hide:" target="Ady-hI-5gd" id="PnN-Uc-m68"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO">
|
||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="hideOtherApplications:" target="Ady-hI-5gd" id="VT4-aY-XCT"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Show All" id="Kd2-mp-pUS">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="unhideAllApplications:" target="Ady-hI-5gd" id="Dhg-Le-xox"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/>
|
||||
<menuItem title="Quit" keyEquivalent="q" id="4sb-4s-VLi">
|
||||
<connections>
|
||||
<action selector="terminate:" target="Ady-hI-5gd" id="Te7-pn-YzF"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="View" id="H8h-7b-M4v">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="View" id="HyV-fh-RgO">
|
||||
<items>
|
||||
<menuItem title="Enter Full Screen" keyEquivalent="f" id="4J7-dP-txa">
|
||||
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
|
||||
<connections>
|
||||
<action selector="toggleFullScreen:" target="Ady-hI-5gd" id="dU3-MA-1Rq"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Window" id="aUF-d1-5bR">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo">
|
||||
<items>
|
||||
<menuItem title="Minimize" keyEquivalent="m" id="OY7-WF-poV">
|
||||
<connections>
|
||||
<action selector="performMiniaturize:" target="Ady-hI-5gd" id="VwT-WD-YPe"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Zoom" id="R4o-n2-Eq4">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="performZoom:" target="Ady-hI-5gd" id="DIl-cC-cCs"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="Voe-Tx-rLC" id="PrD-fu-P6m"/>
|
||||
</connections>
|
||||
</application>
|
||||
<customObject id="Voe-Tx-rLC" customClass="AppDelegate"/>
|
||||
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
|
||||
<customObject id="Ady-hI-5gd" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-362" y="-38"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
||||
366
examples/example_apple_metal4/main.mm
Normal file
366
examples/example_apple_metal4/main.mm
Normal file
|
|
@ -0,0 +1,366 @@
|
|||
// Dear ImGui: standalone example application for OSX + Metal.
|
||||
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - 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
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#if TARGET_OS_OSX
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#else
|
||||
#import <UIKit/UIKit.h>
|
||||
#endif
|
||||
|
||||
#import <Metal/Metal.h>
|
||||
#import <MetalKit/MetalKit.h>
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_metal4.h"
|
||||
#if TARGET_OS_OSX
|
||||
#include "imgui_impl_osx.h"
|
||||
@interface AppViewController : NSViewController<NSWindowDelegate>
|
||||
@end
|
||||
#else
|
||||
@interface AppViewController : UIViewController
|
||||
@end
|
||||
#endif
|
||||
|
||||
@interface AppViewController () <MTKViewDelegate>
|
||||
@property (nonatomic, readonly) MTKView *mtkView;
|
||||
@property (nonatomic, strong) id <MTLDevice> device;
|
||||
@property (nonatomic, strong) id <MTL4CommandQueue> commandQueue;
|
||||
@property (nonatomic, strong) id <MTL4CommandAllocator> commandAllocator;
|
||||
@end
|
||||
|
||||
#define FRAMES_IN_FLIGHT 2
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
// AppViewController
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
@implementation AppViewController
|
||||
|
||||
-(instancetype)initWithNibName:(nullable NSString *)nibNameOrNil bundle:(nullable NSBundle *)nibBundleOrNil
|
||||
{
|
||||
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
|
||||
|
||||
_device = MTLCreateSystemDefaultDevice();
|
||||
_commandQueue = [_device newMTL4CommandQueue];
|
||||
_commandAllocator = [_device newCommandAllocator];
|
||||
|
||||
if (!self.device)
|
||||
{
|
||||
NSLog(@"Metal is not supported");
|
||||
abort();
|
||||
}
|
||||
|
||||
// Setup Dear ImGui context
|
||||
// FIXME: This example doesn't have proper cleanup...
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
|
||||
|
||||
// Setup Dear ImGui style
|
||||
ImGui::StyleColorsDark();
|
||||
//ImGui::StyleColorsLight();
|
||||
|
||||
// When viewports are enabled we tweak WindowRounding/WindowBg so platform windows can look identical to regular ones.
|
||||
|
||||
// Setup Renderer backend
|
||||
ImGui_ImplMetal4_Init(_device, _commandQueue, FRAMES_IN_FLIGHT);
|
||||
|
||||
// Load Fonts
|
||||
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
|
||||
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
|
||||
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
|
||||
// - Read 'docs/FONTS.md' for more instructions and details.
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
//style.FontSizeBase = 20.0f;
|
||||
//io.Fonts->AddFontDefaultVector();
|
||||
//io.Fonts->AddFontDefaultBitmap();
|
||||
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf");
|
||||
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf");
|
||||
//IM_ASSERT(font != nullptr);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
-(MTKView *)mtkView
|
||||
{
|
||||
return (MTKView *)self.view;
|
||||
}
|
||||
|
||||
-(void)loadView
|
||||
{
|
||||
self.view = [[MTKView alloc] initWithFrame:CGRectMake(0, 0, 1200, 800)];
|
||||
}
|
||||
|
||||
-(void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
|
||||
self.mtkView.device = self.device;
|
||||
self.mtkView.delegate = self;
|
||||
|
||||
#if TARGET_OS_OSX
|
||||
ImGui_ImplOSX_Init(self.view);
|
||||
[NSApp activateIgnoringOtherApps:YES];
|
||||
#endif
|
||||
}
|
||||
|
||||
-(void)drawInMTKView:(MTKView*)view
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.DisplaySize.x = view.bounds.size.width;
|
||||
io.DisplaySize.y = view.bounds.size.height;
|
||||
|
||||
#if TARGET_OS_OSX
|
||||
CGFloat framebufferScale = view.window.screen.backingScaleFactor ?: NSScreen.mainScreen.backingScaleFactor;
|
||||
#else
|
||||
CGFloat framebufferScale = view.window.screen.scale ?: UIScreen.mainScreen.scale;
|
||||
#endif
|
||||
io.DisplayFramebufferScale = ImVec2(framebufferScale, framebufferScale);
|
||||
[self.commandAllocator reset];
|
||||
|
||||
id<MTL4CommandBuffer> commandBuffer = [self.device newCommandBuffer];
|
||||
[commandBuffer beginCommandBufferWithAllocator:self.commandAllocator];
|
||||
|
||||
MTL4RenderPassDescriptor* renderPassDescriptor = view.currentMTL4RenderPassDescriptor;
|
||||
if (renderPassDescriptor == nil)
|
||||
{
|
||||
[commandBuffer endCommandBuffer];
|
||||
[self.commandQueue commit:&commandBuffer count:1];
|
||||
return;
|
||||
}
|
||||
|
||||
// Start the Dear ImGui frame
|
||||
static int frameIndex = 0;
|
||||
ImGui_ImplMetal4_NewFrame(renderPassDescriptor, frameIndex);
|
||||
frameIndex++;
|
||||
frameIndex = (frameIndex + 1) % FRAMES_IN_FLIGHT;
|
||||
|
||||
#if TARGET_OS_OSX
|
||||
ImGui_ImplOSX_NewFrame(view);
|
||||
#endif
|
||||
ImGui::NewFrame();
|
||||
|
||||
// Our state (make them static = more or less global) as a convenience to keep the example terse.
|
||||
static bool show_demo_window = true;
|
||||
static bool show_another_window = false;
|
||||
static ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
|
||||
|
||||
// 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
|
||||
if (show_demo_window)
|
||||
ImGui::ShowDemoWindow(&show_demo_window);
|
||||
|
||||
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window.
|
||||
{
|
||||
static float f = 0.0f;
|
||||
static int counter = 0;
|
||||
|
||||
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
|
||||
|
||||
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
|
||||
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
|
||||
ImGui::Checkbox("Another Window", &show_another_window);
|
||||
|
||||
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
|
||||
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
|
||||
|
||||
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
|
||||
counter++;
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("counter = %d", counter);
|
||||
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// 3. Show another simple window.
|
||||
if (show_another_window)
|
||||
{
|
||||
ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
|
||||
ImGui::Text("Hello from another window!");
|
||||
if (ImGui::Button("Close Me"))
|
||||
show_another_window = false;
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// Rendering
|
||||
ImGui::Render();
|
||||
ImDrawData* draw_data = ImGui::GetDrawData();
|
||||
|
||||
renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
|
||||
id <MTL4RenderCommandEncoder> renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];
|
||||
[renderEncoder pushDebugGroup:@"Dear ImGui rendering"];
|
||||
ImGui_ImplMetal4_RenderDrawData(draw_data, commandBuffer, renderEncoder);
|
||||
[renderEncoder popDebugGroup];
|
||||
[renderEncoder endEncoding];
|
||||
|
||||
// Present
|
||||
[commandBuffer endCommandBuffer];
|
||||
[self.commandQueue waitForDrawable:view.currentDrawable];
|
||||
[self.commandQueue commit:&commandBuffer count:1];
|
||||
[self.commandQueue signalDrawable:view.currentDrawable];
|
||||
[view.currentDrawable present];
|
||||
}
|
||||
|
||||
-(void)mtkView:(MTKView*)view drawableSizeWillChange:(CGSize)size
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
// Input processing
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
#if TARGET_OS_OSX
|
||||
|
||||
- (void)viewWillAppear
|
||||
{
|
||||
[super viewWillAppear];
|
||||
self.view.window.delegate = self;
|
||||
}
|
||||
|
||||
- (void)windowWillClose:(NSNotification *)notification
|
||||
{
|
||||
ImGui_ImplMetal4_Shutdown();
|
||||
ImGui_ImplOSX_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// This touch mapping is super cheesy/hacky. We treat any touch on the screen
|
||||
// as if it were a depressed left mouse button, and we don't bother handling
|
||||
// multitouch correctly at all. This causes the "cursor" to behave very erratically
|
||||
// when there are multiple active touches. But for demo purposes, single-touch
|
||||
// interaction actually works surprisingly well.
|
||||
-(void)updateIOWithTouchEvent:(UIEvent *)event
|
||||
{
|
||||
UITouch *anyTouch = event.allTouches.anyObject;
|
||||
CGPoint touchLocation = [anyTouch locationInView:self.view];
|
||||
ImGuiIO &io = ImGui::GetIO();
|
||||
io.AddMouseSourceEvent(ImGuiMouseSource_TouchScreen);
|
||||
io.AddMousePosEvent(touchLocation.x, touchLocation.y);
|
||||
|
||||
BOOL hasActiveTouch = NO;
|
||||
for (UITouch *touch in event.allTouches)
|
||||
{
|
||||
if (touch.phase != UITouchPhaseEnded && touch.phase != UITouchPhaseCancelled)
|
||||
{
|
||||
hasActiveTouch = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
io.AddMouseButtonEvent(0, hasActiveTouch);
|
||||
}
|
||||
|
||||
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [self updateIOWithTouchEvent:event]; }
|
||||
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [self updateIOWithTouchEvent:event]; }
|
||||
-(void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [self updateIOWithTouchEvent:event]; }
|
||||
-(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [self updateIOWithTouchEvent:event]; }
|
||||
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
// AppDelegate
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
#if TARGET_OS_OSX
|
||||
|
||||
@interface AppDelegate : NSObject <NSApplicationDelegate>
|
||||
@property (nonatomic, strong) NSWindow *window;
|
||||
@end
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
-(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
-(instancetype)init
|
||||
{
|
||||
if (self = [super init])
|
||||
{
|
||||
NSViewController *rootViewController = [[AppViewController alloc] initWithNibName:nil bundle:nil];
|
||||
self.window = [[NSWindow alloc] initWithContentRect:NSZeroRect
|
||||
styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable | NSWindowStyleMaskMiniaturizable
|
||||
backing:NSBackingStoreBuffered
|
||||
defer:NO];
|
||||
self.window.contentViewController = rootViewController;
|
||||
[self.window center];
|
||||
[self.window makeKeyAndOrderFront:self];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#else
|
||||
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
||||
@property (strong, nonatomic) UIWindow *window;
|
||||
@end
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
-(BOOL)application:(UIApplication *)application
|
||||
didFinishLaunchingWithOptions:(NSDictionary<UIApplicationLaunchOptionsKey,id> *)launchOptions
|
||||
{
|
||||
UIViewController *rootViewController = [[AppViewController alloc] init];
|
||||
self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
|
||||
self.window.rootViewController = rootViewController;
|
||||
[self.window makeKeyAndVisible];
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
// Application main() function
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
#if TARGET_OS_OSX
|
||||
|
||||
int main(int, const char**)
|
||||
{
|
||||
@autoreleasepool
|
||||
{
|
||||
[NSApplication sharedApplication];
|
||||
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
|
||||
|
||||
AppDelegate *appDelegate = [[AppDelegate alloc] init]; // creates window
|
||||
[NSApp setDelegate:appDelegate];
|
||||
|
||||
[NSApp activateIgnoringOtherApps:YES];
|
||||
[NSApp run];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
@autoreleasepool
|
||||
{
|
||||
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -6,6 +6,7 @@
|
|||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
#define GL_SILENCE_DEPRECATION
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <OpenGL/gl.h>
|
||||
#import <OpenGL/glu.h>
|
||||
|
|
@ -32,7 +33,7 @@
|
|||
|
||||
#ifndef DEBUG
|
||||
GLint swapInterval = 1;
|
||||
[[self openGLContext] setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval];
|
||||
[[self openGLContext] setValues:&swapInterval forParameter:NSOpenGLContextParameterSwapInterval];
|
||||
if (swapInterval == 0)
|
||||
NSLog(@"Error: Cannot set swap interval.");
|
||||
#endif
|
||||
|
|
@ -130,8 +131,8 @@
|
|||
ImDrawData* draw_data = ImGui::GetDrawData();
|
||||
|
||||
[[self openGLContext] makeCurrentContext];
|
||||
GLsizei width = (GLsizei)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
|
||||
GLsizei height = (GLsizei)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
|
||||
GLsizei width = (GLsizei)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
|
||||
GLsizei height = (GLsizei)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
|
||||
glViewport(0, 0, width, height);
|
||||
glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
|
|
|||
21
examples/example_apple_opengl3/Makefile
Normal file
21
examples/example_apple_opengl3/Makefile
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
# Makefile for example_apple_opengl3, for macOS only (**not iOS**)
|
||||
CXX = clang++
|
||||
EXE = example_apple_opengl3
|
||||
IMGUI_DIR = ../../
|
||||
SOURCES = main.mm
|
||||
SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
|
||||
SOURCES += $(IMGUI_DIR)/backends/imgui_impl_osx.mm $(IMGUI_DIR)/backends/imgui_impl_opengl3.cpp
|
||||
|
||||
CXXFLAGS = -std=c++11 -ObjC++ -fobjc-arc -Wall -Wextra -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
|
||||
FRAMEWORKS = -framework Cocoa -framework OpenGL -framework GameController
|
||||
|
||||
all: $(EXE)
|
||||
|
||||
$(EXE): $(SOURCES)
|
||||
$(CXX) $(CXXFLAGS) $(SOURCES) -o $(EXE) $(FRAMEWORKS)
|
||||
|
||||
run: all
|
||||
./$(EXE)
|
||||
|
||||
clean:
|
||||
rm -f $(EXE) *.o
|
||||
|
|
@ -0,0 +1,334 @@
|
|||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 48;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
05E31B59274EF0700083FCB6 /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05E31B57274EF0360083FCB6 /* GameController.framework */; };
|
||||
07A82EDB213941D00078D120 /* imgui_widgets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07A82EDA213941D00078D120 /* imgui_widgets.cpp */; };
|
||||
4080A99820B02D340036BA46 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4080A98A20B02CD90036BA46 /* main.mm */; };
|
||||
4080A9A220B034280036BA46 /* imgui_impl_opengl3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4080A99E20B034280036BA46 /* imgui_impl_opengl3.cpp */; };
|
||||
4080A9AD20B0343C0036BA46 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4080A9A620B0343C0036BA46 /* imgui_demo.cpp */; };
|
||||
4080A9AE20B0343C0036BA46 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4080A9A720B0343C0036BA46 /* imgui.cpp */; };
|
||||
4080A9AF20B0343C0036BA46 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4080A9AA20B0343C0036BA46 /* imgui_draw.cpp */; };
|
||||
4080A9B020B0347A0036BA46 /* imgui_impl_osx.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4080A99F20B034280036BA46 /* imgui_impl_osx.mm */; };
|
||||
4080A9B320B034E40036BA46 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4080A9B220B034E40036BA46 /* Cocoa.framework */; };
|
||||
4080A9B520B034EA0036BA46 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4080A9B420B034EA0036BA46 /* OpenGL.framework */; };
|
||||
50798230257677FD0038A28D /* imgui_tables.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5079822F257677FC0038A28D /* imgui_tables.cpp */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
4080A96920B029B00036BA46 /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = /usr/share/man/man1/;
|
||||
dstSubfolderSpec = 0;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
05E31B57274EF0360083FCB6 /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = System/Library/Frameworks/GameController.framework; sourceTree = SDKROOT; };
|
||||
07A82EDA213941D00078D120 /* imgui_widgets.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_widgets.cpp; path = ../../imgui_widgets.cpp; sourceTree = "<group>"; };
|
||||
4080A96B20B029B00036BA46 /* example_osx_opengl3 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = example_osx_opengl3; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
4080A98A20B02CD90036BA46 /* main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = SOURCE_ROOT; };
|
||||
4080A99E20B034280036BA46 /* imgui_impl_opengl3.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_impl_opengl3.cpp; path = ../../backends/imgui_impl_opengl3.cpp; sourceTree = "<group>"; };
|
||||
4080A99F20B034280036BA46 /* imgui_impl_osx.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = imgui_impl_osx.mm; path = ../../backends/imgui_impl_osx.mm; sourceTree = "<group>"; };
|
||||
4080A9A020B034280036BA46 /* imgui_impl_opengl3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui_impl_opengl3.h; path = ../../backends/imgui_impl_opengl3.h; sourceTree = "<group>"; };
|
||||
4080A9A120B034280036BA46 /* imgui_impl_osx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui_impl_osx.h; path = ../../backends/imgui_impl_osx.h; sourceTree = "<group>"; };
|
||||
4080A9A320B034280036BA46 /* imgui_impl_opengl3_loader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui_impl_opengl3_loader.h; path = ../../backends/imgui_impl_opengl3_loader.h; sourceTree = "<group>"; };
|
||||
4080A9A520B0343C0036BA46 /* imgui_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui_internal.h; path = ../../imgui_internal.h; sourceTree = "<group>"; };
|
||||
4080A9A620B0343C0036BA46 /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../imgui_demo.cpp; sourceTree = "<group>"; };
|
||||
4080A9A720B0343C0036BA46 /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = "<group>"; };
|
||||
4080A9A820B0343C0036BA46 /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = "<group>"; };
|
||||
4080A9AA20B0343C0036BA46 /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = "<group>"; };
|
||||
4080A9AC20B0343C0036BA46 /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = "<group>"; };
|
||||
4080A9B220B034E40036BA46 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
|
||||
4080A9B420B034EA0036BA46 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; };
|
||||
5079822F257677FC0038A28D /* imgui_tables.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_tables.cpp; path = ../../imgui_tables.cpp; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
4080A96820B029B00036BA46 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
4080A9B520B034EA0036BA46 /* OpenGL.framework in Frameworks */,
|
||||
4080A9B320B034E40036BA46 /* Cocoa.framework in Frameworks */,
|
||||
05E31B59274EF0700083FCB6 /* GameController.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
4080A96220B029B00036BA46 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
5079822F257677FC0038A28D /* imgui_tables.cpp */,
|
||||
4080A9AC20B0343C0036BA46 /* imconfig.h */,
|
||||
4080A9A720B0343C0036BA46 /* imgui.cpp */,
|
||||
4080A9A820B0343C0036BA46 /* imgui.h */,
|
||||
07A82EDA213941D00078D120 /* imgui_widgets.cpp */,
|
||||
4080A9A620B0343C0036BA46 /* imgui_demo.cpp */,
|
||||
4080A9AA20B0343C0036BA46 /* imgui_draw.cpp */,
|
||||
4080A9A520B0343C0036BA46 /* imgui_internal.h */,
|
||||
4080A99E20B034280036BA46 /* imgui_impl_opengl3.cpp */,
|
||||
4080A9A020B034280036BA46 /* imgui_impl_opengl3.h */,
|
||||
4080A9A320B034280036BA46 /* imgui_impl_opengl3_loader.h */,
|
||||
4080A9A120B034280036BA46 /* imgui_impl_osx.h */,
|
||||
4080A99F20B034280036BA46 /* imgui_impl_osx.mm */,
|
||||
4080A98A20B02CD90036BA46 /* main.mm */,
|
||||
4080A96C20B029B00036BA46 /* Products */,
|
||||
4080A9B120B034E40036BA46 /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4080A96C20B029B00036BA46 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4080A96B20B029B00036BA46 /* example_osx_opengl3 */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4080A9B120B034E40036BA46 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
05E31B57274EF0360083FCB6 /* GameController.framework */,
|
||||
4080A9B420B034EA0036BA46 /* OpenGL.framework */,
|
||||
4080A9B220B034E40036BA46 /* Cocoa.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
4080A96A20B029B00036BA46 /* example_osx_opengl3 */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 4080A97220B029B00036BA46 /* Build configuration list for PBXNativeTarget "example_osx_opengl3" */;
|
||||
buildPhases = (
|
||||
4080A96720B029B00036BA46 /* Sources */,
|
||||
4080A96820B029B00036BA46 /* Frameworks */,
|
||||
4080A96920B029B00036BA46 /* CopyFiles */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = example_osx_opengl3;
|
||||
productName = example_osx_opengl3;
|
||||
productReference = 4080A96B20B029B00036BA46 /* example_osx_opengl3 */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
4080A96320B029B00036BA46 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0930;
|
||||
ORGANIZATIONNAME = ImGui;
|
||||
TargetAttributes = {
|
||||
4080A96A20B029B00036BA46 = {
|
||||
CreatedOnToolsVersion = 9.3.1;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 4080A96620B029B00036BA46 /* Build configuration list for PBXProject "example_apple_opengl3" */;
|
||||
compatibilityVersion = "Xcode 8.0";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
);
|
||||
mainGroup = 4080A96220B029B00036BA46;
|
||||
productRefGroup = 4080A96C20B029B00036BA46 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
4080A96A20B029B00036BA46 /* example_osx_opengl3 */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
4080A96720B029B00036BA46 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
4080A99820B02D340036BA46 /* main.mm in Sources */,
|
||||
4080A9AD20B0343C0036BA46 /* imgui_demo.cpp in Sources */,
|
||||
4080A9AF20B0343C0036BA46 /* imgui_draw.cpp in Sources */,
|
||||
4080A9A220B034280036BA46 /* imgui_impl_opengl3.cpp in Sources */,
|
||||
4080A9B020B0347A0036BA46 /* imgui_impl_osx.mm in Sources */,
|
||||
4080A9AE20B0343C0036BA46 /* imgui.cpp in Sources */,
|
||||
50798230257677FD0038A28D /* imgui_tables.cpp in Sources */,
|
||||
07A82EDB213941D00078D120 /* imgui_widgets.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
4080A97020B029B00036BA46 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
4080A97120B029B00036BA46 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
4080A97320B029B00036BA46 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
USER_HEADER_SEARCH_PATHS = ../..;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
4080A97420B029B00036BA46 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
USER_HEADER_SEARCH_PATHS = ../..;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
4080A96620B029B00036BA46 /* Build configuration list for PBXProject "example_apple_opengl3" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
4080A97020B029B00036BA46 /* Debug */,
|
||||
4080A97120B029B00036BA46 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
4080A97220B029B00036BA46 /* Build configuration list for PBXNativeTarget "example_osx_opengl3" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
4080A97320B029B00036BA46 /* Debug */,
|
||||
4080A97420B029B00036BA46 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 4080A96320B029B00036BA46 /* Project object */;
|
||||
}
|
||||
260
examples/example_apple_opengl3/main.mm
Normal file
260
examples/example_apple_opengl3/main.mm
Normal file
|
|
@ -0,0 +1,260 @@
|
|||
// Dear ImGui: standalone example application for OSX + OpenGL3
|
||||
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - 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
|
||||
|
||||
#define GL_SILENCE_DEPRECATION
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <OpenGL/gl3.h>
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_opengl3.h"
|
||||
#include "imgui_impl_osx.h"
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
// AppView
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
@interface AppView : NSOpenGLView
|
||||
{
|
||||
NSTimer* animationTimer;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation AppView
|
||||
|
||||
-(void)prepareOpenGL
|
||||
{
|
||||
[super prepareOpenGL];
|
||||
|
||||
#ifndef DEBUG
|
||||
GLint swapInterval = 1;
|
||||
[[self openGLContext] setValues:&swapInterval forParameter:NSOpenGLContextParameterSwapInterval];
|
||||
if (swapInterval == 0)
|
||||
NSLog(@"Error: Cannot set swap interval.");
|
||||
#endif
|
||||
}
|
||||
|
||||
-(void)initialize
|
||||
{
|
||||
// Setup Dear ImGui context
|
||||
// FIXME: This example doesn't have proper cleanup...
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
|
||||
|
||||
// Setup Dear ImGui style
|
||||
ImGui::StyleColorsDark();
|
||||
//ImGui::StyleColorsLight();
|
||||
|
||||
// Setup Platform/Renderer backends
|
||||
[[self openGLContext] makeCurrentContext]; // ImGui_ImplOpenGL3_Init() requires a current GL context.
|
||||
ImGui_ImplOSX_Init(self);
|
||||
ImGui_ImplOpenGL3_Init();
|
||||
|
||||
// Load Fonts
|
||||
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
|
||||
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
|
||||
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
|
||||
// - Read 'docs/FONTS.md' for more instructions and details.
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
//style.FontSizeBase = 20.0f;
|
||||
//io.Fonts->AddFontDefaultVector();
|
||||
//io.Fonts->AddFontDefaultBitmap();
|
||||
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf");
|
||||
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf");
|
||||
//IM_ASSERT(font != nullptr);
|
||||
}
|
||||
|
||||
-(void)updateAndDrawDemoView
|
||||
{
|
||||
// Start the Dear ImGui frame
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplOSX_NewFrame(self);
|
||||
ImGui::NewFrame();
|
||||
|
||||
// Our state (make them static = more or less global) as a convenience to keep the example terse.
|
||||
static bool show_demo_window = true;
|
||||
static bool show_another_window = false;
|
||||
static ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
|
||||
|
||||
// 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
|
||||
if (show_demo_window)
|
||||
ImGui::ShowDemoWindow(&show_demo_window);
|
||||
|
||||
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window.
|
||||
{
|
||||
static float f = 0.0f;
|
||||
static int counter = 0;
|
||||
|
||||
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
|
||||
|
||||
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
|
||||
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
|
||||
ImGui::Checkbox("Another Window", &show_another_window);
|
||||
|
||||
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
|
||||
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
|
||||
|
||||
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
|
||||
counter++;
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("counter = %d", counter);
|
||||
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// 3. Show another simple window.
|
||||
if (show_another_window)
|
||||
{
|
||||
ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
|
||||
ImGui::Text("Hello from another window!");
|
||||
if (ImGui::Button("Close Me"))
|
||||
show_another_window = false;
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// Rendering
|
||||
ImGui::Render();
|
||||
ImDrawData* draw_data = ImGui::GetDrawData();
|
||||
|
||||
[[self openGLContext] makeCurrentContext];
|
||||
GLsizei width = (GLsizei)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x + 0.5f);
|
||||
GLsizei height = (GLsizei)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y + 0.5f);
|
||||
glViewport(0, 0, width, height);
|
||||
glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
ImGui_ImplOpenGL3_RenderDrawData(draw_data);
|
||||
|
||||
// Present
|
||||
[[self openGLContext] flushBuffer];
|
||||
|
||||
if (!animationTimer)
|
||||
animationTimer = [NSTimer scheduledTimerWithTimeInterval:0.017 target:self selector:@selector(animationTimerFired:) userInfo:nil repeats:YES];
|
||||
}
|
||||
|
||||
-(void)reshape { [super reshape]; [[self openGLContext] update]; [self updateAndDrawDemoView]; }
|
||||
-(void)drawRect:(NSRect)bounds { [self updateAndDrawDemoView]; }
|
||||
-(void)animationTimerFired:(NSTimer*)timer { [self setNeedsDisplay:YES]; }
|
||||
-(void)dealloc { animationTimer = nil; }
|
||||
|
||||
@end
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
// AppDelegate
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
@interface AppDelegate : NSObject <NSApplicationDelegate>
|
||||
@property (nonatomic, readonly) NSWindow* window;
|
||||
@end
|
||||
|
||||
@implementation AppDelegate
|
||||
@synthesize window = _window;
|
||||
|
||||
-(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
-(NSWindow*)window
|
||||
{
|
||||
if (_window != nil)
|
||||
return _window;
|
||||
|
||||
NSRect viewRect = NSMakeRect(100.0, 100.0, 100.0 + 1280.0, 100 + 800.0);
|
||||
|
||||
_window = [[NSWindow alloc] initWithContentRect:viewRect styleMask:NSWindowStyleMaskTitled|NSWindowStyleMaskMiniaturizable|NSWindowStyleMaskResizable|NSWindowStyleMaskClosable backing:NSBackingStoreBuffered defer:YES];
|
||||
[_window setTitle:@"Dear ImGui OSX+OpenGL3 Example"];
|
||||
[_window setAcceptsMouseMovedEvents:YES];
|
||||
[_window setOpaque:YES];
|
||||
[_window makeKeyAndOrderFront:NSApp];
|
||||
|
||||
return _window;
|
||||
}
|
||||
|
||||
-(void)setupMenu
|
||||
{
|
||||
NSMenu* mainMenuBar = [[NSMenu alloc] init];
|
||||
NSMenu* appMenu;
|
||||
NSMenuItem* menuItem;
|
||||
|
||||
appMenu = [[NSMenu alloc] initWithTitle:@"Dear ImGui OSX+OpenGL3 Example"];
|
||||
menuItem = [appMenu addItemWithTitle:@"Quit Dear ImGui OSX+OpenGL3 Example" action:@selector(terminate:) keyEquivalent:@"q"];
|
||||
[menuItem setKeyEquivalentModifierMask:NSEventModifierFlagCommand];
|
||||
|
||||
menuItem = [[NSMenuItem alloc] init];
|
||||
[menuItem setSubmenu:appMenu];
|
||||
|
||||
[mainMenuBar addItem:menuItem];
|
||||
|
||||
appMenu = nil;
|
||||
[NSApp setMainMenu:mainMenuBar];
|
||||
}
|
||||
|
||||
-(void)dealloc
|
||||
{
|
||||
_window = nil;
|
||||
}
|
||||
|
||||
-(void)applicationDidFinishLaunching:(NSNotification *)aNotification
|
||||
{
|
||||
// Make the application a foreground application (else it won't receive keyboard events)
|
||||
ProcessSerialNumber psn = {0, kCurrentProcess};
|
||||
TransformProcessType(&psn, kProcessTransformToForegroundApplication);
|
||||
|
||||
// Menu
|
||||
[self setupMenu];
|
||||
|
||||
NSOpenGLPixelFormatAttribute attrs[] =
|
||||
{
|
||||
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
|
||||
NSOpenGLPFADoubleBuffer,
|
||||
NSOpenGLPFADepthSize, 32,
|
||||
0
|
||||
};
|
||||
|
||||
NSOpenGLPixelFormat* format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
|
||||
AppView* view = [[AppView alloc] initWithFrame:self.window.frame pixelFormat:format];
|
||||
format = nil;
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
|
||||
if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6)
|
||||
[view setWantsBestResolutionOpenGLSurface:YES];
|
||||
#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
|
||||
[self.window setContentView:view];
|
||||
|
||||
if ([view openGLContext] == nil)
|
||||
NSLog(@"No OpenGL Context!");
|
||||
|
||||
[view initialize];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
// Application main() function
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
int main(int argc, const char* argv[])
|
||||
{
|
||||
@autoreleasepool
|
||||
{
|
||||
NSApp = [NSApplication sharedApplication];
|
||||
AppDelegate* delegate = [[AppDelegate alloc] init];
|
||||
[[NSApplication sharedApplication] setDelegate:delegate];
|
||||
[NSApp run];
|
||||
}
|
||||
return NSApplicationMain(argc, argv);
|
||||
}
|
||||
|
|
@ -92,6 +92,7 @@
|
|||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\..;..\..\backends;..\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<SupportJustMyCode>false</SupportJustMyCode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
|
|
@ -107,6 +108,7 @@
|
|||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\..;..\..\backends;..\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<SupportJustMyCode>false</SupportJustMyCode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@
|
|||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\..;..\..\backends;..\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<SupportJustMyCode>false</SupportJustMyCode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
|
|
@ -107,6 +108,7 @@
|
|||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\..;..\..\backends;..\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<SupportJustMyCode>false</SupportJustMyCode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
|
|
|
|||
|
|
@ -41,29 +41,26 @@ int main(int, char**)
|
|||
if (!glfwInit())
|
||||
return 1;
|
||||
|
||||
// Decide GL+GLSL versions
|
||||
// Select GL version + let the backend select a GLSL version
|
||||
const char* glsl_version = nullptr;
|
||||
#if defined(IMGUI_IMPL_OPENGL_ES2)
|
||||
// GL ES 2.0 + GLSL 100 (WebGL 1.0)
|
||||
const char* glsl_version = "#version 100";
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
|
||||
#elif defined(IMGUI_IMPL_OPENGL_ES3)
|
||||
// GL ES 3.0 + GLSL 300 es (WebGL 2.0)
|
||||
const char* glsl_version = "#version 300 es";
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
|
||||
#elif defined(__APPLE__)
|
||||
// GL 3.2 + GLSL 150
|
||||
const char* glsl_version = "#version 150";
|
||||
// GL 3.2 + generally GLSL 150
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only
|
||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Required on Mac
|
||||
#else
|
||||
// GL 3.0 + GLSL 130
|
||||
const char* glsl_version = "#version 130";
|
||||
// GL 3.0 + generally GLSL 130
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
||||
//glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@
|
|||
<AdditionalIncludeDirectories>..\..;..\..\backends;%VULKAN_SDK%\include;..\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<SupportJustMyCode>false</SupportJustMyCode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
|
|
@ -109,6 +110,7 @@
|
|||
<AdditionalIncludeDirectories>..\..;..\..\backends;%VULKAN_SDK%\include;..\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<SupportJustMyCode>false</SupportJustMyCode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,3 @@
|
|||
# Building for desktop with Dawn:
|
||||
# 1. git clone https://github.com/google/dawn dawn
|
||||
# 2. cmake -B build -DIMGUI_DAWN_DIR=dawn
|
||||
# 3. cmake --build build
|
||||
# The resulting binary will be found at one of the following locations:
|
||||
# * build/example_glfw_wgpu[.exe] or build/Debug/example_glfw_wgpu[.exe]
|
||||
|
||||
# Building for desktop with WGPU-Native:
|
||||
# 1. download WGPU-Native autogenerated binary modules for your platform/compiler from: https://github.com/gfx-rs/wgpu-native/releases
|
||||
# 2. unzip the downloaded file in your_preferred_folder
|
||||
|
|
@ -13,8 +6,15 @@
|
|||
# The resulting binary will be found at one of the following locations:
|
||||
# * build/example_glfw_wgpu[.exe] or build/Debug/example_glfw_wgpu[.exe]
|
||||
|
||||
# Building for desktop with WGVK (MUCH EASIER)
|
||||
# 1. git clone https://github.com/manuel5975p/WGVK dawn
|
||||
# Building for desktop with Dawn: (VERY LONG TO BUILD)
|
||||
# 1. git clone https://github.com/google/dawn dawn
|
||||
# 2. cmake -B build -DIMGUI_DAWN_DIR=dawn
|
||||
# 3. cmake --build build
|
||||
# The resulting binary will be found at one of the following locations:
|
||||
# * build/example_glfw_wgpu[.exe] or build/Debug/example_glfw_wgpu[.exe]
|
||||
|
||||
# Building for desktop with WGVK:
|
||||
# 1. git clone https://github.com/manuel5975p/WGVK wgvk
|
||||
# 2. cmake -B build -DIMGUI_WGVK_DIR=wgvk
|
||||
# 3. cmake --build build
|
||||
# The resulting binary will be found at one of the following locations:
|
||||
|
|
@ -29,7 +29,7 @@
|
|||
# 4. emrun build/index.html
|
||||
|
||||
cmake_minimum_required(VERSION 3.22) # Dawn requires CMake >= 3.22
|
||||
project(imgui_example_glfw_wgpu C CXX)
|
||||
project(example_glfw_wgpu C CXX)
|
||||
|
||||
set(IMGUI_EXECUTABLE example_glfw_wgpu)
|
||||
|
||||
|
|
@ -37,7 +37,7 @@ if(NOT CMAKE_BUILD_TYPE)
|
|||
set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE)
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17) # Dawn requires C++17
|
||||
set(CMAKE_CXX_STANDARD 20) # Dawn requires C++20
|
||||
|
||||
# Dear ImGui
|
||||
set(IMGUI_DIR ../../)
|
||||
|
|
|
|||
|
|
@ -344,29 +344,25 @@ static WGPUDevice RequestDevice(wgpu::Instance& instance, wgpu::Adapter& adapter
|
|||
static void handle_request_adapter(WGPURequestAdapterStatus status, WGPUAdapter adapter, WGPUStringView message, void* userdata1, void* userdata2)
|
||||
{
|
||||
IM_UNUSED(userdata2);
|
||||
if (status == WGPURequestAdapterStatus_Success)
|
||||
if (status != WGPURequestAdapterStatus_Success)
|
||||
{
|
||||
WGPUAdapter* extAdapter = (WGPUAdapter*)userdata1;
|
||||
*extAdapter = adapter;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Request_adapter status=%#.8x message=%.*s\n", status, (int) message.length, message.data);
|
||||
printf("Request_adapter status=%#.8x message=%.*s\n", status, (int)message.length, message.data);
|
||||
return;
|
||||
}
|
||||
WGPUAdapter* extAdapter = (WGPUAdapter*)userdata1;
|
||||
*extAdapter = adapter;
|
||||
}
|
||||
|
||||
static void handle_request_device(WGPURequestDeviceStatus status, WGPUDevice device, WGPUStringView message, void* userdata1, void* userdata2)
|
||||
{
|
||||
IM_UNUSED(userdata2);
|
||||
if (status == WGPURequestDeviceStatus_Success)
|
||||
if (status != WGPURequestDeviceStatus_Success)
|
||||
{
|
||||
WGPUDevice* extDevice = (WGPUDevice*)userdata1;
|
||||
*extDevice = device;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Request_device status=%#.8x message=%.*s\n", status, (int) message.length, message.data);
|
||||
printf("Request_device status=%#.8x message=%.*s\n", status, (int)message.length, message.data);
|
||||
return;
|
||||
}
|
||||
WGPUDevice* extDevice = (WGPUDevice*)userdata1;
|
||||
*extDevice = device;
|
||||
}
|
||||
|
||||
static WGPUAdapter RequestAdapter(WGPUInstance& instance)
|
||||
|
|
@ -380,8 +376,10 @@ static WGPUAdapter RequestAdapter(WGPUInstance& instance)
|
|||
adapterCallbackInfo.userdata1 = &local_adapter;
|
||||
|
||||
WGPUFuture future = wgpuInstanceRequestAdapter(instance, &adapter_options, adapterCallbackInfo);
|
||||
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||
WGPUFutureWaitInfo waitInfo = { future, false };
|
||||
wgpuInstanceWaitAny(instance, 1, &waitInfo, ~0ull);
|
||||
#endif
|
||||
IM_ASSERT(local_adapter && "Error on Adapter request");
|
||||
return local_adapter;
|
||||
}
|
||||
|
|
@ -393,15 +391,20 @@ static WGPUDevice RequestDevice(WGPUInstance& instance, WGPUAdapter& adapter)
|
|||
deviceCallbackInfo.mode = WGPUCallbackMode_WaitAnyOnly;
|
||||
deviceCallbackInfo.callback = handle_request_device;
|
||||
deviceCallbackInfo.userdata1 = &local_device;
|
||||
|
||||
WGPUFuture future = wgpuAdapterRequestDevice(adapter, nullptr, deviceCallbackInfo);
|
||||
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||
WGPUFutureWaitInfo waitInfo = { future, false };
|
||||
wgpuInstanceWaitAny(instance, 1, &waitInfo, ~0ull);
|
||||
#else
|
||||
IM_UNUSED(instance);
|
||||
#endif
|
||||
IM_ASSERT(local_device && "Error on Device request");
|
||||
return local_device;
|
||||
}
|
||||
#endif // IMGUI_IMPL_WEBGPU_BACKEND_WGPU
|
||||
|
||||
bool InitWGPU(GLFWwindow* window)
|
||||
static bool InitWGPU(GLFWwindow* window)
|
||||
{
|
||||
WGPUTextureFormat preferred_fmt = WGPUTextureFormat_Undefined; // acquired from SurfaceCapabilities
|
||||
|
||||
|
|
@ -450,7 +453,7 @@ bool InitWGPU(GLFWwindow* window)
|
|||
|
||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||
wgpuSetLogCallback(
|
||||
[](WGPULogLevel level, WGPUStringView msg, void* userdata) { fprintf(stderr, "%s: %.*s\n", ImGui_ImplWGPU_GetLogLevelName(level), (int)msg.length, msg.data); }, nullptr
|
||||
[](WGPULogLevel level, WGPUStringView msg, void*) { fprintf(stderr, "%s: %.*s\n", ImGui_ImplWGPU_GetLogLevelName(level), (int)msg.length, msg.data); }, nullptr
|
||||
);
|
||||
wgpuSetLogLevel(WGPULogLevel_Warn);
|
||||
#endif
|
||||
|
|
@ -548,7 +551,7 @@ WGPUSurface CreateWGPUSurface(const WGPUInstance& instance, GLFWwindow* window)
|
|||
{
|
||||
create_info.System = "win32";
|
||||
create_info.RawWindow = (void*)glfwGetWin32Window(window);
|
||||
create_info.RawInstance = (void*)::GetModuleHandle(NULL);
|
||||
create_info.RawInstance = (void*)::GetModuleHandle(nullptr);
|
||||
return ImGui_ImplWGPU_CreateWGPUSurfaceHelper(&create_info);
|
||||
}
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@
|
|||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>$(GLUT_INCLUDE_DIR);..\..;..\..\backends;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<SupportJustMyCode>false</SupportJustMyCode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
|
|
@ -107,6 +108,7 @@
|
|||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>$(GLUT_INCLUDE_DIR);..\..;..\..\backends;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<SupportJustMyCode>false</SupportJustMyCode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@
|
|||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<SupportJustMyCode>false</SupportJustMyCode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
|
|
@ -102,6 +103,7 @@
|
|||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<SupportJustMyCode>false</SupportJustMyCode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
|
|
|
|||
2
examples/example_qnx_opengl3/Makefile
Normal file
2
examples/example_qnx_opengl3/Makefile
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
LIST=OS
|
||||
include recurse.mk
|
||||
29
examples/example_qnx_opengl3/README.md
Normal file
29
examples/example_qnx_opengl3/README.md
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# Dear ImGui QNX Screen + OpenGL ES 3 example
|
||||
|
||||
This example uses:
|
||||
|
||||
- `imgui_impl_qnx.cpp` as the QNX Screen platform backend
|
||||
- `imgui_impl_opengl3.cpp` as the renderer backend
|
||||
- EGL to create an OpenGL ES 3 context and Screen window surface
|
||||
|
||||
`imgui_impl_opengl3.cpp` supports desktop OpenGL and OpenGL ES. On QNX this
|
||||
example compiles it with `IMGUI_IMPL_OPENGL_ES3` and uses `#version 300 es`.
|
||||
No separate Screen/OpenGL renderer backend is required.
|
||||
|
||||
## Build
|
||||
|
||||
Load the QNX SDP environment, then run:
|
||||
|
||||
```sh
|
||||
cd examples/example_qnx_opengl3
|
||||
make
|
||||
```
|
||||
|
||||
The QNX recursive make files build for the CPUs enabled in your SDP
|
||||
configuration and install the program as `example_qnx_opengl3`.
|
||||
|
||||
## Input
|
||||
|
||||
The application polls its `screen_context_t` event queue and forwards every
|
||||
non-`SCREEN_EVENT_NONE` event to `ImGui_ImplQNX_ProcessEvent()`.
|
||||
Escape exits the example.
|
||||
31
examples/example_qnx_opengl3/common.mk
Normal file
31
examples/example_qnx_opengl3/common.mk
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
ifndef QCONFIG
|
||||
QCONFIG=qconfig.mk
|
||||
endif
|
||||
include $(QCONFIG)
|
||||
|
||||
NAME=example_qnx_opengl3
|
||||
|
||||
SRCS = \
|
||||
main.cpp \
|
||||
imgui.cpp \
|
||||
imgui_demo.cpp \
|
||||
imgui_draw.cpp \
|
||||
imgui_tables.cpp \
|
||||
imgui_widgets.cpp \
|
||||
imgui_impl_qnx.cpp \
|
||||
imgui_impl_opengl3.cpp
|
||||
|
||||
EXTRA_SRCVPATH += $(PROJECT_ROOT)/../.. $(PROJECT_ROOT)/../../backends
|
||||
EXTRA_INCVPATH += $(PROJECT_ROOT)/../.. $(PROJECT_ROOT)/../../backends
|
||||
|
||||
CXXFLAGS += -std=gnu++11 -DIMGUI_IMPL_OPENGL_ES3
|
||||
LIBS += EGL GLESv2 screen m
|
||||
|
||||
INSTALLDIR=$(firstword $(INSTALLDIR_$(OS)) usr/bin)
|
||||
|
||||
define PINFO
|
||||
PINFO DESCRIPTION=Dear ImGui QNX Screen and OpenGL ES 3 example
|
||||
endef
|
||||
|
||||
include $(MKFILES_ROOT)/qmacros.mk
|
||||
include $(MKFILES_ROOT)/qtargets.mk
|
||||
307
examples/example_qnx_opengl3/main.cpp
Normal file
307
examples/example_qnx_opengl3/main.cpp
Normal file
|
|
@ -0,0 +1,307 @@
|
|||
// Dear ImGui: standalone example application for QNX Screen + OpenGL ES 3
|
||||
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - 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
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_qnx.h"
|
||||
#include "imgui_impl_opengl3.h"
|
||||
#include <stdio.h> // printf, fprintf
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/keycodes.h>
|
||||
#include <screen/screen.h>
|
||||
#include <EGL/egl.h>
|
||||
#include <GLES3/gl3.h>
|
||||
|
||||
#ifndef EGL_OPENGL_ES3_BIT
|
||||
#ifdef EGL_OPENGL_ES3_BIT_KHR
|
||||
#define EGL_OPENGL_ES3_BIT EGL_OPENGL_ES3_BIT_KHR
|
||||
#else
|
||||
#define EGL_OPENGL_ES3_BIT 0x0040
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct QNXWindow
|
||||
{
|
||||
screen_context_t Context = nullptr;
|
||||
screen_window_t Window = nullptr;
|
||||
screen_event_t Event = nullptr;
|
||||
EGLDisplay Display = EGL_NO_DISPLAY;
|
||||
EGLContext GLContext = EGL_NO_CONTEXT;
|
||||
EGLSurface GLSurface = EGL_NO_SURFACE;
|
||||
int Size[2] = {};
|
||||
};
|
||||
|
||||
// Forward declarations of helper functions
|
||||
bool CreateQNXWindow(QNXWindow* window);
|
||||
void DestroyQNXWindow(QNXWindow* window);
|
||||
bool ProcessQNXEvents(QNXWindow* window);
|
||||
|
||||
// Main code
|
||||
int main(int, char**)
|
||||
{
|
||||
// Setup QNX Screen and EGL
|
||||
QNXWindow window;
|
||||
if (!CreateQNXWindow(&window))
|
||||
{
|
||||
DestroyQNXWindow(&window);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// GL ES 3.0 + GLSL 300 es
|
||||
const char* glsl_version = "#version 300 es";
|
||||
float main_scale = 1.0f;
|
||||
|
||||
// Setup Dear ImGui context
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||
|
||||
// Setup Dear ImGui style
|
||||
ImGui::StyleColorsDark();
|
||||
//ImGui::StyleColorsLight();
|
||||
|
||||
// Setup scaling
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
|
||||
style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor)
|
||||
|
||||
// Setup Platform/Renderer backends
|
||||
ImGui_ImplQNX_Init(window.Context, window.Window);
|
||||
ImGui_ImplOpenGL3_Init(glsl_version);
|
||||
|
||||
// Load Fonts
|
||||
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
|
||||
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
|
||||
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
|
||||
// - Read 'docs/FONTS.md' for more instructions and details.
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
//style.FontSizeBase = 20.0f;
|
||||
//io.Fonts->AddFontDefaultVector();
|
||||
//io.Fonts->AddFontDefaultBitmap();
|
||||
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf");
|
||||
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf");
|
||||
//IM_ASSERT(font != nullptr);
|
||||
|
||||
// Our state
|
||||
bool show_demo_window = true;
|
||||
bool show_another_window = false;
|
||||
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
|
||||
|
||||
// Main loop
|
||||
bool done = false;
|
||||
while (!done)
|
||||
{
|
||||
// Poll and handle events (inputs, window resize, etc.)
|
||||
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
|
||||
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
|
||||
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
||||
if (!ProcessQNXEvents(&window))
|
||||
done = true;
|
||||
|
||||
// Start the Dear ImGui frame
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplQNX_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
// 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
|
||||
if (show_demo_window)
|
||||
ImGui::ShowDemoWindow(&show_demo_window);
|
||||
|
||||
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window.
|
||||
{
|
||||
static float f = 0.0f;
|
||||
static int counter = 0;
|
||||
|
||||
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
|
||||
|
||||
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
|
||||
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
|
||||
ImGui::Checkbox("Another Window", &show_another_window);
|
||||
|
||||
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
|
||||
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
|
||||
|
||||
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
|
||||
counter++;
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("counter = %d", counter);
|
||||
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// 3. Show another simple window.
|
||||
if (show_another_window)
|
||||
{
|
||||
ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
|
||||
ImGui::Text("Hello from another window!");
|
||||
if (ImGui::Button("Close Me"))
|
||||
show_another_window = false;
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// Rendering
|
||||
ImGui::Render();
|
||||
glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
|
||||
glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
eglSwapBuffers(window.Display, window.GLSurface);
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
ImGui_ImplOpenGL3_Shutdown();
|
||||
ImGui_ImplQNX_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
|
||||
DestroyQNXWindow(&window);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Helper functions
|
||||
|
||||
bool CreateQNXWindow(QNXWindow* window)
|
||||
{
|
||||
if (screen_create_context(&window->Context, 0) != 0 ||
|
||||
screen_create_window(&window->Window, window->Context) != 0 ||
|
||||
screen_create_event(&window->Event) != 0)
|
||||
{
|
||||
fprintf(stderr, "QNX Screen initialization failed: %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
// A newly created QNX Screen window reports the fullscreen dimensions.
|
||||
if (screen_get_window_property_iv(window->Window, SCREEN_PROPERTY_SIZE, window->Size) != 0 || window->Size[0] <= 0 || window->Size[1] <= 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to obtain QNX Screen window size: %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
const int usage = SCREEN_USAGE_OPENGL_ES2 | SCREEN_USAGE_OPENGL_ES3 | SCREEN_USAGE_NATIVE;
|
||||
const int transparency = SCREEN_TRANSPARENCY_NONE;
|
||||
const int swap_interval = 1;
|
||||
if (screen_set_window_property_iv(window->Window, SCREEN_PROPERTY_USAGE, &usage) != 0 ||
|
||||
screen_set_window_property_iv(window->Window, SCREEN_PROPERTY_SIZE, window->Size) != 0 ||
|
||||
screen_set_window_property_iv(window->Window, SCREEN_PROPERTY_TRANSPARENCY, &transparency) != 0 ||
|
||||
screen_set_window_property_iv(window->Window, SCREEN_PROPERTY_SWAP_INTERVAL, &swap_interval) != 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to configure QNX Screen window: %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
window->Display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
if (window->Display == EGL_NO_DISPLAY || eglInitialize(window->Display, nullptr, nullptr) != EGL_TRUE || eglBindAPI(EGL_OPENGL_ES_API) != EGL_TRUE)
|
||||
{
|
||||
fprintf(stderr, "EGL initialization failed: 0x%04x\n", eglGetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
const EGLint config_attributes[] =
|
||||
{
|
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT,
|
||||
EGL_RED_SIZE, 8,
|
||||
EGL_GREEN_SIZE, 8,
|
||||
EGL_BLUE_SIZE, 8,
|
||||
EGL_ALPHA_SIZE, 8,
|
||||
EGL_DEPTH_SIZE, 24,
|
||||
EGL_STENCIL_SIZE, 8,
|
||||
EGL_NONE
|
||||
};
|
||||
EGLConfig config = nullptr;
|
||||
EGLint config_count = 0;
|
||||
if (eglChooseConfig(window->Display, config_attributes, &config, 1, &config_count) != EGL_TRUE || config_count == 0)
|
||||
{
|
||||
fprintf(stderr, "eglChooseConfig() failed: 0x%04x\n", eglGetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
EGLint native_visual = 0;
|
||||
if (eglGetConfigAttrib(window->Display, config, EGL_NATIVE_VISUAL_ID, &native_visual) != EGL_TRUE ||
|
||||
screen_set_window_property_iv(window->Window, SCREEN_PROPERTY_FORMAT, &native_visual) != 0 ||
|
||||
screen_create_window_buffers(window->Window, 2) != 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to create QNX Screen buffers: %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
const EGLint context_attributes[] = { EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE };
|
||||
window->GLContext = eglCreateContext(window->Display, config, EGL_NO_CONTEXT, context_attributes);
|
||||
window->GLSurface = eglCreateWindowSurface(window->Display, config, window->Window, nullptr);
|
||||
if (window->GLContext == EGL_NO_CONTEXT || window->GLSurface == EGL_NO_SURFACE ||
|
||||
eglMakeCurrent(window->Display, window->GLSurface, window->GLSurface, window->GLContext) != EGL_TRUE ||
|
||||
eglSwapInterval(window->Display, 1) != EGL_TRUE)
|
||||
{
|
||||
fprintf(stderr, "EGL context creation failed: 0x%04x\n", eglGetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
const int visible = 1;
|
||||
if (screen_set_window_property_iv(window->Window, SCREEN_PROPERTY_VISIBLE, &visible) != 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to show QNX Screen window: %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void DestroyQNXWindow(QNXWindow* window)
|
||||
{
|
||||
if (window->Display != EGL_NO_DISPLAY)
|
||||
{
|
||||
eglMakeCurrent(window->Display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
if (window->GLSurface != EGL_NO_SURFACE)
|
||||
eglDestroySurface(window->Display, window->GLSurface);
|
||||
if (window->GLContext != EGL_NO_CONTEXT)
|
||||
eglDestroyContext(window->Display, window->GLContext);
|
||||
eglTerminate(window->Display);
|
||||
}
|
||||
if (window->Event != nullptr)
|
||||
screen_destroy_event(window->Event);
|
||||
if (window->Window != nullptr)
|
||||
screen_destroy_window(window->Window);
|
||||
if (window->Context != nullptr)
|
||||
screen_destroy_context(window->Context);
|
||||
}
|
||||
|
||||
bool ProcessQNXEvents(QNXWindow* window)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (screen_get_event(window->Context, window->Event, 0) != 0)
|
||||
return false;
|
||||
|
||||
int type = SCREEN_EVENT_NONE;
|
||||
if (screen_get_event_property_iv(window->Event, SCREEN_PROPERTY_TYPE, &type) != 0)
|
||||
return false;
|
||||
if (type == SCREEN_EVENT_NONE)
|
||||
return true;
|
||||
|
||||
ImGui_ImplQNX_ProcessEvent(window->Event);
|
||||
if (type == SCREEN_EVENT_CLOSE)
|
||||
return false;
|
||||
if (type == SCREEN_EVENT_KEYBOARD)
|
||||
{
|
||||
int flags = 0;
|
||||
int key_cap = 0;
|
||||
if (screen_get_event_property_iv(window->Event, SCREEN_PROPERTY_FLAGS, &flags) == 0 &&
|
||||
screen_get_event_property_iv(window->Event, SCREEN_PROPERTY_KEY_CAP, &key_cap) == 0 &&
|
||||
(flags & SCREEN_FLAG_KEY_DOWN) != 0 && key_cap == KEYCODE_ESCAPE)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
8
examples/example_qnx_opengl3/nto/Makefile
Normal file
8
examples/example_qnx_opengl3/nto/Makefile
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
LIST=CPU
|
||||
ifndef QRECURSE
|
||||
QRECURSE=recurse.mk
|
||||
ifdef QCONFIG
|
||||
QRDIR=$(dir $(QCONFIG))
|
||||
endif
|
||||
endif
|
||||
include $(QRDIR)$(QRECURSE)
|
||||
8
examples/example_qnx_opengl3/nto/aarch64/Makefile
Normal file
8
examples/example_qnx_opengl3/nto/aarch64/Makefile
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
LIST=VARIANT
|
||||
ifndef QRECURSE
|
||||
QRECURSE=recurse.mk
|
||||
ifdef QCONFIG
|
||||
QRDIR=$(dir $(QCONFIG))
|
||||
endif
|
||||
endif
|
||||
include $(QRDIR)$(QRECURSE)
|
||||
1
examples/example_qnx_opengl3/nto/aarch64/o.le/Makefile
Normal file
1
examples/example_qnx_opengl3/nto/aarch64/o.le/Makefile
Normal file
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
||||
8
examples/example_qnx_opengl3/nto/x86_64/Makefile
Normal file
8
examples/example_qnx_opengl3/nto/x86_64/Makefile
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
LIST=VARIANT
|
||||
ifndef QRECURSE
|
||||
QRECURSE=recurse.mk
|
||||
ifdef QCONFIG
|
||||
QRDIR=$(dir $(QCONFIG))
|
||||
endif
|
||||
endif
|
||||
include $(QRDIR)$(QRECURSE)
|
||||
1
examples/example_qnx_opengl3/nto/x86_64/o/Makefile
Normal file
1
examples/example_qnx_opengl3/nto/x86_64/o/Makefile
Normal file
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
||||
2
examples/example_qnx_vulkan/Makefile
Normal file
2
examples/example_qnx_vulkan/Makefile
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
LIST=OS
|
||||
include recurse.mk
|
||||
29
examples/example_qnx_vulkan/README.md
Normal file
29
examples/example_qnx_vulkan/README.md
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# Dear ImGui QNX Screen + Vulkan example
|
||||
|
||||
This example uses:
|
||||
|
||||
- `imgui_impl_qnx.cpp` as the QNX Screen platform backend
|
||||
- the unmodified `imgui_impl_vulkan.cpp` renderer backend
|
||||
- `vkCreateScreenSurfaceQNX()` and `VK_QNX_screen_surface`
|
||||
|
||||
No separate Screen/Vulkan renderer backend is required. The QNX-specific work
|
||||
is limited to the Screen platform backend, native window setup, and Vulkan WSI
|
||||
surface creation.
|
||||
|
||||
## Build
|
||||
|
||||
Load the QNX SDP environment, then run:
|
||||
|
||||
```sh
|
||||
cd examples/example_qnx_vulkan
|
||||
make
|
||||
```
|
||||
|
||||
The build defines `VK_USE_PLATFORM_SCREEN_QNX` and links `libvulkan` and
|
||||
`libscreen`.
|
||||
|
||||
## Input and resize
|
||||
|
||||
The application forwards Screen input events to `ImGui_ImplQNX_ProcessEvent()`.
|
||||
It recreates the Vulkan swapchain when the Screen window size changes or Vulkan
|
||||
reports `VK_ERROR_OUT_OF_DATE_KHR` / `VK_SUBOPTIMAL_KHR`. Escape exits.
|
||||
31
examples/example_qnx_vulkan/common.mk
Normal file
31
examples/example_qnx_vulkan/common.mk
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
ifndef QCONFIG
|
||||
QCONFIG=qconfig.mk
|
||||
endif
|
||||
include $(QCONFIG)
|
||||
|
||||
NAME=example_qnx_vulkan
|
||||
|
||||
SRCS = \
|
||||
main.cpp \
|
||||
imgui.cpp \
|
||||
imgui_demo.cpp \
|
||||
imgui_draw.cpp \
|
||||
imgui_tables.cpp \
|
||||
imgui_widgets.cpp \
|
||||
imgui_impl_qnx.cpp \
|
||||
imgui_impl_vulkan.cpp
|
||||
|
||||
EXTRA_SRCVPATH += $(PROJECT_ROOT)/../.. $(PROJECT_ROOT)/../../backends
|
||||
EXTRA_INCVPATH += $(PROJECT_ROOT)/../.. $(PROJECT_ROOT)/../../backends
|
||||
|
||||
CXXFLAGS += -std=gnu++11 -DVK_USE_PLATFORM_SCREEN_QNX=1
|
||||
LIBS += vulkan screen m
|
||||
|
||||
INSTALLDIR=$(firstword $(INSTALLDIR_$(OS)) usr/bin)
|
||||
|
||||
define PINFO
|
||||
PINFO DESCRIPTION=Dear ImGui QNX Screen and Vulkan example
|
||||
endef
|
||||
|
||||
include $(MKFILES_ROOT)/qmacros.mk
|
||||
include $(MKFILES_ROOT)/qtargets.mk
|
||||
626
examples/example_qnx_vulkan/main.cpp
Normal file
626
examples/example_qnx_vulkan/main.cpp
Normal file
|
|
@ -0,0 +1,626 @@
|
|||
// Dear ImGui: standalone example application for QNX Screen + Vulkan
|
||||
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - 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
|
||||
|
||||
// Important note to the reader who wish to integrate imgui_impl_vulkan.cpp/.h in their own engine/app.
|
||||
// - Common ImGui_ImplVulkan_XXX functions and structures are used to interface with imgui_impl_vulkan.cpp/.h.
|
||||
// You will use those if you want to use this rendering backend in your engine/app.
|
||||
// - Helper ImGui_ImplVulkanH_XXX functions and structures are only used by this example (main.cpp) and by
|
||||
// the backend itself (imgui_impl_vulkan.cpp), but should PROBABLY NOT be used by your own engine/app code.
|
||||
// Read comments in imgui_impl_vulkan.h.
|
||||
|
||||
#ifndef VK_USE_PLATFORM_SCREEN_QNX
|
||||
#define VK_USE_PLATFORM_SCREEN_QNX
|
||||
#endif
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_qnx.h"
|
||||
#include "imgui_impl_vulkan.h"
|
||||
#include <stdio.h> // printf, fprintf
|
||||
#include <stdlib.h> // abort
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/keycodes.h>
|
||||
#include <time.h>
|
||||
#include <screen/screen.h>
|
||||
|
||||
// Volk headers
|
||||
#ifdef IMGUI_IMPL_VULKAN_USE_VOLK
|
||||
#define VOLK_IMPLEMENTATION
|
||||
#include <volk.h>
|
||||
#endif
|
||||
|
||||
//#define APP_USE_UNLIMITED_FRAME_RATE
|
||||
#ifdef _DEBUG
|
||||
#define APP_USE_VULKAN_DEBUG_REPORT
|
||||
static VkDebugReportCallbackEXT g_DebugReport = VK_NULL_HANDLE;
|
||||
#endif
|
||||
|
||||
// Data
|
||||
static VkAllocationCallbacks* g_Allocator = nullptr;
|
||||
static VkInstance g_Instance = VK_NULL_HANDLE;
|
||||
static VkPhysicalDevice g_PhysicalDevice = VK_NULL_HANDLE;
|
||||
static VkDevice g_Device = VK_NULL_HANDLE;
|
||||
static uint32_t g_QueueFamily = (uint32_t)-1;
|
||||
static VkQueue g_Queue = VK_NULL_HANDLE;
|
||||
static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE;
|
||||
static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE;
|
||||
|
||||
static ImGui_ImplVulkanH_Window g_MainWindowData;
|
||||
static uint32_t g_MinImageCount = 2;
|
||||
static bool g_SwapChainRebuild = false;
|
||||
|
||||
static void check_vk_result(VkResult err)
|
||||
{
|
||||
if (err == VK_SUCCESS)
|
||||
return;
|
||||
fprintf(stderr, "[vulkan] Error: VkResult = %d\n", err);
|
||||
if (err < 0)
|
||||
abort();
|
||||
}
|
||||
|
||||
#ifdef APP_USE_VULKAN_DEBUG_REPORT
|
||||
static VKAPI_ATTR VkBool32 VKAPI_CALL debug_report(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage, void* pUserData)
|
||||
{
|
||||
(void)flags; (void)object; (void)location; (void)messageCode; (void)pUserData; (void)pLayerPrefix; // Unused arguments
|
||||
fprintf(stderr, "[vulkan] Debug report from ObjectType: %i\nMessage: %s\n\n", objectType, pMessage);
|
||||
return VK_FALSE;
|
||||
}
|
||||
#endif // APP_USE_VULKAN_DEBUG_REPORT
|
||||
|
||||
static bool IsExtensionAvailable(const ImVector<VkExtensionProperties>& properties, const char* extension)
|
||||
{
|
||||
for (const VkExtensionProperties& p : properties)
|
||||
if (strcmp(p.extensionName, extension) == 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void SetupVulkan(ImVector<const char*> instance_extensions)
|
||||
{
|
||||
VkResult err;
|
||||
#ifdef IMGUI_IMPL_VULKAN_USE_VOLK
|
||||
volkInitialize();
|
||||
#endif
|
||||
|
||||
// Create Vulkan Instance
|
||||
{
|
||||
VkInstanceCreateInfo create_info = {};
|
||||
create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||
|
||||
// Enumerate available extensions
|
||||
uint32_t properties_count;
|
||||
ImVector<VkExtensionProperties> properties;
|
||||
vkEnumerateInstanceExtensionProperties(nullptr, &properties_count, nullptr);
|
||||
properties.resize(properties_count);
|
||||
err = vkEnumerateInstanceExtensionProperties(nullptr, &properties_count, properties.Data);
|
||||
check_vk_result(err);
|
||||
|
||||
// Enable required extensions
|
||||
if (IsExtensionAvailable(properties, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME))
|
||||
instance_extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
|
||||
#ifdef VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME
|
||||
if (IsExtensionAvailable(properties, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME))
|
||||
{
|
||||
instance_extensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
|
||||
create_info.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Enabling validation layers
|
||||
#ifdef APP_USE_VULKAN_DEBUG_REPORT
|
||||
const char* layers[] = { "VK_LAYER_KHRONOS_validation" };
|
||||
create_info.enabledLayerCount = 1;
|
||||
create_info.ppEnabledLayerNames = layers;
|
||||
instance_extensions.push_back("VK_EXT_debug_report");
|
||||
#endif
|
||||
|
||||
// Create Vulkan Instance
|
||||
create_info.enabledExtensionCount = (uint32_t)instance_extensions.Size;
|
||||
create_info.ppEnabledExtensionNames = instance_extensions.Data;
|
||||
err = vkCreateInstance(&create_info, g_Allocator, &g_Instance);
|
||||
check_vk_result(err);
|
||||
#ifdef IMGUI_IMPL_VULKAN_USE_VOLK
|
||||
volkLoadInstance(g_Instance);
|
||||
#endif
|
||||
|
||||
// Setup the debug report callback
|
||||
#ifdef APP_USE_VULKAN_DEBUG_REPORT
|
||||
auto f_vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT");
|
||||
IM_ASSERT(f_vkCreateDebugReportCallbackEXT != nullptr);
|
||||
VkDebugReportCallbackCreateInfoEXT debug_report_ci = {};
|
||||
debug_report_ci.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
|
||||
debug_report_ci.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
|
||||
debug_report_ci.pfnCallback = debug_report;
|
||||
debug_report_ci.pUserData = nullptr;
|
||||
err = f_vkCreateDebugReportCallbackEXT(g_Instance, &debug_report_ci, g_Allocator, &g_DebugReport);
|
||||
check_vk_result(err);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Select Physical Device (GPU)
|
||||
g_PhysicalDevice = ImGui_ImplVulkanH_SelectPhysicalDevice(g_Instance);
|
||||
IM_ASSERT(g_PhysicalDevice != VK_NULL_HANDLE);
|
||||
|
||||
// Select graphics queue family
|
||||
g_QueueFamily = ImGui_ImplVulkanH_SelectQueueFamilyIndex(g_PhysicalDevice);
|
||||
IM_ASSERT(g_QueueFamily != (uint32_t)-1);
|
||||
|
||||
// Create Logical Device (with 1 queue)
|
||||
{
|
||||
ImVector<const char*> device_extensions;
|
||||
device_extensions.push_back("VK_KHR_swapchain");
|
||||
|
||||
// Enumerate physical device extension
|
||||
uint32_t properties_count;
|
||||
ImVector<VkExtensionProperties> properties;
|
||||
vkEnumerateDeviceExtensionProperties(g_PhysicalDevice, nullptr, &properties_count, nullptr);
|
||||
properties.resize(properties_count);
|
||||
vkEnumerateDeviceExtensionProperties(g_PhysicalDevice, nullptr, &properties_count, properties.Data);
|
||||
#ifdef VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME
|
||||
if (IsExtensionAvailable(properties, VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME))
|
||||
device_extensions.push_back(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME);
|
||||
#endif
|
||||
|
||||
const float queue_priority[] = { 1.0f };
|
||||
VkDeviceQueueCreateInfo queue_info[1] = {};
|
||||
queue_info[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||
queue_info[0].queueFamilyIndex = g_QueueFamily;
|
||||
queue_info[0].queueCount = 1;
|
||||
queue_info[0].pQueuePriorities = queue_priority;
|
||||
VkDeviceCreateInfo create_info = {};
|
||||
create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||
create_info.queueCreateInfoCount = sizeof(queue_info) / sizeof(queue_info[0]);
|
||||
create_info.pQueueCreateInfos = queue_info;
|
||||
create_info.enabledExtensionCount = (uint32_t)device_extensions.Size;
|
||||
create_info.ppEnabledExtensionNames = device_extensions.Data;
|
||||
err = vkCreateDevice(g_PhysicalDevice, &create_info, g_Allocator, &g_Device);
|
||||
check_vk_result(err);
|
||||
vkGetDeviceQueue(g_Device, g_QueueFamily, 0, &g_Queue);
|
||||
}
|
||||
|
||||
// Create Descriptor Pool
|
||||
// If you wish to load e.g. additional textures you may need to alter pools sizes and maxSets.
|
||||
{
|
||||
VkDescriptorPoolSize pool_sizes[] =
|
||||
{
|
||||
{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE },
|
||||
{ VK_DESCRIPTOR_TYPE_SAMPLER, IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE },
|
||||
};
|
||||
VkDescriptorPoolCreateInfo pool_info = {};
|
||||
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
||||
pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
|
||||
pool_info.maxSets = 0;
|
||||
for (VkDescriptorPoolSize& pool_size : pool_sizes)
|
||||
pool_info.maxSets += pool_size.descriptorCount;
|
||||
pool_info.poolSizeCount = (uint32_t)IM_COUNTOF(pool_sizes);
|
||||
pool_info.pPoolSizes = pool_sizes;
|
||||
err = vkCreateDescriptorPool(g_Device, &pool_info, g_Allocator, &g_DescriptorPool);
|
||||
check_vk_result(err);
|
||||
}
|
||||
}
|
||||
|
||||
// All the ImGui_ImplVulkanH_XXX structures/functions are optional helpers used by the demo.
|
||||
// Your real engine/app may not use them.
|
||||
static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface, int width, int height)
|
||||
{
|
||||
// Check for WSI support
|
||||
VkBool32 res;
|
||||
vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, surface, &res);
|
||||
if (res != VK_TRUE)
|
||||
{
|
||||
fprintf(stderr, "Error no WSI support on physical device 0\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// Select Surface Format
|
||||
const VkFormat requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM };
|
||||
const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
|
||||
wd->Surface = surface;
|
||||
wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_COUNTOF(requestSurfaceImageFormat), requestSurfaceColorSpace);
|
||||
|
||||
// Select Present Mode
|
||||
#ifdef APP_USE_UNLIMITED_FRAME_RATE
|
||||
VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_FIFO_KHR };
|
||||
#else
|
||||
VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_FIFO_KHR };
|
||||
#endif
|
||||
wd->PresentMode = ImGui_ImplVulkanH_SelectPresentMode(g_PhysicalDevice, wd->Surface, &present_modes[0], IM_COUNTOF(present_modes));
|
||||
//printf("[vulkan] Selected PresentMode = %d\n", wd->PresentMode);
|
||||
|
||||
// Create SwapChain, RenderPass, Framebuffer, etc.
|
||||
IM_ASSERT(g_MinImageCount >= 2);
|
||||
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount, 0);
|
||||
}
|
||||
|
||||
static void CleanupVulkan()
|
||||
{
|
||||
vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator);
|
||||
|
||||
#ifdef APP_USE_VULKAN_DEBUG_REPORT
|
||||
// Remove the debug report callback
|
||||
auto f_vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkDestroyDebugReportCallbackEXT");
|
||||
f_vkDestroyDebugReportCallbackEXT(g_Instance, g_DebugReport, g_Allocator);
|
||||
#endif // APP_USE_VULKAN_DEBUG_REPORT
|
||||
|
||||
vkDestroyDevice(g_Device, g_Allocator);
|
||||
vkDestroyInstance(g_Instance, g_Allocator);
|
||||
}
|
||||
|
||||
static void CleanupVulkanWindow(ImGui_ImplVulkanH_Window* wd)
|
||||
{
|
||||
ImGui_ImplVulkanH_DestroyWindow(g_Instance, g_Device, wd, g_Allocator);
|
||||
vkDestroySurfaceKHR(g_Instance, wd->Surface, g_Allocator);
|
||||
}
|
||||
|
||||
static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data)
|
||||
{
|
||||
VkSemaphore image_acquired_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].ImageAcquiredSemaphore;
|
||||
VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore;
|
||||
VkResult err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &wd->FrameIndex);
|
||||
if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR)
|
||||
g_SwapChainRebuild = true;
|
||||
if (err == VK_ERROR_OUT_OF_DATE_KHR)
|
||||
return;
|
||||
if (err != VK_SUBOPTIMAL_KHR)
|
||||
check_vk_result(err);
|
||||
|
||||
ImGui_ImplVulkanH_Frame* fd = &wd->Frames[wd->FrameIndex];
|
||||
{
|
||||
err = vkWaitForFences(g_Device, 1, &fd->Fence, VK_TRUE, UINT64_MAX); // wait indefinitely instead of periodically checking
|
||||
check_vk_result(err);
|
||||
|
||||
err = vkResetFences(g_Device, 1, &fd->Fence);
|
||||
check_vk_result(err);
|
||||
}
|
||||
{
|
||||
err = vkResetCommandPool(g_Device, fd->CommandPool, 0);
|
||||
check_vk_result(err);
|
||||
VkCommandBufferBeginInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||
info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||
err = vkBeginCommandBuffer(fd->CommandBuffer, &info);
|
||||
check_vk_result(err);
|
||||
}
|
||||
{
|
||||
VkRenderPassBeginInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
info.renderPass = wd->RenderPass;
|
||||
info.framebuffer = fd->Framebuffer;
|
||||
info.renderArea.extent.width = wd->Width;
|
||||
info.renderArea.extent.height = wd->Height;
|
||||
info.clearValueCount = 1;
|
||||
info.pClearValues = &wd->ClearValue;
|
||||
vkCmdBeginRenderPass(fd->CommandBuffer, &info, VK_SUBPASS_CONTENTS_INLINE);
|
||||
}
|
||||
|
||||
// Record dear imgui primitives into command buffer
|
||||
ImGui_ImplVulkan_RenderDrawData(draw_data, fd->CommandBuffer);
|
||||
|
||||
// Submit command buffer
|
||||
vkCmdEndRenderPass(fd->CommandBuffer);
|
||||
{
|
||||
VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
VkSubmitInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||
info.waitSemaphoreCount = 1;
|
||||
info.pWaitSemaphores = &image_acquired_semaphore;
|
||||
info.pWaitDstStageMask = &wait_stage;
|
||||
info.commandBufferCount = 1;
|
||||
info.pCommandBuffers = &fd->CommandBuffer;
|
||||
info.signalSemaphoreCount = 1;
|
||||
info.pSignalSemaphores = &render_complete_semaphore;
|
||||
|
||||
err = vkEndCommandBuffer(fd->CommandBuffer);
|
||||
check_vk_result(err);
|
||||
err = vkQueueSubmit(g_Queue, 1, &info, fd->Fence);
|
||||
check_vk_result(err);
|
||||
}
|
||||
}
|
||||
|
||||
static void FramePresent(ImGui_ImplVulkanH_Window* wd)
|
||||
{
|
||||
if (g_SwapChainRebuild)
|
||||
return;
|
||||
VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore;
|
||||
VkPresentInfoKHR info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||
info.waitSemaphoreCount = 1;
|
||||
info.pWaitSemaphores = &render_complete_semaphore;
|
||||
info.swapchainCount = 1;
|
||||
info.pSwapchains = &wd->Swapchain;
|
||||
info.pImageIndices = &wd->FrameIndex;
|
||||
VkResult err = vkQueuePresentKHR(g_Queue, &info);
|
||||
if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR)
|
||||
g_SwapChainRebuild = true;
|
||||
if (err == VK_ERROR_OUT_OF_DATE_KHR)
|
||||
return;
|
||||
if (err != VK_SUBOPTIMAL_KHR)
|
||||
check_vk_result(err);
|
||||
wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->SemaphoreCount; // Now we can use the next set of semaphores
|
||||
}
|
||||
|
||||
|
||||
struct QNXWindow
|
||||
{
|
||||
screen_context_t Context = nullptr;
|
||||
screen_window_t Window = nullptr;
|
||||
screen_event_t Event = nullptr;
|
||||
int Size[2] = {};
|
||||
};
|
||||
|
||||
static bool CreateQNXWindow(QNXWindow* window)
|
||||
{
|
||||
if (screen_create_context(&window->Context, 0) != 0 ||
|
||||
screen_create_window(&window->Window, window->Context) != 0 ||
|
||||
screen_create_event(&window->Event) != 0)
|
||||
{
|
||||
fprintf(stderr, "QNX Screen initialization failed: %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
// A newly created QNX Screen window reports the fullscreen dimensions.
|
||||
if (screen_get_window_property_iv(window->Window, SCREEN_PROPERTY_SIZE, window->Size) != 0 || window->Size[0] <= 0 || window->Size[1] <= 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to obtain QNX Screen window size: %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
const int usage = SCREEN_USAGE_VULKAN | SCREEN_USAGE_NATIVE;
|
||||
const int transparency = SCREEN_TRANSPARENCY_NONE;
|
||||
if (screen_set_window_property_iv(window->Window, SCREEN_PROPERTY_USAGE, &usage) != 0 ||
|
||||
screen_set_window_property_iv(window->Window, SCREEN_PROPERTY_SIZE, window->Size) != 0 ||
|
||||
screen_set_window_property_iv(window->Window, SCREEN_PROPERTY_TRANSPARENCY, &transparency) != 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to configure QNX Screen window: %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void DestroyQNXWindow(QNXWindow* window)
|
||||
{
|
||||
if (window->Event != nullptr)
|
||||
screen_destroy_event(window->Event);
|
||||
if (window->Window != nullptr)
|
||||
screen_destroy_window(window->Window);
|
||||
if (window->Context != nullptr)
|
||||
screen_destroy_context(window->Context);
|
||||
}
|
||||
|
||||
static bool ProcessQNXEvents(QNXWindow* window)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (screen_get_event(window->Context, window->Event, 0) != 0)
|
||||
return false;
|
||||
|
||||
int type = SCREEN_EVENT_NONE;
|
||||
if (screen_get_event_property_iv(window->Event, SCREEN_PROPERTY_TYPE, &type) != 0)
|
||||
return false;
|
||||
if (type == SCREEN_EVENT_NONE)
|
||||
return true;
|
||||
|
||||
ImGui_ImplQNX_ProcessEvent(window->Event);
|
||||
if (type == SCREEN_EVENT_CLOSE)
|
||||
return false;
|
||||
if (type == SCREEN_EVENT_KEYBOARD)
|
||||
{
|
||||
int flags = 0;
|
||||
int key_cap = 0;
|
||||
if (screen_get_event_property_iv(window->Event, SCREEN_PROPERTY_FLAGS, &flags) == 0 &&
|
||||
screen_get_event_property_iv(window->Event, SCREEN_PROPERTY_KEY_CAP, &key_cap) == 0 &&
|
||||
(flags & SCREEN_FLAG_KEY_DOWN) != 0 && key_cap == KEYCODE_ESCAPE)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void QNXSleep(int milliseconds)
|
||||
{
|
||||
struct timespec request = { milliseconds / 1000, (milliseconds % 1000) * 1000000L };
|
||||
nanosleep(&request, nullptr);
|
||||
}
|
||||
|
||||
// Main code
|
||||
int main(int, char**)
|
||||
{
|
||||
// Create window with Vulkan graphics context
|
||||
QNXWindow window;
|
||||
if (!CreateQNXWindow(&window))
|
||||
{
|
||||
DestroyQNXWindow(&window);
|
||||
return 1;
|
||||
}
|
||||
float main_scale = 1.0f;
|
||||
|
||||
ImVector<const char*> extensions;
|
||||
extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
|
||||
extensions.push_back(VK_QNX_SCREEN_SURFACE_EXTENSION_NAME);
|
||||
SetupVulkan(extensions);
|
||||
|
||||
// Create Window Surface
|
||||
VkScreenSurfaceCreateInfoQNX surface_create_info = {};
|
||||
surface_create_info.sType = VK_STRUCTURE_TYPE_SCREEN_SURFACE_CREATE_INFO_QNX;
|
||||
surface_create_info.context = window.Context;
|
||||
surface_create_info.window = window.Window;
|
||||
VkSurfaceKHR surface;
|
||||
VkResult err = vkCreateScreenSurfaceQNX(g_Instance, &surface_create_info, g_Allocator, &surface);
|
||||
check_vk_result(err);
|
||||
|
||||
// Create Framebuffers
|
||||
int w = window.Size[0];
|
||||
int h = window.Size[1];
|
||||
ImGui_ImplVulkanH_Window* wd = &g_MainWindowData;
|
||||
SetupVulkanWindow(wd, surface, w, h);
|
||||
|
||||
const int visible = 1;
|
||||
if (screen_set_window_property_iv(window.Window, SCREEN_PROPERTY_VISIBLE, &visible) != 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to show QNX Screen window: %s\n", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Setup Dear ImGui context
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||
|
||||
// Setup Dear ImGui style
|
||||
ImGui::StyleColorsDark();
|
||||
//ImGui::StyleColorsLight();
|
||||
|
||||
// Setup scaling
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
|
||||
style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor)
|
||||
|
||||
// Setup Platform/Renderer backends
|
||||
ImGui_ImplQNX_Init(window.Context, window.Window);
|
||||
ImGui_ImplVulkan_InitInfo init_info = {};
|
||||
//init_info.ApiVersion = VK_API_VERSION_1_3; // Pass in your value of VkApplicationInfo::apiVersion, otherwise will default to header version.
|
||||
init_info.Instance = g_Instance;
|
||||
init_info.PhysicalDevice = g_PhysicalDevice;
|
||||
init_info.Device = g_Device;
|
||||
init_info.QueueFamily = g_QueueFamily;
|
||||
init_info.Queue = g_Queue;
|
||||
init_info.PipelineCache = g_PipelineCache;
|
||||
init_info.DescriptorPool = g_DescriptorPool;
|
||||
init_info.MinImageCount = g_MinImageCount;
|
||||
init_info.ImageCount = wd->ImageCount;
|
||||
init_info.Allocator = g_Allocator;
|
||||
init_info.PipelineInfoMain.RenderPass = wd->RenderPass;
|
||||
init_info.PipelineInfoMain.Subpass = 0;
|
||||
init_info.PipelineInfoMain.MSAASamples = VK_SAMPLE_COUNT_1_BIT;
|
||||
init_info.CheckVkResultFn = check_vk_result;
|
||||
ImGui_ImplVulkan_Init(&init_info);
|
||||
|
||||
// Load Fonts
|
||||
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
|
||||
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
|
||||
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
|
||||
// - Read 'docs/FONTS.md' for more instructions and details.
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
//style.FontSizeBase = 20.0f;
|
||||
//io.Fonts->AddFontDefaultVector();
|
||||
//io.Fonts->AddFontDefaultBitmap();
|
||||
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf");
|
||||
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf");
|
||||
//IM_ASSERT(font != nullptr);
|
||||
|
||||
// Our state
|
||||
bool show_demo_window = true;
|
||||
bool show_another_window = false;
|
||||
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
|
||||
|
||||
// Main loop
|
||||
bool done = false;
|
||||
while (!done)
|
||||
{
|
||||
// Poll and handle events (inputs, window resize, etc.)
|
||||
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
|
||||
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
|
||||
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
||||
if (!ProcessQNXEvents(&window))
|
||||
done = true;
|
||||
|
||||
// Resize swap chain?
|
||||
int framebuffer_size[2] = {};
|
||||
if (screen_get_window_property_iv(window.Window, SCREEN_PROPERTY_SIZE, framebuffer_size) != 0)
|
||||
done = true;
|
||||
int fb_width = framebuffer_size[0];
|
||||
int fb_height = framebuffer_size[1];
|
||||
if (fb_width <= 0 || fb_height <= 0)
|
||||
{
|
||||
QNXSleep(10);
|
||||
continue;
|
||||
}
|
||||
if (fb_width > 0 && fb_height > 0 && (g_SwapChainRebuild || g_MainWindowData.Width != fb_width || g_MainWindowData.Height != fb_height))
|
||||
{
|
||||
ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount);
|
||||
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount, 0);
|
||||
g_MainWindowData.FrameIndex = 0;
|
||||
g_SwapChainRebuild = false;
|
||||
}
|
||||
|
||||
// Start the Dear ImGui frame
|
||||
ImGui_ImplVulkan_NewFrame();
|
||||
ImGui_ImplQNX_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
// 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
|
||||
if (show_demo_window)
|
||||
ImGui::ShowDemoWindow(&show_demo_window);
|
||||
|
||||
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window.
|
||||
{
|
||||
static float f = 0.0f;
|
||||
static int counter = 0;
|
||||
|
||||
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
|
||||
|
||||
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
|
||||
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
|
||||
ImGui::Checkbox("Another Window", &show_another_window);
|
||||
|
||||
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
|
||||
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
|
||||
|
||||
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
|
||||
counter++;
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("counter = %d", counter);
|
||||
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// 3. Show another simple window.
|
||||
if (show_another_window)
|
||||
{
|
||||
ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
|
||||
ImGui::Text("Hello from another window!");
|
||||
if (ImGui::Button("Close Me"))
|
||||
show_another_window = false;
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// Rendering
|
||||
ImGui::Render();
|
||||
ImDrawData* draw_data = ImGui::GetDrawData();
|
||||
const bool is_minimized = (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f);
|
||||
if (!is_minimized)
|
||||
{
|
||||
wd->ClearValue.color.float32[0] = clear_color.x * clear_color.w;
|
||||
wd->ClearValue.color.float32[1] = clear_color.y * clear_color.w;
|
||||
wd->ClearValue.color.float32[2] = clear_color.z * clear_color.w;
|
||||
wd->ClearValue.color.float32[3] = clear_color.w;
|
||||
FrameRender(wd, draw_data);
|
||||
FramePresent(wd);
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
err = vkDeviceWaitIdle(g_Device);
|
||||
check_vk_result(err);
|
||||
ImGui_ImplVulkan_Shutdown();
|
||||
ImGui_ImplQNX_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
|
||||
CleanupVulkanWindow(&g_MainWindowData);
|
||||
CleanupVulkan();
|
||||
|
||||
DestroyQNXWindow(&window);
|
||||
|
||||
return 0;
|
||||
}
|
||||
8
examples/example_qnx_vulkan/nto/Makefile
Normal file
8
examples/example_qnx_vulkan/nto/Makefile
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
LIST=CPU
|
||||
ifndef QRECURSE
|
||||
QRECURSE=recurse.mk
|
||||
ifdef QCONFIG
|
||||
QRDIR=$(dir $(QCONFIG))
|
||||
endif
|
||||
endif
|
||||
include $(QRDIR)$(QRECURSE)
|
||||
8
examples/example_qnx_vulkan/nto/aarch64/Makefile
Normal file
8
examples/example_qnx_vulkan/nto/aarch64/Makefile
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
LIST=VARIANT
|
||||
ifndef QRECURSE
|
||||
QRECURSE=recurse.mk
|
||||
ifdef QCONFIG
|
||||
QRDIR=$(dir $(QCONFIG))
|
||||
endif
|
||||
endif
|
||||
include $(QRDIR)$(QRECURSE)
|
||||
1
examples/example_qnx_vulkan/nto/aarch64/o.le/Makefile
Normal file
1
examples/example_qnx_vulkan/nto/aarch64/o.le/Makefile
Normal file
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
||||
8
examples/example_qnx_vulkan/nto/x86_64/Makefile
Normal file
8
examples/example_qnx_vulkan/nto/x86_64/Makefile
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
LIST=VARIANT
|
||||
ifndef QRECURSE
|
||||
QRECURSE=recurse.mk
|
||||
ifdef QCONFIG
|
||||
QRDIR=$(dir $(QCONFIG))
|
||||
endif
|
||||
endif
|
||||
include $(QRDIR)$(QRECURSE)
|
||||
1
examples/example_qnx_vulkan/nto/x86_64/o/Makefile
Normal file
1
examples/example_qnx_vulkan/nto/x86_64/o/Makefile
Normal file
|
|
@ -0,0 +1 @@
|
|||
include ../../../common.mk
|
||||
|
|
@ -93,6 +93,7 @@
|
|||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<SupportJustMyCode>false</SupportJustMyCode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
|
|
@ -108,6 +109,7 @@
|
|||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<SupportJustMyCode>false</SupportJustMyCode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
|
|
|
|||
|
|
@ -10,25 +10,76 @@
|
|||
#include "imgui.h"
|
||||
#include "imgui_impl_sdl2.h"
|
||||
#include "imgui_impl_metal.h"
|
||||
#include <stdio.h>
|
||||
#include <stdio.h> // printf, fprintf
|
||||
#include <SDL.h>
|
||||
|
||||
#import <Metal/Metal.h>
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
|
||||
// Main code
|
||||
int main(int, char**)
|
||||
{
|
||||
// Setup SDL
|
||||
// (Some versions of SDL before <2.0.10 appears to have performance/stalling issues on a minority of Windows systems,
|
||||
// depending on whether SDL_INIT_GAMECONTROLLER is enabled or disabled.. updating to latest version of SDL is recommended!)
|
||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
|
||||
{
|
||||
printf("Error: SDL_Init(): %s\n", SDL_GetError());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// From 2.0.18: Enable native IME.
|
||||
#ifdef SDL_HINT_IME_SHOW_UI
|
||||
SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");
|
||||
#endif
|
||||
|
||||
// Create SDL window graphics context
|
||||
float main_scale = ImGui_ImplSDL2_GetContentScaleForDisplay(0);
|
||||
int window_flags = SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI;
|
||||
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+Metal example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, (int)(1280 * main_scale), (int)(800 * main_scale), window_flags);
|
||||
if (window == nullptr)
|
||||
{
|
||||
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Create Metal device _before_ creating the view/layer
|
||||
id<MTLDevice> metalDevice = MTLCreateSystemDefaultDevice();
|
||||
if (!metalDevice)
|
||||
{
|
||||
printf("Error: failed to create Metal device.\n");
|
||||
SDL_DestroyWindow(window);
|
||||
SDL_Quit();
|
||||
return 1;
|
||||
}
|
||||
SDL_MetalView view = SDL_Metal_CreateView(window);
|
||||
CAMetalLayer* layer = (__bridge CAMetalLayer*)SDL_Metal_GetLayer(view);
|
||||
layer.device = metalDevice;
|
||||
layer.pixelFormat = MTLPixelFormatBGRA8Unorm;
|
||||
|
||||
id<MTLCommandQueue> commandQueue = [layer.device newCommandQueue];
|
||||
MTLRenderPassDescriptor* renderPassDescriptor = [MTLRenderPassDescriptor new];
|
||||
|
||||
// Setup Dear ImGui context
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
|
||||
|
||||
// Setup style
|
||||
// Setup Dear ImGui style
|
||||
ImGui::StyleColorsDark();
|
||||
//ImGui::StyleColorsLight();
|
||||
|
||||
// Setup scaling
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
|
||||
style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor)
|
||||
|
||||
// Setup Platform/Renderer backends
|
||||
ImGui_ImplMetal_Init(layer.device);
|
||||
ImGui_ImplSDL2_InitForMetal(window);
|
||||
|
||||
// Load Fonts
|
||||
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
|
||||
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
|
||||
|
|
@ -47,48 +98,10 @@ int main(int, char**)
|
|||
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf");
|
||||
//IM_ASSERT(font != nullptr);
|
||||
|
||||
// Setup SDL
|
||||
// (Some versions of SDL before <2.0.10 appears to have performance/stalling issues on a minority of Windows systems,
|
||||
// depending on whether SDL_INIT_GAMECONTROLLER is enabled or disabled.. updating to latest version of SDL is recommended!)
|
||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
|
||||
{
|
||||
printf("Error: %s\n", SDL_GetError());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Inform SDL that we will be using metal for rendering. Without this hint initialization of metal renderer may fail.
|
||||
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "metal");
|
||||
|
||||
// Enable native IME.
|
||||
SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");
|
||||
|
||||
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL+Metal example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 800, SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
|
||||
if (window == nullptr)
|
||||
{
|
||||
printf("Error creating window: %s\n", SDL_GetError());
|
||||
return -2;
|
||||
}
|
||||
|
||||
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
|
||||
if (renderer == nullptr)
|
||||
{
|
||||
printf("Error creating renderer: %s\n", SDL_GetError());
|
||||
return -3;
|
||||
}
|
||||
|
||||
// Setup Platform/Renderer backends
|
||||
CAMetalLayer* layer = (__bridge CAMetalLayer*)SDL_RenderGetMetalLayer(renderer);
|
||||
layer.pixelFormat = MTLPixelFormatBGRA8Unorm;
|
||||
ImGui_ImplMetal_Init(layer.device);
|
||||
ImGui_ImplSDL2_InitForMetal(window);
|
||||
|
||||
id<MTLCommandQueue> commandQueue = [layer.device newCommandQueue];
|
||||
MTLRenderPassDescriptor* renderPassDescriptor = [MTLRenderPassDescriptor new];
|
||||
|
||||
// Our state
|
||||
bool show_demo_window = true;
|
||||
bool show_another_window = false;
|
||||
float clear_color[4] = {0.45f, 0.55f, 0.60f, 1.00f};
|
||||
float clear_color[4] = { 0.45f, 0.55f, 0.60f, 1.00f };
|
||||
|
||||
// Main loop
|
||||
bool done = false;
|
||||
|
|
@ -112,7 +125,8 @@ int main(int, char**)
|
|||
}
|
||||
|
||||
int width, height;
|
||||
SDL_GetRendererOutputSize(renderer, &width, &height);
|
||||
SDL_GetWindowSizeInPixels(window, &width, &height);
|
||||
|
||||
layer.drawableSize = CGSizeMake(width, height);
|
||||
id<CAMetalDrawable> drawable = [layer nextDrawable];
|
||||
|
||||
|
|
@ -168,7 +182,8 @@ int main(int, char**)
|
|||
|
||||
// Rendering
|
||||
ImGui::Render();
|
||||
ImGui_ImplMetal_RenderDrawData(ImGui::GetDrawData(), commandBuffer, renderEncoder);
|
||||
ImDrawData* draw_data = ImGui::GetDrawData();
|
||||
ImGui_ImplMetal_RenderDrawData(draw_data, commandBuffer, renderEncoder);
|
||||
|
||||
[renderEncoder popDebugGroup];
|
||||
[renderEncoder endEncoding];
|
||||
|
|
@ -183,7 +198,6 @@ int main(int, char**)
|
|||
ImGui_ImplSDL2_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
|
||||
SDL_DestroyRenderer(renderer);
|
||||
SDL_DestroyWindow(window);
|
||||
SDL_Quit();
|
||||
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@
|
|||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<SupportJustMyCode>false</SupportJustMyCode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
|
|
@ -107,6 +108,7 @@
|
|||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<SupportJustMyCode>false</SupportJustMyCode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@
|
|||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<SupportJustMyCode>false</SupportJustMyCode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
|
|
@ -107,6 +108,7 @@
|
|||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<SupportJustMyCode>false</SupportJustMyCode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
|
|
|
|||
|
|
@ -39,31 +39,28 @@ int main(int, char**)
|
|||
return 1;
|
||||
}
|
||||
|
||||
// Decide GL+GLSL versions
|
||||
// Select GL version + let the backend select a GLSL version
|
||||
const char* glsl_version = nullptr;
|
||||
#if defined(IMGUI_IMPL_OPENGL_ES2)
|
||||
// GL ES 2.0 + GLSL 100 (WebGL 1.0)
|
||||
const char* glsl_version = "#version 100";
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||
#elif defined(IMGUI_IMPL_OPENGL_ES3)
|
||||
// GL ES 3.0 + GLSL 300 es (WebGL 2.0)
|
||||
const char* glsl_version = "#version 300 es";
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||
#elif defined(__APPLE__)
|
||||
// GL 3.2 Core + GLSL 150
|
||||
const char* glsl_version = "#version 150";
|
||||
// GL 3.2 Core + generally GLSL 150
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); // Always required on Mac
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
|
||||
#else
|
||||
// GL 3.0 + GLSL 130
|
||||
const char* glsl_version = "#version 130";
|
||||
// GL 3.0 + generally GLSL 130
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@
|
|||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<SupportJustMyCode>false</SupportJustMyCode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
|
|
@ -108,6 +109,7 @@
|
|||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<SupportJustMyCode>false</SupportJustMyCode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@
|
|||
<AdditionalIncludeDirectories>..\..;..\..\backends;%VULKAN_SDK%\include;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<SupportJustMyCode>false</SupportJustMyCode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
|
|
@ -109,6 +110,7 @@
|
|||
<AdditionalIncludeDirectories>..\..;..\..\backends;%VULKAN_SDK%\include;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<SupportJustMyCode>false</SupportJustMyCode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
|
|
|
|||
|
|
@ -386,7 +386,7 @@ int main(int, char**)
|
|||
|
||||
// Create Framebuffers
|
||||
int w, h;
|
||||
SDL_GetWindowSize(window, &w, &h);
|
||||
SDL_GetWindowSizeInPixels(window, &w, &h);
|
||||
ImGui_ImplVulkanH_Window* wd = &g_MainWindowData;
|
||||
SetupVulkanWindow(wd, surface, w, h);
|
||||
|
||||
|
|
@ -475,7 +475,7 @@ int main(int, char**)
|
|||
|
||||
// Resize swap chain?
|
||||
int fb_width, fb_height;
|
||||
SDL_GetWindowSize(window, &fb_width, &fb_height);
|
||||
SDL_GetWindowSizeInPixels(window, &fb_width, &fb_height);
|
||||
if (fb_width > 0 && fb_height > 0 && (g_SwapChainRebuild || g_MainWindowData.Width != fb_width || g_MainWindowData.Height != fb_height))
|
||||
{
|
||||
ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount);
|
||||
|
|
|
|||
|
|
@ -1,10 +1,3 @@
|
|||
# Building for desktop with Dawn:
|
||||
# 1. git clone https://github.com/google/dawn dawn
|
||||
# 2. cmake -B build -DIMGUI_DAWN_DIR=dawn
|
||||
# 3. cmake --build build
|
||||
# The resulting binary will be found at one of the following locations:
|
||||
# * build/example_sdl2_wgpu[.exe] or build/Debug/example_sdl2_wgpu[.exe]
|
||||
|
||||
# Building for desktop with WGPU-Native:
|
||||
# 1. download WGPU-Native autogenerated binary modules for your platform/compiler from: https://github.com/gfx-rs/wgpu-native/releases
|
||||
# 2. unzip the downloaded file in your_preferred_folder
|
||||
|
|
@ -13,8 +6,15 @@
|
|||
# The resulting binary will be found at one of the following locations:
|
||||
# * build/example_sdl2_wgpu[.exe] or build/Debug/example_sdl2_wgpu[.exe]
|
||||
|
||||
# Building for desktop with WGVK (MUCH EASIER)
|
||||
# 1. git clone https://github.com/manuel5975p/WGVK dawn
|
||||
# Building for desktop with Dawn: (VERY LONG TO BUILD)
|
||||
# 1. git clone https://github.com/google/dawn dawn
|
||||
# 2. cmake -B build -DIMGUI_DAWN_DIR=dawn
|
||||
# 3. cmake --build build
|
||||
# The resulting binary will be found at one of the following locations:
|
||||
# * build/example_sdl2_wgpu[.exe] or build/Debug/example_sdl2_wgpu[.exe]
|
||||
|
||||
# Building for desktop with WGVK:
|
||||
# 1. git clone https://github.com/manuel5975p/WGVK wgvk
|
||||
# 2. cmake -B build -DIMGUI_WGVK_DIR=wgvk
|
||||
# 3. cmake --build build
|
||||
# The resulting binary will be found at one of the following locations:
|
||||
|
|
@ -29,7 +29,7 @@
|
|||
# 4. emrun build/index.html
|
||||
|
||||
cmake_minimum_required(VERSION 3.22) # Dawn requires CMake >= 3.22
|
||||
project(imgui_example_sdl2_wgpu C CXX)
|
||||
project(example_sdl2_wgpu C CXX)
|
||||
|
||||
set(IMGUI_EXECUTABLE example_sdl2_wgpu)
|
||||
|
||||
|
|
@ -37,7 +37,7 @@ if(NOT CMAKE_BUILD_TYPE)
|
|||
set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE)
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17) # Dawn requires C++17
|
||||
set(CMAKE_CXX_STANDARD 20) # Dawn requires C++20
|
||||
|
||||
# Dear ImGui
|
||||
set(IMGUI_DIR ../../)
|
||||
|
|
@ -162,7 +162,7 @@ else() # Native/Desktop build
|
|||
endif()
|
||||
list(APPEND WGVK_PLATFORM_LIBS m dl pthread)
|
||||
endif()
|
||||
set(LIBRARIES glfw Vulkan::Vulkan ${WGVK_PLATFORM_LIBS})
|
||||
set(LIBRARIES Vulkan::Vulkan ${WGVK_PLATFORM_LIBS})
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -330,29 +330,25 @@ static WGPUDevice RequestDevice(wgpu::Instance& instance, wgpu::Adapter& adapter
|
|||
static void handle_request_adapter(WGPURequestAdapterStatus status, WGPUAdapter adapter, WGPUStringView message, void* userdata1, void* userdata2)
|
||||
{
|
||||
IM_UNUSED(userdata2);
|
||||
if (status == WGPURequestAdapterStatus_Success)
|
||||
{
|
||||
WGPUAdapter* extAdapter = (WGPUAdapter*)userdata1;
|
||||
*extAdapter = adapter;
|
||||
}
|
||||
else
|
||||
if (status != WGPURequestAdapterStatus_Success)
|
||||
{
|
||||
printf("Request_adapter status=%#.8x message=%.*s\n", status, (int)message.length, message.data);
|
||||
return;
|
||||
}
|
||||
WGPUAdapter* extAdapter = (WGPUAdapter*)userdata1;
|
||||
*extAdapter = adapter;
|
||||
}
|
||||
|
||||
static void handle_request_device(WGPURequestDeviceStatus status, WGPUDevice device, WGPUStringView message, void* userdata1, void* userdata2)
|
||||
{
|
||||
IM_UNUSED(userdata2);
|
||||
if (status == WGPURequestDeviceStatus_Success)
|
||||
{
|
||||
WGPUDevice* extDevice = (WGPUDevice*)userdata1;
|
||||
*extDevice = device;
|
||||
}
|
||||
else
|
||||
if (status != WGPURequestDeviceStatus_Success)
|
||||
{
|
||||
printf("Request_device status=%#.8x message=%.*s\n", status, (int)message.length, message.data);
|
||||
return;
|
||||
}
|
||||
WGPUDevice* extDevice = (WGPUDevice*)userdata1;
|
||||
*extDevice = device;
|
||||
}
|
||||
|
||||
static WGPUAdapter RequestAdapter(WGPUInstance& instance)
|
||||
|
|
@ -366,8 +362,10 @@ static WGPUAdapter RequestAdapter(WGPUInstance& instance)
|
|||
adapterCallbackInfo.userdata1 = &local_adapter;
|
||||
|
||||
WGPUFuture future = wgpuInstanceRequestAdapter(instance, &adapter_options, adapterCallbackInfo);
|
||||
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||
WGPUFutureWaitInfo waitInfo = { future, false };
|
||||
wgpuInstanceWaitAny(instance, 1, &waitInfo, ~0ull);
|
||||
#endif
|
||||
IM_ASSERT(local_adapter && "Error on Adapter request");
|
||||
return local_adapter;
|
||||
}
|
||||
|
|
@ -379,9 +377,14 @@ static WGPUDevice RequestDevice(WGPUInstance& instance, WGPUAdapter& adapter)
|
|||
deviceCallbackInfo.mode = WGPUCallbackMode_WaitAnyOnly;
|
||||
deviceCallbackInfo.callback = handle_request_device;
|
||||
deviceCallbackInfo.userdata1 = &local_device;
|
||||
|
||||
WGPUFuture future = wgpuAdapterRequestDevice(adapter, nullptr, deviceCallbackInfo);
|
||||
#if !defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||
WGPUFutureWaitInfo waitInfo = { future, false };
|
||||
wgpuInstanceWaitAny(instance, 1, &waitInfo, ~0ull);
|
||||
#else
|
||||
IM_UNUSED(instance);
|
||||
#endif
|
||||
IM_ASSERT(local_device && "Error on Device request");
|
||||
return local_device;
|
||||
}
|
||||
|
|
@ -437,7 +440,7 @@ static bool InitWGPU(SDL_Window* window)
|
|||
|
||||
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
|
||||
wgpuSetLogCallback(
|
||||
[](WGPULogLevel level, WGPUStringView msg, void* userdata) { fprintf(stderr, "%s: %.*s\n", ImGui_ImplWGPU_GetLogLevelName(level), (int)msg.length, msg.data); }, nullptr
|
||||
[](WGPULogLevel level, WGPUStringView msg, void*) { fprintf(stderr, "%s: %.*s\n", ImGui_ImplWGPU_GetLogLevelName(level), (int)msg.length, msg.data); }, nullptr
|
||||
);
|
||||
wgpuSetLogLevel(WGPULogLevel_Warn);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@
|
|||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<SupportJustMyCode>false</SupportJustMyCode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
|
|
@ -108,6 +109,7 @@
|
|||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<SupportJustMyCode>false</SupportJustMyCode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
|
|
|
|||
48
examples/example_sdl3_metal4/Makefile
Normal file
48
examples/example_sdl3_metal4/Makefile
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
#
|
||||
# You will need SDL3 (http://www.libsdl.org):
|
||||
# brew install sdl3
|
||||
#
|
||||
|
||||
#CXX = g++
|
||||
#CXX = clang++
|
||||
|
||||
EXE = example_sdl3_metal4
|
||||
IMGUI_DIR = ../..
|
||||
SOURCES = main.mm
|
||||
SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
|
||||
SOURCES += $(IMGUI_DIR)/backends/imgui_impl_sdl3.cpp $(IMGUI_DIR)/backends/imgui_impl_metal4.mm
|
||||
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
|
||||
|
||||
LIBS = -framework Metal -framework MetalKit -framework Cocoa -framework IOKit -framework CoreVideo -framework QuartzCore
|
||||
LIBS += `pkg-config --libs sdl3`
|
||||
LIBS += -L/usr/local/lib -L/opt/local/lib
|
||||
|
||||
CXXFLAGS += `pkg-config --cflags sdl3`
|
||||
CXXFLAGS += -I/usr/local/include -I/opt/local/include
|
||||
CXXFLAGS += -std=c++11 -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
|
||||
CXXFLAGS += -Wall -Wformat
|
||||
CFLAGS = $(CXXFLAGS)
|
||||
|
||||
%.o:%.cpp
|
||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
%.o:$(IMGUI_DIR)/%.cpp
|
||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
%.o:$(IMGUI_DIR)/backends/%.cpp
|
||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
%.o:%.mm
|
||||
$(CXX) $(CXXFLAGS) -ObjC++ -fobjc-weak -fobjc-arc -c -o $@ $<
|
||||
|
||||
%.o:$(IMGUI_DIR)/backends/%.mm
|
||||
$(CXX) $(CXXFLAGS) -ObjC++ -fobjc-weak -fobjc-arc -c -o $@ $<
|
||||
|
||||
all: $(EXE)
|
||||
@echo Build complete
|
||||
|
||||
$(EXE): $(OBJS)
|
||||
$(CXX) -o $@ $^ $(CXXFLAGS) $(LIBS)
|
||||
|
||||
clean:
|
||||
rm -f $(EXE) $(OBJS)
|
||||
240
examples/example_sdl3_metal4/main.mm
Normal file
240
examples/example_sdl3_metal4/main.mm
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
// Dear ImGui: standalone example application for SDL3 + Metal 4
|
||||
// (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan/Metal graphics context creation, etc.)
|
||||
// (Metal 4 requires Apple Silicon and macOS 26+.)
|
||||
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - 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
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_sdl3.h"
|
||||
#include "imgui_impl_metal4.h"
|
||||
#include <stdio.h> // printf, fprintf
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#import <Metal/Metal.h>
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
|
||||
#define FRAMES_IN_FLIGHT 3
|
||||
|
||||
// Main code
|
||||
int main(int, char**)
|
||||
{
|
||||
// Setup SDL
|
||||
// [If using SDL_MAIN_USE_CALLBACKS: all code below until the main loop starts would likely be your SDL_AppInit() function]
|
||||
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD))
|
||||
{
|
||||
printf("Error: SDL_Init(): %s\n", SDL_GetError());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Create SDL window graphics context
|
||||
float main_scale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay());
|
||||
SDL_WindowFlags window_flags = SDL_WINDOW_METAL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN | SDL_WINDOW_HIGH_PIXEL_DENSITY;
|
||||
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL3+Metal4 example", (int)(1280 * main_scale), (int)(800 * main_scale), window_flags);
|
||||
if (window == nullptr)
|
||||
{
|
||||
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
|
||||
return 1;
|
||||
}
|
||||
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
|
||||
SDL_ShowWindow(window);
|
||||
|
||||
// Create Metal device _before_ creating the view/layer
|
||||
id<MTLDevice> metalDevice = MTLCreateSystemDefaultDevice();
|
||||
if (!metalDevice)
|
||||
{
|
||||
printf("Error: failed to create Metal device.\n");
|
||||
SDL_DestroyWindow(window);
|
||||
SDL_Quit();
|
||||
return 1;
|
||||
}
|
||||
SDL_MetalView view = SDL_Metal_CreateView(window);
|
||||
CAMetalLayer* layer = (__bridge CAMetalLayer*)SDL_Metal_GetLayer(view);
|
||||
layer.device = metalDevice;
|
||||
layer.pixelFormat = MTLPixelFormatBGRA8Unorm;
|
||||
|
||||
id<MTL4CommandQueue> commandQueue = [layer.device newMTL4CommandQueue];
|
||||
id<MTLSharedEvent> sharedEvent = [layer.device newSharedEvent];
|
||||
MTL4RenderPassDescriptor* renderPassDescriptor = [MTL4RenderPassDescriptor new];
|
||||
|
||||
[commandQueue addResidencySet:layer.residencySet];
|
||||
|
||||
id<MTL4CommandBuffer> commandBuffers[FRAMES_IN_FLIGHT];
|
||||
id<MTL4CommandAllocator> commandAllocators[FRAMES_IN_FLIGHT];
|
||||
for (int i = 0; i < FRAMES_IN_FLIGHT; i++)
|
||||
{
|
||||
commandAllocators[i] = [layer.device newCommandAllocator];
|
||||
commandBuffers[i] = [layer.device newCommandBuffer];
|
||||
}
|
||||
uint32_t frameIndex = 0;
|
||||
uint32_t frameInFlight = 0;
|
||||
|
||||
// Setup Dear ImGui context
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
|
||||
|
||||
// Setup Dear ImGui style
|
||||
ImGui::StyleColorsDark();
|
||||
//ImGui::StyleColorsLight();
|
||||
|
||||
// Setup scaling
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
|
||||
style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor)
|
||||
|
||||
// Setup Platform/Renderer backends
|
||||
ImGui_ImplMetal4_Init(layer.device, commandQueue, FRAMES_IN_FLIGHT);
|
||||
ImGui_ImplSDL3_InitForMetal(window);
|
||||
|
||||
// Load Fonts
|
||||
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
|
||||
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
|
||||
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
|
||||
// - Read 'docs/FONTS.md' for more instructions and details.
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
//style.FontSizeBase = 20.0f;
|
||||
//io.Fonts->AddFontDefaultVector();
|
||||
//io.Fonts->AddFontDefaultBitmap();
|
||||
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf");
|
||||
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf");
|
||||
//IM_ASSERT(font != nullptr);
|
||||
|
||||
// Our state
|
||||
bool show_demo_window = true;
|
||||
bool show_another_window = false;
|
||||
float clear_color[4] = { 0.45f, 0.55f, 0.60f, 1.00f };
|
||||
|
||||
// Main loop
|
||||
bool done = false;
|
||||
while (!done)
|
||||
{
|
||||
@autoreleasepool
|
||||
{
|
||||
// Poll and handle events (inputs, window resize, etc.)
|
||||
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
|
||||
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
|
||||
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
||||
// [If using SDL_MAIN_USE_CALLBACKS: call ImGui_ImplSDL3_ProcessEvent() from your SDL_AppEvent() function]
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event))
|
||||
{
|
||||
ImGui_ImplSDL3_ProcessEvent(&event);
|
||||
if (event.type == SDL_EVENT_QUIT)
|
||||
done = true;
|
||||
if (event.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED && event.window.windowID == SDL_GetWindowID(window))
|
||||
done = true;
|
||||
}
|
||||
|
||||
// [If using SDL_MAIN_USE_CALLBACKS: all code below would likely be your SDL_AppIterate() function]
|
||||
if (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED)
|
||||
{
|
||||
SDL_Delay(10);
|
||||
continue;
|
||||
}
|
||||
|
||||
int width, height;
|
||||
SDL_GetWindowSizeInPixels(window, &width, &height);
|
||||
|
||||
layer.drawableSize = CGSizeMake(width, height);
|
||||
id<CAMetalDrawable> drawable = [layer nextDrawable];
|
||||
|
||||
uint64_t waitValue = (frameIndex >= FRAMES_IN_FLIGHT) ? (frameIndex - FRAMES_IN_FLIGHT + 1) : 0;
|
||||
[sharedEvent waitUntilSignaledValue:waitValue timeoutMS:1000];
|
||||
[commandAllocators[frameInFlight] reset];
|
||||
[commandBuffers[frameInFlight] beginCommandBufferWithAllocator:commandAllocators[frameInFlight]];
|
||||
|
||||
renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(clear_color[0] * clear_color[3], clear_color[1] * clear_color[3], clear_color[2] * clear_color[3], clear_color[3]);
|
||||
renderPassDescriptor.colorAttachments[0].texture = drawable.texture;
|
||||
renderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear;
|
||||
renderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore;
|
||||
id <MTL4RenderCommandEncoder> renderEncoder = [commandBuffers[frameInFlight] renderCommandEncoderWithDescriptor:renderPassDescriptor];
|
||||
[renderEncoder pushDebugGroup:@"ImGui demo"];
|
||||
|
||||
// Start the Dear ImGui frame
|
||||
ImGui_ImplMetal4_NewFrame(renderPassDescriptor, frameInFlight);
|
||||
ImGui_ImplSDL3_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
// 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
|
||||
if (show_demo_window)
|
||||
ImGui::ShowDemoWindow(&show_demo_window);
|
||||
|
||||
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window.
|
||||
{
|
||||
static float f = 0.0f;
|
||||
static int counter = 0;
|
||||
|
||||
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
|
||||
|
||||
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
|
||||
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
|
||||
ImGui::Checkbox("Another Window", &show_another_window);
|
||||
|
||||
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
|
||||
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
|
||||
|
||||
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
|
||||
counter++;
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("counter = %d", counter);
|
||||
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// 3. Show another simple window.
|
||||
if (show_another_window)
|
||||
{
|
||||
ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
|
||||
ImGui::Text("Hello from another window!");
|
||||
if (ImGui::Button("Close Me"))
|
||||
show_another_window = false;
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// Rendering
|
||||
ImGui::Render();
|
||||
ImDrawData* draw_data = ImGui::GetDrawData();
|
||||
ImGui_ImplMetal4_RenderDrawData(draw_data, commandBuffers[frameInFlight], renderEncoder);
|
||||
|
||||
[renderEncoder popDebugGroup];
|
||||
[renderEncoder endEncoding];
|
||||
[commandBuffers[frameInFlight] endCommandBuffer];
|
||||
|
||||
id<MTL4CommandBuffer> to_commit[] = { commandBuffers[frameInFlight] };
|
||||
|
||||
[commandQueue waitForDrawable:drawable];
|
||||
[commandQueue commit:to_commit count:1];
|
||||
|
||||
[commandQueue signalEvent:sharedEvent value:frameIndex + 1];
|
||||
[commandQueue signalDrawable:drawable];
|
||||
[drawable present];
|
||||
|
||||
frameIndex++;
|
||||
frameInFlight = (frameInFlight + 1) % FRAMES_IN_FLIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
// [If using SDL_MAIN_USE_CALLBACKS: all code below would likely be your SDL_AppQuit() function]
|
||||
ImGui_ImplMetal4_Shutdown();
|
||||
ImGui_ImplSDL3_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
|
||||
SDL_DestroyWindow(window);
|
||||
SDL_Quit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -92,6 +92,7 @@
|
|||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL3;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<SupportJustMyCode>false</SupportJustMyCode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
|
|
@ -107,6 +108,7 @@
|
|||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL3;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<SupportJustMyCode>false</SupportJustMyCode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
|
|
|
|||
|
|
@ -33,31 +33,28 @@ int main(int, char**)
|
|||
return 1;
|
||||
}
|
||||
|
||||
// Decide GL+GLSL versions
|
||||
// Select GL version + let the backend select a GLSL version
|
||||
const char* glsl_version = nullptr;
|
||||
#if defined(IMGUI_IMPL_OPENGL_ES2)
|
||||
// GL ES 2.0 + GLSL 100 (WebGL 1.0)
|
||||
const char* glsl_version = "#version 100";
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||
#elif defined(IMGUI_IMPL_OPENGL_ES3)
|
||||
// GL ES 3.0 + GLSL 300 es (WebGL 2.0)
|
||||
const char* glsl_version = "#version 300 es";
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||
#elif defined(__APPLE__)
|
||||
// GL 3.2 Core + GLSL 150
|
||||
const char* glsl_version = "#version 150";
|
||||
// GL 3.2 Core + generally GLSL 150
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); // Always required on Mac
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
|
||||
#else
|
||||
// GL 3.0 + GLSL 130
|
||||
const char* glsl_version = "#version 130";
|
||||
// GL 3.0 + generally GLSL 130
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue