mirror of
				https://github.com/Drezil/imgui.git
				synced 2025-10-31 05:01:05 +01:00 
			
		
		
		
	Merge branch 'master' into docking
# Conflicts: # imgui.cpp # imgui_widgets.cpp
This commit is contained in:
		
							
								
								
									
										12
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							| @@ -458,10 +458,20 @@ jobs: | ||||
|         popd | ||||
|         make -C examples/example_emscripten_wgpu | ||||
|  | ||||
|   Android: | ||||
|     runs-on: ubuntu-18.04 | ||||
|     steps: | ||||
|     - uses: actions/checkout@v2 | ||||
|  | ||||
|     - name: Build example_android_opengl3 | ||||
|       run: | | ||||
|         cd examples/example_android_opengl3/android | ||||
|         gradle assembleDebug | ||||
|  | ||||
|   Discord-CI: | ||||
|     runs-on: ubuntu-18.04 | ||||
|     if: always() | ||||
|     needs: [Windows, Linux, MacOS, iOS, Emscripten] | ||||
|     needs: [Windows, Linux, MacOS, iOS, Emscripten, Android] | ||||
|     steps: | ||||
|     - uses: dearimgui/github_discord_notifier@latest | ||||
|       with: | ||||
|   | ||||
							
								
								
									
										187
									
								
								backends/imgui_impl_android.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								backends/imgui_impl_android.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,187 @@ | ||||
| // dear imgui: Platform Binding for Android native app | ||||
| // This needs to be used along with the OpenGL 3 Renderer (imgui_impl_opengl3) | ||||
|  | ||||
| // Implemented features: | ||||
| //  [X] Platform: Keyboard arrays indexed using AKEYCODE_* codes, e.g. ImGui::IsKeyPressed(AKEYCODE_SPACE). | ||||
| // Missing features: | ||||
| //  [ ] Platform: Clipboard support. | ||||
| //  [ ] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. | ||||
| //  [ ] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. FIXME: Check if this is even possible with Android. | ||||
| // Important: | ||||
| //  - FIXME: On-screen keyboard currently needs to be enabled by the application (see examples/ and issue #3446) | ||||
| //  - FIXME: Unicode character inputs needs to be passed by Dear ImGui by the application (see examples/ and issue #3446) | ||||
|  | ||||
| // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. | ||||
| // If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp. | ||||
| // https://github.com/ocornut/imgui | ||||
|  | ||||
| // CHANGELOG | ||||
| // (minor and older changes stripped away, please see git history for details) | ||||
| //  2021-03-04: Initial version. | ||||
|  | ||||
| #include "imgui.h" | ||||
| #include "imgui_impl_android.h" | ||||
| #include <time.h> | ||||
| #include <map> | ||||
| #include <queue> | ||||
| #include <android/native_window.h> | ||||
| #include <android/input.h> | ||||
| #include <android/keycodes.h> | ||||
| #include <android/log.h> | ||||
|  | ||||
| // Android data | ||||
| static double                                   g_Time = 0.0; | ||||
| static ANativeWindow*                           g_Window; | ||||
| static char                                     g_LogTag[] = "ImGuiExample"; | ||||
| static std::map<int32_t, std::queue<int32_t>>   g_KeyEventQueues; // FIXME: Remove dependency on map and queue once we use upcoming input queue. | ||||
|  | ||||
| int32_t ImGui_ImplAndroid_HandleInputEvent(AInputEvent* input_event) | ||||
| { | ||||
|     ImGuiIO& io = ImGui::GetIO(); | ||||
|     int32_t event_type = AInputEvent_getType(input_event); | ||||
|     switch (event_type) | ||||
|     { | ||||
|     case AINPUT_EVENT_TYPE_KEY: | ||||
|     { | ||||
|         int32_t event_key_code = AKeyEvent_getKeyCode(input_event); | ||||
|         int32_t event_action = AKeyEvent_getAction(input_event); | ||||
|         int32_t event_meta_state = AKeyEvent_getMetaState(input_event); | ||||
|  | ||||
|         io.KeyCtrl = ((event_meta_state & AMETA_CTRL_ON) != 0); | ||||
|         io.KeyShift = ((event_meta_state & AMETA_SHIFT_ON) != 0); | ||||
|         io.KeyAlt = ((event_meta_state & AMETA_ALT_ON) != 0); | ||||
|  | ||||
|         switch (event_action) | ||||
|         { | ||||
|         // FIXME: AKEY_EVENT_ACTION_DOWN and AKEY_EVENT_ACTION_UP occur at once as soon as a touch pointer | ||||
|         // goes up from a key. We use a simple key event queue/ and process one event per key per frame in | ||||
|         // ImGui_ImplAndroid_NewFrame()...or consider using IO queue, if suitable: https://github.com/ocornut/imgui/issues/2787 | ||||
|         case AKEY_EVENT_ACTION_DOWN: | ||||
|         case AKEY_EVENT_ACTION_UP: | ||||
|             g_KeyEventQueues[event_key_code].push(event_action); | ||||
|             break; | ||||
|         default: | ||||
|             break; | ||||
|         } | ||||
|         break; | ||||
|     } | ||||
|     case AINPUT_EVENT_TYPE_MOTION: | ||||
|     { | ||||
|         int32_t event_action = AMotionEvent_getAction(input_event); | ||||
|         int32_t event_pointer_index = (event_action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; | ||||
|         event_action &= AMOTION_EVENT_ACTION_MASK; | ||||
|         switch (event_action) | ||||
|         { | ||||
|         case AMOTION_EVENT_ACTION_DOWN: | ||||
|         case AMOTION_EVENT_ACTION_UP: | ||||
|             // Physical mouse buttons (and probably other physical devices) also invoke the actions AMOTION_EVENT_ACTION_DOWN/_UP, | ||||
|             // but we have to process them separately to identify the actual button pressed. This is done below via | ||||
|             // AMOTION_EVENT_ACTION_BUTTON_PRESS/_RELEASE. Here, we only process "FINGER" input (and "UNKNOWN", as a fallback). | ||||
|             if((AMotionEvent_getToolType(input_event, event_pointer_index) == AMOTION_EVENT_TOOL_TYPE_FINGER) | ||||
|             || (AMotionEvent_getToolType(input_event, event_pointer_index) == AMOTION_EVENT_TOOL_TYPE_UNKNOWN)) | ||||
|             { | ||||
|                 io.MouseDown[0] = (event_action == AMOTION_EVENT_ACTION_DOWN) ? true : false; | ||||
|                 io.MousePos = ImVec2(AMotionEvent_getX(input_event, event_pointer_index), AMotionEvent_getY(input_event, event_pointer_index)); | ||||
|             } | ||||
|             break; | ||||
|         case AMOTION_EVENT_ACTION_BUTTON_PRESS: | ||||
|         case AMOTION_EVENT_ACTION_BUTTON_RELEASE: | ||||
|             { | ||||
|                 int32_t button_state = AMotionEvent_getButtonState(input_event); | ||||
|                 io.MouseDown[0] = (button_state & AMOTION_EVENT_BUTTON_PRIMARY) ? true : false; | ||||
|                 io.MouseDown[1] = (button_state & AMOTION_EVENT_BUTTON_SECONDARY) ? true : false; | ||||
|                 io.MouseDown[2] = (button_state & AMOTION_EVENT_BUTTON_TERTIARY) ? true : false; | ||||
|             } | ||||
|             break; | ||||
|         case AMOTION_EVENT_ACTION_HOVER_MOVE: // Hovering: Tool moves while NOT pressed (such as a physical mouse) | ||||
|         case AMOTION_EVENT_ACTION_MOVE:       // Touch pointer moves while DOWN | ||||
|             io.MousePos = ImVec2(AMotionEvent_getX(input_event, event_pointer_index), AMotionEvent_getY(input_event, event_pointer_index)); | ||||
|             break; | ||||
|         case AMOTION_EVENT_ACTION_SCROLL: | ||||
|             io.MouseWheel = AMotionEvent_getAxisValue(input_event, AMOTION_EVENT_AXIS_VSCROLL, event_pointer_index); | ||||
|             io.MouseWheelH = AMotionEvent_getAxisValue(input_event, AMOTION_EVENT_AXIS_HSCROLL, event_pointer_index); | ||||
|             break; | ||||
|         default: | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|         return 1; | ||||
|     default: | ||||
|         break; | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| bool ImGui_ImplAndroid_Init(ANativeWindow* window) | ||||
| { | ||||
|     g_Window = window; | ||||
|     g_Time = 0.0; | ||||
|  | ||||
|     // Setup backend capabilities flags | ||||
|     ImGuiIO& io = ImGui::GetIO(); | ||||
|     io.BackendPlatformName = "imgui_impl_android"; | ||||
|  | ||||
|     // Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array. | ||||
|     io.KeyMap[ImGuiKey_Tab] = AKEYCODE_TAB; | ||||
|     io.KeyMap[ImGuiKey_LeftArrow] = AKEYCODE_DPAD_LEFT;   // also covers physical keyboard arrow key | ||||
|     io.KeyMap[ImGuiKey_RightArrow] = AKEYCODE_DPAD_RIGHT; // also covers physical keyboard arrow key | ||||
|     io.KeyMap[ImGuiKey_UpArrow] = AKEYCODE_DPAD_UP;       // also covers physical keyboard arrow key | ||||
|     io.KeyMap[ImGuiKey_DownArrow] = AKEYCODE_DPAD_DOWN;   // also covers physical keyboard arrow key | ||||
|     io.KeyMap[ImGuiKey_PageUp] = AKEYCODE_PAGE_UP; | ||||
|     io.KeyMap[ImGuiKey_PageDown] = AKEYCODE_PAGE_DOWN; | ||||
|     io.KeyMap[ImGuiKey_Home] = AKEYCODE_MOVE_HOME; | ||||
|     io.KeyMap[ImGuiKey_End] = AKEYCODE_MOVE_END; | ||||
|     io.KeyMap[ImGuiKey_Insert] = AKEYCODE_INSERT; | ||||
|     io.KeyMap[ImGuiKey_Delete] = AKEYCODE_FORWARD_DEL; | ||||
|     io.KeyMap[ImGuiKey_Backspace] = AKEYCODE_DEL; | ||||
|     io.KeyMap[ImGuiKey_Space] = AKEYCODE_SPACE; | ||||
|     io.KeyMap[ImGuiKey_Enter] = AKEYCODE_ENTER; | ||||
|     io.KeyMap[ImGuiKey_Escape] = AKEYCODE_ESCAPE; | ||||
|     io.KeyMap[ImGuiKey_KeyPadEnter] = AKEYCODE_NUMPAD_ENTER; | ||||
|     io.KeyMap[ImGuiKey_A] = AKEYCODE_A; | ||||
|     io.KeyMap[ImGuiKey_C] = AKEYCODE_C; | ||||
|     io.KeyMap[ImGuiKey_V] = AKEYCODE_V; | ||||
|     io.KeyMap[ImGuiKey_X] = AKEYCODE_X; | ||||
|     io.KeyMap[ImGuiKey_Y] = AKEYCODE_Y; | ||||
|     io.KeyMap[ImGuiKey_Z] = AKEYCODE_Z; | ||||
|  | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| void ImGui_ImplAndroid_Shutdown() | ||||
| { | ||||
| } | ||||
|  | ||||
| void ImGui_ImplAndroid_NewFrame() | ||||
| { | ||||
|     ImGuiIO& io = ImGui::GetIO(); | ||||
|     IM_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built! It is generally built by the renderer backend. Missing call to renderer _NewFrame() function? e.g. ImGui_ImplOpenGL3_NewFrame()."); | ||||
|  | ||||
|     // Process queued key events | ||||
|     // FIXME: This is a workaround for multiple key event actions occurring at once (see above) and can be removed once we use upcoming input queue. | ||||
|     for (auto& key_queue : g_KeyEventQueues) | ||||
|     { | ||||
|         if (key_queue.second.empty()) | ||||
|             continue; | ||||
|         io.KeysDown[key_queue.first] = (key_queue.second.front() == AKEY_EVENT_ACTION_DOWN); | ||||
|         key_queue.second.pop(); | ||||
|     } | ||||
|  | ||||
|     // Setup display size (every frame to accommodate for window resizing) | ||||
|     int32_t window_width = ANativeWindow_getWidth(g_Window); | ||||
|     int32_t window_height = ANativeWindow_getHeight(g_Window); | ||||
|     int display_width = window_width; | ||||
|     int display_height = window_height; | ||||
|  | ||||
|     io.DisplaySize = ImVec2((float)window_width, (float)window_height); | ||||
|     if (window_width > 0 && window_height > 0) | ||||
|         io.DisplayFramebufferScale = ImVec2((float)display_width / window_width, (float)display_height / window_height); | ||||
|  | ||||
|     // Setup time step | ||||
|     struct timespec current_timespec; | ||||
|     clock_gettime(CLOCK_MONOTONIC, ¤t_timespec); | ||||
|     double current_time = (double)(current_timespec.tv_sec) + (current_timespec.tv_nsec / 1000000000.0); | ||||
|     io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f / 60.0f); | ||||
|     g_Time = current_time; | ||||
| } | ||||
							
								
								
									
										26
									
								
								backends/imgui_impl_android.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								backends/imgui_impl_android.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| // dear imgui: Platform Binding for Android native app | ||||
| // This needs to be used along with the OpenGL 3 Renderer (imgui_impl_opengl3) | ||||
|  | ||||
| // Implemented features: | ||||
| //  [X] Platform: Keyboard arrays indexed using AKEYCODE_* codes, e.g. ImGui::IsKeyPressed(AKEYCODE_SPACE). | ||||
| // Missing features: | ||||
| //  [ ] Platform: Clipboard support. | ||||
| //  [ ] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. | ||||
| //  [ ] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. FIXME: Check if this is even possible with Android. | ||||
| // Important: | ||||
| //  - FIXME: On-screen keyboard currently needs to be enabled by the application (see examples/ and issue #3446) | ||||
| //  - FIXME: Unicode character inputs needs to be passed by Dear ImGui by the application (see examples/ and issue #3446) | ||||
|  | ||||
| // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. | ||||
| // If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp. | ||||
| // https://github.com/ocornut/imgui | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| struct ANativeWindow; | ||||
| struct AInputEvent; | ||||
|  | ||||
| IMGUI_IMPL_API bool     ImGui_ImplAndroid_Init(ANativeWindow* window); | ||||
| IMGUI_IMPL_API int32_t  ImGui_ImplAndroid_HandleInputEvent(AInputEvent* input_event); | ||||
| IMGUI_IMPL_API void     ImGui_ImplAndroid_Shutdown(); | ||||
| IMGUI_IMPL_API void     ImGui_ImplAndroid_NewFrame(); | ||||
| @@ -269,11 +269,15 @@ static bool ImGui_ImplDX9_CreateFontsTexture() | ||||
|     int width, height, bytes_per_pixel; | ||||
|     io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height, &bytes_per_pixel); | ||||
|  | ||||
|     // Convert RGBA32 to BGRA32 as the earlier is not well supported by DX9 devices | ||||
|     // Convert RGBA32 to BGRA32 (because RGBA32 is not well supported by DX9 devices) | ||||
| #ifndef IMGUI_USE_BGRA_PACKED_COLOR | ||||
|     if (io.Fonts->TexPixelsUseColors) | ||||
|         for (ImU32* p = (ImU32*)pixels, *p_end = p + width * height; p < p_end; p++) | ||||
|             *p = IMGUI_COL_TO_DX9_ARGB(*p); | ||||
|     { | ||||
|         ImU32* dst_start = (ImU32*)ImGui::MemAlloc(width * height * bytes_per_pixel); | ||||
|         for (ImU32* src = (ImU32*)pixels, *dst = dst_start, *dst_end = dst_start + width * height; dst < dst_end; src++, dst++) | ||||
|             *dst = IMGUI_COL_TO_DX9_ARGB(*src); | ||||
|         pixels = (unsigned char*)dst_start; | ||||
|     } | ||||
| #endif | ||||
|  | ||||
|     // Upload texture to graphics system | ||||
| @@ -290,6 +294,11 @@ static bool ImGui_ImplDX9_CreateFontsTexture() | ||||
|     // Store our identifier | ||||
|     io.Fonts->SetTexID((ImTextureID)g_FontTexture); | ||||
|  | ||||
| #ifndef IMGUI_USE_BGRA_PACKED_COLOR | ||||
|     if (io.Fonts->TexPixelsUseColors) | ||||
|         ImGui::MemFree(pixels); | ||||
| #endif | ||||
|  | ||||
|     return true; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -179,7 +179,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw | ||||
| #endif | ||||
|     io.BackendPlatformName = "imgui_impl_glfw"; | ||||
|  | ||||
|     // Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array. | ||||
|     // Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array. | ||||
|     io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; | ||||
|     io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT; | ||||
|     io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT; | ||||
|   | ||||
| @@ -220,7 +220,8 @@ bool    ImGui_Marmalade_Init(bool install_callbacks) | ||||
|     ImGuiIO& io = ImGui::GetIO(); | ||||
|     io.BackendPlatformName = io.BackendRendererName = "imgui_impl_marmalade"; | ||||
|  | ||||
|     io.KeyMap[ImGuiKey_Tab] = s3eKeyTab;                     // Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array. | ||||
|     // Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array. | ||||
|     io.KeyMap[ImGuiKey_Tab] = s3eKeyTab | ||||
|     io.KeyMap[ImGuiKey_LeftArrow] = s3eKeyLeft; | ||||
|     io.KeyMap[ImGuiKey_RightArrow] = s3eKeyRight; | ||||
|     io.KeyMap[ImGuiKey_UpArrow] = s3eKeyUp; | ||||
|   | ||||
| @@ -173,7 +173,7 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, void* sdl_gl_context) | ||||
| #endif | ||||
|     io.BackendPlatformName = "imgui_impl_sdl"; | ||||
|  | ||||
|     // Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array. | ||||
|     // Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array. | ||||
|     io.KeyMap[ImGuiKey_Tab] = SDL_SCANCODE_TAB; | ||||
|     io.KeyMap[ImGuiKey_LeftArrow] = SDL_SCANCODE_LEFT; | ||||
|     io.KeyMap[ImGuiKey_RightArrow] = SDL_SCANCODE_RIGHT; | ||||
|   | ||||
| @@ -731,7 +731,7 @@ void ImGui_ImplWGPU_InvalidateDeviceObjects() | ||||
|  | ||||
| bool ImGui_ImplWGPU_Init(WGPUDevice device, int num_frames_in_flight, WGPUTextureFormat rt_format) | ||||
| { | ||||
|     // Setup back-end capabilities flags | ||||
|     // Setup backend capabilities flags | ||||
|     ImGuiIO& io = ImGui::GetIO(); | ||||
|     io.BackendRendererName = "imgui_impl_webgpu"; | ||||
|     io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset;  // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. | ||||
|   | ||||
| @@ -106,7 +106,7 @@ bool    ImGui_ImplWin32_Init(void* hwnd) | ||||
|     if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) | ||||
|         ImGui_ImplWin32_InitPlatformInterface(); | ||||
|  | ||||
|     // Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array that we will update during the application lifetime. | ||||
|     // Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array that we will update during the application lifetime. | ||||
|     io.KeyMap[ImGuiKey_Tab] = VK_TAB; | ||||
|     io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT; | ||||
|     io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT; | ||||
|   | ||||
| @@ -57,6 +57,7 @@ In the [backends/](https://github.com/ocornut/imgui/blob/master/backends) folder | ||||
|  | ||||
| List of Platforms 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_sdl.cpp        ; SDL2 (Windows, macOS, Linux, iOS, Android) https://www.libsdl.org | ||||
|   | ||||
| @@ -119,12 +119,19 @@ Other Changes: | ||||
| - Window: Shrink close button hit-testing region when it covers an abnormally high portion of the window visible | ||||
|   area (e.g. when window is collapsed + moved in a corner) to facilitate moving the window away. (#3825) | ||||
| - Window, Nav: Fixed crash when calling SetWindowFocus(NULL) as the time a new window appears. (#3865) [@nem0] | ||||
| - Tables: Fixed unaligned accesses when using TableSetBgColor(ImGuiTableBgTarget_CellBg). (#3872) | ||||
| - IsItemHovered(): fixed return value false positive when used after EndChild(), EndGroup() or widgets using | ||||
|   either of them, when the hovered location is located within a child window, e.g. InputTextMultiline(). | ||||
|   This is intended to have no side effects, but brace yourself for the possible comeback.. (#3851, #1370) | ||||
| - Added GetAllocatorFunctions() to facilitate sharing allocators accross DLL boundaries. (#3836) | ||||
| - ImFontAtlas: Added 'bool TexPixelsUseColors' output to help backend decide of underlying texture format. (#3369) | ||||
|   This can currently only ever be set by the Freetype renderer. | ||||
| - imgui_freetype: Added ImGuiFreeTypeBuilderFlags_Bitmap flag to request Freetype loading bitmap data.  | ||||
|   This may have an effect on size and must be called with correct size values. (#3879) [@metarutaiga] | ||||
| - ImDrawList: AddCircle, AddCircleFilled(): Tweaked default segment count calculation to honor MaxError | ||||
|   with more accuracy. Made default segment count always even for better looking result. (#3808) [@thedmd] | ||||
| - ImDrawList: AddCircle, AddCircleFilled(): New default for style. | ||||
| - Backends: Android: Added native Android backend. (#3446) [@duddel] | ||||
| - Backends: Win32: Added ImGui_ImplWin32_EnableAlphaCompositing() to facilitate experimenting with  | ||||
|   alpha compositing and transparent windows. (#2766, #3447 etc.). | ||||
| - Backends: OpenGL, Vulkan, DX9, DX10, DX11, DX12, Metal, WebGPU, Allegro: Rework blending equation to | ||||
| @@ -133,6 +140,7 @@ Other Changes: | ||||
|   (#2693, #2764, #2766, #2873, #3447, #3813, #3816) [@ocornut, @thedmd, @ShawnM427, @Ubpa, @aiekick] | ||||
| - Backends: DX9: Fix to support IMGUI_USE_BGRA_PACKED_COLOR. (#3844) [@Xiliusha] | ||||
| - Backends: DX9: Fix to support colored glyphs, using newly introduced 'TexPixelsUseColors' info. (#3844) | ||||
| - Examples: Android: Added Android + GL ES2 example. (#3446) [@duddel] | ||||
| - Examples: Reworked setup of clear color to be compatible with transparent values. | ||||
| - CI: Use a dedicated "scheduled" workflow to trigger scheduled builds. Forks may disable this workflow if | ||||
|   scheduled builds builds are not required. [@rokups] | ||||
|   | ||||
| @@ -79,6 +79,10 @@ Changelog, so if you want to update them later it will be easier to catch up wit | ||||
| Allegro 5 example. <BR> | ||||
| = main.cpp + imgui_impl_allegro5.cpp | ||||
|  | ||||
| [example_android_opengl3/](https://github.com/ocornut/imgui/blob/master/examples/example_android_opengl3/) <BR> | ||||
| Android + OpenGL3 (ES) example. <BR> | ||||
| = main.cpp + imgui_impl_android.cpp + imgui_impl_opengl3.cpp | ||||
|  | ||||
| [example_apple_metal/](https://github.com/ocornut/imgui/blob/master/examples/example_metal/) <BR> | ||||
| OSX & iOS + Metal example. <BR> | ||||
| = main.m + imgui_impl_osx.mm + imgui_impl_metal.mm <BR> | ||||
|   | ||||
| @@ -117,7 +117,7 @@ Integrating Dear ImGui within your custom engine is a matter of 1) wiring mouse/ | ||||
|  | ||||
| Officially maintained backends/bindings (in repository): | ||||
| - Renderers: DirectX9, DirectX10, DirectX11, DirectX12, Metal, OpenGL/ES/ES2, Vulkan, WebGPU. | ||||
| - Platforms: GLFW, SDL2, Win32, Glut, OSX. | ||||
| - Platforms: GLFW, SDL2, Win32, Glut, OSX, Android. | ||||
| - Frameworks: Emscripten, Allegro5, Marmalade. | ||||
|  | ||||
| [Third-party backends/bindings](https://github.com/ocornut/imgui/wiki/Bindings) wiki page: | ||||
|   | ||||
							
								
								
									
										40
									
								
								examples/example_android_opengl3/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								examples/example_android_opengl3/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| cmake_minimum_required(VERSION 3.6) | ||||
|  | ||||
| project(ImGuiExample) | ||||
|  | ||||
| set(CMAKE_CXX_STANDARD 11) | ||||
| set(CMAKE_CXX_STANDARD_REQUIRED ON) | ||||
| set(CMAKE_CXX_EXTENSIONS OFF) | ||||
|  | ||||
| add_library(${CMAKE_PROJECT_NAME} SHARED | ||||
|   ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp | ||||
|   ${CMAKE_CURRENT_SOURCE_DIR}/../../imgui.cpp | ||||
|   ${CMAKE_CURRENT_SOURCE_DIR}/../../imgui_demo.cpp | ||||
|   ${CMAKE_CURRENT_SOURCE_DIR}/../../imgui_draw.cpp | ||||
|   ${CMAKE_CURRENT_SOURCE_DIR}/../../imgui_tables.cpp | ||||
|   ${CMAKE_CURRENT_SOURCE_DIR}/../../imgui_widgets.cpp | ||||
|   ${CMAKE_CURRENT_SOURCE_DIR}/../../backends/imgui_impl_android.cpp | ||||
|   ${CMAKE_CURRENT_SOURCE_DIR}/../../backends/imgui_impl_opengl3.cpp | ||||
|   ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c | ||||
| ) | ||||
|  | ||||
| set(CMAKE_SHARED_LINKER_FLAGS | ||||
|   "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate" | ||||
| ) | ||||
|  | ||||
| target_compile_definitions(${CMAKE_PROJECT_NAME} PRIVATE | ||||
|   IMGUI_IMPL_OPENGL_ES3 | ||||
| ) | ||||
|  | ||||
| target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE | ||||
|   ${CMAKE_CURRENT_SOURCE_DIR}/../.. | ||||
|   ${CMAKE_CURRENT_SOURCE_DIR}/../../backends | ||||
|   ${ANDROID_NDK}/sources/android/native_app_glue | ||||
| ) | ||||
|  | ||||
| target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE | ||||
|   android | ||||
|   EGL | ||||
|   GLESv3 | ||||
|   log | ||||
| ) | ||||
							
								
								
									
										12
									
								
								examples/example_android_opengl3/android/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								examples/example_android_opengl3/android/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| .cxx | ||||
| .externalNativeBuild | ||||
| build/ | ||||
| *.iml | ||||
|  | ||||
| .idea | ||||
| .gradle | ||||
| local.properties | ||||
|  | ||||
| # Android Studio puts a Gradle wrapper here, that we don't want: | ||||
| gradle/ | ||||
| gradlew* | ||||
							
								
								
									
										34
									
								
								examples/example_android_opengl3/android/app/build.gradle
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								examples/example_android_opengl3/android/app/build.gradle
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| apply plugin: 'com.android.application' | ||||
| apply plugin: 'kotlin-android' | ||||
|  | ||||
| android { | ||||
|     compileSdkVersion 29 | ||||
|     buildToolsVersion "30.0.3" | ||||
|     ndkVersion "21.4.7075529" | ||||
|     defaultConfig { | ||||
|         applicationId "imgui.example.android" | ||||
|         minSdkVersion 23 | ||||
|         targetSdkVersion 29 | ||||
|         versionCode 1 | ||||
|         versionName "1.0" | ||||
|     } | ||||
|  | ||||
|     buildTypes { | ||||
|         release { | ||||
|             minifyEnabled false | ||||
|             proguardFiles getDefaultProguardFile('proguard-android-optimize.txt') | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     externalNativeBuild { | ||||
|         cmake { | ||||
|             path "../../CMakeLists.txt" | ||||
|         } | ||||
|     } | ||||
| } | ||||
| repositories { | ||||
|     mavenCentral() | ||||
| } | ||||
| dependencies { | ||||
|     implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" | ||||
| } | ||||
| @@ -0,0 +1,24 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <manifest xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     package="imgui.example.android"> | ||||
|  | ||||
|     <application | ||||
|         android:label="ImGuiExample" | ||||
|         android:allowBackup="false" | ||||
|         android:fullBackupContent="false" | ||||
|         android:hasCode="true"> | ||||
|  | ||||
|         <activity | ||||
|             android:name="imgui.example.android.MainActivity" | ||||
|             android:theme="@android:style/Theme.NoTitleBar.Fullscreen" | ||||
|             android:configChanges="orientation|keyboardHidden|screenSize"> | ||||
|             <meta-data android:name="android.app.lib_name" | ||||
|                 android:value="ImGuiExample" /> | ||||
|  | ||||
|             <intent-filter> | ||||
|                 <action android:name="android.intent.action.MAIN" /> | ||||
|                 <category android:name="android.intent.category.LAUNCHER" /> | ||||
|             </intent-filter> | ||||
|         </activity> | ||||
|     </application> | ||||
| </manifest> | ||||
| @@ -0,0 +1,40 @@ | ||||
| package imgui.example.android | ||||
|  | ||||
| import android.app.NativeActivity | ||||
| import android.os.Bundle | ||||
| import android.content.Context | ||||
| import android.view.inputmethod.InputMethodManager | ||||
| import android.view.KeyEvent | ||||
| import java.util.concurrent.LinkedBlockingQueue | ||||
|  | ||||
| class MainActivity : NativeActivity() { | ||||
|     public override fun onCreate(savedInstanceState: Bundle?) { | ||||
|         super.onCreate(savedInstanceState) | ||||
|     } | ||||
|  | ||||
|     fun showSoftInput() { | ||||
|         val inputMethodManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager | ||||
|         inputMethodManager.showSoftInput(this.window.decorView, 0) | ||||
|     } | ||||
|  | ||||
|     fun hideSoftInput() { | ||||
|         val inputMethodManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager | ||||
|         inputMethodManager.hideSoftInputFromWindow(this.window.decorView.windowToken, 0) | ||||
|     } | ||||
|  | ||||
|     // Queue for the Unicode characters to be polled from native code (via pollUnicodeChar()) | ||||
|     private var unicodeCharacterQueue: LinkedBlockingQueue<Int> = LinkedBlockingQueue() | ||||
|  | ||||
|     // We assume dispatchKeyEvent() of the NativeActivity is actually called for every | ||||
|     // KeyEvent and not consumed by any View before it reaches here | ||||
|     override fun dispatchKeyEvent(event: KeyEvent): Boolean { | ||||
|         if (event.action == KeyEvent.ACTION_DOWN) { | ||||
|             unicodeCharacterQueue.offer(event.getUnicodeChar(event.metaState)) | ||||
|         } | ||||
|         return super.dispatchKeyEvent(event) | ||||
|     } | ||||
|  | ||||
|     fun pollUnicodeChar(): Int { | ||||
|         return unicodeCharacterQueue.poll() ?: 0 | ||||
|     } | ||||
| } | ||||
							
								
								
									
										24
									
								
								examples/example_android_opengl3/android/build.gradle
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								examples/example_android_opengl3/android/build.gradle
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| buildscript { | ||||
|     ext.kotlin_version = '1.4.30' | ||||
|     repositories { | ||||
|         google() | ||||
|         jcenter() | ||||
|  | ||||
|     } | ||||
|     dependencies { | ||||
|         classpath 'com.android.tools.build:gradle:4.0.1' | ||||
|         classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" | ||||
|  | ||||
|     } | ||||
| } | ||||
|  | ||||
| allprojects { | ||||
|     repositories { | ||||
|         google() | ||||
|         jcenter() | ||||
|     } | ||||
| } | ||||
|  | ||||
| task clean(type: Delete) { | ||||
|     delete rootProject.buildDir | ||||
| } | ||||
							
								
								
									
										1
									
								
								examples/example_android_opengl3/android/settings.gradle
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								examples/example_android_opengl3/android/settings.gradle
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| include ':app' | ||||
							
								
								
									
										369
									
								
								examples/example_android_opengl3/main.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										369
									
								
								examples/example_android_opengl3/main.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,369 @@ | ||||
| // dear imgui: standalone example application for Android + OpenGL ES 3 | ||||
| // If you are new to dear imgui, see examples/README.txt and documentation at the top of imgui.cpp. | ||||
|  | ||||
| #include "imgui.h" | ||||
| #include "imgui_impl_android.h" | ||||
| #include "imgui_impl_opengl3.h" | ||||
| #include <android/log.h> | ||||
| #include <android_native_app_glue.h> | ||||
| #include <android/asset_manager.h> | ||||
| #include <EGL/egl.h> | ||||
| #include <GLES3/gl3.h> | ||||
|  | ||||
| // Data | ||||
| static EGLDisplay           g_EglDisplay = EGL_NO_DISPLAY; | ||||
| static EGLSurface           g_EglSurface = EGL_NO_SURFACE; | ||||
| static EGLContext           g_EglContext = EGL_NO_CONTEXT; | ||||
| static struct android_app*  g_App = NULL; | ||||
| static bool                 g_Initialized = false; | ||||
| static char                 g_LogTag[] = "ImGuiExample"; | ||||
|  | ||||
| // Forward declarations of helper functions | ||||
| static int ShowSoftKeyboardInput(); | ||||
| static int PollUnicodeChars(); | ||||
| static int GetAssetData(const char* filename, void** out_data); | ||||
|  | ||||
| void init(struct android_app* app) | ||||
| { | ||||
|     if (g_Initialized) | ||||
|         return; | ||||
|  | ||||
|     g_App = app; | ||||
|     ANativeWindow_acquire(g_App->window); | ||||
|  | ||||
|     // Initialize EGL | ||||
|     // This is mostly boilerplate code for EGL... | ||||
|     { | ||||
|         g_EglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); | ||||
|         if (g_EglDisplay == EGL_NO_DISPLAY) | ||||
|             __android_log_print(ANDROID_LOG_ERROR, g_LogTag, "%s", "eglGetDisplay(EGL_DEFAULT_DISPLAY) returned EGL_NO_DISPLAY"); | ||||
|  | ||||
|         if (eglInitialize(g_EglDisplay, 0, 0) != EGL_TRUE) | ||||
|             __android_log_print(ANDROID_LOG_ERROR, g_LogTag, "%s", "eglInitialize() returned with an error"); | ||||
|  | ||||
|         const EGLint egl_attributes[] = { EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_RED_SIZE, 8, EGL_DEPTH_SIZE, 24, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_NONE }; | ||||
|         EGLint num_configs = 0; | ||||
|         if (eglChooseConfig(g_EglDisplay, egl_attributes, nullptr, 0, &num_configs) != EGL_TRUE) | ||||
|             __android_log_print(ANDROID_LOG_ERROR, g_LogTag, "%s", "eglChooseConfig() returned with an error"); | ||||
|         if (num_configs == 0) | ||||
|             __android_log_print(ANDROID_LOG_ERROR, g_LogTag, "%s", "eglChooseConfig() returned 0 matching config"); | ||||
|  | ||||
|         // Get the first matching config | ||||
|         EGLConfig egl_config; | ||||
|         eglChooseConfig(g_EglDisplay, egl_attributes, &egl_config, 1, &num_configs); | ||||
|         EGLint egl_format; | ||||
|         eglGetConfigAttrib(g_EglDisplay, egl_config, EGL_NATIVE_VISUAL_ID, &egl_format); | ||||
|         ANativeWindow_setBuffersGeometry(g_App->window, 0, 0, egl_format); | ||||
|  | ||||
|         const EGLint egl_context_attributes[] = { EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE }; | ||||
|         g_EglContext = eglCreateContext(g_EglDisplay, egl_config, EGL_NO_CONTEXT, egl_context_attributes); | ||||
|  | ||||
|         if (g_EglContext == EGL_NO_CONTEXT) | ||||
|             __android_log_print(ANDROID_LOG_ERROR, g_LogTag, "%s", "eglCreateContext() returned EGL_NO_CONTEXT"); | ||||
|  | ||||
|         g_EglSurface = eglCreateWindowSurface(g_EglDisplay, egl_config, g_App->window, NULL); | ||||
|         eglMakeCurrent(g_EglDisplay, g_EglSurface, g_EglSurface, g_EglContext); | ||||
|     } | ||||
|  | ||||
|     // Setup Dear ImGui context | ||||
|     IMGUI_CHECKVERSION(); | ||||
|     ImGui::CreateContext(); | ||||
|     ImGuiIO& io = ImGui::GetIO(); | ||||
|  | ||||
|     // Disable loading/saving of .ini file from disk. | ||||
|     // FIXME: Consider using LoadIniSettingsFromMemory() / SaveIniSettingsToMemory() to save in appropriate location for Android. | ||||
|     io.IniFilename = NULL; | ||||
|  | ||||
|     // Setup Dear ImGui style | ||||
|     ImGui::StyleColorsDark(); | ||||
|     //ImGui::StyleColorsClassic(); | ||||
|  | ||||
|     // Setup Platform/Renderer backends | ||||
|     ImGui_ImplAndroid_Init(g_App->window); | ||||
|     ImGui_ImplOpenGL3_Init("#version 300 es"); | ||||
|  | ||||
|     // Load Fonts | ||||
|     // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. | ||||
|     // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). | ||||
|     // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. | ||||
|     // - Read 'docs/FONTS.md' for more instructions and details. | ||||
|     // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! | ||||
|     // - Android: The TTF files have to be placed into the assets/ directory (android/app/src/main/assets), we use our GetAssetData() helper to retrieve them. | ||||
|  | ||||
|     // We load the default font with increased size to improve readability on many devices with "high" DPI. | ||||
|     // FIXME: Put some effort into DPI awareness. | ||||
|     // Important: when calling AddFontFromMemoryTTF(), ownership of font_data is transfered by Dear ImGui by default (deleted is handled by Dear ImGui), unless we set FontDataOwnedByAtlas=false in ImFontConfig | ||||
|     ImFontConfig font_cfg; | ||||
|     font_cfg.SizePixels = 22.0f; | ||||
|     io.Fonts->AddFontDefault(&font_cfg); | ||||
|     //void* font_data; | ||||
|     //int font_data_size; | ||||
|     //ImFont* font; | ||||
|     //font_data_size = GetAssetData("Roboto-Medium.ttf", &font_data); | ||||
|     //font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size, 16.0f); | ||||
|     //IM_ASSERT(font != NULL); | ||||
|     //font_data_size = GetAssetData("Cousine-Regular.ttf", &font_data); | ||||
|     //font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size, 15.0f); | ||||
|     //IM_ASSERT(font != NULL); | ||||
|     //font_data_size = GetAssetData("DroidSans.ttf", &font_data); | ||||
|     //font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size, 16.0f); | ||||
|     //IM_ASSERT(font != NULL); | ||||
|     //font_data_size = GetAssetData("ProggyTiny.ttf", &font_data); | ||||
|     //font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size, 10.0f); | ||||
|     //IM_ASSERT(font != NULL); | ||||
|     //font_data_size = GetAssetData("ArialUni.ttf", &font_data); | ||||
|     //font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size, 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); | ||||
|     //IM_ASSERT(font != NULL); | ||||
|  | ||||
|     // Arbitrary scale-up | ||||
|     // FIXME: Put some effort into DPI awareness | ||||
|     ImGui::GetStyle().ScaleAllSizes(3.0f); | ||||
|  | ||||
|     g_Initialized = true; | ||||
| } | ||||
|  | ||||
| void tick() | ||||
| { | ||||
|     ImGuiIO& io = ImGui::GetIO(); | ||||
|     if (g_EglDisplay == EGL_NO_DISPLAY) | ||||
|         return; | ||||
|  | ||||
|     // Our state | ||||
|     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); | ||||
|  | ||||
|     // Poll Unicode characters via JNI | ||||
|     // FIXME: do not call this every frame because of JNI overhead | ||||
|     PollUnicodeChars(); | ||||
|  | ||||
|     // Open on-screen (soft) input if requested by Dear ImGui | ||||
|     static bool WantTextInputLast = false; | ||||
|     if (io.WantTextInput && !WantTextInputLast) | ||||
|         ShowSoftKeyboardInput(); | ||||
|     WantTextInputLast = io.WantTextInput; | ||||
|  | ||||
|     // Start the Dear ImGui frame | ||||
|     ImGui_ImplOpenGL3_NewFrame(); | ||||
|     ImGui_ImplAndroid_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 created 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 / ImGui::GetIO().Framerate, ImGui::GetIO().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(g_EglDisplay, g_EglSurface); | ||||
| } | ||||
|  | ||||
| void shutdown() | ||||
| { | ||||
|     if (!g_Initialized) | ||||
|         return; | ||||
|  | ||||
|     // Cleanup | ||||
|     ImGui_ImplOpenGL3_Shutdown(); | ||||
|     ImGui_ImplAndroid_Shutdown(); | ||||
|     ImGui::DestroyContext(); | ||||
|  | ||||
|     if (g_EglDisplay != EGL_NO_DISPLAY) | ||||
|     { | ||||
|         eglMakeCurrent(g_EglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); | ||||
|  | ||||
|         if (g_EglContext != EGL_NO_CONTEXT) | ||||
|             eglDestroyContext(g_EglDisplay, g_EglContext); | ||||
|  | ||||
|         if (g_EglSurface != EGL_NO_SURFACE) | ||||
|             eglDestroySurface(g_EglDisplay, g_EglSurface); | ||||
|  | ||||
|         eglTerminate(g_EglDisplay); | ||||
|     } | ||||
|  | ||||
|     g_EglDisplay = EGL_NO_DISPLAY; | ||||
|     g_EglContext = EGL_NO_CONTEXT; | ||||
|     g_EglSurface = EGL_NO_SURFACE; | ||||
|     ANativeWindow_release(g_App->window); | ||||
|  | ||||
|     g_Initialized = false; | ||||
| } | ||||
|  | ||||
| static void handleAppCmd(struct android_app* app, int32_t appCmd) | ||||
| { | ||||
|     switch (appCmd) | ||||
|     { | ||||
|     case APP_CMD_SAVE_STATE: | ||||
|         break; | ||||
|     case APP_CMD_INIT_WINDOW: | ||||
|         init(app); | ||||
|         break; | ||||
|     case APP_CMD_TERM_WINDOW: | ||||
|         shutdown(); | ||||
|         break; | ||||
|     case APP_CMD_GAINED_FOCUS: | ||||
|         break; | ||||
|     case APP_CMD_LOST_FOCUS: | ||||
|         break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static int32_t handleInputEvent(struct android_app* app, AInputEvent* inputEvent) | ||||
| { | ||||
|     return ImGui_ImplAndroid_HandleInputEvent(inputEvent); | ||||
| } | ||||
|  | ||||
| void android_main(struct android_app* app) | ||||
| { | ||||
|     app->onAppCmd = handleAppCmd; | ||||
|     app->onInputEvent = handleInputEvent; | ||||
|  | ||||
|     while (true) | ||||
|     { | ||||
|         int out_events; | ||||
|         struct android_poll_source* out_data; | ||||
|  | ||||
|         // Poll all events. If the app is not visible, this loop blocks until g_Initialized == true. | ||||
|         while (ALooper_pollAll(g_Initialized ? 0 : -1, NULL, &out_events, (void**)&out_data) >= 0) | ||||
|         { | ||||
|             // Process one event | ||||
|             if (out_data != NULL) | ||||
|                 out_data->process(app, out_data); | ||||
|  | ||||
|             // Exit the app by returning from within the infinite loop | ||||
|             if (app->destroyRequested != 0) | ||||
|             { | ||||
|                 // shutdown() should have been called already while processing the | ||||
|                 // app command APP_CMD_TERM_WINDOW. But we play save here | ||||
|                 if (!g_Initialized) | ||||
|                     shutdown(); | ||||
|  | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // Initiate a new frame | ||||
|         tick(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| // Unfortunately, there is no way to show the on-screen input from native code. | ||||
| // Therefore, we call ShowSoftKeyboardInput() of the main activity implemented in MainActivity.kt via JNI. | ||||
| static int ShowSoftKeyboardInput() | ||||
| { | ||||
|     JavaVM* java_vm = g_App->activity->vm; | ||||
|     JNIEnv* java_env = NULL; | ||||
|  | ||||
|     jint jni_return = java_vm->GetEnv((void**)&java_env, JNI_VERSION_1_6); | ||||
|     if (jni_return == JNI_ERR) | ||||
|         return -1; | ||||
|  | ||||
|     jni_return = java_vm->AttachCurrentThread(&java_env, NULL); | ||||
|     if (jni_return != JNI_OK) | ||||
|         return -2; | ||||
|  | ||||
|     jclass native_activity_clazz = java_env->GetObjectClass(g_App->activity->clazz); | ||||
|     if (native_activity_clazz == NULL) | ||||
|         return -3; | ||||
|  | ||||
|     jmethodID method_id = java_env->GetMethodID(native_activity_clazz, "showSoftInput", "()V"); | ||||
|     if (method_id == NULL) | ||||
|         return -4; | ||||
|  | ||||
|     java_env->CallVoidMethod(g_App->activity->clazz, method_id); | ||||
|  | ||||
|     jni_return = java_vm->DetachCurrentThread(); | ||||
|     if (jni_return != JNI_OK) | ||||
|         return -5; | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| // Unfortunately, the native KeyEvent implementation has no getUnicodeChar() function. | ||||
| // Therefore, we implement the processing of KeyEvents in MainActivity.kt and poll | ||||
| // the resulting Unicode characters here via JNI and send them to Dear ImGui. | ||||
| static int PollUnicodeChars() | ||||
| { | ||||
|     JavaVM* java_vm = g_App->activity->vm; | ||||
|     JNIEnv* java_env = NULL; | ||||
|  | ||||
|     jint jni_return = java_vm->GetEnv((void**)&java_env, JNI_VERSION_1_6); | ||||
|     if (jni_return == JNI_ERR) | ||||
|         return -1; | ||||
|  | ||||
|     jni_return = java_vm->AttachCurrentThread(&java_env, NULL); | ||||
|     if (jni_return != JNI_OK) | ||||
|         return -2; | ||||
|  | ||||
|     jclass native_activity_clazz = java_env->GetObjectClass(g_App->activity->clazz); | ||||
|     if (native_activity_clazz == NULL) | ||||
|         return -3; | ||||
|  | ||||
|     jmethodID method_id = java_env->GetMethodID(native_activity_clazz, "pollUnicodeChar", "()I"); | ||||
|     if (method_id == NULL) | ||||
|         return -4; | ||||
|  | ||||
|     // Send the actual characters to Dear ImGui | ||||
|     ImGuiIO& io = ImGui::GetIO(); | ||||
|     jint unicode_character; | ||||
|     while ((unicode_character = java_env->CallIntMethod(g_App->activity->clazz, method_id)) != 0) | ||||
|         io.AddInputCharacter(unicode_character); | ||||
|  | ||||
|     jni_return = java_vm->DetachCurrentThread(); | ||||
|     if (jni_return != JNI_OK) | ||||
|         return -5; | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| // Helper to retrieve data placed into the assets/ directory (android/app/src/main/assets) | ||||
| static int GetAssetData(const char* filename, void** outData) | ||||
| { | ||||
|     int num_bytes = 0; | ||||
|     AAsset* asset_descriptor = AAssetManager_open(g_App->activity->assetManager, filename, AASSET_MODE_BUFFER); | ||||
|     if (asset_descriptor) | ||||
|     { | ||||
|         num_bytes = AAsset_getLength(asset_descriptor); | ||||
|         *outData = IM_ALLOC(num_bytes); | ||||
|         int64_t num_bytes_read = AAsset_read(asset_descriptor, *outData, num_bytes); | ||||
|         AAsset_close(asset_descriptor); | ||||
|         IM_ASSERT(num_bytes_read == num_bytes); | ||||
|     } | ||||
|     return num_bytes; | ||||
| } | ||||
							
								
								
									
										66
									
								
								imgui.cpp
									
									
									
									
									
								
							
							
						
						
									
										66
									
								
								imgui.cpp
									
									
									
									
									
								
							| @@ -971,8 +971,8 @@ static void    FreeWrapper(void* ptr, void* user_data)        { IM_UNUSED(user_d | ||||
| static void*   MallocWrapper(size_t size, void* user_data)    { IM_UNUSED(user_data); IM_UNUSED(size); IM_ASSERT(0); return NULL; } | ||||
| static void    FreeWrapper(void* ptr, void* user_data)        { IM_UNUSED(user_data); IM_UNUSED(ptr); IM_ASSERT(0); } | ||||
| #endif | ||||
| static ImGuiMemAllocFunc*   GImAllocatorAllocFunc = MallocWrapper; | ||||
| static ImGuiMemFreeFunc*    GImAllocatorFreeFunc = FreeWrapper; | ||||
| static ImGuiMemAllocFunc    GImAllocatorAllocFunc = MallocWrapper; | ||||
| static ImGuiMemFreeFunc     GImAllocatorFreeFunc = FreeWrapper; | ||||
| static void*                GImAllocatorUserData = NULL; | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| @@ -3174,20 +3174,22 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags) | ||||
|         return IsItemFocused(); | ||||
|  | ||||
|     // Test for bounding box overlap, as updated as ItemAdd() | ||||
|     if (!(window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect)) | ||||
|     ImGuiItemStatusFlags status_flags = window->DC.LastItemStatusFlags; | ||||
|     if (!(status_flags & ImGuiItemStatusFlags_HoveredRect)) | ||||
|         return false; | ||||
|     IM_ASSERT((flags & (ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows)) == 0);   // Flags not supported by this function | ||||
|  | ||||
|     // Test if we are hovering the right window (our window could be behind another window) | ||||
|     // [2017/10/16] Reverted commit 344d48be3 and testing RootWindow instead. I believe it is correct to NOT test for RootWindow but this leaves us unable to use IsItemHovered() after EndChild() itself. | ||||
|     // Until a solution is found I believe reverting to the test from 2017/09/27 is safe since this was the test that has been running for a long while. | ||||
|     //if (g.HoveredWindow != window) | ||||
|     //    return false; | ||||
|     if (g.HoveredRootWindow != window->RootWindow && !(flags & ImGuiHoveredFlags_AllowWhenOverlapped)) | ||||
|         return false; | ||||
|     // [2021/03/02] Reworked / reverted the revert, finally. Note we want e.g. BeginGroup/ItemAdd/EndGroup to work as well. (#3851) | ||||
|     // [2017/10/16] Reverted commit 344d48be3 and testing RootWindow instead. I believe it is correct to NOT test for RootWindow but this leaves us unable | ||||
|     // to use IsItemHovered() after EndChild() itself. Until a solution is found I believe reverting to the test from 2017/09/27 is safe since this was | ||||
|     // the test that has been running for a long while. | ||||
|     if (g.HoveredWindow != window && (status_flags & ImGuiItemStatusFlags_HoveredWindow) == 0) | ||||
|         if ((flags & ImGuiHoveredFlags_AllowWhenOverlapped) == 0) | ||||
|             return false; | ||||
|  | ||||
|     // Test if another item is active (e.g. being dragged) | ||||
|     if (!(flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) | ||||
|     if ((flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) == 0) | ||||
|         if (g.ActiveId != 0 && g.ActiveId != window->DC.LastItemId && !g.ActiveIdAllowOverlap && g.ActiveId != window->MoveId) | ||||
|             return false; | ||||
|  | ||||
| @@ -3342,7 +3344,7 @@ void* ImGui::MemAlloc(size_t size) | ||||
| { | ||||
|     if (ImGuiContext* ctx = GImGui) | ||||
|         ctx->IO.MetricsActiveAllocations++; | ||||
|     return GImAllocatorAllocFunc(size, GImAllocatorUserData); | ||||
|     return (*GImAllocatorAllocFunc)(size, GImAllocatorUserData); | ||||
| } | ||||
|  | ||||
| // IM_FREE() == ImGui::MemFree() | ||||
| @@ -3351,7 +3353,7 @@ void ImGui::MemFree(void* ptr) | ||||
|     if (ptr) | ||||
|         if (ImGuiContext* ctx = GImGui) | ||||
|             ctx->IO.MetricsActiveAllocations--; | ||||
|     return GImAllocatorFreeFunc(ptr, GImAllocatorUserData); | ||||
|     return (*GImAllocatorFreeFunc)(ptr, GImAllocatorUserData); | ||||
| } | ||||
|  | ||||
| const char* ImGui::GetClipboardText() | ||||
| @@ -3388,7 +3390,7 @@ void ImGui::SetCurrentContext(ImGuiContext* ctx) | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void ImGui::SetAllocatorFunctions(ImGuiMemAllocFunc* alloc_func, ImGuiMemFreeFunc* free_func, void* user_data) | ||||
| void ImGui::SetAllocatorFunctions(ImGuiMemAllocFunc alloc_func, ImGuiMemFreeFunc free_func, void* user_data) | ||||
| { | ||||
|     GImAllocatorAllocFunc = alloc_func; | ||||
|     GImAllocatorFreeFunc = free_func; | ||||
| @@ -3396,7 +3398,7 @@ void ImGui::SetAllocatorFunctions(ImGuiMemAllocFunc* alloc_func, ImGuiMemFreeFun | ||||
| } | ||||
|  | ||||
| // This is provided to facilitate copying allocators from one static/DLL boundary to another (e.g. retrieve default allocator of your executable address space) | ||||
| void ImGui::GetAllocatorFunctions(ImGuiMemAllocFunc** p_alloc_func, ImGuiMemFreeFunc** p_free_func, void** p_user_data) | ||||
| void ImGui::GetAllocatorFunctions(ImGuiMemAllocFunc* p_alloc_func, ImGuiMemFreeFunc* p_free_func, void** p_user_data) | ||||
| { | ||||
|     *p_alloc_func = GImAllocatorAllocFunc; | ||||
|     *p_free_func = GImAllocatorFreeFunc; | ||||
| @@ -3920,7 +3922,7 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags() | ||||
|  | ||||
|     // Modal windows prevents mouse from hovering behind them. | ||||
|     ImGuiWindow* modal_window = GetTopMostPopupModal(); | ||||
|     if (modal_window && g.HoveredRootWindow && !IsWindowChildOf(g.HoveredRootWindow, modal_window)) | ||||
|     if (modal_window && g.HoveredWindow && !IsWindowChildOf(g.HoveredWindow->RootWindow, modal_window)) | ||||
|         clear_hovered_windows = true; | ||||
|  | ||||
|     // Disabled mouse? | ||||
| @@ -3948,7 +3950,7 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags() | ||||
|         clear_hovered_windows = true; | ||||
|  | ||||
|     if (clear_hovered_windows) | ||||
|         g.HoveredWindow = g.HoveredRootWindow = g.HoveredWindowUnderMovingWindow = NULL; | ||||
|         g.HoveredWindow = g.HoveredWindowUnderMovingWindow = NULL; | ||||
|  | ||||
|     // Update io.WantCaptureMouse for the user application (true = dispatch mouse info to imgui, false = dispatch mouse info to Dear ImGui + app) | ||||
|     if (g.WantCaptureMouseNextFrame != -1) | ||||
| @@ -4300,7 +4302,7 @@ void ImGui::Shutdown(ImGuiContext* context) | ||||
|     g.CurrentWindowStack.clear(); | ||||
|     g.WindowsById.Clear(); | ||||
|     g.NavWindow = NULL; | ||||
|     g.HoveredWindow = g.HoveredRootWindow = g.HoveredWindowUnderMovingWindow = NULL; | ||||
|     g.HoveredWindow = g.HoveredWindowUnderMovingWindow = NULL; | ||||
|     g.ActiveIdWindow = g.ActiveIdPreviousFrameWindow = NULL; | ||||
|     g.MovingWindow = NULL; | ||||
|     g.ColorStack.clear(); | ||||
| @@ -4804,7 +4806,6 @@ static void FindHoveredWindow() | ||||
|     } | ||||
|  | ||||
|     g.HoveredWindow = hovered_window; | ||||
|     g.HoveredRootWindow = g.HoveredWindow ? g.HoveredWindow->RootWindow : NULL; | ||||
|     g.HoveredWindowUnderMovingWindow = hovered_window_ignoring_moving_window; | ||||
|  | ||||
|     if (g.MovingWindow) | ||||
| @@ -5281,6 +5282,8 @@ void ImGui::EndChild() | ||||
|             // Not navigable into | ||||
|             ItemAdd(bb, 0); | ||||
|         } | ||||
|         if (g.HoveredWindow == window) | ||||
|             parent_window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HoveredWindow; | ||||
|     } | ||||
|     g.WithinEndChild = false; | ||||
|     g.LogLinePosY = -FLT_MAX; // To enforce a carriage return | ||||
| @@ -7027,6 +7030,7 @@ void ImGui::FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWind | ||||
|     FocusWindow(NULL); | ||||
| } | ||||
|  | ||||
| // Important: this alone doesn't alter current ImDrawList state. This is called by PushFont/PopFont only. | ||||
| void ImGui::SetCurrentFont(ImFont* font) | ||||
| { | ||||
|     ImGuiContext& g = *GImGui; | ||||
| @@ -7150,30 +7154,28 @@ bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags) | ||||
| { | ||||
|     IM_ASSERT((flags & ImGuiHoveredFlags_AllowWhenOverlapped) == 0);   // Flags not supported by this function | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     if (g.HoveredWindow == NULL) | ||||
|         return false; | ||||
|  | ||||
|     if (flags & ImGuiHoveredFlags_AnyWindow) | ||||
|     { | ||||
|         if (g.HoveredWindow == NULL) | ||||
|             return false; | ||||
|     } | ||||
|     else | ||||
|     if ((flags & ImGuiHoveredFlags_AnyWindow) == 0) | ||||
|     { | ||||
|         ImGuiWindow* window = g.CurrentWindow; | ||||
|         switch (flags & (ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows)) | ||||
|         { | ||||
|         case ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows: | ||||
|             if (g.HoveredWindow == NULL || g.HoveredWindow->RootWindowDockStop != g.CurrentWindow->RootWindowDockStop) | ||||
|             if (g.HoveredWindow->RootWindowDockStop != window->RootWindowDockStop) | ||||
|                 return false; | ||||
|             break; | ||||
|         case ImGuiHoveredFlags_RootWindow: | ||||
|             if (g.HoveredWindow != g.CurrentWindow->RootWindowDockStop) | ||||
|             if (g.HoveredWindow != window->RootWindowDockStop) | ||||
|                 return false; | ||||
|             break; | ||||
|         case ImGuiHoveredFlags_ChildWindows: | ||||
|             if (g.HoveredWindow == NULL || !IsWindowChildOf(g.HoveredWindow, g.CurrentWindow)) | ||||
|             if (!IsWindowChildOf(g.HoveredWindow, window)) | ||||
|                 return false; | ||||
|             break; | ||||
|         default: | ||||
|             if (g.HoveredWindow != g.CurrentWindow) | ||||
|             if (g.HoveredWindow != window) | ||||
|                 return false; | ||||
|             break; | ||||
|         } | ||||
| @@ -8330,6 +8332,7 @@ void ImGui::BeginGroup() | ||||
|     group_data.BackupCurrLineSize = window->DC.CurrLineSize; | ||||
|     group_data.BackupCurrLineTextBaseOffset = window->DC.CurrLineTextBaseOffset; | ||||
|     group_data.BackupActiveIdIsAlive = g.ActiveIdIsAlive; | ||||
|     group_data.BackupHoveredIdIsAlive = g.HoveredId != 0; | ||||
|     group_data.BackupActiveIdPreviousFrameIsAlive = g.ActiveIdPreviousFrameIsAlive; | ||||
|     group_data.EmitItem = true; | ||||
|  | ||||
| @@ -8383,6 +8386,11 @@ void ImGui::EndGroup() | ||||
|         window->DC.LastItemId = g.ActiveIdPreviousFrame; | ||||
|     window->DC.LastItemRect = group_bb; | ||||
|  | ||||
|     // Forward Hovered flag | ||||
|     const bool group_contains_curr_hovered_id = (group_data.BackupHoveredIdIsAlive == false) && g.HoveredId != 0; | ||||
|     if (group_contains_curr_hovered_id) | ||||
|         window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HoveredWindow; | ||||
|  | ||||
|     // Forward Edited flag | ||||
|     if (group_contains_curr_active_id && g.ActiveIdHasBeenEditedThisFrame) | ||||
|         window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_Edited; | ||||
| @@ -16264,7 +16272,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) | ||||
|         Text("WINDOWING"); | ||||
|         Indent(); | ||||
|         Text("HoveredWindow: '%s'", g.HoveredWindow ? g.HoveredWindow->Name : "NULL"); | ||||
|         Text("HoveredRootWindow: '%s'", g.HoveredRootWindow ? g.HoveredRootWindow->Name : "NULL"); | ||||
|         Text("HoveredWindow->Root: '%s'", g.HoveredWindow ? g.HoveredWindow->RootWindow->Name : "NULL"); | ||||
|         Text("HoveredWindowUnderMovingWindow: '%s'", g.HoveredWindowUnderMovingWindow ? g.HoveredWindowUnderMovingWindow->Name : "NULL"); | ||||
|         Text("HoveredDockNode: 0x%08X", g.HoveredDockNode ? g.HoveredDockNode->ID : 0); | ||||
|         Text("MovingWindow: '%s'", g.MovingWindow ? g.MovingWindow->Name : "NULL"); | ||||
|   | ||||
							
								
								
									
										10
									
								
								imgui.h
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								imgui.h
									
									
									
									
									
								
							| @@ -201,8 +201,8 @@ typedef void* ImTextureID;          // User data for rendering backend to identi | ||||
| typedef unsigned int ImGuiID;       // A unique ID used by widgets, typically hashed from a stack of string. | ||||
| typedef int (*ImGuiInputTextCallback)(ImGuiInputTextCallbackData* data);    // Callback function for ImGui::InputText() | ||||
| typedef void (*ImGuiSizeCallback)(ImGuiSizeCallbackData* data);             // Callback function for ImGui::SetNextWindowSizeConstraints() | ||||
| typedef void* (ImGuiMemAllocFunc)(size_t sz, void* user_data);              // Function signature for ImGui::SetAllocatorFunctions() | ||||
| typedef void (ImGuiMemFreeFunc)(void* ptr, void* user_data);                // Function signature for ImGui::SetAllocatorFunctions() | ||||
| typedef void* (*ImGuiMemAllocFunc)(size_t sz, void* user_data);             // Function signature for ImGui::SetAllocatorFunctions() | ||||
| typedef void (*ImGuiMemFreeFunc)(void* ptr, void* user_data);               // Function signature for ImGui::SetAllocatorFunctions() | ||||
|  | ||||
| // Character types | ||||
| // (we generally use UTF-8 encoded string in the API. This is storage specifically for a decoded character used for keyboard input and display) | ||||
| @@ -903,8 +903,8 @@ namespace ImGui | ||||
|     // - Those functions are not reliant on the current context. | ||||
|     // - DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions() | ||||
|     //   for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details. | ||||
|     IMGUI_API void          SetAllocatorFunctions(ImGuiMemAllocFunc* alloc_func, ImGuiMemFreeFunc* free_func, void* user_data = NULL); | ||||
|     IMGUI_API void          GetAllocatorFunctions(ImGuiMemAllocFunc** p_alloc_func, ImGuiMemFreeFunc** p_free_func, void** p_user_data); | ||||
|     IMGUI_API void          SetAllocatorFunctions(ImGuiMemAllocFunc alloc_func, ImGuiMemFreeFunc free_func, void* user_data = NULL); | ||||
|     IMGUI_API void          GetAllocatorFunctions(ImGuiMemAllocFunc* p_alloc_func, ImGuiMemFreeFunc* p_free_func, void** p_user_data); | ||||
|     IMGUI_API void*         MemAlloc(size_t size); | ||||
|     IMGUI_API void          MemFree(void* ptr); | ||||
|  | ||||
| @@ -2881,7 +2881,7 @@ struct ImGuiViewport | ||||
| { | ||||
|     ImGuiID             ID;                     // Unique identifier for the viewport | ||||
|     ImGuiViewportFlags  Flags;                  // See ImGuiViewportFlags_ | ||||
|     ImVec2              Pos;                    // Main Area: Position of the viewport (Dear Imgui coordinates are the same as OS desktop/native coordinates) | ||||
|     ImVec2              Pos;                    // Main Area: Position of the viewport (Dear ImGui coordinates are the same as OS desktop/native coordinates) | ||||
|     ImVec2              Size;                   // Main Area: Size of the viewport. | ||||
|     ImVec2              WorkPos;                // Work Area: Position of the viewport minus task bars, menus bars, status bars (>= Pos) | ||||
|     ImVec2              WorkSize;               // Work Area: Size of the viewport minus task bars, menu bars, status bars (<= Size) | ||||
|   | ||||
| @@ -136,6 +136,16 @@ Index of this file: | ||||
| #define vsnprintf   _vsnprintf | ||||
| #endif | ||||
|  | ||||
| // Format specifiers, printing 64-bit hasn't been decently standardized... | ||||
| // In a real application you should be using PRId64 and PRIu64 from <inttypes.h> (non-windows) and on Windows define them yourself. | ||||
| #ifdef _MSC_VER | ||||
| #define IM_PRId64   "I64d" | ||||
| #define IM_PRIu64   "I64u" | ||||
| #else | ||||
| #define IM_PRId64   "lld" | ||||
| #define IM_PRIu64   "llu" | ||||
| #endif | ||||
|  | ||||
| // Helpers macros | ||||
| // We normally try to not use many helpers in imgui_demo.cpp in order to make code easier to copy and paste, | ||||
| // but making an exception here as those are largely simplifying code... | ||||
| @@ -1972,12 +1982,12 @@ static void ShowDemoWindowWidgets() | ||||
|         ImGui::SliderScalar("slider u32 low",       ImGuiDataType_U32,    &u32_v, &u32_zero, &u32_fifty,"%u"); | ||||
|         ImGui::SliderScalar("slider u32 high",      ImGuiDataType_U32,    &u32_v, &u32_hi_a, &u32_hi_b, "%u"); | ||||
|         ImGui::SliderScalar("slider u32 full",      ImGuiDataType_U32,    &u32_v, &u32_min,  &u32_max,  "%u"); | ||||
|         ImGui::SliderScalar("slider s64 low",       ImGuiDataType_S64,    &s64_v, &s64_zero, &s64_fifty,"%I64d"); | ||||
|         ImGui::SliderScalar("slider s64 high",      ImGuiDataType_S64,    &s64_v, &s64_hi_a, &s64_hi_b, "%I64d"); | ||||
|         ImGui::SliderScalar("slider s64 full",      ImGuiDataType_S64,    &s64_v, &s64_min,  &s64_max,  "%I64d"); | ||||
|         ImGui::SliderScalar("slider u64 low",       ImGuiDataType_U64,    &u64_v, &u64_zero, &u64_fifty,"%I64u ms"); | ||||
|         ImGui::SliderScalar("slider u64 high",      ImGuiDataType_U64,    &u64_v, &u64_hi_a, &u64_hi_b, "%I64u ms"); | ||||
|         ImGui::SliderScalar("slider u64 full",      ImGuiDataType_U64,    &u64_v, &u64_min,  &u64_max,  "%I64u ms"); | ||||
|         ImGui::SliderScalar("slider s64 low",       ImGuiDataType_S64,    &s64_v, &s64_zero, &s64_fifty,"%" IM_PRId64); | ||||
|         ImGui::SliderScalar("slider s64 high",      ImGuiDataType_S64,    &s64_v, &s64_hi_a, &s64_hi_b, "%" IM_PRId64); | ||||
|         ImGui::SliderScalar("slider s64 full",      ImGuiDataType_S64,    &s64_v, &s64_min,  &s64_max,  "%" IM_PRId64); | ||||
|         ImGui::SliderScalar("slider u64 low",       ImGuiDataType_U64,    &u64_v, &u64_zero, &u64_fifty,"%" IM_PRIu64 " ms"); | ||||
|         ImGui::SliderScalar("slider u64 high",      ImGuiDataType_U64,    &u64_v, &u64_hi_a, &u64_hi_b, "%" IM_PRIu64 " ms"); | ||||
|         ImGui::SliderScalar("slider u64 full",      ImGuiDataType_U64,    &u64_v, &u64_min,  &u64_max,  "%" IM_PRIu64 " ms"); | ||||
|         ImGui::SliderScalar("slider float low",     ImGuiDataType_Float,  &f32_v, &f32_zero, &f32_one); | ||||
|         ImGui::SliderScalar("slider float low log", ImGuiDataType_Float,  &f32_v, &f32_zero, &f32_one,  "%.10f", ImGuiSliderFlags_Logarithmic); | ||||
|         ImGui::SliderScalar("slider float high",    ImGuiDataType_Float,  &f32_v, &f32_lo_a, &f32_hi_a, "%e"); | ||||
| @@ -1986,12 +1996,12 @@ static void ShowDemoWindowWidgets() | ||||
|         ImGui::SliderScalar("slider double high",   ImGuiDataType_Double, &f64_v, &f64_lo_a, &f64_hi_a, "%e grams"); | ||||
|  | ||||
|         ImGui::Text("Sliders (reverse)"); | ||||
|         ImGui::SliderScalar("slider s8 reverse",    ImGuiDataType_S8,   &s8_v,  &s8_max,    &s8_min, "%d"); | ||||
|         ImGui::SliderScalar("slider u8 reverse",    ImGuiDataType_U8,   &u8_v,  &u8_max,    &u8_min, "%u"); | ||||
|         ImGui::SliderScalar("slider s8 reverse",    ImGuiDataType_S8,   &s8_v,  &s8_max,    &s8_min,   "%d"); | ||||
|         ImGui::SliderScalar("slider u8 reverse",    ImGuiDataType_U8,   &u8_v,  &u8_max,    &u8_min,   "%u"); | ||||
|         ImGui::SliderScalar("slider s32 reverse",   ImGuiDataType_S32,  &s32_v, &s32_fifty, &s32_zero, "%d"); | ||||
|         ImGui::SliderScalar("slider u32 reverse",   ImGuiDataType_U32,  &u32_v, &u32_fifty, &u32_zero, "%u"); | ||||
|         ImGui::SliderScalar("slider s64 reverse",   ImGuiDataType_S64,  &s64_v, &s64_fifty, &s64_zero, "%I64d"); | ||||
|         ImGui::SliderScalar("slider u64 reverse",   ImGuiDataType_U64,  &u64_v, &u64_fifty, &u64_zero, "%I64u ms"); | ||||
|         ImGui::SliderScalar("slider s64 reverse",   ImGuiDataType_S64,  &s64_v, &s64_fifty, &s64_zero, "%" IM_PRId64); | ||||
|         ImGui::SliderScalar("slider u64 reverse",   ImGuiDataType_U64,  &u64_v, &u64_fifty, &u64_zero, "%" IM_PRIu64 " ms"); | ||||
|  | ||||
|         static bool inputs_step = true; | ||||
|         ImGui::Text("Inputs"); | ||||
| @@ -5460,29 +5470,34 @@ static void ShowDemoWindowMisc() | ||||
|         ImGui::Text("WantSetMousePos: %d", io.WantSetMousePos); | ||||
|         ImGui::Text("NavActive: %d, NavVisible: %d", io.NavActive, io.NavVisible); | ||||
|  | ||||
|         // Display Keyboard/Mouse state | ||||
|         if (ImGui::TreeNode("Keyboard, Mouse & Navigation State")) | ||||
|         // Display Mouse state | ||||
|         if (ImGui::TreeNode("Mouse State")) | ||||
|         { | ||||
|             if (ImGui::IsMousePosValid()) | ||||
|                 ImGui::Text("Mouse pos: (%g, %g)", io.MousePos.x, io.MousePos.y); | ||||
|             else | ||||
|                 ImGui::Text("Mouse pos: <INVALID>"); | ||||
|             ImGui::Text("Mouse delta: (%g, %g)", io.MouseDelta.x, io.MouseDelta.y); | ||||
|             ImGui::Text("Mouse down:");     for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (io.MouseDownDuration[i] >= 0.0f)   { ImGui::SameLine(); ImGui::Text("b%d (%.02f secs)", i, io.MouseDownDuration[i]); } | ||||
|             ImGui::Text("Mouse clicked:");  for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseClicked(i))          { ImGui::SameLine(); ImGui::Text("b%d", i); } | ||||
|             ImGui::Text("Mouse dblclick:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseDoubleClicked(i))    { ImGui::SameLine(); ImGui::Text("b%d", i); } | ||||
|             ImGui::Text("Mouse released:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseReleased(i))         { ImGui::SameLine(); ImGui::Text("b%d", i); } | ||||
|             ImGui::Text("Mouse down:");     for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseDown(i))         { ImGui::SameLine(); ImGui::Text("b%d (%.02f secs)", i, io.MouseDownDuration[i]); } | ||||
|             ImGui::Text("Mouse clicked:");  for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseClicked(i))      { ImGui::SameLine(); ImGui::Text("b%d", i); } | ||||
|             ImGui::Text("Mouse dblclick:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseDoubleClicked(i)){ ImGui::SameLine(); ImGui::Text("b%d", i); } | ||||
|             ImGui::Text("Mouse released:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseReleased(i))     { ImGui::SameLine(); ImGui::Text("b%d", i); } | ||||
|             ImGui::Text("Mouse wheel: %.1f", io.MouseWheel); | ||||
|             ImGui::Text("Pen Pressure: %.1f", io.PenPressure); // Note: currently unused | ||||
|             ImGui::TreePop(); | ||||
|         } | ||||
|  | ||||
|             ImGui::Text("Keys down:");      for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (io.KeysDownDuration[i] >= 0.0f)     { ImGui::SameLine(); ImGui::Text("%d (0x%X) (%.02f secs)", i, i, io.KeysDownDuration[i]); } | ||||
|             ImGui::Text("Keys pressed:");   for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyPressed(i))             { ImGui::SameLine(); ImGui::Text("%d (0x%X)", i, i); } | ||||
|             ImGui::Text("Keys release:");   for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyReleased(i))            { ImGui::SameLine(); ImGui::Text("%d (0x%X)", i, i); } | ||||
|         // Display Keyboard/Mouse state | ||||
|         if (ImGui::TreeNode("Keyboard & Navigation State")) | ||||
|         { | ||||
|             ImGui::Text("Keys down:");          for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyDown(i))        { ImGui::SameLine(); ImGui::Text("%d (0x%X) (%.02f secs)", i, i, io.KeysDownDuration[i]); } | ||||
|             ImGui::Text("Keys pressed:");       for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyPressed(i))     { ImGui::SameLine(); ImGui::Text("%d (0x%X)", i, i); } | ||||
|             ImGui::Text("Keys release:");       for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyReleased(i))    { ImGui::SameLine(); ImGui::Text("%d (0x%X)", i, i); } | ||||
|             ImGui::Text("Keys mods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : ""); | ||||
|             ImGui::Text("Chars queue:");    for (int i = 0; i < io.InputQueueCharacters.Size; i++) { ImWchar c = io.InputQueueCharacters[i]; ImGui::SameLine();  ImGui::Text("\'%c\' (0x%04X)", (c > ' ' && c <= 255) ? (char)c : '?', c); } // FIXME: We should convert 'c' to UTF-8 here but the functions are not public. | ||||
|             ImGui::Text("Chars queue:");        for (int i = 0; i < io.InputQueueCharacters.Size; i++) { ImWchar c = io.InputQueueCharacters[i]; ImGui::SameLine();  ImGui::Text("\'%c\' (0x%04X)", (c > ' ' && c <= 255) ? (char)c : '?', c); } // FIXME: We should convert 'c' to UTF-8 here but the functions are not public. | ||||
|  | ||||
|             ImGui::Text("NavInputs down:");     for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputs[i] > 0.0f)              { ImGui::SameLine(); ImGui::Text("[%d] %.2f", i, io.NavInputs[i]); } | ||||
|             ImGui::Text("NavInputs down:");     for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputs[i] > 0.0f)              { ImGui::SameLine(); ImGui::Text("[%d] %.2f (%.02f secs)", i, io.NavInputs[i], io.NavInputsDownDuration[i]); } | ||||
|             ImGui::Text("NavInputs pressed:");  for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputsDownDuration[i] == 0.0f) { ImGui::SameLine(); ImGui::Text("[%d]", i); } | ||||
|             ImGui::Text("NavInputs duration:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputsDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("[%d] %.2f", i, io.NavInputsDownDuration[i]); } | ||||
|  | ||||
|             ImGui::Button("Hovering me sets the\nkeyboard capture flag"); | ||||
|             if (ImGui::IsItemHovered()) | ||||
| @@ -5491,7 +5506,6 @@ static void ShowDemoWindowMisc() | ||||
|             ImGui::Button("Holding me clears the\nthe keyboard capture flag"); | ||||
|             if (ImGui::IsItemActive()) | ||||
|                 ImGui::CaptureKeyboardFromApp(false); | ||||
|  | ||||
|             ImGui::TreePop(); | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -1467,7 +1467,7 @@ void ImDrawList::AddImageRounded(ImTextureID user_texture_id, const ImVec2& p_mi | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     const bool push_texture_id = _TextureIdStack.empty() || user_texture_id != _TextureIdStack.back(); | ||||
|     const bool push_texture_id = user_texture_id != _CmdHeader.TextureId; | ||||
|     if (push_texture_id) | ||||
|         PushTextureID(user_texture_id); | ||||
|  | ||||
|   | ||||
| @@ -226,6 +226,7 @@ namespace ImStb | ||||
| #define IM_NEWLINE                      "\n" | ||||
| #endif | ||||
| #define IM_TABSIZE                      (4) | ||||
| #define IM_MEMALIGN(_OFF,_ALIGN)        (((_OFF) + (_ALIGN - 1)) & ~(_ALIGN - 1))               // Memory align e.g. IM_ALIGN(0,4)=0, IM_ALIGN(1,4)=4, IM_ALIGN(4,4)=4, IM_ALIGN(5,4)=8 | ||||
| #define IM_F32_TO_INT8_UNBOUND(_VAL)    ((int)((_VAL) * 255.0f + ((_VAL)>=0 ? 0.5f : -0.5f)))   // Unsaturated, for display purpose | ||||
| #define IM_F32_TO_INT8_SAT(_VAL)        ((int)(ImSaturate(_VAL) * 255.0f + 0.5f))               // Saturated, always output 0..255 | ||||
| #define IM_FLOOR(_VAL)                  ((float)(int)(_VAL))                                    // ImFloor() is not inlined in MSVC debug builds | ||||
| @@ -557,20 +558,22 @@ struct ImSpan | ||||
|  | ||||
| // Helper: ImSpanAllocator<> | ||||
| // Facilitate storing multiple chunks into a single large block (the "arena") | ||||
| // - Usage: call Reserve() N times, allocate GetArenaSizeInBytes() worth, pass it to SetArenaBasePtr(), call GetSpan() N times to retrieve the aligned ranges. | ||||
| template<int CHUNKS> | ||||
| struct ImSpanAllocator | ||||
| { | ||||
|     char*   BasePtr; | ||||
|     int     TotalSize; | ||||
|     int     CurrSpan; | ||||
|     int     CurrOff; | ||||
|     int     CurrIdx; | ||||
|     int     Offsets[CHUNKS]; | ||||
|     int     Sizes[CHUNKS]; | ||||
|  | ||||
|     ImSpanAllocator()                               { memset(this, 0, sizeof(*this)); } | ||||
|     inline void  ReserveBytes(int n, size_t sz)     { IM_ASSERT(n == CurrSpan && n < CHUNKS); IM_UNUSED(n); Offsets[CurrSpan++] = TotalSize; TotalSize += (int)sz; } | ||||
|     inline int   GetArenaSizeInBytes()              { return TotalSize; } | ||||
|     inline void  Reserve(int n, size_t sz, int a=4) { IM_ASSERT(n == CurrIdx && n < CHUNKS); CurrOff = IM_MEMALIGN(CurrOff, a); Offsets[n] = CurrOff; Sizes[n] = (int)sz; CurrIdx++; CurrOff += (int)sz; } | ||||
|     inline int   GetArenaSizeInBytes()              { return CurrOff; } | ||||
|     inline void  SetArenaBasePtr(void* base_ptr)    { BasePtr = (char*)base_ptr; } | ||||
|     inline void* GetSpanPtrBegin(int n)             { IM_ASSERT(n >= 0 && n < CHUNKS && CurrSpan == CHUNKS); return (void*)(BasePtr + Offsets[n]); } | ||||
|     inline void* GetSpanPtrEnd(int n)               { IM_ASSERT(n >= 0 && n < CHUNKS && CurrSpan == CHUNKS); return (n + 1 < CHUNKS) ? BasePtr + Offsets[n + 1] : (void*)(BasePtr + TotalSize); } | ||||
|     inline void* GetSpanPtrBegin(int n)             { IM_ASSERT(n >= 0 && n < CHUNKS && CurrIdx == CHUNKS); return (void*)(BasePtr + Offsets[n]); } | ||||
|     inline void* GetSpanPtrEnd(int n)               { IM_ASSERT(n >= 0 && n < CHUNKS && CurrIdx == CHUNKS); return (void*)(BasePtr + Offsets[n] + Sizes[n]); } | ||||
|     template<typename T> | ||||
|     inline void  GetSpan(int n, ImSpan<T>* span)    { span->set((T*)GetSpanPtrBegin(n), (T*)GetSpanPtrEnd(n)); } | ||||
| }; | ||||
| @@ -604,7 +607,7 @@ struct IMGUI_API ImPool | ||||
| // Helper: ImChunkStream<> | ||||
| // Build and iterate a contiguous stream of variable-sized structures. | ||||
| // This is used by Settings to store persistent data while reducing allocation count. | ||||
| // We store the chunk size first, and align the final size on 4 bytes boundaries (this what the '(X + 3) & ~3' statement is for) | ||||
| // We store the chunk size first, and align the final size on 4 bytes boundaries. | ||||
| // The tedious/zealous amount of casting is to avoid -Wcast-align warnings. | ||||
| template<typename T> | ||||
| struct IMGUI_API ImChunkStream | ||||
| @@ -614,7 +617,7 @@ struct IMGUI_API ImChunkStream | ||||
|     void    clear()                     { Buf.clear(); } | ||||
|     bool    empty() const               { return Buf.Size == 0; } | ||||
|     int     size() const                { return Buf.Size; } | ||||
|     T*      alloc_chunk(size_t sz)      { size_t HDR_SZ = 4; sz = ((HDR_SZ + sz) + 3u) & ~3u; int off = Buf.Size; Buf.resize(off + (int)sz); ((int*)(void*)(Buf.Data + off))[0] = (int)sz; return (T*)(void*)(Buf.Data + off + (int)HDR_SZ); } | ||||
|     T*      alloc_chunk(size_t sz)      { size_t HDR_SZ = 4; sz = IM_MEMALIGN(HDR_SZ + sz, 4u); int off = Buf.Size; Buf.resize(off + (int)sz); ((int*)(void*)(Buf.Data + off))[0] = (int)sz; return (T*)(void*)(Buf.Data + off + (int)HDR_SZ); } | ||||
|     T*      begin()                     { size_t HDR_SZ = 4; if (!Buf.Data) return NULL; return (T*)(void*)(Buf.Data + HDR_SZ); } | ||||
|     T*      next_chunk(T* p)            { size_t HDR_SZ = 4; IM_ASSERT(p >= begin() && p < end()); p = (T*)(void*)((char*)(void*)p + chunk_size(p)); if (p == (T*)(void*)((char*)end() + HDR_SZ)) return (T*)0; IM_ASSERT(p < end()); return p; } | ||||
|     int     chunk_size(const T* p)      { return ((const int*)p)[-1]; } | ||||
| @@ -706,12 +709,13 @@ enum ImGuiItemStatusFlags_ | ||||
| { | ||||
|     ImGuiItemStatusFlags_None               = 0, | ||||
|     ImGuiItemStatusFlags_HoveredRect        = 1 << 0, | ||||
|     ImGuiItemStatusFlags_HasDisplayRect     = 1 << 1, | ||||
|     ImGuiItemStatusFlags_HasDisplayRect     = 1 << 1,   // LastItemDisplayRect is valid | ||||
|     ImGuiItemStatusFlags_Edited             = 1 << 2,   // Value exposed by item was edited in the current frame (should match the bool return value of most widgets) | ||||
|     ImGuiItemStatusFlags_ToggledSelection   = 1 << 3,   // Set when Selectable(), TreeNode() reports toggling a selection. We can't report "Selected" because reporting the change allows us to handle clipping with less issues. | ||||
|     ImGuiItemStatusFlags_ToggledOpen        = 1 << 4,   // Set when TreeNode() reports toggling their open state. | ||||
|     ImGuiItemStatusFlags_HasDeactivated     = 1 << 5,   // Set if the widget/group is able to provide data for the ImGuiItemStatusFlags_Deactivated flag. | ||||
|     ImGuiItemStatusFlags_Deactivated        = 1 << 6    // Only valid if ImGuiItemStatusFlags_HasDeactivated is set. | ||||
|     ImGuiItemStatusFlags_Deactivated        = 1 << 6,   // Only valid if ImGuiItemStatusFlags_HasDeactivated is set. | ||||
|     ImGuiItemStatusFlags_HoveredWindow      = 1 << 7    // Override the HoveredWindow test to allow cross-window hover testing. | ||||
|  | ||||
| #ifdef IMGUI_ENABLE_TEST_ENGINE | ||||
|     , // [imgui_tests only] | ||||
| @@ -933,7 +937,7 @@ struct ImGuiStyleMod | ||||
| }; | ||||
|  | ||||
| // Stacked storage data for BeginGroup()/EndGroup() | ||||
| struct ImGuiGroupData | ||||
| struct IMGUI_API ImGuiGroupData | ||||
| { | ||||
|     ImGuiID     WindowID; | ||||
|     ImVec2      BackupCursorPos; | ||||
| @@ -944,6 +948,7 @@ struct ImGuiGroupData | ||||
|     float       BackupCurrLineTextBaseOffset; | ||||
|     ImGuiID     BackupActiveIdIsAlive; | ||||
|     bool        BackupActiveIdPreviousFrameIsAlive; | ||||
|     bool        BackupHoveredIdIsAlive; | ||||
|     bool        EmitItem; | ||||
| }; | ||||
|  | ||||
| @@ -1476,7 +1481,6 @@ struct ImGuiContext | ||||
|     int                     WindowsActiveCount;                 // Number of unique windows submitted by frame | ||||
|     ImGuiWindow*            CurrentWindow;                      // Window being drawn into | ||||
|     ImGuiWindow*            HoveredWindow;                      // Window the mouse is hovering. Will typically catch mouse inputs. | ||||
|     ImGuiWindow*            HoveredRootWindow;                  // == HoveredWindow ? HoveredWindow->RootWindow : NULL, merely a shortcut to avoid null test in some situation. | ||||
|     ImGuiWindow*            HoveredWindowUnderMovingWindow;     // Hovered window ignoring MovingWindow. Only set if MovingWindow is set. | ||||
|     ImGuiDockNode*          HoveredDockNode;                    // Hovered dock node. | ||||
|     ImGuiWindow*            MovingWindow;                       // Track the window we clicked on (in order to preserve focus). The actual window that is moved is generally MovingWindow->RootWindow. | ||||
| @@ -1720,7 +1724,6 @@ struct ImGuiContext | ||||
|         WindowsActiveCount = 0; | ||||
|         CurrentWindow = NULL; | ||||
|         HoveredWindow = NULL; | ||||
|         HoveredRootWindow = NULL; | ||||
|         HoveredWindowUnderMovingWindow = NULL; | ||||
|         HoveredDockNode = NULL; | ||||
|         MovingWindow = NULL; | ||||
|   | ||||
| @@ -538,9 +538,9 @@ void ImGui::TableBeginInitMemory(ImGuiTable* table, int columns_count) | ||||
| { | ||||
|     // Allocate single buffer for our arrays | ||||
|     ImSpanAllocator<3> span_allocator; | ||||
|     span_allocator.ReserveBytes(0, columns_count * sizeof(ImGuiTableColumn)); | ||||
|     span_allocator.ReserveBytes(1, columns_count * sizeof(ImGuiTableColumnIdx)); | ||||
|     span_allocator.ReserveBytes(2, columns_count * sizeof(ImGuiTableCellData)); | ||||
|     span_allocator.Reserve(0, columns_count * sizeof(ImGuiTableColumn)); | ||||
|     span_allocator.Reserve(1, columns_count * sizeof(ImGuiTableColumnIdx)); | ||||
|     span_allocator.Reserve(2, columns_count * sizeof(ImGuiTableCellData), 4); | ||||
|     table->RawData = IM_ALLOC(span_allocator.GetArenaSizeInBytes()); | ||||
|     memset(table->RawData, 0, span_allocator.GetArenaSizeInBytes()); | ||||
|     span_allocator.SetArenaBasePtr(table->RawData); | ||||
|   | ||||
| @@ -500,7 +500,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool | ||||
|         flags |= ImGuiButtonFlags_PressedOnDefault_; | ||||
|  | ||||
|     ImGuiWindow* backup_hovered_window = g.HoveredWindow; | ||||
|     const bool flatten_hovered_children = (flags & ImGuiButtonFlags_FlattenChildren) && g.HoveredRootWindow == window->RootWindow; | ||||
|     const bool flatten_hovered_children = (flags & ImGuiButtonFlags_FlattenChildren) && g.HoveredWindow && g.HoveredWindow->RootWindow == window->RootWindow; | ||||
|     if (flatten_hovered_children) | ||||
|         g.HoveredWindow = window; | ||||
|  | ||||
|   | ||||
| @@ -6,6 +6,7 @@ | ||||
|  | ||||
| // CHANGELOG | ||||
| // (minor and older changes stripped away, please see git history for details) | ||||
| //  2021/03/05: added ImGuiFreeTypeBuilderFlags_Bitmap to load bitmap glyphs. | ||||
| //  2021/03/02: set 'atlas->TexPixelsUseColors = true' to help some backends with deciding of a prefered texture format. | ||||
| //  2021/01/28: added support for color-layered glyphs via ImGuiFreeTypeBuilderFlags_LoadColor (require Freetype 2.10+). | ||||
| //  2021/01/26: simplified integration by using '#define IMGUI_ENABLE_FREETYPE'. | ||||
| @@ -152,12 +153,13 @@ namespace | ||||
|         if (error != 0) | ||||
|             return false; | ||||
|  | ||||
|         memset(&Info, 0, sizeof(Info)); | ||||
|         SetPixelHeight((uint32_t)cfg.SizePixels); | ||||
|  | ||||
|         // Convert to FreeType flags (NB: Bold and Oblique are processed separately) | ||||
|         UserFlags = cfg.FontBuilderFlags | extra_font_builder_flags; | ||||
|         LoadFlags = FT_LOAD_NO_BITMAP; | ||||
|  | ||||
|         LoadFlags = 0; | ||||
|         if ((UserFlags & ImGuiFreeTypeBuilderFlags_Bitmap) == 0) | ||||
|             LoadFlags |= FT_LOAD_NO_BITMAP; | ||||
|  | ||||
|         if (UserFlags & ImGuiFreeTypeBuilderFlags_NoHinting) | ||||
|             LoadFlags |= FT_LOAD_NO_HINTING; | ||||
|         if (UserFlags & ImGuiFreeTypeBuilderFlags_NoAutoHint) | ||||
| @@ -179,6 +181,9 @@ namespace | ||||
|         if (UserFlags & ImGuiFreeTypeBuilderFlags_LoadColor) | ||||
|             LoadFlags |= FT_LOAD_COLOR; | ||||
|  | ||||
|         memset(&Info, 0, sizeof(Info)); | ||||
|         SetPixelHeight((uint32_t)cfg.SizePixels); | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
| @@ -197,7 +202,7 @@ namespace | ||||
|         // is a maximum height of an any given glyph, i.e. it's the sum of font's ascender and descender. Seems strange to me. | ||||
|         // NB: FT_Set_Pixel_Sizes() doesn't seem to get us the same result. | ||||
|         FT_Size_RequestRec req; | ||||
|         req.type = FT_SIZE_REQUEST_TYPE_REAL_DIM; | ||||
|         req.type = (UserFlags & ImGuiFreeTypeBuilderFlags_Bitmap) ? FT_SIZE_REQUEST_TYPE_NOMINAL : FT_SIZE_REQUEST_TYPE_REAL_DIM; | ||||
|         req.width = 0; | ||||
|         req.height = (uint32_t)pixel_height * 64; | ||||
|         req.horiResolution = 0; | ||||
| @@ -225,7 +230,7 @@ namespace | ||||
|  | ||||
|         // Need an outline for this to work | ||||
|         FT_GlyphSlot slot = Face->glyph; | ||||
|         IM_ASSERT(slot->format == FT_GLYPH_FORMAT_OUTLINE); | ||||
|         IM_ASSERT(slot->format == FT_GLYPH_FORMAT_OUTLINE || slot->format == FT_GLYPH_FORMAT_BITMAP); | ||||
|  | ||||
|         // Apply convenience transform (this is not picking from real "Bold"/"Italic" fonts! Merely applying FreeType helper transform. Oblique == Slanting) | ||||
|         if (UserFlags & ImGuiFreeTypeBuilderFlags_Bold) | ||||
|   | ||||
| @@ -26,7 +26,8 @@ enum ImGuiFreeTypeBuilderFlags | ||||
|     ImGuiFreeTypeBuilderFlags_Bold          = 1 << 5,   // Styling: Should we artificially embolden the font? | ||||
|     ImGuiFreeTypeBuilderFlags_Oblique       = 1 << 6,   // Styling: Should we slant the font, emulating italic style? | ||||
|     ImGuiFreeTypeBuilderFlags_Monochrome    = 1 << 7,   // Disable anti-aliasing. Combine this with MonoHinting for best results! | ||||
|     ImGuiFreeTypeBuilderFlags_LoadColor     = 1 << 8    // Enable FreeType color-layered glyphs | ||||
|     ImGuiFreeTypeBuilderFlags_LoadColor     = 1 << 8,   // Enable FreeType color-layered glyphs | ||||
|     ImGuiFreeTypeBuilderFlags_Bitmap        = 1 << 9    // Enable FreeType bitmap glyphs | ||||
| }; | ||||
|  | ||||
| namespace ImGuiFreeType | ||||
|   | ||||
		Reference in New Issue
	
	Block a user