mirror of
https://github.com/Drezil/imgui.git
synced 2025-07-13 00:09:55 +02:00
Compare commits
16 Commits
Author | SHA1 | Date | |
---|---|---|---|
a8d3b045b7 | |||
a830037eab | |||
309ff44579 | |||
f30d23a502 | |||
a905505cca | |||
46eee0cee4 | |||
29863b55ef | |||
530f103dfe | |||
7a3e6aa38d | |||
cda3aecc6a | |||
b6d1d85d86 | |||
9a426faf4f | |||
b0d5600ffb | |||
c52a54ef43 | |||
cc9d63b46a | |||
d3ad5ce475 |
@ -1,11 +1,13 @@
|
||||
ImGui
|
||||
=====
|
||||
|
||||
ImGui is a bloat-free graphical user interface library for C++. It is portable, renderer agnostic and carries minimal amount of dependencies (only 3 files are needed). It is based on an "immediate" graphical user interface paradigm which allows you to build simple user interfaces with ease.
|
||||
ImGui is a bloat-free graphical user interface library for C++. It outputs vertex buffers that you can render in your 3D-pipeline enabled application. It is portable, renderer agnostic and carries minimal amount of dependencies (only 3 files are needed). It is based on an "immediate" graphical user interface paradigm which allows you to build simple user interfaces with ease.
|
||||
|
||||
ImGui is designed to allow programmers to create "content creation" or "debug" tools (as opposed to tools for the average end-user). It favors simplicity and thus lacks certain features normally found in more high-level libraries, such as string localisation.
|
||||
ImGui is designed to enable fast iteration and allow programmers to create "content creation" or "debug" tools (as opposed to tools for the average end-user). It favors simplicity and thus lacks certain features normally found in more high-level libraries, such as string localisation.
|
||||
|
||||
After ImGui is setup in your application, you can use it like in this example:
|
||||
ImGui is particularly suited to integration in 3D applications, fullscreen applications, embedded applications, games, or any applications on consoles platforms where operating system features are non-standard.
|
||||
|
||||
After ImGui is setup in your engine, you can use it like in this example:
|
||||
|
||||

|
||||
|
||||
|
@ -99,55 +99,6 @@ static void ImImpl_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_c
|
||||
}
|
||||
}
|
||||
|
||||
// Get text data in Win32 clipboard
|
||||
static const char* ImImpl_GetClipboardTextFn()
|
||||
{
|
||||
static char* buf_local = NULL;
|
||||
if (buf_local)
|
||||
{
|
||||
free(buf_local);
|
||||
buf_local = NULL;
|
||||
}
|
||||
|
||||
if (!OpenClipboard(NULL))
|
||||
return NULL;
|
||||
|
||||
HANDLE buf_handle = GetClipboardData(CF_TEXT);
|
||||
if (buf_handle == NULL)
|
||||
return NULL;
|
||||
|
||||
if (char* buf_global = (char*)GlobalLock(buf_handle))
|
||||
buf_local = strdup(buf_global);
|
||||
GlobalUnlock(buf_handle);
|
||||
CloseClipboard();
|
||||
|
||||
return buf_local;
|
||||
}
|
||||
|
||||
// Set text data in Win32 clipboard
|
||||
static void ImImpl_SetClipboardTextFn(const char* text, const char* text_end)
|
||||
{
|
||||
if (!OpenClipboard(NULL))
|
||||
return;
|
||||
|
||||
if (!text_end)
|
||||
text_end = text + strlen(text);
|
||||
|
||||
const int buf_length = (text_end - text) + 1;
|
||||
HGLOBAL buf_handle = GlobalAlloc(GMEM_MOVEABLE, buf_length * sizeof(char));
|
||||
if (buf_handle == NULL)
|
||||
return;
|
||||
|
||||
char* buf_global = (char *)GlobalLock(buf_handle);
|
||||
memcpy(buf_global, text, text_end - text);
|
||||
buf_global[text_end - text] = 0;
|
||||
GlobalUnlock(buf_handle);
|
||||
|
||||
EmptyClipboard();
|
||||
SetClipboardData(CF_TEXT, buf_handle);
|
||||
CloseClipboard();
|
||||
}
|
||||
|
||||
HRESULT InitD3D(HWND hWnd)
|
||||
{
|
||||
if (NULL == (g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)))
|
||||
@ -250,8 +201,6 @@ void InitImGui()
|
||||
io.KeyMap[ImGuiKey_Z] = 'Z';
|
||||
|
||||
io.RenderDrawListsFn = ImImpl_RenderDrawLists;
|
||||
io.SetClipboardTextFn = ImImpl_SetClipboardTextFn;
|
||||
io.GetClipboardTextFn = ImImpl_GetClipboardTextFn;
|
||||
|
||||
// Create the vertex buffer
|
||||
if (g_pd3dDevice->CreateVertexBuffer(10000 * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL) < 0)
|
||||
@ -271,6 +220,35 @@ void InitImGui()
|
||||
}
|
||||
}
|
||||
|
||||
INT64 ticks_per_second = 0;
|
||||
INT64 time = 0;
|
||||
|
||||
void UpdateImGui()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
// Setup timestep
|
||||
INT64 current_time;
|
||||
QueryPerformanceCounter((LARGE_INTEGER *)¤t_time);
|
||||
io.DeltaTime = (float)(current_time - time) / ticks_per_second;
|
||||
time = current_time;
|
||||
|
||||
// Setup inputs
|
||||
// (we already got mouse position, buttons, wheel from the window message callback)
|
||||
BYTE keystate[256];
|
||||
GetKeyboardState(keystate);
|
||||
for (int i = 0; i < 256; i++)
|
||||
io.KeysDown[i] = (keystate[i] & 0x80) != 0;
|
||||
io.KeyCtrl = (keystate[VK_CONTROL] & 0x80) != 0;
|
||||
io.KeyShift = (keystate[VK_SHIFT] & 0x80) != 0;
|
||||
// io.MousePos : filled by WM_MOUSEMOVE event
|
||||
// io.MouseDown : filled by WM_*BUTTON* events
|
||||
// io.MouseWheel : filled by WM_MOUSEWHEEL events
|
||||
|
||||
// Start the frame
|
||||
ImGui::NewFrame();
|
||||
}
|
||||
|
||||
int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE, LPWSTR, int)
|
||||
{
|
||||
// Register the window class
|
||||
@ -280,101 +258,91 @@ int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE, LPWSTR, int)
|
||||
// Create the application's window
|
||||
hWnd = CreateWindow(L"ImGui Example", L"ImGui DirectX9 Example", WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, NULL, NULL, wc.hInstance, NULL);
|
||||
|
||||
INT64 ticks_per_second, time;
|
||||
if (!QueryPerformanceFrequency((LARGE_INTEGER *)&ticks_per_second))
|
||||
return 1;
|
||||
if (!QueryPerformanceCounter((LARGE_INTEGER *)&time))
|
||||
return 1;
|
||||
|
||||
// Initialize Direct3D
|
||||
if (InitD3D(hWnd) >= 0)
|
||||
if (InitD3D(hWnd) < 0)
|
||||
{
|
||||
if (g_pVB)
|
||||
g_pVB->Release();
|
||||
UnregisterClass(L"ImGui Example", wc.hInstance);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Show the window
|
||||
ShowWindow(hWnd, SW_SHOWDEFAULT);
|
||||
UpdateWindow(hWnd);
|
||||
|
||||
InitImGui();
|
||||
|
||||
// Enter the message loop
|
||||
MSG msg;
|
||||
ZeroMemory(&msg, sizeof(msg));
|
||||
while (msg.message != WM_QUIT)
|
||||
{
|
||||
// Show the window
|
||||
ShowWindow(hWnd, SW_SHOWDEFAULT);
|
||||
UpdateWindow(hWnd);
|
||||
|
||||
InitImGui();
|
||||
|
||||
// Enter the message loop
|
||||
MSG msg;
|
||||
ZeroMemory(&msg, sizeof(msg));
|
||||
while (msg.message != WM_QUIT)
|
||||
if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
|
||||
{
|
||||
if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
continue;
|
||||
}
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 1) ImGui start frame, setup time delta & inputs
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
INT64 current_time;
|
||||
QueryPerformanceCounter((LARGE_INTEGER *)¤t_time);
|
||||
io.DeltaTime = (float)(current_time - time) / ticks_per_second;
|
||||
time = current_time;
|
||||
BYTE keystate[256];
|
||||
GetKeyboardState(keystate);
|
||||
for (int i = 0; i < 256; i++)
|
||||
io.KeysDown[i] = (keystate[i] & 0x80) != 0;
|
||||
io.KeyCtrl = (keystate[VK_CONTROL] & 0x80) != 0;
|
||||
io.KeyShift = (keystate[VK_SHIFT] & 0x80) != 0;
|
||||
// io.MousePos : filled by WM_MOUSEMOVE event
|
||||
// io.MouseDown : filled by WM_*BUTTON* events
|
||||
// io.MouseWheel : filled by WM_MOUSEWHEEL events
|
||||
ImGui::NewFrame();
|
||||
UpdateImGui();
|
||||
|
||||
// 2) ImGui usage
|
||||
static bool show_test_window = true;
|
||||
static bool show_another_window = false;
|
||||
static float f;
|
||||
ImGui::Text("Hello, world!");
|
||||
ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
|
||||
show_test_window ^= ImGui::Button("Test Window");
|
||||
show_another_window ^= ImGui::Button("Another Window");
|
||||
// Create a simple window
|
||||
// Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug"
|
||||
static bool show_test_window = true;
|
||||
static bool show_another_window = false;
|
||||
static float f;
|
||||
ImGui::Text("Hello, world!");
|
||||
ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
|
||||
show_test_window ^= ImGui::Button("Test Window");
|
||||
show_another_window ^= ImGui::Button("Another Window");
|
||||
|
||||
// Calculate and show framerate
|
||||
static float ms_per_frame[120] = { 0 };
|
||||
static int ms_per_frame_idx = 0;
|
||||
static float ms_per_frame_accum = 0.0f;
|
||||
ms_per_frame_accum -= ms_per_frame[ms_per_frame_idx];
|
||||
ms_per_frame[ms_per_frame_idx] = io.DeltaTime * 1000.0f;
|
||||
ms_per_frame_accum += ms_per_frame[ms_per_frame_idx];
|
||||
ms_per_frame_idx = (ms_per_frame_idx + 1) % 120;
|
||||
const float ms_per_frame_avg = ms_per_frame_accum / 120;
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", ms_per_frame_avg, 1000.0f / ms_per_frame_avg);
|
||||
// Calculate and show framerate
|
||||
static float ms_per_frame[120] = { 0 };
|
||||
static int ms_per_frame_idx = 0;
|
||||
static float ms_per_frame_accum = 0.0f;
|
||||
ms_per_frame_accum -= ms_per_frame[ms_per_frame_idx];
|
||||
ms_per_frame[ms_per_frame_idx] = ImGui::GetIO().DeltaTime * 1000.0f;
|
||||
ms_per_frame_accum += ms_per_frame[ms_per_frame_idx];
|
||||
ms_per_frame_idx = (ms_per_frame_idx + 1) % 120;
|
||||
const float ms_per_frame_avg = ms_per_frame_accum / 120;
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", ms_per_frame_avg, 1000.0f / ms_per_frame_avg);
|
||||
|
||||
if (show_test_window)
|
||||
{
|
||||
// More example code in ShowTestWindow()
|
||||
ImGui::SetNewWindowDefaultPos(ImVec2(650, 20)); // Normally user code doesn't need/want to call it because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly!
|
||||
ImGui::ShowTestWindow(&show_test_window);
|
||||
}
|
||||
|
||||
if (show_another_window)
|
||||
{
|
||||
ImGui::Begin("Another Window", &show_another_window, ImVec2(200,100));
|
||||
ImGui::Text("Hello");
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// 3) Rendering
|
||||
// Clear frame buffer
|
||||
g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, false);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, false);
|
||||
g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(204, 153, 153), 1.0f, 0);
|
||||
if (g_pd3dDevice->BeginScene() >= 0)
|
||||
{
|
||||
// Render ImGui
|
||||
ImGui::Render();
|
||||
g_pd3dDevice->EndScene();
|
||||
}
|
||||
g_pd3dDevice->Present(NULL, NULL, NULL, NULL);
|
||||
// Show the ImGui test window
|
||||
// Most of user example code is in ImGui::ShowTestWindow()
|
||||
if (show_test_window)
|
||||
{
|
||||
ImGui::SetNewWindowDefaultPos(ImVec2(650, 20)); // Normally user code doesn't need/want to call it because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly!
|
||||
ImGui::ShowTestWindow(&show_test_window);
|
||||
}
|
||||
|
||||
ImGui::Shutdown();
|
||||
}
|
||||
// Show another simple window
|
||||
if (show_another_window)
|
||||
{
|
||||
ImGui::Begin("Another Window", &show_another_window, ImVec2(200,100));
|
||||
ImGui::Text("Hello");
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// Rendering
|
||||
g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, false);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, false);
|
||||
g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(204, 153, 153), 1.0f, 0);
|
||||
if (g_pd3dDevice->BeginScene() >= 0)
|
||||
{
|
||||
ImGui::Render();
|
||||
g_pd3dDevice->EndScene();
|
||||
}
|
||||
g_pd3dDevice->Present(NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
ImGui::Shutdown();
|
||||
|
||||
if (g_pVB)
|
||||
g_pVB->Release();
|
||||
|
@ -5,7 +5,8 @@
|
||||
#
|
||||
|
||||
CXXFLAGS=-framework OpenGL -framework Cocoa -framework IOKit
|
||||
#CXXFLAGS+=-L/usr/local/Cellar/glew/1.10.0/lib -L/usr/local/Cellar/glfw3/3.0.4/lib
|
||||
CXXFLAGS+=-I/usr/local/Cellar/glew/1.10.0/include -I/usr/local/Cellar/glfw3/3.0.4/include
|
||||
CXXFLAGS+=-L/usr/local/Cellar/glew/1.10.0/lib -L/usr/local/Cellar/glfw3/3.0.4/lib
|
||||
CXXFLAGS+=-lglew -lglfw3
|
||||
CXXFLAGS+=-I../../
|
||||
CXXFLAGS+= -D__APPLE__
|
||||
|
@ -19,24 +19,26 @@ static void ImImpl_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_c
|
||||
if (cmd_lists_count == 0)
|
||||
return;
|
||||
|
||||
// Setup render state: alpha-blending enabled, no face culling, no depth testing
|
||||
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers.
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
//glEnable(GL_SCISSOR_TEST);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
// Bind texture
|
||||
// Setup texture
|
||||
glBindTexture(GL_TEXTURE_2D, fontTex);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
// Setup matrices
|
||||
// Setup orthographic projection matrix
|
||||
const float width = ImGui::GetIO().DisplaySize.x;
|
||||
const float height = ImGui::GetIO().DisplaySize.y;
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glOrtho(0.0f, ImGui::GetIO().DisplaySize.x, ImGui::GetIO().DisplaySize.y, 0.0f, -1.0f, +1.0f);
|
||||
glOrtho(0.0f, width, height, 0.0f, -1.0f, +1.0f);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
@ -53,7 +55,7 @@ static void ImImpl_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_c
|
||||
const ImDrawCmd* pcmd_end = cmd_list->commands.end();
|
||||
for (const ImDrawCmd* pcmd = cmd_list->commands.begin(); pcmd != pcmd_end; pcmd++)
|
||||
{
|
||||
glScissor((int)pcmd->clip_rect.x, (int)pcmd->clip_rect.y, (int)(pcmd->clip_rect.z - pcmd->clip_rect.x), (int)(pcmd->clip_rect.w - pcmd->clip_rect.y));
|
||||
glScissor((int)pcmd->clip_rect.x, (int)(height - pcmd->clip_rect.w), (int)(pcmd->clip_rect.z - pcmd->clip_rect.x), (int)(pcmd->clip_rect.w - pcmd->clip_rect.y));
|
||||
glDrawArrays(GL_TRIANGLES, vtx_offset, pcmd->vtx_count);
|
||||
vtx_offset += pcmd->vtx_count;
|
||||
}
|
||||
@ -71,24 +73,33 @@ static void ImImpl_SetClipboardTextFn(const char* text, const char* text_end)
|
||||
if (!text_end)
|
||||
text_end = text + strlen(text);
|
||||
|
||||
// Add a zero-terminator because glfw function doesn't take a size
|
||||
char* buf = (char*)malloc(text_end - text + 1);
|
||||
memcpy(buf, text, text_end-text);
|
||||
buf[text_end-text] = '\0';
|
||||
glfwSetClipboardString(window, buf);
|
||||
free(buf);
|
||||
if (*text_end == 0)
|
||||
{
|
||||
// Already got a zero-terminator at 'text_end', we don't need to add one
|
||||
glfwSetClipboardString(window, text);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add a zero-terminator because glfw function doesn't take a size
|
||||
char* buf = (char*)malloc(text_end - text + 1);
|
||||
memcpy(buf, text, text_end-text);
|
||||
buf[text_end-text] = '\0';
|
||||
glfwSetClipboardString(window, buf);
|
||||
free(buf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// GLFW callbacks to get events
|
||||
static void glfw_error_callback(int error, const char* description)
|
||||
{
|
||||
fputs(description, stderr);
|
||||
}
|
||||
|
||||
static float mouse_wheel = 0.0f;
|
||||
static void glfw_scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
|
||||
{
|
||||
mouse_wheel = (float)yoffset;
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.MouseWheel = (yoffset != 0.0f) ? yoffset > 0.0f ? 1 : - 1 : 0; // Mouse wheel: -1,0,+1
|
||||
}
|
||||
|
||||
static void glfw_key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
|
||||
@ -171,37 +182,43 @@ void InitImGui()
|
||||
stbi_image_free(tex_data);
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
void UpdateImGui()
|
||||
{
|
||||
ImGui::Shutdown();
|
||||
glfwTerminate();
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
// Setup timestep
|
||||
static double time = 0.0f;
|
||||
const double current_time = glfwGetTime();
|
||||
io.DeltaTime = (float)(current_time - time);
|
||||
time = current_time;
|
||||
|
||||
// Setup inputs
|
||||
// (we already got mouse wheel, keyboard keys & characters from glfw callbacks polled in glfwPollEvents())
|
||||
double mouse_x, mouse_y;
|
||||
glfwGetCursorPos(window, &mouse_x, &mouse_y);
|
||||
io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.)
|
||||
io.MouseDown[0] = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) != 0;
|
||||
io.MouseDown[1] = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT) != 0;
|
||||
|
||||
// Start the frame
|
||||
ImGui::NewFrame();
|
||||
}
|
||||
|
||||
// Application code
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
InitGL();
|
||||
InitImGui();
|
||||
|
||||
double time = glfwGetTime();
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.MouseWheel = 0;
|
||||
glfwPollEvents();
|
||||
UpdateImGui();
|
||||
|
||||
// 1) ImGui start frame, setup time delta & inputs
|
||||
const double current_time = glfwGetTime();
|
||||
io.DeltaTime = (float)(current_time - time);
|
||||
time = current_time;
|
||||
double mouse_x, mouse_y;
|
||||
glfwGetCursorPos(window, &mouse_x, &mouse_y);
|
||||
io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.)
|
||||
io.MouseDown[0] = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) != 0;
|
||||
io.MouseDown[1] = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT) != 0;
|
||||
io.MouseWheel = (mouse_wheel != 0) ? mouse_wheel > 0.0f ? 1 : - 1 : 0; // Mouse wheel: -1,0,+1
|
||||
mouse_wheel = 0.0f;
|
||||
ImGui::NewFrame();
|
||||
|
||||
// 2) ImGui usage
|
||||
// Create a simple window
|
||||
// Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug"
|
||||
static bool show_test_window = true;
|
||||
static bool show_another_window = false;
|
||||
static float f;
|
||||
@ -215,19 +232,21 @@ int main(int argc, char** argv)
|
||||
static int ms_per_frame_idx = 0;
|
||||
static float ms_per_frame_accum = 0.0f;
|
||||
ms_per_frame_accum -= ms_per_frame[ms_per_frame_idx];
|
||||
ms_per_frame[ms_per_frame_idx] = io.DeltaTime * 1000.0f;
|
||||
ms_per_frame[ms_per_frame_idx] = ImGui::GetIO().DeltaTime * 1000.0f;
|
||||
ms_per_frame_accum += ms_per_frame[ms_per_frame_idx];
|
||||
ms_per_frame_idx = (ms_per_frame_idx + 1) % 120;
|
||||
const float ms_per_frame_avg = ms_per_frame_accum / 120;
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", ms_per_frame_avg, 1000.0f / ms_per_frame_avg);
|
||||
|
||||
// Show the ImGui test window
|
||||
// Most of user example code is in ImGui::ShowTestWindow()
|
||||
if (show_test_window)
|
||||
{
|
||||
// More example code in ShowTestWindow()
|
||||
ImGui::SetNewWindowDefaultPos(ImVec2(650, 20)); // Normally user code doesn't need/want to call it because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly!
|
||||
ImGui::ShowTestWindow(&show_test_window);
|
||||
}
|
||||
|
||||
// Show another simple window
|
||||
if (show_another_window)
|
||||
{
|
||||
ImGui::Begin("Another Window", &show_another_window, ImVec2(200,100));
|
||||
@ -235,15 +254,15 @@ int main(int argc, char** argv)
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// 3) Rendering
|
||||
// Rendering
|
||||
glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
|
||||
glClearColor(0.8f, 0.6f, 0.6f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
ImGui::Render();
|
||||
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
|
||||
Shutdown();
|
||||
ImGui::Shutdown();
|
||||
glfwTerminate();
|
||||
return 0;
|
||||
}
|
||||
|
19
imconfig.h
19
imconfig.h
@ -4,15 +4,22 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
//----- Define your own ImVector<> type if you don't want to use the provided implementation defined in imgui.h
|
||||
//---- Define your own ImVector<> type if you don't want to use the provided implementation defined in imgui.h
|
||||
//#include <vector>
|
||||
//#define ImVector std::vector
|
||||
//#define ImVector MyVector
|
||||
|
||||
//----- Define assertion handler. Default to calling assert().
|
||||
// #define IM_ASSERT(_EXPR) MyAssert(_EXPR)
|
||||
//---- Define assertion handler. Defaults to calling assert().
|
||||
//#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
|
||||
|
||||
//----- Define implicit cast operators to convert back<>forth from your math types and ImVec2/ImVec4.
|
||||
//---- Don't implement default clipboard handlers for Windows (so as not to link with OpenClipboard(), etc.)
|
||||
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS
|
||||
|
||||
//---- If you are loading a custom font, ImGui expect to find a pure white pixel at (0,0)
|
||||
// Change it's UV coordinate here if you can't have a white pixel at (0,0)
|
||||
//#define IMGUI_FONT_TEX_UV_FOR_WHITE ImVec2(0.f/256.f,0.f/256.f)
|
||||
|
||||
//---- Define implicit cast operators to convert back<>forth from your math types and ImVec2/ImVec4.
|
||||
/*
|
||||
#define IM_VEC2_CLASS_EXTRA \
|
||||
ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \
|
||||
@ -23,8 +30,8 @@
|
||||
operator MyVec4() const { return MyVec4(x,y,z,w); }
|
||||
*/
|
||||
|
||||
//----- Freely implement extra functions within the ImGui:: namespace.
|
||||
//----- e.g. you can create variants of the ImGui::Value() helper for your low-level math types.
|
||||
//---- Freely implement extra functions within the ImGui:: namespace.
|
||||
//---- e.g. you can create variants of the ImGui::Value() helper for your low-level math types.
|
||||
/*
|
||||
namespace ImGui
|
||||
{
|
||||
|
333
imgui.cpp
333
imgui.cpp
@ -101,7 +101,7 @@
|
||||
|
||||
- if you want to use a different font than the default
|
||||
- create bitmap font data using BMFont. allocate ImGui::GetIO().Font and use ->LoadFromFile()/LoadFromMemory(), set ImGui::GetIO().FontHeight
|
||||
- load your texture yourself. texture *MUST* have white pixel at UV coordinate 'IMDRAW_TEX_UV_FOR_WHITE' (you can #define it in imconfig.h), this is used by solid objects.
|
||||
- load your texture yourself. texture *MUST* have white pixel at UV coordinate 'IMGUI_FONT_TEX_UV_FOR_WHITE' (you can #define it in imconfig.h), this is used by solid objects.
|
||||
|
||||
- tip: the construct 'if (IMGUI_ONCE_UPON_A_FRAME)' will evaluate to true only once a frame, you can use it to add custom UI in the middle of a deep nested inner loop in your code.
|
||||
- tip: you can call Render() multiple times (e.g for VR renders), up to you to communicate the extra state to your RenderDrawListFn function.
|
||||
@ -110,18 +110,20 @@
|
||||
ISSUES AND TODO-LIST
|
||||
|
||||
- misc: merge ImVec4 / ImGuiAabb, they are essentially duplicate containers
|
||||
- main: make IsHovered() more consistent for various type of widgets, widgets with multiple components, etc. also effectively IsHovered() region sometimes differs from hot region, e.g tree nodes
|
||||
- window: autofit is losing its purpose when user relies on any dynamic layout (window width multiplier, column). maybe just discard autofit?
|
||||
- window: support horizontal scroll
|
||||
- window: fix resize grip scaling along with Rounding style setting
|
||||
- window/style: add global alpha modifier (not just "fill_alpha")
|
||||
- widgets: switching from "widget-label" to "label-widget" would make it more convenient to integrate widgets in trees
|
||||
- widgets: clip text? hover clipped text shows it in a tooltip or in-place overlay
|
||||
- main: make IsHovered() more consistent for various type of widgets, widgets with multiple components, etc. also effectively IsHovered() region sometimes differs from hot region, e.g tree nodes
|
||||
- main: make IsHovered() info stored in a stack? so that 'if TreeNode() { Text; TreePop; } if IsHovered' return the hover state of the TreeNode?
|
||||
- scrollbar: use relative mouse movement when first-clicking inside of scroll grab box.
|
||||
- input number: optional range min/max
|
||||
- input number: holding [-]/[+] buttons should increase the step non-linearly
|
||||
- input number: rename Input*() to Input(), Slider*() to Slider() ?
|
||||
- layout: clean up the InputFloat3/SliderFloat3/ColorEdit4 horrible layout code. item width should include frame padding, then we can have a generic horizontal layout helper.
|
||||
- add input2/4 helper (once above layout helpers are in they'll be smaller)
|
||||
- add input4 helper (once above layout helpers are in they'll be smaller)
|
||||
- columns: declare column set (each column: fixed size, %, fill, distribute default size among fills)
|
||||
- columns: columns header to act as button (~sort op) and allow resize/reorder
|
||||
- columns: user specify columns size
|
||||
@ -144,7 +146,6 @@
|
||||
- filters: handle wildcards (with implicit leading/trailing *), regexps
|
||||
- shortcuts: add a shortcut api, e.g. parse "&Save" and/or "Save (CTRL+S)", pass in to widgets or provide simple ways to use (button=activate, input=focus)
|
||||
- keyboard: full keyboard navigation and focus
|
||||
- clipboard: add a default "local" implementation of clipboard functions (user will only need to override them to connect to OS clipboard)
|
||||
- misc: not thread-safe
|
||||
- optimisation/render: use indexed rendering
|
||||
- optimisation/render: move clip-rect to vertex data? would allow merging all commands
|
||||
@ -152,8 +153,6 @@
|
||||
- optimisation: turn some the various stack vectors into statically-sized arrays
|
||||
- optimisation: better clipping for multi-component widgets
|
||||
- optimisation: specialize for height based clipping first (assume widgets never go up + height tests before width tests?)
|
||||
- optimisation/portability: provide ImVector style implementation
|
||||
- optimisation/portability: remove dependency on <algorithm>
|
||||
*/
|
||||
|
||||
#include "imgui.h"
|
||||
@ -195,6 +194,13 @@ static ImGuiWindow* FindHoveredWindow(ImVec2 pos, bool excluding_childs);
|
||||
|
||||
}; // namespace ImGui
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Platform dependant default implementations
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static const char* GetClipboardTextFn_DefaultImpl();
|
||||
static void SetClipboardTextFn_DefaultImpl(const char* text, const char* text_end);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// User facing structures
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -267,6 +273,10 @@ ImGuiIO::ImGuiIO()
|
||||
MousePosPrev = ImVec2(-1,-1);
|
||||
MouseDoubleClickTime = 0.30f;
|
||||
MouseDoubleClickMaxDist = 6.0f;
|
||||
|
||||
// Platform dependant default implementations
|
||||
GetClipboardTextFn = GetClipboardTextFn_DefaultImpl;
|
||||
SetClipboardTextFn = SetClipboardTextFn_DefaultImpl;
|
||||
}
|
||||
|
||||
// Pass in translated ASCII characters for text input.
|
||||
@ -286,8 +296,7 @@ void ImGuiIO::AddInputCharacter(char c)
|
||||
// Helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#undef ARRAYSIZE
|
||||
#define ARRAYSIZE(_ARR) ((int)(sizeof(_ARR)/sizeof(*_ARR)))
|
||||
#define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR)/sizeof(*_ARR)))
|
||||
|
||||
#undef PI
|
||||
const float PI = 3.14159265358979323846f;
|
||||
@ -420,7 +429,7 @@ static void ImConvertColorRGBtoHSV(float r, float g, float b, float& out_h, floa
|
||||
}
|
||||
|
||||
const float chroma = r - (g < b ? g : b);
|
||||
out_h = abs(K + (g - b) / (6.f * chroma + 1e-20f));
|
||||
out_h = fabsf(K + (g - b) / (6.f * chroma + 1e-20f));
|
||||
out_s = chroma / (r + 1e-20f);
|
||||
out_v = r;
|
||||
}
|
||||
@ -497,6 +506,7 @@ struct ImGuiDrawContext
|
||||
float PrevLineHeight;
|
||||
float LogLineHeight;
|
||||
int TreeDepth;
|
||||
ImGuiAabb LastItemAabb;
|
||||
bool LastItemHovered;
|
||||
ImVector<ImGuiWindow*> ChildWindows;
|
||||
ImVector<bool> AllowKeyboardFocus;
|
||||
@ -519,6 +529,7 @@ struct ImGuiDrawContext
|
||||
CurrentLineHeight = PrevLineHeight = 0.0f;
|
||||
LogLineHeight = -1.0f;
|
||||
TreeDepth = 0;
|
||||
LastItemAabb = ImGuiAabb(0.0f,0.0f,0.0f,0.0f);
|
||||
LastItemHovered = false;
|
||||
StateStorage = NULL;
|
||||
OpenNextNode = -1;
|
||||
@ -608,6 +619,7 @@ struct ImGuiState
|
||||
ImGuiStorage ColorEditModeStorage; // for user selection
|
||||
ImGuiID ActiveComboID;
|
||||
char Tooltip[1024];
|
||||
char* PrivateClipboard; // if no custom clipboard handler is defined
|
||||
|
||||
// Logging
|
||||
bool LogEnabled;
|
||||
@ -631,6 +643,7 @@ struct ImGuiState
|
||||
SliderAsInputTextId = 0;
|
||||
ActiveComboID = 0;
|
||||
memset(Tooltip, 0, sizeof(Tooltip));
|
||||
PrivateClipboard = NULL;
|
||||
LogEnabled = false;
|
||||
LogFile = NULL;
|
||||
LogAutoExpandMaxDepth = 2;
|
||||
@ -794,7 +807,7 @@ void ImGuiTextFilter::Draw(const char* label, float width)
|
||||
width = ImMax(window->Pos.x + ImGui::GetWindowContentRegionMax().x - window->DC.CursorPos.x - (label_size.x + GImGui.Style.ItemSpacing.x*4), 10.0f);
|
||||
}
|
||||
ImGui::PushItemWidth(width);
|
||||
ImGui::InputText(label, InputBuf, ARRAYSIZE(InputBuf));
|
||||
ImGui::InputText(label, InputBuf, IM_ARRAYSIZE(InputBuf));
|
||||
ImGui::PopItemWidth();
|
||||
Build();
|
||||
}
|
||||
@ -1036,7 +1049,7 @@ static void LoadSettings()
|
||||
if (fseek(f, 0, SEEK_SET))
|
||||
return;
|
||||
char* f_data = new char[f_size+1];
|
||||
f_size = fread(f_data, 1, f_size, f); // Text conversion alter read size so let's not be fussy about return value
|
||||
f_size = (long)fread(f_data, 1, f_size, f); // Text conversion alter read size so let's not be fussy about return value
|
||||
fclose(f);
|
||||
if (f_size == 0)
|
||||
{
|
||||
@ -1056,7 +1069,7 @@ static void LoadSettings()
|
||||
if (line_start[0] == '[' && line_end > line_start && line_end[-1] == ']')
|
||||
{
|
||||
char name[64];
|
||||
ImFormatString(name, ARRAYSIZE(name), "%.*s", line_end-line_start-2, line_start+1);
|
||||
ImFormatString(name, IM_ARRAYSIZE(name), "%.*s", line_end-line_start-2, line_start+1);
|
||||
settings = FindWindowSettings(name);
|
||||
}
|
||||
else if (settings)
|
||||
@ -1171,7 +1184,7 @@ void NewFrame()
|
||||
else
|
||||
g.IO.MouseDelta = g.IO.MousePos - g.IO.MousePosPrev;
|
||||
g.IO.MousePosPrev = g.IO.MousePos;
|
||||
for (size_t i = 0; i < ARRAYSIZE(g.IO.MouseDown); i++)
|
||||
for (size_t i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++)
|
||||
{
|
||||
g.IO.MouseDownTime[i] = g.IO.MouseDown[i] ? (g.IO.MouseDownTime[i] < 0.0f ? 0.0f : g.IO.MouseDownTime[i] + g.IO.DeltaTime) : -1.0f;
|
||||
g.IO.MouseClicked[i] = (g.IO.MouseDownTime[i] == 0.0f);
|
||||
@ -1191,7 +1204,7 @@ void NewFrame()
|
||||
}
|
||||
}
|
||||
}
|
||||
for (size_t i = 0; i < ARRAYSIZE(g.IO.KeysDown); i++)
|
||||
for (size_t i = 0; i < IM_ARRAYSIZE(g.IO.KeysDown); i++)
|
||||
g.IO.KeysDownTime[i] = g.IO.KeysDown[i] ? (g.IO.KeysDownTime[i] < 0.0f ? 0.0f : g.IO.KeysDownTime[i] + g.IO.DeltaTime) : -1.0f;
|
||||
|
||||
// Clear reference to active widget if the widget isn't alive anymore
|
||||
@ -1291,6 +1304,12 @@ void Shutdown()
|
||||
g.IO.Font = NULL;
|
||||
}
|
||||
|
||||
if (g.PrivateClipboard)
|
||||
{
|
||||
free(g.PrivateClipboard);
|
||||
g.PrivateClipboard = NULL;
|
||||
}
|
||||
|
||||
g.Initialized = false;
|
||||
}
|
||||
|
||||
@ -1604,7 +1623,7 @@ static bool IsKeyPressedMap(ImGuiKey key, bool repeat)
|
||||
bool IsKeyPressed(int key_index, bool repeat)
|
||||
{
|
||||
ImGuiState& g = GImGui;
|
||||
IM_ASSERT(key_index >= 0 && key_index < ARRAYSIZE(g.IO.KeysDown));
|
||||
IM_ASSERT(key_index >= 0 && key_index < IM_ARRAYSIZE(g.IO.KeysDown));
|
||||
const float t = g.IO.KeysDownTime[key_index];
|
||||
if (t == 0.0f)
|
||||
return true;
|
||||
@ -1622,7 +1641,7 @@ bool IsKeyPressed(int key_index, bool repeat)
|
||||
bool IsMouseClicked(int button, bool repeat)
|
||||
{
|
||||
ImGuiState& g = GImGui;
|
||||
IM_ASSERT(button >= 0 && button < ARRAYSIZE(g.IO.MouseDown));
|
||||
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
|
||||
const float t = g.IO.MouseDownTime[button];
|
||||
if (t == 0.0f)
|
||||
return true;
|
||||
@ -1640,7 +1659,7 @@ bool IsMouseClicked(int button, bool repeat)
|
||||
bool IsMouseDoubleClicked(int button)
|
||||
{
|
||||
ImGuiState& g = GImGui;
|
||||
IM_ASSERT(button >= 0 && button < ARRAYSIZE(g.IO.MouseDown));
|
||||
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
|
||||
return g.IO.MouseDoubleClicked[button];
|
||||
}
|
||||
|
||||
@ -1655,12 +1674,24 @@ bool IsHovered()
|
||||
return window->DC.LastItemHovered;
|
||||
}
|
||||
|
||||
ImVec2 GetItemBoxMin()
|
||||
{
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
return window->DC.LastItemAabb.Min;
|
||||
}
|
||||
|
||||
ImVec2 GetItemBoxMax()
|
||||
{
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
return window->DC.LastItemAabb.Max;
|
||||
}
|
||||
|
||||
void SetTooltip(const char* fmt, ...)
|
||||
{
|
||||
ImGuiState& g = GImGui;
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
ImFormatStringV(g.Tooltip, ARRAYSIZE(g.Tooltip), fmt, args);
|
||||
ImFormatStringV(g.Tooltip, IM_ARRAYSIZE(g.Tooltip), fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
@ -1713,7 +1744,7 @@ void BeginChild(const char* str_id, ImVec2 size, bool border, ImGuiWindowFlags e
|
||||
flags |= extra_flags;
|
||||
|
||||
char title[256];
|
||||
ImFormatString(title, ARRAYSIZE(title), "%s.%s", window->Name, str_id);
|
||||
ImFormatString(title, IM_ARRAYSIZE(title), "%s.%s", window->Name, str_id);
|
||||
|
||||
const float alpha = (flags & ImGuiWindowFlags_ComboBox) ? 1.0f : 0.0f;
|
||||
ImGui::Begin(title, NULL, size, alpha, flags);
|
||||
@ -1802,13 +1833,13 @@ bool Begin(const char* name, bool* open, ImVec2 size, float fill_alpha, ImGuiWin
|
||||
parent_window->DC.ChildWindows.push_back(window);
|
||||
window->Pos = window->PosFloat = parent_window->DC.CursorPos;
|
||||
window->SizeFull = size;
|
||||
if (!(flags & ImGuiWindowFlags_ComboBox))
|
||||
ImGui::PushClipRect(parent_window->ClipRectStack.back());
|
||||
}
|
||||
|
||||
// Outer clipping rectangle
|
||||
if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_ComboBox))
|
||||
ImGui::PushClipRect(g.CurrentWindowStack[g.CurrentWindowStack.size()-2]->ClipRectStack.back());
|
||||
else
|
||||
{
|
||||
ImGui::PushClipRect(ImVec4(0.0f, 0.0f, g.IO.DisplaySize.x, g.IO.DisplaySize.y));
|
||||
}
|
||||
|
||||
// ID stack
|
||||
window->IDStack.resize(0);
|
||||
@ -2049,8 +2080,16 @@ bool Begin(const char* name, bool* open, ImVec2 size, float fill_alpha, ImGuiWin
|
||||
ImGui::CloseWindowButton(open);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Outer clipping rectangle
|
||||
if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_ComboBox))
|
||||
ImGui::PushClipRect(g.CurrentWindowStack[g.CurrentWindowStack.size()-2]->ClipRectStack.back());
|
||||
else
|
||||
ImGui::PushClipRect(ImVec4(0.0f, 0.0f, g.IO.DisplaySize.x, g.IO.DisplaySize.y));
|
||||
}
|
||||
|
||||
// Clip rectangle
|
||||
// Innter clipping rectangle
|
||||
// We set this up after processing the resize grip so that our clip rectangle doesn't lag by a frame
|
||||
const ImGuiAabb title_bar_aabb = window->TitleBarAabb();
|
||||
ImVec4 clip_rect(title_bar_aabb.Min.x+0.5f, title_bar_aabb.Max.y+0.5f, window->Aabb().Max.x-1.5f, window->Aabb().Max.y-1.5f);
|
||||
@ -2074,16 +2113,8 @@ void End()
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
|
||||
ImGui::Columns(1, "#CloseColumns");
|
||||
ImGui::PopClipRect();
|
||||
if (window->Flags & ImGuiWindowFlags_ChildWindow)
|
||||
{
|
||||
if (!(window->Flags & ImGuiWindowFlags_ComboBox))
|
||||
ImGui::PopClipRect();
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::PopClipRect();
|
||||
}
|
||||
ImGui::PopClipRect(); // inner window clip rectangle
|
||||
ImGui::PopClipRect(); // outer window clip rectangle
|
||||
|
||||
// Select window for move/focus when we're done with all our widgets
|
||||
ImGuiAabb bb(window->Pos, window->Pos+window->Size);
|
||||
@ -2340,7 +2371,7 @@ void TextV(const char* fmt, va_list args)
|
||||
return;
|
||||
|
||||
static char buf[1024];
|
||||
const char* text_end = buf + ImFormatStringV(buf, ARRAYSIZE(buf), fmt, args);
|
||||
const char* text_end = buf + ImFormatStringV(buf, IM_ARRAYSIZE(buf), fmt, args);
|
||||
TextUnformatted(buf, text_end);
|
||||
}
|
||||
|
||||
@ -2475,7 +2506,7 @@ void LabelText(const char* label, const char* fmt, ...)
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
const char* text_begin = &buf[0];
|
||||
const char* text_end = text_begin + ImFormatStringV(buf, ARRAYSIZE(buf), fmt, args);
|
||||
const char* text_end = text_begin + ImFormatStringV(buf, IM_ARRAYSIZE(buf), fmt, args);
|
||||
va_end(args);
|
||||
|
||||
const ImVec2 text_size = CalcTextSize(label);
|
||||
@ -2783,7 +2814,7 @@ void BulletText(const char* fmt, ...)
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
const char* text_begin = buf;
|
||||
const char* text_end = text_begin + ImFormatStringV(buf, ARRAYSIZE(buf), fmt, args);
|
||||
const char* text_end = text_begin + ImFormatStringV(buf, IM_ARRAYSIZE(buf), fmt, args);
|
||||
va_end(args);
|
||||
|
||||
const float line_height = window->FontSize();
|
||||
@ -2805,7 +2836,7 @@ bool TreeNode(const char* str_id, const char* fmt, ...)
|
||||
static char buf[1024];
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
ImFormatStringV(buf, ARRAYSIZE(buf), fmt, args);
|
||||
ImFormatStringV(buf, IM_ARRAYSIZE(buf), fmt, args);
|
||||
va_end(args);
|
||||
|
||||
if (!str_id || !str_id[0])
|
||||
@ -2826,7 +2857,7 @@ bool TreeNode(const void* ptr_id, const char* fmt, ...)
|
||||
static char buf[1024];
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
ImFormatStringV(buf, ARRAYSIZE(buf), fmt, args);
|
||||
ImFormatStringV(buf, IM_ARRAYSIZE(buf), fmt, args);
|
||||
va_end(args);
|
||||
|
||||
if (!ptr_id)
|
||||
@ -2986,8 +3017,8 @@ bool SliderFloat(const char* label, float* v, float v_min, float v_max, const ch
|
||||
if (v_min * v_max < 0.0f)
|
||||
{
|
||||
// Different sign
|
||||
const float linear_dist_min_to_0 = powf(abs(0.0f - v_min), 1.0f/power);
|
||||
const float linear_dist_max_to_0 = powf(abs(v_max - 0.0f), 1.0f/power);
|
||||
const float linear_dist_min_to_0 = powf(fabsf(0.0f - v_min), 1.0f/power);
|
||||
const float linear_dist_max_to_0 = powf(fabsf(v_max - 0.0f), 1.0f/power);
|
||||
linear_zero_pos = linear_dist_min_to_0 / (linear_dist_min_to_0+linear_dist_max_to_0);
|
||||
}
|
||||
else
|
||||
@ -3019,12 +3050,12 @@ bool SliderFloat(const char* label, float* v, float v_min, float v_max, const ch
|
||||
if (start_text_input || (g.ActiveId == id && id == g.SliderAsInputTextId))
|
||||
{
|
||||
char text_buf[64];
|
||||
ImFormatString(text_buf, ARRAYSIZE(text_buf), "%.*f", decimal_precision, *v);
|
||||
ImFormatString(text_buf, IM_ARRAYSIZE(text_buf), "%.*f", decimal_precision, *v);
|
||||
|
||||
g.ActiveId = g.SliderAsInputTextId;
|
||||
g.HoveredId = 0;
|
||||
window->FocusItemUnregister(); // Our replacement slider will override the focus ID (that we needed to declare previously to allow for a TAB focus to happen before we got selected)
|
||||
value_changed = ImGui::InputText(label, text_buf, ARRAYSIZE(text_buf), ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_AlignCenter);
|
||||
value_changed = ImGui::InputText(label, text_buf, IM_ARRAYSIZE(text_buf), ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_AlignCenter);
|
||||
if (g.SliderAsInputTextId == 0)
|
||||
{
|
||||
// First frame
|
||||
@ -3057,7 +3088,7 @@ bool SliderFloat(const char* label, float* v, float v_min, float v_max, const ch
|
||||
if (!is_unbound)
|
||||
{
|
||||
const float normalized_pos = ImClamp((g.IO.MousePos.x - slider_effective_x1) / slider_effective_w, 0.0f, 1.0f);
|
||||
|
||||
|
||||
// Linear slider
|
||||
//float new_value = ImLerp(v_min, v_max, normalized_pos);
|
||||
|
||||
@ -3073,9 +3104,11 @@ bool SliderFloat(const char* label, float* v, float v_min, float v_max, const ch
|
||||
else
|
||||
{
|
||||
// Positive: rescale to the positive range before powering
|
||||
float a = normalized_pos;
|
||||
if (abs(linear_zero_pos - 1.0f) > 1.e-6)
|
||||
a = (a - linear_zero_pos) / (1.0f - linear_zero_pos);
|
||||
float a;
|
||||
if (fabsf(linear_zero_pos - 1.0f) > 1.e-6)
|
||||
a = (normalized_pos - linear_zero_pos) / (1.0f - linear_zero_pos);
|
||||
else
|
||||
a = normalized_pos;
|
||||
a = powf(a, power);
|
||||
new_value = ImLerp(ImMax(v_min,0.0f), v_max, a);
|
||||
}
|
||||
@ -3132,7 +3165,7 @@ bool SliderFloat(const char* label, float* v, float v_min, float v_max, const ch
|
||||
}
|
||||
|
||||
char value_buf[64];
|
||||
ImFormatString(value_buf, ARRAYSIZE(value_buf), display_format, *v);
|
||||
ImFormatString(value_buf, IM_ARRAYSIZE(value_buf), display_format, *v);
|
||||
RenderText(ImVec2(slider_bb.GetCenter().x-CalcTextSize(value_buf).x*0.5f, frame_bb.Min.y + style.FramePadding.y), value_buf);
|
||||
|
||||
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, slider_bb.Min.y), label);
|
||||
@ -3158,6 +3191,38 @@ bool SliderInt(const char* label, int* v, int v_min, int v_max, const char* disp
|
||||
return changed;
|
||||
}
|
||||
|
||||
bool SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* display_format, float power)
|
||||
{
|
||||
ImGuiState& g = GImGui;
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
if (window->Collapsed)
|
||||
return false;
|
||||
|
||||
const ImGuiStyle& style = g.Style;
|
||||
|
||||
bool value_changed = false;
|
||||
ImGui::PushID(label);
|
||||
|
||||
const int components = 2;
|
||||
const float w_full = window->DC.ItemWidth.back();
|
||||
const float w_item_one = ImMax(1.0f, (float)(int)((w_full - (style.FramePadding.x*2.0f+style.ItemInnerSpacing.x)*(components-1)) / (float)components));
|
||||
const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one+style.FramePadding.x*2.0f+style.ItemInnerSpacing.x)*(components-1)));
|
||||
|
||||
ImGui::PushItemWidth(w_item_one);
|
||||
value_changed |= ImGui::SliderFloat("##X", &v[0], v_min, v_max, display_format, power);
|
||||
ImGui::SameLine(0, 0);
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::PushItemWidth(w_item_last);
|
||||
value_changed |= ImGui::SliderFloat("##Y", &v[1], v_min, v_max, display_format, power);
|
||||
ImGui::SameLine(0, 0);
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
ImGui::TextUnformatted(label, FindTextDisplayEnd(label));
|
||||
|
||||
ImGui::PopID();
|
||||
return value_changed;
|
||||
}
|
||||
|
||||
bool SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* display_format, float power)
|
||||
{
|
||||
ImGuiState& g = GImGui;
|
||||
@ -3168,7 +3233,6 @@ bool SliderFloat3(const char* label, float v[3], float v_min, float v_max, const
|
||||
const ImGuiStyle& style = g.Style;
|
||||
|
||||
bool value_changed = false;
|
||||
|
||||
ImGui::PushID(label);
|
||||
|
||||
const int components = 3;
|
||||
@ -3191,7 +3255,6 @@ bool SliderFloat3(const char* label, float v[3], float v_min, float v_max, const
|
||||
ImGui::TextUnformatted(label, FindTextDisplayEnd(label));
|
||||
|
||||
ImGui::PopID();
|
||||
|
||||
return value_changed;
|
||||
}
|
||||
|
||||
@ -3571,11 +3634,11 @@ bool InputFloat(const char* label, float *v, float step, float step_fast, int de
|
||||
|
||||
char buf[64];
|
||||
if (decimal_precision < 0)
|
||||
ImFormatString(buf, ARRAYSIZE(buf), "%f", *v); // Ideally we'd have a minimum decimal precision of 1 to visually denote that it is a float, while hiding non-significant digits?
|
||||
ImFormatString(buf, IM_ARRAYSIZE(buf), "%f", *v); // Ideally we'd have a minimum decimal precision of 1 to visually denote that it is a float, while hiding non-significant digits?
|
||||
else
|
||||
ImFormatString(buf, ARRAYSIZE(buf), "%.*f", decimal_precision, *v);
|
||||
ImFormatString(buf, IM_ARRAYSIZE(buf), "%.*f", decimal_precision, *v);
|
||||
bool value_changed = false;
|
||||
if (ImGui::InputText("", buf, ARRAYSIZE(buf), ImGuiInputTextFlags_CharsDecimal|ImGuiInputTextFlags_AlignCenter|ImGuiInputTextFlags_AutoSelectAll))
|
||||
if (ImGui::InputText("", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_CharsDecimal|ImGuiInputTextFlags_AlignCenter|ImGuiInputTextFlags_AutoSelectAll))
|
||||
{
|
||||
ApplyNumericalTextInput(buf, v);
|
||||
value_changed = true;
|
||||
@ -3680,7 +3743,7 @@ bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlag
|
||||
bool cancel_edit = false;
|
||||
if (g.ActiveId == id)
|
||||
{
|
||||
edit_state.BufSize = buf_size < ARRAYSIZE(edit_state.Text) ? buf_size : ARRAYSIZE(edit_state.Text);
|
||||
edit_state.BufSize = buf_size < IM_ARRAYSIZE(edit_state.Text) ? buf_size : IM_ARRAYSIZE(edit_state.Text);
|
||||
edit_state.Font = window->Font();
|
||||
edit_state.FontSize = window->FontSize();
|
||||
|
||||
@ -3763,7 +3826,7 @@ bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlag
|
||||
else if (g.IO.InputCharacters[0])
|
||||
{
|
||||
// Text input
|
||||
for (int n = 0; n < ARRAYSIZE(g.IO.InputCharacters) && g.IO.InputCharacters[n]; n++)
|
||||
for (int n = 0; n < IM_ARRAYSIZE(g.IO.InputCharacters) && g.IO.InputCharacters[n]; n++)
|
||||
{
|
||||
const char c = g.IO.InputCharacters[n];
|
||||
if (c)
|
||||
@ -3840,6 +3903,38 @@ bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlag
|
||||
return value_changed;
|
||||
}
|
||||
|
||||
bool InputFloat2(const char* label, float v[2], int decimal_precision)
|
||||
{
|
||||
ImGuiState& g = GImGui;
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
if (window->Collapsed)
|
||||
return false;
|
||||
|
||||
const ImGuiStyle& style = g.Style;
|
||||
|
||||
bool value_changed = false;
|
||||
ImGui::PushID(label);
|
||||
|
||||
const int components = 2;
|
||||
const float w_full = window->DC.ItemWidth.back();
|
||||
const float w_item_one = ImMax(1.0f, (float)(int)((w_full - (style.FramePadding.x*2.0f+style.ItemInnerSpacing.x) * (components-1)) / (float)components));
|
||||
const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one+style.FramePadding.x*2.0f+style.ItemInnerSpacing.x) * (components-1)));
|
||||
|
||||
ImGui::PushItemWidth(w_item_one);
|
||||
value_changed |= ImGui::InputFloat("##X", &v[0], 0, 0, decimal_precision);
|
||||
ImGui::SameLine(0, 0);
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::PushItemWidth(w_item_last);
|
||||
value_changed |= ImGui::InputFloat("##Y", &v[1], 0, 0, decimal_precision);
|
||||
ImGui::SameLine(0, 0);
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
ImGui::TextUnformatted(label, FindTextDisplayEnd(label));
|
||||
|
||||
ImGui::PopID();
|
||||
return value_changed;
|
||||
}
|
||||
|
||||
bool InputFloat3(const char* label, float v[3], int decimal_precision)
|
||||
{
|
||||
ImGuiState& g = GImGui;
|
||||
@ -3850,7 +3945,6 @@ bool InputFloat3(const char* label, float v[3], int decimal_precision)
|
||||
const ImGuiStyle& style = g.Style;
|
||||
|
||||
bool value_changed = false;
|
||||
|
||||
ImGui::PushID(label);
|
||||
|
||||
const int components = 3;
|
||||
@ -3873,7 +3967,6 @@ bool InputFloat3(const char* label, float v[3], int decimal_precision)
|
||||
ImGui::TextUnformatted(label, FindTextDisplayEnd(label));
|
||||
|
||||
ImGui::PopID();
|
||||
|
||||
return value_changed;
|
||||
}
|
||||
|
||||
@ -3982,6 +4075,7 @@ bool Combo(const char* label, int* current_item, bool (*items_getter)(void*, int
|
||||
ImGuiWindowFlags flags = ImGuiWindowFlags_ComboBox | ((window->Flags & ImGuiWindowFlags_ShowBorders) ? ImGuiWindowFlags_ShowBorders : 0);
|
||||
ImGui::BeginChild("#ComboBox", popup_aabb.GetSize(), false, flags);
|
||||
ImGuiWindow* child_window = GetCurrentWindow();
|
||||
ImGui::Spacing();
|
||||
|
||||
bool combo_item_active = false;
|
||||
combo_item_active |= (g.ActiveId == child_window->GetID("#SCROLLY"));
|
||||
@ -4164,7 +4258,7 @@ bool ColorEdit4(const char* label, float col[4], bool alpha)
|
||||
else
|
||||
sprintf(buf, "#%02X%02X%02X", ix, iy, iz);
|
||||
ImGui::PushItemWidth(w_slider_all - g.Style.ItemInnerSpacing.x);
|
||||
value_changed |= ImGui::InputText("##Text", buf, ARRAYSIZE(buf), ImGuiInputTextFlags_CharsHexadecimal);
|
||||
value_changed |= ImGui::InputText("##Text", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_CharsHexadecimal);
|
||||
ImGui::PopItemWidth();
|
||||
char* p = buf;
|
||||
while (*p == '#' || *p == ' ' || *p == '\t')
|
||||
@ -4322,6 +4416,7 @@ bool IsClipped(ImVec2 item_size)
|
||||
static bool ClipAdvance(const ImGuiAabb& bb)
|
||||
{
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
window->DC.LastItemAabb = bb;
|
||||
if (ImGui::IsClipped(bb))
|
||||
{
|
||||
window->DC.LastItemHovered = false;
|
||||
@ -4442,7 +4537,8 @@ void Columns(int columns_count, const char* id, bool border)
|
||||
|
||||
// Draw before resize so our items positioning are in sync with the line
|
||||
const ImU32 col = window->Color(held ? ImGuiCol_ColumnActive : hovered ? ImGuiCol_ColumnHovered : ImGuiCol_Column);
|
||||
window->DrawList->AddLine(ImVec2(x, y1), ImVec2(x, y2), col);
|
||||
const float xi = (float)(int)x;
|
||||
window->DrawList->AddLine(ImVec2(xi, y1), ImVec2(xi, y2), col);
|
||||
|
||||
if (held)
|
||||
{
|
||||
@ -4610,7 +4706,7 @@ void ImDrawList::AddVtx(const ImVec2& pos, ImU32 col)
|
||||
{
|
||||
vtx_write->pos = pos;
|
||||
vtx_write->col = col;
|
||||
vtx_write->uv = IMDRAW_TEX_UV_FOR_WHITE;
|
||||
vtx_write->uv = IMGUI_FONT_TEX_UV_FOR_WHITE;
|
||||
vtx_write++;
|
||||
}
|
||||
|
||||
@ -4643,9 +4739,9 @@ void ImDrawList::AddArc(const ImVec2& center, float rad, ImU32 col, int a_min, i
|
||||
static bool circle_vtx_builds = false;
|
||||
if (!circle_vtx_builds)
|
||||
{
|
||||
for (int i = 0; i < ARRAYSIZE(circle_vtx); i++)
|
||||
for (int i = 0; i < IM_ARRAYSIZE(circle_vtx); i++)
|
||||
{
|
||||
const float a = ((float)i / (float)ARRAYSIZE(circle_vtx)) * 2*PI;
|
||||
const float a = ((float)i / (float)IM_ARRAYSIZE(circle_vtx)) * 2*PI;
|
||||
circle_vtx[i].x = cos(a + PI);
|
||||
circle_vtx[i].y = sin(a + PI);
|
||||
}
|
||||
@ -4657,8 +4753,8 @@ void ImDrawList::AddArc(const ImVec2& center, float rad, ImU32 col, int a_min, i
|
||||
ReserveVertices((a_max-a_min) * 3);
|
||||
for (int a = a_min; a < a_max; a++)
|
||||
{
|
||||
AddVtx(center + circle_vtx[a % ARRAYSIZE(circle_vtx)] * rad, col);
|
||||
AddVtx(center + circle_vtx[(a+1) % ARRAYSIZE(circle_vtx)] * rad, col);
|
||||
AddVtx(center + circle_vtx[a % IM_ARRAYSIZE(circle_vtx)] * rad, col);
|
||||
AddVtx(center + circle_vtx[(a+1) % IM_ARRAYSIZE(circle_vtx)] * rad, col);
|
||||
AddVtx(center + third_point_offset, col);
|
||||
}
|
||||
}
|
||||
@ -4666,7 +4762,7 @@ void ImDrawList::AddArc(const ImVec2& center, float rad, ImU32 col, int a_min, i
|
||||
{
|
||||
ReserveVertices((a_max-a_min) * 6);
|
||||
for (int a = a_min; a < a_max; a++)
|
||||
AddVtxLine(center + circle_vtx[a % ARRAYSIZE(circle_vtx)] * rad, center + circle_vtx[(a+1) % ARRAYSIZE(circle_vtx)] * rad, col);
|
||||
AddVtxLine(center + circle_vtx[a % IM_ARRAYSIZE(circle_vtx)] * rad, center + circle_vtx[(a+1) % IM_ARRAYSIZE(circle_vtx)] * rad, col);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4675,10 +4771,10 @@ void ImDrawList::AddRect(const ImVec2& a, const ImVec2& b, ImU32 col, float roun
|
||||
if ((col >> 24) == 0)
|
||||
return;
|
||||
|
||||
//const float r = ImMin(rounding, ImMin(abs(b.x-a.x), abs(b.y-a.y))*0.5f);
|
||||
//const float r = ImMin(rounding, ImMin(fabsf(b.x-a.x), fabsf(b.y-a.y))*0.5f);
|
||||
float r = rounding;
|
||||
r = ImMin(r, abs(b.x-a.x) * ( ((rounding_corners&(1|2))==(1|2)) || ((rounding_corners&(4|8))==(4|8)) ? 0.5f : 1.0f ));
|
||||
r = ImMin(r, abs(b.y-a.y) * ( ((rounding_corners&(1|8))==(1|8)) || ((rounding_corners&(2|4))==(2|4)) ? 0.5f : 1.0f ));
|
||||
r = ImMin(r, fabsf(b.x-a.x) * ( ((rounding_corners&(1|2))==(1|2)) || ((rounding_corners&(4|8))==(4|8)) ? 0.5f : 1.0f ));
|
||||
r = ImMin(r, fabsf(b.y-a.y) * ( ((rounding_corners&(1|8))==(1|8)) || ((rounding_corners&(2|4))==(2|4)) ? 0.5f : 1.0f ));
|
||||
|
||||
if (r == 0.0f || rounding_corners == 0)
|
||||
{
|
||||
@ -4708,10 +4804,10 @@ void ImDrawList::AddRectFilled(const ImVec2& a, const ImVec2& b, ImU32 col, floa
|
||||
if ((col >> 24) == 0)
|
||||
return;
|
||||
|
||||
//const float r = ImMin(rounding, ImMin(abs(b.x-a.x), abs(b.y-a.y))*0.5f);
|
||||
//const float r = ImMin(rounding, ImMin(fabsf(b.x-a.x), fabsf(b.y-a.y))*0.5f);
|
||||
float r = rounding;
|
||||
r = ImMin(r, abs(b.x-a.x) * ( ((rounding_corners&(1|2))==(1|2)) || ((rounding_corners&(4|8))==(4|8)) ? 0.5f : 1.0f ));
|
||||
r = ImMin(r, abs(b.y-a.y) * ( ((rounding_corners&(1|8))==(1|8)) || ((rounding_corners&(2|4))==(2|4)) ? 0.5f : 1.0f ));
|
||||
r = ImMin(r, fabsf(b.x-a.x) * ( ((rounding_corners&(1|2))==(1|2)) || ((rounding_corners&(4|8))==(4|8)) ? 0.5f : 1.0f ));
|
||||
r = ImMin(r, fabsf(b.y-a.y) * ( ((rounding_corners&(1|8))==(1|8)) || ((rounding_corners&(2|4))==(2|4)) ? 0.5f : 1.0f ));
|
||||
|
||||
if (r == 0.0f || rounding_corners == 0)
|
||||
{
|
||||
@ -5104,6 +5200,81 @@ void ImBitmapFont::RenderText(float size, ImVec2 pos, ImU32 col, const ImVec4& c
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PLATFORM DEPENDANT HELPERS
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#if defined(_MSC_VER) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS)
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
// Win32 API clipboard implementation
|
||||
static const char* GetClipboardTextFn_DefaultImpl()
|
||||
{
|
||||
static char* buf_local = NULL;
|
||||
if (buf_local)
|
||||
{
|
||||
free(buf_local);
|
||||
buf_local = NULL;
|
||||
}
|
||||
if (!OpenClipboard(NULL))
|
||||
return NULL;
|
||||
HANDLE buf_handle = GetClipboardData(CF_TEXT);
|
||||
if (buf_handle == NULL)
|
||||
return NULL;
|
||||
if (char* buf_global = (char*)GlobalLock(buf_handle))
|
||||
buf_local = strdup(buf_global);
|
||||
GlobalUnlock(buf_handle);
|
||||
CloseClipboard();
|
||||
return buf_local;
|
||||
}
|
||||
|
||||
// Win32 API clipboard implementation
|
||||
static void SetClipboardTextFn_DefaultImpl(const char* text, const char* text_end)
|
||||
{
|
||||
if (!OpenClipboard(NULL))
|
||||
return;
|
||||
if (!text_end)
|
||||
text_end = text + strlen(text);
|
||||
const int buf_length = (text_end - text) + 1;
|
||||
HGLOBAL buf_handle = GlobalAlloc(GMEM_MOVEABLE, buf_length * sizeof(char));
|
||||
if (buf_handle == NULL)
|
||||
return;
|
||||
char* buf_global = (char *)GlobalLock(buf_handle);
|
||||
memcpy(buf_global, text, text_end - text);
|
||||
buf_global[text_end - text] = 0;
|
||||
GlobalUnlock(buf_handle);
|
||||
EmptyClipboard();
|
||||
SetClipboardData(CF_TEXT, buf_handle);
|
||||
CloseClipboard();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// Local ImGui-only clipboard implementation, if user hasn't defined better clipboard handlers
|
||||
static const char* GetClipboardTextFn_DefaultImpl()
|
||||
{
|
||||
return GImGui.PrivateClipboard;
|
||||
}
|
||||
|
||||
// Local ImGui-only clipboard implementation, if user hasn't defined better clipboard handlers
|
||||
static void SetClipboardTextFn_DefaultImpl(const char* text, const char* text_end)
|
||||
{
|
||||
if (GImGui.PrivateClipboard)
|
||||
{
|
||||
free(GImGui.PrivateClipboard);
|
||||
GImGui.PrivateClipboard = NULL;
|
||||
}
|
||||
if (!text_end)
|
||||
text_end = text + strlen(text);
|
||||
GImGui.PrivateClipboard = (char*)malloc(text_end - text + 1);
|
||||
memcpy(GImGui.PrivateClipboard, text, text_end - text);
|
||||
GImGui.PrivateClipboard[text_end - text] = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// HELP
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -5282,15 +5453,18 @@ void ShowTestWindow(bool* open)
|
||||
|
||||
const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK" };
|
||||
static int item2 = -1;
|
||||
ImGui::Combo("combo scroll", &item2, items, ARRAYSIZE(items));
|
||||
ImGui::Combo("combo scroll", &item2, items, IM_ARRAYSIZE(items));
|
||||
|
||||
static char str0[128] = "Hello, world!";
|
||||
static int i0=123;
|
||||
static float f0=0.001f;
|
||||
ImGui::InputText("string", str0, ARRAYSIZE(str0));
|
||||
ImGui::InputText("string", str0, IM_ARRAYSIZE(str0));
|
||||
ImGui::InputInt("input int", &i0);
|
||||
ImGui::InputFloat("input float", &f0, 0.01f, 1.0f);
|
||||
|
||||
//static float vec2b[3] = { 0.10f, 0.20f };
|
||||
//ImGui::InputFloat2("input float2", vec2b);
|
||||
|
||||
static float vec3b[3] = { 0.10f, 0.20f, 0.30f };
|
||||
ImGui::InputFloat3("input float3", vec3b);
|
||||
|
||||
@ -5310,6 +5484,9 @@ void ShowTestWindow(bool* open)
|
||||
static float angle = 0.0f;
|
||||
ImGui::SliderAngle("angle", &angle);
|
||||
|
||||
//static float vec2a[3] = { 0.10f, 0.20f };
|
||||
//ImGui::SliderFloat2("slider float2", vec2a, 0.0f, 1.0f);
|
||||
|
||||
static float vec3a[3] = { 0.10f, 0.20f, 0.30f };
|
||||
ImGui::SliderFloat3("slider float3", vec3a, 0.0f, 1.0f);
|
||||
|
||||
@ -5324,7 +5501,7 @@ void ShowTestWindow(bool* open)
|
||||
if (ImGui::CollapsingHeader("Graphs widgets"))
|
||||
{
|
||||
static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
|
||||
ImGui::PlotLines("Frame Times", arr, ARRAYSIZE(arr));
|
||||
ImGui::PlotLines("Frame Times", arr, IM_ARRAYSIZE(arr));
|
||||
|
||||
static bool pause;
|
||||
static ImVector<float> values; if (values.empty()) { values.resize(100); memset(&values.front(), 0, values.size()*sizeof(float)); }
|
||||
@ -5342,10 +5519,10 @@ void ShowTestWindow(bool* open)
|
||||
phase += 0.10f*values_offset;
|
||||
}
|
||||
}
|
||||
ImGui::PlotLines("Frame Times", &values.front(), values.size(), values_offset, "avg 0.0", -1.0f, 1.0f, ImVec2(0,70));
|
||||
ImGui::PlotLines("Frame Times", &values.front(), (int)values.size(), values_offset, "avg 0.0", -1.0f, 1.0f, ImVec2(0,70));
|
||||
|
||||
ImGui::SameLine(); ImGui::Checkbox("pause", &pause);
|
||||
ImGui::PlotHistogram("Histogram", arr, ARRAYSIZE(arr), 0, NULL, 0.0f, 1.0f, ImVec2(0,70));
|
||||
ImGui::PlotHistogram("Histogram", arr, IM_ARRAYSIZE(arr), 0, NULL, 0.0f, 1.0f, ImVec2(0,70));
|
||||
}
|
||||
|
||||
if (ImGui::CollapsingHeader("Widgets on same line"))
|
||||
@ -5435,7 +5612,7 @@ void ShowTestWindow(bool* open)
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
char buf[32];
|
||||
ImFormatString(buf, ARRAYSIZE(buf), "%08x", i*5731);
|
||||
ImFormatString(buf, IM_ARRAYSIZE(buf), "%08x", i*5731);
|
||||
ImGui::Button(buf);
|
||||
ImGui::NextColumn();
|
||||
}
|
||||
@ -5534,7 +5711,7 @@ void ShowTestWindow(bool* open)
|
||||
static ImGuiTextFilter filter;
|
||||
filter.Draw();
|
||||
const char* lines[] = { "aaa1.c", "bbb1.c", "ccc1.c", "aaa2.cpp", "bbb2.cpp", "ccc2.cpp", "abc.h", "hello, world" };
|
||||
for (size_t i = 0; i < ARRAYSIZE(lines); i++)
|
||||
for (size_t i = 0; i < IM_ARRAYSIZE(lines); i++)
|
||||
if (filter.PassFilter(lines[i]))
|
||||
ImGui::BulletText("%s", lines[i]);
|
||||
}
|
||||
|
31
imgui.h
31
imgui.h
@ -85,9 +85,9 @@ public:
|
||||
|
||||
inline void clear() { if (_data) { _size = _capacity = 0; free(_data); _data = NULL; } }
|
||||
inline iterator begin() { return _data; }
|
||||
inline const iterator begin() const { return _data; }
|
||||
inline const_iterator begin() const { return _data; }
|
||||
inline iterator end() { return _data + _size; }
|
||||
inline const iterator end() const { return _data + _size; }
|
||||
inline const_iterator end() const { return _data + _size; }
|
||||
inline value_type& front() { return at(0); }
|
||||
inline const value_type& front() const { return at(0); }
|
||||
inline value_type& back() { IM_ASSERT(_size > 0); return at(_size-1); }
|
||||
@ -183,6 +183,7 @@ namespace ImGui
|
||||
bool SmallButton(const char* label);
|
||||
bool CollapsingHeader(const char* label, const char* str_id = NULL, const bool display_frame = true, const bool default_open = false);
|
||||
bool SliderFloat(const char* label, float* v, float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f);
|
||||
bool SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f);
|
||||
bool SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f);
|
||||
bool SliderAngle(const char* label, float* v, float v_degrees_min = -360.0f, float v_degrees_max = +360.0f); // *v in radians
|
||||
bool SliderInt(const char* label, int* v, int v_min, int v_max, const char* display_format = "%.0f");
|
||||
@ -193,6 +194,7 @@ namespace ImGui
|
||||
bool RadioButton(const char* label, bool active);
|
||||
bool RadioButton(const char* label, int* v, int v_button);
|
||||
bool InputFloat(const char* label, float* v, float step = 0.0f, float step_fast = 0.0f, int decimal_precision = -1);
|
||||
bool InputFloat2(const char* label, float v[2], int decimal_precision = -1);
|
||||
bool InputFloat3(const char* label, float v[3], int decimal_precision = -1);
|
||||
bool InputInt(const char* label, int* v, int step = 1, int step_fast = 100);
|
||||
bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0);
|
||||
@ -230,6 +232,8 @@ namespace ImGui
|
||||
void SetTooltip(const char* fmt, ...); // set tooltip under mouse-cursor, typically use with ImGui::IsHovered(). (currently no contention handling, last call win)
|
||||
void SetNewWindowDefaultPos(ImVec2 pos); // set position of window that do
|
||||
bool IsHovered(); // was the last item active area hovered by mouse?
|
||||
ImVec2 GetItemBoxMin(); // get bounding box of last item
|
||||
ImVec2 GetItemBoxMax(); // get bounding box of last item
|
||||
bool IsClipped(ImVec2 item_size); // to perform coarse clipping on user's side (as an optimisation)
|
||||
bool IsKeyPressed(int key_index, bool repeat = true); // key_index into the keys_down[512] array, imgui doesn't know the semantic of each entry
|
||||
bool IsMouseClicked(int button, bool repeat = false);
|
||||
@ -380,10 +384,16 @@ struct ImGuiIO
|
||||
bool FontAllowScaling; // = false // Set to allow scaling text with CTRL+Wheel.
|
||||
float PixelCenterOffset; // = 0.5f // Set to 0.0f for DirectX <= 9, 0.5f for Direct3D >= 10 and OpenGL.
|
||||
|
||||
// Settings - Functions (fill once)
|
||||
void (*RenderDrawListsFn)(ImDrawList** const draw_lists, int count); // Required
|
||||
const char* (*GetClipboardTextFn)(); // Required for clipboard support
|
||||
void (*SetClipboardTextFn)(const char* text, const char* text_end); // Required for clipboard support (nb- the string is *NOT* zero-terminated at 'text_end')
|
||||
// Settings - Rendering function (REQUIRED)
|
||||
// See example code if you are unsure of how to implement this.
|
||||
void (*RenderDrawListsFn)(ImDrawList** const draw_lists, int count);
|
||||
|
||||
// Settings - Clipboard Support
|
||||
// Override to provide your clipboard handlers.
|
||||
// On Windows architecture, defaults to use the native Win32 clipboard, otherwise default to use a ImGui private clipboard.
|
||||
// NB- for SetClipboardTextFn, the string is *NOT* zero-terminated at 'text_end'
|
||||
const char* (*GetClipboardTextFn)();
|
||||
void (*SetClipboardTextFn)(const char* text, const char* text_end);
|
||||
|
||||
// Input - Fill before calling NewFrame()
|
||||
ImVec2 MousePos; // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.)
|
||||
@ -505,8 +515,8 @@ struct ImDrawCmd
|
||||
ImVec4 clip_rect;
|
||||
};
|
||||
|
||||
#ifndef IMDRAW_TEX_UV_FOR_WHITE
|
||||
#define IMDRAW_TEX_UV_FOR_WHITE ImVec2(0,0)
|
||||
#ifndef IMGUI_FONT_TEX_UV_FOR_WHITE
|
||||
#define IMGUI_FONT_TEX_UV_FOR_WHITE ImVec2(0.f,0.f)
|
||||
#endif
|
||||
|
||||
// sizeof() == 20
|
||||
@ -521,8 +531,11 @@ struct ImDrawVert
|
||||
// User is responsible for providing a renderer for this in ImGuiIO::RenderDrawListFn
|
||||
struct ImDrawList
|
||||
{
|
||||
ImVector<ImDrawCmd> commands;
|
||||
// This is what you have to render
|
||||
ImVector<ImDrawCmd> commands; // commands
|
||||
ImVector<ImDrawVert> vtx_buffer; // each command consume ImDrawCmd::vtx_count of those
|
||||
|
||||
// [Internal to ImGui]
|
||||
ImVector<ImVec4> clip_rect_stack; // [internal] clip rect stack while building the command-list (so text command can perform clipping early on)
|
||||
ImDrawVert* vtx_write; // [internal] point within vtx_buffer after each add command (to avoid using the ImVector<> operators too much)
|
||||
|
||||
|
Reference in New Issue
Block a user