mirror of
https://github.com/Drezil/imgui.git
synced 2024-12-18 06:06:35 +00:00
Merge remote-tracking branch 'origin' into 2015-03-antialiased-primitives
Conflicts: imgui.cpp
This commit is contained in:
commit
cc3ed515ca
@ -26,7 +26,8 @@ static ID3D10Blob * g_pPixelShaderBlob = NULL;
|
|||||||
static ID3D11PixelShader* g_pPixelShader = NULL;
|
static ID3D11PixelShader* g_pPixelShader = NULL;
|
||||||
static ID3D11SamplerState* g_pFontSampler = NULL;
|
static ID3D11SamplerState* g_pFontSampler = NULL;
|
||||||
static ID3D11ShaderResourceView*g_pFontTextureView = NULL;
|
static ID3D11ShaderResourceView*g_pFontTextureView = NULL;
|
||||||
static ID3D11BlendState* g_blendState = NULL;
|
static ID3D11RasterizerState* g_pRasterizerState = NULL;
|
||||||
|
static ID3D11BlendState* g_pBlendState = NULL;
|
||||||
static int VERTEX_BUFFER_SIZE = 30000; // TODO: Make vertex buffer smaller and grow dynamically as needed.
|
static int VERTEX_BUFFER_SIZE = 30000; // TODO: Make vertex buffer smaller and grow dynamically as needed.
|
||||||
|
|
||||||
struct VERTEX_CONSTANT_BUFFER
|
struct VERTEX_CONSTANT_BUFFER
|
||||||
@ -100,7 +101,8 @@ static void ImGui_ImplDX11_RenderDrawLists(ImDrawList** const cmd_lists, int cmd
|
|||||||
|
|
||||||
// Setup render state
|
// Setup render state
|
||||||
const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f };
|
const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f };
|
||||||
g_pd3dDeviceContext->OMSetBlendState(g_blendState, blendFactor, 0xffffffff);
|
g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff);
|
||||||
|
g_pd3dDeviceContext->RSSetState(g_pRasterizerState);
|
||||||
|
|
||||||
// Render command lists
|
// Render command lists
|
||||||
int vtx_offset = 0;
|
int vtx_offset = 0;
|
||||||
@ -339,19 +341,30 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
|
|||||||
desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
|
desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
|
||||||
desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
|
desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
|
||||||
desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
|
desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
|
||||||
g_pd3dDevice->CreateBlendState(&desc, &g_blendState);
|
g_pd3dDevice->CreateBlendState(&desc, &g_pBlendState);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the rasterizer state
|
||||||
|
{
|
||||||
|
D3D11_RASTERIZER_DESC desc;
|
||||||
|
ZeroMemory(&desc, sizeof(desc));
|
||||||
|
desc.FillMode = D3D11_FILL_SOLID;
|
||||||
|
desc.CullMode = D3D11_CULL_NONE;
|
||||||
|
desc.ScissorEnable = true;
|
||||||
|
desc.DepthClipEnable = true;
|
||||||
|
g_pd3dDevice->CreateRasterizerState(&desc, &g_pRasterizerState);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the vertex buffer
|
// Create the vertex buffer
|
||||||
{
|
{
|
||||||
D3D11_BUFFER_DESC bufferDesc;
|
D3D11_BUFFER_DESC desc;
|
||||||
memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC));
|
memset(&desc, 0, sizeof(D3D11_BUFFER_DESC));
|
||||||
bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
|
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||||
bufferDesc.ByteWidth = VERTEX_BUFFER_SIZE * sizeof(ImDrawVert);
|
desc.ByteWidth = VERTEX_BUFFER_SIZE * sizeof(ImDrawVert);
|
||||||
bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||||
bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||||
bufferDesc.MiscFlags = 0;
|
desc.MiscFlags = 0;
|
||||||
if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pVB) < 0)
|
if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -369,7 +382,8 @@ void ImGui_ImplDX11_InvalidateDeviceObjects()
|
|||||||
if (g_pFontTextureView) { g_pFontTextureView->Release(); ImGui::GetIO().Fonts->TexID = 0; }
|
if (g_pFontTextureView) { g_pFontTextureView->Release(); ImGui::GetIO().Fonts->TexID = 0; }
|
||||||
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
|
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
|
||||||
|
|
||||||
if (g_blendState) { g_blendState->Release(); g_blendState = NULL; }
|
if (g_pBlendState) { g_pBlendState->Release(); g_pBlendState = NULL; }
|
||||||
|
if (g_pRasterizerState) { g_pRasterizerState->Release(); g_pRasterizerState = NULL; }
|
||||||
if (g_pPixelShader) { g_pPixelShader->Release(); g_pPixelShader = NULL; }
|
if (g_pPixelShader) { g_pPixelShader->Release(); g_pPixelShader = NULL; }
|
||||||
if (g_pPixelShaderBlob) { g_pPixelShaderBlob->Release(); g_pPixelShaderBlob = NULL; }
|
if (g_pPixelShaderBlob) { g_pPixelShaderBlob->Release(); g_pPixelShaderBlob = NULL; }
|
||||||
if (g_pVertexConstantBuffer) { g_pVertexConstantBuffer->Release(); g_pVertexConstantBuffer = NULL; }
|
if (g_pVertexConstantBuffer) { g_pVertexConstantBuffer->Release(); g_pVertexConstantBuffer = NULL; }
|
||||||
|
@ -20,6 +20,9 @@ int main(int, char**)
|
|||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||||
|
#if __APPLE__
|
||||||
|
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
|
||||||
|
#endif
|
||||||
GLFWwindow* window = glfwCreateWindow(1280, 720, "ImGui OpenGL3 example", NULL, NULL);
|
GLFWwindow* window = glfwCreateWindow(1280, 720, "ImGui OpenGL3 example", NULL, NULL);
|
||||||
glfwMakeContextCurrent(window);
|
glfwMakeContextCurrent(window);
|
||||||
gl3wInit();
|
gl3wInit();
|
||||||
|
96
imgui.cpp
96
imgui.cpp
@ -19,7 +19,7 @@
|
|||||||
- API BREAKING CHANGES (read me when you update!)
|
- API BREAKING CHANGES (read me when you update!)
|
||||||
- FREQUENTLY ASKED QUESTIONS (FAQ), TIPS
|
- FREQUENTLY ASKED QUESTIONS (FAQ), TIPS
|
||||||
- How do I update to a newer version of ImGui?
|
- How do I update to a newer version of ImGui?
|
||||||
- Can I have multiple widgets with the same label? (Yes)
|
- Can I have multiple widgets with the same label? Can I have widget without a label? (Yes)
|
||||||
- Why is my text output blurry?
|
- Why is my text output blurry?
|
||||||
- How can I load a different font than the default?
|
- How can I load a different font than the default?
|
||||||
- How can I load multiple fonts?
|
- How can I load multiple fonts?
|
||||||
@ -202,38 +202,42 @@
|
|||||||
Check the "API BREAKING CHANGES" sections for a list of occasional API breaking changes. If you have a problem with a function, search for its name
|
Check the "API BREAKING CHANGES" sections for a list of occasional API breaking changes. If you have a problem with a function, search for its name
|
||||||
in the code, there will likely be a comment about it. Please report any issue to the GitHub page!
|
in the code, there will likely be a comment about it. Please report any issue to the GitHub page!
|
||||||
|
|
||||||
Q: Can I have multiple widgets with the same label?
|
Q: Can I have multiple widgets with the same label? Can I have widget without a label? (Yes)
|
||||||
A: Yes. A primer on the use of labels/IDs in ImGui..
|
A: Yes. A primer on the use of labels/IDs in ImGui..
|
||||||
|
|
||||||
|
- Elements that are not clickable, such as Text() items don't need an ID.
|
||||||
|
|
||||||
- Interactive widgets require state to be carried over multiple frames (most typically ImGui often needs to remember what is the "active" widget).
|
- Interactive widgets require state to be carried over multiple frames (most typically ImGui often needs to remember what is the "active" widget).
|
||||||
to do so they need an unique ID. unique ID are typically derived from a string label, an integer index or a pointer.
|
to do so they need an unique ID. unique ID are typically derived from a string label, an integer index or a pointer.
|
||||||
|
|
||||||
Button("OK"); // Label = "OK", ID = hash of "OK"
|
Button("OK"); // Label = "OK", ID = hash of "OK"
|
||||||
Button("Cancel"); // Label = "Cancel", ID = hash of "Cancel"
|
Button("Cancel"); // Label = "Cancel", ID = hash of "Cancel"
|
||||||
|
|
||||||
- Elements that are not clickable, such as Text() items don't need an ID.
|
|
||||||
|
|
||||||
- ID are uniquely scoped within windows, tree nodes, etc. so no conflict can happen if you have two buttons called "OK" in two different windows
|
- ID are uniquely scoped within windows, tree nodes, etc. so no conflict can happen if you have two buttons called "OK" in two different windows
|
||||||
or in two different locations of a tree.
|
or in two different locations of a tree.
|
||||||
|
|
||||||
- if you have a same ID twice in the same location, you'll have a conflict:
|
- if you have a same ID twice in the same location, you'll have a conflict:
|
||||||
|
|
||||||
Button("OK");
|
Button("OK");
|
||||||
Button("OK"); // ID collision! Both buttons will be treated as the same.
|
Button("OK"); // ID collision! Both buttons will be treated as the same.
|
||||||
|
|
||||||
Fear not! this is easy to solve and there are many ways to solve it!
|
Fear not! this is easy to solve and there are many ways to solve it!
|
||||||
|
|
||||||
- when passing a label you can optionally specify extra unique ID information within string itself. This helps solving the simpler collision cases.
|
- when passing a label you can optionally specify extra unique ID information within string itself. This helps solving the simpler collision cases.
|
||||||
use "##" to pass a complement to the ID that won't be visible to the end-user:
|
use "##" to pass a complement to the ID that won't be visible to the end-user:
|
||||||
|
|
||||||
Button("Play##0"); // Label = "Play", ID = hash of "Play##0"
|
Button("Play##0"); // Label = "Play", ID = hash of "Play##0"
|
||||||
Button("Play##1"); // Label = "Play", ID = hash of "Play##1" (different from above)
|
Button("Play##1"); // Label = "Play", ID = hash of "Play##1" (different from above)
|
||||||
|
|
||||||
|
- so if you want to hide the label but need an ID:
|
||||||
|
|
||||||
|
Checkbox("##On", &b); // Label = "", ID = hash of "##On"
|
||||||
|
|
||||||
- occasionally (rarely) you might want change a label while preserving a constant ID. This allows you to animate labels.
|
- occasionally (rarely) you might want change a label while preserving a constant ID. This allows you to animate labels.
|
||||||
use "###" to pass a label that isn't part of ID:
|
use "###" to pass a label that isn't part of ID:
|
||||||
|
|
||||||
Button("Hello###ID"; // Label = "Hello", ID = hash of "ID"
|
Button("Hello###ID"; // Label = "Hello", ID = hash of "ID"
|
||||||
Button("World###ID"; // Label = "World", ID = hash of "ID" (same as above)
|
Button("World###ID"; // Label = "World", ID = hash of "ID" (same as above)
|
||||||
|
|
||||||
- use PushID() / PopID() to create scopes and avoid ID conflicts within the same Window.
|
- use PushID() / PopID() to create scopes and avoid ID conflicts within the same Window.
|
||||||
this is the most convenient way of distinguish ID if you are iterating and creating many UI elements.
|
this is the most convenient way of distinguish ID if you are iterating and creating many UI elements.
|
||||||
@ -501,8 +505,9 @@ struct ImGuiTextEditState;
|
|||||||
struct ImGuiIniData;
|
struct ImGuiIniData;
|
||||||
struct ImGuiState;
|
struct ImGuiState;
|
||||||
struct ImGuiWindow;
|
struct ImGuiWindow;
|
||||||
|
typedef int ImGuiButtonFlags; // enum ImGuiButtonFlags_
|
||||||
|
|
||||||
static bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, bool allow_key_modifiers, bool repeat = false, bool pressed_on_click = false);
|
static bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, bool allow_key_modifiers, ImGuiButtonFlags flags = 0);
|
||||||
static void LogText(const ImVec2& ref_pos, const char* text, const char* text_end = NULL);
|
static void LogText(const ImVec2& ref_pos, const char* text, const char* text_end = NULL);
|
||||||
|
|
||||||
static void RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true);
|
static void RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true);
|
||||||
@ -706,6 +711,7 @@ static inline ImVec2& operator+=(ImVec2& lhs, const ImVec2& rhs)
|
|||||||
static inline ImVec2& operator-=(ImVec2& lhs, const ImVec2& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; return lhs; }
|
static inline ImVec2& operator-=(ImVec2& lhs, const ImVec2& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; return lhs; }
|
||||||
static inline ImVec2& operator*=(ImVec2& lhs, const float rhs) { lhs.x *= rhs; lhs.y *= rhs; return lhs; }
|
static inline ImVec2& operator*=(ImVec2& lhs, const float rhs) { lhs.x *= rhs; lhs.y *= rhs; return lhs; }
|
||||||
//static inline ImVec2& operator/=(ImVec2& lhs, const float rhs) { lhs.x /= rhs; lhs.y /= rhs; return lhs; }
|
//static inline ImVec2& operator/=(ImVec2& lhs, const float rhs) { lhs.x /= rhs; lhs.y /= rhs; return lhs; }
|
||||||
|
static inline ImVec4 operator-(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x-rhs.x, lhs.y-rhs.y, lhs.z-rhs.z, lhs.w-lhs.w); }
|
||||||
|
|
||||||
static inline int ImMin(int lhs, int rhs) { return lhs < rhs ? lhs : rhs; }
|
static inline int ImMin(int lhs, int rhs) { return lhs < rhs ? lhs : rhs; }
|
||||||
static inline int ImMax(int lhs, int rhs) { return lhs >= rhs ? lhs : rhs; }
|
static inline int ImMax(int lhs, int rhs) { return lhs >= rhs ? lhs : rhs; }
|
||||||
@ -720,6 +726,7 @@ static inline float ImSaturate(float f)
|
|||||||
static inline float ImLerp(float a, float b, float t) { return a + (b - a) * t; }
|
static inline float ImLerp(float a, float b, float t) { return a + (b - a) * t; }
|
||||||
static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, const ImVec2& t) { return ImVec2(a.x + (b.x - a.x) * t.x, a.y + (b.y - a.y) * t.y); }
|
static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, const ImVec2& t) { return ImVec2(a.x + (b.x - a.x) * t.x, a.y + (b.y - a.y) * t.y); }
|
||||||
static inline float ImLengthSqr(const ImVec2& lhs) { return lhs.x*lhs.x + lhs.y*lhs.y; }
|
static inline float ImLengthSqr(const ImVec2& lhs) { return lhs.x*lhs.x + lhs.y*lhs.y; }
|
||||||
|
static inline float ImLengthSqr(const ImVec4& lhs) { return lhs.x*lhs.x + lhs.y*lhs.y + lhs.z*lhs.z + lhs.w*lhs.w; }
|
||||||
|
|
||||||
static int ImStricmp(const char* str1, const char* str2)
|
static int ImStricmp(const char* str1, const char* str2)
|
||||||
{
|
{
|
||||||
@ -938,6 +945,13 @@ static bool ImLoadFileToMemory(const char* filename, const char* file_open_mode,
|
|||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
enum ImGuiButtonFlags_
|
||||||
|
{
|
||||||
|
ImGuiButtonFlags_Repeat = (1 << 0),
|
||||||
|
ImGuiButtonFlags_PressedOnClick = (1 << 1),
|
||||||
|
ImGuiButtonFlags_FlattenChilds = (1 << 2)
|
||||||
|
};
|
||||||
|
|
||||||
struct ImGuiColMod // Color modifier, backup of modified data so we can restore it
|
struct ImGuiColMod // Color modifier, backup of modified data so we can restore it
|
||||||
{
|
{
|
||||||
ImGuiCol Col;
|
ImGuiCol Col;
|
||||||
@ -1283,6 +1297,7 @@ struct ImGuiWindow
|
|||||||
bool Accessed; // Set to true when any widget access the current window
|
bool Accessed; // Set to true when any widget access the current window
|
||||||
bool Collapsed; // Set when collapsing window to become only title-bar
|
bool Collapsed; // Set when collapsing window to become only title-bar
|
||||||
bool SkipItems; // == Visible && !Collapsed
|
bool SkipItems; // == Visible && !Collapsed
|
||||||
|
int BeginCount; // Number of Begin() during the current frame (generally 0 or 1, 1+ if appending via multiple Begin/End pairs)
|
||||||
int AutoFitFrames;
|
int AutoFitFrames;
|
||||||
bool AutoFitOnlyGrows;
|
bool AutoFitOnlyGrows;
|
||||||
int AutoPosLastDirection;
|
int AutoPosLastDirection;
|
||||||
@ -1642,6 +1657,7 @@ ImGuiWindow::ImGuiWindow(const char* name)
|
|||||||
Accessed = false;
|
Accessed = false;
|
||||||
Collapsed = false;
|
Collapsed = false;
|
||||||
SkipItems = false;
|
SkipItems = false;
|
||||||
|
BeginCount = 0;
|
||||||
AutoFitFrames = -1;
|
AutoFitFrames = -1;
|
||||||
AutoFitOnlyGrows = false;
|
AutoFitOnlyGrows = false;
|
||||||
AutoPosLastDirection = -1;
|
AutoPosLastDirection = -1;
|
||||||
@ -1873,7 +1889,6 @@ static void SaveSettings()
|
|||||||
static void MarkSettingsDirty()
|
static void MarkSettingsDirty()
|
||||||
{
|
{
|
||||||
ImGuiState& g = *GImGui;
|
ImGuiState& g = *GImGui;
|
||||||
|
|
||||||
if (g.SettingsDirtyTimer <= 0.0f)
|
if (g.SettingsDirtyTimer <= 0.0f)
|
||||||
g.SettingsDirtyTimer = g.IO.IniSavingRate;
|
g.SettingsDirtyTimer = g.IO.IniSavingRate;
|
||||||
}
|
}
|
||||||
@ -2986,7 +3001,7 @@ void ImGui::EndChild()
|
|||||||
ImGuiWindow* window = GetCurrentWindow();
|
ImGuiWindow* window = GetCurrentWindow();
|
||||||
|
|
||||||
IM_ASSERT(window->Flags & ImGuiWindowFlags_ChildWindow);
|
IM_ASSERT(window->Flags & ImGuiWindowFlags_ChildWindow);
|
||||||
if (window->Flags & ImGuiWindowFlags_ComboBox)
|
if ((window->Flags & ImGuiWindowFlags_ComboBox) || window->BeginCount > 1)
|
||||||
{
|
{
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
@ -3223,21 +3238,19 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_
|
|||||||
if (first_begin_of_the_frame)
|
if (first_begin_of_the_frame)
|
||||||
{
|
{
|
||||||
window->Active = true;
|
window->Active = true;
|
||||||
|
window->BeginCount = 0;
|
||||||
window->DrawList->Clear();
|
window->DrawList->Clear();
|
||||||
window->ClipRectStack.resize(0);
|
window->ClipRectStack.resize(0);
|
||||||
window->LastFrameDrawn = current_frame;
|
window->LastFrameDrawn = current_frame;
|
||||||
window->IDStack.resize(1);
|
window->IDStack.resize(1);
|
||||||
}
|
|
||||||
|
|
||||||
// Setup texture, outer clipping rectangle
|
// Setup texture, outer clipping rectangle
|
||||||
window->DrawList->PushTextureID(g.Font->ContainerAtlas->TexID);
|
window->DrawList->PushTextureID(g.Font->ContainerAtlas->TexID);
|
||||||
if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_ComboBox))
|
if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_ComboBox))
|
||||||
PushClipRect(parent_window->ClipRectStack.back());
|
PushClipRect(parent_window->ClipRectStack.back());
|
||||||
else
|
else
|
||||||
PushClipRect(GetVisibleRect());
|
PushClipRect(GetVisibleRect());
|
||||||
|
|
||||||
if (first_begin_of_the_frame)
|
|
||||||
{
|
|
||||||
// New windows appears in front
|
// New windows appears in front
|
||||||
if (!window_was_visible)
|
if (!window_was_visible)
|
||||||
{
|
{
|
||||||
@ -3436,7 +3449,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_
|
|||||||
const ImRect resize_rect(window->Rect().GetBR()-ImVec2(14,14), window->Rect().GetBR());
|
const ImRect resize_rect(window->Rect().GetBR()-ImVec2(14,14), window->Rect().GetBR());
|
||||||
const ImGuiID resize_id = window->GetID("#RESIZE");
|
const ImGuiID resize_id = window->GetID("#RESIZE");
|
||||||
bool hovered, held;
|
bool hovered, held;
|
||||||
ButtonBehavior(resize_rect, resize_id, &hovered, &held, true);
|
ButtonBehavior(resize_rect, resize_id, &hovered, &held, true, ImGuiButtonFlags_FlattenChilds);
|
||||||
resize_col = window->Color(held ? ImGuiCol_ResizeGripActive : hovered ? ImGuiCol_ResizeGripHovered : ImGuiCol_ResizeGrip);
|
resize_col = window->Color(held ? ImGuiCol_ResizeGripActive : hovered ? ImGuiCol_ResizeGripHovered : ImGuiCol_ResizeGrip);
|
||||||
|
|
||||||
if (hovered || held)
|
if (hovered || held)
|
||||||
@ -3584,6 +3597,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_
|
|||||||
ImGui::LogToClipboard();
|
ImGui::LogToClipboard();
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
window->BeginCount++;
|
||||||
|
|
||||||
// Inner clipping rectangle
|
// Inner clipping rectangle
|
||||||
// We set this up after processing the resize grip so that our clip rectangle doesn't lag by a frame
|
// We set this up after processing the resize grip so that our clip rectangle doesn't lag by a frame
|
||||||
@ -3628,8 +3642,6 @@ void ImGui::End()
|
|||||||
|
|
||||||
ImGui::Columns(1, "#CloseColumns");
|
ImGui::Columns(1, "#CloseColumns");
|
||||||
PopClipRect(); // inner window clip rectangle
|
PopClipRect(); // inner window clip rectangle
|
||||||
PopClipRect(); // outer window clip rectangle
|
|
||||||
window->DrawList->PopTextureID();
|
|
||||||
|
|
||||||
// Stop logging
|
// Stop logging
|
||||||
if (!(window->Flags & ImGuiWindowFlags_ChildWindow)) // FIXME: add more options for scope of logging
|
if (!(window->Flags & ImGuiWindowFlags_ChildWindow)) // FIXME: add more options for scope of logging
|
||||||
@ -3782,7 +3794,6 @@ float ImGui::CalcItemWidth()
|
|||||||
static void SetFont(ImFont* font)
|
static void SetFont(ImFont* font)
|
||||||
{
|
{
|
||||||
ImGuiState& g = *GImGui;
|
ImGuiState& g = *GImGui;
|
||||||
|
|
||||||
IM_ASSERT(font && font->IsLoaded());
|
IM_ASSERT(font && font->IsLoaded());
|
||||||
IM_ASSERT(font->Scale > 0.0f);
|
IM_ASSERT(font->Scale > 0.0f);
|
||||||
g.Font = font;
|
g.Font = font;
|
||||||
@ -3794,10 +3805,8 @@ static void SetFont(ImFont* font)
|
|||||||
void ImGui::PushFont(ImFont* font)
|
void ImGui::PushFont(ImFont* font)
|
||||||
{
|
{
|
||||||
ImGuiState& g = *GImGui;
|
ImGuiState& g = *GImGui;
|
||||||
|
|
||||||
if (!font)
|
if (!font)
|
||||||
font = g.IO.Fonts->Fonts[0];
|
font = g.IO.Fonts->Fonts[0];
|
||||||
|
|
||||||
SetFont(font);
|
SetFont(font);
|
||||||
g.FontStack.push_back(font);
|
g.FontStack.push_back(font);
|
||||||
g.CurrentWindow->DrawList->PushTextureID(font->ContainerAtlas->TexID);
|
g.CurrentWindow->DrawList->PushTextureID(font->ContainerAtlas->TexID);
|
||||||
@ -3806,7 +3815,6 @@ void ImGui::PushFont(ImFont* font)
|
|||||||
void ImGui::PopFont()
|
void ImGui::PopFont()
|
||||||
{
|
{
|
||||||
ImGuiState& g = *GImGui;
|
ImGuiState& g = *GImGui;
|
||||||
|
|
||||||
g.CurrentWindow->DrawList->PopTextureID();
|
g.CurrentWindow->DrawList->PopTextureID();
|
||||||
g.FontStack.pop_back();
|
g.FontStack.pop_back();
|
||||||
SetFont(g.FontStack.empty() ? g.IO.Fonts->Fonts[0] : g.FontStack.back());
|
SetFont(g.FontStack.empty() ? g.IO.Fonts->Fonts[0] : g.FontStack.back());
|
||||||
@ -3839,7 +3847,6 @@ void ImGui::PopTextWrapPos()
|
|||||||
void ImGui::PushStyleColor(ImGuiCol idx, const ImVec4& col)
|
void ImGui::PushStyleColor(ImGuiCol idx, const ImVec4& col)
|
||||||
{
|
{
|
||||||
ImGuiState& g = *GImGui;
|
ImGuiState& g = *GImGui;
|
||||||
|
|
||||||
ImGuiColMod backup;
|
ImGuiColMod backup;
|
||||||
backup.Col = idx;
|
backup.Col = idx;
|
||||||
backup.PreviousValue = g.Style.Colors[idx];
|
backup.PreviousValue = g.Style.Colors[idx];
|
||||||
@ -3850,7 +3857,6 @@ void ImGui::PushStyleColor(ImGuiCol idx, const ImVec4& col)
|
|||||||
void ImGui::PopStyleColor(int count)
|
void ImGui::PopStyleColor(int count)
|
||||||
{
|
{
|
||||||
ImGuiState& g = *GImGui;
|
ImGuiState& g = *GImGui;
|
||||||
|
|
||||||
while (count > 0)
|
while (count > 0)
|
||||||
{
|
{
|
||||||
ImGuiColMod& backup = g.ColorModifiers.back();
|
ImGuiColMod& backup = g.ColorModifiers.back();
|
||||||
@ -3891,7 +3897,6 @@ static ImVec2* GetStyleVarVec2Addr(ImGuiStyleVar idx)
|
|||||||
void ImGui::PushStyleVar(ImGuiStyleVar idx, float val)
|
void ImGui::PushStyleVar(ImGuiStyleVar idx, float val)
|
||||||
{
|
{
|
||||||
ImGuiState& g = *GImGui;
|
ImGuiState& g = *GImGui;
|
||||||
|
|
||||||
float* pvar = GetStyleVarFloatAddr(idx);
|
float* pvar = GetStyleVarFloatAddr(idx);
|
||||||
IM_ASSERT(pvar != NULL); // Called function with wrong-type? Variable is not a float.
|
IM_ASSERT(pvar != NULL); // Called function with wrong-type? Variable is not a float.
|
||||||
ImGuiStyleMod backup;
|
ImGuiStyleMod backup;
|
||||||
@ -3905,7 +3910,6 @@ void ImGui::PushStyleVar(ImGuiStyleVar idx, float val)
|
|||||||
void ImGui::PushStyleVar(ImGuiStyleVar idx, const ImVec2& val)
|
void ImGui::PushStyleVar(ImGuiStyleVar idx, const ImVec2& val)
|
||||||
{
|
{
|
||||||
ImGuiState& g = *GImGui;
|
ImGuiState& g = *GImGui;
|
||||||
|
|
||||||
ImVec2* pvar = GetStyleVarVec2Addr(idx);
|
ImVec2* pvar = GetStyleVarVec2Addr(idx);
|
||||||
IM_ASSERT(pvar != NULL); // Called function with wrong-type? Variable is not a ImVec2.
|
IM_ASSERT(pvar != NULL); // Called function with wrong-type? Variable is not a ImVec2.
|
||||||
ImGuiStyleMod backup;
|
ImGuiStyleMod backup;
|
||||||
@ -3918,7 +3922,6 @@ void ImGui::PushStyleVar(ImGuiStyleVar idx, const ImVec2& val)
|
|||||||
void ImGui::PopStyleVar(int count)
|
void ImGui::PopStyleVar(int count)
|
||||||
{
|
{
|
||||||
ImGuiState& g = *GImGui;
|
ImGuiState& g = *GImGui;
|
||||||
|
|
||||||
while (count > 0)
|
while (count > 0)
|
||||||
{
|
{
|
||||||
ImGuiStyleMod& backup = g.StyleModifiers.back();
|
ImGuiStyleMod& backup = g.StyleModifiers.back();
|
||||||
@ -4521,10 +4524,9 @@ void ImGui::LabelText(const char* label, const char* fmt, ...)
|
|||||||
|
|
||||||
static inline bool IsWindowContentHoverable(ImGuiWindow* window)
|
static inline bool IsWindowContentHoverable(ImGuiWindow* window)
|
||||||
{
|
{
|
||||||
ImGuiState& g = *GImGui;
|
|
||||||
|
|
||||||
// An active popup disable hovering on other windows (apart from its own children)
|
// An active popup disable hovering on other windows (apart from its own children)
|
||||||
if (ImGuiWindow* focused_window = g.FocusedWindow)
|
ImGuiState& g = *GImGui;
|
||||||
|
if (ImGuiWindow* focused_window = g.FocusedWindow)
|
||||||
if (ImGuiWindow* focused_root_window = focused_window->RootWindow)
|
if (ImGuiWindow* focused_root_window = focused_window->RootWindow)
|
||||||
if ((focused_root_window->Flags & ImGuiWindowFlags_Popup) != 0 && focused_root_window->WasActive && focused_root_window != window->RootWindow)
|
if ((focused_root_window->Flags & ImGuiWindowFlags_Popup) != 0 && focused_root_window->WasActive && focused_root_window != window->RootWindow)
|
||||||
return false;
|
return false;
|
||||||
@ -4532,13 +4534,13 @@ static inline bool IsWindowContentHoverable(ImGuiWindow* window)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsHovered(const ImRect& bb, ImGuiID id)
|
static bool IsHovered(const ImRect& bb, ImGuiID id, bool flatten_childs = false)
|
||||||
{
|
{
|
||||||
ImGuiState& g = *GImGui;
|
ImGuiState& g = *GImGui;
|
||||||
if (g.HoveredId == 0)
|
if (g.HoveredId == 0)
|
||||||
{
|
{
|
||||||
ImGuiWindow* window = GetCurrentWindow();
|
ImGuiWindow* window = GetCurrentWindow();
|
||||||
if (g.HoveredRootWindow == window->RootWindow)
|
if (g.HoveredWindow == window || (flatten_childs && g.HoveredRootWindow == window->RootWindow))
|
||||||
if ((g.ActiveId == 0 || g.ActiveId == id || g.ActiveIdIsFocusedOnly) && IsMouseHoveringRect(bb))
|
if ((g.ActiveId == 0 || g.ActiveId == id || g.ActiveIdIsFocusedOnly) && IsMouseHoveringRect(bb))
|
||||||
if (IsWindowContentHoverable(g.HoveredRootWindow))
|
if (IsWindowContentHoverable(g.HoveredRootWindow))
|
||||||
return true;
|
return true;
|
||||||
@ -4546,13 +4548,13 @@ static bool IsHovered(const ImRect& bb, ImGuiID id)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, bool allow_key_modifiers, bool repeat, bool pressed_on_click)
|
static bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, bool allow_key_modifiers, ImGuiButtonFlags flags)
|
||||||
{
|
{
|
||||||
ImGuiState& g = *GImGui;
|
ImGuiState& g = *GImGui;
|
||||||
ImGuiWindow* window = GetCurrentWindow();
|
ImGuiWindow* window = GetCurrentWindow();
|
||||||
|
|
||||||
const bool hovered = IsHovered(bb, id);
|
|
||||||
bool pressed = false;
|
bool pressed = false;
|
||||||
|
const bool hovered = IsHovered(bb, id, (flags & ImGuiButtonFlags_FlattenChilds) != 0);
|
||||||
if (hovered)
|
if (hovered)
|
||||||
{
|
{
|
||||||
g.HoveredId = id;
|
g.HoveredId = id;
|
||||||
@ -4560,7 +4562,7 @@ static bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
|
|||||||
{
|
{
|
||||||
if (g.IO.MouseClicked[0])
|
if (g.IO.MouseClicked[0])
|
||||||
{
|
{
|
||||||
if (pressed_on_click)
|
if (flags & ImGuiButtonFlags_PressedOnClick)
|
||||||
{
|
{
|
||||||
pressed = true;
|
pressed = true;
|
||||||
SetActiveId(0);
|
SetActiveId(0);
|
||||||
@ -4571,7 +4573,7 @@ static bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
|
|||||||
}
|
}
|
||||||
FocusWindow(window);
|
FocusWindow(window);
|
||||||
}
|
}
|
||||||
else if (repeat && g.ActiveId && ImGui::IsMouseClicked(0, true))
|
else if ((flags & ImGuiButtonFlags_Repeat) && g.ActiveId == id && ImGui::IsMouseClicked(0, true))
|
||||||
{
|
{
|
||||||
pressed = true;
|
pressed = true;
|
||||||
}
|
}
|
||||||
@ -4617,7 +4619,7 @@ bool ImGui::Button(const char* label, const ImVec2& size_arg, bool repeat_when_h
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
bool hovered, held;
|
bool hovered, held;
|
||||||
bool pressed = ButtonBehavior(bb, id, &hovered, &held, true, repeat_when_held);
|
bool pressed = ButtonBehavior(bb, id, &hovered, &held, true, repeat_when_held ? ImGuiButtonFlags_Repeat : 0);
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
const ImU32 col = window->Color((hovered && held) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
|
const ImU32 col = window->Color((hovered && held) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
|
||||||
@ -7093,7 +7095,7 @@ bool ImGui::Selectable(const char* label, bool selected, const ImVec2& size_arg)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
bool hovered, held;
|
bool hovered, held;
|
||||||
bool pressed = ButtonBehavior(bb_with_spacing, id, &hovered, &held, true, false, false);
|
bool pressed = ButtonBehavior(bb_with_spacing, id, &hovered, &held, true);
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
if (hovered || selected)
|
if (hovered || selected)
|
||||||
@ -7999,7 +8001,11 @@ void ImDrawList::UpdateClipRect()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
current_cmd->clip_rect = clip_rect_stack.empty() ? GNullClipRect : clip_rect_stack.back();
|
ImVec4 current_clip_rect = clip_rect_stack.empty() ? GNullClipRect : clip_rect_stack.back();
|
||||||
|
if (commands.size() > 2 && ImLengthSqr(commands[commands.size()-2].clip_rect - current_clip_rect) < 0.00001f)
|
||||||
|
commands.pop_back();
|
||||||
|
else
|
||||||
|
current_cmd->clip_rect = current_clip_rect;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
137
imgui.h
137
imgui.h
@ -36,7 +36,7 @@ struct ImGuiStorage;
|
|||||||
struct ImGuiStyle;
|
struct ImGuiStyle;
|
||||||
|
|
||||||
typedef unsigned int ImU32;
|
typedef unsigned int ImU32;
|
||||||
typedef unsigned short ImWchar; // character for display
|
typedef unsigned short ImWchar; // character for keyboard input/display
|
||||||
typedef void* ImTextureID; // user data to refer to a texture (e.g. store your texture handle/id)
|
typedef void* ImTextureID; // user data to refer to a texture (e.g. store your texture handle/id)
|
||||||
typedef ImU32 ImGuiID; // unique ID used by widgets (typically hashed from a stack of string)
|
typedef ImU32 ImGuiID; // unique ID used by widgets (typically hashed from a stack of string)
|
||||||
typedef int ImGuiCol; // enum ImGuiCol_
|
typedef int ImGuiCol; // enum ImGuiCol_
|
||||||
@ -73,79 +73,17 @@ struct ImVec4
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace ImGui
|
|
||||||
{
|
|
||||||
// Proxy functions to access the MemAllocFn/MemFreeFn pointers in ImGui::GetIO(). The only reason they exist here is to allow ImVector<> to compile inline.
|
|
||||||
IMGUI_API void* MemAlloc(size_t sz);
|
|
||||||
IMGUI_API void MemFree(void* ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// std::vector<> like class to avoid dragging dependencies (also: windows implementation of STL with debug enabled is absurdly slow, so let's bypass it so our code runs fast in debug).
|
|
||||||
// Use '#define ImVector std::vector' if you want to use the STL type or your own type.
|
|
||||||
// Our implementation does NOT call c++ constructors! because the data types we use don't need them (but that could be added as well). Only provide the minimum functionalities we need.
|
|
||||||
#ifndef ImVector
|
|
||||||
template<typename T>
|
|
||||||
class ImVector
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
size_t Size;
|
|
||||||
size_t Capacity;
|
|
||||||
T* Data;
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef T value_type;
|
|
||||||
typedef value_type* iterator;
|
|
||||||
typedef const value_type* const_iterator;
|
|
||||||
|
|
||||||
ImVector() { Size = Capacity = 0; Data = NULL; }
|
|
||||||
~ImVector() { if (Data) ImGui::MemFree(Data); }
|
|
||||||
|
|
||||||
inline bool empty() const { return Size == 0; }
|
|
||||||
inline size_t size() const { return Size; }
|
|
||||||
inline size_t capacity() const { return Capacity; }
|
|
||||||
|
|
||||||
inline value_type& at(size_t i) { IM_ASSERT(i < Size); return Data[i]; }
|
|
||||||
inline const value_type& at(size_t i) const { IM_ASSERT(i < Size); return Data[i]; }
|
|
||||||
inline value_type& operator[](size_t i) { IM_ASSERT(i < Size); return Data[i]; }
|
|
||||||
inline const value_type& operator[](size_t i) const { IM_ASSERT(i < Size); return Data[i]; }
|
|
||||||
|
|
||||||
inline void clear() { if (Data) { Size = Capacity = 0; ImGui::MemFree(Data); Data = NULL; } }
|
|
||||||
inline iterator begin() { return Data; }
|
|
||||||
inline const_iterator begin() const { return Data; }
|
|
||||||
inline iterator end() { return Data + Size; }
|
|
||||||
inline const_iterator end() const { return Data + Size; }
|
|
||||||
inline value_type& front() { IM_ASSERT(Size > 0); return Data[0]; }
|
|
||||||
inline const value_type& front() const { IM_ASSERT(Size > 0); return Data[0]; }
|
|
||||||
inline value_type& back() { IM_ASSERT(Size > 0); return Data[Size-1]; }
|
|
||||||
inline const value_type& back() const { IM_ASSERT(Size > 0); return Data[Size-1]; }
|
|
||||||
inline void swap(ImVector<T>& rhs) { const size_t rhs_size = rhs.Size; rhs.Size = Size; Size = rhs_size; const size_t rhs_cap = rhs.Capacity; rhs.Capacity = Capacity; Capacity = rhs_cap; value_type* rhs_data = rhs.Data; rhs.Data = Data; Data = rhs_data; }
|
|
||||||
|
|
||||||
inline void resize(size_t new_size) { if (new_size > Capacity) reserve(new_size); Size = new_size; }
|
|
||||||
inline void reserve(size_t new_capacity)
|
|
||||||
{
|
|
||||||
if (new_capacity <= Capacity) return;
|
|
||||||
T* new_data = (value_type*)ImGui::MemAlloc(new_capacity * sizeof(value_type));
|
|
||||||
memcpy(new_data, Data, Size * sizeof(value_type));
|
|
||||||
ImGui::MemFree(Data);
|
|
||||||
Data = new_data;
|
|
||||||
Capacity = new_capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void push_back(const value_type& v) { if (Size == Capacity) reserve(Capacity ? Capacity * 2 : 4); Data[Size++] = v; }
|
|
||||||
inline void pop_back() { IM_ASSERT(Size > 0); Size--; }
|
|
||||||
|
|
||||||
inline iterator erase(const_iterator it) { IM_ASSERT(it >= begin() && it < end()); const ptrdiff_t off = it - begin(); memmove(Data + off, Data + off + 1, (Size - (size_t)off - 1) * sizeof(value_type)); Size--; return Data + off; }
|
|
||||||
inline iterator insert(const_iterator it, const value_type& v) { IM_ASSERT(it >= begin() && it <= end()); const ptrdiff_t off = it - begin(); if (Size == Capacity) reserve(Capacity ? Capacity * 2 : 4); if (off < (int)Size) memmove(Data + off + 1, Data + off, (Size - (size_t)off) * sizeof(value_type)); Data[off] = v; Size++; return Data + off; }
|
|
||||||
};
|
|
||||||
#endif // #ifndef ImVector
|
|
||||||
|
|
||||||
// Helpers at bottom of the file:
|
// Helpers at bottom of the file:
|
||||||
|
// - class ImVector<> // Lightweight std::vector like class. Use '#define ImVector std::vector' if you want to use the STL type or your own type.
|
||||||
// - IMGUI_ONCE_UPON_A_FRAME // Execute a block of code once per frame only (convenient for creating UI within deep-nested code that runs multiple times)
|
// - IMGUI_ONCE_UPON_A_FRAME // Execute a block of code once per frame only (convenient for creating UI within deep-nested code that runs multiple times)
|
||||||
// - struct ImGuiTextFilter // Parse and apply text filters. In format "aaaaa[,bbbb][,ccccc]"
|
// - struct ImGuiTextFilter // Parse and apply text filters. In format "aaaaa[,bbbb][,ccccc]"
|
||||||
// - struct ImGuiTextBuffer // Text buffer for logging/accumulating text
|
// - struct ImGuiTextBuffer // Text buffer for logging/accumulating text
|
||||||
// - struct ImGuiStorage // Custom key value storage (if you need to alter open/close states manually)
|
// - struct ImGuiStorage // Custom key value storage (if you need to alter open/close states manually)
|
||||||
|
// - struct ImGuiTextEditCallbackData // Shared state of ImGui::InputText() when using custom callbacks
|
||||||
|
// - struct ImColor // Helper functions to created packed 32-bit RGBA color values
|
||||||
// - struct ImDrawList // Draw command list
|
// - struct ImDrawList // Draw command list
|
||||||
// - struct ImFont // TTF font loader, bake glyphs into bitmap
|
// - struct ImFontAtlas // Bake multiple fonts into a single texture, TTF font loader, bake glyphs into bitmap
|
||||||
|
// - struct ImFont // Single font
|
||||||
|
|
||||||
// ImGui end-user API
|
// ImGui end-user API
|
||||||
// In a namespace so that user can add extra functions in a separate file (e.g. Value() helpers for your vector or common types)
|
// In a namespace so that user can add extra functions in a separate file (e.g. Value() helpers for your vector or common types)
|
||||||
@ -421,6 +359,10 @@ namespace ImGui
|
|||||||
IMGUI_API void ColorConvertRGBtoHSV(float r, float g, float b, float& out_h, float& out_s, float& out_v);
|
IMGUI_API void ColorConvertRGBtoHSV(float r, float g, float b, float& out_h, float& out_s, float& out_v);
|
||||||
IMGUI_API void ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float& out_g, float& out_b);
|
IMGUI_API void ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float& out_g, float& out_b);
|
||||||
|
|
||||||
|
// Proxy functions to access the MemAllocFn/MemFreeFn pointers in ImGui::GetIO()
|
||||||
|
IMGUI_API void* MemAlloc(size_t sz);
|
||||||
|
IMGUI_API void MemFree(void* ptr);
|
||||||
|
|
||||||
// Internal state access - if you want to share ImGui state between modules (e.g. DLL) or allocate it yourself
|
// Internal state access - if you want to share ImGui state between modules (e.g. DLL) or allocate it yourself
|
||||||
IMGUI_API const char* GetVersion();
|
IMGUI_API const char* GetVersion();
|
||||||
IMGUI_API void* GetInternalState();
|
IMGUI_API void* GetInternalState();
|
||||||
@ -724,6 +666,65 @@ struct ImGuiIO
|
|||||||
// Helpers
|
// Helpers
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Lightweight std::vector<> like class to avoid dragging dependencies (also: windows implementation of STL with debug enabled is absurdly slow, so let's bypass it so our code runs fast in debug).
|
||||||
|
// Use '#define ImVector std::vector' if you want to use the STL type or your own type.
|
||||||
|
// Our implementation does NOT call c++ constructors because we don't use them in ImGui. Don't use this class as a straight std::vector replacement in your code!
|
||||||
|
#ifndef ImVector
|
||||||
|
template<typename T>
|
||||||
|
class ImVector
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
size_t Size;
|
||||||
|
size_t Capacity;
|
||||||
|
T* Data;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef T value_type;
|
||||||
|
typedef value_type* iterator;
|
||||||
|
typedef const value_type* const_iterator;
|
||||||
|
|
||||||
|
ImVector() { Size = Capacity = 0; Data = NULL; }
|
||||||
|
~ImVector() { if (Data) ImGui::MemFree(Data); }
|
||||||
|
|
||||||
|
inline bool empty() const { return Size == 0; }
|
||||||
|
inline size_t size() const { return Size; }
|
||||||
|
inline size_t capacity() const { return Capacity; }
|
||||||
|
|
||||||
|
inline value_type& at(size_t i) { IM_ASSERT(i < Size); return Data[i]; }
|
||||||
|
inline const value_type& at(size_t i) const { IM_ASSERT(i < Size); return Data[i]; }
|
||||||
|
inline value_type& operator[](size_t i) { IM_ASSERT(i < Size); return Data[i]; }
|
||||||
|
inline const value_type& operator[](size_t i) const { IM_ASSERT(i < Size); return Data[i]; }
|
||||||
|
|
||||||
|
inline void clear() { if (Data) { Size = Capacity = 0; ImGui::MemFree(Data); Data = NULL; } }
|
||||||
|
inline iterator begin() { return Data; }
|
||||||
|
inline const_iterator begin() const { return Data; }
|
||||||
|
inline iterator end() { return Data + Size; }
|
||||||
|
inline const_iterator end() const { return Data + Size; }
|
||||||
|
inline value_type& front() { IM_ASSERT(Size > 0); return Data[0]; }
|
||||||
|
inline const value_type& front() const { IM_ASSERT(Size > 0); return Data[0]; }
|
||||||
|
inline value_type& back() { IM_ASSERT(Size > 0); return Data[Size-1]; }
|
||||||
|
inline const value_type& back() const { IM_ASSERT(Size > 0); return Data[Size-1]; }
|
||||||
|
inline void swap(ImVector<T>& rhs) { const size_t rhs_size = rhs.Size; rhs.Size = Size; Size = rhs_size; const size_t rhs_cap = rhs.Capacity; rhs.Capacity = Capacity; Capacity = rhs_cap; value_type* rhs_data = rhs.Data; rhs.Data = Data; Data = rhs_data; }
|
||||||
|
|
||||||
|
inline void resize(size_t new_size) { if (new_size > Capacity) reserve(new_size); Size = new_size; }
|
||||||
|
inline void reserve(size_t new_capacity)
|
||||||
|
{
|
||||||
|
if (new_capacity <= Capacity) return;
|
||||||
|
T* new_data = (value_type*)ImGui::MemAlloc(new_capacity * sizeof(value_type));
|
||||||
|
memcpy(new_data, Data, Size * sizeof(value_type));
|
||||||
|
ImGui::MemFree(Data);
|
||||||
|
Data = new_data;
|
||||||
|
Capacity = new_capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void push_back(const value_type& v) { if (Size == Capacity) reserve(Capacity ? Capacity * 2 : 4); Data[Size++] = v; }
|
||||||
|
inline void pop_back() { IM_ASSERT(Size > 0); Size--; }
|
||||||
|
|
||||||
|
inline iterator erase(const_iterator it) { IM_ASSERT(it >= begin() && it < end()); const ptrdiff_t off = it - begin(); memmove(Data + off, Data + off + 1, (Size - (size_t)off - 1) * sizeof(value_type)); Size--; return Data + off; }
|
||||||
|
inline iterator insert(const_iterator it, const value_type& v) { IM_ASSERT(it >= begin() && it <= end()); const ptrdiff_t off = it - begin(); if (Size == Capacity) reserve(Capacity ? Capacity * 2 : 4); if (off < (int)Size) memmove(Data + off + 1, Data + off, (Size - (size_t)off) * sizeof(value_type)); Data[off] = v; Size++; return Data + off; }
|
||||||
|
};
|
||||||
|
#endif // #ifndef ImVector
|
||||||
|
|
||||||
// Helper: execute a block of code once a frame only
|
// Helper: execute a block of code once a frame only
|
||||||
// Convenient if you want to quickly create an UI within deep-nested code that runs multiple times every frame.
|
// Convenient if you want to quickly create an UI within deep-nested code that runs multiple times every frame.
|
||||||
// Usage:
|
// Usage:
|
||||||
|
Loading…
Reference in New Issue
Block a user