mirror of
				https://github.com/ocornut/imgui.git
				synced 2025-10-26 12:27:30 +00:00 
			
		
		
		
	Merge branch 'master' into docking + incl add wd->Pipeline in ImGui_ImplVulkan_RenderDrawData platform code (#3455, #3459)
This commit is contained in:
		| @@ -109,14 +109,21 @@ Other Changes: | |||||||
| - Window: Fixed using non-zero pivot in SetNextWindowPos() when the window is collapsed. (#3433) | - Window: Fixed using non-zero pivot in SetNextWindowPos() when the window is collapsed. (#3433) | ||||||
| - Nav: Fixed navigation resuming on first visible item when using gamepad. [@rokups] | - Nav: Fixed navigation resuming on first visible item when using gamepad. [@rokups] | ||||||
| - Nav: Fixed using Alt to toggle the Menu layer when inside a Modal window. (#787) | - Nav: Fixed using Alt to toggle the Menu layer when inside a Modal window. (#787) | ||||||
|  | - Scrolling: Fixed SetScrollHere functions edge snapping when called during a frame where ContentSize | ||||||
|  |   is changing (issue introduced in 1.78). (#3452). | ||||||
| - InputText: Added selection helpers in ImGuiInputTextCallbackData(). | - InputText: Added selection helpers in ImGuiInputTextCallbackData(). | ||||||
| - InputText: Added ImGuiInputTextFlags_CallbackEdit to modify internally owned buffer after an edit. | - InputText: Added ImGuiInputTextFlags_CallbackEdit to modify internally owned buffer after an edit. | ||||||
|   (note that InputText() already returns true on edit, the callback is useful mainly to manipulate the |   (note that InputText() already returns true on edit, the callback is useful mainly to manipulate the | ||||||
|   underlying buffer while focus is active). |   underlying buffer while focus is active). | ||||||
| - InputText: Fixed using ImGuiInputTextFlags_Password with InputTextMultiline(). (#3427, #3428) | - InputText: Fixed using ImGuiInputTextFlags_Password with InputTextMultiline(). (#3427, #3428) | ||||||
|   It is a rather unusual or useless combination of features but no reason it shouldn't work! |   It is a rather unusual or useless combination of features but no reason it shouldn't work! | ||||||
|  | - InputText: Fixed minor scrolling glitch when erasing trailing lines in InputTextMultiline(). | ||||||
|  | - InputText: Fixed cursor being partially covered after using Ctrl+End key. | ||||||
|  | - InputText: Fixed callback's helper DeleteChars() function when cursor is inside the deleted block. (#3454). | ||||||
| - DragFloat, DragScalar: Fixed ImGuiSliderFlags_ClampOnInput not being honored in the special case | - DragFloat, DragScalar: Fixed ImGuiSliderFlags_ClampOnInput not being honored in the special case | ||||||
|   where v_min == v_max. (#3361) |   where v_min == v_max. (#3361) | ||||||
|  | - SliderInt, SliderScalar: Fixed reaching of maximum value with inverted integer min/max ranges, both | ||||||
|  |   with signed and unsigned types. Added reverse Sliders to Demo. (#3432, #3449) [@rokups] | ||||||
| - BeginMenuBar: Fixed minor bug where CursorPosMax gets pushed to CursorPos prior to calling BeginMenuBar(), | - BeginMenuBar: Fixed minor bug where CursorPosMax gets pushed to CursorPos prior to calling BeginMenuBar(), | ||||||
|   so e.g. calling the function at the end of a window would often add +ItemSpacing.y to scrolling range. |   so e.g. calling the function at the end of a window would often add +ItemSpacing.y to scrolling range. | ||||||
| - TreeNode, CollapsingHeader: Made clicking on arrow toggle toggle the open state on the Mouse Down event | - TreeNode, CollapsingHeader: Made clicking on arrow toggle toggle the open state on the Mouse Down event | ||||||
| @@ -128,7 +135,11 @@ Other Changes: | |||||||
|   tabs reordered in the tab list popup. [@Xipiryon] |   tabs reordered in the tab list popup. [@Xipiryon] | ||||||
| - Metrics: Various tweaks, listing windows front-to-back, greying inactive items when possible. | - Metrics: Various tweaks, listing windows front-to-back, greying inactive items when possible. | ||||||
| - Demo: Add simple InputText() callbacks demo (aside from the more elaborate ones in 'Examples->Console'). | - Demo: Add simple InputText() callbacks demo (aside from the more elaborate ones in 'Examples->Console'). | ||||||
|  | - Backends: Vulkan: Some internal refactor aimed at allowing multi-viewport feature to create their | ||||||
|  |   own render pass. (#3455, #3459) [@FunMiles] | ||||||
| - Examples: Vulkan: Reworked buffer resize handling, fix for Linux/X11. (#3390, #2626) [@RoryO] | - Examples: Vulkan: Reworked buffer resize handling, fix for Linux/X11. (#3390, #2626) [@RoryO] | ||||||
|  | - Examples: Vulkan: Switch validation layer to use "VK_LAYER_KHRONOS_validation" instead of | ||||||
|  |   "VK_LAYER_LUNARG_standard_validation" which is deprecated (#3459) [@FunMiles] | ||||||
|  |  | ||||||
|  |  | ||||||
| ----------------------------------------------------------------------- | ----------------------------------------------------------------------- | ||||||
|   | |||||||
| @@ -28,9 +28,11 @@ set(IMGUI_DIR ../../) | |||||||
| include_directories(${IMGUI_DIR} ..) | include_directories(${IMGUI_DIR} ..) | ||||||
|  |  | ||||||
| # Libraries | # Libraries | ||||||
| find_library(VULKAN_LIBRARY | find_package(Vulkan REQUIRED) | ||||||
|   NAMES vulkan vulkan-1) | #find_library(VULKAN_LIBRARY | ||||||
| set(LIBRARIES "glfw;${VULKAN_LIBRARY}") |   #NAMES vulkan vulkan-1) | ||||||
|  | #set(LIBRARIES "glfw;${VULKAN_LIBRARY}") | ||||||
|  | set(LIBRARIES "glfw;Vulkan::Vulkan") | ||||||
|  |  | ||||||
| # Use vulkan headers from glfw: | # Use vulkan headers from glfw: | ||||||
| include_directories(${GLFW_DIR}/deps) | include_directories(${GLFW_DIR}/deps) | ||||||
|   | |||||||
| @@ -72,10 +72,9 @@ static void SetupVulkan(const char** extensions, uint32_t extensions_count) | |||||||
|         create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; |         create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; | ||||||
|         create_info.enabledExtensionCount = extensions_count; |         create_info.enabledExtensionCount = extensions_count; | ||||||
|         create_info.ppEnabledExtensionNames = extensions; |         create_info.ppEnabledExtensionNames = extensions; | ||||||
|  |  | ||||||
| #ifdef IMGUI_VULKAN_DEBUG_REPORT | #ifdef IMGUI_VULKAN_DEBUG_REPORT | ||||||
|         // Enabling multiple validation layers grouped as LunarG standard validation |         // Enabling validation layers | ||||||
|         const char* layers[] = { "VK_LAYER_LUNARG_standard_validation" }; |         const char* layers[] = { "VK_LAYER_KHRONOS_validation" }; | ||||||
|         create_info.enabledLayerCount = 1; |         create_info.enabledLayerCount = 1; | ||||||
|         create_info.ppEnabledLayerNames = layers; |         create_info.ppEnabledLayerNames = layers; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -99,6 +99,8 @@ int main(int, char**) | |||||||
|             ImGui_ImplSDL2_ProcessEvent(&event); |             ImGui_ImplSDL2_ProcessEvent(&event); | ||||||
|             if (event.type == SDL_QUIT) |             if (event.type == SDL_QUIT) | ||||||
|                 done = true; |                 done = true; | ||||||
|  |             if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window)) | ||||||
|  |                 done = true; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // Start the Dear ImGui frame |         // Start the Dear ImGui frame | ||||||
|   | |||||||
| @@ -64,10 +64,9 @@ static void SetupVulkan(const char** extensions, uint32_t extensions_count) | |||||||
|         create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; |         create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; | ||||||
|         create_info.enabledExtensionCount = extensions_count; |         create_info.enabledExtensionCount = extensions_count; | ||||||
|         create_info.ppEnabledExtensionNames = extensions; |         create_info.ppEnabledExtensionNames = extensions; | ||||||
|  |  | ||||||
| #ifdef IMGUI_VULKAN_DEBUG_REPORT | #ifdef IMGUI_VULKAN_DEBUG_REPORT | ||||||
|         // Enabling multiple validation layers grouped as LunarG standard validation |         // Enabling validation layers | ||||||
|         const char* layers[] = { "VK_LAYER_LUNARG_standard_validation" }; |         const char* layers[] = { "VK_LAYER_KHRONOS_validation" }; | ||||||
|         create_info.enabledLayerCount = 1; |         create_info.enabledLayerCount = 1; | ||||||
|         create_info.ppEnabledLayerNames = layers; |         create_info.ppEnabledLayerNames = layers; | ||||||
|  |  | ||||||
| @@ -467,6 +466,8 @@ int main(int, char**) | |||||||
|             ImGui_ImplSDL2_ProcessEvent(&event); |             ImGui_ImplSDL2_ProcessEvent(&event); | ||||||
|             if (event.type == SDL_QUIT) |             if (event.type == SDL_QUIT) | ||||||
|                 done = true; |                 done = true; | ||||||
|  |             if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window)) | ||||||
|  |                 done = true; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // Resize swap chain? |         // Resize swap chain? | ||||||
|   | |||||||
| @@ -23,6 +23,7 @@ | |||||||
|  |  | ||||||
| // CHANGELOG | // CHANGELOG | ||||||
| // (minor and older changes stripped away, please see git history for details) | // (minor and older changes stripped away, please see git history for details) | ||||||
|  | //  2020-09-07: Vulkan: Added VkPipeline parameter to ImGui_ImplVulkan_RenderDrawData (default to one passed to ImGui_ImplVulkan_Init). | ||||||
| //  2020-05-04: Vulkan: Fixed crash if initial frame has no vertices. | //  2020-05-04: Vulkan: Fixed crash if initial frame has no vertices. | ||||||
| //  2020-04-26: Vulkan: Fixed edge case where render callbacks wouldn't be called if the ImDrawData didn't have vertices. | //  2020-04-26: Vulkan: Fixed edge case where render callbacks wouldn't be called if the ImDrawData didn't have vertices. | ||||||
| //  2019-08-01: Vulkan: Added support for specifying multisample count. Set ImGui_ImplVulkan_InitInfo::MSAASamples to one of the VkSampleCountFlagBits values to use, default is non-multisampled as before. | //  2019-08-01: Vulkan: Added support for specifying multisample count. Set ImGui_ImplVulkan_InitInfo::MSAASamples to one of the VkSampleCountFlagBits values to use, default is non-multisampled as before. | ||||||
| @@ -93,6 +94,8 @@ static VkDescriptorSetLayout    g_DescriptorSetLayout = VK_NULL_HANDLE; | |||||||
| static VkPipelineLayout         g_PipelineLayout = VK_NULL_HANDLE; | static VkPipelineLayout         g_PipelineLayout = VK_NULL_HANDLE; | ||||||
| static VkDescriptorSet          g_DescriptorSet = VK_NULL_HANDLE; | static VkDescriptorSet          g_DescriptorSet = VK_NULL_HANDLE; | ||||||
| static VkPipeline               g_Pipeline = VK_NULL_HANDLE; | static VkPipeline               g_Pipeline = VK_NULL_HANDLE; | ||||||
|  | static VkShaderModule           g_ShaderModuleVert; | ||||||
|  | static VkShaderModule           g_ShaderModuleFrag; | ||||||
|  |  | ||||||
| // Font data | // Font data | ||||||
| static VkSampler                g_FontSampler = VK_NULL_HANDLE; | static VkSampler                g_FontSampler = VK_NULL_HANDLE; | ||||||
| @@ -281,11 +284,11 @@ static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory | |||||||
|     p_buffer_size = new_size; |     p_buffer_size = new_size; | ||||||
| } | } | ||||||
|  |  | ||||||
| static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkCommandBuffer command_buffer, ImGui_ImplVulkanH_FrameRenderBuffers* rb, int fb_width, int fb_height) | static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkPipeline pipeline, VkCommandBuffer command_buffer, ImGui_ImplVulkanH_FrameRenderBuffers* rb, int fb_width, int fb_height) | ||||||
| { | { | ||||||
|     // Bind pipeline and descriptor sets: |     // Bind pipeline and descriptor sets: | ||||||
|     { |     { | ||||||
|         vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_Pipeline); |         vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); | ||||||
|         VkDescriptorSet desc_set[1] = { g_DescriptorSet }; |         VkDescriptorSet desc_set[1] = { g_DescriptorSet }; | ||||||
|         vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_PipelineLayout, 0, 1, desc_set, 0, NULL); |         vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_PipelineLayout, 0, 1, desc_set, 0, NULL); | ||||||
|     } |     } | ||||||
| @@ -327,7 +330,7 @@ static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkCommandBu | |||||||
|  |  | ||||||
| // Render function | // Render function | ||||||
| // (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) | // (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) | ||||||
| void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer) | 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) |     // 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_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x); | ||||||
| @@ -336,6 +339,8 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm | |||||||
|         return; |         return; | ||||||
|  |  | ||||||
|     ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo; |     ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo; | ||||||
|  |     if (pipeline == VK_NULL_HANDLE) | ||||||
|  |         pipeline = g_Pipeline; | ||||||
|  |  | ||||||
|     // Allocate array to store enough vertex/index buffers. Each unique viewport gets its own storage. |     // Allocate array to store enough vertex/index buffers. Each unique viewport gets its own storage. | ||||||
|     ImGuiViewportDataVulkan* viewport_renderer_data = (ImGuiViewportDataVulkan*)draw_data->OwnerViewport->RendererUserData; |     ImGuiViewportDataVulkan* viewport_renderer_data = (ImGuiViewportDataVulkan*)draw_data->OwnerViewport->RendererUserData; | ||||||
| @@ -391,7 +396,7 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Setup desired Vulkan state |     // Setup desired Vulkan state | ||||||
|     ImGui_ImplVulkan_SetupRenderState(draw_data, command_buffer, rb, fb_width, fb_height); |     ImGui_ImplVulkan_SetupRenderState(draw_data, pipeline, command_buffer, rb, fb_width, fb_height); | ||||||
|  |  | ||||||
|     // Will project scissor/clipping rectangles into framebuffer space |     // Will project scissor/clipping rectangles into framebuffer space | ||||||
|     ImVec2 clip_off = draw_data->DisplayPos;         // (0,0) unless using multi-viewports |     ImVec2 clip_off = draw_data->DisplayPos;         // (0,0) unless using multi-viewports | ||||||
| @@ -412,7 +417,7 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm | |||||||
|                 // User callback, registered via ImDrawList::AddCallback() |                 // User callback, registered via ImDrawList::AddCallback() | ||||||
|                 // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) |                 // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) | ||||||
|                 if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) |                 if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) | ||||||
|                     ImGui_ImplVulkan_SetupRenderState(draw_data, command_buffer, rb, fb_width, fb_height); |                     ImGui_ImplVulkan_SetupRenderState(draw_data, pipeline, command_buffer, rb, fb_width, fb_height); | ||||||
|                 else |                 else | ||||||
|                     pcmd->UserCallback(cmd_list, pcmd); |                     pcmd->UserCallback(cmd_list, pcmd); | ||||||
|             } |             } | ||||||
| @@ -603,6 +608,195 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer) | |||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static void ImGui_ImplVulkan_CreateShaderModules(VkDevice device, const VkAllocationCallbacks* allocator) | ||||||
|  | { | ||||||
|  |     // Create the shader modules | ||||||
|  |     if (g_ShaderModuleVert == NULL) | ||||||
|  |     { | ||||||
|  |         VkShaderModuleCreateInfo vert_info = {}; | ||||||
|  |         vert_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; | ||||||
|  |         vert_info.codeSize = sizeof(__glsl_shader_vert_spv); | ||||||
|  |         vert_info.pCode = (uint32_t*)__glsl_shader_vert_spv; | ||||||
|  |         VkResult err = vkCreateShaderModule(device, &vert_info, allocator, &g_ShaderModuleVert); | ||||||
|  |         check_vk_result(err); | ||||||
|  |     } | ||||||
|  |     if (g_ShaderModuleFrag == NULL) | ||||||
|  |     { | ||||||
|  |         VkShaderModuleCreateInfo frag_info = {}; | ||||||
|  |         frag_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; | ||||||
|  |         frag_info.codeSize = sizeof(__glsl_shader_frag_spv); | ||||||
|  |         frag_info.pCode = (uint32_t*)__glsl_shader_frag_spv; | ||||||
|  |         VkResult err = vkCreateShaderModule(device, &frag_info, allocator, &g_ShaderModuleFrag); | ||||||
|  |         check_vk_result(err); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void ImGui_ImplVulkan_CreateFontSampler(VkDevice device, const VkAllocationCallbacks* allocator) | ||||||
|  | { | ||||||
|  |     if (g_FontSampler) | ||||||
|  |         return; | ||||||
|  |  | ||||||
|  |     VkSamplerCreateInfo info = {}; | ||||||
|  |     info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; | ||||||
|  |     info.magFilter = VK_FILTER_LINEAR; | ||||||
|  |     info.minFilter = VK_FILTER_LINEAR; | ||||||
|  |     info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; | ||||||
|  |     info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; | ||||||
|  |     info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; | ||||||
|  |     info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; | ||||||
|  |     info.minLod = -1000; | ||||||
|  |     info.maxLod = 1000; | ||||||
|  |     info.maxAnisotropy = 1.0f; | ||||||
|  |     VkResult err = vkCreateSampler(device, &info, allocator, &g_FontSampler); | ||||||
|  |     check_vk_result(err); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void ImGui_ImplVulkan_CreateDescriptorSetLayout(VkDevice device, const VkAllocationCallbacks* allocator) | ||||||
|  | { | ||||||
|  |     if (g_DescriptorSetLayout) | ||||||
|  |         return; | ||||||
|  |  | ||||||
|  |     ImGui_ImplVulkan_CreateFontSampler(device, allocator); | ||||||
|  |     VkSampler sampler[1] = { g_FontSampler }; | ||||||
|  |     VkDescriptorSetLayoutBinding binding[1] = {}; | ||||||
|  |     binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; | ||||||
|  |     binding[0].descriptorCount = 1; | ||||||
|  |     binding[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; | ||||||
|  |     binding[0].pImmutableSamplers = sampler; | ||||||
|  |     VkDescriptorSetLayoutCreateInfo info = {}; | ||||||
|  |     info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; | ||||||
|  |     info.bindingCount = 1; | ||||||
|  |     info.pBindings = binding; | ||||||
|  |     VkResult err = vkCreateDescriptorSetLayout(device, &info, allocator, &g_DescriptorSetLayout); | ||||||
|  |     check_vk_result(err); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void ImGui_ImplVulkan_CreatePipelineLayout(VkDevice device, const VkAllocationCallbacks* allocator) | ||||||
|  | { | ||||||
|  |     if (g_PipelineLayout) | ||||||
|  |         return; | ||||||
|  |  | ||||||
|  |     // Constants: we are using 'vec2 offset' and 'vec2 scale' instead of a full 3d projection matrix | ||||||
|  |     ImGui_ImplVulkan_CreateDescriptorSetLayout(device, allocator); | ||||||
|  |     VkPushConstantRange push_constants[1] = {}; | ||||||
|  |     push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; | ||||||
|  |     push_constants[0].offset = sizeof(float) * 0; | ||||||
|  |     push_constants[0].size = sizeof(float) * 4; | ||||||
|  |     VkDescriptorSetLayout set_layout[1] = { g_DescriptorSetLayout }; | ||||||
|  |     VkPipelineLayoutCreateInfo layout_info = {}; | ||||||
|  |     layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; | ||||||
|  |     layout_info.setLayoutCount = 1; | ||||||
|  |     layout_info.pSetLayouts = set_layout; | ||||||
|  |     layout_info.pushConstantRangeCount = 1; | ||||||
|  |     layout_info.pPushConstantRanges = push_constants; | ||||||
|  |     VkResult  err = vkCreatePipelineLayout(device, &layout_info, allocator, &g_PipelineLayout); | ||||||
|  |     check_vk_result(err); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationCallbacks* allocator, VkPipelineCache pipelineCache, VkRenderPass renderPass, VkSampleCountFlagBits MSAASamples, VkPipeline *pipeline) | ||||||
|  | { | ||||||
|  |     ImGui_ImplVulkan_CreateShaderModules(device, allocator); | ||||||
|  |  | ||||||
|  |     VkPipelineShaderStageCreateInfo stage[2] = {}; | ||||||
|  |     stage[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; | ||||||
|  |     stage[0].stage = VK_SHADER_STAGE_VERTEX_BIT; | ||||||
|  |     stage[0].module = g_ShaderModuleVert; | ||||||
|  |     stage[0].pName = "main"; | ||||||
|  |     stage[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; | ||||||
|  |     stage[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; | ||||||
|  |     stage[1].module = g_ShaderModuleFrag; | ||||||
|  |     stage[1].pName = "main"; | ||||||
|  |  | ||||||
|  |     VkVertexInputBindingDescription binding_desc[1] = {}; | ||||||
|  |     binding_desc[0].stride = sizeof(ImDrawVert); | ||||||
|  |     binding_desc[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; | ||||||
|  |  | ||||||
|  |     VkVertexInputAttributeDescription attribute_desc[3] = {}; | ||||||
|  |     attribute_desc[0].location = 0; | ||||||
|  |     attribute_desc[0].binding = binding_desc[0].binding; | ||||||
|  |     attribute_desc[0].format = VK_FORMAT_R32G32_SFLOAT; | ||||||
|  |     attribute_desc[0].offset = IM_OFFSETOF(ImDrawVert, pos); | ||||||
|  |     attribute_desc[1].location = 1; | ||||||
|  |     attribute_desc[1].binding = binding_desc[0].binding; | ||||||
|  |     attribute_desc[1].format = VK_FORMAT_R32G32_SFLOAT; | ||||||
|  |     attribute_desc[1].offset = IM_OFFSETOF(ImDrawVert, uv); | ||||||
|  |     attribute_desc[2].location = 2; | ||||||
|  |     attribute_desc[2].binding = binding_desc[0].binding; | ||||||
|  |     attribute_desc[2].format = VK_FORMAT_R8G8B8A8_UNORM; | ||||||
|  |     attribute_desc[2].offset = IM_OFFSETOF(ImDrawVert, col); | ||||||
|  |  | ||||||
|  |     VkPipelineVertexInputStateCreateInfo vertex_info = {}; | ||||||
|  |     vertex_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; | ||||||
|  |     vertex_info.vertexBindingDescriptionCount = 1; | ||||||
|  |     vertex_info.pVertexBindingDescriptions = binding_desc; | ||||||
|  |     vertex_info.vertexAttributeDescriptionCount = 3; | ||||||
|  |     vertex_info.pVertexAttributeDescriptions = attribute_desc; | ||||||
|  |  | ||||||
|  |     VkPipelineInputAssemblyStateCreateInfo ia_info = {}; | ||||||
|  |     ia_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; | ||||||
|  |     ia_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; | ||||||
|  |  | ||||||
|  |     VkPipelineViewportStateCreateInfo viewport_info = {}; | ||||||
|  |     viewport_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; | ||||||
|  |     viewport_info.viewportCount = 1; | ||||||
|  |     viewport_info.scissorCount = 1; | ||||||
|  |  | ||||||
|  |     VkPipelineRasterizationStateCreateInfo raster_info = {}; | ||||||
|  |     raster_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; | ||||||
|  |     raster_info.polygonMode = VK_POLYGON_MODE_FILL; | ||||||
|  |     raster_info.cullMode = VK_CULL_MODE_NONE; | ||||||
|  |     raster_info.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; | ||||||
|  |     raster_info.lineWidth = 1.0f; | ||||||
|  |  | ||||||
|  |     VkPipelineMultisampleStateCreateInfo ms_info = {}; | ||||||
|  |     ms_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; | ||||||
|  |     ms_info.rasterizationSamples = (MSAASamples != 0) ? MSAASamples : VK_SAMPLE_COUNT_1_BIT; | ||||||
|  |  | ||||||
|  |     VkPipelineColorBlendAttachmentState color_attachment[1] = {}; | ||||||
|  |     color_attachment[0].blendEnable = VK_TRUE; | ||||||
|  |     color_attachment[0].srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; | ||||||
|  |     color_attachment[0].dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; | ||||||
|  |     color_attachment[0].colorBlendOp = VK_BLEND_OP_ADD; | ||||||
|  |     color_attachment[0].srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; | ||||||
|  |     color_attachment[0].dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; | ||||||
|  |     color_attachment[0].alphaBlendOp = VK_BLEND_OP_ADD; | ||||||
|  |     color_attachment[0].colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; | ||||||
|  |  | ||||||
|  |     VkPipelineDepthStencilStateCreateInfo depth_info = {}; | ||||||
|  |     depth_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; | ||||||
|  |  | ||||||
|  |     VkPipelineColorBlendStateCreateInfo blend_info = {}; | ||||||
|  |     blend_info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; | ||||||
|  |     blend_info.attachmentCount = 1; | ||||||
|  |     blend_info.pAttachments = color_attachment; | ||||||
|  |  | ||||||
|  |     VkDynamicState dynamic_states[2] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; | ||||||
|  |     VkPipelineDynamicStateCreateInfo dynamic_state = {}; | ||||||
|  |     dynamic_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; | ||||||
|  |     dynamic_state.dynamicStateCount = (uint32_t)IM_ARRAYSIZE(dynamic_states); | ||||||
|  |     dynamic_state.pDynamicStates = dynamic_states; | ||||||
|  |  | ||||||
|  |     ImGui_ImplVulkan_CreatePipelineLayout(device, allocator); | ||||||
|  |  | ||||||
|  |     VkGraphicsPipelineCreateInfo info = {}; | ||||||
|  |     info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; | ||||||
|  |     info.flags = g_PipelineCreateFlags; | ||||||
|  |     info.stageCount = 2; | ||||||
|  |     info.pStages = stage; | ||||||
|  |     info.pVertexInputState = &vertex_info; | ||||||
|  |     info.pInputAssemblyState = &ia_info; | ||||||
|  |     info.pViewportState = &viewport_info; | ||||||
|  |     info.pRasterizationState = &raster_info; | ||||||
|  |     info.pMultisampleState = &ms_info; | ||||||
|  |     info.pDepthStencilState = &depth_info; | ||||||
|  |     info.pColorBlendState = &blend_info; | ||||||
|  |     info.pDynamicState = &dynamic_state; | ||||||
|  |     info.layout = g_PipelineLayout; | ||||||
|  |     info.renderPass = renderPass; | ||||||
|  |     VkResult err = vkCreateGraphicsPipelines(device, pipelineCache, 1, &info, allocator, pipeline); | ||||||
|  |     check_vk_result(err); | ||||||
|  | } | ||||||
|  |  | ||||||
| bool ImGui_ImplVulkan_CreateDeviceObjects() | bool ImGui_ImplVulkan_CreateDeviceObjects() | ||||||
| { | { | ||||||
|     ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo; |     ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo; | ||||||
| @@ -688,105 +882,7 @@ bool ImGui_ImplVulkan_CreateDeviceObjects() | |||||||
|         check_vk_result(err); |         check_vk_result(err); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     VkPipelineShaderStageCreateInfo stage[2] = {}; |     ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, v->PipelineCache, g_RenderPass, v->MSAASamples, &g_Pipeline); | ||||||
|     stage[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; |  | ||||||
|     stage[0].stage = VK_SHADER_STAGE_VERTEX_BIT; |  | ||||||
|     stage[0].module = vert_module; |  | ||||||
|     stage[0].pName = "main"; |  | ||||||
|     stage[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; |  | ||||||
|     stage[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; |  | ||||||
|     stage[1].module = frag_module; |  | ||||||
|     stage[1].pName = "main"; |  | ||||||
|  |  | ||||||
|     VkVertexInputBindingDescription binding_desc[1] = {}; |  | ||||||
|     binding_desc[0].stride = sizeof(ImDrawVert); |  | ||||||
|     binding_desc[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; |  | ||||||
|  |  | ||||||
|     VkVertexInputAttributeDescription attribute_desc[3] = {}; |  | ||||||
|     attribute_desc[0].location = 0; |  | ||||||
|     attribute_desc[0].binding = binding_desc[0].binding; |  | ||||||
|     attribute_desc[0].format = VK_FORMAT_R32G32_SFLOAT; |  | ||||||
|     attribute_desc[0].offset = IM_OFFSETOF(ImDrawVert, pos); |  | ||||||
|     attribute_desc[1].location = 1; |  | ||||||
|     attribute_desc[1].binding = binding_desc[0].binding; |  | ||||||
|     attribute_desc[1].format = VK_FORMAT_R32G32_SFLOAT; |  | ||||||
|     attribute_desc[1].offset = IM_OFFSETOF(ImDrawVert, uv); |  | ||||||
|     attribute_desc[2].location = 2; |  | ||||||
|     attribute_desc[2].binding = binding_desc[0].binding; |  | ||||||
|     attribute_desc[2].format = VK_FORMAT_R8G8B8A8_UNORM; |  | ||||||
|     attribute_desc[2].offset = IM_OFFSETOF(ImDrawVert, col); |  | ||||||
|  |  | ||||||
|     VkPipelineVertexInputStateCreateInfo vertex_info = {}; |  | ||||||
|     vertex_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; |  | ||||||
|     vertex_info.vertexBindingDescriptionCount = 1; |  | ||||||
|     vertex_info.pVertexBindingDescriptions = binding_desc; |  | ||||||
|     vertex_info.vertexAttributeDescriptionCount = 3; |  | ||||||
|     vertex_info.pVertexAttributeDescriptions = attribute_desc; |  | ||||||
|  |  | ||||||
|     VkPipelineInputAssemblyStateCreateInfo ia_info = {}; |  | ||||||
|     ia_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; |  | ||||||
|     ia_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; |  | ||||||
|  |  | ||||||
|     VkPipelineViewportStateCreateInfo viewport_info = {}; |  | ||||||
|     viewport_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; |  | ||||||
|     viewport_info.viewportCount = 1; |  | ||||||
|     viewport_info.scissorCount = 1; |  | ||||||
|  |  | ||||||
|     VkPipelineRasterizationStateCreateInfo raster_info = {}; |  | ||||||
|     raster_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; |  | ||||||
|     raster_info.polygonMode = VK_POLYGON_MODE_FILL; |  | ||||||
|     raster_info.cullMode = VK_CULL_MODE_NONE; |  | ||||||
|     raster_info.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; |  | ||||||
|     raster_info.lineWidth = 1.0f; |  | ||||||
|  |  | ||||||
|     VkPipelineMultisampleStateCreateInfo ms_info = {}; |  | ||||||
|     ms_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; |  | ||||||
|     if (v->MSAASamples != 0) |  | ||||||
|         ms_info.rasterizationSamples = v->MSAASamples; |  | ||||||
|     else |  | ||||||
|         ms_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; |  | ||||||
|  |  | ||||||
|     VkPipelineColorBlendAttachmentState color_attachment[1] = {}; |  | ||||||
|     color_attachment[0].blendEnable = VK_TRUE; |  | ||||||
|     color_attachment[0].srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; |  | ||||||
|     color_attachment[0].dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; |  | ||||||
|     color_attachment[0].colorBlendOp = VK_BLEND_OP_ADD; |  | ||||||
|     color_attachment[0].srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; |  | ||||||
|     color_attachment[0].dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; |  | ||||||
|     color_attachment[0].alphaBlendOp = VK_BLEND_OP_ADD; |  | ||||||
|     color_attachment[0].colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; |  | ||||||
|  |  | ||||||
|     VkPipelineDepthStencilStateCreateInfo depth_info = {}; |  | ||||||
|     depth_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; |  | ||||||
|  |  | ||||||
|     VkPipelineColorBlendStateCreateInfo blend_info = {}; |  | ||||||
|     blend_info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; |  | ||||||
|     blend_info.attachmentCount = 1; |  | ||||||
|     blend_info.pAttachments = color_attachment; |  | ||||||
|  |  | ||||||
|     VkDynamicState dynamic_states[2] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; |  | ||||||
|     VkPipelineDynamicStateCreateInfo dynamic_state = {}; |  | ||||||
|     dynamic_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; |  | ||||||
|     dynamic_state.dynamicStateCount = (uint32_t)IM_ARRAYSIZE(dynamic_states); |  | ||||||
|     dynamic_state.pDynamicStates = dynamic_states; |  | ||||||
|  |  | ||||||
|     VkGraphicsPipelineCreateInfo info = {}; |  | ||||||
|     info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; |  | ||||||
|     info.flags = g_PipelineCreateFlags; |  | ||||||
|     info.stageCount = 2; |  | ||||||
|     info.pStages = stage; |  | ||||||
|     info.pVertexInputState = &vertex_info; |  | ||||||
|     info.pInputAssemblyState = &ia_info; |  | ||||||
|     info.pViewportState = &viewport_info; |  | ||||||
|     info.pRasterizationState = &raster_info; |  | ||||||
|     info.pMultisampleState = &ms_info; |  | ||||||
|     info.pDepthStencilState = &depth_info; |  | ||||||
|     info.pColorBlendState = &blend_info; |  | ||||||
|     info.pDynamicState = &dynamic_state; |  | ||||||
|     info.layout = g_PipelineLayout; |  | ||||||
|     info.renderPass = g_RenderPass; |  | ||||||
|     err = vkCreateGraphicsPipelines(v->Device, v->PipelineCache, 1, &info, v->Allocator, &g_Pipeline); |  | ||||||
|     check_vk_result(err); |  | ||||||
|  |  | ||||||
|     vkDestroyShaderModule(v->Device, vert_module, v->Allocator); |     vkDestroyShaderModule(v->Device, vert_module, v->Allocator); | ||||||
|     vkDestroyShaderModule(v->Device, frag_module, v->Allocator); |     vkDestroyShaderModule(v->Device, frag_module, v->Allocator); | ||||||
| @@ -1054,6 +1150,8 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V | |||||||
|     wd->ImageCount = 0; |     wd->ImageCount = 0; | ||||||
|     if (wd->RenderPass) |     if (wd->RenderPass) | ||||||
|         vkDestroyRenderPass(device, wd->RenderPass, allocator); |         vkDestroyRenderPass(device, wd->RenderPass, allocator); | ||||||
|  |     if (wd->Pipeline) | ||||||
|  |         vkDestroyPipeline(device, wd->Pipeline, allocator); | ||||||
|  |  | ||||||
|     // If min image count was not specified, request different count of images dependent on selected present mode |     // If min image count was not specified, request different count of images dependent on selected present mode | ||||||
|     if (min_image_count == 0) |     if (min_image_count == 0) | ||||||
| @@ -1149,6 +1247,7 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V | |||||||
|         info.pDependencies = &dependency; |         info.pDependencies = &dependency; | ||||||
|         err = vkCreateRenderPass(device, &info, allocator, &wd->RenderPass); |         err = vkCreateRenderPass(device, &info, allocator, &wd->RenderPass); | ||||||
|         check_vk_result(err); |         check_vk_result(err); | ||||||
|  |         ImGui_ImplVulkan_CreatePipeline(device, allocator, VK_NULL_HANDLE, wd->RenderPass, VK_SAMPLE_COUNT_1_BIT, &wd->Pipeline); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Create The Image Views |     // Create The Image Views | ||||||
| @@ -1385,7 +1484,7 @@ static void ImGui_ImplVulkan_RenderWindow(ImGuiViewport* viewport, void*) | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     ImGui_ImplVulkan_RenderDrawData(viewport->DrawData, fd->CommandBuffer); |     ImGui_ImplVulkan_RenderDrawData(viewport->DrawData, fd->CommandBuffer, wd->Pipeline); | ||||||
|  |  | ||||||
|     { |     { | ||||||
|         vkCmdEndRenderPass(fd->CommandBuffer); |         vkCmdEndRenderPass(fd->CommandBuffer); | ||||||
|   | |||||||
| @@ -47,7 +47,7 @@ struct ImGui_ImplVulkan_InitInfo | |||||||
| IMGUI_IMPL_API bool     ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass render_pass); | IMGUI_IMPL_API bool     ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass render_pass); | ||||||
| IMGUI_IMPL_API void     ImGui_ImplVulkan_Shutdown(); | IMGUI_IMPL_API void     ImGui_ImplVulkan_Shutdown(); | ||||||
| IMGUI_IMPL_API void     ImGui_ImplVulkan_NewFrame(); | IMGUI_IMPL_API void     ImGui_ImplVulkan_NewFrame(); | ||||||
| IMGUI_IMPL_API void     ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer); | IMGUI_IMPL_API void     ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer, VkPipeline pipeline = VK_NULL_HANDLE); | ||||||
| IMGUI_IMPL_API bool     ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer); | IMGUI_IMPL_API bool     ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer); | ||||||
| IMGUI_IMPL_API void     ImGui_ImplVulkan_DestroyFontUploadObjects(); | IMGUI_IMPL_API void     ImGui_ImplVulkan_DestroyFontUploadObjects(); | ||||||
| IMGUI_IMPL_API void     ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count); // To override MinImageCount after initialization (e.g. if swap chain is recreated) | IMGUI_IMPL_API void     ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count); // To override MinImageCount after initialization (e.g. if swap chain is recreated) | ||||||
| @@ -109,6 +109,7 @@ struct ImGui_ImplVulkanH_Window | |||||||
|     VkSurfaceFormatKHR  SurfaceFormat; |     VkSurfaceFormatKHR  SurfaceFormat; | ||||||
|     VkPresentModeKHR    PresentMode; |     VkPresentModeKHR    PresentMode; | ||||||
|     VkRenderPass        RenderPass; |     VkRenderPass        RenderPass; | ||||||
|  |     VkPipeline          Pipeline;               // The window pipeline uses a different VkRenderPass than the user's | ||||||
|     bool                ClearEnable; |     bool                ClearEnable; | ||||||
|     VkClearValue        ClearValue; |     VkClearValue        ClearValue; | ||||||
|     uint32_t            FrameIndex;             // Current frame being rendered to (0 <= FrameIndex < FrameInFlightCount) |     uint32_t            FrameIndex;             // Current frame being rendered to (0 <= FrameIndex < FrameInFlightCount) | ||||||
|   | |||||||
							
								
								
									
										118
									
								
								imgui.cpp
									
									
									
									
									
								
							
							
						
						
									
										118
									
								
								imgui.cpp
									
									
									
									
									
								
							| @@ -8083,21 +8083,42 @@ void ImGui::EndGroup() | |||||||
| // [SECTION] SCROLLING | // [SECTION] SCROLLING | ||||||
| //----------------------------------------------------------------------------- | //----------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | // Helper to snap on edges when aiming at an item very close to the edge, | ||||||
|  | // So the difference between WindowPadding and ItemSpacing will be in the visible area after scrolling. | ||||||
|  | // When we refactor the scrolling API this may be configurable with a flag? | ||||||
|  | // Note that the effect for this won't be visible on X axis with default Style settings as WindowPadding.x == ItemSpacing.x by default. | ||||||
|  | static float CalcScrollEdgeSnap(float target, float snap_min, float snap_max, float snap_threshold, float center_ratio) | ||||||
|  | { | ||||||
|  |     if (target <= snap_min + snap_threshold) | ||||||
|  |         return ImLerp(snap_min, target, center_ratio); | ||||||
|  |     if (target >= snap_max - snap_threshold) | ||||||
|  |         return ImLerp(target, snap_max, center_ratio); | ||||||
|  |     return target; | ||||||
|  | } | ||||||
|  |  | ||||||
| static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window) | static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window) | ||||||
| { | { | ||||||
|     ImVec2 scroll = window->Scroll; |     ImVec2 scroll = window->Scroll; | ||||||
|     if (window->ScrollTarget.x < FLT_MAX) |     if (window->ScrollTarget.x < FLT_MAX) | ||||||
|     { |     { | ||||||
|         float cr_x = window->ScrollTargetCenterRatio.x; |         float center_x_ratio = window->ScrollTargetCenterRatio.x; | ||||||
|         float target_x = window->ScrollTarget.x; |         float scroll_target_x = window->ScrollTarget.x; | ||||||
|         scroll.x = target_x - cr_x * (window->SizeFull.x - window->ScrollbarSizes.x); |         float snap_x_min = 0.0f; | ||||||
|  |         float snap_x_max = window->ScrollMax.x + window->Size.x; | ||||||
|  |         if (window->ScrollTargetEdgeSnapDist.x > 0.0f) | ||||||
|  |             scroll_target_x = CalcScrollEdgeSnap(scroll_target_x, snap_x_min, snap_x_max, window->ScrollTargetEdgeSnapDist.x, center_x_ratio); | ||||||
|  |         scroll.x = scroll_target_x - center_x_ratio * (window->SizeFull.x - window->ScrollbarSizes.x); | ||||||
|     } |     } | ||||||
|     if (window->ScrollTarget.y < FLT_MAX) |     if (window->ScrollTarget.y < FLT_MAX) | ||||||
|     { |     { | ||||||
|         float decoration_up_height = window->TitleBarHeight() + window->MenuBarHeight(); |         float decoration_up_height = window->TitleBarHeight() + window->MenuBarHeight(); | ||||||
|         float cr_y = window->ScrollTargetCenterRatio.y; |         float center_y_ratio = window->ScrollTargetCenterRatio.y; | ||||||
|         float target_y = window->ScrollTarget.y; |         float scroll_target_y = window->ScrollTarget.y; | ||||||
|         scroll.y = target_y - cr_y * (window->SizeFull.y - window->ScrollbarSizes.y - decoration_up_height); |         float snap_y_min = 0.0f; | ||||||
|  |         float snap_y_max = window->ScrollMax.y + window->Size.y - decoration_up_height; | ||||||
|  |         if (window->ScrollTargetEdgeSnapDist.y > 0.0f) | ||||||
|  |             scroll_target_y = CalcScrollEdgeSnap(scroll_target_y, snap_y_min, snap_y_max, window->ScrollTargetEdgeSnapDist.y, center_y_ratio); | ||||||
|  |         scroll.y = scroll_target_y - center_y_ratio * (window->SizeFull.y - window->ScrollbarSizes.y - decoration_up_height); | ||||||
|     } |     } | ||||||
|     scroll.x = IM_FLOOR(ImMax(scroll.x, 0.0f)); |     scroll.x = IM_FLOOR(ImMax(scroll.x, 0.0f)); | ||||||
|     scroll.y = IM_FLOOR(ImMax(scroll.y, 0.0f)); |     scroll.y = IM_FLOOR(ImMax(scroll.y, 0.0f)); | ||||||
| @@ -8163,47 +8184,57 @@ float ImGui::GetScrollMaxY() | |||||||
|     return window->ScrollMax.y; |     return window->ScrollMax.y; | ||||||
| } | } | ||||||
|  |  | ||||||
| void ImGui::SetScrollX(float scroll_x) | void ImGui::SetScrollX(ImGuiWindow* window, float scroll_x) | ||||||
| { | { | ||||||
|     ImGuiWindow* window = GetCurrentWindow(); |  | ||||||
|     window->ScrollTarget.x = scroll_x; |     window->ScrollTarget.x = scroll_x; | ||||||
|     window->ScrollTargetCenterRatio.x = 0.0f; |     window->ScrollTargetCenterRatio.x = 0.0f; | ||||||
|  |     window->ScrollTargetEdgeSnapDist.x = 0.0f; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ImGui::SetScrollY(ImGuiWindow* window, float scroll_y) | ||||||
|  | { | ||||||
|  |     window->ScrollTarget.y = scroll_y; | ||||||
|  |     window->ScrollTargetCenterRatio.y = 0.0f; | ||||||
|  |     window->ScrollTargetEdgeSnapDist.y = 0.0f; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ImGui::SetScrollX(float scroll_x) | ||||||
|  | { | ||||||
|  |     ImGuiContext& g = *GImGui; | ||||||
|  |     SetScrollX(g.CurrentWindow, scroll_x); | ||||||
| } | } | ||||||
|  |  | ||||||
| void ImGui::SetScrollY(float scroll_y) | void ImGui::SetScrollY(float scroll_y) | ||||||
| { | { | ||||||
|     ImGuiWindow* window = GetCurrentWindow(); |     ImGuiContext& g = *GImGui; | ||||||
|     window->ScrollTarget.y = scroll_y; |     SetScrollY(g.CurrentWindow, scroll_y); | ||||||
|     window->ScrollTargetCenterRatio.y = 0.0f; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void ImGui::SetScrollX(ImGuiWindow* window, float new_scroll_x) | // Note that a local position will vary depending on initial scroll value, | ||||||
| { | // This is a little bit confusing so bear with us: | ||||||
|     window->ScrollTarget.x = new_scroll_x; | //  - local_pos = (absolution_pos - window->Pos) | ||||||
|     window->ScrollTargetCenterRatio.x = 0.0f; | //  - So local_x/local_y are 0.0f for a position at the upper-left corner of a window, | ||||||
| } | //    and generally local_x/local_y are >(padding+decoration) && <(size-padding-decoration) when in the visible area. | ||||||
|  | //  - They mostly exists because of legacy API. | ||||||
| void ImGui::SetScrollY(ImGuiWindow* window, float new_scroll_y) | // Following the rules above, when trying to work with scrolling code, consider that: | ||||||
| { | //  - SetScrollFromPosY(0.0f) == SetScrollY(0.0f + scroll.y) == has no effect! | ||||||
|     window->ScrollTarget.y = new_scroll_y; | //  - SetScrollFromPosY(-scroll.y) == SetScrollY(-scroll.y + scroll.y) == SetScrollY(0.0f) == reset scroll. Of course writing SetScrollY(0.0f) directly then makes more sense | ||||||
|     window->ScrollTargetCenterRatio.y = 0.0f; | // We store a target position so centering and clamping can occur on the next frame when we are guaranteed to have a known window size | ||||||
| } |  | ||||||
|  |  | ||||||
| // Note that a local position will vary depending on initial scroll value |  | ||||||
| // We store a target position so centering can occur on the next frame when we are guaranteed to have a known window size |  | ||||||
| void ImGui::SetScrollFromPosX(ImGuiWindow* window, float local_x, float center_x_ratio) | void ImGui::SetScrollFromPosX(ImGuiWindow* window, float local_x, float center_x_ratio) | ||||||
| { | { | ||||||
|     IM_ASSERT(center_x_ratio >= 0.0f && center_x_ratio <= 1.0f); |     IM_ASSERT(center_x_ratio >= 0.0f && center_x_ratio <= 1.0f); | ||||||
|     window->ScrollTarget.x = IM_FLOOR(local_x + window->Scroll.x); |     window->ScrollTarget.x = IM_FLOOR(local_x + window->Scroll.x); // Convert local position to scroll offset | ||||||
|     window->ScrollTargetCenterRatio.x = center_x_ratio; |     window->ScrollTargetCenterRatio.x = center_x_ratio; | ||||||
|  |     window->ScrollTargetEdgeSnapDist.x = 0.0f; | ||||||
| } | } | ||||||
|  |  | ||||||
| void ImGui::SetScrollFromPosY(ImGuiWindow* window, float local_y, float center_y_ratio) | void ImGui::SetScrollFromPosY(ImGuiWindow* window, float local_y, float center_y_ratio) | ||||||
| { | { | ||||||
|     IM_ASSERT(center_y_ratio >= 0.0f && center_y_ratio <= 1.0f); |     IM_ASSERT(center_y_ratio >= 0.0f && center_y_ratio <= 1.0f); | ||||||
|     local_y -= window->TitleBarHeight() + window->MenuBarHeight(); // FIXME: Would be nice to have a more standardized access to our scrollable/client rect |     local_y -= window->TitleBarHeight() + window->MenuBarHeight(); // FIXME: Would be nice to have a more standardized access to our scrollable/client rect | ||||||
|     window->ScrollTarget.y = IM_FLOOR(local_y + window->Scroll.y); |     window->ScrollTarget.y = IM_FLOOR(local_y + window->Scroll.y); // Convert local position to scroll offset | ||||||
|     window->ScrollTargetCenterRatio.y = center_y_ratio; |     window->ScrollTargetCenterRatio.y = center_y_ratio; | ||||||
|  |     window->ScrollTargetEdgeSnapDist.y = 0.0f; | ||||||
| } | } | ||||||
|  |  | ||||||
| void ImGui::SetScrollFromPosX(float local_x, float center_x_ratio) | void ImGui::SetScrollFromPosX(float local_x, float center_x_ratio) | ||||||
| @@ -8218,34 +8249,17 @@ void ImGui::SetScrollFromPosY(float local_y, float center_y_ratio) | |||||||
|     SetScrollFromPosY(g.CurrentWindow, local_y, center_y_ratio); |     SetScrollFromPosY(g.CurrentWindow, local_y, center_y_ratio); | ||||||
| } | } | ||||||
|  |  | ||||||
| // Tweak: snap on edges when aiming at an item very close to the edge, |  | ||||||
| // So the difference between WindowPadding and ItemSpacing will be in the visible area after scrolling. |  | ||||||
| // When we refactor the scrolling API this may be configurable with a flag? |  | ||||||
| // Note that the effect for this won't be visible on X axis with default Style settings as WindowPadding.x == ItemSpacing.x by default. |  | ||||||
| static float CalcScrollSnap(float target, float snap_min, float snap_max, float snap_threshold, float center_ratio) |  | ||||||
| { |  | ||||||
|     if (target <= snap_min + snap_threshold) |  | ||||||
|         return ImLerp(snap_min, target, center_ratio); |  | ||||||
|     if (target >= snap_max - snap_threshold) |  | ||||||
|         return ImLerp(target, snap_max, center_ratio); |  | ||||||
|     return target; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // center_x_ratio: 0.0f left of last item, 0.5f horizontal center of last item, 1.0f right of last item. | // center_x_ratio: 0.0f left of last item, 0.5f horizontal center of last item, 1.0f right of last item. | ||||||
| void ImGui::SetScrollHereX(float center_x_ratio) | void ImGui::SetScrollHereX(float center_x_ratio) | ||||||
| { | { | ||||||
|     ImGuiContext& g = *GImGui; |     ImGuiContext& g = *GImGui; | ||||||
|     ImGuiWindow* window = g.CurrentWindow; |     ImGuiWindow* window = g.CurrentWindow; | ||||||
|     float spacing_x = g.Style.ItemSpacing.x; |     float spacing_x = g.Style.ItemSpacing.x; | ||||||
|     float target_x = ImLerp(window->DC.LastItemRect.Min.x - spacing_x, window->DC.LastItemRect.Max.x + spacing_x, center_x_ratio); |     float target_pos_x = ImLerp(window->DC.LastItemRect.Min.x - spacing_x, window->DC.LastItemRect.Max.x + spacing_x, center_x_ratio); | ||||||
|  |     SetScrollFromPosX(window, target_pos_x - window->Pos.x, center_x_ratio); // Convert from absolute to local pos | ||||||
|  |  | ||||||
|     // Tweak: snap on edges when aiming at an item very close to the edge |     // Tweak: snap on edges when aiming at an item very close to the edge | ||||||
|     const float snap_x_threshold = ImMax(0.0f, window->WindowPadding.x - spacing_x); |     window->ScrollTargetEdgeSnapDist.x = ImMax(0.0f, window->WindowPadding.x - spacing_x); | ||||||
|     const float snap_x_min = window->DC.CursorStartPos.x - window->WindowPadding.x; |  | ||||||
|     const float snap_x_max = window->DC.CursorStartPos.x + window->ContentSize.x + window->WindowPadding.x; |  | ||||||
|     target_x = CalcScrollSnap(target_x, snap_x_min, snap_x_max, snap_x_threshold, center_x_ratio); |  | ||||||
|  |  | ||||||
|     SetScrollFromPosX(window, target_x - window->Pos.x, center_x_ratio); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| // center_y_ratio: 0.0f top of last item, 0.5f vertical center of last item, 1.0f bottom of last item. | // center_y_ratio: 0.0f top of last item, 0.5f vertical center of last item, 1.0f bottom of last item. | ||||||
| @@ -8254,15 +8268,11 @@ void ImGui::SetScrollHereY(float center_y_ratio) | |||||||
|     ImGuiContext& g = *GImGui; |     ImGuiContext& g = *GImGui; | ||||||
|     ImGuiWindow* window = g.CurrentWindow; |     ImGuiWindow* window = g.CurrentWindow; | ||||||
|     float spacing_y = g.Style.ItemSpacing.y; |     float spacing_y = g.Style.ItemSpacing.y; | ||||||
|     float target_y = ImLerp(window->DC.CursorPosPrevLine.y - spacing_y, window->DC.CursorPosPrevLine.y + window->DC.PrevLineSize.y + spacing_y, center_y_ratio); |     float target_pos_y = ImLerp(window->DC.CursorPosPrevLine.y - spacing_y, window->DC.CursorPosPrevLine.y + window->DC.PrevLineSize.y + spacing_y, center_y_ratio); | ||||||
|  |     SetScrollFromPosY(window, target_pos_y - window->Pos.y, center_y_ratio); // Convert from absolute to local pos | ||||||
|  |  | ||||||
|     // Tweak: snap on edges when aiming at an item very close to the edge |     // Tweak: snap on edges when aiming at an item very close to the edge | ||||||
|     const float snap_y_threshold = ImMax(0.0f, window->WindowPadding.y - spacing_y); |     window->ScrollTargetEdgeSnapDist.y = ImMax(0.0f, window->WindowPadding.y - spacing_y); | ||||||
|     const float snap_y_min = window->DC.CursorStartPos.y - window->WindowPadding.y; |  | ||||||
|     const float snap_y_max = window->DC.CursorStartPos.y + window->ContentSize.y + window->WindowPadding.y; |  | ||||||
|     target_y = CalcScrollSnap(target_y, snap_y_min, snap_y_max, snap_y_threshold, center_y_ratio); |  | ||||||
|  |  | ||||||
|     SetScrollFromPosY(window, target_y - window->Pos.y, center_y_ratio); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| //----------------------------------------------------------------------------- | //----------------------------------------------------------------------------- | ||||||
|   | |||||||
							
								
								
									
										4
									
								
								imgui.h
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								imgui.h
									
									
									
									
									
								
							| @@ -1470,7 +1470,7 @@ struct ImVector | |||||||
|     inline bool         empty() const                       { return Size == 0; } |     inline bool         empty() const                       { return Size == 0; } | ||||||
|     inline int          size() const                        { return Size; } |     inline int          size() const                        { return Size; } | ||||||
|     inline int          size_in_bytes() const               { return Size * (int)sizeof(T); } |     inline int          size_in_bytes() const               { return Size * (int)sizeof(T); } | ||||||
|     inline int          max_size() const                    { return (~(unsigned int)0) / (int)sizeof(T); } |     inline int          max_size() const                    { return 0x7FFFFFFF / (int)sizeof(T); } | ||||||
|     inline int          capacity() const                    { return Capacity; } |     inline int          capacity() const                    { return Capacity; } | ||||||
|     inline T&           operator[](int i)                   { IM_ASSERT(i < Size); return Data[i]; } |     inline T&           operator[](int i)                   { IM_ASSERT(i < Size); return Data[i]; } | ||||||
|     inline const T&     operator[](int i) const             { IM_ASSERT(i < Size); return Data[i]; } |     inline const T&     operator[](int i) const             { IM_ASSERT(i < Size); return Data[i]; } | ||||||
| @@ -2547,7 +2547,7 @@ struct ImFont | |||||||
|     IMGUI_API void              BuildLookupTable(); |     IMGUI_API void              BuildLookupTable(); | ||||||
|     IMGUI_API void              ClearOutputData(); |     IMGUI_API void              ClearOutputData(); | ||||||
|     IMGUI_API void              GrowIndex(int new_size); |     IMGUI_API void              GrowIndex(int new_size); | ||||||
|     IMGUI_API void              AddGlyph(ImFontConfig* src_cfg, ImWchar c, float x0, float y0, float x1, float y1, float u0, float v0, float u1, float v1, float advance_x); |     IMGUI_API void              AddGlyph(const ImFontConfig* src_cfg, ImWchar c, float x0, float y0, float x1, float y1, float u0, float v0, float u1, float v1, float advance_x); | ||||||
|     IMGUI_API void              AddRemapChar(ImWchar dst, ImWchar src, bool overwrite_dst = true); // Makes 'dst' character/glyph points to 'src' character/glyph. Currently needs to be called AFTER fonts have been built. |     IMGUI_API void              AddRemapChar(ImWchar dst, ImWchar src, bool overwrite_dst = true); // Makes 'dst' character/glyph points to 'src' character/glyph. Currently needs to be called AFTER fonts have been built. | ||||||
|     IMGUI_API void              SetGlyphVisible(ImWchar c, bool visible); |     IMGUI_API void              SetGlyphVisible(ImWchar c, bool visible); | ||||||
|     IMGUI_API void              SetFallbackChar(ImWchar c); |     IMGUI_API void              SetFallbackChar(ImWchar c); | ||||||
|   | |||||||
| @@ -672,7 +672,7 @@ static void ShowDemoWindowWidgets() | |||||||
|                 "Hold SHIFT/ALT for faster/slower edit.\n" |                 "Hold SHIFT/ALT for faster/slower edit.\n" | ||||||
|                 "Double-click or CTRL+click to input value."); |                 "Double-click or CTRL+click to input value."); | ||||||
|  |  | ||||||
|             ImGui::DragInt("drag int 0..100", &i2, 1, 0, 100, "%d%%"); |             ImGui::DragInt("drag int 0..100", &i2, 1, 0, 100, "%d%%", ImGuiSliderFlags_ClampOnInput); | ||||||
|  |  | ||||||
|             static float f1 = 1.00f, f2 = 0.0067f; |             static float f1 = 1.00f, f2 = 0.0067f; | ||||||
|             ImGui::DragFloat("drag float", &f1, 0.005f); |             ImGui::DragFloat("drag float", &f1, 0.005f); | ||||||
| @@ -1743,6 +1743,14 @@ static void ShowDemoWindowWidgets() | |||||||
|         ImGui::SliderScalar("slider double low log",ImGuiDataType_Double, &f64_v, &f64_zero, &f64_one,  "%.10f", ImGuiSliderFlags_Logarithmic); |         ImGui::SliderScalar("slider double low log",ImGuiDataType_Double, &f64_v, &f64_zero, &f64_one,  "%.10f", ImGuiSliderFlags_Logarithmic); | ||||||
|         ImGui::SliderScalar("slider double high",   ImGuiDataType_Double, &f64_v, &f64_lo_a, &f64_hi_a, "%e grams"); |         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 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"); | ||||||
|  |  | ||||||
|         static bool inputs_step = true; |         static bool inputs_step = true; | ||||||
|         ImGui::Text("Inputs"); |         ImGui::Text("Inputs"); | ||||||
|         ImGui::Checkbox("Show step buttons", &inputs_step); |         ImGui::Checkbox("Show step buttons", &inputs_step); | ||||||
| @@ -4291,9 +4299,9 @@ struct ExampleAppConsole | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         ImGui::TextWrapped( |         ImGui::TextWrapped( | ||||||
|             "This example implements a console with basic coloring, completion and history. A more elaborate " |             "This example implements a console with basic coloring, completion (TAB key) and history (Up/Down keys). A more elaborate " | ||||||
|             "implementation may want to store entries along with extra data such as timestamp, emitter, etc."); |             "implementation may want to store entries along with extra data such as timestamp, emitter, etc."); | ||||||
|         ImGui::TextWrapped("Enter 'HELP' for help, press TAB to use text completion."); |         ImGui::TextWrapped("Enter 'HELP' for help."); | ||||||
|  |  | ||||||
|         // TODO: display items starting from the bottom |         // TODO: display items starting from the bottom | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2892,7 +2892,7 @@ void ImFont::GrowIndex(int new_size) | |||||||
| // x0/y0/x1/y1 are offset from the character upper-left layout position, in pixels. Therefore x0/y0 are often fairly close to zero. | // x0/y0/x1/y1 are offset from the character upper-left layout position, in pixels. Therefore x0/y0 are often fairly close to zero. | ||||||
| // Not to be mistaken with texture coordinates, which are held by u0/v0/u1/v1 in normalized format (0.0..1.0 on each texture axis). | // Not to be mistaken with texture coordinates, which are held by u0/v0/u1/v1 in normalized format (0.0..1.0 on each texture axis). | ||||||
| // 'cfg' is not necessarily == 'this->ConfigData' because multiple source fonts+configs can be used to build one target font. | // 'cfg' is not necessarily == 'this->ConfigData' because multiple source fonts+configs can be used to build one target font. | ||||||
| void ImFont::AddGlyph(ImFontConfig* cfg, ImWchar codepoint, float x0, float y0, float x1, float y1, float u0, float v0, float u1, float v1, float advance_x) | void ImFont::AddGlyph(const ImFontConfig* cfg, ImWchar codepoint, float x0, float y0, float x1, float y1, float u0, float v0, float u1, float v1, float advance_x) | ||||||
| { | { | ||||||
|     if (cfg != NULL) |     if (cfg != NULL) | ||||||
|     { |     { | ||||||
|   | |||||||
| @@ -1774,6 +1774,7 @@ struct IMGUI_API ImGuiWindow | |||||||
|     ImVec2                  ScrollMax; |     ImVec2                  ScrollMax; | ||||||
|     ImVec2                  ScrollTarget;                       // target scroll position. stored as cursor position with scrolling canceled out, so the highest point is always 0.0f. (FLT_MAX for no change) |     ImVec2                  ScrollTarget;                       // target scroll position. stored as cursor position with scrolling canceled out, so the highest point is always 0.0f. (FLT_MAX for no change) | ||||||
|     ImVec2                  ScrollTargetCenterRatio;            // 0.0f = scroll so that target position is at top, 0.5f = scroll so that target position is centered |     ImVec2                  ScrollTargetCenterRatio;            // 0.0f = scroll so that target position is at top, 0.5f = scroll so that target position is centered | ||||||
|  |     ImVec2                  ScrollTargetEdgeSnapDist;           // 0.0f = no snapping, >0.0f snapping threshold | ||||||
|     ImVec2                  ScrollbarSizes;                     // Size taken by each scrollbars on their smaller axis. Pay attention! ScrollbarSizes.x == width of the vertical scrollbar, ScrollbarSizes.y = height of the horizontal scrollbar. |     ImVec2                  ScrollbarSizes;                     // Size taken by each scrollbars on their smaller axis. Pay attention! ScrollbarSizes.x == width of the vertical scrollbar, ScrollbarSizes.y = height of the horizontal scrollbar. | ||||||
|     bool                    ScrollbarX, ScrollbarY;             // Are scrollbars visible? |     bool                    ScrollbarX, ScrollbarY;             // Are scrollbars visible? | ||||||
|     bool                    ViewportOwned; |     bool                    ViewportOwned; | ||||||
| @@ -2043,10 +2044,10 @@ namespace ImGui | |||||||
|  |  | ||||||
|     // Scrolling |     // Scrolling | ||||||
|     IMGUI_API void          SetNextWindowScroll(const ImVec2& scroll); // Use -1.0f on one axis to leave as-is |     IMGUI_API void          SetNextWindowScroll(const ImVec2& scroll); // Use -1.0f on one axis to leave as-is | ||||||
|     IMGUI_API void          SetScrollX(ImGuiWindow* window, float new_scroll_x); |     IMGUI_API void          SetScrollX(ImGuiWindow* window, float scroll_x); | ||||||
|     IMGUI_API void          SetScrollY(ImGuiWindow* window, float new_scroll_y); |     IMGUI_API void          SetScrollY(ImGuiWindow* window, float scroll_y); | ||||||
|     IMGUI_API void          SetScrollFromPosX(ImGuiWindow* window, float local_x, float center_x_ratio = 0.5f); |     IMGUI_API void          SetScrollFromPosX(ImGuiWindow* window, float local_x, float center_x_ratio); | ||||||
|     IMGUI_API void          SetScrollFromPosY(ImGuiWindow* window, float local_y, float center_y_ratio = 0.5f); |     IMGUI_API void          SetScrollFromPosY(ImGuiWindow* window, float local_y, float center_y_ratio); | ||||||
|     IMGUI_API ImVec2        ScrollToBringRectIntoView(ImGuiWindow* window, const ImRect& item_rect); |     IMGUI_API ImVec2        ScrollToBringRectIntoView(ImGuiWindow* window, const ImRect& item_rect); | ||||||
|  |  | ||||||
|     // Basic Accessors |     // Basic Accessors | ||||||
| @@ -2262,8 +2263,8 @@ namespace ImGui | |||||||
|     // Template functions are instantiated in imgui_widgets.cpp for a finite number of types. |     // Template functions are instantiated in imgui_widgets.cpp for a finite number of types. | ||||||
|     // To use them externally (for custom widget) you may need an "extern template" statement in your code in order to link to existing instances and silence Clang warnings (see #2036). |     // To use them externally (for custom widget) you may need an "extern template" statement in your code in order to link to existing instances and silence Clang warnings (see #2036). | ||||||
|     // e.g. " extern template IMGUI_API float RoundScalarWithFormatT<float, float>(const char* format, ImGuiDataType data_type, float v); " |     // e.g. " extern template IMGUI_API float RoundScalarWithFormatT<float, float>(const char* format, ImGuiDataType data_type, float v); " | ||||||
|     template<typename T, typename FLOAT_T>                      IMGUI_API float ScaleRatioFromValueT(ImGuiDataType data_type, T v, T v_min, T v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_size); |     template<typename T, typename SIGNED_T, typename FLOAT_T>   IMGUI_API float ScaleRatioFromValueT(ImGuiDataType data_type, T v, T v_min, T v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_size); | ||||||
|     template<typename T, typename FLOAT_T>                      IMGUI_API T     ScaleValueFromRatioT(ImGuiDataType data_type, float t, T v_min, T v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_size); |     template<typename T, typename SIGNED_T, typename FLOAT_T>   IMGUI_API T     ScaleValueFromRatioT(ImGuiDataType data_type, float t, T v_min, T v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_size); | ||||||
|     template<typename T, typename SIGNED_T, typename FLOAT_T>   IMGUI_API bool  DragBehaviorT(ImGuiDataType data_type, T* v, float v_speed, T v_min, T v_max, const char* format, ImGuiSliderFlags flags); |     template<typename T, typename SIGNED_T, typename FLOAT_T>   IMGUI_API bool  DragBehaviorT(ImGuiDataType data_type, T* v, float v_speed, T v_min, T v_max, const char* format, ImGuiSliderFlags flags); | ||||||
|     template<typename T, typename SIGNED_T, typename FLOAT_T>   IMGUI_API bool  SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, T* v, T v_min, T v_max, const char* format, ImGuiSliderFlags flags, ImRect* out_grab_bb); |     template<typename T, typename SIGNED_T, typename FLOAT_T>   IMGUI_API bool  SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, T* v, T v_min, T v_max, const char* format, ImGuiSliderFlags flags, ImRect* out_grab_bb); | ||||||
|     template<typename T, typename SIGNED_T>                     IMGUI_API T     RoundScalarWithFormatT(const char* format, ImGuiDataType data_type, T v); |     template<typename T, typename SIGNED_T>                     IMGUI_API T     RoundScalarWithFormatT(const char* format, ImGuiDataType data_type, T v); | ||||||
|   | |||||||
| @@ -2101,9 +2101,9 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const | |||||||
|         logarithmic_zero_epsilon = ImPow(0.1f, (float)decimal_precision); |         logarithmic_zero_epsilon = ImPow(0.1f, (float)decimal_precision); | ||||||
|  |  | ||||||
|         // Convert to parametric space, apply delta, convert back |         // Convert to parametric space, apply delta, convert back | ||||||
|         float v_old_parametric = ScaleRatioFromValueT<TYPE, FLOATTYPE>(data_type, v_cur, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); |         float v_old_parametric = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, v_cur, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); | ||||||
|         float v_new_parametric = v_old_parametric + g.DragCurrentAccum; |         float v_new_parametric = v_old_parametric + g.DragCurrentAccum; | ||||||
|         v_cur = ScaleValueFromRatioT<TYPE, FLOATTYPE>(data_type, v_new_parametric, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); |         v_cur = ScaleValueFromRatioT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, v_new_parametric, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); | ||||||
|         v_old_ref_for_accum_remainder = v_old_parametric; |         v_old_ref_for_accum_remainder = v_old_parametric; | ||||||
|     } |     } | ||||||
|     else |     else | ||||||
| @@ -2120,7 +2120,7 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const | |||||||
|     if (is_logarithmic) |     if (is_logarithmic) | ||||||
|     { |     { | ||||||
|         // Convert to parametric space, apply delta, convert back |         // Convert to parametric space, apply delta, convert back | ||||||
|         float v_new_parametric = ScaleRatioFromValueT<TYPE, FLOATTYPE>(data_type, v_cur, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); |         float v_new_parametric = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, v_cur, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); | ||||||
|         g.DragCurrentAccum -= (float)(v_new_parametric - v_old_ref_for_accum_remainder); |         g.DragCurrentAccum -= (float)(v_new_parametric - v_old_ref_for_accum_remainder); | ||||||
|     } |     } | ||||||
|     else |     else | ||||||
| @@ -2456,7 +2456,7 @@ bool ImGui::DragScalarN(const char* label, ImGuiDataType data_type, void* p_data | |||||||
| //------------------------------------------------------------------------- | //------------------------------------------------------------------------- | ||||||
|  |  | ||||||
| // Convert a value v in the output space of a slider into a parametric position on the slider itself (the logical opposite of ScaleValueFromRatioT) | // Convert a value v in the output space of a slider into a parametric position on the slider itself (the logical opposite of ScaleValueFromRatioT) | ||||||
| template<typename TYPE, typename FLOATTYPE> | template<typename TYPE, typename SIGNEDTYPE, typename FLOATTYPE> | ||||||
| float ImGui::ScaleRatioFromValueT(ImGuiDataType data_type, TYPE v, TYPE v_min, TYPE v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_halfsize) | float ImGui::ScaleRatioFromValueT(ImGuiDataType data_type, TYPE v, TYPE v_min, TYPE v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_halfsize) | ||||||
| { | { | ||||||
|     if (v_min == v_max) |     if (v_min == v_max) | ||||||
| @@ -2508,11 +2508,11 @@ float ImGui::ScaleRatioFromValueT(ImGuiDataType data_type, TYPE v, TYPE v_min, T | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Linear slider |     // Linear slider | ||||||
|     return (float)((FLOATTYPE)(v_clamped - v_min) / (FLOATTYPE)(v_max - v_min)); |     return (float)((FLOATTYPE)(SIGNEDTYPE)(v_clamped - v_min) / (FLOATTYPE)(SIGNEDTYPE)(v_max - v_min)); | ||||||
| } | } | ||||||
|  |  | ||||||
| // Convert a parametric position on a slider into a value v in the output space (the logical opposite of ScaleRatioFromValueT) | // Convert a parametric position on a slider into a value v in the output space (the logical opposite of ScaleRatioFromValueT) | ||||||
| template<typename TYPE, typename FLOATTYPE> | template<typename TYPE, typename SIGNEDTYPE, typename FLOATTYPE> | ||||||
| TYPE ImGui::ScaleValueFromRatioT(ImGuiDataType data_type, float t, TYPE v_min, TYPE v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_halfsize) | TYPE ImGui::ScaleValueFromRatioT(ImGuiDataType data_type, float t, TYPE v_min, TYPE v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_halfsize) | ||||||
| { | { | ||||||
|     if (v_min == v_max) |     if (v_min == v_max) | ||||||
| @@ -2571,15 +2571,19 @@ TYPE ImGui::ScaleValueFromRatioT(ImGuiDataType data_type, float t, TYPE v_min, T | |||||||
|         } |         } | ||||||
|         else |         else | ||||||
|         { |         { | ||||||
|             // For integer values we want the clicking position to match the grab box so we round above |             // - For integer values we want the clicking position to match the grab box so we round above | ||||||
|             //   This code is carefully tuned to work with large values (e.g. high ranges of U64) while preserving this property.. |             //   This code is carefully tuned to work with large values (e.g. high ranges of U64) while preserving this property.. | ||||||
|             FLOATTYPE v_new_off_f = (v_max - v_min) * t; |             // - Not doing a *1.0 multiply at the end of a range as it tends to be lossy. While absolute aiming at a large s64/u64 | ||||||
|             TYPE v_new_off_floor = (TYPE)(v_new_off_f); |             //   range is going to be imprecise anyway, with this check we at least make the edge values matches expected limits. | ||||||
|             TYPE v_new_off_round = (TYPE)(v_new_off_f + (FLOATTYPE)0.5); |             if (t < 1.0) | ||||||
|             if (v_new_off_floor < v_new_off_round) |             { | ||||||
|                 result = v_min + v_new_off_round; |                 FLOATTYPE v_new_off_f = (SIGNEDTYPE)(v_max - v_min) * t; | ||||||
|  |                 result = (TYPE)((SIGNEDTYPE)v_min + (SIGNEDTYPE)(v_new_off_f + (FLOATTYPE)(v_min > v_max ? -0.5 : 0.5))); | ||||||
|  |             } | ||||||
|             else |             else | ||||||
|                 result = v_min + v_new_off_floor; |             { | ||||||
|  |                 result = v_max; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -2679,7 +2683,7 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ | |||||||
|             } |             } | ||||||
|             else if (g.SliderCurrentAccumDirty) |             else if (g.SliderCurrentAccumDirty) | ||||||
|             { |             { | ||||||
|                 clicked_t = ScaleRatioFromValueT<TYPE, FLOATTYPE>(data_type, *v, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); |                 clicked_t = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, *v, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); | ||||||
|  |  | ||||||
|                 if ((clicked_t >= 1.0f && delta > 0.0f) || (clicked_t <= 0.0f && delta < 0.0f)) // This is to avoid applying the saturation when already past the limits |                 if ((clicked_t >= 1.0f && delta > 0.0f) || (clicked_t <= 0.0f && delta < 0.0f)) // This is to avoid applying the saturation when already past the limits | ||||||
|                 { |                 { | ||||||
| @@ -2693,10 +2697,10 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ | |||||||
|                     clicked_t = ImSaturate(clicked_t + delta); |                     clicked_t = ImSaturate(clicked_t + delta); | ||||||
|  |  | ||||||
|                     // Calculate what our "new" clicked_t will be, and thus how far we actually moved the slider, and subtract this from the accumulator |                     // Calculate what our "new" clicked_t will be, and thus how far we actually moved the slider, and subtract this from the accumulator | ||||||
|                     TYPE v_new = ScaleValueFromRatioT<TYPE, FLOATTYPE>(data_type, clicked_t, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); |                     TYPE v_new = ScaleValueFromRatioT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, clicked_t, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); | ||||||
|                     if (!(flags & ImGuiSliderFlags_NoRoundToFormat)) |                     if (!(flags & ImGuiSliderFlags_NoRoundToFormat)) | ||||||
|                         v_new = RoundScalarWithFormatT<TYPE, SIGNEDTYPE>(format, data_type, v_new); |                         v_new = RoundScalarWithFormatT<TYPE, SIGNEDTYPE>(format, data_type, v_new); | ||||||
|                     float new_clicked_t = ScaleRatioFromValueT<TYPE, FLOATTYPE>(data_type, v_new, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); |                     float new_clicked_t = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, v_new, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); | ||||||
|  |  | ||||||
|                     if (delta > 0) |                     if (delta > 0) | ||||||
|                         g.SliderCurrentAccum -= ImMin(new_clicked_t - old_clicked_t, delta); |                         g.SliderCurrentAccum -= ImMin(new_clicked_t - old_clicked_t, delta); | ||||||
| @@ -2710,7 +2714,7 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ | |||||||
|  |  | ||||||
|         if (set_new_value) |         if (set_new_value) | ||||||
|         { |         { | ||||||
|             TYPE v_new = ScaleValueFromRatioT<TYPE, FLOATTYPE>(data_type, clicked_t, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); |             TYPE v_new = ScaleValueFromRatioT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, clicked_t, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); | ||||||
|  |  | ||||||
|             // Round to user desired precision based on format string |             // Round to user desired precision based on format string | ||||||
|             if (!(flags & ImGuiSliderFlags_NoRoundToFormat)) |             if (!(flags & ImGuiSliderFlags_NoRoundToFormat)) | ||||||
| @@ -2732,7 +2736,7 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ | |||||||
|     else |     else | ||||||
|     { |     { | ||||||
|         // Output grab position so it can be displayed by the caller |         // Output grab position so it can be displayed by the caller | ||||||
|         float grab_t = ScaleRatioFromValueT<TYPE, FLOATTYPE>(data_type, *v, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); |         float grab_t = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, *v, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); | ||||||
|         if (axis == ImGuiAxis_Y) |         if (axis == ImGuiAxis_Y) | ||||||
|             grab_t = 1.0f - grab_t; |             grab_t = 1.0f - grab_t; | ||||||
|         const float grab_pos = ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t); |         const float grab_pos = ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t); | ||||||
| @@ -3194,7 +3198,11 @@ bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImG | |||||||
|         // Apply new value (or operations) then clamp |         // Apply new value (or operations) then clamp | ||||||
|         DataTypeApplyOpFromText(data_buf, g.InputTextState.InitialTextA.Data, data_type, p_data, NULL); |         DataTypeApplyOpFromText(data_buf, g.InputTextState.InitialTextA.Data, data_type, p_data, NULL); | ||||||
|         if (p_clamp_min || p_clamp_max) |         if (p_clamp_min || p_clamp_max) | ||||||
|  |         { | ||||||
|  |             if (DataTypeCompare(data_type, p_clamp_min, p_clamp_max) > 0) | ||||||
|  |                 ImSwap(p_clamp_min, p_clamp_max); | ||||||
|             DataTypeClamp(data_type, p_data, p_clamp_min, p_clamp_max); |             DataTypeClamp(data_type, p_data, p_clamp_min, p_clamp_max); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         // Only mark as edited if new value is different |         // Only mark as edited if new value is different | ||||||
|         value_changed = memcmp(&data_backup, p_data, data_type_size) != 0; |         value_changed = memcmp(&data_backup, p_data, data_type_size) != 0; | ||||||
| @@ -3627,7 +3635,7 @@ void ImGuiInputTextCallbackData::DeleteChars(int pos, int bytes_count) | |||||||
|         *dst++ = c; |         *dst++ = c; | ||||||
|     *dst = '\0'; |     *dst = '\0'; | ||||||
|  |  | ||||||
|     if (CursorPos + bytes_count >= pos) |     if (CursorPos >= pos + bytes_count) | ||||||
|         CursorPos -= bytes_count; |         CursorPos -= bytes_count; | ||||||
|     else if (CursorPos >= pos) |     else if (CursorPos >= pos) | ||||||
|         CursorPos = pos; |         CursorPos = pos; | ||||||
| @@ -4432,11 +4440,14 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ | |||||||
|             // Vertical scroll |             // Vertical scroll | ||||||
|             if (is_multiline) |             if (is_multiline) | ||||||
|             { |             { | ||||||
|  |                 // Test if cursor is vertically visible | ||||||
|                 float scroll_y = draw_window->Scroll.y; |                 float scroll_y = draw_window->Scroll.y; | ||||||
|  |                 const float scroll_max_y = ImMax((text_size.y + style.FramePadding.y * 2.0f) - inner_size.y, 0.0f); | ||||||
|                 if (cursor_offset.y - g.FontSize < scroll_y) |                 if (cursor_offset.y - g.FontSize < scroll_y) | ||||||
|                     scroll_y = ImMax(0.0f, cursor_offset.y - g.FontSize); |                     scroll_y = ImMax(0.0f, cursor_offset.y - g.FontSize); | ||||||
|                 else if (cursor_offset.y - inner_size.y >= scroll_y) |                 else if (cursor_offset.y - inner_size.y >= scroll_y) | ||||||
|                     scroll_y = cursor_offset.y - inner_size.y; |                     scroll_y = cursor_offset.y - inner_size.y + style.FramePadding.y * 2.0f; | ||||||
|  |                 scroll_y = ImClamp(scroll_y, 0.0f, scroll_max_y); | ||||||
|                 draw_pos.y += (draw_window->Scroll.y - scroll_y);   // Manipulate cursor pos immediately avoid a frame of lag |                 draw_pos.y += (draw_window->Scroll.y - scroll_y);   // Manipulate cursor pos immediately avoid a frame of lag | ||||||
|                 draw_window->Scroll.y = scroll_y; |                 draw_window->Scroll.y = scroll_y; | ||||||
|             } |             } | ||||||
| @@ -4528,7 +4539,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ | |||||||
|  |  | ||||||
|     if (is_multiline) |     if (is_multiline) | ||||||
|     { |     { | ||||||
|         Dummy(text_size + ImVec2(0.0f, g.FontSize)); // Always add room to scroll an extra line |         Dummy(text_size); | ||||||
|         EndChild(); |         EndChild(); | ||||||
|         EndGroup(); |         EndGroup(); | ||||||
|     } |     } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 omar
					omar