mirror of
https://github.com/Drezil/imgui.git
synced 2025-07-13 16:29:54 +02:00
Compare commits
20 Commits
Author | SHA1 | Date | |
---|---|---|---|
cb3d503941 | |||
ddc7f8b0b0 | |||
57ac561ecb | |||
2573ffb6fc | |||
c938affcac | |||
a1e176fb07 | |||
901e9890d4 | |||
f4ee74b312 | |||
64e5c2f127 | |||
e2655d104e | |||
8825545653 | |||
150ad95bd6 | |||
ab8561e6fc | |||
2a1ba33263 | |||
4fa623c43b | |||
080eb69e68 | |||
1b330f420e | |||
28df6f39d9 | |||
98a000055e | |||
4020ef7b58 |
13
README.md
13
README.md
@ -5,13 +5,12 @@ ImGui is a bloat-free graphical user interface library for C++. It is portable,
|
|||||||
|
|
||||||
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 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.
|
||||||
|
|
||||||
Usage example:
|
After ImGui is setup in your application, you can use it like in this example:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
ImGui outputs vertex buffers and simple command-lists that you can render in your application. Because it doesn't know or touch graphics state directly, you can call ImGui commands anywhere in your code (e.g. in the middle of a running algorithm, or in the middle of your own rendering process). Refer to the sample applications in the examples/ folder for instructions on how to integrate ImGui with your existing codebase.
|
ImGui outputs vertex buffers and simple command-lists that you can render in your application. Because it doesn't know or touch graphics state directly, you can call ImGui commands anywhere in your code (e.g. in the middle of a running algorithm, or in the middle of your own rendering process). Refer to the sample applications in the examples/ folder for instructions on how to integrate ImGui with your existing codebase.
|
||||||
|
|
||||||
|
|
||||||
Gallery
|
Gallery
|
||||||
-------
|
-------
|
||||||
|
|
||||||
@ -20,6 +19,16 @@ Gallery
|
|||||||

|

|
||||||

|

|
||||||
|
|
||||||
|
References
|
||||||
|
----------
|
||||||
|
|
||||||
|
The Immediate Mode GUI paradigm may at first appear unusual to some users. This is mainly because "Retained Mode" GUIs have been so widespread and predominant. The following links can give you a better understanding about how Immediate Mode GUIs works.
|
||||||
|
- [Johannes 'johno' Norneby's article](http://www.johno.se/book/imgui.html).
|
||||||
|
- [A presentation by Rickard Gustafsson and Johannes Algelind](http://www.cse.chalmers.se/edu/year/2011/course/TDA361/Advanced%20Computer%20Graphics/IMGUI.pdf).
|
||||||
|
- [Jari Komppa's tutorial on building an ImGui library](http://iki.fi/sol/imgui/).
|
||||||
|
- [Casey Muratori's original video that popularized the concept](https://mollyrocket.com/861).
|
||||||
|
|
||||||
|
|
||||||
Credits
|
Credits
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
@ -12,16 +12,15 @@ static LPDIRECT3D9 g_pD3D = NULL; // Used to create the D3DDevice
|
|||||||
static LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; // Our rendering device
|
static LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; // Our rendering device
|
||||||
static LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; // Buffer to hold vertices
|
static LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; // Buffer to hold vertices
|
||||||
static LPDIRECT3DTEXTURE9 g_pTexture = NULL; // Our texture
|
static LPDIRECT3DTEXTURE9 g_pTexture = NULL; // Our texture
|
||||||
|
|
||||||
struct CUSTOMVERTEX
|
struct CUSTOMVERTEX
|
||||||
{
|
{
|
||||||
D3DXVECTOR3 position;
|
D3DXVECTOR3 position;
|
||||||
D3DCOLOR color;
|
D3DCOLOR color;
|
||||||
float tu, tv;
|
float tu, tv;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)
|
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)
|
||||||
|
|
||||||
|
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structuer)
|
||||||
static void ImImpl_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count)
|
static void ImImpl_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count)
|
||||||
{
|
{
|
||||||
size_t total_vtx_count = 0;
|
size_t total_vtx_count = 0;
|
||||||
@ -30,31 +29,13 @@ static void ImImpl_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_c
|
|||||||
if (total_vtx_count == 0)
|
if (total_vtx_count == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ImVector<ImVec4> clip_rect_stack;
|
// Copy and convert all vertices into a single contiguous buffer
|
||||||
clip_rect_stack.push_back(ImVec4(-9999,-9999,+9999,+9999));
|
|
||||||
|
|
||||||
// Setup orthographic projection
|
|
||||||
// Set up world matrix
|
|
||||||
D3DXMATRIXA16 mat;
|
|
||||||
D3DXMatrixIdentity(&mat);
|
|
||||||
g_pd3dDevice->SetTransform(D3DTS_WORLD, &mat);
|
|
||||||
g_pd3dDevice->SetTransform(D3DTS_VIEW, &mat);
|
|
||||||
D3DXMatrixOrthoOffCenterLH(&mat, 0.0f, ImGui::GetIO().DisplaySize.x, ImGui::GetIO().DisplaySize.y, 0.0f, -1.0f, +1.0f);
|
|
||||||
g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &mat);
|
|
||||||
|
|
||||||
D3DSURFACE_DESC texture_desc;
|
|
||||||
g_pTexture->GetLevelDesc(0, &texture_desc);
|
|
||||||
|
|
||||||
// Fill the vertex buffer
|
|
||||||
CUSTOMVERTEX* vtx_dst;
|
CUSTOMVERTEX* vtx_dst;
|
||||||
if (g_pVB->Lock(0, total_vtx_count, (void**)&vtx_dst, D3DLOCK_DISCARD) < 0)
|
if (g_pVB->Lock(0, total_vtx_count, (void**)&vtx_dst, D3DLOCK_DISCARD) < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (int n = 0; n < cmd_lists_count; n++)
|
for (int n = 0; n < cmd_lists_count; n++)
|
||||||
{
|
{
|
||||||
const ImDrawList* cmd_list = cmd_lists[n];
|
const ImDrawList* cmd_list = cmd_lists[n];
|
||||||
if (cmd_list->commands.empty() || cmd_list->vtx_buffer.empty())
|
|
||||||
continue;
|
|
||||||
const ImDrawVert* vtx_src = &cmd_list->vtx_buffer[0];
|
const ImDrawVert* vtx_src = &cmd_list->vtx_buffer[0];
|
||||||
for (size_t i = 0; i < cmd_list->vtx_buffer.size(); i++)
|
for (size_t i = 0; i < cmd_list->vtx_buffer.size(); i++)
|
||||||
{
|
{
|
||||||
@ -73,11 +54,10 @@ static void ImImpl_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_c
|
|||||||
g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof( CUSTOMVERTEX ) );
|
g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof( CUSTOMVERTEX ) );
|
||||||
g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
|
g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
|
||||||
|
|
||||||
// Setup render state: alpha-blending enabled, no face culling, no depth testing
|
// Setup render state: alpha-blending, no face culling, no depth testing
|
||||||
g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
|
g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
|
||||||
g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, false );
|
g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, false );
|
||||||
g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, false );
|
g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, false );
|
||||||
|
|
||||||
g_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, true );
|
g_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, true );
|
||||||
g_pd3dDevice->SetRenderState( D3DRS_BLENDOP, D3DBLENDOP_ADD );
|
g_pd3dDevice->SetRenderState( D3DRS_BLENDOP, D3DBLENDOP_ADD );
|
||||||
g_pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, false );
|
g_pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, false );
|
||||||
@ -94,44 +74,27 @@ static void ImImpl_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_c
|
|||||||
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
|
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
|
||||||
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
|
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
|
||||||
|
|
||||||
int vtx_consumed = 0; // offset in vertex buffer. each command consume ImDrawCmd::vtx_count of those
|
// Setup orthographic projection matrix
|
||||||
bool clip_rect_dirty = true;
|
D3DXMATRIXA16 mat;
|
||||||
|
D3DXMatrixIdentity(&mat);
|
||||||
|
g_pd3dDevice->SetTransform(D3DTS_WORLD, &mat);
|
||||||
|
g_pd3dDevice->SetTransform(D3DTS_VIEW, &mat);
|
||||||
|
D3DXMatrixOrthoOffCenterLH(&mat, 0.0f, ImGui::GetIO().DisplaySize.x, ImGui::GetIO().DisplaySize.y, 0.0f, -1.0f, +1.0f);
|
||||||
|
g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &mat);
|
||||||
|
|
||||||
|
// Render command lists
|
||||||
|
int vtx_offset = 0;
|
||||||
for (int n = 0; n < cmd_lists_count; n++)
|
for (int n = 0; n < cmd_lists_count; n++)
|
||||||
{
|
{
|
||||||
|
// Render command list
|
||||||
const ImDrawList* cmd_list = cmd_lists[n];
|
const ImDrawList* cmd_list = cmd_lists[n];
|
||||||
if (cmd_list->commands.empty() || cmd_list->vtx_buffer.empty())
|
const ImDrawCmd* pcmd_end = cmd_list->commands.end();
|
||||||
continue;
|
for (const ImDrawCmd* pcmd = cmd_list->commands.begin(); pcmd != pcmd_end; pcmd++)
|
||||||
const ImDrawCmd* pcmd = &cmd_list->commands.front();
|
|
||||||
const ImDrawCmd* pcmd_end = &cmd_list->commands.back();
|
|
||||||
int clip_rect_buf_consumed = 0; // offset in cmd_list->clip_rect_buffer. each PushClipRect command consume 1 of those.
|
|
||||||
while (pcmd <= pcmd_end)
|
|
||||||
{
|
{
|
||||||
const ImDrawCmd& cmd = *pcmd++;
|
const RECT r = { (LONG)pcmd->clip_rect.x, (LONG)pcmd->clip_rect.y, (LONG)pcmd->clip_rect.z, (LONG)pcmd->clip_rect.w };
|
||||||
switch (cmd.cmd_type)
|
g_pd3dDevice->SetScissorRect(&r);
|
||||||
{
|
g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, vtx_offset, pcmd->vtx_count/3);
|
||||||
case ImDrawCmdType_DrawTriangleList:
|
vtx_offset += pcmd->vtx_count;
|
||||||
if (clip_rect_dirty)
|
|
||||||
{
|
|
||||||
const ImVec4& clip_rect = clip_rect_stack.back();
|
|
||||||
const RECT r = { (LONG)clip_rect.x, (LONG)clip_rect.y, (LONG)clip_rect.z, (LONG)clip_rect.w };
|
|
||||||
g_pd3dDevice->SetScissorRect(&r);
|
|
||||||
clip_rect_dirty = false;
|
|
||||||
}
|
|
||||||
g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, vtx_consumed, cmd.vtx_count/3);
|
|
||||||
vtx_consumed += cmd.vtx_count;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ImDrawCmdType_PushClipRect:
|
|
||||||
clip_rect_stack.push_back(cmd_list->clip_rect_buffer[clip_rect_buf_consumed++]);
|
|
||||||
clip_rect_dirty = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ImDrawCmdType_PopClipRect:
|
|
||||||
clip_rect_stack.pop_back();
|
|
||||||
clip_rect_dirty = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -290,7 +253,6 @@ void InitImGui()
|
|||||||
io.SetClipboardTextFn = ImImpl_SetClipboardTextFn;
|
io.SetClipboardTextFn = ImImpl_SetClipboardTextFn;
|
||||||
io.GetClipboardTextFn = ImImpl_GetClipboardTextFn;
|
io.GetClipboardTextFn = ImImpl_GetClipboardTextFn;
|
||||||
|
|
||||||
|
|
||||||
// Create the vertex buffer
|
// Create the vertex buffer
|
||||||
if (g_pd3dDevice->CreateVertexBuffer(10000 * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL) < 0)
|
if (g_pd3dDevice->CreateVertexBuffer(10000 * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL) < 0)
|
||||||
{
|
{
|
||||||
@ -396,13 +358,15 @@ int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE, LPWSTR, int)
|
|||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3) Render
|
// 3) Rendering
|
||||||
|
// Clear frame buffer
|
||||||
g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, false);
|
g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, false);
|
||||||
g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
|
g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
|
||||||
g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, false);
|
g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, false);
|
||||||
g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(204, 153, 153), 1.0f, 0); // Clear the backbuffer and the zbuffer
|
g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(204, 153, 153), 1.0f, 0);
|
||||||
if (g_pd3dDevice->BeginScene() >= 0)
|
if (g_pd3dDevice->BeginScene() >= 0)
|
||||||
{
|
{
|
||||||
|
// Render ImGui
|
||||||
ImGui::Render();
|
ImGui::Render();
|
||||||
g_pd3dDevice->EndScene();
|
g_pd3dDevice->EndScene();
|
||||||
}
|
}
|
||||||
|
18
examples/opengl_example/Makefile.Linux
Normal file
18
examples/opengl_example/Makefile.Linux
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#
|
||||||
|
# Quick and dirty makefile to build on Linux
|
||||||
|
# tested on Ubuntu 14.04.1 32bit
|
||||||
|
#
|
||||||
|
|
||||||
|
SRC = main.cpp ../../imgui.cpp
|
||||||
|
|
||||||
|
OBJ = $(SRC:.cpp=.o)
|
||||||
|
|
||||||
|
CXXFLAGS = -I../../ `pkg-config --cflags glfw3`
|
||||||
|
|
||||||
|
LIBS = `pkg-config --static --libs glfw3` -lGLEW
|
||||||
|
|
||||||
|
all: $(OBJ)
|
||||||
|
$(CXX) $(OBJ) $(LIBS)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(RM) -f $(OBJ)
|
17
examples/opengl_example/Makefile.Macosx
Normal file
17
examples/opengl_example/Makefile.Macosx
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# This makefile currently only works for mac os
|
||||||
|
# You should install via homebrew:
|
||||||
|
# brew install glew
|
||||||
|
# brew install glfw3
|
||||||
|
#
|
||||||
|
|
||||||
|
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+=-lglew -lglfw3
|
||||||
|
CXXFLAGS+=-I../../
|
||||||
|
CXXFLAGS+= -D__APPLE__
|
||||||
|
|
||||||
|
main: main.cpp ../../imgui.cpp
|
||||||
|
$(CXX) $(CXXFLAGS) -o $@ $^
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm main
|
@ -2,116 +2,63 @@
|
|||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
#define STB_IMAGE_IMPLEMENTATION
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
#include "stb_image.h" // for .png loading
|
#include "stb_image.h" // for .png loading
|
||||||
#include "../../imgui.h"
|
#include "../../imgui.h"
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
|
#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static GLFWwindow* window;
|
static GLFWwindow* window;
|
||||||
static GLuint vbo;
|
|
||||||
static GLuint vao;
|
|
||||||
static GLuint vertexShader;
|
|
||||||
static GLuint fragmentShader;
|
|
||||||
static GLuint shaderProgram;
|
|
||||||
static GLuint fontTex;
|
static GLuint fontTex;
|
||||||
static GLint uniMVP;
|
|
||||||
static GLint uniClipRect;
|
|
||||||
|
|
||||||
|
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structuer)
|
||||||
|
// We are using the fixed pipeline.
|
||||||
|
// A faster way would be to collate all vertices from all cmd_lists into a single vertex buffer
|
||||||
static void ImImpl_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count)
|
static void ImImpl_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count)
|
||||||
{
|
{
|
||||||
size_t total_vtx_count = 0;
|
if (cmd_lists_count == 0)
|
||||||
for (int n = 0; n < cmd_lists_count; n++)
|
|
||||||
total_vtx_count += cmd_lists[n]->vtx_buffer.size();
|
|
||||||
if (total_vtx_count == 0)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int read_pos_clip_rect_buf = 0; // offset in 'clip_rect_buffer'. each PushClipRect command consume 1 of those.
|
|
||||||
|
|
||||||
ImVector<ImVec4> clip_rect_stack;
|
|
||||||
clip_rect_stack.push_back(ImVec4(-9999,-9999,+9999,+9999));
|
|
||||||
|
|
||||||
// Setup orthographic projection
|
|
||||||
const float L = 0.0f;
|
|
||||||
const float R = ImGui::GetIO().DisplaySize.x;
|
|
||||||
const float B = ImGui::GetIO().DisplaySize.y;
|
|
||||||
const float T = 0.0f;
|
|
||||||
const float mvp[4][4] =
|
|
||||||
{
|
|
||||||
{ 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
|
|
||||||
{ 0.0f, 2.0f/(T-B), 0.0f, 0.0f },
|
|
||||||
{ 0.0f, 0.0f, -1.0f, 0.0f },
|
|
||||||
{ -(R+L)/(R-L), -(T+B)/(T-B), 0.0f, 1.0f },
|
|
||||||
};
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
|
||||||
glBindVertexArray(vao);
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, total_vtx_count * sizeof(ImDrawVert), NULL, GL_STREAM_DRAW);
|
|
||||||
unsigned char* buffer_data = (unsigned char*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
|
|
||||||
if (!buffer_data)
|
|
||||||
return;
|
|
||||||
int vtx_consumed = 0;
|
|
||||||
for (int n = 0; n < cmd_lists_count; n++)
|
|
||||||
{
|
|
||||||
const ImDrawList* cmd_list = cmd_lists[n];
|
|
||||||
if (!cmd_list->vtx_buffer.empty())
|
|
||||||
{
|
|
||||||
memcpy(buffer_data, &cmd_list->vtx_buffer[0], cmd_list->vtx_buffer.size() * sizeof(ImDrawVert));
|
|
||||||
buffer_data += cmd_list->vtx_buffer.size() * sizeof(ImDrawVert);
|
|
||||||
vtx_consumed += cmd_list->vtx_buffer.size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
glUnmapBuffer(GL_ARRAY_BUFFER);
|
|
||||||
|
|
||||||
glUseProgram(shaderProgram);
|
|
||||||
glUniformMatrix4fv(uniMVP, 1, GL_FALSE, &mvp[0][0]);
|
|
||||||
|
|
||||||
// Setup render state: alpha-blending enabled, no face culling, no depth testing
|
// Setup render state: alpha-blending enabled, no face culling, no depth testing
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
glDisable(GL_CULL_FACE);
|
glDisable(GL_CULL_FACE);
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
//glEnable(GL_SCISSOR_TEST);
|
||||||
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
glEnableClientState(GL_COLOR_ARRAY);
|
||||||
|
|
||||||
|
// Bind texture
|
||||||
glBindTexture(GL_TEXTURE_2D, fontTex);
|
glBindTexture(GL_TEXTURE_2D, fontTex);
|
||||||
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
|
||||||
vtx_consumed = 0; // offset in vertex buffer. each command consume ImDrawCmd::vtx_count of those
|
// Setup matrices
|
||||||
bool clip_rect_dirty = true;
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity();
|
||||||
|
glOrtho(0.0f, ImGui::GetIO().DisplaySize.x, ImGui::GetIO().DisplaySize.y, 0.0f, -1.0f, +1.0f);
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
// Render command lists
|
||||||
for (int n = 0; n < cmd_lists_count; n++)
|
for (int n = 0; n < cmd_lists_count; n++)
|
||||||
{
|
{
|
||||||
const ImDrawList* cmd_list = cmd_lists[n];
|
const ImDrawList* cmd_list = cmd_lists[n];
|
||||||
if (cmd_list->commands.empty() || cmd_list->vtx_buffer.empty())
|
const unsigned char* vtx_buffer = (const unsigned char*)cmd_list->vtx_buffer.begin();
|
||||||
continue;
|
glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (void*)(vtx_buffer));
|
||||||
const ImDrawCmd* pcmd = &cmd_list->commands.front();
|
glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (void*)(vtx_buffer+8));
|
||||||
const ImDrawCmd* pcmd_end = &cmd_list->commands.back();
|
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (void*)(vtx_buffer+16));
|
||||||
int clip_rect_buf_consumed = 0; // offset in cmd_list->clip_rect_buffer. each PushClipRect command consume 1 of those.
|
|
||||||
while (pcmd <= pcmd_end)
|
int vtx_offset = 0;
|
||||||
|
const ImDrawCmd* pcmd_end = cmd_list->commands.end();
|
||||||
|
for (const ImDrawCmd* pcmd = cmd_list->commands.begin(); pcmd != pcmd_end; pcmd++)
|
||||||
{
|
{
|
||||||
const ImDrawCmd& cmd = *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));
|
||||||
switch (cmd.cmd_type)
|
glDrawArrays(GL_TRIANGLES, vtx_offset, pcmd->vtx_count);
|
||||||
{
|
vtx_offset += pcmd->vtx_count;
|
||||||
case ImDrawCmdType_DrawTriangleList:
|
|
||||||
if (clip_rect_dirty)
|
|
||||||
{
|
|
||||||
glUniform4fv(uniClipRect, 1, (float*)&clip_rect_stack.back());
|
|
||||||
clip_rect_dirty = false;
|
|
||||||
}
|
|
||||||
glDrawArrays(GL_TRIANGLES, vtx_consumed, cmd.vtx_count);
|
|
||||||
vtx_consumed += cmd.vtx_count;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ImDrawCmdType_PushClipRect:
|
|
||||||
clip_rect_stack.push_back(cmd_list->clip_rect_buffer[clip_rect_buf_consumed++]);
|
|
||||||
clip_rect_dirty = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ImDrawCmdType_PopClipRect:
|
|
||||||
clip_rect_stack.pop_back();
|
|
||||||
clip_rect_dirty = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
glDisable(GL_SCISSOR_TEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* ImImpl_GetClipboardTextFn()
|
static const char* ImImpl_GetClipboardTextFn()
|
||||||
@ -124,6 +71,7 @@ static void ImImpl_SetClipboardTextFn(const char* text, const char* text_end)
|
|||||||
if (!text_end)
|
if (!text_end)
|
||||||
text_end = text + strlen(text);
|
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);
|
char* buf = (char*)malloc(text_end - text + 1);
|
||||||
memcpy(buf, text, text_end-text);
|
memcpy(buf, text, text_end-text);
|
||||||
buf[text_end-text] = '\0';
|
buf[text_end-text] = '\0';
|
||||||
@ -131,42 +79,10 @@ static void ImImpl_SetClipboardTextFn(const char* text, const char* text_end)
|
|||||||
free(buf);
|
free(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shader sources
|
// GLFW callbacks to get events
|
||||||
// FIXME-OPT: clip at vertex level
|
|
||||||
const GLchar* vertexSource =
|
|
||||||
"#version 150 core\n"
|
|
||||||
"uniform mat4 MVP;"
|
|
||||||
"in vec2 i_pos;"
|
|
||||||
"in vec2 i_uv;"
|
|
||||||
"in vec4 i_col;"
|
|
||||||
"out vec4 col;"
|
|
||||||
"out vec2 pixel_pos;"
|
|
||||||
"out vec2 uv;"
|
|
||||||
"void main() {"
|
|
||||||
" col = i_col;"
|
|
||||||
" pixel_pos = i_pos;"
|
|
||||||
" uv = i_uv;"
|
|
||||||
" gl_Position = MVP * vec4(i_pos.x, i_pos.y, 0.0f, 1.0f);"
|
|
||||||
"}";
|
|
||||||
|
|
||||||
const GLchar* fragmentSource =
|
|
||||||
"#version 150 core\n"
|
|
||||||
"uniform sampler2D Tex;"
|
|
||||||
"uniform vec4 ClipRect;"
|
|
||||||
"in vec4 col;"
|
|
||||||
"in vec2 pixel_pos;"
|
|
||||||
"in vec2 uv;"
|
|
||||||
"out vec4 o_col;"
|
|
||||||
"void main() {"
|
|
||||||
" o_col = texture(Tex, uv) * col;"
|
|
||||||
//" if (pixel_pos.x < ClipRect.x || pixel_pos.y < ClipRect.y || pixel_pos.x > ClipRect.z || pixel_pos.y > ClipRect.w) discard;" // Clipping: using discard
|
|
||||||
//" if (step(ClipRect.x,pixel_pos.x) * step(ClipRect.y,pixel_pos.y) * step(pixel_pos.x,ClipRect.z) * step(pixel_pos.y,ClipRect.w) < 1.0f) discard;" // Clipping: using discard and step
|
|
||||||
" o_col.w *= (step(ClipRect.x,pixel_pos.x) * step(ClipRect.y,pixel_pos.y) * step(pixel_pos.x,ClipRect.z) * step(pixel_pos.y,ClipRect.w));" // Clipping: branch-less, set alpha 0.0f
|
|
||||||
"}";
|
|
||||||
|
|
||||||
static void glfw_error_callback(int error, const char* description)
|
static void glfw_error_callback(int error, const char* description)
|
||||||
{
|
{
|
||||||
fputs(description, stderr);
|
fputs(description, stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static float mouse_wheel = 0.0f;
|
static float mouse_wheel = 0.0f;
|
||||||
@ -197,27 +113,17 @@ void InitGL()
|
|||||||
{
|
{
|
||||||
glfwSetErrorCallback(glfw_error_callback);
|
glfwSetErrorCallback(glfw_error_callback);
|
||||||
|
|
||||||
if (!glfwInit())
|
if (!glfwInit())
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
||||||
//glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
|
||||||
//glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
|
||||||
//glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
|
||||||
//glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
|
|
||||||
glfwWindowHint(GLFW_REFRESH_RATE, 60);
|
|
||||||
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
|
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
|
||||||
window = glfwCreateWindow(1280, 720, "ImGui OpenGL example", nullptr, nullptr);
|
window = glfwCreateWindow(1280, 720, "ImGui OpenGL example", NULL, NULL);
|
||||||
glfwMakeContextCurrent(window);
|
glfwMakeContextCurrent(window);
|
||||||
|
|
||||||
glfwSetKeyCallback(window, glfw_key_callback);
|
glfwSetKeyCallback(window, glfw_key_callback);
|
||||||
glfwSetScrollCallback(window, glfw_scroll_callback);
|
glfwSetScrollCallback(window, glfw_scroll_callback);
|
||||||
glfwSetCharCallback(window, glfw_char_callback);
|
glfwSetCharCallback(window, glfw_char_callback);
|
||||||
|
|
||||||
glewExperimental = GL_TRUE;
|
|
||||||
glewInit();
|
glewInit();
|
||||||
|
|
||||||
GLenum err = GL_NO_ERROR;
|
|
||||||
err = glGetError(); IM_ASSERT(err == GL_NO_ERROR);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitImGui()
|
void InitImGui()
|
||||||
@ -226,10 +132,10 @@ void InitImGui()
|
|||||||
glfwGetWindowSize(window, &w, &h);
|
glfwGetWindowSize(window, &w, &h);
|
||||||
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
io.DisplaySize = ImVec2((float)w, (float)h); // Display size, in pixels. For clamping windows positions.
|
io.DisplaySize = ImVec2((float)w, (float)h); // Display size, in pixels. For clamping windows positions.
|
||||||
io.DeltaTime = 1.0f/60.0f; // Time elapsed since last frame, in seconds (in this sample app we'll override this every frame because our timestep is variable)
|
io.DeltaTime = 1.0f/60.0f; // Time elapsed since last frame, in seconds (in this sample app we'll override this every frame because our timestep is variable)
|
||||||
io.PixelCenterOffset = 0.5f; // Align OpenGL texels
|
io.PixelCenterOffset = 0.5f; // Align OpenGL texels
|
||||||
io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array that we will update during the application lifetime.
|
io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array.
|
||||||
io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT;
|
io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT;
|
||||||
io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT;
|
io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT;
|
||||||
io.KeyMap[ImGuiKey_UpArrow] = GLFW_KEY_UP;
|
io.KeyMap[ImGuiKey_UpArrow] = GLFW_KEY_UP;
|
||||||
@ -251,69 +157,11 @@ void InitImGui()
|
|||||||
io.SetClipboardTextFn = ImImpl_SetClipboardTextFn;
|
io.SetClipboardTextFn = ImImpl_SetClipboardTextFn;
|
||||||
io.GetClipboardTextFn = ImImpl_GetClipboardTextFn;
|
io.GetClipboardTextFn = ImImpl_GetClipboardTextFn;
|
||||||
|
|
||||||
|
|
||||||
// Setup graphics backend
|
|
||||||
GLint status = GL_TRUE;
|
|
||||||
GLenum err = GL_NO_ERROR;
|
|
||||||
err = glGetError(); IM_ASSERT(err == GL_NO_ERROR);
|
|
||||||
|
|
||||||
// Create and compile the vertex shader
|
|
||||||
vertexShader = glCreateShader(GL_VERTEX_SHADER);
|
|
||||||
glShaderSource(vertexShader, 1, &vertexSource, NULL);
|
|
||||||
glCompileShader(vertexShader);
|
|
||||||
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status);
|
|
||||||
if (status != GL_TRUE)
|
|
||||||
{
|
|
||||||
char buffer[512];
|
|
||||||
glGetShaderInfoLog(vertexShader, 1024, NULL, buffer);
|
|
||||||
printf("%s", buffer);
|
|
||||||
IM_ASSERT(status == GL_TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create and compile the fragment shader
|
|
||||||
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
|
||||||
glShaderSource(fragmentShader, 1, &fragmentSource, NULL);
|
|
||||||
glCompileShader(fragmentShader);
|
|
||||||
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status);
|
|
||||||
IM_ASSERT(status == GL_TRUE);
|
|
||||||
|
|
||||||
// Link the vertex and fragment shader into a shader program
|
|
||||||
shaderProgram = glCreateProgram();
|
|
||||||
glAttachShader(shaderProgram, vertexShader);
|
|
||||||
glAttachShader(shaderProgram, fragmentShader);
|
|
||||||
glBindFragDataLocation(shaderProgram, 0, "o_col");
|
|
||||||
glLinkProgram(shaderProgram);
|
|
||||||
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &status);
|
|
||||||
IM_ASSERT(status == GL_TRUE);
|
|
||||||
|
|
||||||
uniMVP = glGetUniformLocation(shaderProgram, "MVP");
|
|
||||||
uniClipRect = glGetUniformLocation(shaderProgram, "ClipRect");
|
|
||||||
|
|
||||||
// Create Vertex Buffer Objects & Vertex Array Objects
|
|
||||||
glGenBuffers(1, &vbo);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
|
||||||
glGenVertexArrays(1, &vao);
|
|
||||||
glBindVertexArray(vao);
|
|
||||||
|
|
||||||
GLint posAttrib = glGetAttribLocation(shaderProgram, "i_pos");
|
|
||||||
glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), 0);
|
|
||||||
glEnableVertexAttribArray(posAttrib);
|
|
||||||
|
|
||||||
GLint uvAttrib = glGetAttribLocation(shaderProgram, "i_uv");
|
|
||||||
glEnableVertexAttribArray(uvAttrib);
|
|
||||||
glVertexAttribPointer(uvAttrib, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (void*)(2*sizeof(float)));
|
|
||||||
|
|
||||||
GLint colAttrib = glGetAttribLocation(shaderProgram, "i_col");
|
|
||||||
glVertexAttribPointer(colAttrib, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (void*)(4*sizeof(float)));
|
|
||||||
glEnableVertexAttribArray(colAttrib);
|
|
||||||
err = glGetError(); IM_ASSERT(err == GL_NO_ERROR);
|
|
||||||
|
|
||||||
// Load font texture
|
// Load font texture
|
||||||
glGenTextures(1, &fontTex);
|
glGenTextures(1, &fontTex);
|
||||||
glBindTexture(GL_TEXTURE_2D, fontTex);
|
glBindTexture(GL_TEXTURE_2D, fontTex);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
|
||||||
const void* png_data;
|
const void* png_data;
|
||||||
unsigned int png_size;
|
unsigned int png_size;
|
||||||
ImGui::GetDefaultFontData(NULL, NULL, &png_data, &png_size);
|
ImGui::GetDefaultFontData(NULL, NULL, &png_data, &png_size);
|
||||||
@ -326,13 +174,6 @@ void InitImGui()
|
|||||||
void Shutdown()
|
void Shutdown()
|
||||||
{
|
{
|
||||||
ImGui::Shutdown();
|
ImGui::Shutdown();
|
||||||
|
|
||||||
glDeleteProgram(shaderProgram);
|
|
||||||
glDeleteShader(fragmentShader);
|
|
||||||
glDeleteShader(vertexShader);
|
|
||||||
glDeleteBuffers(1, &vbo);
|
|
||||||
glDeleteVertexArrays(1, &vao);
|
|
||||||
|
|
||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -353,10 +194,10 @@ int main(int argc, char** argv)
|
|||||||
time = current_time;
|
time = current_time;
|
||||||
double mouse_x, mouse_y;
|
double mouse_x, mouse_y;
|
||||||
glfwGetCursorPos(window, &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.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[0] = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) != 0;
|
||||||
io.MouseDown[1] = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT) != 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
|
io.MouseWheel = (mouse_wheel != 0) ? mouse_wheel > 0.0f ? 1 : - 1 : 0; // Mouse wheel: -1,0,+1
|
||||||
mouse_wheel = 0.0f;
|
mouse_wheel = 0.0f;
|
||||||
ImGui::NewFrame();
|
ImGui::NewFrame();
|
||||||
|
|
||||||
@ -383,7 +224,7 @@ int main(int argc, char** argv)
|
|||||||
if (show_test_window)
|
if (show_test_window)
|
||||||
{
|
{
|
||||||
// More example code in ShowTestWindow()
|
// 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::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::ShowTestWindow(&show_test_window);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -394,15 +235,15 @@ int main(int argc, char** argv)
|
|||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3) Render
|
// 3) Rendering
|
||||||
glClearColor(0.8f, 0.6f, 0.6f, 1.0f);
|
glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClearColor(0.8f, 0.6f, 0.6f, 1.0f);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
ImGui::Render();
|
ImGui::Render();
|
||||||
|
|
||||||
glfwSwapBuffers(window);
|
glfwSwapBuffers(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
Shutdown();
|
Shutdown();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
/*
|
/*
|
||||||
namespace ImGui
|
namespace ImGui
|
||||||
{
|
{
|
||||||
void Value(const char* prefix, cosnt MyVec2& v, const char* float_format = NULL);
|
void Value(const char* prefix, const MyVec2& v, const char* float_format = NULL);
|
||||||
void Value(const char* prefix, cosnt MyVec4& v, const char* float_format = NULL);
|
void Value(const char* prefix, const MyVec4& v, const char* float_format = NULL);
|
||||||
};
|
};
|
||||||
*/
|
*/
|
||||||
|
319
imgui.cpp
319
imgui.cpp
@ -158,7 +158,6 @@
|
|||||||
|
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
#include <ctype.h> // toupper
|
#include <ctype.h> // toupper
|
||||||
#include <limits.h> // INT_MAX
|
|
||||||
#include <math.h> // sqrt
|
#include <math.h> // sqrt
|
||||||
#include <stdint.h> // intptr_t
|
#include <stdint.h> // intptr_t
|
||||||
#include <stdio.h> // vsnprintf
|
#include <stdio.h> // vsnprintf
|
||||||
@ -185,7 +184,7 @@ static void ItemSize(ImVec2 size, ImVec2* adjust_start_offset = NULL);
|
|||||||
static void ItemSize(const ImGuiAabb& aabb, ImVec2* adjust_start_offset = NULL);
|
static void ItemSize(const ImGuiAabb& aabb, ImVec2* adjust_start_offset = NULL);
|
||||||
static void PushColumnClipRect(int column_index = -1);
|
static void PushColumnClipRect(int column_index = -1);
|
||||||
static bool IsClipped(const ImGuiAabb& aabb);
|
static bool IsClipped(const ImGuiAabb& aabb);
|
||||||
static bool ClipAdvance(const ImGuiAabb& aabb, bool skip_columns = false);
|
static bool ClipAdvance(const ImGuiAabb& aabb);
|
||||||
|
|
||||||
static bool IsMouseHoveringBox(const ImGuiAabb& box);
|
static bool IsMouseHoveringBox(const ImGuiAabb& box);
|
||||||
static bool IsKeyPressedMap(ImGuiKey key, bool repeat = true);
|
static bool IsKeyPressedMap(ImGuiKey key, bool repeat = true);
|
||||||
@ -227,6 +226,7 @@ ImGuiStyle::ImGuiStyle()
|
|||||||
Colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.40f, 0.80f, 0.40f);
|
Colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.40f, 0.80f, 0.40f);
|
||||||
Colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.80f, 0.50f, 0.50f, 0.40f);
|
Colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.80f, 0.50f, 0.50f, 0.40f);
|
||||||
Colors[ImGuiCol_ComboBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.99f);
|
Colors[ImGuiCol_ComboBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.99f);
|
||||||
|
Colors[ImGuiCol_CheckHovered] = ImVec4(0.60f, 0.40f, 0.40f, 0.45f);
|
||||||
Colors[ImGuiCol_CheckActive] = ImVec4(0.90f, 0.90f, 0.90f, 0.50f);
|
Colors[ImGuiCol_CheckActive] = ImVec4(0.90f, 0.90f, 0.90f, 0.50f);
|
||||||
Colors[ImGuiCol_SliderGrab] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f);
|
Colors[ImGuiCol_SliderGrab] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f);
|
||||||
Colors[ImGuiCol_SliderGrabActive] = ImVec4(0.80f, 0.50f, 0.50f, 1.00f);
|
Colors[ImGuiCol_SliderGrabActive] = ImVec4(0.80f, 0.50f, 0.50f, 1.00f);
|
||||||
@ -274,7 +274,7 @@ ImGuiIO::ImGuiIO()
|
|||||||
// - on Windows you can get those using ToAscii+keyboard state, or via the VM_CHAR message
|
// - on Windows you can get those using ToAscii+keyboard state, or via the VM_CHAR message
|
||||||
void ImGuiIO::AddInputCharacter(char c)
|
void ImGuiIO::AddInputCharacter(char c)
|
||||||
{
|
{
|
||||||
const int n = strlen(InputCharacters);
|
const size_t n = strlen(InputCharacters);
|
||||||
if (n < sizeof(InputCharacters) / sizeof(InputCharacters[0]))
|
if (n < sizeof(InputCharacters) / sizeof(InputCharacters[0]))
|
||||||
{
|
{
|
||||||
InputCharacters[n] = c;
|
InputCharacters[n] = c;
|
||||||
@ -287,11 +287,17 @@ void ImGuiIO::AddInputCharacter(char c)
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#undef ARRAYSIZE
|
#undef ARRAYSIZE
|
||||||
#define ARRAYSIZE(_ARR) (sizeof(_ARR)/sizeof(*_ARR))
|
#define ARRAYSIZE(_ARR) ((int)(sizeof(_ARR)/sizeof(*_ARR)))
|
||||||
|
|
||||||
#undef PI
|
#undef PI
|
||||||
const float PI = 3.14159265358979323846f;
|
const float PI = 3.14159265358979323846f;
|
||||||
|
|
||||||
|
#ifdef INT_MAX
|
||||||
|
#define IM_INT_MAX INT_MAX
|
||||||
|
#else
|
||||||
|
#define IM_INT_MAX 2147483647
|
||||||
|
#endif
|
||||||
|
|
||||||
// Math bits
|
// Math bits
|
||||||
// We are keeping those static in the .cpp file so as not to leak them outside, in the case the user has implicit cast operators between ImVec2 and its own types.
|
// We are keeping those static in the .cpp file so as not to leak them outside, in the case the user has implicit cast operators between ImVec2 and its own types.
|
||||||
static inline ImVec2 operator*(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x*rhs, lhs.y*rhs); }
|
static inline ImVec2 operator*(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x*rhs, lhs.y*rhs); }
|
||||||
@ -331,7 +337,7 @@ static const char* ImStristr(const char* haystack, const char* needle, const cha
|
|||||||
if (!needle_end)
|
if (!needle_end)
|
||||||
needle_end = needle + strlen(needle);
|
needle_end = needle + strlen(needle);
|
||||||
|
|
||||||
const char un0 = toupper(*needle);
|
const char un0 = (char)toupper(*needle);
|
||||||
while (*haystack)
|
while (*haystack)
|
||||||
{
|
{
|
||||||
if (toupper(*haystack) == un0)
|
if (toupper(*haystack) == un0)
|
||||||
@ -376,7 +382,7 @@ static size_t ImFormatString(char* buf, size_t buf_size, const char* fmt, ...)
|
|||||||
int w = vsnprintf(buf, buf_size, fmt, args);
|
int w = vsnprintf(buf, buf_size, fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
buf[buf_size-1] = 0;
|
buf[buf_size-1] = 0;
|
||||||
if (w == -1) w = buf_size;
|
if (w == -1) w = (int)buf_size;
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -384,7 +390,7 @@ static size_t ImFormatStringV(char* buf, size_t buf_size, const char* fmt, va_li
|
|||||||
{
|
{
|
||||||
int w = vsnprintf(buf, buf_size, fmt, args);
|
int w = vsnprintf(buf, buf_size, fmt, args);
|
||||||
buf[buf_size-1] = 0;
|
buf[buf_size-1] = 0;
|
||||||
if (w == -1) w = buf_size;
|
if (w == -1) w = (int)buf_size;
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -535,7 +541,7 @@ struct ImGuiTextEditState
|
|||||||
{
|
{
|
||||||
char Text[1024]; // edit buffer, we need to persist but can't guarantee the persistence of the user-provided buffer. so own buffer.
|
char Text[1024]; // edit buffer, we need to persist but can't guarantee the persistence of the user-provided buffer. so own buffer.
|
||||||
char InitialText[1024]; // backup of end-user buffer at focusing time, to ESC key can do a revert. Also used for arithmetic operations (but could use a pre-parsed float there).
|
char InitialText[1024]; // backup of end-user buffer at focusing time, to ESC key can do a revert. Also used for arithmetic operations (but could use a pre-parsed float there).
|
||||||
int MaxLength; // end-user buffer size <= 1024 (or increase above)
|
size_t BufSize; // end-user buffer size, <= 1024 (or increase above)
|
||||||
float Width; // widget width
|
float Width; // widget width
|
||||||
float ScrollX;
|
float ScrollX;
|
||||||
STB_TexteditState StbState;
|
STB_TexteditState StbState;
|
||||||
@ -549,7 +555,7 @@ struct ImGuiTextEditState
|
|||||||
void CursorAnimReset() { CursorAnim = -0.30f; } // After a user-input the cursor stays on for a while without blinking
|
void CursorAnimReset() { CursorAnim = -0.30f; } // After a user-input the cursor stays on for a while without blinking
|
||||||
bool CursorIsVisible() const { return CursorAnim <= 0.0f || fmodf(CursorAnim, 1.20f) <= 0.80f; } // Blinking
|
bool CursorIsVisible() const { return CursorAnim <= 0.0f || fmodf(CursorAnim, 1.20f) <= 0.80f; } // Blinking
|
||||||
bool HasSelection() const { return StbState.select_start != StbState.select_end; }
|
bool HasSelection() const { return StbState.select_start != StbState.select_end; }
|
||||||
void SelectAll() { StbState.select_start = 0; StbState.select_end = strlen(Text); StbState.cursor = StbState.select_end; StbState.has_preferred_x = false; }
|
void SelectAll() { StbState.select_start = 0; StbState.select_end = (int)strlen(Text); StbState.cursor = StbState.select_end; StbState.has_preferred_x = false; }
|
||||||
|
|
||||||
void OnKeyboardPressed(int key);
|
void OnKeyboardPressed(int key);
|
||||||
void UpdateScrollOffset();
|
void UpdateScrollOffset();
|
||||||
@ -688,6 +694,7 @@ public:
|
|||||||
|
|
||||||
static ImGuiWindow* GetCurrentWindow()
|
static ImGuiWindow* GetCurrentWindow()
|
||||||
{
|
{
|
||||||
|
IM_ASSERT(GImGui.CurrentWindow != NULL); // ImGui::NewFrame() hasn't been called yet?
|
||||||
GImGui.CurrentWindow->Accessed = true;
|
GImGui.CurrentWindow->Accessed = true;
|
||||||
return GImGui.CurrentWindow;
|
return GImGui.CurrentWindow;
|
||||||
}
|
}
|
||||||
@ -710,7 +717,7 @@ static ImVector<ImGuiStorage::Pair>::iterator LowerBound(ImVector<ImGuiStorage::
|
|||||||
{
|
{
|
||||||
ImVector<ImGuiStorage::Pair>::iterator first = data.begin();
|
ImVector<ImGuiStorage::Pair>::iterator first = data.begin();
|
||||||
ImVector<ImGuiStorage::Pair>::iterator last = data.end();
|
ImVector<ImGuiStorage::Pair>::iterator last = data.end();
|
||||||
int count = last - first;
|
int count = (int)(last - first);
|
||||||
while (count > 0)
|
while (count > 0)
|
||||||
{
|
{
|
||||||
int count2 = count / 2;
|
int count2 = count / 2;
|
||||||
@ -863,18 +870,20 @@ bool ImGuiTextFilter::PassFilter(const char* val) const
|
|||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
void ImGuiTextBuffer::Append(const char* fmt, ...)
|
void ImGuiTextBuffer::append(const char* fmt, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
int len = vsnprintf(NULL, 0, fmt, args);
|
int len = vsnprintf(NULL, 0, fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
if (len <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
const size_t write_off = Buf.size();
|
const size_t write_off = Buf.size();
|
||||||
if (write_off + len >= Buf.capacity())
|
if (write_off + len >= Buf.capacity())
|
||||||
Buf.reserve(Buf.capacity() * 2);
|
Buf.reserve(Buf.capacity() * 2);
|
||||||
|
|
||||||
Buf.resize(write_off + len);
|
Buf.resize(write_off + (size_t)len);
|
||||||
|
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
ImFormatStringV(&Buf[write_off] - 1, len+1, fmt, args);
|
ImFormatStringV(&Buf[write_off] - 1, len+1, fmt, args);
|
||||||
@ -907,8 +916,8 @@ ImGuiWindow::ImGuiWindow(const char* name, ImVec2 default_pos, ImVec2 default_si
|
|||||||
AutoFitFrames = 3;
|
AutoFitFrames = 3;
|
||||||
|
|
||||||
FocusIdxCounter = -1;
|
FocusIdxCounter = -1;
|
||||||
FocusIdxRequestCurrent = INT_MAX;
|
FocusIdxRequestCurrent = IM_INT_MAX;
|
||||||
FocusIdxRequestNext = INT_MAX;
|
FocusIdxRequestNext = IM_INT_MAX;
|
||||||
|
|
||||||
DrawList = new ImDrawList();
|
DrawList = new ImDrawList();
|
||||||
}
|
}
|
||||||
@ -949,7 +958,7 @@ bool ImGuiWindow::FocusItemRegister(bool is_active, int* out_idx)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Process input at this point: TAB, Shift-TAB switch focus
|
// Process input at this point: TAB, Shift-TAB switch focus
|
||||||
if (FocusIdxRequestNext == INT_MAX && is_active && ImGui::IsKeyPressedMap(ImGuiKey_Tab))
|
if (FocusIdxRequestNext == IM_INT_MAX && is_active && ImGui::IsKeyPressedMap(ImGuiKey_Tab))
|
||||||
{
|
{
|
||||||
// Modulo on index will be applied at the end of frame once we've got the total counter of items.
|
// Modulo on index will be applied at the end of frame once we've got the total counter of items.
|
||||||
FocusIdxRequestNext = FocusIdxCounter + (g.IO.KeyShift ? -1 : +1);
|
FocusIdxRequestNext = FocusIdxCounter + (g.IO.KeyShift ? -1 : +1);
|
||||||
@ -969,7 +978,11 @@ void ImGuiWindow::AddToRenderList()
|
|||||||
ImGuiState& g = GImGui;
|
ImGuiState& g = GImGui;
|
||||||
|
|
||||||
if (!DrawList->commands.empty() && !DrawList->vtx_buffer.empty())
|
if (!DrawList->commands.empty() && !DrawList->vtx_buffer.empty())
|
||||||
|
{
|
||||||
|
if (DrawList->commands.back().vtx_count == 0)
|
||||||
|
DrawList->commands.pop_back();
|
||||||
g.RenderDrawLists.push_back(DrawList);
|
g.RenderDrawLists.push_back(DrawList);
|
||||||
|
}
|
||||||
for (size_t i = 0; i < DC.ChildWindows.size(); i++)
|
for (size_t i = 0; i < DC.ChildWindows.size(); i++)
|
||||||
{
|
{
|
||||||
ImGuiWindow* child = DC.ChildWindows[i];
|
ImGuiWindow* child = DC.ChildWindows[i];
|
||||||
@ -1158,7 +1171,7 @@ void NewFrame()
|
|||||||
else
|
else
|
||||||
g.IO.MouseDelta = g.IO.MousePos - g.IO.MousePosPrev;
|
g.IO.MouseDelta = g.IO.MousePos - g.IO.MousePosPrev;
|
||||||
g.IO.MousePosPrev = g.IO.MousePos;
|
g.IO.MousePosPrev = g.IO.MousePos;
|
||||||
for (int i = 0; i < ARRAYSIZE(g.IO.MouseDown); i++)
|
for (size_t i = 0; i < 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.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);
|
g.IO.MouseClicked[i] = (g.IO.MouseDownTime[i] == 0.0f);
|
||||||
@ -1178,7 +1191,7 @@ void NewFrame()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i = 0; i < ARRAYSIZE(g.IO.KeysDown); i++)
|
for (size_t i = 0; i < 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;
|
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
|
// Clear reference to active widget if the widget isn't alive anymore
|
||||||
@ -1296,7 +1309,6 @@ static void AddWindowToSortedBuffer(ImGuiWindow* window, ImVector<ImGuiWindow*>&
|
|||||||
|
|
||||||
static void PushClipRect(const ImVec4& clip_rect, bool clipped = true)
|
static void PushClipRect(const ImVec4& clip_rect, bool clipped = true)
|
||||||
{
|
{
|
||||||
ImGuiState& g = GImGui;
|
|
||||||
ImGuiWindow* window = GetCurrentWindow();
|
ImGuiWindow* window = GetCurrentWindow();
|
||||||
|
|
||||||
ImVec4 cr = clip_rect;
|
ImVec4 cr = clip_rect;
|
||||||
@ -1313,7 +1325,6 @@ static void PushClipRect(const ImVec4& clip_rect, bool clipped = true)
|
|||||||
|
|
||||||
static void PopClipRect()
|
static void PopClipRect()
|
||||||
{
|
{
|
||||||
ImGuiState& g = GImGui;
|
|
||||||
ImGuiWindow* window = GetCurrentWindow();
|
ImGuiWindow* window = GetCurrentWindow();
|
||||||
window->ClipRectStack.pop_back();
|
window->ClipRectStack.pop_back();
|
||||||
window->DrawList->PopClipRect();
|
window->DrawList->PopClipRect();
|
||||||
@ -1444,9 +1455,9 @@ static void LogText(const ImVec2& ref_pos, const char* text, const char* text_en
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (log_new_line || !is_first_line)
|
if (log_new_line || !is_first_line)
|
||||||
g.LogClipboard.Append("\n%*s%.*s", tree_depth*4, "", char_count, text_remaining);
|
g.LogClipboard.append("\n%*s%.*s", tree_depth*4, "", char_count, text_remaining);
|
||||||
else
|
else
|
||||||
g.LogClipboard.Append(" %.*s", char_count, text_remaining);
|
g.LogClipboard.append(" %.*s", char_count, text_remaining);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1489,7 +1500,6 @@ static void RenderText(ImVec2 pos, const char* text, const char* text_end, const
|
|||||||
|
|
||||||
static void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border, float rounding)
|
static void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border, float rounding)
|
||||||
{
|
{
|
||||||
ImGuiState& g = GImGui;
|
|
||||||
ImGuiWindow* window = GetCurrentWindow();
|
ImGuiWindow* window = GetCurrentWindow();
|
||||||
|
|
||||||
window->DrawList->AddRectFilled(p_min, p_max, fill_col, rounding);
|
window->DrawList->AddRectFilled(p_min, p_max, fill_col, rounding);
|
||||||
@ -1502,7 +1512,6 @@ static void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border,
|
|||||||
|
|
||||||
static void RenderCollapseTriangle(ImVec2 p_min, bool open, float scale = 1.0f, bool shadow = false)
|
static void RenderCollapseTriangle(ImVec2 p_min, bool open, float scale = 1.0f, bool shadow = false)
|
||||||
{
|
{
|
||||||
ImGuiState& g = GImGui;
|
|
||||||
ImGuiWindow* window = GetCurrentWindow();
|
ImGuiWindow* window = GetCurrentWindow();
|
||||||
|
|
||||||
const float h = window->FontSize() * 1.00f;
|
const float h = window->FontSize() * 1.00f;
|
||||||
@ -1531,7 +1540,6 @@ static void RenderCollapseTriangle(ImVec2 p_min, bool open, float scale = 1.0f,
|
|||||||
|
|
||||||
static ImVec2 CalcTextSize(const char* text, const char* text_end, const bool hide_text_after_hash)
|
static ImVec2 CalcTextSize(const char* text, const char* text_end, const bool hide_text_after_hash)
|
||||||
{
|
{
|
||||||
ImGuiState& g = GImGui;
|
|
||||||
ImGuiWindow* window = GetCurrentWindow();
|
ImGuiWindow* window = GetCurrentWindow();
|
||||||
|
|
||||||
const char* text_display_end;
|
const char* text_display_end;
|
||||||
@ -1549,7 +1557,7 @@ static ImGuiWindow* FindHoveredWindow(ImVec2 pos, bool excluding_childs)
|
|||||||
ImGuiState& g = GImGui;
|
ImGuiState& g = GImGui;
|
||||||
for (int i = (int)g.Windows.size()-1; i >= 0; i--)
|
for (int i = (int)g.Windows.size()-1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
ImGuiWindow* window = g.Windows[i];
|
ImGuiWindow* window = g.Windows[(size_t)i];
|
||||||
if (!window->Visible)
|
if (!window->Visible)
|
||||||
continue;
|
continue;
|
||||||
if (excluding_childs && (window->Flags & ImGuiWindowFlags_ChildWindow) != 0)
|
if (excluding_childs && (window->Flags & ImGuiWindowFlags_ChildWindow) != 0)
|
||||||
@ -1581,6 +1589,11 @@ static bool IsMouseHoveringBox(const ImGuiAabb& box)
|
|||||||
return box_for_touch.Contains(g.IO.MousePos);
|
return box_for_touch.Contains(g.IO.MousePos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsMouseHoveringBox(const ImVec2& box_min, const ImVec2& box_max)
|
||||||
|
{
|
||||||
|
return IsMouseHoveringBox(ImGuiAabb(box_min, box_max));
|
||||||
|
}
|
||||||
|
|
||||||
static bool IsKeyPressedMap(ImGuiKey key, bool repeat)
|
static bool IsKeyPressedMap(ImGuiKey key, bool repeat)
|
||||||
{
|
{
|
||||||
ImGuiState& g = GImGui;
|
ImGuiState& g = GImGui;
|
||||||
@ -1624,6 +1637,13 @@ bool IsMouseClicked(int button, bool repeat)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsMouseDoubleClicked(int button)
|
||||||
|
{
|
||||||
|
ImGuiState& g = GImGui;
|
||||||
|
IM_ASSERT(button >= 0 && button < ARRAYSIZE(g.IO.MouseDown));
|
||||||
|
return g.IO.MouseDoubleClicked[button];
|
||||||
|
}
|
||||||
|
|
||||||
ImVec2 GetMousePos()
|
ImVec2 GetMousePos()
|
||||||
{
|
{
|
||||||
return GImGui.IO.MousePos;
|
return GImGui.IO.MousePos;
|
||||||
@ -1674,7 +1694,7 @@ void BeginChild(const char* str_id, ImVec2 size, bool border, ImGuiWindowFlags e
|
|||||||
ImGuiState& g = GImGui;
|
ImGuiState& g = GImGui;
|
||||||
ImGuiWindow* window = GetCurrentWindow();
|
ImGuiWindow* window = GetCurrentWindow();
|
||||||
|
|
||||||
ImU32 flags = ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_ChildWindow;
|
ImGuiWindowFlags flags = ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_ChildWindow;
|
||||||
|
|
||||||
const ImVec2 content_max = window->Pos + ImGui::GetWindowContentRegionMax();
|
const ImVec2 content_max = window->Pos + ImGui::GetWindowContentRegionMax();
|
||||||
const ImVec2 cursor_pos = window->Pos + ImGui::GetCursorPos();
|
const ImVec2 cursor_pos = window->Pos + ImGui::GetCursorPos();
|
||||||
@ -1785,6 +1805,10 @@ bool Begin(const char* name, bool* open, ImVec2 size, float fill_alpha, ImGuiWin
|
|||||||
if (!(flags & ImGuiWindowFlags_ComboBox))
|
if (!(flags & ImGuiWindowFlags_ComboBox))
|
||||||
ImGui::PushClipRect(parent_window->ClipRectStack.back());
|
ImGui::PushClipRect(parent_window->ClipRectStack.back());
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ImGui::PushClipRect(ImVec4(0.0f, 0.0f, g.IO.DisplaySize.x, g.IO.DisplaySize.y));
|
||||||
|
}
|
||||||
|
|
||||||
// ID stack
|
// ID stack
|
||||||
window->IDStack.resize(0);
|
window->IDStack.resize(0);
|
||||||
@ -1826,9 +1850,9 @@ bool Begin(const char* name, bool* open, ImVec2 size, float fill_alpha, ImGuiWin
|
|||||||
window->ItemWidthDefault = (float)(int)(window->Size.x > 0.0f ? window->Size.x * 0.65f : 250.0f);
|
window->ItemWidthDefault = (float)(int)(window->Size.x > 0.0f ? window->Size.x * 0.65f : 250.0f);
|
||||||
|
|
||||||
// Prepare for focus requests
|
// Prepare for focus requests
|
||||||
if (window->FocusIdxRequestNext == INT_MAX || window->FocusIdxCounter == -1)
|
if (window->FocusIdxRequestNext == IM_INT_MAX || window->FocusIdxCounter == -1)
|
||||||
{
|
{
|
||||||
window->FocusIdxRequestCurrent = INT_MAX;
|
window->FocusIdxRequestCurrent = IM_INT_MAX;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1836,7 +1860,7 @@ bool Begin(const char* name, bool* open, ImVec2 size, float fill_alpha, ImGuiWin
|
|||||||
window->FocusIdxRequestCurrent = (window->FocusIdxRequestNext + mod) % mod;
|
window->FocusIdxRequestCurrent = (window->FocusIdxRequestNext + mod) % mod;
|
||||||
}
|
}
|
||||||
window->FocusIdxCounter = -1;
|
window->FocusIdxCounter = -1;
|
||||||
window->FocusIdxRequestNext = INT_MAX;
|
window->FocusIdxRequestNext = IM_INT_MAX;
|
||||||
|
|
||||||
ImGuiAabb title_bar_aabb = window->TitleBarAabb();
|
ImGuiAabb title_bar_aabb = window->TitleBarAabb();
|
||||||
|
|
||||||
@ -2019,12 +2043,10 @@ bool Begin(const char* name, bool* open, ImVec2 size, float fill_alpha, ImGuiWin
|
|||||||
// Title bar
|
// Title bar
|
||||||
if (!(window->Flags & ImGuiWindowFlags_NoTitleBar))
|
if (!(window->Flags & ImGuiWindowFlags_NoTitleBar))
|
||||||
{
|
{
|
||||||
ImGui::PushClipRect(ImVec4(window->Pos.x-0.5f, window->Pos.y-0.5f, window->Pos.x+window->Size.x-1.5f, window->Pos.y+window->Size.y-1.5f), false);
|
|
||||||
RenderCollapseTriangle(window->Pos + style.FramePadding, !window->Collapsed, 1.0f, true);
|
RenderCollapseTriangle(window->Pos + style.FramePadding, !window->Collapsed, 1.0f, true);
|
||||||
RenderText(window->Pos + style.FramePadding + ImVec2(window->FontSize() + style.ItemInnerSpacing.x, 0), name);
|
RenderText(window->Pos + style.FramePadding + ImVec2(window->FontSize() + style.ItemInnerSpacing.x, 0), name);
|
||||||
if (open)
|
if (open)
|
||||||
ImGui::CloseWindowButton(open);
|
ImGui::CloseWindowButton(open);
|
||||||
ImGui::PopClipRect();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2054,8 +2076,14 @@ void End()
|
|||||||
ImGui::Columns(1, "#CloseColumns");
|
ImGui::Columns(1, "#CloseColumns");
|
||||||
ImGui::PopClipRect();
|
ImGui::PopClipRect();
|
||||||
if (window->Flags & ImGuiWindowFlags_ChildWindow)
|
if (window->Flags & ImGuiWindowFlags_ChildWindow)
|
||||||
|
{
|
||||||
if (!(window->Flags & ImGuiWindowFlags_ComboBox))
|
if (!(window->Flags & ImGuiWindowFlags_ComboBox))
|
||||||
ImGui::PopClipRect();
|
ImGui::PopClipRect();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ImGui::PopClipRect();
|
||||||
|
}
|
||||||
|
|
||||||
// Select window for move/focus when we're done with all our widgets
|
// Select window for move/focus when we're done with all our widgets
|
||||||
ImGuiAabb bb(window->Pos, window->Pos+window->Size);
|
ImGuiAabb bb(window->Pos, window->Pos+window->Size);
|
||||||
@ -2077,7 +2105,7 @@ void End()
|
|||||||
}
|
}
|
||||||
if (g.LogClipboard.size() > 1)
|
if (g.LogClipboard.size() > 1)
|
||||||
{
|
{
|
||||||
g.LogClipboard.Append("\n");
|
g.LogClipboard.append("\n");
|
||||||
if (g.IO.SetClipboardTextFn)
|
if (g.IO.SetClipboardTextFn)
|
||||||
g.IO.SetClipboardTextFn(g.LogClipboard.begin(), g.LogClipboard.end());
|
g.IO.SetClipboardTextFn(g.LogClipboard.begin(), g.LogClipboard.end());
|
||||||
g.LogClipboard.clear();
|
g.LogClipboard.clear();
|
||||||
@ -2117,6 +2145,12 @@ void PopItemWidth()
|
|||||||
window->DC.ItemWidth.pop_back();
|
window->DC.ItemWidth.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float GetItemWidth()
|
||||||
|
{
|
||||||
|
ImGuiWindow* window = GetCurrentWindow();
|
||||||
|
return window->DC.ItemWidth.back();
|
||||||
|
}
|
||||||
|
|
||||||
void PushAllowKeyboardFocus(bool allow_keyboard_focus)
|
void PushAllowKeyboardFocus(bool allow_keyboard_focus)
|
||||||
{
|
{
|
||||||
ImGuiWindow* window = GetCurrentWindow();
|
ImGuiWindow* window = GetCurrentWindow();
|
||||||
@ -2168,6 +2202,7 @@ const char* GetStyleColorName(ImGuiCol idx)
|
|||||||
case ImGuiCol_ScrollbarGrabHovered: return "ScrollbarGrabHovered";
|
case ImGuiCol_ScrollbarGrabHovered: return "ScrollbarGrabHovered";
|
||||||
case ImGuiCol_ScrollbarGrabActive: return "ScrollbarGrabActive";
|
case ImGuiCol_ScrollbarGrabActive: return "ScrollbarGrabActive";
|
||||||
case ImGuiCol_ComboBg: return "ComboBg";
|
case ImGuiCol_ComboBg: return "ComboBg";
|
||||||
|
case ImGuiCol_CheckHovered: return "CheckHovered";
|
||||||
case ImGuiCol_CheckActive: return "CheckActive";
|
case ImGuiCol_CheckActive: return "CheckActive";
|
||||||
case ImGuiCol_SliderGrab: return "SliderGrab";
|
case ImGuiCol_SliderGrab: return "SliderGrab";
|
||||||
case ImGuiCol_SliderGrabActive: return "SliderGrabActive";
|
case ImGuiCol_SliderGrabActive: return "SliderGrabActive";
|
||||||
@ -2282,21 +2317,24 @@ void SetCursorPos(ImVec2 p)
|
|||||||
|
|
||||||
void SetScrollPosHere()
|
void SetScrollPosHere()
|
||||||
{
|
{
|
||||||
ImGuiState& g = GImGui;
|
|
||||||
ImGuiWindow* window = GetCurrentWindow();
|
ImGuiWindow* window = GetCurrentWindow();
|
||||||
window->NextScrollY = (window->DC.CursorPos.y + window->ScrollY) - (window->Pos.y + window->SizeFull.y * 0.5f) - (window->TitleBarHeight() + window->WindowPadding().y);
|
window->NextScrollY = (window->DC.CursorPos.y + window->ScrollY) - (window->Pos.y + window->SizeFull.y * 0.5f) - (window->TitleBarHeight() + window->WindowPadding().y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetTreeStateStorage(ImGuiStorage* tree)
|
void SetTreeStateStorage(ImGuiStorage* tree)
|
||||||
{
|
{
|
||||||
ImGuiState& g = GImGui;
|
|
||||||
ImGuiWindow* window = GetCurrentWindow();
|
ImGuiWindow* window = GetCurrentWindow();
|
||||||
window->DC.StateStorage = tree ? tree : &window->StateStorage;
|
window->DC.StateStorage = tree ? tree : &window->StateStorage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGuiStorage* GetTreeStateStorage()
|
||||||
|
{
|
||||||
|
ImGuiWindow* window = GetCurrentWindow();
|
||||||
|
return window->DC.StateStorage;
|
||||||
|
}
|
||||||
|
|
||||||
void TextV(const char* fmt, va_list args)
|
void TextV(const char* fmt, va_list args)
|
||||||
{
|
{
|
||||||
ImGuiState& g = GImGui;
|
|
||||||
ImGuiWindow* window = GetCurrentWindow();
|
ImGuiWindow* window = GetCurrentWindow();
|
||||||
if (window->Collapsed)
|
if (window->Collapsed)
|
||||||
return;
|
return;
|
||||||
@ -2356,10 +2394,6 @@ void TextUnformatted(const char* text, const char* text_end)
|
|||||||
pos.y += lines_skipped * line_height;
|
pos.y += lines_skipped * line_height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("");
|
|
||||||
}
|
|
||||||
|
|
||||||
// lines to render?
|
// lines to render?
|
||||||
if (line < text_end)
|
if (line < text_end)
|
||||||
@ -2567,7 +2601,6 @@ bool SmallButton(const char* label)
|
|||||||
|
|
||||||
static bool CloseWindowButton(bool* open)
|
static bool CloseWindowButton(bool* open)
|
||||||
{
|
{
|
||||||
ImGuiState& g = GImGui;
|
|
||||||
ImGuiWindow* window = GetCurrentWindow();
|
ImGuiWindow* window = GetCurrentWindow();
|
||||||
|
|
||||||
const ImGuiID id = window->GetID("##CLOSE");
|
const ImGuiID id = window->GetID("##CLOSE");
|
||||||
@ -2603,7 +2636,8 @@ void LogToTTY(int max_depth)
|
|||||||
return;
|
return;
|
||||||
g.LogEnabled = true;
|
g.LogEnabled = true;
|
||||||
g.LogFile = stdout;
|
g.LogFile = stdout;
|
||||||
g.LogAutoExpandMaxDepth = max_depth;
|
if (max_depth >= 0)
|
||||||
|
g.LogAutoExpandMaxDepth = max_depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogToFile(int max_depth, const char* filename)
|
void LogToFile(int max_depth, const char* filename)
|
||||||
@ -2611,10 +2645,12 @@ void LogToFile(int max_depth, const char* filename)
|
|||||||
ImGuiState& g = GImGui;
|
ImGuiState& g = GImGui;
|
||||||
if (g.LogEnabled)
|
if (g.LogEnabled)
|
||||||
return;
|
return;
|
||||||
IM_ASSERT(filename);
|
if (!filename)
|
||||||
|
filename = g.IO.LogFilename;
|
||||||
g.LogEnabled = true;
|
g.LogEnabled = true;
|
||||||
g.LogFile = fopen(filename, "at");
|
g.LogFile = fopen(filename, "at");
|
||||||
g.LogAutoExpandMaxDepth = max_depth;
|
if (max_depth >= 0)
|
||||||
|
g.LogAutoExpandMaxDepth = max_depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogToClipboard(int max_depth)
|
void LogToClipboard(int max_depth)
|
||||||
@ -2624,7 +2660,8 @@ void LogToClipboard(int max_depth)
|
|||||||
return;
|
return;
|
||||||
g.LogEnabled = true;
|
g.LogEnabled = true;
|
||||||
g.LogFile = NULL;
|
g.LogFile = NULL;
|
||||||
g.LogAutoExpandMaxDepth = max_depth;
|
if (max_depth >= 0)
|
||||||
|
g.LogAutoExpandMaxDepth = max_depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogButtons()
|
void LogButtons()
|
||||||
@ -2751,7 +2788,7 @@ void BulletText(const char* fmt, ...)
|
|||||||
|
|
||||||
const float line_height = window->FontSize();
|
const float line_height = window->FontSize();
|
||||||
const ImVec2 text_size = CalcTextSize(text_begin, text_end);
|
const ImVec2 text_size = CalcTextSize(text_begin, text_end);
|
||||||
const ImGuiAabb bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(line_height + (text_size.x ? (g.Style.FramePadding.x*2) : 0.0f),0) + text_size); // Empty text doesn't add padding
|
const ImGuiAabb bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(line_height + (text_size.x > 0.0f ? (g.Style.FramePadding.x*2) : 0.0f),0) + text_size); // Empty text doesn't add padding
|
||||||
ItemSize(bb);
|
ItemSize(bb);
|
||||||
|
|
||||||
if (ClipAdvance(bb))
|
if (ClipAdvance(bb))
|
||||||
@ -2765,10 +2802,6 @@ void BulletText(const char* fmt, ...)
|
|||||||
|
|
||||||
bool TreeNode(const char* str_id, const char* fmt, ...)
|
bool TreeNode(const char* str_id, const char* fmt, ...)
|
||||||
{
|
{
|
||||||
ImGuiState& g = GImGui;
|
|
||||||
ImGuiWindow* window = GetCurrentWindow();
|
|
||||||
ImGuiStorage* tree = window->DC.StateStorage;
|
|
||||||
|
|
||||||
static char buf[1024];
|
static char buf[1024];
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
@ -2790,10 +2823,6 @@ bool TreeNode(const char* str_id, const char* fmt, ...)
|
|||||||
|
|
||||||
bool TreeNode(const void* ptr_id, const char* fmt, ...)
|
bool TreeNode(const void* ptr_id, const char* fmt, ...)
|
||||||
{
|
{
|
||||||
ImGuiState& g = GImGui;
|
|
||||||
ImGuiWindow* window = GetCurrentWindow();
|
|
||||||
ImGuiStorage* tree = window->DC.StateStorage;
|
|
||||||
|
|
||||||
static char buf[1024];
|
static char buf[1024];
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
@ -3137,7 +3166,6 @@ bool SliderFloat3(const char* label, float v[3], float v_min, float v_max, const
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
const ImGuiStyle& style = g.Style;
|
const ImGuiStyle& style = g.Style;
|
||||||
const ImVec2 text_size = CalcTextSize(label);
|
|
||||||
|
|
||||||
bool value_changed = false;
|
bool value_changed = false;
|
||||||
|
|
||||||
@ -3182,7 +3210,6 @@ static void Plot(ImGuiPlotType plot_type, const char* label, const float* values
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
const ImGuiStyle& style = g.Style;
|
const ImGuiStyle& style = g.Style;
|
||||||
const ImGuiID id = window->GetID(label);
|
|
||||||
|
|
||||||
const ImVec2 text_size = CalcTextSize(label);
|
const ImVec2 text_size = CalcTextSize(label);
|
||||||
if (graph_size.x == 0)
|
if (graph_size.x == 0)
|
||||||
@ -3300,13 +3327,12 @@ void Checkbox(const char* label, bool* v)
|
|||||||
|
|
||||||
const ImGuiAabb text_bb(window->DC.CursorPos + ImVec2(0,style.FramePadding.y), window->DC.CursorPos + ImVec2(0,style.FramePadding.y) + text_size);
|
const ImGuiAabb text_bb(window->DC.CursorPos + ImVec2(0,style.FramePadding.y), window->DC.CursorPos + ImVec2(0,style.FramePadding.y) + text_size);
|
||||||
ItemSize(ImVec2(text_bb.GetWidth(), check_bb.GetHeight()));
|
ItemSize(ImVec2(text_bb.GetWidth(), check_bb.GetHeight()));
|
||||||
|
const ImGuiAabb total_bb(ImMin(check_bb.Min, text_bb.Min), ImMax(check_bb.Max, text_bb.Max));
|
||||||
|
|
||||||
if (ClipAdvance(check_bb))
|
if (ClipAdvance(total_bb))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
RenderFrame(check_bb.Min, check_bb.Max, window->Color(ImGuiCol_FrameBg));
|
const bool hovered = (g.HoveredWindow == window) && (g.HoveredId == 0) && IsMouseHoveringBox(total_bb);
|
||||||
|
|
||||||
const bool hovered = (g.HoveredWindow == window) && (g.HoveredId == 0) && IsMouseHoveringBox(check_bb);
|
|
||||||
const bool pressed = hovered && g.IO.MouseClicked[0];
|
const bool pressed = hovered && g.IO.MouseClicked[0];
|
||||||
if (hovered)
|
if (hovered)
|
||||||
g.HoveredId = id;
|
g.HoveredId = id;
|
||||||
@ -3316,6 +3342,7 @@ void Checkbox(const char* label, bool* v)
|
|||||||
g.ActiveId = 0; // Clear focus
|
g.ActiveId = 0; // Clear focus
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RenderFrame(check_bb.Min, check_bb.Max, window->Color(hovered ? ImGuiCol_CheckHovered : ImGuiCol_FrameBg));
|
||||||
if (*v)
|
if (*v)
|
||||||
{
|
{
|
||||||
window->DrawList->AddRectFilled(check_bb.Min+ImVec2(4,4), check_bb.Max-ImVec2(4,4), window->Color(ImGuiCol_CheckActive));
|
window->DrawList->AddRectFilled(check_bb.Min+ImVec2(4,4), check_bb.Max-ImVec2(4,4), window->Color(ImGuiCol_CheckActive));
|
||||||
@ -3354,8 +3381,9 @@ bool RadioButton(const char* label, bool active)
|
|||||||
|
|
||||||
const ImGuiAabb text_bb(window->DC.CursorPos + ImVec2(0, style.FramePadding.y), window->DC.CursorPos + ImVec2(0, style.FramePadding.y) + text_size);
|
const ImGuiAabb text_bb(window->DC.CursorPos + ImVec2(0, style.FramePadding.y), window->DC.CursorPos + ImVec2(0, style.FramePadding.y) + text_size);
|
||||||
ItemSize(ImVec2(text_bb.GetWidth(), check_bb.GetHeight()));
|
ItemSize(ImVec2(text_bb.GetWidth(), check_bb.GetHeight()));
|
||||||
|
const ImGuiAabb total_bb(ImMin(check_bb.Min, text_bb.Min), ImMax(check_bb.Max, text_bb.Max));
|
||||||
|
|
||||||
if (ClipAdvance(check_bb))
|
if (ClipAdvance(total_bb))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
ImVec2 center = check_bb.GetCenter();
|
ImVec2 center = check_bb.GetCenter();
|
||||||
@ -3363,12 +3391,12 @@ bool RadioButton(const char* label, bool active)
|
|||||||
center.y = (float)(int)center.y + 0.5f;
|
center.y = (float)(int)center.y + 0.5f;
|
||||||
const float radius = check_bb.GetHeight() * 0.5f;
|
const float radius = check_bb.GetHeight() * 0.5f;
|
||||||
|
|
||||||
const bool hovered = (g.HoveredWindow == window) && (g.HoveredId == 0) && IsMouseHoveringBox(check_bb);
|
const bool hovered = (g.HoveredWindow == window) && (g.HoveredId == 0) && IsMouseHoveringBox(total_bb);
|
||||||
const bool pressed = hovered && g.IO.MouseClicked[0];
|
const bool pressed = hovered && g.IO.MouseClicked[0];
|
||||||
if (hovered)
|
if (hovered)
|
||||||
g.HoveredId = id;
|
g.HoveredId = id;
|
||||||
|
|
||||||
window->DrawList->AddCircleFilled(center, radius, window->Color(ImGuiCol_FrameBg), 16);
|
window->DrawList->AddCircleFilled(center, radius, window->Color(hovered ? ImGuiCol_CheckHovered : ImGuiCol_FrameBg), 16);
|
||||||
if (active)
|
if (active)
|
||||||
window->DrawList->AddCircleFilled(center, radius-2, window->Color(ImGuiCol_CheckActive), 16);
|
window->DrawList->AddCircleFilled(center, radius-2, window->Color(ImGuiCol_CheckActive), 16);
|
||||||
|
|
||||||
@ -3398,7 +3426,7 @@ bool RadioButton(const char* label, int* v, int v_button)
|
|||||||
// Wrapper for stb_textedit.h to edit text (our wrapper is for: statically sized buffer, single-line, ASCII, fixed-width font)
|
// Wrapper for stb_textedit.h to edit text (our wrapper is for: statically sized buffer, single-line, ASCII, fixed-width font)
|
||||||
int STB_TEXTEDIT_STRINGLEN(const STB_TEXTEDIT_STRING* obj) { return (int)strlen(obj->Text); }
|
int STB_TEXTEDIT_STRINGLEN(const STB_TEXTEDIT_STRING* obj) { return (int)strlen(obj->Text); }
|
||||||
char STB_TEXTEDIT_GETCHAR(const STB_TEXTEDIT_STRING* obj, int idx) { return (char)obj->Text[idx]; }
|
char STB_TEXTEDIT_GETCHAR(const STB_TEXTEDIT_STRING* obj, int idx) { return (char)obj->Text[idx]; }
|
||||||
float STB_TEXTEDIT_GETWIDTH(STB_TEXTEDIT_STRING* obj, int line_start_idx, int char_idx) { return obj->Font->CalcTextSize(obj->FontSize, 0, &obj->Text[char_idx], &obj->Text[char_idx]+1, NULL).x; }
|
float STB_TEXTEDIT_GETWIDTH(STB_TEXTEDIT_STRING* obj, int line_start_idx, int char_idx) { (void)line_start_idx; return obj->Font->CalcTextSize(obj->FontSize, 0, &obj->Text[char_idx], &obj->Text[char_idx]+1, NULL).x; }
|
||||||
char STB_TEXTEDIT_KEYTOTEXT(int key) { return key >= 0x10000 ? 0 : (char)key; }
|
char STB_TEXTEDIT_KEYTOTEXT(int key) { return key >= 0x10000 ? 0 : (char)key; }
|
||||||
char STB_TEXTEDIT_NEWLINE = '\n';
|
char STB_TEXTEDIT_NEWLINE = '\n';
|
||||||
void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, STB_TEXTEDIT_STRING* obj, int line_start_idx)
|
void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, STB_TEXTEDIT_STRING* obj, int line_start_idx)
|
||||||
@ -3419,17 +3447,17 @@ static bool is_separator(char c) { return c==',' || c==';' || c=='(' || c==')' |
|
|||||||
#define STB_TEXTEDIT_IS_SPACE(c) (is_white(c) || is_separator(c))
|
#define STB_TEXTEDIT_IS_SPACE(c) (is_white(c) || is_separator(c))
|
||||||
void STB_TEXTEDIT_DELETECHARS(STB_TEXTEDIT_STRING* obj, int idx, int n) { char* dst = obj->Text+idx; const char* src = obj->Text+idx+n; while (char c = *src++) *dst++ = c; *dst = '\0'; }
|
void STB_TEXTEDIT_DELETECHARS(STB_TEXTEDIT_STRING* obj, int idx, int n) { char* dst = obj->Text+idx; const char* src = obj->Text+idx+n; while (char c = *src++) *dst++ = c; *dst = '\0'; }
|
||||||
|
|
||||||
bool STB_TEXTEDIT_INSERTCHARS(STB_TEXTEDIT_STRING* obj, int idx, const char* new_text, int new_text_size)
|
bool STB_TEXTEDIT_INSERTCHARS(STB_TEXTEDIT_STRING* obj, int idx, const char* new_text, int new_text_len)
|
||||||
{
|
{
|
||||||
char* buf_end = obj->Text + obj->MaxLength;
|
char* buf_end = obj->Text + obj->BufSize;
|
||||||
int text_size = strlen(obj->Text);
|
const int text_len = (int)strlen(obj->Text);
|
||||||
|
|
||||||
if (new_text_size > buf_end - (obj->Text + text_size + 1))
|
if (new_text_len > buf_end - (obj->Text + text_len + 1))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
memmove(obj->Text + idx + new_text_size, obj->Text + idx, text_size - idx);
|
memmove(obj->Text + idx + new_text_len, obj->Text + idx, text_len - idx);
|
||||||
memcpy(obj->Text + idx, new_text, new_text_size);
|
memcpy(obj->Text + idx, new_text, new_text_len);
|
||||||
obj->Text[text_size + new_text_size] = 0;
|
obj->Text[text_len + new_text_len] = 0;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -3511,7 +3539,7 @@ void ImGuiTextEditState::RenderTextScrolledClipped(ImFont font, float font_size,
|
|||||||
const float clip_end = (text_end[0] != '\0' && text_end > text_start) ? symbol_w : 0.0f;
|
const float clip_end = (text_end[0] != '\0' && text_end > text_start) ? symbol_w : 0.0f;
|
||||||
|
|
||||||
// Draw text
|
// Draw text
|
||||||
ImGui::RenderText(pos+ImVec2(clip_begin,0), text_start+(clip_begin?1:0), text_end-(clip_end?1:0), false);//, &text_params_with_clipping);
|
ImGui::RenderText(pos+ImVec2(clip_begin,0), text_start+(clip_begin>0.0f?1:0), text_end-(clip_end>0.0f?1:0), false);//, &text_params_with_clipping);
|
||||||
|
|
||||||
// Draw the clip symbol
|
// Draw the clip symbol
|
||||||
const char s[2] = {symbol_c,'\0'};
|
const char s[2] = {symbol_c,'\0'};
|
||||||
@ -3538,7 +3566,7 @@ bool InputFloat(const char* label, float *v, float step, float step_fast, int de
|
|||||||
|
|
||||||
ImGui::PushID(label);
|
ImGui::PushID(label);
|
||||||
const float button_sz = window->FontSize();
|
const float button_sz = window->FontSize();
|
||||||
if (step)
|
if (step > 0.0f)
|
||||||
ImGui::PushItemWidth(ImMax(1.0f, window->DC.ItemWidth.back() - (button_sz+g.Style.FramePadding.x*2.0f+g.Style.ItemInnerSpacing.x)*2));
|
ImGui::PushItemWidth(ImMax(1.0f, window->DC.ItemWidth.back() - (button_sz+g.Style.FramePadding.x*2.0f+g.Style.ItemInnerSpacing.x)*2));
|
||||||
|
|
||||||
char buf[64];
|
char buf[64];
|
||||||
@ -3552,21 +3580,20 @@ bool InputFloat(const char* label, float *v, float step, float step_fast, int de
|
|||||||
ApplyNumericalTextInput(buf, v);
|
ApplyNumericalTextInput(buf, v);
|
||||||
value_changed = true;
|
value_changed = true;
|
||||||
}
|
}
|
||||||
if (step)
|
|
||||||
ImGui::PopItemWidth();
|
|
||||||
|
|
||||||
if (step)
|
if (step > 0.0f)
|
||||||
{
|
{
|
||||||
|
ImGui::PopItemWidth();
|
||||||
ImGui::SameLine(0, 0);
|
ImGui::SameLine(0, 0);
|
||||||
if (ImGui::Button("-", ImVec2(button_sz,button_sz), true))
|
if (ImGui::Button("-", ImVec2(button_sz,button_sz), true))
|
||||||
{
|
{
|
||||||
*v -= g.IO.KeyCtrl && step_fast ? step_fast : step;
|
*v -= g.IO.KeyCtrl && step_fast > 0.0f ? step_fast : step;
|
||||||
value_changed = true;
|
value_changed = true;
|
||||||
}
|
}
|
||||||
ImGui::SameLine(0, (int)g.Style.ItemInnerSpacing.x);
|
ImGui::SameLine(0, (int)g.Style.ItemInnerSpacing.x);
|
||||||
if (ImGui::Button("+", ImVec2(button_sz,button_sz), true))
|
if (ImGui::Button("+", ImVec2(button_sz,button_sz), true))
|
||||||
{
|
{
|
||||||
*v += g.IO.KeyCtrl && step_fast ? step_fast : step;
|
*v += g.IO.KeyCtrl && step_fast > 0.0f ? step_fast : step;
|
||||||
value_changed = true;
|
value_changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3653,7 +3680,7 @@ bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlag
|
|||||||
bool cancel_edit = false;
|
bool cancel_edit = false;
|
||||||
if (g.ActiveId == id)
|
if (g.ActiveId == id)
|
||||||
{
|
{
|
||||||
edit_state.MaxLength = buf_size < ARRAYSIZE(edit_state.Text) ? buf_size : ARRAYSIZE(edit_state.Text);
|
edit_state.BufSize = buf_size < ARRAYSIZE(edit_state.Text) ? buf_size : ARRAYSIZE(edit_state.Text);
|
||||||
edit_state.Font = window->Font();
|
edit_state.Font = window->Font();
|
||||||
edit_state.FontSize = window->FontSize();
|
edit_state.FontSize = window->FontSize();
|
||||||
|
|
||||||
@ -3718,7 +3745,7 @@ bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlag
|
|||||||
if (const char* clipboard = g.IO.GetClipboardTextFn())
|
if (const char* clipboard = g.IO.GetClipboardTextFn())
|
||||||
{
|
{
|
||||||
// Remove new-line from pasted buffer
|
// Remove new-line from pasted buffer
|
||||||
int clipboard_len = strlen(clipboard);
|
size_t clipboard_len = strlen(clipboard);
|
||||||
char* clipboard_filtered = (char*)malloc(clipboard_len+1);
|
char* clipboard_filtered = (char*)malloc(clipboard_len+1);
|
||||||
int clipboard_filtered_len = 0;
|
int clipboard_filtered_len = 0;
|
||||||
for (int i = 0; clipboard[i]; i++)
|
for (int i = 0; clipboard[i]; i++)
|
||||||
@ -3821,7 +3848,6 @@ bool InputFloat3(const char* label, float v[3], int decimal_precision)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
const ImGuiStyle& style = g.Style;
|
const ImGuiStyle& style = g.Style;
|
||||||
const ImVec2 text_size = CalcTextSize(label);
|
|
||||||
|
|
||||||
bool value_changed = false;
|
bool value_changed = false;
|
||||||
|
|
||||||
@ -4072,8 +4098,6 @@ bool ColorEdit4(const char* label, float col[4], bool alpha)
|
|||||||
const float w_full = window->DC.ItemWidth.back();
|
const float w_full = window->DC.ItemWidth.back();
|
||||||
const float square_sz = (window->FontSize() + style.FramePadding.x * 2.0f);
|
const float square_sz = (window->FontSize() + style.FramePadding.x * 2.0f);
|
||||||
|
|
||||||
const ImVec2 text_size = CalcTextSize(label);
|
|
||||||
|
|
||||||
ImGuiColorEditMode edit_mode = window->DC.ColorEditMode;
|
ImGuiColorEditMode edit_mode = window->DC.ColorEditMode;
|
||||||
if (edit_mode == ImGuiColorEditMode_UserSelect)
|
if (edit_mode == ImGuiColorEditMode_UserSelect)
|
||||||
edit_mode = g.ColorEditModeStorage.GetInt(id, 0) % 3;
|
edit_mode = g.ColorEditModeStorage.GetInt(id, 0) % 3;
|
||||||
@ -4195,15 +4219,12 @@ bool ColorEdit4(const char* label, float col[4], bool alpha)
|
|||||||
|
|
||||||
void ColorEditMode(ImGuiColorEditMode mode)
|
void ColorEditMode(ImGuiColorEditMode mode)
|
||||||
{
|
{
|
||||||
ImGuiState& g = GImGui;
|
|
||||||
ImGuiWindow* window = GetCurrentWindow();
|
ImGuiWindow* window = GetCurrentWindow();
|
||||||
|
|
||||||
window->DC.ColorEditMode = mode;
|
window->DC.ColorEditMode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Separator()
|
void Separator()
|
||||||
{
|
{
|
||||||
ImGuiState& g = GImGui;
|
|
||||||
ImGuiWindow* window = GetCurrentWindow();
|
ImGuiWindow* window = GetCurrentWindow();
|
||||||
if (window->Collapsed)
|
if (window->Collapsed)
|
||||||
return;
|
return;
|
||||||
@ -4214,7 +4235,7 @@ void Separator()
|
|||||||
const ImGuiAabb bb(ImVec2(window->Pos.x, window->DC.CursorPos.y), ImVec2(window->Pos.x + window->Size.x, window->DC.CursorPos.y));
|
const ImGuiAabb bb(ImVec2(window->Pos.x, window->DC.CursorPos.y), ImVec2(window->Pos.x + window->Size.x, window->DC.CursorPos.y));
|
||||||
ItemSize(ImVec2(0.0f, bb.GetSize().y)); // NB: we don't provide our width so that it doesn't get feed back into AutoFit
|
ItemSize(ImVec2(0.0f, bb.GetSize().y)); // NB: we don't provide our width so that it doesn't get feed back into AutoFit
|
||||||
|
|
||||||
if (ClipAdvance(bb, true))
|
if (ClipAdvance(bb))
|
||||||
{
|
{
|
||||||
if (window->DC.ColumnsCount > 1)
|
if (window->DC.ColumnsCount > 1)
|
||||||
ImGui::PushColumnClipRect();
|
ImGui::PushColumnClipRect();
|
||||||
@ -4229,7 +4250,6 @@ void Separator()
|
|||||||
|
|
||||||
void Spacing()
|
void Spacing()
|
||||||
{
|
{
|
||||||
ImGuiState& g = GImGui;
|
|
||||||
ImGuiWindow* window = GetCurrentWindow();
|
ImGuiWindow* window = GetCurrentWindow();
|
||||||
if (window->Collapsed)
|
if (window->Collapsed)
|
||||||
return;
|
return;
|
||||||
@ -4299,7 +4319,7 @@ bool IsClipped(ImVec2 item_size)
|
|||||||
return IsClipped(ImGuiAabb(window->DC.CursorPos, window->DC.CursorPos + item_size));
|
return IsClipped(ImGuiAabb(window->DC.CursorPos, window->DC.CursorPos + item_size));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ClipAdvance(const ImGuiAabb& bb, bool skip_columns)
|
static bool ClipAdvance(const ImGuiAabb& bb)
|
||||||
{
|
{
|
||||||
ImGuiWindow* window = GetCurrentWindow();
|
ImGuiWindow* window = GetCurrentWindow();
|
||||||
if (ImGui::IsClipped(bb))
|
if (ImGui::IsClipped(bb))
|
||||||
@ -4536,58 +4556,62 @@ void ImDrawList::Clear()
|
|||||||
{
|
{
|
||||||
commands.resize(0);
|
commands.resize(0);
|
||||||
vtx_buffer.resize(0);
|
vtx_buffer.resize(0);
|
||||||
clip_rect_buffer.resize(0);
|
vtx_write = NULL;
|
||||||
vtx_write_ = NULL;
|
clip_rect_stack.resize(0);
|
||||||
clip_rect_stack_.resize(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImDrawList::PushClipRect(const ImVec4& clip_rect)
|
void ImDrawList::PushClipRect(const ImVec4& clip_rect)
|
||||||
{
|
{
|
||||||
commands.push_back(ImDrawCmd(ImDrawCmdType_PushClipRect));
|
if (!commands.empty() && commands.back().vtx_count == 0)
|
||||||
clip_rect_buffer.push_back(clip_rect);
|
{
|
||||||
clip_rect_stack_.push_back(clip_rect);
|
// Reuse empty command because high-level clipping may have discarded the other vertices already
|
||||||
|
commands.back().clip_rect = clip_rect;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ImDrawCmd draw_cmd;
|
||||||
|
draw_cmd.vtx_count = 0;
|
||||||
|
draw_cmd.clip_rect = clip_rect;
|
||||||
|
commands.push_back(draw_cmd);
|
||||||
|
}
|
||||||
|
clip_rect_stack.push_back(clip_rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImDrawList::PopClipRect()
|
void ImDrawList::PopClipRect()
|
||||||
{
|
{
|
||||||
if (!commands.empty() && commands.back().cmd_type == ImDrawCmdType_PushClipRect)
|
clip_rect_stack.pop_back();
|
||||||
|
const ImVec4 clip_rect = clip_rect_stack.empty() ? ImVec4(-9999.0f,-9999.0f, +9999.0f, +9999.0f) : clip_rect_stack.back();
|
||||||
|
if (!commands.empty() && commands.back().vtx_count == 0)
|
||||||
{
|
{
|
||||||
// Discard push/pop combo because high-level clipping may have discarded the other draw commands already
|
// Reuse empty command because high-level clipping may have discarded the other vertices already
|
||||||
commands.pop_back();
|
commands.back().clip_rect = clip_rect;
|
||||||
clip_rect_buffer.pop_back();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
commands.push_back(ImDrawCmd(ImDrawCmdType_PopClipRect));
|
ImDrawCmd draw_cmd;
|
||||||
|
draw_cmd.vtx_count = 0;
|
||||||
|
draw_cmd.clip_rect = clip_rect;
|
||||||
|
commands.push_back(draw_cmd);
|
||||||
}
|
}
|
||||||
clip_rect_stack_.pop_back();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImDrawList::AddCommand(ImDrawCmdType cmd_type, int vtx_count)
|
void ImDrawList::ReserveVertices(unsigned int vtx_count)
|
||||||
{
|
{
|
||||||
// Maximum value that can fit in our u16 vtx_count member
|
|
||||||
const int VTX_COUNT_MAX = (1<<16);
|
|
||||||
|
|
||||||
// Merge commands if we can, turning them into less draw calls
|
|
||||||
ImDrawCmd* prev = commands.empty() ? NULL : &commands.back();
|
|
||||||
if (vtx_count > 0 && prev && prev->cmd_type == (ImU32)cmd_type && prev->vtx_count + vtx_count < VTX_COUNT_MAX)
|
|
||||||
prev->vtx_count += vtx_count;
|
|
||||||
else
|
|
||||||
commands.push_back(ImDrawCmd(cmd_type, vtx_count));
|
|
||||||
|
|
||||||
if (vtx_count > 0)
|
if (vtx_count > 0)
|
||||||
{
|
{
|
||||||
|
ImDrawCmd& draw_cmd = commands.back();
|
||||||
|
draw_cmd.vtx_count += vtx_count;
|
||||||
vtx_buffer.resize(vtx_buffer.size() + vtx_count);
|
vtx_buffer.resize(vtx_buffer.size() + vtx_count);
|
||||||
vtx_write_ = &vtx_buffer[vtx_buffer.size() - vtx_count];
|
vtx_write = &vtx_buffer[vtx_buffer.size() - vtx_count];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImDrawList::AddVtx(const ImVec2& pos, ImU32 col)
|
void ImDrawList::AddVtx(const ImVec2& pos, ImU32 col)
|
||||||
{
|
{
|
||||||
vtx_write_->pos = pos;
|
vtx_write->pos = pos;
|
||||||
vtx_write_->col = col;
|
vtx_write->col = col;
|
||||||
vtx_write_->uv = IMDRAW_TEX_UV_FOR_WHITE;
|
vtx_write->uv = IMDRAW_TEX_UV_FOR_WHITE;
|
||||||
vtx_write_++;
|
vtx_write++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImDrawList::AddVtxLine(const ImVec2& a, const ImVec2& b, ImU32 col)
|
void ImDrawList::AddVtxLine(const ImVec2& a, const ImVec2& b, ImU32 col)
|
||||||
@ -4609,7 +4633,7 @@ void ImDrawList::AddLine(const ImVec2& a, const ImVec2& b, ImU32 col)
|
|||||||
if ((col >> 24) == 0)
|
if ((col >> 24) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
AddCommand(ImDrawCmdType_DrawTriangleList, 6);
|
ReserveVertices(6);
|
||||||
AddVtxLine(a, b, col);
|
AddVtxLine(a, b, col);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4630,7 +4654,7 @@ void ImDrawList::AddArc(const ImVec2& center, float rad, ImU32 col, int a_min, i
|
|||||||
|
|
||||||
if (tris)
|
if (tris)
|
||||||
{
|
{
|
||||||
AddCommand(ImDrawCmdType_DrawTriangleList, (a_max-a_min) * 3);
|
ReserveVertices((a_max-a_min) * 3);
|
||||||
for (int a = a_min; a < a_max; a++)
|
for (int a = a_min; a < a_max; a++)
|
||||||
{
|
{
|
||||||
AddVtx(center + circle_vtx[a % ARRAYSIZE(circle_vtx)] * rad, col);
|
AddVtx(center + circle_vtx[a % ARRAYSIZE(circle_vtx)] * rad, col);
|
||||||
@ -4640,7 +4664,7 @@ void ImDrawList::AddArc(const ImVec2& center, float rad, ImU32 col, int a_min, i
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AddCommand(ImDrawCmdType_DrawTriangleList, (a_max-a_min) * 6);
|
ReserveVertices((a_max-a_min) * 6);
|
||||||
for (int a = a_min; a < a_max; a++)
|
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 % ARRAYSIZE(circle_vtx)] * rad, center + circle_vtx[(a+1) % ARRAYSIZE(circle_vtx)] * rad, col);
|
||||||
}
|
}
|
||||||
@ -4658,7 +4682,7 @@ void ImDrawList::AddRect(const ImVec2& a, const ImVec2& b, ImU32 col, float roun
|
|||||||
|
|
||||||
if (r == 0.0f || rounding_corners == 0)
|
if (r == 0.0f || rounding_corners == 0)
|
||||||
{
|
{
|
||||||
AddCommand(ImDrawCmdType_DrawTriangleList, 4*6);
|
ReserveVertices(4*6);
|
||||||
AddVtxLine(ImVec2(a.x,a.y), ImVec2(b.x,a.y), col);
|
AddVtxLine(ImVec2(a.x,a.y), ImVec2(b.x,a.y), col);
|
||||||
AddVtxLine(ImVec2(b.x,a.y), ImVec2(b.x,b.y), col);
|
AddVtxLine(ImVec2(b.x,a.y), ImVec2(b.x,b.y), col);
|
||||||
AddVtxLine(ImVec2(b.x,b.y), ImVec2(a.x,b.y), col);
|
AddVtxLine(ImVec2(b.x,b.y), ImVec2(a.x,b.y), col);
|
||||||
@ -4666,7 +4690,7 @@ void ImDrawList::AddRect(const ImVec2& a, const ImVec2& b, ImU32 col, float roun
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AddCommand(ImDrawCmdType_DrawTriangleList, 4*6);
|
ReserveVertices(4*6);
|
||||||
AddVtxLine(ImVec2(a.x + ((rounding_corners & 1)?r:0), a.y), ImVec2(b.x - ((rounding_corners & 2)?r:0), a.y), col);
|
AddVtxLine(ImVec2(a.x + ((rounding_corners & 1)?r:0), a.y), ImVec2(b.x - ((rounding_corners & 2)?r:0), a.y), col);
|
||||||
AddVtxLine(ImVec2(b.x, a.y + ((rounding_corners & 2)?r:0)), ImVec2(b.x, b.y - ((rounding_corners & 4)?r:0)), col);
|
AddVtxLine(ImVec2(b.x, a.y + ((rounding_corners & 2)?r:0)), ImVec2(b.x, b.y - ((rounding_corners & 4)?r:0)), col);
|
||||||
AddVtxLine(ImVec2(b.x - ((rounding_corners & 4)?r:0), b.y), ImVec2(a.x + ((rounding_corners & 8)?r:0), b.y), col);
|
AddVtxLine(ImVec2(b.x - ((rounding_corners & 4)?r:0), b.y), ImVec2(a.x + ((rounding_corners & 8)?r:0), b.y), col);
|
||||||
@ -4692,7 +4716,7 @@ void ImDrawList::AddRectFilled(const ImVec2& a, const ImVec2& b, ImU32 col, floa
|
|||||||
if (r == 0.0f || rounding_corners == 0)
|
if (r == 0.0f || rounding_corners == 0)
|
||||||
{
|
{
|
||||||
// Use triangle so we can merge more draw calls together (at the cost of extra vertices)
|
// Use triangle so we can merge more draw calls together (at the cost of extra vertices)
|
||||||
AddCommand(ImDrawCmdType_DrawTriangleList, 6);
|
ReserveVertices(6);
|
||||||
AddVtx(ImVec2(a.x,a.y), col);
|
AddVtx(ImVec2(a.x,a.y), col);
|
||||||
AddVtx(ImVec2(b.x,a.y), col);
|
AddVtx(ImVec2(b.x,a.y), col);
|
||||||
AddVtx(ImVec2(b.x,b.y), col);
|
AddVtx(ImVec2(b.x,b.y), col);
|
||||||
@ -4702,7 +4726,7 @@ void ImDrawList::AddRectFilled(const ImVec2& a, const ImVec2& b, ImU32 col, floa
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AddCommand(ImDrawCmdType_DrawTriangleList, 6+6*2);
|
ReserveVertices(6+6*2);
|
||||||
AddVtx(ImVec2(a.x+r,a.y), col);
|
AddVtx(ImVec2(a.x+r,a.y), col);
|
||||||
AddVtx(ImVec2(b.x-r,a.y), col);
|
AddVtx(ImVec2(b.x-r,a.y), col);
|
||||||
AddVtx(ImVec2(b.x-r,b.y), col);
|
AddVtx(ImVec2(b.x-r,b.y), col);
|
||||||
@ -4740,7 +4764,7 @@ void ImDrawList::AddTriangleFilled(const ImVec2& a, const ImVec2& b, const ImVec
|
|||||||
if ((col >> 24) == 0)
|
if ((col >> 24) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
AddCommand(ImDrawCmdType_DrawTriangleList, 3);
|
ReserveVertices(3);
|
||||||
AddVtx(a, col);
|
AddVtx(a, col);
|
||||||
AddVtx(b, col);
|
AddVtx(b, col);
|
||||||
AddVtx(c, col);
|
AddVtx(c, col);
|
||||||
@ -4751,7 +4775,7 @@ void ImDrawList::AddCircle(const ImVec2& centre, float radius, ImU32 col, int nu
|
|||||||
if ((col >> 24) == 0)
|
if ((col >> 24) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
AddCommand(ImDrawCmdType_DrawTriangleList, num_segments*6);
|
ReserveVertices(num_segments*6);
|
||||||
const float a_step = 2*PI/(float)num_segments;
|
const float a_step = 2*PI/(float)num_segments;
|
||||||
float a0 = 0.0f;
|
float a0 = 0.0f;
|
||||||
for (int i = 0; i < num_segments; i++)
|
for (int i = 0; i < num_segments; i++)
|
||||||
@ -4767,7 +4791,7 @@ void ImDrawList::AddCircleFilled(const ImVec2& centre, float radius, ImU32 col,
|
|||||||
if ((col >> 24) == 0)
|
if ((col >> 24) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
AddCommand(ImDrawCmdType_DrawTriangleList, num_segments*3);
|
ReserveVertices(num_segments*3);
|
||||||
const float a_step = 2*PI/(float)num_segments;
|
const float a_step = 2*PI/(float)num_segments;
|
||||||
float a0 = 0.0f;
|
float a0 = 0.0f;
|
||||||
for (int i = 0; i < num_segments; i++)
|
for (int i = 0; i < num_segments; i++)
|
||||||
@ -4788,17 +4812,19 @@ void ImDrawList::AddText(ImFont font, float font_size, const ImVec2& pos, ImU32
|
|||||||
if (text_end == NULL)
|
if (text_end == NULL)
|
||||||
text_end = text_begin + strlen(text_begin);
|
text_end = text_begin + strlen(text_begin);
|
||||||
|
|
||||||
int char_count = text_end - text_begin;
|
// reserve vertices for worse case
|
||||||
int vtx_count_max = char_count * 6;
|
const int char_count = (int)(text_end - text_begin);
|
||||||
int vtx_begin = vtx_buffer.size();
|
const int vtx_count_max = char_count * 6;
|
||||||
AddCommand(ImDrawCmdType_DrawTriangleList, vtx_count_max);
|
const size_t vtx_begin = vtx_buffer.size();
|
||||||
|
ReserveVertices(vtx_count_max);
|
||||||
|
|
||||||
font->RenderText(font_size, pos, col, clip_rect_stack_.back(), text_begin, text_end, vtx_write_);
|
font->RenderText(font_size, pos, col, clip_rect_stack.back(), text_begin, text_end, vtx_write);
|
||||||
vtx_buffer.resize(vtx_write_ - &vtx_buffer.front());
|
|
||||||
int vtx_count = vtx_buffer.size() - vtx_begin;
|
|
||||||
|
|
||||||
|
// give unused vertices
|
||||||
|
vtx_buffer.resize(vtx_write - &vtx_buffer.front());
|
||||||
|
const int vtx_count = (int)(vtx_buffer.size() - vtx_begin);
|
||||||
commands.back().vtx_count -= (vtx_count_max - vtx_count);
|
commands.back().vtx_count -= (vtx_count_max - vtx_count);
|
||||||
vtx_write_ -= (vtx_count_max - vtx_count);
|
vtx_write -= (vtx_count_max - vtx_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -4847,7 +4873,7 @@ bool ImBitmapFont::LoadFromFile(const char* filename)
|
|||||||
fclose(f);
|
fclose(f);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (fread(Data, 1, DataSize, f) != DataSize)
|
if ((int)fread(Data, 1, DataSize, f) != DataSize)
|
||||||
{
|
{
|
||||||
fclose(f);
|
fclose(f);
|
||||||
free(Data);
|
free(Data);
|
||||||
@ -4908,7 +4934,7 @@ bool ImBitmapFont::LoadFromMemory(const void* data, int data_size)
|
|||||||
void ImBitmapFont::BuildLookupTable()
|
void ImBitmapFont::BuildLookupTable()
|
||||||
{
|
{
|
||||||
ImU32 max_c = 0;
|
ImU32 max_c = 0;
|
||||||
for (int i = 0; i != GlyphsCount; i++)
|
for (size_t i = 0; i != GlyphsCount; i++)
|
||||||
if (max_c < Glyphs[i].Id)
|
if (max_c < Glyphs[i].Id)
|
||||||
max_c = Glyphs[i].Id;
|
max_c = Glyphs[i].Id;
|
||||||
|
|
||||||
@ -4958,7 +4984,8 @@ ImVec2 ImBitmapFont::CalcTextSize(float size, float max_width, const char* text_
|
|||||||
if (const FntGlyph* glyph = FindGlyph((unsigned short)c))
|
if (const FntGlyph* glyph = FindGlyph((unsigned short)c))
|
||||||
{
|
{
|
||||||
const float char_width = (glyph->XAdvance + Info->SpacingHoriz) * scale;
|
const float char_width = (glyph->XAdvance + Info->SpacingHoriz) * scale;
|
||||||
const float char_extend = (glyph->XOffset + glyph->Width * scale);
|
//const float char_extend = (glyph->XOffset + glyph->Width * scale);
|
||||||
|
|
||||||
if (line_width + char_width >= max_width)
|
if (line_width + char_width >= max_width)
|
||||||
break;
|
break;
|
||||||
line_width += char_width;
|
line_width += char_width;
|
||||||
@ -5000,8 +5027,6 @@ void ImBitmapFont::RenderText(float size, ImVec2 pos, ImU32 col, const ImVec4& c
|
|||||||
pos.x = (float)(int)pos.x + 0.5f;
|
pos.x = (float)(int)pos.x + 0.5f;
|
||||||
pos.y = (float)(int)pos.y + 0.5f;
|
pos.y = (float)(int)pos.y + 0.5f;
|
||||||
|
|
||||||
ImVec2 text_size = ImVec2(0,0);
|
|
||||||
float line_width = 0.0f;
|
|
||||||
const ImVec4 clip_rect = clip_rect_ref;
|
const ImVec4 clip_rect = clip_rect_ref;
|
||||||
|
|
||||||
const float uv_offset = GImGui.IO.PixelCenterOffset;
|
const float uv_offset = GImGui.IO.PixelCenterOffset;
|
||||||
@ -5021,7 +5046,7 @@ void ImBitmapFont::RenderText(float size, ImVec2 pos, ImU32 col, const ImVec4& c
|
|||||||
if (const FntGlyph* glyph = FindGlyph((unsigned short)c))
|
if (const FntGlyph* glyph = FindGlyph((unsigned short)c))
|
||||||
{
|
{
|
||||||
const float char_width = (glyph->XAdvance + Info->SpacingHoriz) * scale;
|
const float char_width = (glyph->XAdvance + Info->SpacingHoriz) * scale;
|
||||||
const float char_extend = (glyph->XOffset + glyph->Width * scale);
|
//const float char_extend = (glyph->XOffset + glyph->Width * scale);
|
||||||
|
|
||||||
if (c != ' ' && c != '\n')
|
if (c != ' ' && c != '\n')
|
||||||
{
|
{
|
||||||
@ -5135,11 +5160,17 @@ void ShowStyleEditor(ImGuiStyle* ref)
|
|||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::RadioButton("HEX", &edit_mode, ImGuiColorEditMode_HEX);
|
ImGui::RadioButton("HEX", &edit_mode, ImGuiColorEditMode_HEX);
|
||||||
|
|
||||||
|
static ImGuiTextFilter filter;
|
||||||
|
filter.Draw("Filter colors", 200);
|
||||||
|
|
||||||
ImGui::ColorEditMode(edit_mode);
|
ImGui::ColorEditMode(edit_mode);
|
||||||
for (size_t i = 0; i < ImGuiCol_COUNT; i++)
|
for (int i = 0; i < ImGuiCol_COUNT; i++)
|
||||||
{
|
{
|
||||||
|
const char* name = GetStyleColorName(i);
|
||||||
|
if (!filter.PassFilter(name))
|
||||||
|
continue;
|
||||||
ImGui::PushID(i);
|
ImGui::PushID(i);
|
||||||
ImGui::ColorEdit4(GetStyleColorName(i), (float*)&style.Colors[i], true);
|
ImGui::ColorEdit4(name, (float*)&style.Colors[i], true);
|
||||||
if (memcmp(&style.Colors[i], (ref ? &ref->Colors[i] : &def.Colors[i]), sizeof(ImVec4)) != 0)
|
if (memcmp(&style.Colors[i], (ref ? &ref->Colors[i] : &def.Colors[i]), sizeof(ImVec4)) != 0)
|
||||||
{
|
{
|
||||||
ImGui::SameLine(); if (ImGui::Button("Revert")) style.Colors[i] = ref ? ref->Colors[i] : def.Colors[i];
|
ImGui::SameLine(); if (ImGui::Button("Revert")) style.Colors[i] = ref ? ref->Colors[i] : def.Colors[i];
|
||||||
@ -5459,7 +5490,7 @@ void ShowTestWindow(bool* open)
|
|||||||
static float foo = 1.0f;
|
static float foo = 1.0f;
|
||||||
ImGui::InputFloat("red", &foo, 0.05f, 0, 3); ImGui::NextColumn();
|
ImGui::InputFloat("red", &foo, 0.05f, 0, 3); ImGui::NextColumn();
|
||||||
static float bar = 1.0f;
|
static float bar = 1.0f;
|
||||||
ImGui::InputFloat("blue", &foo, 0.05f, 0, 3); ImGui::NextColumn();
|
ImGui::InputFloat("blue", &bar, 0.05f, 0, 3); ImGui::NextColumn();
|
||||||
ImGui::Columns(1);
|
ImGui::Columns(1);
|
||||||
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
@ -5519,7 +5550,7 @@ void ShowTestWindow(bool* open)
|
|||||||
if (ImGui::Button("Add 1000 lines"))
|
if (ImGui::Button("Add 1000 lines"))
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < 1000; i++)
|
for (size_t i = 0; i < 1000; i++)
|
||||||
log.Append("%i The quick brown fox jumps over the lazy dog\n", lines+i);
|
log.append("%i The quick brown fox jumps over the lazy dog\n", lines+i);
|
||||||
lines += 1000;
|
lines += 1000;
|
||||||
}
|
}
|
||||||
ImGui::BeginChild("Log");
|
ImGui::BeginChild("Log");
|
||||||
|
43
imgui.h
43
imgui.h
@ -29,8 +29,8 @@ typedef ImU32 ImGuiID;
|
|||||||
typedef int ImGuiCol; // enum ImGuiCol_
|
typedef int ImGuiCol; // enum ImGuiCol_
|
||||||
typedef int ImGuiKey; // enum ImGuiKey_
|
typedef int ImGuiKey; // enum ImGuiKey_
|
||||||
typedef int ImGuiColorEditMode; // enum ImGuiColorEditMode_
|
typedef int ImGuiColorEditMode; // enum ImGuiColorEditMode_
|
||||||
typedef ImU32 ImGuiWindowFlags; // enum ImGuiWindowFlags_
|
typedef int ImGuiWindowFlags; // enum ImGuiWindowFlags_
|
||||||
typedef ImU32 ImGuiInputTextFlags; // enum ImGuiInputTextFlags_
|
typedef int ImGuiInputTextFlags; // enum ImGuiInputTextFlags_
|
||||||
typedef ImBitmapFont* ImFont;
|
typedef ImBitmapFont* ImFont;
|
||||||
|
|
||||||
struct ImVec2
|
struct ImVec2
|
||||||
@ -143,8 +143,10 @@ namespace ImGui
|
|||||||
void SetFontScale(float scale);
|
void SetFontScale(float scale);
|
||||||
void SetScrollPosHere();
|
void SetScrollPosHere();
|
||||||
void SetTreeStateStorage(ImGuiStorage* tree);
|
void SetTreeStateStorage(ImGuiStorage* tree);
|
||||||
|
ImGuiStorage* GetTreeStateStorage();
|
||||||
void PushItemWidth(float item_width);
|
void PushItemWidth(float item_width);
|
||||||
void PopItemWidth();
|
void PopItemWidth();
|
||||||
|
float GetItemWidth();
|
||||||
void PushAllowKeyboardFocus(bool v);
|
void PushAllowKeyboardFocus(bool v);
|
||||||
void PopAllowKeyboardFocus();
|
void PopAllowKeyboardFocus();
|
||||||
void PushStyleColor(ImGuiCol idx, ImVec4 col);
|
void PushStyleColor(ImGuiCol idx, ImVec4 col);
|
||||||
@ -220,9 +222,9 @@ namespace ImGui
|
|||||||
|
|
||||||
// Logging
|
// Logging
|
||||||
void LogButtons();
|
void LogButtons();
|
||||||
void LogToTTY(int max_depth);
|
void LogToTTY(int max_depth = -1);
|
||||||
void LogToFile(int max_depth, const char* filename);
|
void LogToFile(int max_depth = -1, const char* filename = NULL);
|
||||||
void LogToClipboard(int max_depth);
|
void LogToClipboard(int max_depth = -1);
|
||||||
|
|
||||||
// Utilities
|
// Utilities
|
||||||
void SetTooltip(const char* fmt, ...); // set tooltip under mouse-cursor, typically use with ImGui::IsHovered(). (currently no contention handling, last call win)
|
void SetTooltip(const char* fmt, ...); // set tooltip under mouse-cursor, typically use with ImGui::IsHovered(). (currently no contention handling, last call win)
|
||||||
@ -231,6 +233,8 @@ namespace ImGui
|
|||||||
bool IsClipped(ImVec2 item_size); // to perform coarse clipping on user's side (as an optimisation)
|
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 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);
|
bool IsMouseClicked(int button, bool repeat = false);
|
||||||
|
bool IsMouseDoubleClicked(int button);
|
||||||
|
bool IsMouseHoveringBox(const ImVec2& box_min, const ImVec2& box_max);
|
||||||
ImVec2 GetMousePos();
|
ImVec2 GetMousePos();
|
||||||
float GetTime();
|
float GetTime();
|
||||||
int GetFrameCount();
|
int GetFrameCount();
|
||||||
@ -302,6 +306,7 @@ enum ImGuiCol_
|
|||||||
ImGuiCol_ScrollbarGrabHovered,
|
ImGuiCol_ScrollbarGrabHovered,
|
||||||
ImGuiCol_ScrollbarGrabActive,
|
ImGuiCol_ScrollbarGrabActive,
|
||||||
ImGuiCol_ComboBg,
|
ImGuiCol_ComboBg,
|
||||||
|
ImGuiCol_CheckHovered,
|
||||||
ImGuiCol_CheckActive,
|
ImGuiCol_CheckActive,
|
||||||
ImGuiCol_SliderGrab,
|
ImGuiCol_SliderGrab,
|
||||||
ImGuiCol_SliderGrabActive,
|
ImGuiCol_SliderGrabActive,
|
||||||
@ -389,10 +394,13 @@ struct ImGuiIO
|
|||||||
bool KeysDown[512]; // Keyboard keys that are pressed (in whatever order user naturally has access to keyboard data)
|
bool KeysDown[512]; // Keyboard keys that are pressed (in whatever order user naturally has access to keyboard data)
|
||||||
char InputCharacters[16]; // List of characters input (translated by user from keypress+keyboard state). Fill using AddInputCharacter() helper.
|
char InputCharacters[16]; // List of characters input (translated by user from keypress+keyboard state). Fill using AddInputCharacter() helper.
|
||||||
|
|
||||||
// Output - Retrieve after calling NewFrame(), you can use them to discard inputs for the rest of your application
|
// Output - Retrieve after calling NewFrame(), you can use them to discard inputs or hide them from the rest of your application
|
||||||
bool WantCaptureMouse; // ImGui is using your mouse input (= window is being hovered or widget is active).
|
bool WantCaptureMouse; // ImGui is using your mouse input (= window is being hovered or widget is active).
|
||||||
bool WantCaptureKeyboard; // imGui is using your keyboard input (= widget is active).
|
bool WantCaptureKeyboard; // imGui is using your keyboard input (= widget is active).
|
||||||
|
|
||||||
|
// Function
|
||||||
|
void AddInputCharacter(char c); // Helper to add a new character into InputCharacters[]
|
||||||
|
|
||||||
// [Internal] ImGui will maintain those fields for you
|
// [Internal] ImGui will maintain those fields for you
|
||||||
ImVec2 MousePosPrev;
|
ImVec2 MousePosPrev;
|
||||||
ImVec2 MouseDelta;
|
ImVec2 MouseDelta;
|
||||||
@ -404,7 +412,6 @@ struct ImGuiIO
|
|||||||
float KeysDownTime[512];
|
float KeysDownTime[512];
|
||||||
|
|
||||||
ImGuiIO();
|
ImGuiIO();
|
||||||
void AddInputCharacter(char c); // Helper to add a new character into InputCharacters[]
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -465,7 +472,7 @@ struct ImGuiTextBuffer
|
|||||||
size_t size() const { return Buf.size()-1; }
|
size_t size() const { return Buf.size()-1; }
|
||||||
bool empty() { return Buf.empty(); }
|
bool empty() { return Buf.empty(); }
|
||||||
void clear() { Buf.clear(); Buf.push_back(0); }
|
void clear() { Buf.clear(); Buf.push_back(0); }
|
||||||
void Append(const char* fmt, ...);
|
void append(const char* fmt, ...);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Helper: Key->value storage
|
// Helper: Key->value storage
|
||||||
@ -492,19 +499,10 @@ struct ImGuiStorage
|
|||||||
// Hold a series of drawing commands. The user provide a renderer for ImDrawList
|
// Hold a series of drawing commands. The user provide a renderer for ImDrawList
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
enum ImDrawCmdType
|
|
||||||
{
|
|
||||||
ImDrawCmdType_DrawTriangleList,
|
|
||||||
ImDrawCmdType_PushClipRect,
|
|
||||||
ImDrawCmdType_PopClipRect,
|
|
||||||
};
|
|
||||||
|
|
||||||
// sizeof() == 4
|
|
||||||
struct ImDrawCmd
|
struct ImDrawCmd
|
||||||
{
|
{
|
||||||
ImDrawCmdType cmd_type : 16;
|
unsigned int vtx_count;
|
||||||
unsigned int vtx_count : 16;
|
ImVec4 clip_rect;
|
||||||
ImDrawCmd(ImDrawCmdType _cmd_type = ImDrawCmdType_DrawTriangleList, unsigned int _vtx_count = 0) { cmd_type = _cmd_type; vtx_count = _vtx_count; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef IMDRAW_TEX_UV_FOR_WHITE
|
#ifndef IMDRAW_TEX_UV_FOR_WHITE
|
||||||
@ -525,16 +523,15 @@ struct ImDrawList
|
|||||||
{
|
{
|
||||||
ImVector<ImDrawCmd> commands;
|
ImVector<ImDrawCmd> commands;
|
||||||
ImVector<ImDrawVert> vtx_buffer; // each command consume ImDrawCmd::vtx_count of those
|
ImVector<ImDrawVert> vtx_buffer; // each command consume ImDrawCmd::vtx_count of those
|
||||||
ImVector<ImVec4> clip_rect_buffer; // each PushClipRect command consume 1 of those
|
ImVector<ImVec4> clip_rect_stack; // [internal] clip rect stack while building the command-list (so text command can perform clipping early on)
|
||||||
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)
|
||||||
ImDrawVert* vtx_write_; // [internal] point within vtx_buffer after each add command. allow us to use less [] and .resize on the vector (often slow on windows/debug)
|
|
||||||
|
|
||||||
ImDrawList() { Clear(); }
|
ImDrawList() { Clear(); }
|
||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
void PushClipRect(const ImVec4& clip_rect);
|
void PushClipRect(const ImVec4& clip_rect);
|
||||||
void PopClipRect();
|
void PopClipRect();
|
||||||
void AddCommand(ImDrawCmdType cmd_type, int vtx_count);
|
void ReserveVertices(unsigned int vtx_count);
|
||||||
void AddVtx(const ImVec2& pos, ImU32 col);
|
void AddVtx(const ImVec2& pos, ImU32 col);
|
||||||
void AddVtxLine(const ImVec2& a, const ImVec2& b, ImU32 col);
|
void AddVtxLine(const ImVec2& a, const ImVec2& b, ImU32 col);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user