mirror of
https://github.com/ocornut/imgui.git
synced 2024-12-05 06:57:13 +08:00
Examples: Using draw_data->DisplaySize, followup to c50198debe
. Fix Vulkan secondary viewport rendering. SDL+Vulkan: Matched changes. Fix vcprojs. (#1542, #1042)
This commit is contained in:
parent
921bb92eec
commit
98b66a5fc9
@ -42,8 +42,7 @@ struct CUSTOMVERTEX
|
|||||||
void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
|
void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
|
||||||
{
|
{
|
||||||
// Avoid rendering when minimized
|
// Avoid rendering when minimized
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
|
||||||
if (io.DisplaySize.x <= 0.0f || io.DisplaySize.y <= 0.0f)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Create and grow buffers if needed
|
// Create and grow buffers if needed
|
||||||
@ -101,8 +100,8 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
|
|||||||
// Setup viewport
|
// Setup viewport
|
||||||
D3DVIEWPORT9 vp;
|
D3DVIEWPORT9 vp;
|
||||||
vp.X = vp.Y = 0;
|
vp.X = vp.Y = 0;
|
||||||
vp.Width = (DWORD)io.DisplaySize.x;
|
vp.Width = (DWORD)draw_data->DisplaySize.x;
|
||||||
vp.Height = (DWORD)io.DisplaySize.y;
|
vp.Height = (DWORD)draw_data->DisplaySize.y;
|
||||||
vp.MinZ = 0.0f;
|
vp.MinZ = 0.0f;
|
||||||
vp.MaxZ = 1.0f;
|
vp.MaxZ = 1.0f;
|
||||||
g_pd3dDevice->SetViewport(&vp);
|
g_pd3dDevice->SetViewport(&vp);
|
||||||
@ -131,7 +130,10 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
|
|||||||
// Setup orthographic projection matrix
|
// Setup orthographic projection matrix
|
||||||
// Being agnostic of whether <d3dx9.h> or <DirectXMath.h> can be used, we aren't relying on D3DXMatrixIdentity()/D3DXMatrixOrthoOffCenterLH() or DirectX::XMMatrixIdentity()/DirectX::XMMatrixOrthographicOffCenterLH()
|
// Being agnostic of whether <d3dx9.h> or <DirectXMath.h> can be used, we aren't relying on D3DXMatrixIdentity()/D3DXMatrixOrthoOffCenterLH() or DirectX::XMMatrixIdentity()/DirectX::XMMatrixOrthographicOffCenterLH()
|
||||||
{
|
{
|
||||||
const float L = 0.5f, R = io.DisplaySize.x+0.5f, T = 0.5f, B = io.DisplaySize.y+0.5f;
|
float L = draw_data->DisplayPos.x + 0.5f;
|
||||||
|
float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x + 0.5f;
|
||||||
|
float T = draw_data->DisplayPos.y + 0.5f;
|
||||||
|
float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y + 0.5f;
|
||||||
D3DMATRIX mat_identity = { { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f } };
|
D3DMATRIX mat_identity = { { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f } };
|
||||||
D3DMATRIX mat_projection =
|
D3DMATRIX mat_projection =
|
||||||
{
|
{
|
||||||
|
@ -60,8 +60,8 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
|
|||||||
{
|
{
|
||||||
// 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)
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
int fb_width = (int)(io.DisplaySize.x * io.DisplayFramebufferScale.x);
|
int fb_width = (int)(draw_data->DisplaySize.x * io.DisplayFramebufferScale.x);
|
||||||
int fb_height = (int)(io.DisplaySize.y * io.DisplayFramebufferScale.y);
|
int fb_height = (int)(draw_data->DisplaySize.y * io.DisplayFramebufferScale.y);
|
||||||
if (fb_width == 0 || fb_height == 0)
|
if (fb_width == 0 || fb_height == 0)
|
||||||
return;
|
return;
|
||||||
draw_data->ScaleClipRects(io.DisplayFramebufferScale);
|
draw_data->ScaleClipRects(io.DisplayFramebufferScale);
|
||||||
|
@ -263,8 +263,8 @@ void ImGui_ImplVulkan_RenderDrawData(VkCommandBuffer command_buffer, ImDrawData*
|
|||||||
VkViewport viewport;
|
VkViewport viewport;
|
||||||
viewport.x = 0;
|
viewport.x = 0;
|
||||||
viewport.y = 0;
|
viewport.y = 0;
|
||||||
viewport.width = io.DisplaySize.x;
|
viewport.width = draw_data->DisplaySize.x;
|
||||||
viewport.height = io.DisplaySize.y;
|
viewport.height = draw_data->DisplaySize.y;
|
||||||
viewport.minDepth = 0.0f;
|
viewport.minDepth = 0.0f;
|
||||||
viewport.maxDepth = 1.0f;
|
viewport.maxDepth = 1.0f;
|
||||||
vkCmdSetViewport(command_buffer, 0, 1, &viewport);
|
vkCmdSetViewport(command_buffer, 0, 1, &viewport);
|
||||||
|
@ -121,7 +121,7 @@ int main(int, char**)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Rendering
|
// Rendering
|
||||||
glViewport(0, 0, (int)ImGui::GetIO().DisplaySize.x, (int)ImGui::GetIO().DisplaySize.y);
|
glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
|
||||||
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
|
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
//glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context where shaders may be bound
|
//glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context where shaders may be bound
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
#include <SDL_vulkan.h>
|
#include <SDL_vulkan.h>
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
// FIXME-VULKAN: Resizing with IMGUI_UNLIMITED_FRAME_RATE triggers errors from the validation layer.
|
|
||||||
#define IMGUI_UNLIMITED_FRAME_RATE
|
#define IMGUI_UNLIMITED_FRAME_RATE
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
#define IMGUI_VULKAN_DEBUG_REPORT
|
#define IMGUI_VULKAN_DEBUG_REPORT
|
||||||
@ -220,19 +219,20 @@ static void CleanupVulkan()
|
|||||||
vkDestroyInstance(g_Instance, g_Allocator);
|
vkDestroyInstance(g_Instance, g_Allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void FrameBegin(ImGui_ImplVulkan_WindowData* wd)
|
static void FrameRender(ImGui_ImplVulkan_WindowData* wd)
|
||||||
{
|
{
|
||||||
|
VkResult err;
|
||||||
|
|
||||||
|
VkSemaphore& image_acquired_semaphore = wd->Frames[wd->FrameIndex].ImageAcquiredSemaphore;
|
||||||
|
err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &wd->FrameIndex);
|
||||||
|
check_vk_result(err);
|
||||||
|
|
||||||
ImGui_ImplVulkan_FrameData* fd = &wd->Frames[wd->FrameIndex];
|
ImGui_ImplVulkan_FrameData* fd = &wd->Frames[wd->FrameIndex];
|
||||||
VkResult err;
|
|
||||||
for (;;)
|
|
||||||
{
|
{
|
||||||
err = vkWaitForFences(g_Device, 1, &fd->Fence, VK_TRUE, 100);
|
err = vkWaitForFences(g_Device, 1, &fd->Fence, VK_TRUE, UINT64_MAX); // wait indefinitely instead of periodically checking
|
||||||
if (err == VK_SUCCESS) break;
|
|
||||||
if (err == VK_TIMEOUT) continue;
|
|
||||||
check_vk_result(err);
|
check_vk_result(err);
|
||||||
}
|
|
||||||
{
|
err = vkResetFences(g_Device, 1, &fd->Fence);
|
||||||
err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, fd->PresentCompleteSemaphore, VK_NULL_HANDLE, &fd->BackbufferIndex);
|
|
||||||
check_vk_result(err);
|
check_vk_result(err);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
@ -248,26 +248,25 @@ static void FrameBegin(ImGui_ImplVulkan_WindowData* wd)
|
|||||||
VkRenderPassBeginInfo info = {};
|
VkRenderPassBeginInfo info = {};
|
||||||
info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||||
info.renderPass = wd->RenderPass;
|
info.renderPass = wd->RenderPass;
|
||||||
info.framebuffer = wd->Framebuffer[fd->BackbufferIndex];
|
info.framebuffer = wd->Framebuffer[wd->FrameIndex];
|
||||||
info.renderArea.extent.width = wd->Width;
|
info.renderArea.extent.width = wd->Width;
|
||||||
info.renderArea.extent.height = wd->Height;
|
info.renderArea.extent.height = wd->Height;
|
||||||
info.clearValueCount = 1;
|
info.clearValueCount = 1;
|
||||||
info.pClearValues = &wd->ClearValue;
|
info.pClearValues = &wd->ClearValue;
|
||||||
vkCmdBeginRenderPass(fd->CommandBuffer, &info, VK_SUBPASS_CONTENTS_INLINE);
|
vkCmdBeginRenderPass(fd->CommandBuffer, &info, VK_SUBPASS_CONTENTS_INLINE);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static void FrameEnd(ImGui_ImplVulkan_WindowData* wd)
|
// Record Imgui Draw Data and draw funcs into command buffer
|
||||||
{
|
ImGui_ImplVulkan_RenderDrawData(fd->CommandBuffer, ImGui::GetDrawData());
|
||||||
ImGui_ImplVulkan_FrameData* fd = &wd->Frames[wd->FrameIndex];
|
|
||||||
VkResult err;
|
// Submit command buffer
|
||||||
vkCmdEndRenderPass(fd->CommandBuffer);
|
vkCmdEndRenderPass(fd->CommandBuffer);
|
||||||
{
|
{
|
||||||
VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
VkSubmitInfo info = {};
|
VkSubmitInfo info = {};
|
||||||
info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||||
info.waitSemaphoreCount = 1;
|
info.waitSemaphoreCount = 1;
|
||||||
info.pWaitSemaphores = &fd->PresentCompleteSemaphore;
|
info.pWaitSemaphores = &image_acquired_semaphore;
|
||||||
info.pWaitDstStageMask = &wait_stage;
|
info.pWaitDstStageMask = &wait_stage;
|
||||||
info.commandBufferCount = 1;
|
info.commandBufferCount = 1;
|
||||||
info.pCommandBuffers = &fd->CommandBuffer;
|
info.pCommandBuffers = &fd->CommandBuffer;
|
||||||
@ -276,8 +275,6 @@ static void FrameEnd(ImGui_ImplVulkan_WindowData* wd)
|
|||||||
|
|
||||||
err = vkEndCommandBuffer(fd->CommandBuffer);
|
err = vkEndCommandBuffer(fd->CommandBuffer);
|
||||||
check_vk_result(err);
|
check_vk_result(err);
|
||||||
err = vkResetFences(g_Device, 1, &fd->Fence);
|
|
||||||
check_vk_result(err);
|
|
||||||
err = vkQueueSubmit(g_Queue, 1, &info, fd->Fence);
|
err = vkQueueSubmit(g_Queue, 1, &info, fd->Fence);
|
||||||
check_vk_result(err);
|
check_vk_result(err);
|
||||||
}
|
}
|
||||||
@ -285,23 +282,15 @@ static void FrameEnd(ImGui_ImplVulkan_WindowData* wd)
|
|||||||
|
|
||||||
static void FramePresent(ImGui_ImplVulkan_WindowData* wd)
|
static void FramePresent(ImGui_ImplVulkan_WindowData* wd)
|
||||||
{
|
{
|
||||||
VkResult err;
|
ImGui_ImplVulkan_FrameData* fd = &wd->Frames[wd->FrameIndex];
|
||||||
// If IMGUI_UNLIMITED_FRAME_RATE is defined we present the latest but one frame. Otherwise we present the latest rendered frame
|
|
||||||
#ifdef IMGUI_UNLIMITED_FRAME_RATE
|
|
||||||
uint32_t PresentIndex = (wd->FrameIndex + IMGUI_VK_QUEUED_FRAMES - 1) % IMGUI_VK_QUEUED_FRAMES;
|
|
||||||
#else
|
|
||||||
uint32_t PresentIndex = wd->FrameIndex;
|
|
||||||
#endif // IMGUI_UNLIMITED_FRAME_RATE
|
|
||||||
|
|
||||||
ImGui_ImplVulkan_FrameData* fd = &wd->Frames[PresentIndex];
|
|
||||||
VkPresentInfoKHR info = {};
|
VkPresentInfoKHR info = {};
|
||||||
info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||||
info.waitSemaphoreCount = 1;
|
info.waitSemaphoreCount = 1;
|
||||||
info.pWaitSemaphores = &fd->RenderCompleteSemaphore;
|
info.pWaitSemaphores = &fd->RenderCompleteSemaphore;
|
||||||
info.swapchainCount = 1;
|
info.swapchainCount = 1;
|
||||||
info.pSwapchains = &wd->Swapchain;
|
info.pSwapchains = &wd->Swapchain;
|
||||||
info.pImageIndices = &fd->BackbufferIndex;
|
info.pImageIndices = &wd->FrameIndex;
|
||||||
err = vkQueuePresentKHR(g_Queue, &info);
|
VkResult err = vkQueuePresentKHR(g_Queue, &info);
|
||||||
check_vk_result(err);
|
check_vk_result(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -329,6 +318,7 @@ int main(int, char**)
|
|||||||
|
|
||||||
// Create Window Surface
|
// Create Window Surface
|
||||||
VkSurfaceKHR surface;
|
VkSurfaceKHR surface;
|
||||||
|
VkResult err;
|
||||||
if (SDL_Vulkan_CreateSurface(window, g_Instance, &surface) == 0)
|
if (SDL_Vulkan_CreateSurface(window, g_Instance, &surface) == 0)
|
||||||
{
|
{
|
||||||
printf("Failed to create Vulkan surface.\n");
|
printf("Failed to create Vulkan surface.\n");
|
||||||
@ -348,6 +338,9 @@ int main(int, char**)
|
|||||||
io.ConfigFlags |= ImGuiConfigFlags_PlatformNoTaskBar;
|
io.ConfigFlags |= ImGuiConfigFlags_PlatformNoTaskBar;
|
||||||
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||||
|
|
||||||
|
// Setup SDL binding
|
||||||
|
ImGui_ImplSDL2_Init(window, NULL);
|
||||||
|
|
||||||
// Setup Vulkan binding
|
// Setup Vulkan binding
|
||||||
ImGui_ImplVulkan_InitInfo init_info = {};
|
ImGui_ImplVulkan_InitInfo init_info = {};
|
||||||
init_info.Instance = g_Instance;
|
init_info.Instance = g_Instance;
|
||||||
@ -359,7 +352,6 @@ int main(int, char**)
|
|||||||
init_info.DescriptorPool = g_DescriptorPool;
|
init_info.DescriptorPool = g_DescriptorPool;
|
||||||
init_info.Allocator = g_Allocator;
|
init_info.Allocator = g_Allocator;
|
||||||
init_info.CheckVkResultFn = check_vk_result;
|
init_info.CheckVkResultFn = check_vk_result;
|
||||||
ImGui_ImplSDL2_Init(window, NULL);
|
|
||||||
ImGui_ImplVulkan_Init(&init_info, wd->RenderPass);
|
ImGui_ImplVulkan_Init(&init_info, wd->RenderPass);
|
||||||
|
|
||||||
// Setup style
|
// Setup style
|
||||||
@ -387,7 +379,6 @@ int main(int, char**)
|
|||||||
VkCommandPool command_pool = wd->Frames[wd->FrameIndex].CommandPool;
|
VkCommandPool command_pool = wd->Frames[wd->FrameIndex].CommandPool;
|
||||||
VkCommandBuffer command_buffer = wd->Frames[wd->FrameIndex].CommandBuffer;
|
VkCommandBuffer command_buffer = wd->Frames[wd->FrameIndex].CommandBuffer;
|
||||||
|
|
||||||
VkResult err;
|
|
||||||
err = vkResetCommandPool(g_Device, command_pool, 0);
|
err = vkResetCommandPool(g_Device, command_pool, 0);
|
||||||
check_vk_result(err);
|
check_vk_result(err);
|
||||||
VkCommandBufferBeginInfo begin_info = {};
|
VkCommandBufferBeginInfo begin_info = {};
|
||||||
@ -416,8 +407,6 @@ int main(int, char**)
|
|||||||
bool show_another_window = false;
|
bool show_another_window = false;
|
||||||
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
|
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
|
||||||
|
|
||||||
bool swap_chain_has_at_least_one_image = false;
|
|
||||||
|
|
||||||
// Main loop
|
// Main loop
|
||||||
bool done = false;
|
bool done = false;
|
||||||
while (!done)
|
while (!done)
|
||||||
@ -478,26 +467,13 @@ int main(int, char**)
|
|||||||
// Rendering
|
// Rendering
|
||||||
ImGui::Render();
|
ImGui::Render();
|
||||||
memcpy(&wd->ClearValue.color.float32[0], &clear_color, 4 * sizeof(float));
|
memcpy(&wd->ClearValue.color.float32[0], &clear_color, 4 * sizeof(float));
|
||||||
FrameBegin(wd);
|
FrameRender(wd);
|
||||||
ImGui_ImplVulkan_RenderDrawData(wd->Frames[wd->FrameIndex].CommandBuffer, ImGui::GetDrawData());
|
|
||||||
FrameEnd(wd);
|
|
||||||
|
|
||||||
ImGui::RenderAdditionalViewports();
|
ImGui::RenderAdditionalViewports();
|
||||||
|
|
||||||
#ifdef IMGUI_UNLIMITED_FRAME_RATE
|
|
||||||
// When IMGUI_UNLIMITED_FRAME_RATE is defined we render into latest image acquired from the swapchain but we display the image which was rendered before.
|
|
||||||
// Hence we must render once and increase the FrameIndex without presenting.
|
|
||||||
if (swap_chain_has_at_least_one_image)
|
|
||||||
FramePresent(wd);
|
|
||||||
#else
|
|
||||||
FramePresent(wd);
|
FramePresent(wd);
|
||||||
#endif
|
|
||||||
swap_chain_has_at_least_one_image = true;
|
|
||||||
wd->FrameIndex = (wd->FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
VkResult err = vkDeviceWaitIdle(g_Device);
|
err = vkDeviceWaitIdle(g_Device);
|
||||||
check_vk_result(err);
|
check_vk_result(err);
|
||||||
ImGui_ImplVulkan_Shutdown();
|
ImGui_ImplVulkan_Shutdown();
|
||||||
ImGui_ImplSDL2_Shutdown();
|
ImGui_ImplSDL2_Shutdown();
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Globals">
|
<PropertyGroup Label="Globals">
|
||||||
<ProjectGuid>{BAE3D0B5-9695-4EB1-AD0F-75890EB4A3B3}</ProjectGuid>
|
<ProjectGuid>{BAE3D0B5-9695-4EB1-AD0F-75890EB4A3B3}</ProjectGuid>
|
||||||
<RootNamespace>opengl3_example</RootNamespace>
|
<RootNamespace>sdl_vulkan_example</RootNamespace>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Globals">
|
<PropertyGroup Label="Globals">
|
||||||
<ProjectGuid>{57E2DF5A-6FC8-45BB-99DD-91A18C646E80}</ProjectGuid>
|
<ProjectGuid>{57E2DF5A-6FC8-45BB-99DD-91A18C646E80}</ProjectGuid>
|
||||||
<RootNamespace>opengl3_example</RootNamespace>
|
<RootNamespace>vulkan_example</RootNamespace>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
Loading…
Reference in New Issue
Block a user